32-bit version working (not yet the dnload version)

This commit is contained in:
PoroCYon 2019-04-30 01:05:41 +02:00 committed by PoroCYon
parent 8c7ce9c930
commit 3eea42e29c
6 changed files with 90 additions and 97 deletions

View File

@ -41,8 +41,8 @@ CXXFLAGS += -m$(BITS) $(shell pkg-config --cflags sdl2)
LIBS=-lc LIBS=-lc
SMOLFLAGS += -s SMOLFLAGS +=
ASFLAGS += -DUSE_INTERP -DUSE_DNLOAD_LOADER -DNO_START_ARG -DUNSAFE_DYNAMIC #-DALIGN_STACK ASFLAGS += -DUSE_INTERP -DNO_START_ARG -DUNSAFE_DYNAMIC -DUSE_DNLOAD_LOADER #-DALIGN_STACK
#-DUSE_DNLOAD_LOADER #-DUSE_DT_DEBUG #-DUSE_DL_FINI #-DNO_START_ARG #-DUNSAFE_DYNAMIC #-DUSE_DNLOAD_LOADER #-DUSE_DT_DEBUG #-DUSE_DL_FINI #-DNO_START_ARG #-DUNSAFE_DYNAMIC
NASM ?= nasm NASM ?= nasm

View File

@ -35,7 +35,7 @@
%define DT_DEBUG (21) %define DT_DEBUG (21)
%define ST_NAME_OFF ( 0) %define ST_NAME_OFF ( 0)
; ,---- not 16? ; ,---- not 16? ; what's this comment??!
; v ; v
%if __BITS__ == 32 %if __BITS__ == 32
%define D_UN_PTR_OFF ( 4) %define D_UN_PTR_OFF ( 4)

View File

@ -2,6 +2,9 @@
%include "rtld.inc" %include "rtld.inc"
; TODO
%define R10_BIAS (0)
%ifdef ELF_TYPE %ifdef ELF_TYPE
[section .text.startup.smol] [section .text.startup.smol]
%else %else
@ -9,9 +12,14 @@
[section .text] [section .text]
%endif %endif
%ifndef USE_DNLOAD_LOADER
_smol_linkmap:
dd 0
_smol_linkoff:
dd 0
%endif
_smol_start: _smol_start:
;.loopme: jmp short .loopme
%ifdef USE_DL_FINI %ifdef USE_DL_FINI
push edx ; _dl_fini push edx ; _dl_fini
%endif %endif
@ -28,9 +36,14 @@ _smol_start:
; mov eax, [eax + LM_NEXT_OFFSET] ; skip the vdso ; mov eax, [eax + LM_NEXT_OFFSET] ; skip the vdso
%endif %endif
%ifdef USE_JMP_BYTES
push _symbols+1
%else
push _symbols push _symbols
push eax %endif
%ifdef USE_DNLOAD_LOADER %ifdef USE_DNLOAD_LOADER
; TODO: borked!
pop ebp pop ebp
pop edi pop edi
@ -152,6 +165,10 @@ _smol_start:
; if USE_DNLOAD_LOADER ; if USE_DNLOAD_LOADER
%else %else
;.loopme: jmp short .loopme
mov [_smol_linkmap], eax
mov ebx, eax mov ebx, eax
mov edi, eax mov edi, eax
push -1 push -1
@ -160,103 +177,79 @@ _smol_start:
repne scasd repne scasd
sub edi, ebx sub edi, ebx
sub edi, LM_ENTRY_OFFSET_BASE+4 sub edi, LM_ENTRY_OFFSET_BASE+4
mov [_smol_linkoff], edi
xchg ebp, ebx pop edi ; _symbols
xchg ebx, edi;esi
mov esi, _symbols
link: ; (struct link_map *root, char *symtable) ; edi: _symbols
.do_library: ; null library name means end of symbol table, we're done ; ebp: link_map* root
cmp byte [esi], 0 push ecx
jz .done .next_hash:
.find_map_entry: ; compare basename(entry->l_name) to lib name, if so we got a match pop ecx
push esi mov ecx, [edi]
mov esi, [ebp + LM_NAME_OFFSET]
.basename: ; (const char *s (esi)) mov ebp, [_smol_linkmap]
mov edi, esi ; ecx: hash (assumed nonzero)
.basename.cmp: ; ebp: link_map* chain
lodsb
cmp al, '/'
cmove edi, esi
or al, al
jnz short .basename.cmp
.basename.done:
pop esi
.basename.end:
.strcmp: ; (const char *s1 (esi), const char *s2 (edi)) push ecx
push esi .next_link:
push edi pop ecx
.strcmp.cmp: mov ebp, [ebp + L_NEXT_OFF]
lodsb mov esi, ebp
or al, al add esi, [_smol_linkoff]
jz short .strcmp.done
sub al, [edi]
jnz short .strcmp.done
inc edi
jmp short .strcmp.cmp
.strcmp.done:
pop edi
pop esi
.strcmp.end:
; edx: btk_ind
push ecx
push ecx
push ecx
pop eax
mov ecx, [esi + LF_NBUCKETS_OFF]
xor edx, edx
div ecx
pop ecx
shr ecx, 1
jz short .process_map_entry ; ebx: bucket
; no match, next entry it is! mov ebx, [esi + LF_GNU_BUCKETS_OFF]
mov ebp, [ebp + LM_NEXT_OFFSET] mov ebx, [ebx + edx * 4]
jmp short .find_map_entry
.process_map_entry: ; skip past the name in the symbol table now to get to the symbols
lodsb
or al, al
jnz short .process_map_entry
.do_symbols: ; null byte means end of symbols for this library! .next_chain:
lodsb ; edx: luhash
test al, al mov edx, [esi + LF_GNU_CHAIN_ZERO_OFF]
jz short .do_library mov edx, [edx + ebx * 4]
push ebx
xchg ebx, edi
link_symbol: ; (struct link_map *entry, uint32_t *h) ; ecx: hash
mov ecx, esi mov al, dl
; eax = *h % entry->l_nbuckets shr edx, 1
mov eax, [ecx] cmp edx, ecx
xor edx, edx je short .chain_break
mov ebx, [ebp + edi + LM_NBUCKETS_OFFSET]
div ebx and al, 1
; eax = entry->l_gnu_buckets[edx] jnz short .next_link
mov eax, [ebp + edi + LM_GNU_BUCKETS_OFFSET]
mov eax, [eax + edx * 4] inc ebx
; *h |= 1 jmp short .next_chain
or word [ecx], 1
.check_bucket: ; edx = entry->l_gnu_chain_zero[eax] | 1 .chain_break:
mov edx, [ebp + edi + LM_GNU_CHAIN_ZERO_OFFSET] mov eax, [ebp + L_INFO_DT_SYMTAB_OFF]
mov edx, [edx + eax * 4] mov eax, [eax + D_UN_PTR_OFF]
or edx, 1 lea eax, [eax + ebx * 8]
; check if this is our symbol mov eax, [eax + ebx * 8 + ST_VALUE_OFF]
cmp edx, [ecx] %ifdef SKIP_ZERO_VALUE
je short .found or eax, eax
inc eax jz short .next_link
jmp short .check_bucket %endif
.found: ; it is! edx = entry->l_info[DT_SYMTAB]->d_un.d_ptr
mov edx, [ebp + LM_INFO_OFFSET + DT_SYMTAB * 4] add eax, [ebp + L_ADDR_OFF]
mov edx, [edx + DYN_PTR_OFFSET] stosd
; edx = edx[eax].dt_value + entry->l_addr %ifdef USE_JMP_BYTES
shl eax, DT_SYMSIZE_SHIFT inc edi
mov edx, [edx + eax + DT_VALUE_OFFSET] %endif
add edx, [ebp + LM_ADDR_OFFSET] cmp word [edi], 0
sub edx, ecx jne short .next_hash
sub edx, 4
; finally, write it back!
mov [ecx], edx
pop ebx
add esi, 4
jmp short link.do_symbols
inc esi
link.done:
; if USE_DNLOAD_LOADER ... else ... ; if USE_DNLOAD_LOADER ... else ...
%endif %endif

View File

@ -166,7 +166,7 @@ repne scasd ; technically, scasq should be used, but meh. this is 1 byte smaller
push r14 push r14
pop rbx pop rbx
; pop r12 ; pop r12
; shift left because we don't want to compare the lowest bit ; shift right because we don't want to compare the lowest bit
shr ebx, 1 shr ebx, 1
.next_link: .next_link:
@ -180,7 +180,7 @@ repne scasd ; technically, scasq should be used, but meh. this is 1 byte smaller
mov ecx, dword [r10 + LF_NBUCKETS_OFF - R10_BIAS] mov ecx, dword [r10 + LF_NBUCKETS_OFF - R10_BIAS]
div ecx div ecx
; uint32_t bucket(edx) = entry->l_gnu_buckets[bkt_ind] ; uint32_t bucket(ecx) = entry->l_gnu_buckets[bkt_ind]
mov r8 , [r10 + LF_GNU_BUCKETS_OFF - R10_BIAS] mov r8 , [r10 + LF_GNU_BUCKETS_OFF - R10_BIAS]
mov ecx, dword [r8 + rdx * 4] mov ecx, dword [r8 + rdx * 4]
@ -188,7 +188,7 @@ repne scasd ; technically, scasq should be used, but meh. this is 1 byte smaller
; jecxz .next_link ; jecxz .next_link
.next_chain: .next_chain:
; uint32_t luhash(ecx) = entry->l_gnu_chain_zero[bucket] >> 1 ; uint32_t luhash(edx) = entry->l_gnu_chain_zero[bucket] >> 1
mov rdx, [r10 + LF_GNU_CHAIN_ZERO_OFF - R10_BIAS] mov rdx, [r10 + LF_GNU_CHAIN_ZERO_OFF - R10_BIAS]
mov edx, dword [rdx + rcx * 4] mov edx, dword [rdx + rcx * 4]

View File

@ -6,7 +6,7 @@
%define L_LD_OFF ( 8) %define L_LD_OFF ( 8)
%define L_NEXT_OFF (0x0C) %define L_NEXT_OFF (0x0C)
%define L_INFO_OFF (0x20) %define L_INFO_OFF (0x20)
;%define L_INFO_DT_SYMTAB_OFF () %define L_INFO_DT_SYMTAB_OFF (0x38)
%define LF_ENTRY_OFF ( 340) %define LF_ENTRY_OFF ( 340)
%define LF_NBUCKETS_OFF (0x178) %define LF_NBUCKETS_OFF (0x178)

View File

@ -32,7 +32,7 @@ def main():
parser.add_argument('-s', '--hash16', default=False, action='store_true', \ parser.add_argument('-s', '--hash16', default=False, action='store_true', \
help="Use 16-bit (BSD) hashes instead of 32-bit djb2 hashes. "\ help="Use 16-bit (BSD) hashes instead of 32-bit djb2 hashes. "\
+"Conflicts with -DUSE_DNLOAD_LOADER") +"Must be used with -DUSE_DNLOAD_LOADER")
# parser.add_argument('-d', '--dnload', default=False, action='store_true', \ # parser.add_argument('-d', '--dnload', default=False, action='store_true', \
# help="Use dnload's mechanism of importing functions. Slightly larger, but usually better compressable.") # help="Use dnload's mechanism of importing functions. Slightly larger, but usually better compressable.")
# parser.add_argument('--libsep', default=False, action='store_true', \ # parser.add_argument('--libsep', default=False, action='store_true', \