LINUX.ORG.RU

История изменений

Исправление 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;
}