Мне интересно, есть ли функция glibc, которую я могу использовать из gcc/g++, которая будет извлекать текущий исполняемый файл.
Цель этого - предоставить аргумент -e addr2line
, как показано в этом ответе
Мне интересно, есть ли функция glibc, которую я могу использовать из gcc/g++, которая будет извлекать текущий исполняемый файл.
Цель этого - предоставить аргумент -e addr2line
, как показано в этом ответе
В стандартном C и glibc у вас есть argv [0]:
int main (int argc, char *argv[])
первый элемент массива argv
- это имя программы.
Однако это не обязательно достаточно для определения того, где именно находится исполняемый файл. Аргумент фактически задается программой, которая запускала вашу программу - будь то оболочка или оконный менеджер - и они не очень полезны. Если ваша программа находится на пути, и вы запускаете программу просто с помощью
your_program
в оболочке bash, тогда "ваша_программа" - это все, что вы получите в argv [0].
Для полного исполняемого пути linux имеет файловую систему /proc
. В разделе /proc
каждый запущенный процесс получает свой собственный "каталог", названный его идентификатором процесса. В текущем процессе также можно увидеть собственное поддерево под /proc/self
. Один из файлов, который каждый процесс получает, - это /proc/[pid]/exe
, который является символической ссылкой на фактический исполняемый файл, который выполняется процессом.
Итак, вы можете получить фактический полный исполняемый путь следующим образом:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
char exe[1024];
int ret;
ret = readlink("/proc/self/exe",exe,sizeof(exe)-1);
if(ret ==-1) {
fprintf(stderr,"ERRORRRRR\n");
exit(1);
}
exe[ret] = 0;
printf("I am %s\n",exe);
}
Вы также можете передать /proc/[pid]/exe
непосредственно на addr2line()
.
Вы можете получить доступ к argv [0] без ссылки на фактическую переменную, используя сохраненный указатель в glibc: https://github.com/rbdixon/glibc/blob/master/misc/init-misc.c
Пример использования:
extern const char *__progname;
int print_progname()
{
return puts(__progname);
}
argv [0] необязательно отражает имя, которое использовалось для вызова программы. Для получения дополнительной информации см. Man 2 execve и man 7 environ.
Получите его из переменных среды. argv [0] будет работать нормально.