Code: Select all
; Copyright (C) KolibriOS team 2008-2021. All rights reserved
format MS COFF
;-------------------------------------------------
; INFO
;-------------------------------------------------
libname equ 'dll'
LIB_VERSION equ 1
;-------------------------------------------------
; INCLUDES
;-------------------------------------------------
include '../../../proc32.inc'
include '../../../macros.inc'
;-------------------------------------------------
; USED EQUATES
;-------------------------------------------------
SF_SYS_MISC = 68
SSF_LOAD_DLL = 19
SF_TERMINATE_PROCESS = -1
sizeof.push = 4
;-------------------------------------------------
; USED STRUCTURES
;-------------------------------------------------
virtual at 0
LIBRARY_ENTRY:
.lookup_table dd ?
.lpname dd ?
sizeof.LIBRARY_ENTRY = $
dd ? ; last entry with blank lookup_table
sizeof.MINIMAL_IMPORT_TABLE = $
end virtual
virtual at 0
EXPORT_ENTRY:
.lpname dd ?
.lpproc dd ?
sizeof.EXPORT_ENTRY = $
end virtual
virtual at 0
IMPORT_ENTRY:
.lpproc dd ?
sizeof.IMPORT_ENTRY = $
end virtual
virtual at 0
ME_HEADER_V2:
.signature rb 8
.hdr_version dd ?
.entry dd ?
.init_mem_sz dd ?
.rsrvd_mem_sz dd ?
.stacktop dd ?
.params dd ?
.cur_dir_path dd ?
.import_data dd ?
end virtual
;-------------------------------------------------
; USED EXTRA MACROS
;-------------------------------------------------
macro export [name,sname]
{ common local ..export
..export:
public ..export as 'EXPORTS'
forward
dd __#name#_export_name__,name
common
dd 0
forward
;align 4
__#name#_export_name__ db sname,0
}
;-------------------------------------------------
; CODE
;-------------------------------------------------
section '.flat' code readable align 16
GetStrLength:
; string: [in] edi
; string length: [out] ecx
; [unchanged] ebx, edx, esi, edi, ebp, esp
or ecx, -1
xor eax, eax
cld
repne scasb
not ecx
sub edi,ecx
retn
;-------------------------------------------------
Mov_memBlock:
; destination: [in] esi
; source: [in] edi
; size of source: [in] ecx
; destination position after copy [out] edi
[unchanged] ebx, edx, ebp, esp
mov eax, ecx
shr ecx, 2
rep movsd
mov ecx, eax
and ecx, 3
rep movsb
retn
;-------------------------------------------------
Mov_memString:
; destination: [in] esi
; source: [in] edi
; destination position after copy [out] edi
[unchanged] ebx, edx, ebp, esp
lodsb
stosb
test al,al
jnz MoveUnsizedString
retn
;-------------------------------------------------
GetProcOrdinalAddress:
; hInstance (export table): [in] esi
; proc ordinal: [in] edi
; proc address: [out] eax
; [unchanged] ebx, ecx, edx, ebp, esp
xor edi, $80000000
.check_entry:
mov eax, [esi+EXPORT_ENTRY.lpname]
test eax, eax
jz .not_found
sub edi, 1
je .matched
add esi, sizeof.EXPORT_ENTRY
jmp .check_entry
.matched:
mov eax, [esi+EXPORT_ENTRY.lpproc]
.not_found:
retn
;-------------------------------------------------
stdcall_GetProcAddress:
push ebx
push esi
push edi
.hInstance equ esp+4+sizeof.push*3
.name equ esp+8+sizeof.push*3
mov esi, [.hInstance]
mov edi, [.name]
test edi, edi
js .search_by_ordinal
call GetProcAddress
jmp .get_proc_addr_done
.search_by_ordinal:
call GetProcOrdinalAddress
.get_proc_addr_done:
pop edi
pop esi
pop ebx
retn
restore stdcall_GetProcAddress.hInstance,stdcall_GetProcAddress.name
;-------------------------------------------------
GetProcAddress:
; hInstance (export table): [in] esi
; proc name: [in] edi
; proc address: [out] eax
; [unchanged] ebp, esp
call GetStrLength
mov edx, ecx
mov ebx, edi
mov eax, esi
.check_entry:
mov esi, ebx
mov edi, [eax+EXPORT_ENTRY.lpname]
test edi, edi
jz .not_found
repe cmpsb
je .matched
mov ecx, edx
add eax, sizeof.EXPORT_ENTRY
jmp .check_entry
.not_found:
sub eax, EXPORT_ENTRY.lpproc
.matched:
mov eax, [eax+EXPORT_ENTRY.lpproc]
retn
;-------------------------------------------------
ResolveImports:
; hInstance (export table): [in] esi
; lib.lookup table: [in] ebp
; ?isResolved: [out] eax
; [unchanged] esi, esp
load_libraries_error equ esp+8
.import_loop:
mov edi, [ebp+IMPORT_ENTRY.lpproc]
test edi, edi
jz .done
push esi
js .search_by_ordinal
call GetProcAddress
jmp .get_proc_addr_done
.search_by_ordinal:
call GetProcOrdinalAddress
.get_proc_addr_done:
pop esi
test eax, eax
jz .import_not_found
mov [ebp+IMPORT_ENTRY.lpproc], eax
add ebp, sizeof.IMPORT_ENTRY
jmp .import_loop
.import_not_found:
or [ebp+IMPORT_ENTRY.lpproc], -1
or dword[load_libraries_error], -1
add ebp, sizeof.IMPORT_ENTRY
jmp .import_loop
.done:
retn
restore load_libraries_error
;-------------------------------------------------
stdcall_LoadLibrary:
push ebx
push esi
push edi
.name equ esp+4+sizeof.push*3
mov edx, [.name]
call LoadLibrary
pop edi
pop esi
pop ebx
retn
restore stdcall_GetProcAddress.name
;-------------------------------------------------
LoadLibrary:
; library name: [in] edx
; hInstance (export table): [out] eax
; [unchanged] edx, ebp, esp
mov edi, [relative_path_tail]
mov esi, edx
call Mov_memString
mcall SF_SYS_MISC,SSF_LOAD_DLL,relative_path
test eax, eax
jnz .done
mov edi, sys_lib_path_tail
mov esi, edx
call Mov_memString
mcall SF_SYS_MISC,SSF_LOAD_DLL,sys_lib_path
.done:
retn
;-------------------------------------------------
LoadLibraries:
; [in] no
;Error=-1,Success=0 [out] eax
; [unchanged] esp
load_libraries_error equ esp+4
push 0
current_lib_entry equ esp+0
push [ME_HEADER_V2.import.data]
.CopyCurDir:
mov esi, relative_path
mov edi, [ME_HEADER_V2.cur_dir_path]
or ecx, -1
xor eax, eax
cld
repne scasb
not ecx
mov al, '/'
std
repne scasb
cld
sub edi, ecx
add ecx, 2
xchg esi, edi
call Mov_memBlock
mov [relative_path_tail],edi
.LoopLibraries:
mov eax, dword[current_lib_entry]
mov ebp, [eax+LIBRARY_ENTRY.lookup_table]
test ebp, ebp
jz .done
mov edx, [eax+LIBRARY_ENTRY.lpname]
call LoadLibrary;edx=name
test eax, eax
jz .onError
mov esi, eax
mov eax, dword[current_lib_entry]
call ResolveImports
call TryEnterLibEntryPoint
add dword[current_lib_entry], sizeof.LIBRARY_ENTRY
jmp .LoopLibraries
.onError:
mov eax, dword[current_lib_entry]
or [eax+LIBRARY_ENTRY.lookup_table], -1
or dword[load_libraries_error], -1
add dword[current_lib_entry], sizeof.LIBRARY_ENTRY
jmp .LoopLibraries
.done:
pop eax
pop eax
retn
restore current_lib_entry,load_libraries_error
;-------------------------------------------------
TryEnterLibEntryPoint:
; hInstance (export table): [in] esi
; [out] no
; [unchanged] esp
mov edi, lib_init_proc
call GetProcAddress
test eax, eax
jz .processed
push eax
mov eax, mem.Alloc
mov ebx, mem.Free
mov ecx, mem.ReAlloc
mov edx, LoadLibraries
.processed:
retn
;-------------------------------------------------
APP_START_CHUNK:
cmp [ME_HEADER_V2.hdr_version], 2
jb .load_imports_no_needance
xor eax, eax
xchg eax, [exec_once]
test eax, eax
je .load_imports_no_needance
.validate_import:
mov eax, [ME_HEADER_V2.import_data]
test eax, eax
jz .load_imports_no_needance ; no reason to kill app for import absence - skip import processing
js .error
add eax, sizeof.MINIMAL_IMPORT_TABLE
cmp eax, [ME_HEADER_V2.init_mem_sz]
ja .error
call LoadLibraries
test eax, eax
js .handle_load_imports_error
mov eax, [ME_HEADER_V2.entry]
call eax
mcall SF_TERMINATE_PROCESS
.handle_load_imports_error:
;tell user via board or console or whatever about unsuccesed searching of import
;when GetProcAddress failed IMPORT_ENTRY.lpproc filled with -1
;when LoadLibrary failed LIBRARY_ENTRY.lookup_table filled with -1
;that should help to workaround import table and signal everything what failed
;that handling made by OS - so no needance in terminating process
.load_imports_no_needance:
retn
;-------------------------------------------------
align 4
exec_once dd APP_START_CHUNK
;-------------------------------------------------
; EXPORT
;-------------------------------------------------
export \
LoadLibraries, 'LoadLibraries',\
LoadLibrary, 'asmLoadLibrary',\
GetProcAddress, 'asmGetProcAddress',\
GetProcOrdinalAddress, 'asmGetProcOrdinalAddress',\
stdcall_LoadLibrary, 'LoadLibrary',\
stdcall_GetProcAddress, 'GetProcAddress'
;-------------------------------------------------
; INITIALIZED DATA
;-------------------------------------------------
align 4
relative_path_tail dd ?
lib_init_proc db 'lib_init',0
sys_lib_path db '/sys/lib/'
;---------------------------------------------------------------------
; UNINITIALIZED DATA
;---------------------------------------------------------------------
sys_lib_path_tail rb $400
relative_path rb $400