Функция glibc для извлечения текущего исполняемого имени?

Мне интересно, есть ли функция glibc, которую я могу использовать из gcc/g++, которая будет извлекать текущий исполняемый файл.

Цель этого - предоставить аргумент -e addr2line, как показано в этом ответе

Ответ 1

В стандартном 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().

Ответ 2

Вы можете получить доступ к 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.

Ответ 3

Получите его из переменных среды. argv [0] будет работать нормально.