Created
October 5, 2021 15:19
-
-
Save sitano/55a8fc47058de2774914d43d46b19346 to your computer and use it in GitHub Desktop.
Scan allocable .dynsym symbol table from loaded elf image
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// dl_iterate_phdr(scan_dynsym, NULL); | |
// | |
// better see the impl from musl: https://github.com/esmil/musl/blob/194f9cf93da8ae62491b7386edf481ea8565ae4e/src/ldso/dynlink.c#L1451 | |
#define UINTS_PER_WORD (__WORDSIZE / (CHAR_BIT * sizeof (unsigned int))) | |
static ElfW(Word) | |
gnu_hashtab_symbol_count(const unsigned int *const table) { | |
const unsigned int *const bucket = table + 4 + table[2] * (unsigned int)(UINTS_PER_WORD); | |
unsigned int b = table[0]; | |
unsigned int max = 0U; | |
while (b-->0U) | |
if (bucket[b] > max) | |
max = bucket[b]; | |
return (ElfW(Word))max; | |
} | |
// Reference: | |
// https://stackoverflow.com/questions/15779185/list-all-the-functions-symbols-on-the-fly-in-c | |
// | |
/* Callback for dl_iterate_phdr. | |
* Is called by dl_iterate_phdr for every loaded shared lib until something | |
* else than 0 is returned by one call of this function. | |
*/ | |
static int | |
scan_dynsym(struct dl_phdr_info* info) { | |
/* ElfW is a macro that creates proper typenames for the used system architecture | |
* (e.g. on a 32 bit system, ElfW(Dyn*) becomes "Elf32_Dyn*") */ | |
ElfW(Dyn *) dyn; | |
ElfW(Sym *) sym; | |
ElfW(Word *) hash; | |
char *strtab = NULL; | |
char *sym_name = NULL; | |
ElfW(Word) sym_cnt = 0; | |
/* Iterate over all headers of the current shared lib | |
* (first call is for the executable itself) */ | |
for (size_t header_index = 0; header_index < info->dlpi_phnum; header_index++) { | |
/* Further processing is only needed if the dynamic section is reached */ | |
if (info->dlpi_phdr[header_index].p_type == PT_DYNAMIC) { | |
/* Get a pointer to the first entry of the dynamic section. | |
* It's address is the shared lib's address + the virtual address */ | |
dyn = (ElfW(Dyn)*)(info->dlpi_addr + info->dlpi_phdr[header_index].p_vaddr); | |
while(dyn->d_tag != DT_NULL) { | |
switch(dyn->d_tag) { | |
case DT_HASH: { | |
hash = (ElfW(Word *))dyn->d_un.d_ptr; | |
sym_cnt = hash[1]; | |
} | |
break; | |
case DT_GNU_HASH: { | |
hash = (ElfW(Word *))dyn->d_un.d_ptr; | |
sym_cnt = gnu_hashtab_symbol_count(hash); | |
} | |
break; | |
case DT_STRTAB: { | |
/* Get the pointer to the string table */ | |
strtab = (char *)dyn->d_un.d_ptr; | |
} | |
break; | |
case DT_SYMTAB: { | |
/* Get the pointer to the first entry of the symbol table */ | |
sym = (ElfW(Sym *))dyn->d_un.d_ptr; | |
/* Iterate over the symbol table */ | |
for (ElfW(Word) sym_index = 0; sym_index < sym_cnt; sym_index++) { | |
/* get the name of the i-th symbol. | |
* This is located at the address of st_name | |
* relative to the beginning of the string table. */ | |
sym_name = &strtab[sym[sym_index].st_name]; | |
printf("%s %d %d |\n", sym_name, ELF64_ST_TYPE(sym[sym_index].st_info), sym[sym_index].st_other); | |
} | |
} | |
break; | |
default: | |
// printf(">> %d \n", dyn->d_tag); | |
// Unsupported dyn->d_tag? | |
break; | |
} | |
/* move pointer to the next entry */ | |
dyn++; | |
} | |
} else { | |
printf(">> info->dlpi_phdr[%d].p_type=%d \n", header_index, info->dlpi_phdr[header_index].p_type); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment