Я пробовал простой тест с использованием 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 может быть полезна (предупреждение: article is 10лет).
Это не так хорошо, как делать нативный самоанализ, и странно, что dladdr(3C)
не работает: (
Альтернативное промежуточное звено: вы пробовали флаг RTLD_DL_SYMENT
до dladdr1(3C)
(а затем, возможно, позаимствовать у nm.c
, как указано выше в возвращаемом симе ELF)?