extern _DYNAMIC extern __hash_list extern __procedure_list extern _start global __tinker_start section .text %macro get_dynamic_sections 0 mov ecx, 3 ;3 runs of the loop .dynamic_tag_loop: ;esi=dynamic address push esi ;back it up .find_tag lodsd ;eax=tag sub eax, byte 3 ;DT_HASH-1 cmp ecx, eax lodsd ;eax=address, flags unaffected jne .find_tag .found_tag: pop esi ;restore dynamic address push eax ;address loop .dynamic_tag_loop pop ecx ;hash table address pop ebx ;strtab address pop esi ;symtab address %endmacro %macro find_symbol_in_map 0 ;ebx=link_map address, edx=hash mov esi, [ebx+8] get_dynamic_sections ;macro - now ecx=hash address, esi=symtab address, ebx=strtab address mov ecx, [ecx+4] ;num chains .symbol_loop: lodsd ;eax=st_name, esi now points to st_value push esi ;save symtab address lea esi, [ebx+eax] ;st_name+strtab address, esi=string address ;calculate the hash push ebx ;back up ebx xor ebx, ebx ;ebx=hash xor eax, eax ;clear upper bits .hash_char_loop: ;these 2 lines dont do anything on the first run of the loop imul ebx, ebx, byte 33 ;same as ((hash<<5)+hash) xor ebx, eax lodsb ;next char test al, al jnz short .hash_char_loop ;not 0? carry on cmp ebx, edx ;compare calculated hash to stored hash pop ebx ;restore ebx pop esi ;restore symtab address lodsd ;eax=st_value, flags unaffected je short .got_symbol ;did hashes match? lodsd ;skip esi 8 bytes to next Elf32_Sym lodsd loop .symbol_loop xor eax, eax ;not found, so null .got_symbol: %endmacro __tinker_start: lea esi, [__hash_list] lea edi, [__procedure_list] .import_symbol_loop: lodsd test eax, eax jz near .done_import_symbol_loop mov edx, eax ;edx=hash ;hacky version for post-build modified dynamic section mov ebx, [_DYNAMIC+4] mov ebx, [ebx+4] ;ebx=executables link_map address .link_map_loop: ;;; test ebx, ebx ;;; jz short .done_import_symbol_loop ;would be sensible to check here if link_map address is 0 ie. if symbol is not found, but whats the point? mov eax, [ebx+4] ;name address mov eax, [eax] ;name test al, al ;only check first byte of string jz short .next_link_map ;is link_map name empty? push ebx push esi find_symbol_in_map ;macro - ebx=link_map address, edx=hash, eax=returned address pop esi pop ebx add eax, [ebx] ;returned address+=link map address cmp eax, [ebx] ;compare return address to link map address (ie. was returned address 0?) .next_link_map: mov ebx, [ebx+12] ;ebx=next link_map address - flags unaffected je short .link_map_loop ;if returned address+link map address = link map address then returned address = 0, continue ;write generated code for linkage table push eax ;symbol address mov al, 0x68 ;'push' opcode stosb ;edi=__procedure_list on first run of loop pop eax stosd ;store address mov al, 0xC3 ;'ret' opcode stosb jmp .import_symbol_loop ;next symbol .done_import_symbol_loop: ;;; xor eax, eax ;;; inc eax ;;; int 0x80 ; exit process jmp _start