X-Git-Url: https://git.alrj.org/?p=bold.git;a=blobdiff_plain;f=runtime%2Fbold_ibh-x86_64.asm;fp=runtime%2Fbold_ibh-x86_64.asm;h=5395cd440fceec25330775fcbe8a914a4611a3c6;hp=0000000000000000000000000000000000000000;hb=b2cbc828fcbff8ecf501a53ee3b5b62195913923;hpb=cfa01bd9bb99e5e7ded6db402951c081bdd21aa5 diff --git a/runtime/bold_ibh-x86_64.asm b/runtime/bold_ibh-x86_64.asm new file mode 100644 index 0000000..5395cd4 --- /dev/null +++ b/runtime/bold_ibh-x86_64.asm @@ -0,0 +1,132 @@ +; kate: syntax Intel x86 (NASM); + +; Copyright (C) 2009 Amand "alrj" Tihon + +; Import by hash for linux/amd64 (elf64-x86-64) +; This file is part of bold, the Byte Optimized Linker. + +; You can redistribute this file and/or modify it under the terms of the +; GNU General Public License as published by the Free Software Foundation, +; either version 3 of the License or (at your option) any later version. + +;------------------------------------------------------------------------------ +; alrj's x86_64 version of the import by hash method by parapete, las, leblane. +; See the wonderful thread at http://www.pouet.net/topic.php?which=5392 to +; learn everything about import by hash on Linux. + +; Compile with +; yasm -f elf64 -o bold_ibh-x86_64.o bold_ibh-x86_64.asm +; (or replace yasm by nasm) + + +BITS 64 +CPU X64 + +global _bold__ibh +global exit + +extern _dt_debug ; defined by bold linker +extern _bold__functions_hash ; in .data, generated by bold +extern _bold__functions_pointers ; in .bss, generated by bold +extern _bold__functions_count ; immediate 32 bits +extern main ; must be declared when using this + +%define SYS_exit 60 +%define DT_HASH 4 + +segment .text + +_bold__ibh: +; {{{ Do the RTLD + mov rbx, [_dt_debug] ; rbx points to r_debug + mov rbx, [rbx + 8] ; rbx points to link_map + mov rbx, [rbx + 24] ; skip the first two link_map entries + mov rbx, [rbx + 24] + + mov esi, _bold__functions_hash ; Implicitly zero-extended + mov edi, _bold__functions_pointers ; ditto + mov ecx, _bold__functions_count + + ; Load all the symbols + .symbol_loop: + lodsd ; Load symbol hash in eax + push rsi + push rcx + +; {{{ For each hash + mov r15d, eax ; Save function hash + mov r13, rbx ; copy link_map's pseudo-head + + ; Iterate over libraries found in link_map + .libloop: + mov rdx, [r13 + 16] ; link_map->l_ld + + ; Find the interesting entries in the DYNAMIC table. + .dynamic_loop: + xor eax, eax ; enough because hash was 32 bits + + mov al, DT_HASH ; DT_HASH == 4 + cmp [rdx], rax + cmove r9, [rdx+8] ; r9 : pointer to the hash table + + inc al ; DT_STRTAB == 5 + cmp [rdx], rax + cmove r10, [rdx+8] ; r10 : pointer to strtab + + inc al ; DT_SYMTAB == 6 + cmp [rdx], rax + cmove r11, [rdx+8] ; r11 : pointer to symtab + + ; Next dynamic entry + add rdx, 16 + xor al, al + cmp [rdx], rax + jnz .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: + ; Find the symbol name in strtab + mov esi, [r11] ; st_name, offset in strtab + add rsi, r10 ; pointer to symbol name + + ; Compute the hash + xor edx, edx + xor eax, eax + .hash_loop: ; over each char + imul edx, edx, byte 0x21 + xor edx, eax + lodsb + test al, al + jnz short .hash_loop + + .hash_end: + cmp edx, r15d ; Compare with stored hash + je .found + add r11, 24 ; Next symtab entry + loop .symbolloop + + ; Symbol was not found in this library + mov r13, [r13 + 24] ; Next link_map entry + jmp short .libloop + .found: + mov rax, [r11 + 8] ; st_value, offset of the symbol + add rax, [r13] ; add link_map->l_addr +; }}} + + pop rcx + pop rsi + stosq ; Store function pointer + loop .symbol_loop +; }}} + + ; When all is resolved, call main() + call main + mov edi, eax + +exit: + ; Exit cleanly + mov eax, SYS_exit + syscall