История изменений
Исправление
kvpfs,
(текущая версия)
:
А чем тебе -finstrument не подходит? Получай рантайме имена функций через парсинг elf’а. Я как-то баловался, так получал имя передавая адрес функции:
__attribute__((no_instrument_function))
static uintptr_t get_base()
{
FILE *f = fopen("/proc/self/maps", "r");
if (! f)
return 0;
void *base;
int res = fscanf(f, "%p", &base);
fclose(f);
if (res < 1)
return 0;
return (uintptr_t)base;
}
__attribute__((no_instrument_function))
static const char *address_to_name(void *fn, int *o_local)
{
static uintptr_t gdb_base_address = 0;
static Elf64_Sym *sym_table = 0;
static int symtab_sz = 0;
static const char *string_sec = 0;
static void *elf_buf;
static enum {
uninit,
ok,
error
}state = uninit;
switch (state) {
case error:
return 0;
case ok:
break;
default: {
FILE *f = fopen("/proc/self/exe", "r");
if (! (gdb_base_address = get_base()))
goto err_label;
{ //block
if (! f || fseek(f, 0, SEEK_END))
goto err_label;
size_t fsz = (size_t)ftell(f);
fseek(f, 0, SEEK_SET);
if (! (elf_buf = malloc(fsz)) ||
fread(elf_buf, 1, fsz, f) != fsz)
goto err_label;
fclose(f), f = 0;
Elf64_Ehdr *head = (Elf64_Ehdr*)elf_buf;
Elf64_Shdr *sec_head = (Elf64_Shdr*)((char*)elf_buf + head->e_shoff);
for (int i = 0; i < head->e_shnum; ++ i) {
if (sec_head[i].sh_type == SHT_SYMTAB) {
sym_table = (Elf64_Sym*)((char*)elf_buf + sec_head[i].sh_offset);
symtab_sz = sec_head[i].sh_size;
}
else if (sym_table && sec_head[i].sh_type == SHT_STRTAB) {
string_sec = (char*)elf_buf + sec_head[i].sh_offset;
break;
}
}
if (! sym_table || ! string_sec)
goto err_label;
state = ok;
break;
}
err_label:
if (f != 0)
fclose(f);
state = error;
return 0;
}
}
for (Elf64_Sym *it = sym_table; (char*)it < (char*)sym_table+symtab_sz;
++ it) {
if (fn == (char*)it->st_value + gdb_base_address) {
*o_local = ELF64_ST_BIND(it->st_info) == STB_LOCAL ? 1 : 0;
return string_sec + it->st_name;
}
}
return 0;
}
Исходная версия
kvpfs,
:
А чем тебе -finstrument не подходит? Получай рантайме имена функций через парсинг elf’а. Я как-то баловался, так получал имя передавая адрес функции:
__attribute__((no_instrument_function))
static uintptr_t get_base()
{
FILE *f = fopen("/proc/self/maps", "r");
if (! f)
return 0;
void *base;
int res = fscanf(f, "%p", &base);
fclose(f);
if (res < 1)
return 0;
return (uintptr_t)base;
}
__attribute__((no_instrument_function))
static const char *address_to_name(void *fn, int *o_local)
{
static uintptr_t gdb_base_address = 0;
static Elf64_Sym *sym_table = 0;
static int symtab_sz = 0;
static const char *string_sec = 0;
static void *elf_buf;
static enum {
uninit,
ok,
error
}state = uninit;
switch (state) {
case error:
return 0;
case ok:
break;
default: {
FILE *f = fopen("/proc/self/exe", "r");
if (! (gdb_base_address = get_base()))
goto err_label;
{ //block
if (! f || fseek(f, 0, SEEK_END))
goto err_label;
size_t fsz = (size_t)ftell(f);
fseek(f, 0, SEEK_SET);
if (! (elf_buf = malloc(fsz)) ||
fread(elf_buf, 1, fsz, f) != fsz)
goto err_label;
fclose(f), f = 0;
Elf64_Ehdr *head = (Elf64_Ehdr*)elf_buf;
Elf64_Shdr *sec_head = (Elf64_Shdr*)((char*)elf_buf + head->e_shoff);
for (int i = 0; i < head->e_shnum; ++ i) {
if (sec_head[i].sh_type == SHT_SYMTAB) {
sym_table = (Elf64_Sym*)((char*)elf_buf + sec_head[i].sh_offset);
symtab_sz = sec_head[i].sh_size;
}
else if (sym_table && sec_head[i].sh_type == SHT_STRTAB) {
string_sec = (char*)elf_buf + sec_head[i].sh_offset;
break;
}
}
if (! sym_table || ! string_sec)
goto err_label;
state = ok;
break;
}
err_label:
if (f != 0)
fclose(f);
state = error;
return 0;
}
}
for (Elf64_Sym *it = sym_table; (char*)it < (char*)sym_table+symtab_sz;
++ it) {
if (fn == (char*)it->st_value + gdb_base_address) {
*o_local = ELF64_ST_BIND(it->st_info) == STB_LOCAL ? 1 : 0;
return string_sec + it->st_name;
}
}
return 0;
}