From: Amand Tihon Date: Sat, 30 Jul 2011 18:38:45 +0000 (+0200) Subject: First support for .gnu.hash/DT_GNU_HASH. X-Git-Url: https://git.alrj.org/?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=bold.git First support for .gnu.hash/DT_GNU_HASH. * Not optimized yet. * Strange bug when using cmove that I'll have to investigate. * Thanks go to kernel_error and flure for the motivation :) --- diff --git a/runtime/bold_ibh-x86_64.asm b/runtime/bold_ibh-x86_64.asm index a9a3732..f309ce7 100644 --- a/runtime/bold_ibh-x86_64.asm +++ b/runtime/bold_ibh-x86_64.asm @@ -65,33 +65,55 @@ _bold__ibh_start: mov rdx, [r14 + 16] ; link_map->l_ld ; Find the interesting entries in the DYNAMIC table. - .dynamic_loop: - - push byte DT_HASH ; DT_HASH == 4 - pop rax - cmp [rdx], eax - cmove r9, [rdx+8] ; r9 : pointer to the hash table - - inc eax ; DT_STRTAB == 5 - cmp [rdx], eax - cmove r10, [rdx+8] ; r10 : pointer to strtab - inc eax ; DT_SYMTAB == 6 - cmp [rdx], eax - cmove r11, [rdx+8] ; r11 : pointer to symtab + .dynamic_loop: + mov rsi, [rdx+8] + + cmp [rdx], dword 4 ; DT_HASH == 4 + jne .no_hash ; Why the heck does it segfault when + mov ecx, [rsi+4] ; I use cmove ecx, [rsi+4] instead + .no_hash: ; of this jne construction ???? + + cmp [rdx], dword 5 ; DT_STRTAB == 5 + cmove r10, rsi ; r10 : pointer to strtab + + cmp [rdx], dword 6 ; DT_SYMTAB == 6 + cmove r11, rsi ; r11 : pointer to symtab + + cmp [rdx], dword 0x6ffffef5 ; DT_GNU_HASH + jne .not_gnu_hash + mov ecx, [rsi] ; ecx is nbuckets + mov r9d, [rsi + 8] ; maskwords (64 bits entries) + lea r9, [rsi + 16 + r9 * 8] ; rdx points to the first bucket + + xor eax, eax + .walk_buckets: ; Find the last chain + cmp eax, [r9] + cmovl eax, [r9] + add r9, 4 ; next bucket + loop .walk_buckets ; eax is offset to the last chain + ; Now, rdx points to the beginning of the first chain + + mov ecx, [rsi+4] ; symndx + xchg eax, ecx + shl rax, 2 ; symndx * 4 + sub r9, rax ; hash values - symndx * 4 + .walk_chain: + bt dword [r9 + rcx*4], 0 ; + inc ecx ; Increment ecx for each entry found + jc .walk_chain ; in the chain. + dec ecx ; fixup. + .not_gnu_hash: ; Next dynamic entry - lea rdx, [rdx + 16] ; add rdx, 16 - xor eax, eax - cmp [rdx], eax - ;cmp [rdx], dword 0 ; Gut feeling: would harm compression + add rdx, 16 + cmp [rdx], dword 0 jnz short .dynamic_loop ; All DYNAMIC entries have been read. - mov ecx, [r9 + 4] ; nchain, number of exported symbols ; Iterate over the symbols in the library (symtab entries). - .symbolloop: + .symtabloop: ; Find the symbol name in strtab mov esi, [r11] ; st_name, offset in strtab add rsi, r10 ; pointer to symbol name @@ -110,11 +132,11 @@ _bold__ibh_start: cmp edx, ebx ; Compare with stored hash je short .found lea r11, [r11 + 24] ; Next symtab entry - loop .symbolloop + loop .symtabloop ; Symbol was not found in this library mov r14, [r14 + 24] ; Next link_map entry - jmp short .libloop + jmp .libloop .found: mov rax, [r11 + 8] ; st_value, offset of the symbol add rax, [r14] ; add link_map->l_addr @@ -123,7 +145,9 @@ _bold__ibh_start: pop rcx pop rsi - loop .symbol_loop + ;loop .symbol_loop + dec ecx + jnz .symbol_loop ; }}} ; When all is resolved, call main() diff --git a/runtime/bold_ibh-x86_64.o b/runtime/bold_ibh-x86_64.o index b72a08b..786f97b 100644 Binary files a/runtime/bold_ibh-x86_64.o and b/runtime/bold_ibh-x86_64.o differ