Я попробовал простой тест с использованием dladdr()
на Solaris 10/SPARC (но предостережение: GCC 3.4, прямой C), и это отлично работает для меня:
#include <dlfcn.h>
#include <stdio.h>
void print_name(char *name, void *addr);
void print_name_by_dladdr(void *addr);
int main(int argc, const char *argv[])
{
print_name("main", (void *)&main);
print_name("print_name", (void *)&print_name);
print_name("printf", (void *)&printf);
return 0;
}
void print_name(char *name, void *addr)
{
(void)printf("Getting name of function %s() at 0x%x\n", name, addr);
print_name_by_dladdr(addr);
}
void print_name_by_dladdr(void *addr)
{
Dl_info dli;
if(!dladdr(addr, &dli)) {
perror("dladdr()");
exit(1);
}
(void)printf(" %s\n", dli.dli_sname);
}
Выход:
Getting name of function main() at 0x10714
main
Getting name of function print_name() at 0x10778
print_name
Getting name of function printf() at 0x209b8
_PROCEDURE_LINKAGE_TABLE_
Это также работает правильно, если я пишу (например)
print_name("main", (void *)&main + 4);
Вы говорите, что можете правильно разрешить вывод nm
, поэтому возможности кажутся ограниченными... вы уверены, что обратный адрес выводится или правильно передается вашей функции распознавания? Я предполагаю, что вы используете для этого встроенные модули GCC? Я протестировал __builtin_return_address(0)
, и у меня это тоже отлично работает. Если вы используете встроенные модули GCC, вызывали ли вы __builtin_extract_return_address()
(подробности см. на странице выше, явно упоминает SPARC)? Можете ли вы опубликовать свой код?
Можете ли вы немного растянуть, чтобы «процесс перечитал свои собственные двоичные/общие объектные файлы»? Если это так, то libelf может помочь. Это именно то, что используют некоторые из упомянутых вами утилит, например nm
: http://cr.opensolaris.org/~devnull/6515400/usr/src/cmd/sgs/nm/common/nm.c.html
Эта вводная статья с сайта sun.com может оказаться полезной (внимание: статья 10 лет).
Это не так приятно, как нативный самоанализ, и странно, что dladdr(3C)
не работает :(
Альтернативный промежуточный вариант: пробовали ли вы использовать флаг RTLD_DL_SYMENT
для dladdr1(3C)
(а затем, возможно, позаимствовать из nm.c
, как указано выше, в возвращенном символе ELF)?
person
Martin Carpenter
schedule
12.08.2011
nm
,objdump
и дажеpstack
для просмотра этой информации, но я говорю о получении этой информации самим процессом. - person evolvah   schedule 12.08.2011