; GNU General Public License as published by the Free Software Foundation,
; either version 3 of the License or (at your option) any later version.
+; Under Section 7 of GPL version 3, you are granted additional
+; permissions described in the Bold Runtime Library Exception, version
+; 1.0, as published by Amand Tihon.
+
;------------------------------------------------------------------------------
; 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)
+; nasm -f elf64 -o bold_ibh-x86_64.o bold_ibh-x86_64.asm
BITS 64
CPU X64
-global _bold__ibh
+global _bold__ibh_start
global exit
extern _dt_debug ; defined by bold linker
segment .text
-_bold__ibh:
+_bold__ibh_start:
; {{{ 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 r14, [rel _dt_debug] ; r14 points to r_debug
+ mov r14, [r14 + 8] ; r14 points to link_map
+ mov r14, [r14 + 24] ; skip the first two link_map entries
+ mov r14, [r14 + 24]
mov esi, _bold__functions_hash ; Implicitly zero-extended
mov edi, _bold__functions_pointers ; ditto
- mov ecx, _bold__functions_count
+ push byte _bold__functions_count ; Warning: Max 127 external symbols.
+ pop rcx ; Linker should enforce this.
; Load all the symbols
.symbol_loop:
- lodsd ; Load symbol hash in eax
+ lodsd ; Load symbol hash
+ xchg ebx, eax ; into ebx
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
+ mov rdx, [r14 + 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
+ .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
add rdx, 16
- xor al, al
- cmp [rdx], rax
- jnz .dynamic_loop
+ 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
jnz short .hash_loop
.hash_end:
- cmp edx, r15d ; Compare with stored hash
- je .found
- add r11, 24 ; Next symtab entry
- loop .symbolloop
+ cmp edx, ebx ; Compare with stored hash
+ je short .found
+ lea r11, [r11 + 24] ; Next symtab entry
+ loop .symtabloop
; Symbol was not found in this library
- mov r13, [r13 + 24] ; Next link_map entry
- jmp short .libloop
+ mov r14, [r14 + 24] ; Next link_map entry
+ jmp .libloop
.found:
mov rax, [r11 + 8] ; st_value, offset of the symbol
- add rax, [r13] ; add link_map->l_addr
+ add rax, [r14] ; add link_map->l_addr
+ stosq ; Store function pointer
; }}}
pop rcx
pop rsi
- stosq ; Store function pointer
- loop .symbol_loop
+ ;loop .symbol_loop
+ dec ecx
+ jnz .symbol_loop
; }}}
; When all is resolved, call main()
call main
- mov edi, eax
exit:
; Exit cleanly
- mov eax, SYS_exit
+ xchg edi, eax
+ push byte SYS_exit
+ pop rax
syscall
+
+%assign code_size $ - _bold__ibh_start
+%warning Code size is: code_size