DT_GNU_HASH deroko of ARTeam DT_GNU_HASH is nowhere documented, nowhere to be found except in binutils, and glibc. I will try to explain it a little bit, and how to find all exported functions in case that DT_GNU_HASH is present in shared lib. ELF Specification talks only about DT_HASH, and since long time default "export" table in linux binaries is DT_GNU_HASH which has only a few similarities with DT_HASH. So let's have a look at this structure: nbuckets [DWORD] symbol base [DWORD] bitmask_nwords [DWORD] gnu_shift [DWORD] variable_length of index bits [array of gnu buckets] [DWORD] [array of chains] [DWORD] chains hold hash of symbol which is defined as this function in binutils: unsigned long bfd_elf_gnu_hash (const char *namearg) { const unsigned char *name = (const unsigned char *) namearg; unsigned long h = 5381; unsigned char ch; while ((ch = *name++) != '\0') h = (h << 5) + h + ch; return h & 0xffffffff; } One thing which I never will understand is, why they didn't add total number of "exported" symbols, eg. symbols which are part of DT_GNU_HASH, but to locate number of symbols we have to go over last chain bucket. I don't understand why this is done. Now let's have a look at a dump in gdb of DT_GNU_HASH table to know how to parse it: 0x0804C140 : 03 00 00 00 08 00 00 00 - 02 00 00 00 06 00 00 00 ................ 0x0804C150 : 8C 00 20 01 00 C4 50 29 - 08 00 00 00 0A 00 00 00 .. ...P)........ 0x0804C160 : 0E 00 00 00 42 45 D5 EC - BB E3 92 7C 86 F0 96 7C ....BE.....|...| 0x0804C170 : D8 71 58 1C B8 8D F1 0E - 3D AD 39 0D EB D3 EF 0E .qX.....=.9..... 0x0804C180 : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ 0x0804C190 : 1C 00 00 00 00 00 00 00 - 00 00 00 00 20 00 00 00 ............ ... And line by line: 0x0804C140 : 03 00 00 00 08 00 00 00 - 02 00 00 00 06 00 00 00 ................ ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^ nbuckets symol base bitmask shift nwords 0x0804C150 : 8C 00 20 01 00 C4 50 29 - 08 00 00 00 0A 00 00 00 .. ...P)........ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^ bitmasks bucket[0] bucket[1] 0x0804C160 : 0E 00 00 00 42 45 D5 EC - BB E3 92 7C 86 F0 96 7C ....BE.....|...| ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bucket[2] chains for each bucket 0x0804C170 : D8 71 58 1C B8 8D F1 0E - 3D AD 39 0D EB D3 EF 0E .qX.....=.9..... 0x0804C180 : 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ 0x0804C190 : 1C 00 00 00 00 00 00 00 - 00 00 00 00 20 00 00 00 ............ ... symbol base is telling us at which index in DT_SYMTAB (Elf32_Sym) exports are starting, but we still don't know where they end, or how big it DT_SYMTAB, simply there is no DT_ entry in Elf32_Dyn which would tell us total size of this table which we can use to calculate remaining export symbols, so we have to approach by searching for the biggest index in a bucket, and in such way to locate last chain, and compute end of exported array. so we do: bucket = DT_GNU_HASH + 16 + bitmask_nwords * 4 (or 8 on x64) unsigned int last_sym = 0; for (index = 0; index < nbucket; index++) if (bucket[index] > last_sym) last_sym = bucket[index]; In this case we endup with 0xE as last_sym, but we are not yet done. This tells us that last chain handles symbols >= 0xE thus we need to find end of this chain to know how many symbols are exported: chain_index = last_sym - symbol_base (0xE - 0x8) unsinged int *chains = ((unsigned long)bucket + nbuckets * 4); last_sym++; while (!(chains[last_sym] & 1)) last_sym++; Note, and it's very important that chains hold hash of a symbol name for fast lookup, but last entry in a chain always ends with low bit (bit 0) set to 1, thus this small loop will give us end of symbols which are exported. It's also important to know that proper lookup of DT_GNU_HASH happens on chains, and doesn't include total number of exported symbols at all. How it's done is like this (we don't even need last_sym!!!): for (index = 0; index < nbuckets; index++){ if (bucket[index] == 0) continue; //believe it or not, some buckets //can be empty!? what's the purpose //I have no idea... unsigned int symidx = bucket[index]; unsigned int chain_idx = symidx - symbol_base; //symbol base = DT_GNU_HASH+4 while (1){ //print symbol by using symidx into DT_SYMTAB which hold Elf32_Sym //you can also determine it's type, eg. if it's SHT_OBJECT or SHT_FUNC //to know if it's exported function or data object (array/some variable etc) print_symbol(symidx); if (chains[symidx] & 1) break; } } Well that would be it, we also know that IDA lacks support for DT_GNU_HASH, and can't process exports of 100% shared libs on Linux, if those would be properly stripped!! Note also that strip which comes with Linux(and other unixes) is not real strip, as it leaves section headers which are NOT NEEDED for proper ELF loading, and never will be!! Thus elf32mod from my web site can properly handle such ELF files. deroko of ARTeam