forked from KolibriOS/kolibrios
[CLEVERMOUSE_PE_KERNEL] Apply CleverMouse PE patch
git-svn-id: svn://kolibrios.org@9048 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
360e379fc7
commit
eccd8f2198
@ -440,11 +440,11 @@ ends
|
|||||||
struct PROC
|
struct PROC
|
||||||
list LHEAD
|
list LHEAD
|
||||||
thr_list LHEAD
|
thr_list LHEAD
|
||||||
|
smap_list LHEAD
|
||||||
heap_lock MUTEX
|
heap_lock MUTEX
|
||||||
heap_base rd 1
|
heap_base rd 1
|
||||||
heap_top rd 1
|
heap_top rd 1
|
||||||
mem_used rd 1
|
mem_used rd 1
|
||||||
dlls_list_ptr rd 1
|
|
||||||
pdt_0_phys rd 1
|
pdt_0_phys rd 1
|
||||||
pdt_1_phys rd 1
|
pdt_1_phys rd 1
|
||||||
io_map_0 rd 1
|
io_map_0 rd 1
|
||||||
@ -651,37 +651,16 @@ struct SMEM
|
|||||||
name rb 32 ;+24
|
name rb 32 ;+24
|
||||||
ends
|
ends
|
||||||
|
|
||||||
struct SMAP APPOBJ
|
struct SMAP
|
||||||
base dd ? ;mapped base
|
fd dd ? ;next in mmapped list
|
||||||
parent dd ? ;SMEM
|
bk dd ? ;prev in mmapped list
|
||||||
ends
|
|
||||||
|
|
||||||
struct DLLDESCR
|
|
||||||
bk dd ?
|
|
||||||
fd dd ? ;+4
|
|
||||||
data dd ? ;+8
|
|
||||||
size dd ? ;+12
|
|
||||||
timestamp dq ?
|
|
||||||
refcount dd ?
|
|
||||||
defaultbase dd ?
|
|
||||||
coff_hdr dd ?
|
|
||||||
symbols_ptr dd ?
|
|
||||||
symbols_num dd ?
|
|
||||||
symbols_lim dd ?
|
|
||||||
exports dd ? ;export table
|
|
||||||
name rb 260
|
|
||||||
ends
|
|
||||||
|
|
||||||
struct HDLL
|
|
||||||
fd dd ? ;next object in list
|
|
||||||
bk dd ? ;prev object in list
|
|
||||||
pid dd ? ;owner id
|
|
||||||
|
|
||||||
base dd ? ;mapped base
|
base dd ? ;mapped base
|
||||||
size dd ? ;mapped size
|
size dd ? ;mapped size
|
||||||
refcount dd ? ;reference counter for this process and this lib
|
type dd ? ;SMAP_TYPE_SMEM or SMAP_TYPE_PE
|
||||||
parent dd ? ;DLLDESCR
|
parent dd ? ;SMEM or PEDESCR
|
||||||
ends
|
ends
|
||||||
|
SMAP_TYPE_SMEM = 1
|
||||||
|
SMAP_TYPE_PE = 2
|
||||||
|
|
||||||
struct DQ
|
struct DQ
|
||||||
lo dd ?
|
lo dd ?
|
||||||
@ -810,6 +789,55 @@ struct PCIDEV
|
|||||||
owner dd ? ; pointer to SRV or 0
|
owner dd ? ; pointer to SRV or 0
|
||||||
ends
|
ends
|
||||||
|
|
||||||
|
struct PEDESCR
|
||||||
|
bk dd ?
|
||||||
|
fd dd ?
|
||||||
|
size dd ? ; in pages
|
||||||
|
timestamp dq ?
|
||||||
|
refcount dd ?
|
||||||
|
defaultbase dd ?
|
||||||
|
name dd ?
|
||||||
|
entry dd ?
|
||||||
|
stacksize dd ?
|
||||||
|
page_array_lock MUTEX
|
||||||
|
; After those fields the array follows, one dword per every of [size] pages.
|
||||||
|
; The value of every field has 3 parts:
|
||||||
|
; - upper 20 bits are page number or zero;
|
||||||
|
; - next 4 bits are access rights shareable/executable/readable/writable
|
||||||
|
; in the same order as IMAGE_SCN_MEM_xxx shifted appropriately;
|
||||||
|
; - lower 8 bits are reference counter.
|
||||||
|
; The exact meaning depends on page type.
|
||||||
|
; * For a page with data in non-shareable section
|
||||||
|
; which has at least one unmodified copy:
|
||||||
|
; - upper 20 bits are page number for unmodified copy,
|
||||||
|
; - reference counter = number of unmodified copies is nonzero up to 0xFF.
|
||||||
|
; If reference counter reaches 0xFF, it becomes locked at this value.
|
||||||
|
; If reference counter reaches zero, the last copy changes ownership
|
||||||
|
; to the last process,
|
||||||
|
; and the page is converted to the following state.
|
||||||
|
; * For a page with data in non-shareable section
|
||||||
|
; with no unmodified copies:
|
||||||
|
; - all fields are reset to zero.
|
||||||
|
; The original content is lost; map_pe_usermode would reload from file.
|
||||||
|
; * For a page with zeroes in non-shareable section:
|
||||||
|
; - upper 20 bits are zero,
|
||||||
|
; - lower 8 bits are 0xFF.
|
||||||
|
; * For a page in shareable section with data or with zeroes:
|
||||||
|
; - upper 20 bits are page number for all copies,
|
||||||
|
; - lower 8 bits are reference counter from 1 to 0xFF.
|
||||||
|
; Reference counter does not actually matter here,
|
||||||
|
; it equals [refcount] unless 0xFF was once reached,
|
||||||
|
; but is kept for consistency.
|
||||||
|
ends
|
||||||
|
|
||||||
|
struct SHARED_LOCKED_PAGE
|
||||||
|
fd dd ?
|
||||||
|
bk dd ?
|
||||||
|
address dd ?
|
||||||
|
parent dd ?
|
||||||
|
offs dd ?
|
||||||
|
ends
|
||||||
|
|
||||||
struct IDE_DATA
|
struct IDE_DATA
|
||||||
ProgrammingInterface dd ?
|
ProgrammingInterface dd ?
|
||||||
Interrupt dw ?
|
Interrupt dw ?
|
||||||
@ -933,6 +961,19 @@ struct COFF_SECTION
|
|||||||
NumLinenum dw ?
|
NumLinenum dw ?
|
||||||
Characteristics dd ?
|
Characteristics dd ?
|
||||||
ends
|
ends
|
||||||
|
IMAGE_SCN_MEM_SHARED = 10000000h
|
||||||
|
IMAGE_SCN_MEM_EXECUTE = 20000000h
|
||||||
|
IMAGE_SCN_MEM_READ = 40000000h
|
||||||
|
IMAGE_SCN_MEM_WRITE = 80000000h
|
||||||
|
|
||||||
|
struct STRIPPED_PE_SECTION
|
||||||
|
Name rb 8
|
||||||
|
VirtualSize dd ?
|
||||||
|
VirtualAddress dd ?
|
||||||
|
SizeOfRawData dd ?
|
||||||
|
PtrRawData dd ?
|
||||||
|
Characteristics dd ?
|
||||||
|
ends
|
||||||
|
|
||||||
struct COFF_RELOC
|
struct COFF_RELOC
|
||||||
VirtualAddress dd ?
|
VirtualAddress dd ?
|
||||||
@ -971,6 +1012,62 @@ SPE_DIRECTORY_IMPORT = 0
|
|||||||
SPE_DIRECTORY_EXPORT = 1
|
SPE_DIRECTORY_EXPORT = 1
|
||||||
SPE_DIRECTORY_BASERELOC = 2
|
SPE_DIRECTORY_BASERELOC = 2
|
||||||
|
|
||||||
|
struct IMAGE_DATA_DIRECTORY
|
||||||
|
VirtualAddress dd ?
|
||||||
|
isize dd ?
|
||||||
|
ends
|
||||||
|
|
||||||
|
struct IMAGE_OPTIONAL_HEADER32
|
||||||
|
Magic dw ?
|
||||||
|
MajorLinkerVersion db ?
|
||||||
|
MinorLinkerVersion db ?
|
||||||
|
SizeOfCode dd ?
|
||||||
|
SizeOfInitializedData dd ?
|
||||||
|
SizeOfUninitializedData dd ?
|
||||||
|
AddressOfEntryPoint dd ?
|
||||||
|
BaseOfCode dd ?
|
||||||
|
BaseOfData dd ?
|
||||||
|
ImageBase dd ?
|
||||||
|
SectionAlignment dd ?
|
||||||
|
FileAlignment dd ?
|
||||||
|
MajorOperatingSystemVersion dw ?
|
||||||
|
MinorOperatingSystemVersion dw ?
|
||||||
|
MajorImageVersion dw ?
|
||||||
|
MinorImageVersion dw ?
|
||||||
|
MajorSubsystemVersion dw ?
|
||||||
|
MinorSubsystemVersion dw ?
|
||||||
|
Win32VersionValue dd ?
|
||||||
|
SizeOfImage dd ?
|
||||||
|
SizeOfHeaders dd ?
|
||||||
|
CheckSum dd ?
|
||||||
|
Subsystem dw ?
|
||||||
|
DllCharacteristics dw ?
|
||||||
|
SizeOfStackReserve dd ?
|
||||||
|
SizeOfStackCommit dd ?
|
||||||
|
SizeOfHeapReserve dd ?
|
||||||
|
SizeOfHeapCommit dd ?
|
||||||
|
LoaderFlags dd ?
|
||||||
|
NumberOfDirectories dd ?
|
||||||
|
DataDirectory IMAGE_DATA_DIRECTORY ?
|
||||||
|
Directories rb sizeof.IMAGE_DATA_DIRECTORY*15
|
||||||
|
ends
|
||||||
|
|
||||||
|
struct IMAGE_FILE_HEADER
|
||||||
|
Machine dw ?
|
||||||
|
NumberOfSections dw ?
|
||||||
|
TimeDateStamp dd ?
|
||||||
|
PointerToSymbolTable dd ?
|
||||||
|
NumberOfSymbols dd ?
|
||||||
|
SizeOfOptionalHeader dw ?
|
||||||
|
Characteristics dw ?
|
||||||
|
ends
|
||||||
|
|
||||||
|
struct IMAGE_NT_HEADERS
|
||||||
|
Signature dd ?
|
||||||
|
FileHeader IMAGE_FILE_HEADER
|
||||||
|
OptionalHeader IMAGE_OPTIONAL_HEADER32
|
||||||
|
ends
|
||||||
|
|
||||||
struct IOCTL
|
struct IOCTL
|
||||||
handle dd ?
|
handle dd ?
|
||||||
io_code dd ?
|
io_code dd ?
|
||||||
|
@ -901,9 +901,13 @@ align 4
|
|||||||
proc load_library stdcall, file_name:dword, encoding:dword
|
proc load_library stdcall, file_name:dword, encoding:dword
|
||||||
locals
|
locals
|
||||||
fullname dd ?
|
fullname dd ?
|
||||||
fileinfo rb 40
|
filesize dd ?
|
||||||
coff dd ?
|
coff dd ?
|
||||||
img_base dd ?
|
img_base dd ?
|
||||||
|
img_size dd ?
|
||||||
|
symbols_ptr dd ?
|
||||||
|
symbols_lim dd ?
|
||||||
|
exports dd ?
|
||||||
endl
|
endl
|
||||||
|
|
||||||
; resolve file name
|
; resolve file name
|
||||||
@ -917,105 +921,19 @@ proc load_library stdcall, file_name:dword, encoding:dword
|
|||||||
pop ebp
|
pop ebp
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .fail
|
jz .fail
|
||||||
; scan for required DLL in list of already loaded for this process,
|
|
||||||
; ignore timestamp
|
|
||||||
cli
|
|
||||||
mov esi, [current_process]
|
|
||||||
mov edi, [fullname]
|
|
||||||
mov ebx, [esi+PROC.dlls_list_ptr]
|
|
||||||
test ebx, ebx
|
|
||||||
jz .not_in_process
|
|
||||||
mov esi, [ebx+HDLL.fd]
|
|
||||||
.scan_in_process:
|
|
||||||
cmp esi, ebx
|
|
||||||
jz .not_in_process
|
|
||||||
mov eax, [esi+HDLL.parent]
|
|
||||||
add eax, DLLDESCR.name
|
|
||||||
stdcall strncmp, eax, edi, -1
|
|
||||||
test eax, eax
|
|
||||||
jnz .next_in_process
|
|
||||||
; simple variant: load DLL which is already loaded in this process
|
|
||||||
; just increment reference counters and return address of exports table
|
|
||||||
inc [esi+HDLL.refcount]
|
|
||||||
mov ecx, [esi+HDLL.parent]
|
|
||||||
inc [ecx+DLLDESCR.refcount]
|
|
||||||
mov eax, [ecx+DLLDESCR.exports]
|
|
||||||
sub eax, [ecx+DLLDESCR.defaultbase]
|
|
||||||
add eax, [esi+HDLL.base]
|
|
||||||
sti
|
|
||||||
push eax
|
|
||||||
stdcall kernel_free, [fullname]
|
|
||||||
pop eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
.next_in_process:
|
|
||||||
mov esi, [esi+HDLL.fd]
|
|
||||||
jmp .scan_in_process
|
|
||||||
|
|
||||||
.not_in_process:
|
|
||||||
; scan in full list, compare timestamp
|
|
||||||
sti
|
|
||||||
lea eax, [fileinfo]
|
|
||||||
stdcall get_fileinfo, edi, eax
|
|
||||||
test eax, eax
|
|
||||||
jnz .fail
|
|
||||||
cli
|
|
||||||
mov esi, [dll_list.fd]
|
|
||||||
.scan_for_dlls:
|
|
||||||
cmp esi, dll_list
|
|
||||||
jz .load_new
|
|
||||||
lea eax, [esi+DLLDESCR.name]
|
|
||||||
stdcall strncmp, eax, edi, -1
|
|
||||||
test eax, eax
|
|
||||||
jnz .continue_scan
|
|
||||||
.test_prev_dll:
|
|
||||||
mov eax, dword [fileinfo+24]; last modified time
|
|
||||||
mov edx, dword [fileinfo+28]; last modified date
|
|
||||||
cmp dword [esi+DLLDESCR.timestamp], eax
|
|
||||||
jnz .continue_scan
|
|
||||||
cmp dword [esi+DLLDESCR.timestamp+4], edx
|
|
||||||
jz .dll_already_loaded
|
|
||||||
.continue_scan:
|
|
||||||
mov esi, [esi+DLLDESCR.fd]
|
|
||||||
jmp .scan_for_dlls
|
|
||||||
|
|
||||||
; new DLL
|
|
||||||
.load_new:
|
|
||||||
sti
|
|
||||||
; load file
|
; load file
|
||||||
stdcall load_file, edi
|
stdcall load_file, [fullname]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .fail
|
jz .fail
|
||||||
mov [coff], eax
|
mov [coff], eax
|
||||||
mov dword [fileinfo+32], ebx
|
mov [filesize], ebx
|
||||||
|
|
||||||
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
|
|
||||||
mov esi, edi
|
|
||||||
mov ecx, -1
|
|
||||||
xor eax, eax
|
|
||||||
repnz scasb
|
|
||||||
not ecx
|
|
||||||
lea eax, [ecx+sizeof.DLLDESCR]
|
|
||||||
push ecx
|
|
||||||
call malloc
|
|
||||||
pop ecx
|
|
||||||
test eax, eax
|
|
||||||
jz .fail_and_free_coff
|
|
||||||
; save timestamp
|
|
||||||
lea edi, [eax+DLLDESCR.name]
|
|
||||||
rep movsb
|
|
||||||
mov esi, eax
|
|
||||||
mov eax, dword [fileinfo+24]
|
|
||||||
mov dword [esi+DLLDESCR.timestamp], eax
|
|
||||||
mov eax, dword [fileinfo+28]
|
|
||||||
mov dword [esi+DLLDESCR.timestamp+4], eax
|
|
||||||
|
|
||||||
; calculate size of loaded DLL
|
; calculate size of loaded DLL
|
||||||
mov edx, [coff]
|
movzx ecx, [eax+COFF_HEADER.nSections]
|
||||||
movzx ecx, [edx+COFF_HEADER.nSections]
|
|
||||||
xor ebx, ebx
|
xor ebx, ebx
|
||||||
|
|
||||||
add edx, 20
|
lea edx, [eax+20]
|
||||||
@@:
|
@@:
|
||||||
call coff_get_align
|
call coff_get_align
|
||||||
add ebx, eax
|
add ebx, eax
|
||||||
@ -1026,31 +944,19 @@ proc load_library stdcall, file_name:dword, encoding:dword
|
|||||||
dec ecx
|
dec ecx
|
||||||
jnz @B
|
jnz @B
|
||||||
; it must be nonzero and not too big
|
; it must be nonzero and not too big
|
||||||
mov [esi+DLLDESCR.size], ebx
|
mov [img_size], ebx
|
||||||
test ebx, ebx
|
test ebx, ebx
|
||||||
jz .fail_and_free_dll
|
jz .fail_and_free_coff
|
||||||
cmp ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
|
cmp ebx, 0x10000000
|
||||||
ja .fail_and_free_dll
|
ja .fail_and_free_coff
|
||||||
; allocate memory for kernel-side image
|
; allocate memory
|
||||||
stdcall kernel_alloc, ebx
|
call init_heap
|
||||||
|
stdcall user_alloc, [img_size]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .fail_and_free_dll
|
jz .fail_and_free_coff
|
||||||
mov [esi+DLLDESCR.data], eax
|
mov [img_base], eax
|
||||||
; calculate preferred base address
|
|
||||||
add ebx, 0x1FFF
|
|
||||||
and ebx, not 0xFFF
|
|
||||||
mov ecx, [dll_cur_addr]
|
|
||||||
lea edx, [ecx+ebx]
|
|
||||||
cmp edx, MAX_DEFAULT_DLL_ADDR
|
|
||||||
jb @f
|
|
||||||
mov ecx, MIN_DEFAULT_DLL_ADDR
|
|
||||||
lea edx, [ecx+ebx]
|
|
||||||
@@:
|
|
||||||
mov [esi+DLLDESCR.defaultbase], ecx
|
|
||||||
mov [dll_cur_addr], edx
|
|
||||||
|
|
||||||
; copy sections and set correct values for VirtualAddress'es in headers
|
; copy sections and set correct values for VirtualAddress'es in headers
|
||||||
push esi
|
|
||||||
mov edx, [coff]
|
mov edx, [coff]
|
||||||
movzx ebx, [edx+COFF_HEADER.nSections]
|
movzx ebx, [edx+COFF_HEADER.nSections]
|
||||||
mov edi, eax
|
mov edi, eax
|
||||||
@ -1058,15 +964,11 @@ proc load_library stdcall, file_name:dword, encoding:dword
|
|||||||
cld
|
cld
|
||||||
@@:
|
@@:
|
||||||
call coff_get_align
|
call coff_get_align
|
||||||
add ecx, eax
|
|
||||||
add edi, eax
|
add edi, eax
|
||||||
not eax
|
not eax
|
||||||
and ecx, eax
|
|
||||||
and edi, eax
|
and edi, eax
|
||||||
mov [edx+COFF_SECTION.VirtualAddress], ecx
|
mov [edx+COFF_SECTION.VirtualAddress], edi
|
||||||
add ecx, [edx+COFF_SECTION.SizeOfRawData]
|
|
||||||
mov esi, [edx+COFF_SECTION.PtrRawData]
|
mov esi, [edx+COFF_SECTION.PtrRawData]
|
||||||
push ecx
|
|
||||||
mov ecx, [edx+COFF_SECTION.SizeOfRawData]
|
mov ecx, [edx+COFF_SECTION.SizeOfRawData]
|
||||||
test esi, esi
|
test esi, esi
|
||||||
jnz .copy
|
jnz .copy
|
||||||
@ -1077,282 +979,78 @@ proc load_library stdcall, file_name:dword, encoding:dword
|
|||||||
add esi, [coff]
|
add esi, [coff]
|
||||||
rep movsb
|
rep movsb
|
||||||
.next:
|
.next:
|
||||||
pop ecx
|
|
||||||
add edx, sizeof.COFF_SECTION
|
add edx, sizeof.COFF_SECTION
|
||||||
dec ebx
|
dec ebx
|
||||||
jnz @B
|
jnz @B
|
||||||
pop esi
|
|
||||||
|
|
||||||
; save some additional data from COFF file
|
|
||||||
; later we will use COFF header, headers for sections and symbol table
|
|
||||||
; and also relocations table for all sections
|
|
||||||
mov edx, [coff]
|
mov edx, [coff]
|
||||||
mov ebx, [edx+COFF_HEADER.pSymTable]
|
mov ebx, [edx+COFF_HEADER.pSymTable]
|
||||||
mov edi, dword [fileinfo+32]
|
mov edi, [filesize]
|
||||||
sub edi, ebx
|
sub edi, ebx
|
||||||
jc .fail_and_free_data
|
jc .fail_and_free_data
|
||||||
mov [esi+DLLDESCR.symbols_lim], edi
|
mov [symbols_lim], edi
|
||||||
add ebx, edx
|
add ebx, edx
|
||||||
movzx ecx, [edx+COFF_HEADER.nSections]
|
; coff_hdr = coff
|
||||||
lea ecx, [ecx*5]
|
; symbols_num = coff.nSymbols
|
||||||
lea edi, [edi+ecx*8+20]
|
mov [symbols_ptr], ebx
|
||||||
add edx, 20
|
mov ebx, edx
|
||||||
@@:
|
|
||||||
movzx eax, [edx+COFF_SECTION.NumReloc]
|
|
||||||
lea eax, [eax*5]
|
|
||||||
lea edi, [edi+eax*2]
|
|
||||||
add edx, sizeof.COFF_SECTION
|
|
||||||
sub ecx, 5
|
|
||||||
jnz @b
|
|
||||||
stdcall kernel_alloc, edi
|
|
||||||
test eax, eax
|
|
||||||
jz .fail_and_free_data
|
|
||||||
mov edx, [coff]
|
|
||||||
movzx ecx, [edx+COFF_HEADER.nSections]
|
|
||||||
lea ecx, [ecx*5]
|
|
||||||
lea ecx, [ecx*2+5]
|
|
||||||
mov [esi+DLLDESCR.coff_hdr], eax
|
|
||||||
push esi
|
|
||||||
mov esi, edx
|
|
||||||
mov edi, eax
|
|
||||||
rep movsd
|
|
||||||
pop esi
|
|
||||||
mov [esi+DLLDESCR.symbols_ptr], edi
|
|
||||||
push esi
|
|
||||||
mov ecx, [edx+COFF_HEADER.nSymbols]
|
|
||||||
mov [esi+DLLDESCR.symbols_num], ecx
|
|
||||||
mov ecx, [esi+DLLDESCR.symbols_lim]
|
|
||||||
mov esi, ebx
|
|
||||||
rep movsb
|
|
||||||
pop esi
|
|
||||||
mov ebx, [esi+DLLDESCR.coff_hdr]
|
|
||||||
push esi
|
|
||||||
movzx eax, [edx+COFF_HEADER.nSections]
|
|
||||||
lea edx, [ebx+20]
|
|
||||||
@@:
|
|
||||||
movzx ecx, [edx+COFF_SECTION.NumReloc]
|
|
||||||
lea ecx, [ecx*5]
|
|
||||||
mov esi, [edx+COFF_SECTION.PtrReloc]
|
|
||||||
mov [edx+COFF_SECTION.PtrReloc], edi
|
|
||||||
sub [edx+COFF_SECTION.PtrReloc], ebx
|
|
||||||
add esi, [coff]
|
|
||||||
shr ecx, 1
|
|
||||||
rep movsd
|
|
||||||
adc ecx, ecx
|
|
||||||
rep movsw
|
|
||||||
add edx, sizeof.COFF_SECTION
|
|
||||||
dec eax
|
|
||||||
jnz @b
|
|
||||||
pop esi
|
|
||||||
|
|
||||||
; fixup symbols
|
; fixup symbols
|
||||||
mov edx, ebx
|
mov eax, [edx+COFF_HEADER.nSymbols]
|
||||||
mov eax, [ebx+COFF_HEADER.nSymbols]
|
|
||||||
add edx, 20
|
add edx, 20
|
||||||
mov ecx, [esi+DLLDESCR.symbols_num]
|
lea ecx, [eax*9]
|
||||||
lea ecx, [ecx*9]
|
|
||||||
add ecx, ecx
|
add ecx, ecx
|
||||||
add ecx, [esi+DLLDESCR.symbols_ptr]
|
add ecx, [symbols_ptr]
|
||||||
|
|
||||||
stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \
|
stdcall fix_coff_symbols, edx, [symbols_ptr], eax, \
|
||||||
ecx, 0
|
ecx, 0
|
||||||
; test eax, eax
|
; test eax, eax
|
||||||
; jnz @F
|
; jnz @F
|
||||||
;
|
;
|
||||||
;@@:
|
;@@:
|
||||||
|
|
||||||
stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
|
stdcall get_coff_sym, [symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz @F
|
jnz @F
|
||||||
|
|
||||||
stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
|
stdcall get_coff_sym, [symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
|
||||||
@@:
|
@@:
|
||||||
mov [esi+DLLDESCR.exports], eax
|
mov [exports], eax
|
||||||
|
|
||||||
; fix relocs in the hidden copy in kernel memory to default address
|
stdcall fix_coff_relocs, ebx, [symbols_ptr], 0
|
||||||
; it is first fix; usually this will be enough, but second fix
|
|
||||||
; can be necessary if real load address will not equal assumption
|
|
||||||
mov eax, [esi+DLLDESCR.data]
|
|
||||||
sub eax, [esi+DLLDESCR.defaultbase]
|
|
||||||
stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
|
|
||||||
|
|
||||||
stdcall kernel_free, [coff]
|
stdcall kernel_free, [coff]
|
||||||
|
|
||||||
cli
|
|
||||||
; initialize DLLDESCR struct
|
|
||||||
and dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented
|
|
||||||
mov [esi+DLLDESCR.fd], dll_list
|
|
||||||
mov eax, [dll_list.bk]
|
|
||||||
mov [dll_list.bk], esi
|
|
||||||
mov [esi+DLLDESCR.bk], eax
|
|
||||||
mov [eax+DLLDESCR.fd], esi
|
|
||||||
.dll_already_loaded:
|
|
||||||
stdcall kernel_free, [fullname]
|
stdcall kernel_free, [fullname]
|
||||||
inc [esi+DLLDESCR.refcount]
|
|
||||||
push esi
|
|
||||||
call init_heap
|
|
||||||
pop esi
|
|
||||||
mov edi, [esi+DLLDESCR.size]
|
|
||||||
stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
|
|
||||||
test eax, eax
|
|
||||||
jnz @f
|
|
||||||
stdcall user_alloc, edi
|
|
||||||
test eax, eax
|
|
||||||
jz .fail_and_dereference
|
|
||||||
@@:
|
|
||||||
mov [img_base], eax
|
|
||||||
mov eax, sizeof.HDLL
|
|
||||||
call malloc
|
|
||||||
test eax, eax
|
|
||||||
jz .fail_and_free_user
|
|
||||||
mov ebx, [current_slot_idx]
|
|
||||||
shl ebx, 5
|
|
||||||
mov edx, [TASK_TABLE+ebx+TASKDATA.pid]
|
|
||||||
mov [eax+HDLL.pid], edx
|
|
||||||
push eax
|
|
||||||
call init_dlls_in_thread
|
|
||||||
pop ebx
|
|
||||||
test eax, eax
|
|
||||||
jz .fail_and_free_user
|
|
||||||
mov edx, [eax+HDLL.fd]
|
|
||||||
mov [ebx+HDLL.fd], edx
|
|
||||||
mov [ebx+HDLL.bk], eax
|
|
||||||
mov [eax+HDLL.fd], ebx
|
|
||||||
mov [edx+HDLL.bk], ebx
|
|
||||||
mov eax, ebx
|
|
||||||
mov ebx, [img_base]
|
|
||||||
mov [eax+HDLL.base], ebx
|
|
||||||
mov [eax+HDLL.size], edi
|
|
||||||
mov [eax+HDLL.refcount], 1
|
|
||||||
mov [eax+HDLL.parent], esi
|
|
||||||
mov edx, ebx
|
|
||||||
shr edx, 12
|
|
||||||
or dword [page_tabs+(edx-1)*4], MEM_BLOCK_DONT_FREE
|
|
||||||
; copy entries of page table from kernel-side image to usermode
|
|
||||||
; use copy-on-write for user-mode image, so map as readonly
|
|
||||||
xor edi, edi
|
|
||||||
mov ecx, [esi+DLLDESCR.data]
|
|
||||||
shr ecx, 12
|
|
||||||
.map_pages_loop:
|
|
||||||
mov eax, [page_tabs+ecx*4]
|
|
||||||
and eax, not 0xFFF
|
|
||||||
or al, PG_UR
|
|
||||||
xchg eax, [page_tabs+edx*4]
|
|
||||||
test al, 1
|
|
||||||
jz @f
|
|
||||||
call free_page
|
|
||||||
@@:
|
|
||||||
invlpg [ebx+edi]
|
|
||||||
inc ecx
|
|
||||||
inc edx
|
|
||||||
add edi, 0x1000
|
|
||||||
cmp edi, [esi+DLLDESCR.size]
|
|
||||||
jb .map_pages_loop
|
|
||||||
|
|
||||||
; if real user-mode base is not equal to preferred base, relocate image
|
mov eax, [exports]
|
||||||
sub ebx, [esi+DLLDESCR.defaultbase]
|
|
||||||
jz @f
|
|
||||||
stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
|
|
||||||
@@:
|
|
||||||
|
|
||||||
mov eax, [esi+DLLDESCR.exports]
|
|
||||||
sub eax, [esi+DLLDESCR.defaultbase]
|
|
||||||
add eax, [img_base]
|
|
||||||
sti
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.fail_and_free_data:
|
.fail_and_free_data:
|
||||||
stdcall kernel_free, [esi+DLLDESCR.data]
|
stdcall user_free, [img_base]
|
||||||
.fail_and_free_dll:
|
|
||||||
mov eax, esi
|
|
||||||
call free
|
|
||||||
.fail_and_free_coff:
|
.fail_and_free_coff:
|
||||||
stdcall kernel_free, [coff]
|
stdcall kernel_free, [coff]
|
||||||
.fail:
|
.fail:
|
||||||
stdcall kernel_free, [fullname]
|
stdcall kernel_free, [fullname]
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.fail_and_free_user:
|
|
||||||
stdcall user_free, [img_base]
|
|
||||||
.fail_and_dereference:
|
|
||||||
mov eax, 1 ; delete 1 reference
|
|
||||||
call dereference_dll
|
|
||||||
sti
|
|
||||||
xor eax, eax
|
|
||||||
ret
|
|
||||||
endp
|
endp
|
||||||
|
|
||||||
; initialize [APPDATA.dlls_list_ptr] for given thread
|
; in: esi -> PEDESCR struct
|
||||||
; DLL is per-process object, so APPDATA.dlls_list_ptr must be
|
proc dereference_pe
|
||||||
; kept in sync for all threads of one process.
|
mov ecx, pe_list_mutex
|
||||||
; out: eax = APPDATA.dlls_list_ptr if all is OK,
|
call mutex_lock
|
||||||
; NULL if memory allocation failed
|
dec [esi+PEDESCR.refcount]
|
||||||
init_dlls_in_thread:
|
jnz mutex_unlock
|
||||||
mov ebx, [current_process]
|
mov eax, [esi+PEDESCR.fd]
|
||||||
mov eax, [ebx+PROC.dlls_list_ptr]
|
mov edx, [esi+PEDESCR.bk]
|
||||||
test eax, eax
|
mov [eax+PEDESCR.bk], edx
|
||||||
jnz .ret
|
mov [edx+PEDESCR.fd], eax
|
||||||
|
call mutex_unlock
|
||||||
mov eax, 8
|
|
||||||
call malloc ; FIXME
|
|
||||||
test eax, eax
|
|
||||||
jz .ret
|
|
||||||
|
|
||||||
mov [eax], eax
|
|
||||||
mov [eax+4], eax
|
|
||||||
|
|
||||||
mov ebx, [current_process]
|
|
||||||
mov [ebx+PROC.dlls_list_ptr], eax
|
|
||||||
.ret:
|
|
||||||
ret
|
|
||||||
|
|
||||||
; in: eax = number of references to delete, esi -> DLLDESCR struc
|
|
||||||
dereference_dll:
|
|
||||||
sub [esi+DLLDESCR.refcount], eax
|
|
||||||
jnz .ret
|
|
||||||
mov eax, [esi+DLLDESCR.fd]
|
|
||||||
mov edx, [esi+DLLDESCR.bk]
|
|
||||||
mov [eax+DLLDESCR.bk], edx
|
|
||||||
mov [edx+DLLDESCR.fd], eax
|
|
||||||
stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
|
|
||||||
stdcall kernel_free, [esi+DLLDESCR.data]
|
|
||||||
mov eax, esi
|
mov eax, esi
|
||||||
call free
|
call free
|
||||||
.ret:
|
|
||||||
ret
|
|
||||||
|
|
||||||
destroy_hdll:
|
|
||||||
push ebx ecx esi edi
|
|
||||||
mov ebx, [eax+HDLL.base]
|
|
||||||
mov esi, [eax+HDLL.parent]
|
|
||||||
mov edx, [esi+DLLDESCR.size]
|
|
||||||
|
|
||||||
push eax
|
|
||||||
mov esi, [eax+HDLL.parent]
|
|
||||||
mov eax, [eax+HDLL.refcount]
|
|
||||||
call dereference_dll
|
|
||||||
pop eax
|
|
||||||
mov edx, [eax+HDLL.bk]
|
|
||||||
mov ebx, [eax+HDLL.fd]
|
|
||||||
mov [ebx+HDLL.bk], edx
|
|
||||||
mov [edx+HDLL.fd], ebx
|
|
||||||
call free
|
|
||||||
pop edi esi ecx ebx
|
|
||||||
ret
|
|
||||||
|
|
||||||
; ecx -> APPDATA for slot, esi = dlls_list_ptr
|
|
||||||
destroy_all_hdlls:
|
|
||||||
test esi, esi
|
|
||||||
jz .ret
|
|
||||||
.loop:
|
|
||||||
mov eax, [esi+HDLL.fd]
|
|
||||||
cmp eax, esi
|
|
||||||
jz free
|
|
||||||
call destroy_hdll
|
|
||||||
jmp .loop
|
|
||||||
.ret:
|
|
||||||
ret
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
stop_all_services:
|
stop_all_services:
|
||||||
|
@ -23,8 +23,13 @@ MEM_BLOCK_FREE = 0x04
|
|||||||
MEM_BLOCK_USED = 0x08
|
MEM_BLOCK_USED = 0x08
|
||||||
MEM_BLOCK_DONT_FREE = 0x10
|
MEM_BLOCK_DONT_FREE = 0x10
|
||||||
|
|
||||||
|
LAZY_ALLOC_PAGE = 2
|
||||||
|
LAZY_ALLOC_UNREADABLE = 20h
|
||||||
|
LAZY_ALLOC_UNWRITABLE = 40h
|
||||||
|
|
||||||
macro calc_index op
|
macro calc_index op
|
||||||
{ shr op, 12
|
{
|
||||||
|
shr op, 12
|
||||||
dec op
|
dec op
|
||||||
cmp op, 63
|
cmp op, 63
|
||||||
jna @f
|
jna @f
|
||||||
@ -561,35 +566,42 @@ proc init_heap
|
|||||||
sub eax, PAGE_SIZE
|
sub eax, PAGE_SIZE
|
||||||
ret
|
ret
|
||||||
@@:
|
@@:
|
||||||
lea ecx, [ebx + PROC.heap_lock]
|
|
||||||
call mutex_init
|
|
||||||
|
|
||||||
mov esi, [ebx + PROC.mem_used]
|
mov edx, [ebx+PROC.mem_used]
|
||||||
add esi, 4095
|
add edx, 4095
|
||||||
and esi, not 4095
|
and edx, not 4095
|
||||||
mov [ebx + PROC.mem_used], esi
|
mov [ebx+PROC.mem_used], edx
|
||||||
mov eax, HEAP_TOP
|
mov eax, HEAP_TOP
|
||||||
mov [ebx + PROC.heap_base], esi
|
mov [ebx+PROC.heap_base], edx
|
||||||
mov [ebx + PROC.heap_top], eax
|
mov [ebx+PROC.heap_top], eax
|
||||||
|
|
||||||
sub eax, esi
|
sub eax, edx
|
||||||
shr esi, 10
|
shr edx, 10
|
||||||
mov ecx, eax
|
mov ecx, eax
|
||||||
sub eax, PAGE_SIZE
|
sub eax, PAGE_SIZE
|
||||||
or ecx, MEM_BLOCK_FREE
|
or ecx, MEM_BLOCK_FREE
|
||||||
mov [page_tabs + esi], ecx
|
mov [page_tabs + edx], ecx
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
proc user_alloc stdcall, alloc_size:dword
|
proc user_alloc ;stdcall, alloc_size:dword
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_lock
|
||||||
|
stdcall user_alloc_nolock, [esp+4]
|
||||||
|
push eax
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
|
pop eax
|
||||||
|
ret 4
|
||||||
|
endp
|
||||||
|
|
||||||
|
proc user_alloc_nolock stdcall, alloc_size:dword
|
||||||
push ebx esi edi
|
push ebx esi edi
|
||||||
|
|
||||||
mov ebx, [current_process]
|
mov ebx, [current_process]
|
||||||
lea ecx, [ebx + PROC.heap_lock]
|
|
||||||
call mutex_lock
|
|
||||||
|
|
||||||
mov ecx, [alloc_size]
|
mov ecx, [alloc_size]
|
||||||
add ecx, (4095 + PAGE_SIZE)
|
add ecx, (4095 + PAGE_SIZE)
|
||||||
and ecx, not 4095
|
and ecx, not 4095
|
||||||
@ -628,15 +640,6 @@ proc user_alloc stdcall, alloc_size:dword
|
|||||||
jnz @B
|
jnz @B
|
||||||
.no:
|
.no:
|
||||||
|
|
||||||
mov edx, [current_process]
|
|
||||||
mov ebx, [alloc_size]
|
|
||||||
add ebx, 0xFFF
|
|
||||||
and ebx, not 0xFFF
|
|
||||||
add [edx + PROC.mem_used], ebx
|
|
||||||
|
|
||||||
lea ecx, [edx + PROC.heap_lock]
|
|
||||||
call mutex_unlock
|
|
||||||
|
|
||||||
lea eax, [esi + 4096]
|
lea eax, [esi + 4096]
|
||||||
|
|
||||||
pop edi
|
pop edi
|
||||||
@ -652,9 +655,6 @@ proc user_alloc stdcall, alloc_size:dword
|
|||||||
add esi, eax
|
add esi, eax
|
||||||
jmp .scan
|
jmp .scan
|
||||||
.m_exit:
|
.m_exit:
|
||||||
mov ecx, [current_process]
|
|
||||||
lea ecx, [ecx + PROC.heap_lock]
|
|
||||||
call mutex_unlock
|
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
pop edi
|
pop edi
|
||||||
@ -664,15 +664,25 @@ proc user_alloc stdcall, alloc_size:dword
|
|||||||
endp
|
endp
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
proc user_alloc_at stdcall, address:dword, alloc_size:dword
|
proc user_alloc_at ;stdcall, address:dword, alloc_size:dword
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_lock
|
||||||
|
stdcall user_alloc_at_nolock, [esp+8], [esp+8]
|
||||||
|
push eax
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
|
pop eax
|
||||||
|
ret 8
|
||||||
|
endp
|
||||||
|
|
||||||
|
proc user_alloc_at_nolock stdcall, address:dword, alloc_size:dword
|
||||||
push ebx
|
push ebx
|
||||||
push esi
|
push esi
|
||||||
push edi
|
push edi
|
||||||
|
|
||||||
mov ebx, [current_process]
|
mov ebx, [current_process]
|
||||||
lea ecx, [ebx + PROC.heap_lock]
|
|
||||||
call mutex_lock
|
|
||||||
|
|
||||||
mov edx, [address]
|
mov edx, [address]
|
||||||
and edx, not 0xFFF
|
and edx, not 0xFFF
|
||||||
@ -697,9 +707,6 @@ proc user_alloc_at stdcall, address:dword, alloc_size:dword
|
|||||||
mov esi, ecx
|
mov esi, ecx
|
||||||
jmp .scan
|
jmp .scan
|
||||||
.error:
|
.error:
|
||||||
mov ecx, [current_process]
|
|
||||||
lea ecx, [ecx + PROC.heap_lock]
|
|
||||||
call mutex_unlock
|
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
pop edi
|
pop edi
|
||||||
@ -751,16 +758,7 @@ proc user_alloc_at stdcall, address:dword, alloc_size:dword
|
|||||||
or cl, MEM_BLOCK_FREE
|
or cl, MEM_BLOCK_FREE
|
||||||
mov [page_tabs + ebx*4], ecx
|
mov [page_tabs + ebx*4], ecx
|
||||||
|
|
||||||
.nothird:
|
.nothird:
|
||||||
mov edx, [current_process]
|
|
||||||
mov ebx, [alloc_size]
|
|
||||||
add ebx, 0xFFF
|
|
||||||
and ebx, not 0xFFF
|
|
||||||
add [edx + PROC.mem_used], ebx
|
|
||||||
|
|
||||||
lea ecx, [edx + PROC.heap_lock]
|
|
||||||
call mutex_unlock
|
|
||||||
|
|
||||||
mov eax, [address]
|
mov eax, [address]
|
||||||
|
|
||||||
pop edi
|
pop edi
|
||||||
@ -775,8 +773,6 @@ proc user_free stdcall, base:dword
|
|||||||
push esi
|
push esi
|
||||||
|
|
||||||
mov esi, [base]
|
mov esi, [base]
|
||||||
test esi, esi
|
|
||||||
jz .fail
|
|
||||||
|
|
||||||
push ebx
|
push ebx
|
||||||
|
|
||||||
@ -786,12 +782,18 @@ proc user_free stdcall, base:dword
|
|||||||
|
|
||||||
xor ebx, ebx
|
xor ebx, ebx
|
||||||
shr esi, 12
|
shr esi, 12
|
||||||
|
jz .cantfree
|
||||||
mov eax, [page_tabs + (esi-1)*4]
|
mov eax, [page_tabs + (esi-1)*4]
|
||||||
test al, MEM_BLOCK_USED
|
test al, MEM_BLOCK_USED
|
||||||
jz .cantfree
|
jz .cantfree
|
||||||
test al, MEM_BLOCK_DONT_FREE
|
test al, MEM_BLOCK_DONT_FREE
|
||||||
jnz .cantfree
|
jnz .cantfree
|
||||||
|
|
||||||
|
push 0
|
||||||
|
virtual at esp
|
||||||
|
.num_released_pages dd ?
|
||||||
|
end virtual
|
||||||
|
|
||||||
and eax, not 4095
|
and eax, not 4095
|
||||||
mov ecx, eax
|
mov ecx, eax
|
||||||
or al, MEM_BLOCK_FREE
|
or al, MEM_BLOCK_FREE
|
||||||
@ -800,35 +802,33 @@ proc user_free stdcall, base:dword
|
|||||||
mov ebx, ecx
|
mov ebx, ecx
|
||||||
shr ecx, 12
|
shr ecx, 12
|
||||||
jz .released
|
jz .released
|
||||||
.release:
|
.release:
|
||||||
xor eax, eax
|
mov edx, [page_tabs+esi*4]
|
||||||
xchg eax, [page_tabs + esi*4]
|
mov dword [page_tabs+esi*4], 0
|
||||||
test al, 1
|
|
||||||
jz @F
|
|
||||||
test eax, PG_SHARED
|
|
||||||
jnz @F
|
|
||||||
call free_page
|
|
||||||
mov eax, esi
|
mov eax, esi
|
||||||
shl eax, 12
|
shl eax, 12
|
||||||
invlpg [eax]
|
invlpg [eax]
|
||||||
@@:
|
test dl, 1
|
||||||
|
jz @F
|
||||||
|
inc [.num_released_pages]
|
||||||
|
test edx, PG_SHARED
|
||||||
|
jnz @f
|
||||||
|
mov eax, edx
|
||||||
|
call free_page
|
||||||
|
@@:
|
||||||
inc esi
|
inc esi
|
||||||
dec ecx
|
dec ecx
|
||||||
jnz .release
|
jnz .release
|
||||||
|
|
||||||
.released:
|
.released:
|
||||||
push edi
|
|
||||||
|
|
||||||
|
pop eax ; .num_released_pages
|
||||||
|
shl eax, 12
|
||||||
mov edx, [current_process]
|
mov edx, [current_process]
|
||||||
lea ecx, [edx + PROC.heap_lock]
|
lea ecx, [edx + PROC.heap_lock]
|
||||||
mov esi, dword [edx + PROC.heap_base]
|
sub [edx + PROC.mem_used], eax
|
||||||
mov edi, dword [edx + PROC.heap_top]
|
|
||||||
sub ebx, [edx + PROC.mem_used]
|
|
||||||
neg ebx
|
|
||||||
mov [edx + PROC.mem_used], ebx
|
|
||||||
call user_normalize
|
call user_normalize
|
||||||
pop edi
|
.exit:
|
||||||
.exit:
|
|
||||||
call mutex_unlock
|
call mutex_unlock
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
@ -850,18 +850,21 @@ endp
|
|||||||
|
|
||||||
align 4
|
align 4
|
||||||
proc user_unmap stdcall, base:dword, offset:dword, size:dword
|
proc user_unmap stdcall, base:dword, offset:dword, size:dword
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_lock
|
||||||
|
|
||||||
push ebx
|
push ebx
|
||||||
|
|
||||||
mov ebx, [base] ; must be valid pointer
|
mov ebx, [base] ; must be valid pointer
|
||||||
test ebx, ebx
|
|
||||||
jz .error
|
|
||||||
|
|
||||||
mov edx, [offset] ; check offset
|
mov edx, [offset] ; check offset
|
||||||
add edx, ebx ; must be below 2Gb app limit
|
add edx, ebx ; must be below 2Gb app limit
|
||||||
|
jc .error
|
||||||
js .error
|
js .error
|
||||||
|
|
||||||
shr ebx, 12 ; chek block attributes
|
shr ebx, 12 ; chek block attributes
|
||||||
|
jz .error
|
||||||
lea ebx, [page_tabs + ebx*4]
|
lea ebx, [page_tabs + ebx*4]
|
||||||
mov eax, [ebx-4] ; block attributes
|
mov eax, [ebx-4] ; block attributes
|
||||||
test al, MEM_BLOCK_USED
|
test al, MEM_BLOCK_USED
|
||||||
@ -887,36 +890,63 @@ proc user_unmap stdcall, base:dword, offset:dword, size:dword
|
|||||||
and ebx, not 4095 ; is it required ?
|
and ebx, not 4095 ; is it required ?
|
||||||
add ebx, [base]
|
add ebx, [base]
|
||||||
|
|
||||||
.unmap:
|
push 0
|
||||||
|
virtual at esp
|
||||||
|
.num_released_pages dd ?
|
||||||
|
end virtual
|
||||||
|
|
||||||
|
.unmap:
|
||||||
mov eax, [edx] ; get page addres
|
mov eax, [edx] ; get page addres
|
||||||
test al, 1 ; page mapped ?
|
test al, 1 ; page mapped ?
|
||||||
jz @F
|
jz .next
|
||||||
test eax, PG_SHARED ; page shared ?
|
test eax, PG_SHARED ; page shared ?
|
||||||
jnz @F
|
jnz .next
|
||||||
mov dword[edx], MEM_BLOCK_RESERVED
|
inc [.num_released_pages]
|
||||||
|
mov dword [edx], LAZY_ALLOC_PAGE
|
||||||
; mark page as reserved
|
; mark page as reserved
|
||||||
|
test eax, PG_READ
|
||||||
|
jnz @f
|
||||||
|
or dword [edx], LAZY_ALLOC_UNREADABLE
|
||||||
|
@@:
|
||||||
|
test eax, PG_WRITE
|
||||||
|
jnz @f
|
||||||
|
or dword [edx], LAZY_ALLOC_UNWRITABLE
|
||||||
|
@@:
|
||||||
invlpg [ebx] ; when we start using
|
invlpg [ebx] ; when we start using
|
||||||
call free_page ; empty c-o-w page instead this ?
|
call free_page ; empty c-o-w page instead this ?
|
||||||
@@:
|
.next:
|
||||||
add ebx, 4096 ; PAGESIZE?
|
add ebx, 4096
|
||||||
add edx, 4
|
add edx, 4
|
||||||
dec ecx
|
dec ecx
|
||||||
jnz .unmap
|
jnz .unmap
|
||||||
|
|
||||||
|
pop eax ; .num_released_pages
|
||||||
pop ebx
|
pop ebx
|
||||||
or al, 1 ; return non zero on success
|
shl eax, 12
|
||||||
|
mov ecx, [current_process]
|
||||||
|
sub [ecx+PROC.mem_used], eax
|
||||||
|
push eax
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
|
pop eax ; return number of released bytes
|
||||||
ret
|
ret
|
||||||
.error:
|
.error:
|
||||||
pop ebx
|
pop ebx
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
xor eax, eax ; something wrong
|
xor eax, eax ; something wrong
|
||||||
|
dec eax
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
user_normalize:
|
proc user_normalize uses esi edi
|
||||||
; in: esi=heap_base, edi=heap_top
|
; in: edx->PROC
|
||||||
; out: eax=0 <=> OK
|
; out: eax=0 <=> OK
|
||||||
; destroys: ebx,edx,esi,edi
|
; destroys: ebx,edx
|
||||||
|
mov esi, dword [edx+PROC.heap_base]
|
||||||
|
mov edi, dword [edx+PROC.heap_top]
|
||||||
shr esi, 12
|
shr esi, 12
|
||||||
shr edi, 12
|
shr edi, 12
|
||||||
@@:
|
@@:
|
||||||
@ -959,6 +989,7 @@ user_normalize:
|
|||||||
.err:
|
.err:
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
user_realloc:
|
user_realloc:
|
||||||
; in: eax = pointer, ebx = new size
|
; in: eax = pointer, ebx = new size
|
||||||
@ -1004,37 +1035,43 @@ user_realloc:
|
|||||||
cmp edx, ebx
|
cmp edx, ebx
|
||||||
jb .realloc_add
|
jb .realloc_add
|
||||||
; release part of allocated memory
|
; release part of allocated memory
|
||||||
|
push edx
|
||||||
|
push 0
|
||||||
|
virtual at esp
|
||||||
|
.num_released_pages dd ?
|
||||||
|
end virtual
|
||||||
.loop:
|
.loop:
|
||||||
cmp edx, ebx
|
cmp edx, ebx
|
||||||
jz .release_done
|
jz .release_done
|
||||||
dec edx
|
dec edx
|
||||||
xor eax, eax
|
push dword [page_tabs + edx*4]
|
||||||
xchg eax, [page_tabs + edx*4]
|
mov dword [page_tabs + edx*4], 0
|
||||||
test al, 1
|
|
||||||
jz .loop
|
|
||||||
call free_page
|
|
||||||
mov eax, edx
|
mov eax, edx
|
||||||
shl eax, 12
|
shl eax, 12
|
||||||
invlpg [eax]
|
invlpg [eax]
|
||||||
|
pop eax
|
||||||
|
test al, 1
|
||||||
|
jz .loop
|
||||||
|
inc [.num_released_pages]
|
||||||
|
test eax, PG_SHARED
|
||||||
|
jnz .loop
|
||||||
|
call free_page
|
||||||
jmp .loop
|
jmp .loop
|
||||||
.release_done:
|
.release_done:
|
||||||
|
pop eax ; .num_released_pages
|
||||||
|
mov edx, [current_process]
|
||||||
|
shl eax, 12
|
||||||
|
sub [edx+PROC.mem_used], eax
|
||||||
|
pop edx
|
||||||
sub ebx, ecx
|
sub ebx, ecx
|
||||||
cmp ebx, 1
|
cmp ebx, 1
|
||||||
jnz .nofreeall
|
jnz .nofreeall
|
||||||
mov eax, [page_tabs + ecx*4]
|
mov eax, [page_tabs + ecx*4]
|
||||||
and eax, not 0xFFF
|
and eax, not 0xFFF
|
||||||
mov edx, [current_process]
|
|
||||||
mov ebx, [edx + PROC.mem_used]
|
|
||||||
sub ebx, eax
|
|
||||||
add ebx, 0x1000
|
|
||||||
or al, MEM_BLOCK_FREE
|
or al, MEM_BLOCK_FREE
|
||||||
mov [page_tabs + ecx*4], eax
|
mov [page_tabs + ecx*4], eax
|
||||||
push esi edi
|
mov edx, [current_process]
|
||||||
mov esi, [edx + PROC.heap_base]
|
|
||||||
mov edi, [edx + PROC.heap_top]
|
|
||||||
mov [edx + PROC.mem_used], ebx
|
|
||||||
call user_normalize
|
call user_normalize
|
||||||
pop edi esi
|
|
||||||
jmp .ret0 ; all freed
|
jmp .ret0 ; all freed
|
||||||
.nofreeall:
|
.nofreeall:
|
||||||
sub edx, ecx
|
sub edx, ecx
|
||||||
@ -1043,13 +1080,6 @@ user_realloc:
|
|||||||
xchg [page_tabs + ecx*4], ebx
|
xchg [page_tabs + ecx*4], ebx
|
||||||
shr ebx, 12
|
shr ebx, 12
|
||||||
sub ebx, edx
|
sub ebx, edx
|
||||||
push ebx ecx edx
|
|
||||||
mov edx, [current_process]
|
|
||||||
shl ebx, 12
|
|
||||||
sub ebx, [edx + PROC.mem_used]
|
|
||||||
neg ebx
|
|
||||||
mov [edx + PROC.mem_used], ebx
|
|
||||||
pop edx ecx ebx
|
|
||||||
lea eax, [ecx + 1]
|
lea eax, [ecx + 1]
|
||||||
shl eax, 12
|
shl eax, 12
|
||||||
push eax
|
push eax
|
||||||
@ -1119,9 +1149,6 @@ user_realloc:
|
|||||||
cld
|
cld
|
||||||
rep stosd
|
rep stosd
|
||||||
pop edi
|
pop edi
|
||||||
mov edx, [current_process]
|
|
||||||
shl ebx, 12
|
|
||||||
add [edx + PROC.mem_used], ebx
|
|
||||||
|
|
||||||
mov ecx, [current_process]
|
mov ecx, [current_process]
|
||||||
lea ecx, [ecx + PROC.heap_lock]
|
lea ecx, [ecx + PROC.heap_lock]
|
||||||
@ -1195,11 +1222,6 @@ user_realloc:
|
|||||||
dec edx
|
dec edx
|
||||||
jnz @b
|
jnz @b
|
||||||
.no:
|
.no:
|
||||||
push ebx
|
|
||||||
mov edx, [current_process]
|
|
||||||
shl ebx, 12
|
|
||||||
add [edx + PROC.mem_used], ebx
|
|
||||||
pop ebx
|
|
||||||
@@:
|
@@:
|
||||||
mov dword [page_tabs + esi*4], MEM_BLOCK_RESERVED
|
mov dword [page_tabs + esi*4], MEM_BLOCK_RESERVED
|
||||||
inc esi
|
inc esi
|
||||||
@ -1218,24 +1240,47 @@ user_realloc:
|
|||||||
|
|
||||||
|
|
||||||
; param
|
; param
|
||||||
; eax= shm_map object
|
; edi= shm_map object
|
||||||
|
; [esp+4] = process
|
||||||
align 4
|
|
||||||
destroy_smap:
|
|
||||||
|
|
||||||
pushfd
|
|
||||||
cli
|
|
||||||
|
|
||||||
|
proc destroy_smap ;stdcall, process:dword
|
||||||
push esi
|
push esi
|
||||||
push edi
|
mov esi, [edi+SMAP.parent]
|
||||||
|
cmp [edi+SMAP.type], SMAP_TYPE_SMEM
|
||||||
|
jz .smem
|
||||||
|
mov ecx, [esp+8]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_lock
|
||||||
|
stdcall release_pemap, [esp+8]
|
||||||
|
mov ecx, [esp+8]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
|
sub ecx, PROC.heap_lock
|
||||||
|
cmp ecx, [current_process]
|
||||||
|
jnz @f
|
||||||
|
stdcall user_free, [edi+SMAP.base]
|
||||||
|
@@:
|
||||||
|
call dereference_pe
|
||||||
|
jmp .common
|
||||||
|
.smem:
|
||||||
|
mov eax, [current_process]
|
||||||
|
cmp [esp+8], eax
|
||||||
|
jnz @f
|
||||||
|
stdcall user_free, [edi+SMAP.base]
|
||||||
|
@@:
|
||||||
|
call dereference_smem
|
||||||
|
.common:
|
||||||
|
mov eax, edi
|
||||||
|
call free
|
||||||
|
pop esi
|
||||||
|
ret 4
|
||||||
|
endp
|
||||||
|
|
||||||
mov edi, eax
|
proc dereference_smem
|
||||||
mov esi, [eax + SMAP.parent]
|
mov ecx, shmem_list_mutex
|
||||||
test esi, esi
|
call mutex_lock
|
||||||
jz .done
|
dec [esi+SMEM.refcount]
|
||||||
|
jnz mutex_unlock
|
||||||
lock dec [esi + SMEM.refcount]
|
|
||||||
jnz .done
|
|
||||||
|
|
||||||
mov ecx, [esi + SMEM.bk]
|
mov ecx, [esi + SMEM.bk]
|
||||||
mov edx, [esi + SMEM.fd]
|
mov edx, [esi + SMEM.fd]
|
||||||
@ -1243,18 +1288,14 @@ destroy_smap:
|
|||||||
mov [ecx + SMEM.fd], edx
|
mov [ecx + SMEM.fd], edx
|
||||||
mov [edx + SMEM.bk], ecx
|
mov [edx + SMEM.bk], ecx
|
||||||
|
|
||||||
|
mov ecx, shmem_list_mutex
|
||||||
|
call mutex_unlock
|
||||||
|
|
||||||
stdcall kernel_free, [esi + SMEM.base]
|
stdcall kernel_free, [esi + SMEM.base]
|
||||||
mov eax, esi
|
mov eax, esi
|
||||||
call free
|
call free
|
||||||
.done:
|
|
||||||
mov eax, edi
|
|
||||||
call destroy_kernel_object
|
|
||||||
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
popfd
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
E_NOTFOUND = 5
|
E_NOTFOUND = 5
|
||||||
E_ACCESS = 10
|
E_ACCESS = 10
|
||||||
@ -1273,31 +1314,28 @@ SHM_CREATE = 2 shl 2
|
|||||||
SHM_OPEN_MASK = 3 shl 2
|
SHM_OPEN_MASK = 3 shl 2
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
proc shmem_open stdcall name:dword, size:dword, access:dword
|
proc shmem_open stdcall uses ebx esi edi, name:dword, size:dword, access:dword
|
||||||
locals
|
locals
|
||||||
action dd ?
|
action dd ?
|
||||||
owner_access dd ?
|
owner_access dd ?
|
||||||
mapped dd ?
|
mapped dd ?
|
||||||
|
edx_ret dd ?
|
||||||
endl
|
endl
|
||||||
|
|
||||||
push ebx
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
|
|
||||||
mov [mapped], 0
|
mov [mapped], 0
|
||||||
mov [owner_access], 0
|
mov [owner_access], 0
|
||||||
|
|
||||||
pushfd ;mutex required
|
|
||||||
cli
|
|
||||||
|
|
||||||
mov eax, [access]
|
mov eax, [access]
|
||||||
and eax, SHM_OPEN_MASK
|
and eax, SHM_OPEN_MASK
|
||||||
mov [action], eax
|
mov [action], eax
|
||||||
|
|
||||||
mov ebx, [name]
|
mov ebx, [name]
|
||||||
test ebx, ebx
|
test ebx, ebx
|
||||||
mov edx, E_PARAM
|
mov [edx_ret], E_PARAM
|
||||||
jz .fail
|
jz .exit
|
||||||
|
|
||||||
|
mov ecx, shmem_list_mutex
|
||||||
|
call mutex_lock
|
||||||
|
|
||||||
mov esi, [shmem_list.fd]
|
mov esi, [shmem_list.fd]
|
||||||
align 4
|
align 4
|
||||||
@ -1316,22 +1354,22 @@ align 4
|
|||||||
.not_found:
|
.not_found:
|
||||||
mov eax, [action]
|
mov eax, [action]
|
||||||
|
|
||||||
|
mov [edx_ret], E_NOTFOUND
|
||||||
cmp eax, SHM_OPEN
|
cmp eax, SHM_OPEN
|
||||||
mov edx, E_NOTFOUND
|
je .exit_unlock
|
||||||
je .fail
|
|
||||||
|
|
||||||
|
mov [edx_ret], E_PARAM
|
||||||
cmp eax, SHM_CREATE
|
cmp eax, SHM_CREATE
|
||||||
mov edx, E_PARAM
|
|
||||||
je .create_shm
|
je .create_shm
|
||||||
|
|
||||||
cmp eax, SHM_OPEN_ALWAYS
|
cmp eax, SHM_OPEN_ALWAYS
|
||||||
jne .fail
|
jne .exit_unlock
|
||||||
|
|
||||||
.create_shm:
|
.create_shm:
|
||||||
|
|
||||||
mov ecx, [size]
|
mov ecx, [size]
|
||||||
test ecx, ecx
|
test ecx, ecx
|
||||||
jz .fail
|
jz .exit_unlock
|
||||||
|
|
||||||
add ecx, 4095
|
add ecx, 4095
|
||||||
and ecx, -4096
|
and ecx, -4096
|
||||||
@ -1341,13 +1379,11 @@ align 4
|
|||||||
call malloc
|
call malloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
mov esi, eax
|
mov esi, eax
|
||||||
mov edx, E_NOMEM
|
mov [edx_ret], E_NOMEM
|
||||||
jz .fail
|
jz .exit_unlock
|
||||||
|
|
||||||
stdcall kernel_alloc, [size]
|
stdcall kernel_alloc, [size]
|
||||||
test eax, eax
|
test eax, eax
|
||||||
mov [mapped], eax
|
|
||||||
mov edx, E_NOMEM
|
|
||||||
jz .cleanup
|
jz .cleanup
|
||||||
|
|
||||||
mov ecx, [size]
|
mov ecx, [size]
|
||||||
@ -1376,16 +1412,16 @@ align 4
|
|||||||
.found:
|
.found:
|
||||||
mov eax, [action]
|
mov eax, [action]
|
||||||
|
|
||||||
|
mov [edx_ret], E_ACCESS
|
||||||
cmp eax, SHM_CREATE
|
cmp eax, SHM_CREATE
|
||||||
mov edx, E_ACCESS
|
je .exit_unlock
|
||||||
je .exit
|
|
||||||
|
|
||||||
|
mov [edx_ret], E_PARAM
|
||||||
cmp eax, SHM_OPEN
|
cmp eax, SHM_OPEN
|
||||||
mov edx, E_PARAM
|
|
||||||
je .create_map
|
je .create_map
|
||||||
|
|
||||||
cmp eax, SHM_OPEN_ALWAYS
|
cmp eax, SHM_OPEN_ALWAYS
|
||||||
jne .fail
|
jne .exit_unlock
|
||||||
|
|
||||||
.create_map:
|
.create_map:
|
||||||
|
|
||||||
@ -1393,129 +1429,148 @@ align 4
|
|||||||
and eax, SHM_ACCESS_MASK
|
and eax, SHM_ACCESS_MASK
|
||||||
cmp eax, [esi + SMEM.access]
|
cmp eax, [esi + SMEM.access]
|
||||||
mov [access], eax
|
mov [access], eax
|
||||||
mov edx, E_ACCESS
|
mov [edx_ret], E_ACCESS
|
||||||
ja .fail
|
ja .exit_unlock
|
||||||
|
|
||||||
|
inc [esi+SMEM.refcount]
|
||||||
|
mov ecx, shmem_list_mutex
|
||||||
|
call mutex_unlock
|
||||||
|
|
||||||
mov ebx, [current_slot_idx]
|
|
||||||
shl ebx, BSF sizeof.TASKDATA
|
|
||||||
mov ebx, [TASK_TABLE + ebx + TASKDATA.pid]
|
|
||||||
mov eax, sizeof.SMAP
|
mov eax, sizeof.SMAP
|
||||||
|
call malloc
|
||||||
call create_kernel_object
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
mov edi, eax
|
mov edi, eax
|
||||||
mov edx, E_NOMEM
|
mov [edx_ret], E_NOMEM
|
||||||
jz .fail
|
|
||||||
|
|
||||||
inc [esi + SMEM.refcount]
|
|
||||||
|
|
||||||
mov [edi + SMAP.magic], 'SMAP'
|
|
||||||
mov [edi + SMAP.destroy], destroy_smap
|
|
||||||
mov [edi + SMAP.parent], esi
|
|
||||||
mov [edi + SMAP.base], 0
|
|
||||||
|
|
||||||
stdcall user_alloc, [esi + SMEM.size]
|
|
||||||
test eax, eax
|
|
||||||
mov [mapped], eax
|
|
||||||
mov edx, E_NOMEM
|
|
||||||
jz .cleanup2
|
jz .cleanup2
|
||||||
|
|
||||||
|
mov [edi+SMAP.type], SMAP_TYPE_SMEM
|
||||||
|
mov [edi + SMAP.parent], esi
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_lock
|
||||||
|
|
||||||
|
stdcall user_alloc_nolock, [esi+SMEM.size]
|
||||||
|
test eax, eax
|
||||||
|
mov [mapped], eax
|
||||||
|
jz .cleanup3
|
||||||
|
|
||||||
mov [edi + SMAP.base], eax
|
mov [edi + SMAP.base], eax
|
||||||
|
mov ecx, [current_process]
|
||||||
|
mov edx, [ecx+PROC.smap_list+SMAP.bk]
|
||||||
|
add ecx, PROC.smap_list
|
||||||
|
mov [edi+SMAP.fd], ecx
|
||||||
|
mov [edi+SMAP.bk], edx
|
||||||
|
mov [ecx+SMAP.bk], edi
|
||||||
|
mov [edx+SMAP.fd], edi
|
||||||
|
|
||||||
mov ecx, [esi + SMEM.size]
|
mov ecx, [esi + SMEM.size]
|
||||||
mov [size], ecx
|
mov [edi + SMAP.size], ecx
|
||||||
|
mov [edx_ret], ecx
|
||||||
|
|
||||||
shr ecx, 12
|
shr ecx, 12
|
||||||
shr eax, 10
|
shr eax, 10
|
||||||
|
|
||||||
mov esi, [esi + SMEM.base]
|
mov esi, [esi + SMEM.base]
|
||||||
shr esi, 10
|
shr esi, 10
|
||||||
lea edi, [page_tabs + eax]
|
|
||||||
add esi, page_tabs
|
|
||||||
|
|
||||||
|
xor ebx, ebx
|
||||||
mov edx, [access]
|
mov edx, [access]
|
||||||
or edx, [owner_access]
|
or edx, [owner_access]
|
||||||
shl edx, 1
|
shl edx, 1
|
||||||
or edx, PG_SHARED + PG_UR
|
or edx, PG_SHARED + PG_UR
|
||||||
@@:
|
@@:
|
||||||
lodsd
|
mov edi, [page_tabs+esi+ebx*4]
|
||||||
and eax, 0xFFFFF000
|
and edi, 0xFFFFF000
|
||||||
or eax, edx
|
or edi, edx
|
||||||
stosd
|
mov [page_tabs+eax+ebx*4], edi
|
||||||
loop @B
|
inc ebx
|
||||||
|
dec ecx
|
||||||
|
jnz @B
|
||||||
|
|
||||||
xor edx, edx
|
mov ecx, [current_process]
|
||||||
|
shl ebx, 12
|
||||||
|
add [ecx+PROC.mem_used], ebx
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
|
|
||||||
cmp [owner_access], 0
|
cmp [owner_access], 0
|
||||||
jne .fail
|
jz .exit
|
||||||
.exit:
|
mov [edx_ret], 0
|
||||||
mov edx, [size]
|
|
||||||
.fail:
|
|
||||||
mov eax, [mapped]
|
|
||||||
|
|
||||||
popfd
|
.exit:
|
||||||
pop edi
|
mov eax, [mapped]
|
||||||
pop esi
|
mov edx, [edx_ret]
|
||||||
pop ebx
|
|
||||||
ret
|
ret
|
||||||
.cleanup:
|
.cleanup:
|
||||||
mov [size], edx
|
|
||||||
mov eax, esi
|
mov eax, esi
|
||||||
call free
|
call free
|
||||||
|
.exit_unlock:
|
||||||
|
mov ecx, shmem_list_mutex
|
||||||
|
call mutex_unlock
|
||||||
jmp .exit
|
jmp .exit
|
||||||
|
|
||||||
.cleanup2:
|
.cleanup3:
|
||||||
mov [size], edx
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
mov eax, edi
|
mov eax, edi
|
||||||
call destroy_smap
|
call free
|
||||||
|
.cleanup2:
|
||||||
|
call dereference_smem
|
||||||
jmp .exit
|
jmp .exit
|
||||||
endp
|
endp
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
proc shmem_close stdcall, name:dword
|
proc shmem_close stdcall, name:dword
|
||||||
|
|
||||||
mov eax, [name]
|
cmp [name], 0
|
||||||
test eax, eax
|
|
||||||
jz .fail
|
jz .fail
|
||||||
|
|
||||||
push esi
|
push esi
|
||||||
push edi
|
push edi
|
||||||
pushfd
|
|
||||||
cli
|
|
||||||
|
|
||||||
mov esi, [current_slot]
|
mov ecx, [current_process]
|
||||||
add esi, APP_OBJ_OFFSET
|
lea edi, [ecx+PROC.smap_list]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_lock
|
||||||
|
mov esi, edi
|
||||||
|
|
||||||
.next:
|
.next:
|
||||||
mov eax, [esi + APPOBJ.fd]
|
mov edi, [edi+SMAP.fd]
|
||||||
test eax, eax
|
cmp edi, esi
|
||||||
jz @F
|
je .notfound
|
||||||
|
|
||||||
cmp eax, esi
|
cmp [edi + SMAP.type], SMAP_TYPE_SMEM
|
||||||
mov esi, eax
|
|
||||||
je @F
|
|
||||||
|
|
||||||
cmp [eax + SMAP.magic], 'SMAP'
|
|
||||||
jne .next
|
jne .next
|
||||||
|
|
||||||
mov edi, [eax + SMAP.parent]
|
mov eax, [edi + SMAP.parent]
|
||||||
test edi, edi
|
add eax, SMEM.name
|
||||||
jz .next
|
|
||||||
|
|
||||||
lea edi, [edi + SMEM.name]
|
stdcall strncmp, [name], eax, 32
|
||||||
stdcall strncmp, [name], edi, 32
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jne .next
|
jne .next
|
||||||
|
|
||||||
stdcall user_free, [esi + SMAP.base]
|
mov eax, [edi+SMAP.fd]
|
||||||
|
mov edx, [edi+SMAP.bk]
|
||||||
|
mov [eax+SMAP.bk], edx
|
||||||
|
mov [edx+SMAP.fd], eax
|
||||||
|
|
||||||
mov eax, esi
|
mov ecx, [current_process]
|
||||||
call [esi + APPOBJ.destroy]
|
add ecx, PROC.heap_lock
|
||||||
@@:
|
call mutex_unlock
|
||||||
popfd
|
|
||||||
|
stdcall destroy_smap, [current_process]
|
||||||
|
|
||||||
|
.exit:
|
||||||
pop edi
|
pop edi
|
||||||
pop esi
|
pop esi
|
||||||
.fail:
|
.fail:
|
||||||
ret
|
ret
|
||||||
|
.notfound:
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
|
jmp .exit
|
||||||
endp
|
endp
|
||||||
|
|
||||||
|
|
||||||
@ -1586,4 +1641,4 @@ endl
|
|||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
endp
|
endp
|
||||||
|
File diff suppressed because it is too large
Load Diff
833
kernel/branches/kolibrios-pe-clevermouse/core/peuser.inc
Normal file
833
kernel/branches/kolibrios-pe-clevermouse/core/peuser.inc
Normal file
@ -0,0 +1,833 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; Copyright (C) KolibriOS team 2016. All rights reserved. ;;
|
||||||
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
|
;; ;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
; Checks whether the given file is already loaded as PE.
|
||||||
|
; If so, returns pointer to PEDESCR which can be used for map_pe_usermode.
|
||||||
|
; out: eax = 0, ebx undefined
|
||||||
|
; out: esi -> PEDESCR
|
||||||
|
; If not, loads the given file; if it is PE, creates PEDESCR;
|
||||||
|
; out: eax -> file data, ebx = file size
|
||||||
|
; out: esi -> PEDESCR
|
||||||
|
; if it is not PE, returns loaded file as is.
|
||||||
|
; out: eax -> file data, ebx = file size
|
||||||
|
; out: esi = 0
|
||||||
|
; On error:
|
||||||
|
; out: eax = negative error code, ebx = 0
|
||||||
|
; out: esi = 0
|
||||||
|
proc load_file_maybe_pe stdcall uses edi, file_name:dword
|
||||||
|
locals
|
||||||
|
fileinfo rb 40
|
||||||
|
filedata dd ?
|
||||||
|
defaultbase dd ?
|
||||||
|
entry dd ?
|
||||||
|
stacksize dd ?
|
||||||
|
endl
|
||||||
|
and [filedata], 0
|
||||||
|
; 1. Lock the common mutex for PE list.
|
||||||
|
mov ecx, pe_list_mutex
|
||||||
|
call mutex_lock
|
||||||
|
; 2. Check whether this PE file is already mapped somewhere.
|
||||||
|
; 2a. Get the timestamp. If failed, pass filesystem error to the caller.
|
||||||
|
lea eax, [fileinfo]
|
||||||
|
stdcall get_fileinfo, [file_name], eax
|
||||||
|
mov edi, eax
|
||||||
|
neg edi
|
||||||
|
jnz .fail_unlock
|
||||||
|
; 2b. Scan the list of PE files, for each file compare timestamp and name.
|
||||||
|
; If all parameters match, go to 6. Otherwide, proceed to 3.
|
||||||
|
mov esi, [pe_list.fd]
|
||||||
|
.scan_existing:
|
||||||
|
cmp esi, pe_list
|
||||||
|
jz .load_new
|
||||||
|
mov eax, dword [fileinfo+24]; last modified time
|
||||||
|
mov edx, dword [fileinfo+28]; last modified date
|
||||||
|
cmp dword [esi+PEDESCR.timestamp], eax
|
||||||
|
jnz .continue_scan
|
||||||
|
cmp dword [esi+PEDESCR.timestamp+4], edx
|
||||||
|
jnz .continue_scan
|
||||||
|
stdcall strncmp, [esi+PEDESCR.name], [file_name], -1
|
||||||
|
test eax, eax
|
||||||
|
jz .already_loaded
|
||||||
|
.continue_scan:
|
||||||
|
mov esi, [esi+PEDESCR.fd]
|
||||||
|
jmp .scan_existing
|
||||||
|
|
||||||
|
; Either this file is not PE, or it has not been mapped yet.
|
||||||
|
.load_new:
|
||||||
|
; 3. Load and unpack file data.
|
||||||
|
; If failed, return -5 "file not found".
|
||||||
|
stdcall load_file, [file_name]
|
||||||
|
movi edi, -5
|
||||||
|
test eax, eax
|
||||||
|
jz .fail_unlock
|
||||||
|
mov [filedata], eax
|
||||||
|
mov dword [fileinfo+32], ebx
|
||||||
|
; 4. Check that the file is valid PE, has image data and is not too large.
|
||||||
|
; If not, pass the loaded file to the caller as is.
|
||||||
|
cmp ebx, 40h
|
||||||
|
jb .not_pe
|
||||||
|
cmp word [eax], 'MZ'
|
||||||
|
jz .check_mz
|
||||||
|
cmp [eax+STRIPPED_PE_HEADER.Signature], STRIPPED_PE_SIGNATURE
|
||||||
|
jnz .not_pe
|
||||||
|
mov ecx, [eax+STRIPPED_PE_HEADER.SizeOfStackReserve]
|
||||||
|
mov [stacksize], ecx
|
||||||
|
mov ecx, [eax+STRIPPED_PE_HEADER.ImageBase]
|
||||||
|
mov esi, [eax+STRIPPED_PE_HEADER.SizeOfImage]
|
||||||
|
mov edi, [eax+STRIPPED_PE_HEADER.AddressOfEntryPoint]
|
||||||
|
jmp .pe
|
||||||
|
.check_mz:
|
||||||
|
mov ecx, [eax+3Ch]
|
||||||
|
add eax, ecx
|
||||||
|
add ecx, IMAGE_NT_HEADERS.OptionalHeader
|
||||||
|
jc .not_pe
|
||||||
|
cmp ecx, ebx
|
||||||
|
ja .not_pe
|
||||||
|
cmp [eax+IMAGE_NT_HEADERS.Signature], 'PE'
|
||||||
|
jnz .not_pe
|
||||||
|
movzx edx, [eax+IMAGE_NT_HEADERS.FileHeader.SizeOfOptionalHeader]
|
||||||
|
cmp edx, IMAGE_OPTIONAL_HEADER32.DataDirectory
|
||||||
|
jb .not_pe
|
||||||
|
add ecx, edx
|
||||||
|
jc .not_pe
|
||||||
|
cmp ecx, ebx
|
||||||
|
ja .not_pe
|
||||||
|
cmp [eax+IMAGE_NT_HEADERS.OptionalHeader.Magic], 10Bh
|
||||||
|
jnz .not_pe
|
||||||
|
mov ecx, [eax+IMAGE_NT_HEADERS.OptionalHeader.SizeOfStackReserve]
|
||||||
|
mov [stacksize], ecx
|
||||||
|
mov ecx, [eax+IMAGE_NT_HEADERS.OptionalHeader.ImageBase]
|
||||||
|
mov esi, [eax+IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage]
|
||||||
|
mov edi, [eax+IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint]
|
||||||
|
.pe:
|
||||||
|
test esi, esi
|
||||||
|
jz .not_pe
|
||||||
|
cmp esi, 16*1024*1024
|
||||||
|
ja .not_pe
|
||||||
|
mov [defaultbase], ecx
|
||||||
|
mov [entry], edi
|
||||||
|
add esi, 0xFFF
|
||||||
|
shr esi, 12
|
||||||
|
; 5. Allocate and initialize PEDESCR structure.
|
||||||
|
; 5a. Calculate structure size: sizeof.PEDESCR + dword per image page + size of PE name.
|
||||||
|
mov edi, [file_name]
|
||||||
|
mov ecx, -1
|
||||||
|
xor eax, eax
|
||||||
|
repnz scasb
|
||||||
|
not ecx
|
||||||
|
lea eax, [ecx+esi*4+sizeof.PEDESCR]
|
||||||
|
; 5b. Allocate memory.
|
||||||
|
; If failed, return -30 "no memory".
|
||||||
|
push ecx
|
||||||
|
call malloc
|
||||||
|
pop ecx
|
||||||
|
movi edi, -30
|
||||||
|
test eax, eax
|
||||||
|
jz .fail_and_free_data
|
||||||
|
; 5c. Initialize PEDESCR structure.
|
||||||
|
mov [eax+PEDESCR.size], esi
|
||||||
|
lea edi, [eax+esi*4+sizeof.PEDESCR]
|
||||||
|
mov esi, [file_name]
|
||||||
|
mov [eax+PEDESCR.name], edi
|
||||||
|
rep movsb
|
||||||
|
mov esi, eax
|
||||||
|
lea edi, [eax+sizeof.PEDESCR]
|
||||||
|
mov ecx, [eax+PEDESCR.size]
|
||||||
|
xor eax, eax
|
||||||
|
rep stosd
|
||||||
|
mov eax, dword [fileinfo+24]
|
||||||
|
mov dword [esi+PEDESCR.timestamp], eax
|
||||||
|
mov eax, dword [fileinfo+28]
|
||||||
|
mov dword [esi+PEDESCR.timestamp+4], eax
|
||||||
|
mov eax, [defaultbase]
|
||||||
|
mov [esi+PEDESCR.defaultbase], eax
|
||||||
|
mov eax, [entry]
|
||||||
|
mov [esi+PEDESCR.entry], eax
|
||||||
|
mov eax, [stacksize]
|
||||||
|
mov [esi+PEDESCR.stacksize], eax
|
||||||
|
and dword [esi+PEDESCR.refcount], 0; no SMAPs yet; later it will be incremented
|
||||||
|
lea ecx, [esi+PEDESCR.page_array_lock]
|
||||||
|
call mutex_init
|
||||||
|
; 5d. Insert PEDESCR structure in tail of the common list.
|
||||||
|
mov [esi+PEDESCR.fd], pe_list
|
||||||
|
mov eax, [pe_list.bk]
|
||||||
|
mov [pe_list.bk], esi
|
||||||
|
mov [esi+PEDESCR.bk], eax
|
||||||
|
mov [eax+PEDESCR.fd], esi
|
||||||
|
.already_loaded:
|
||||||
|
; We have got the PEDESCR structure,
|
||||||
|
; either already-existed from step 2 or created at step 5.
|
||||||
|
; In the last case we have also got the file data,
|
||||||
|
; in the first case [filedata] is still zero.
|
||||||
|
; 6. Increment reference counter in PEDESCR structure.
|
||||||
|
inc [esi+PEDESCR.refcount]
|
||||||
|
; 7. Release the common mutex for PE list.
|
||||||
|
; We have got a new reference to our PEDESCR, it will not go away unexpectedly.
|
||||||
|
mov ecx, pe_list_mutex
|
||||||
|
call mutex_unlock
|
||||||
|
mov eax, [filedata]
|
||||||
|
mov ebx, dword [fileinfo+32]
|
||||||
|
ret
|
||||||
|
.fail_and_free_data:
|
||||||
|
stdcall kernel_free, [filedata]
|
||||||
|
.fail_unlock:
|
||||||
|
mov ecx, pe_list_mutex
|
||||||
|
call mutex_unlock
|
||||||
|
.fail:
|
||||||
|
mov eax, edi
|
||||||
|
xor ebx, ebx
|
||||||
|
xor esi, esi
|
||||||
|
ret
|
||||||
|
.not_pe:
|
||||||
|
mov ecx, pe_list_mutex
|
||||||
|
call mutex_unlock
|
||||||
|
mov eax, [filedata]
|
||||||
|
xor esi, esi
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
|
proc map_pe_usermode stdcall uses ebx esi edi, descr:dword, filedata:dword, filesize:dword
|
||||||
|
locals
|
||||||
|
img_base dd ?
|
||||||
|
peheader dd ?
|
||||||
|
header_size dd ?
|
||||||
|
num_sections dd ?
|
||||||
|
sections dd ?
|
||||||
|
section_idx dd ?
|
||||||
|
page_index dd ?
|
||||||
|
page_offset dd ?
|
||||||
|
cur_page dd ?
|
||||||
|
cur_access db ?
|
||||||
|
rb 3
|
||||||
|
pages dd ?
|
||||||
|
num_allocated_pages dd ?
|
||||||
|
endl
|
||||||
|
|
||||||
|
; 1. Basic preparations.
|
||||||
|
; 1a. Check that the process heap has been initialized.
|
||||||
|
; Return -30 "no memory" if not.
|
||||||
|
mov esi, [descr]
|
||||||
|
movi edi, -30
|
||||||
|
mov eax, [current_process]
|
||||||
|
cmp [eax+PROC.heap_top], 0
|
||||||
|
jz .fail_dereference
|
||||||
|
; 1b. If filedata is passed, fill the required fields from header now.
|
||||||
|
mov eax, [filedata]
|
||||||
|
mov ebx, [filesize]
|
||||||
|
dec edi ; -30 -> -31
|
||||||
|
test eax, eax
|
||||||
|
jz @f
|
||||||
|
call .validate_header
|
||||||
|
jc .fail_dereference
|
||||||
|
@@:
|
||||||
|
|
||||||
|
; 2. Generate array of pages for mapping in address space in the process.
|
||||||
|
; It is possible to join this step with step 13, avoiding temporary allocation
|
||||||
|
; and putting the result directly in the page table, but that would require
|
||||||
|
; doing potentially long operations like loading/unpacking the file
|
||||||
|
; while holding address space lock, which could block other threads
|
||||||
|
; that just want to lazy-allocate their zero-only pages not related to PE.
|
||||||
|
; So, keep generating and mapping separate.
|
||||||
|
; 2a. Allocate memory.
|
||||||
|
inc edi ; -31 -> -30
|
||||||
|
mov eax, [esi+PEDESCR.size]
|
||||||
|
shl eax, 2
|
||||||
|
call malloc
|
||||||
|
test eax, eax
|
||||||
|
jz .fail_dereference
|
||||||
|
mov [pages], eax
|
||||||
|
; 2b. Acquire the lock.
|
||||||
|
lea ecx, [esi+PEDESCR.page_array_lock]
|
||||||
|
call mutex_lock
|
||||||
|
; 2c. Prepare for loop over pages: set page index and page offset to zero.
|
||||||
|
xor ecx, ecx
|
||||||
|
mov [page_index], ecx
|
||||||
|
mov [page_offset], ecx
|
||||||
|
mov [num_allocated_pages], ecx
|
||||||
|
.fill_pages:
|
||||||
|
; 2d. For each page, test whether we need to regenerate it.
|
||||||
|
; Pages that need to be regenerated are marked as zero in pages array.
|
||||||
|
mov eax, [esi+sizeof.PEDESCR+ecx*4]
|
||||||
|
test eax, eax
|
||||||
|
jz .create_page
|
||||||
|
; 2e. For each page that we do not need to regenerate,
|
||||||
|
; increment reference counter if it is less than 0xFF
|
||||||
|
; and go to 2t.
|
||||||
|
lea edx, [eax+1]
|
||||||
|
test edx, 0xFF
|
||||||
|
jz .page_created
|
||||||
|
mov [esi+sizeof.PEDESCR+ecx*4], edx
|
||||||
|
jmp .page_created
|
||||||
|
.create_page:
|
||||||
|
; 2f. If the file has not been already loaded/unpacked,
|
||||||
|
; do it now, validating the content.
|
||||||
|
cmp [filedata], 0
|
||||||
|
jnz @f
|
||||||
|
stdcall load_file, [esi+PEDESCR.name]
|
||||||
|
test eax, eax
|
||||||
|
jz .fail_free_pages
|
||||||
|
call .validate_header
|
||||||
|
jc .fail_free_pages
|
||||||
|
@@:
|
||||||
|
; 2h. Initialize for generating a page:
|
||||||
|
; do not allocate a page until we will be sure that data are present,
|
||||||
|
; there are no access rights yet.
|
||||||
|
and [cur_page], 0
|
||||||
|
mov [cur_access], 0
|
||||||
|
; 2i. Check whether the page overlaps file header.
|
||||||
|
; If not, go to 2m.
|
||||||
|
mov eax, [page_offset]
|
||||||
|
cmp eax, [header_size]
|
||||||
|
jae .no_header
|
||||||
|
; 2j. Allocate the page data.
|
||||||
|
stdcall kernel_alloc, 0x1000
|
||||||
|
test eax, eax
|
||||||
|
jz .fail_free_pages
|
||||||
|
mov [cur_page], eax
|
||||||
|
; 2k. Set access rights for header: readonly; copy header data.
|
||||||
|
mov [cur_access], IMAGE_SCN_MEM_READ shr 28
|
||||||
|
mov esi, [filedata]
|
||||||
|
mov edi, eax
|
||||||
|
add esi, [page_offset]
|
||||||
|
mov ecx, [header_size]
|
||||||
|
sub ecx, [page_offset]
|
||||||
|
cmp ecx, 0x1000
|
||||||
|
jb @f
|
||||||
|
mov ecx, 0x1000
|
||||||
|
@@:
|
||||||
|
mov edx, ecx
|
||||||
|
shr ecx, 2
|
||||||
|
rep movsd
|
||||||
|
mov ecx, edx
|
||||||
|
and ecx, 3
|
||||||
|
rep movsb
|
||||||
|
; 2l. Fill the rest of the page with zeroes.
|
||||||
|
mov ecx, 0x1000
|
||||||
|
sub ecx, edx
|
||||||
|
mov edx, ecx
|
||||||
|
shr ecx, 2
|
||||||
|
and edx, 3
|
||||||
|
xor eax, eax
|
||||||
|
rep stosd
|
||||||
|
mov ecx, edx
|
||||||
|
rep stosb
|
||||||
|
.no_header:
|
||||||
|
; 2m. Prepare for loop over sections.
|
||||||
|
; Skip the loop if there are no sections.
|
||||||
|
mov eax, [num_sections]
|
||||||
|
mov ebx, [sections]
|
||||||
|
test eax, eax
|
||||||
|
jz .no_sections
|
||||||
|
mov [section_idx], eax
|
||||||
|
.sections_loop:
|
||||||
|
; 2n. For every section, check whether it has data overlapped with
|
||||||
|
; the current page; if so, allocate the page if not yet, copy the data
|
||||||
|
; and fill rest of page with zeroes.
|
||||||
|
; If data are present, there can be two cases:
|
||||||
|
; - the current page has data from the beginning,
|
||||||
|
; - first byte of the current page is not covered by the section.
|
||||||
|
; The first case is typical, the second case is rare.
|
||||||
|
; If the page has not been allocated yet, we can optimize by storing zeroes
|
||||||
|
; only in areas that are not covered by the current section.
|
||||||
|
; However, this becomes twisted in the second case,
|
||||||
|
; so don't bother to optimize the rare case.
|
||||||
|
cmp [ebx+COFF_SECTION.SizeOfRawData], 0
|
||||||
|
jz .section_data_done
|
||||||
|
mov esi, [page_offset]
|
||||||
|
sub esi, [ebx+COFF_SECTION.VirtualAddress]
|
||||||
|
cmp esi, [ebx+COFF_SECTION.SizeOfRawData]
|
||||||
|
jb .beginning_inside
|
||||||
|
add esi, 1000h
|
||||||
|
jnc .section_data_done
|
||||||
|
jz .section_data_done
|
||||||
|
; Rare case: there is an overlap, but the first byte is not covered.
|
||||||
|
; If the page has not been allocated, allocate it now and store 4K zeroes.
|
||||||
|
cmp [cur_page], 0
|
||||||
|
jnz @f
|
||||||
|
stdcall kernel_alloc, 0x1000
|
||||||
|
test eax, eax
|
||||||
|
jz .fail_free_pages
|
||||||
|
mov [cur_page], eax
|
||||||
|
mov edi, eax
|
||||||
|
xor eax, eax
|
||||||
|
mov ecx, 0x1000/4
|
||||||
|
rep stosd
|
||||||
|
@@:
|
||||||
|
mov edi, [ebx+COFF_SECTION.VirtualAddress]
|
||||||
|
and edi, 0xFFF
|
||||||
|
xor esi, esi
|
||||||
|
.copy_data:
|
||||||
|
mov eax, [ebx+COFF_SECTION.SizeOfRawData]
|
||||||
|
sub eax, esi
|
||||||
|
mov ecx, 0x1000
|
||||||
|
sub ecx, edi
|
||||||
|
add edi, [cur_page]
|
||||||
|
cmp ecx, eax
|
||||||
|
jb @f
|
||||||
|
mov ecx, eax
|
||||||
|
@@:
|
||||||
|
add esi, [filedata]
|
||||||
|
add esi, [ebx+COFF_SECTION.PtrRawData]
|
||||||
|
mov edx, ecx
|
||||||
|
shr ecx, 2
|
||||||
|
and edx, 3
|
||||||
|
rep movsd
|
||||||
|
mov ecx, edx
|
||||||
|
rep movsb
|
||||||
|
jmp .section_data_done
|
||||||
|
.beginning_inside:
|
||||||
|
; Normal case: do not store zeroes which will be immediately overwritten.
|
||||||
|
xor edi, edi
|
||||||
|
cmp [cur_page], edi
|
||||||
|
jnz .copy_data
|
||||||
|
stdcall kernel_alloc, 0x1000
|
||||||
|
test eax, eax
|
||||||
|
jz .fail_free_pages
|
||||||
|
mov [cur_page], eax
|
||||||
|
mov edi, eax
|
||||||
|
mov ecx, [ebx+COFF_SECTION.SizeOfRawData]
|
||||||
|
sub ecx, esi
|
||||||
|
cmp ecx, 0x1000
|
||||||
|
jb @f
|
||||||
|
mov ecx, 0x1000
|
||||||
|
@@:
|
||||||
|
add esi, [filedata]
|
||||||
|
add esi, [ebx+COFF_SECTION.PtrRawData]
|
||||||
|
mov edx, ecx
|
||||||
|
shr ecx, 2
|
||||||
|
rep movsd
|
||||||
|
mov ecx, edx
|
||||||
|
and ecx, 3
|
||||||
|
rep movsb
|
||||||
|
mov ecx, 0x1000
|
||||||
|
sub ecx, edx
|
||||||
|
mov edx, ecx
|
||||||
|
shr ecx, 2
|
||||||
|
and edx, 3
|
||||||
|
xor eax, eax
|
||||||
|
rep stosd
|
||||||
|
mov ecx, edx
|
||||||
|
rep stosb
|
||||||
|
.section_data_done:
|
||||||
|
; 2o. Get size of the section header.
|
||||||
|
; Characteristics is the last dword in both
|
||||||
|
; COFF_SECTION and STRIPPED_PE_SECTION, so this helps to access it.
|
||||||
|
movi ecx, sizeof.STRIPPED_PE_SECTION
|
||||||
|
cmp [peheader], 0
|
||||||
|
jz @f
|
||||||
|
mov cl, sizeof.COFF_SECTION
|
||||||
|
@@:
|
||||||
|
; 2p. If the current page intersects virtual address range of the section,
|
||||||
|
; update access rights using section access rights.
|
||||||
|
cmp [ebx+COFF_SECTION.VirtualSize], 0
|
||||||
|
jz .section_access_done
|
||||||
|
mov esi, [page_offset]
|
||||||
|
sub esi, [ebx+COFF_SECTION.VirtualAddress]
|
||||||
|
cmp esi, [ebx+COFF_SECTION.VirtualSize]
|
||||||
|
jb @f
|
||||||
|
add esi, 0x1000
|
||||||
|
jnc .section_access_done
|
||||||
|
jz .section_access_done
|
||||||
|
@@:
|
||||||
|
mov eax, [ebx+ecx-4]
|
||||||
|
shr eax, 28
|
||||||
|
or [cur_access], al
|
||||||
|
.section_access_done:
|
||||||
|
; 2q. Advance to the next section, while there are sections left.
|
||||||
|
add ebx, ecx
|
||||||
|
dec [section_idx]
|
||||||
|
jnz .sections_loop
|
||||||
|
.no_sections:
|
||||||
|
; 2r. Shareable pages can not be lazy-allocated
|
||||||
|
; even if they only contain uninitialized data.
|
||||||
|
; If the page is shareable and has not been allocated yet, do it now.
|
||||||
|
test [cur_access], IMAGE_SCN_MEM_SHARED shr 28
|
||||||
|
jz @f
|
||||||
|
cmp [cur_page], 0
|
||||||
|
jnz @f
|
||||||
|
stdcall kernel_alloc, 0x1000
|
||||||
|
test eax, eax
|
||||||
|
jz .fail_free_pages
|
||||||
|
mov [cur_page], eax
|
||||||
|
mov edi, eax
|
||||||
|
xor eax, eax
|
||||||
|
mov ecx, 0x1000/4
|
||||||
|
rep stosd
|
||||||
|
@@:
|
||||||
|
; 2s. Get and store the item for page array: 0xFF for pages with zeroes,
|
||||||
|
; physical address of the page plus 1 for reference counter otherwise,
|
||||||
|
; with access rights in bits 8-11 in both cases.
|
||||||
|
mov edi, 0xFF
|
||||||
|
mov eax, [cur_page]
|
||||||
|
test eax, eax
|
||||||
|
jz @f
|
||||||
|
call get_pg_addr
|
||||||
|
lea edi, [eax+1]
|
||||||
|
stdcall free_kernel_space, [cur_page]
|
||||||
|
@@:
|
||||||
|
movzx eax, [cur_access]
|
||||||
|
shl eax, 8
|
||||||
|
or eax, edi
|
||||||
|
mov ecx, [page_index]
|
||||||
|
mov esi, [descr]
|
||||||
|
mov [esi+sizeof.PEDESCR+ecx*4], eax
|
||||||
|
.page_created:
|
||||||
|
; 2t. Transform the item from page array to page table entry:
|
||||||
|
; - drop reference counter,
|
||||||
|
; - map zero-only page to LAZY_ALLOC_PAGE
|
||||||
|
; with optional flags LAZY_ALLOC_{UNREADABLE,UNWRITABLE},
|
||||||
|
; PF handler will lazy-allocate it;
|
||||||
|
; - for pages with data,
|
||||||
|
; map readable and executable to user bit,
|
||||||
|
; for shareable pages map writable to writable bit,
|
||||||
|
; for non-shareable pages ignore writable to support copy-on-write.
|
||||||
|
mov edx, eax
|
||||||
|
and eax, not 0xFFF
|
||||||
|
jz .page_set_zero
|
||||||
|
inc [num_allocated_pages]
|
||||||
|
or eax, PG_READ+PG_SHARED
|
||||||
|
test dh, (IMAGE_SCN_MEM_READ+IMAGE_SCN_MEM_EXECUTE) shr 28
|
||||||
|
jz @f
|
||||||
|
or al, PG_USER
|
||||||
|
@@:
|
||||||
|
test dh, IMAGE_SCN_MEM_SHARED shr 28
|
||||||
|
jz @f
|
||||||
|
test dh, IMAGE_SCN_MEM_WRITE shr 28
|
||||||
|
jz @f
|
||||||
|
or al, PG_WRITE
|
||||||
|
@@:
|
||||||
|
jmp .pte_generated
|
||||||
|
.page_set_zero:
|
||||||
|
mov al, LAZY_ALLOC_PAGE
|
||||||
|
test dh, (IMAGE_SCN_MEM_READ+IMAGE_SCN_MEM_EXECUTE) shr 28
|
||||||
|
jnz @f
|
||||||
|
or al, LAZY_ALLOC_UNREADABLE
|
||||||
|
@@:
|
||||||
|
test dh, IMAGE_SCN_MEM_WRITE shr 28
|
||||||
|
jnz @f
|
||||||
|
or al, LAZY_ALLOC_UNWRITABLE
|
||||||
|
@@:
|
||||||
|
.pte_generated:
|
||||||
|
mov edi, [pages]
|
||||||
|
mov [edi+ecx*4], eax
|
||||||
|
; 2u. Advance to the next page, until PEDESCR.size is reached.
|
||||||
|
inc ecx
|
||||||
|
inc [page_index]
|
||||||
|
add [page_offset], 0x1000
|
||||||
|
cmp ecx, [esi+PEDESCR.size]
|
||||||
|
jb .fill_pages
|
||||||
|
; 2v. Release the lock.
|
||||||
|
lea ecx, [esi+PEDESCR.page_array_lock]
|
||||||
|
call mutex_unlock
|
||||||
|
; 3. Allocate a new SMAP.
|
||||||
|
movi eax, sizeof.SMAP
|
||||||
|
call malloc
|
||||||
|
test eax, eax
|
||||||
|
jz .fail_free_pages_unlocked
|
||||||
|
mov ebx, eax
|
||||||
|
; 4. Lock the address space so that a random PF from other thread
|
||||||
|
; between end of step 5 and beginning of step 7 would not trash anything.
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_lock
|
||||||
|
; 5. Allocate space in the address space.
|
||||||
|
; Prefer PEDESCR.defaultbase, but allow address anywhere else
|
||||||
|
; if allocation at PEDESCR.defaultbase is not possible.
|
||||||
|
mov edi, [esi+PEDESCR.size]
|
||||||
|
shl edi, 12
|
||||||
|
stdcall user_alloc_at_nolock, [esi+PEDESCR.defaultbase], edi
|
||||||
|
test eax, eax
|
||||||
|
jnz @f
|
||||||
|
stdcall user_alloc_nolock, edi
|
||||||
|
test eax, eax
|
||||||
|
jz .user_alloc_failed
|
||||||
|
@@:
|
||||||
|
mov [img_base], eax
|
||||||
|
; 6. Fill SMAP with values and insert it to the list of SMAPs.
|
||||||
|
mov [ebx+SMAP.type], SMAP_TYPE_PE
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.smap_list
|
||||||
|
mov edx, [ecx+SMAP.fd]
|
||||||
|
mov [ebx+SMAP.fd], edx
|
||||||
|
mov [ebx+SMAP.bk], ecx
|
||||||
|
mov [ecx+SMAP.fd], ebx
|
||||||
|
mov [edx+SMAP.bk], ebx
|
||||||
|
mov [ebx+SMAP.base], eax
|
||||||
|
mov [ebx+SMAP.size], edi
|
||||||
|
mov [ebx+SMAP.parent], esi
|
||||||
|
; 7. Copy page table entries prepared at step 2 to the page table.
|
||||||
|
mov edx, eax
|
||||||
|
shr edx, 12
|
||||||
|
mov ecx, [esi+PEDESCR.size]
|
||||||
|
mov esi, [pages]
|
||||||
|
lea edi, [page_tabs+edx*4]
|
||||||
|
rep movsd
|
||||||
|
mov eax, [num_allocated_pages]
|
||||||
|
shl eax, 12
|
||||||
|
; 8. Release the address space lock.
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add [ecx+PROC.mem_used], eax
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
|
; 9. Cleanup and return allocated address.
|
||||||
|
mov eax, [pages]
|
||||||
|
call free
|
||||||
|
cmp [filedata], 0
|
||||||
|
jz @f
|
||||||
|
stdcall kernel_free, [filedata]
|
||||||
|
@@:
|
||||||
|
mov eax, [img_base]
|
||||||
|
ret
|
||||||
|
.fail_and_free_data:
|
||||||
|
stdcall kernel_free, [filedata]
|
||||||
|
.fail:
|
||||||
|
mov eax, edi
|
||||||
|
ret
|
||||||
|
.user_alloc_failed:
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
|
mov eax, ebx
|
||||||
|
call free
|
||||||
|
.fail_free_pages_unlocked:
|
||||||
|
lea ecx, [esi+PEDESCR.page_array_lock]
|
||||||
|
call mutex_lock
|
||||||
|
.fail_free_pages:
|
||||||
|
mov ecx, [page_index]
|
||||||
|
test ecx, ecx
|
||||||
|
jz .fail_free_pages_array
|
||||||
|
mov eax, [esi+sizeof.PEDESCR+(ecx-1)*4]
|
||||||
|
mov edx, eax
|
||||||
|
and eax, not 0xFFF
|
||||||
|
jz .fail_free_next
|
||||||
|
and edx, 0xFF
|
||||||
|
cmp edx, 0xFF
|
||||||
|
jz .fail_free_next
|
||||||
|
dec dword [esi+sizeof.PEDESCR+(ecx-1)*4]
|
||||||
|
dec edx
|
||||||
|
jnz .fail_free_next
|
||||||
|
mov [esi+sizeof.PEDESCR+(ecx-1)*4], edx
|
||||||
|
call free_page
|
||||||
|
.fail_free_next:
|
||||||
|
dec [page_index]
|
||||||
|
jmp .fail_free_pages
|
||||||
|
.fail_free_pages_array:
|
||||||
|
lea ecx, [esi+PEDESCR.page_array_lock]
|
||||||
|
call mutex_unlock
|
||||||
|
mov eax, [pages]
|
||||||
|
call free
|
||||||
|
movi edi, -30
|
||||||
|
.fail_dereference:
|
||||||
|
cmp [filedata], 0
|
||||||
|
jz @f
|
||||||
|
stdcall kernel_free, [filedata]
|
||||||
|
@@:
|
||||||
|
call dereference_pe
|
||||||
|
mov eax, edi
|
||||||
|
ret
|
||||||
|
|
||||||
|
.validate_header:
|
||||||
|
mov [filedata], eax
|
||||||
|
cmp ebx, 40h
|
||||||
|
jb .validate_header.error
|
||||||
|
mov [peheader], 0
|
||||||
|
cmp word [eax], STRIPPED_PE_SIGNATURE
|
||||||
|
jz .validate_header.stripped
|
||||||
|
cmp word [eax], 'MZ'
|
||||||
|
jnz .validate_header.error
|
||||||
|
mov ecx, [eax+3Ch]
|
||||||
|
add eax, ecx
|
||||||
|
add ecx, IMAGE_NT_HEADERS.OptionalHeader
|
||||||
|
jc .validate_header.error
|
||||||
|
cmp ecx, ebx
|
||||||
|
ja .validate_header.error
|
||||||
|
cmp [eax+IMAGE_NT_HEADERS.Signature], 'PE'
|
||||||
|
jnz .validate_header.error
|
||||||
|
mov [peheader], eax
|
||||||
|
movzx edx, [eax+IMAGE_NT_HEADERS.FileHeader.SizeOfOptionalHeader]
|
||||||
|
cmp edx, IMAGE_OPTIONAL_HEADER32.DataDirectory
|
||||||
|
jb .validate_header.error
|
||||||
|
add ecx, edx
|
||||||
|
jc .validate_header.error
|
||||||
|
cmp ecx, ebx
|
||||||
|
ja .validate_header.error
|
||||||
|
lea edx, [eax+IMAGE_NT_HEADERS.OptionalHeader+edx]
|
||||||
|
mov [sections], edx
|
||||||
|
movzx edx, [eax+IMAGE_NT_HEADERS.FileHeader.NumberOfSections]
|
||||||
|
mov [num_sections], edx
|
||||||
|
imul edx, sizeof.COFF_SECTION
|
||||||
|
add ecx, edx
|
||||||
|
jc .validate_header.error
|
||||||
|
cmp ecx, ebx
|
||||||
|
ja .validate_header.error
|
||||||
|
mov edx, [eax+IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders]
|
||||||
|
mov [header_size], edx
|
||||||
|
cmp edx, ebx
|
||||||
|
ja .validate_header.error
|
||||||
|
mov edx, [num_sections]
|
||||||
|
mov ecx, [sections]
|
||||||
|
test edx, edx
|
||||||
|
jz .validate_header.sections_ok
|
||||||
|
@@:
|
||||||
|
mov eax, [ecx+COFF_SECTION.PtrRawData]
|
||||||
|
add eax, [ecx+COFF_SECTION.SizeOfRawData]
|
||||||
|
jc .validate_header.error
|
||||||
|
cmp eax, ebx
|
||||||
|
ja .validate_header.error
|
||||||
|
add ecx, sizeof.COFF_SECTION
|
||||||
|
dec edx
|
||||||
|
jnz @b
|
||||||
|
.validate_header.sections_ok:
|
||||||
|
.validate_header.ok:
|
||||||
|
clc
|
||||||
|
retn
|
||||||
|
.validate_header.stripped:
|
||||||
|
movzx ecx, [eax+STRIPPED_PE_HEADER.NumberOfRvaAndSizes]
|
||||||
|
lea ecx, [sizeof.STRIPPED_PE_HEADER+ecx*8]
|
||||||
|
movzx edx, [eax+STRIPPED_PE_HEADER.NumberOfSections]
|
||||||
|
mov [num_sections], edx
|
||||||
|
imul edx, sizeof.STRIPPED_PE_SECTION
|
||||||
|
add edx, ecx
|
||||||
|
cmp edx, ebx
|
||||||
|
ja .validate_header.error
|
||||||
|
mov edx, [eax+STRIPPED_PE_HEADER.SizeOfHeaders]
|
||||||
|
mov [header_size], edx
|
||||||
|
cmp edx, ebx
|
||||||
|
ja .validate_header.error
|
||||||
|
add ecx, eax
|
||||||
|
mov [sections], ecx
|
||||||
|
mov edx, [num_sections]
|
||||||
|
test edx, edx
|
||||||
|
jz .validate_header.stripped.sections_ok
|
||||||
|
@@:
|
||||||
|
mov eax, [ecx+STRIPPED_PE_SECTION.PtrRawData]
|
||||||
|
add eax, [ecx+STRIPPED_PE_SECTION.SizeOfRawData]
|
||||||
|
jc .validate_header.error
|
||||||
|
cmp eax, ebx
|
||||||
|
ja .validate_header.error
|
||||||
|
add ecx, sizeof.STRIPPED_PE_SECTION
|
||||||
|
dec edx
|
||||||
|
jnz @b
|
||||||
|
.validate_header.stripped.sections_ok:
|
||||||
|
clc
|
||||||
|
retn
|
||||||
|
.validate_header.error:
|
||||||
|
stc
|
||||||
|
retn
|
||||||
|
endp
|
||||||
|
|
||||||
|
; in: edi -> SMAP
|
||||||
|
; in: address space lock must be held
|
||||||
|
proc release_pemap stdcall uses ebx esi, process:dword
|
||||||
|
locals
|
||||||
|
num_released_pages dd 0
|
||||||
|
mapped_pagedir dd -1
|
||||||
|
endl
|
||||||
|
mov esi, [edi+SMAP.base]
|
||||||
|
mov ebx, [edi+SMAP.parent]
|
||||||
|
shr esi, 12
|
||||||
|
dec esi
|
||||||
|
add ebx, sizeof.PEDESCR
|
||||||
|
call .get_page_tab_entry
|
||||||
|
mov ecx, [eax]
|
||||||
|
and ecx, not MEM_BLOCK_DONT_FREE
|
||||||
|
mov [eax], ecx
|
||||||
|
shr ecx, 12
|
||||||
|
dec ecx
|
||||||
|
jz .released
|
||||||
|
.release:
|
||||||
|
inc esi
|
||||||
|
call .get_page_tab_entry
|
||||||
|
mov edx, [eax]
|
||||||
|
test dl, 1
|
||||||
|
jz .next
|
||||||
|
test edx, PG_SHARED
|
||||||
|
jz .next
|
||||||
|
mov dword [eax], 0
|
||||||
|
inc [num_released_pages]
|
||||||
|
xor edx, [ebx]
|
||||||
|
test edx, not 0xFFF
|
||||||
|
jnz .next
|
||||||
|
mov edx, [ebx]
|
||||||
|
mov eax, edx
|
||||||
|
and edx, 0xFF
|
||||||
|
cmp edx, 0xFF
|
||||||
|
jz .next
|
||||||
|
dec eax
|
||||||
|
test dword [ebx], IMAGE_SCN_MEM_SHARED shr 20
|
||||||
|
jnz @f
|
||||||
|
test eax, 0xFF
|
||||||
|
jnz @f
|
||||||
|
call free_page
|
||||||
|
xor eax, eax
|
||||||
|
@@:
|
||||||
|
mov [ebx], eax
|
||||||
|
.next:
|
||||||
|
add ebx, 4
|
||||||
|
dec ecx
|
||||||
|
jnz .release
|
||||||
|
mov eax, [num_released_pages]
|
||||||
|
shl eax, 12
|
||||||
|
mov edx, [process]
|
||||||
|
sub [edx+PROC.mem_used], eax
|
||||||
|
cmp [mapped_pagedir], -1
|
||||||
|
jz .released
|
||||||
|
stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP
|
||||||
|
.released:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.get_page_tab_entry:
|
||||||
|
mov eax, [process]
|
||||||
|
cmp eax, [current_process]
|
||||||
|
jnz @f
|
||||||
|
lea eax, [page_tabs+esi*4]
|
||||||
|
retn
|
||||||
|
@@:
|
||||||
|
push edx
|
||||||
|
mov edx, esi
|
||||||
|
shr edx, 10
|
||||||
|
cmp edx, [mapped_pagedir]
|
||||||
|
jz @f
|
||||||
|
mov [mapped_pagedir], edx
|
||||||
|
mov eax, [eax+PROC.pdt_0+edx*4]
|
||||||
|
and eax, not 0xFFF
|
||||||
|
stdcall map_page, [tmp_task_ptab], eax, PG_SWR
|
||||||
|
@@:
|
||||||
|
mov eax, [tmp_task_ptab]
|
||||||
|
mov edx, esi
|
||||||
|
and edx, 0x3FF
|
||||||
|
lea eax, [eax+edx*4]
|
||||||
|
pop edx
|
||||||
|
retn
|
||||||
|
endp
|
||||||
|
|
||||||
|
proc unmap_pe_usermode stdcall uses ebx esi edi, address:dword
|
||||||
|
mov ecx, [current_process]
|
||||||
|
lea edi, [ecx+PROC.smap_list]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_lock
|
||||||
|
mov esi, edi
|
||||||
|
mov eax, [address]
|
||||||
|
.scan:
|
||||||
|
mov edi, [edi+SMAP.fd]
|
||||||
|
cmp edi, esi
|
||||||
|
jz .notfound
|
||||||
|
cmp [edi+SMAP.base], eax
|
||||||
|
jnz .scan
|
||||||
|
mov eax, [edi+SMAP.fd]
|
||||||
|
mov edx, [edi+SMAP.bk]
|
||||||
|
mov [eax+SMAP.bk], edx
|
||||||
|
mov [edx+SMAP.fd], eax
|
||||||
|
call mutex_unlock
|
||||||
|
stdcall destroy_smap, [current_process]
|
||||||
|
xor eax, eax
|
||||||
|
ret
|
||||||
|
.notfound:
|
||||||
|
call mutex_unlock
|
||||||
|
or eax, -1
|
||||||
|
ret
|
||||||
|
endp
|
@ -307,7 +307,7 @@ show_error_parameters:
|
|||||||
; incorrect address in the program
|
; incorrect address in the program
|
||||||
|
|
||||||
mov eax, [page_tabs+ebx*4]
|
mov eax, [page_tabs+ebx*4]
|
||||||
test eax, 2
|
test eax, 1
|
||||||
jz .fail ; address not reserved for use. error
|
jz .fail ; address not reserved for use. error
|
||||||
|
|
||||||
pop ebx
|
pop ebx
|
||||||
|
@ -42,10 +42,30 @@ struct APP_HDR
|
|||||||
filename_size rd 1
|
filename_size rd 1
|
||||||
cmdline_size rd 1
|
cmdline_size rd 1
|
||||||
path_string rd 1
|
path_string rd 1
|
||||||
|
pedescr rd 1
|
||||||
ends
|
ends
|
||||||
|
|
||||||
|
; Pointer to this structure is passed as the third argument
|
||||||
|
; to usermode PE loader by the kernel.
|
||||||
|
struct kernel_init_data
|
||||||
|
version dw ?
|
||||||
|
flags dw ?
|
||||||
|
syscall_method dd ?
|
||||||
|
; either one of SYSCALL_METHOD_xxx or pointer to procedure
|
||||||
|
exe_base dd ?
|
||||||
|
stack_base dd ?
|
||||||
|
stack_size dd ?
|
||||||
|
exe_path dd ?
|
||||||
|
command_line dd ?
|
||||||
|
environment dd ?
|
||||||
|
ends
|
||||||
|
SYSCALL_METHOD_I40 = 1
|
||||||
|
SYSCALL_METHOD_SYSENTER = 2
|
||||||
|
SYSCALL_METHOD_SYSCALL = 3
|
||||||
|
|
||||||
macro _clear_ op
|
macro _clear_ op
|
||||||
{ mov ecx, op/4
|
{
|
||||||
|
mov ecx, op/4
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
cld
|
cld
|
||||||
rep stosd
|
rep stosd
|
||||||
@ -98,30 +118,41 @@ proc fs_execute
|
|||||||
filename_size rd 1
|
filename_size rd 1
|
||||||
cmdline_size rd 1
|
cmdline_size rd 1
|
||||||
path_string rd 1
|
path_string rd 1
|
||||||
|
pedescr rd 1
|
||||||
endl
|
endl
|
||||||
|
|
||||||
mov [flags], edx
|
mov [flags], edx
|
||||||
mov [cmdline], ecx
|
mov [cmdline], ecx
|
||||||
mov [path_string], ebx
|
mov [path_string], ebx
|
||||||
mov [filename_size], eax
|
mov [filename_size], eax
|
||||||
mov esi, -ERROR_FILE_NOT_FOUND
|
mov edi, -ERROR_FILE_NOT_FOUND
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .err_file
|
jz .err_file
|
||||||
stdcall load_file, ebx
|
stdcall load_file, ebx
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .err_file
|
jz .err_file
|
||||||
|
stdcall load_file_maybe_pe, [path_string]
|
||||||
|
mov [pedescr], esi
|
||||||
mov [file_base], eax
|
mov [file_base], eax
|
||||||
mov [file_size], ebx
|
mov [file_size], ebx
|
||||||
|
|
||||||
|
test esi, esi
|
||||||
|
jnz .file_ok
|
||||||
|
|
||||||
|
mov edi, eax
|
||||||
|
cmp eax, -0x1000
|
||||||
|
ja .err_file
|
||||||
|
|
||||||
lea ebx, [hdr_cmdline]
|
lea ebx, [hdr_cmdline]
|
||||||
call test_app_header ; fill our app header data locals with values from header of given program (if its correct)
|
call test_app_header ; fill our app header data locals with values from header of given program (if its correct)
|
||||||
mov esi, -TASKMAN_ERROR_NOT_A_EXECUTABLE
|
mov edi, -TASKMAN_ERROR_NOT_A_EXECUTABLE
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .err_hdr
|
jz .err_hdr
|
||||||
|
|
||||||
|
.file_ok:
|
||||||
call lock_application_table
|
call lock_application_table
|
||||||
call alloc_thread_slot ; create a slot for new thread
|
call alloc_thread_slot ; create a slot for new thread
|
||||||
mov esi, -TASKMAN_ERROR_TOO_MANY_PROCESSES
|
mov edi, -TASKMAN_ERROR_TOO_MANY_PROCESSES
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .err_0
|
jz .err_0
|
||||||
|
|
||||||
@ -162,8 +193,15 @@ proc fs_execute
|
|||||||
add [hdr_emem], ebx
|
add [hdr_emem], ebx
|
||||||
@@:
|
@@:
|
||||||
mov [cmdline_size], eax
|
mov [cmdline_size], eax
|
||||||
|
xor eax, eax
|
||||||
|
cmp [pedescr], eax
|
||||||
|
jz @f
|
||||||
|
mov [hdr_eip], eax
|
||||||
|
mov [hdr_esp], eax
|
||||||
|
mov [hdr_emem], eax
|
||||||
|
@@:
|
||||||
stdcall create_process, [hdr_emem] ; create a new process
|
stdcall create_process, [hdr_emem] ; create a new process
|
||||||
mov esi, -TASKMAN_ERROR_OUT_OF_MEMORY
|
mov edi, -TASKMAN_ERROR_OUT_OF_MEMORY
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .err_hdr
|
jz .err_hdr
|
||||||
|
|
||||||
@ -203,12 +241,17 @@ proc fs_execute
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
.err_0:
|
.err_0:
|
||||||
|
mov esi, [pedescr]
|
||||||
|
test esi, esi
|
||||||
|
jz @f
|
||||||
|
call dereference_pe
|
||||||
|
@@:
|
||||||
call unlock_application_table
|
call unlock_application_table
|
||||||
.err_hdr:
|
.err_hdr:
|
||||||
stdcall kernel_free, [file_base]
|
stdcall kernel_free, [file_base]
|
||||||
.err_file:
|
.err_file:
|
||||||
stdcall kernel_free, [path_string]
|
stdcall kernel_free, [path_string]
|
||||||
mov eax, esi
|
mov eax, edi
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
@ -330,13 +373,18 @@ proc create_process stdcall, app_size:dword
|
|||||||
jz .fail
|
jz .fail
|
||||||
mov [process], eax
|
mov [process], eax
|
||||||
|
|
||||||
lea edi, [eax+PROC.heap_lock]
|
lea edi, [eax+PROC.heap_base]
|
||||||
mov ecx, (PROC.ht_free-PROC.heap_lock)/4
|
|
||||||
|
|
||||||
list_init eax
|
list_init eax
|
||||||
add eax, PROC.thr_list
|
add eax, PROC.thr_list
|
||||||
list_init eax
|
list_init eax
|
||||||
|
add eax, PROC.smap_list - PROC.thr_list
|
||||||
|
list_init eax
|
||||||
|
|
||||||
|
lea ecx, [eax+PROC.heap_lock-PROC.smap_list]
|
||||||
|
call mutex_init
|
||||||
|
|
||||||
|
mov ecx, (PROC.ht_free-PROC.heap_base)/4
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
cld
|
cld
|
||||||
rep stosd
|
rep stosd
|
||||||
@ -370,6 +418,8 @@ proc create_process stdcall, app_size:dword
|
|||||||
|
|
||||||
lea edx, [edi-4096]
|
lea edx, [edi-4096]
|
||||||
mov esi, [app_tabs]
|
mov esi, [app_tabs]
|
||||||
|
test esi, esi
|
||||||
|
jz .no_page_dirs
|
||||||
|
|
||||||
.alloc_page_dir:
|
.alloc_page_dir:
|
||||||
call alloc_page
|
call alloc_page
|
||||||
@ -388,6 +438,7 @@ proc create_process stdcall, app_size:dword
|
|||||||
dec esi
|
dec esi
|
||||||
jnz .alloc_page_dir
|
jnz .alloc_page_dir
|
||||||
|
|
||||||
|
.no_page_dirs:
|
||||||
stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP
|
stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP
|
||||||
mov eax, [process]
|
mov eax, [process]
|
||||||
|
|
||||||
@ -397,7 +448,7 @@ proc create_process stdcall, app_size:dword
|
|||||||
ret
|
ret
|
||||||
.fail:
|
.fail:
|
||||||
mov ecx, [process]
|
mov ecx, [process]
|
||||||
jcxz @F
|
jecxz @F
|
||||||
|
|
||||||
call destroy_process
|
call destroy_process
|
||||||
@@:
|
@@:
|
||||||
@ -419,8 +470,6 @@ proc destroy_page_table stdcall, pg_tab:dword
|
|||||||
mov eax, [esi]
|
mov eax, [esi]
|
||||||
test eax, 1
|
test eax, 1
|
||||||
jz .next
|
jz .next
|
||||||
test eax, 2
|
|
||||||
jz .next
|
|
||||||
test eax, 1 shl 9
|
test eax, 1 shl 9
|
||||||
jnz .next ;skip shared pages
|
jnz .next ;skip shared pages
|
||||||
call free_page
|
call free_page
|
||||||
@ -446,8 +495,16 @@ align 4
|
|||||||
mov esi, ecx
|
mov esi, ecx
|
||||||
list_del esi
|
list_del esi
|
||||||
|
|
||||||
mov esi, [esi+PROC.dlls_list_ptr]
|
lea ebx, [esi+PROC.smap_list]
|
||||||
call destroy_all_hdlls
|
mov edi, [esi+PROC.smap_list+SMAP.fd]
|
||||||
|
.smap_list_destroy:
|
||||||
|
cmp edi, ebx
|
||||||
|
jz .smap_list_done
|
||||||
|
push [edi+SMAP.fd]
|
||||||
|
stdcall destroy_smap, [esp+4]
|
||||||
|
pop edi
|
||||||
|
jmp .smap_list_destroy
|
||||||
|
.smap_list_done:
|
||||||
|
|
||||||
mov esi, [esp]
|
mov esi, [esp]
|
||||||
add esi, PROC.pdt_0
|
add esi, PROC.pdt_0
|
||||||
@ -532,6 +589,7 @@ proc read_process_memory
|
|||||||
r_count dd ?
|
r_count dd ?
|
||||||
offset dd ?
|
offset dd ?
|
||||||
tmp_r_cnt dd ?
|
tmp_r_cnt dd ?
|
||||||
|
mapped_size dd ?
|
||||||
endl
|
endl
|
||||||
|
|
||||||
mov [slot], eax
|
mov [slot], eax
|
||||||
@ -541,6 +599,8 @@ proc read_process_memory
|
|||||||
mov [offset], esi
|
mov [offset], esi
|
||||||
|
|
||||||
pushad
|
pushad
|
||||||
|
mov ecx, proc_mem_mutex
|
||||||
|
call mutex_lock
|
||||||
.read_mem:
|
.read_mem:
|
||||||
mov edx, [offset]
|
mov edx, [offset]
|
||||||
mov ebx, [tmp_r_cnt]
|
mov ebx, [tmp_r_cnt]
|
||||||
@ -560,13 +620,14 @@ proc read_process_memory
|
|||||||
|
|
||||||
push ecx
|
push ecx
|
||||||
stdcall map_memEx, [proc_mem_map], \
|
stdcall map_memEx, [proc_mem_map], \
|
||||||
[slot], ebx, ecx, PG_READ
|
[slot], ebx, ecx, PG_READ, [proc_mem_tab]
|
||||||
|
mov [mapped_size], eax
|
||||||
pop ecx
|
pop ecx
|
||||||
|
|
||||||
mov esi, [offset]
|
mov esi, [offset]
|
||||||
and esi, 0xfff
|
and esi, 0xfff
|
||||||
sub eax, esi
|
sub eax, esi
|
||||||
jbe .ret
|
jbe .ret_unmap
|
||||||
cmp ecx, eax
|
cmp ecx, eax
|
||||||
jbe @f
|
jbe @f
|
||||||
mov ecx, eax
|
mov ecx, eax
|
||||||
@ -574,17 +635,26 @@ proc read_process_memory
|
|||||||
@@:
|
@@:
|
||||||
add esi, [proc_mem_map]
|
add esi, [proc_mem_map]
|
||||||
mov edi, [buff]
|
mov edi, [buff]
|
||||||
mov edx, ecx
|
push ecx
|
||||||
rep movsb
|
rep movsb
|
||||||
add [r_count], edx
|
stdcall unmap_memEx, [proc_mem_map], \
|
||||||
|
[slot], ebx, [mapped_size], [proc_mem_tab]
|
||||||
|
pop ecx
|
||||||
|
add [r_count], ecx
|
||||||
|
|
||||||
add [offset], edx
|
add [offset], ecx
|
||||||
sub [tmp_r_cnt], edx
|
sub [tmp_r_cnt], ecx
|
||||||
jnz .read_mem
|
jnz .read_mem
|
||||||
.ret:
|
.ret:
|
||||||
|
mov ecx, proc_mem_mutex
|
||||||
|
call mutex_unlock
|
||||||
popad
|
popad
|
||||||
mov eax, [r_count]
|
mov eax, [r_count]
|
||||||
ret
|
ret
|
||||||
|
.ret_unmap:
|
||||||
|
stdcall unmap_memEx, [proc_mem_map], \
|
||||||
|
[slot], ebx, [mapped_size], [proc_mem_tab]
|
||||||
|
jmp .ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
@ -603,6 +673,7 @@ proc write_process_memory
|
|||||||
w_count dd ?
|
w_count dd ?
|
||||||
offset dd ?
|
offset dd ?
|
||||||
tmp_w_cnt dd ?
|
tmp_w_cnt dd ?
|
||||||
|
mapped_size dd ?
|
||||||
endl
|
endl
|
||||||
|
|
||||||
mov [slot], eax
|
mov [slot], eax
|
||||||
@ -612,7 +683,9 @@ proc write_process_memory
|
|||||||
mov [offset], esi
|
mov [offset], esi
|
||||||
|
|
||||||
pushad
|
pushad
|
||||||
.read_mem:
|
mov ecx, proc_mem_mutex
|
||||||
|
call mutex_lock
|
||||||
|
.write_mem:
|
||||||
mov edx, [offset]
|
mov edx, [offset]
|
||||||
mov ebx, [tmp_w_cnt]
|
mov ebx, [tmp_w_cnt]
|
||||||
|
|
||||||
@ -630,13 +703,14 @@ proc write_process_memory
|
|||||||
mov ebx, [offset]
|
mov ebx, [offset]
|
||||||
push ecx
|
push ecx
|
||||||
stdcall map_memEx, [proc_mem_map], \
|
stdcall map_memEx, [proc_mem_map], \
|
||||||
[slot], ebx, ecx, PG_SWR
|
[slot], ebx, ecx, PG_SWR, [proc_mem_tab]
|
||||||
|
mov [mapped_size], eax
|
||||||
pop ecx
|
pop ecx
|
||||||
|
|
||||||
mov edi, [offset]
|
mov edi, [offset]
|
||||||
and edi, 0xfff
|
and edi, 0xfff
|
||||||
sub eax, edi
|
sub eax, edi
|
||||||
jbe .ret
|
jbe .ret_unmap
|
||||||
cmp ecx, eax
|
cmp ecx, eax
|
||||||
jbe @f
|
jbe @f
|
||||||
mov ecx, eax
|
mov ecx, eax
|
||||||
@ -644,17 +718,25 @@ proc write_process_memory
|
|||||||
@@:
|
@@:
|
||||||
add edi, [proc_mem_map]
|
add edi, [proc_mem_map]
|
||||||
mov esi, [buff]
|
mov esi, [buff]
|
||||||
mov edx, ecx
|
push ecx
|
||||||
rep movsb
|
rep movsb
|
||||||
|
stdcall unmap_memEx, [proc_mem_map], \
|
||||||
|
[slot], ebx, [mapped_size], [proc_mem_tab]
|
||||||
|
pop ecx
|
||||||
|
|
||||||
add [w_count], edx
|
add [w_count], ecx
|
||||||
add [offset], edx
|
add [offset], ecx
|
||||||
sub [tmp_w_cnt], edx
|
sub [tmp_w_cnt], ecx
|
||||||
jnz .read_mem
|
jnz .write_mem
|
||||||
.ret:
|
.ret:
|
||||||
|
mov ecx, proc_mem_mutex
|
||||||
|
call mutex_unlock
|
||||||
popad
|
popad
|
||||||
mov eax, [w_count]
|
mov eax, [w_count]
|
||||||
ret
|
ret
|
||||||
|
.ret_unmap:
|
||||||
|
stdcall unmap_memEx, [proc_mem_map], [slot], ebx, [mapped_size], [proc_mem_tab]
|
||||||
|
jmp .ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
;ebx = 1 - kernel thread
|
;ebx = 1 - kernel thread
|
||||||
@ -799,6 +881,76 @@ common_app_entry:
|
|||||||
jz .exit
|
jz .exit
|
||||||
; APPDATA.exec_params have first thread only,
|
; APPDATA.exec_params have first thread only,
|
||||||
; so second and next threads don't get here (they jump to .exit)
|
; so second and next threads don't get here (they jump to .exit)
|
||||||
|
cmp [ebp+APP_HDR.pedescr], 0
|
||||||
|
jz .init_legacy_app
|
||||||
|
; init PE application
|
||||||
|
mov eax, [current_process]
|
||||||
|
mov [eax+PROC.mem_used], 0xF000 ; leave first 64K as unallocatable
|
||||||
|
call init_heap
|
||||||
|
mov eax, [current_process]
|
||||||
|
mov [eax+PROC.mem_used], 0
|
||||||
|
stdcall map_pe_usermode, [ebp+APP_HDR.pedescr],\
|
||||||
|
[ebp+APP_HDR.img_base], [ebp+APP_HDR.img_size]
|
||||||
|
cmp eax, -0x1000
|
||||||
|
ja .failed
|
||||||
|
push eax
|
||||||
|
stdcall load_file_maybe_pe, pe_loader_usermode
|
||||||
|
test esi, esi
|
||||||
|
jz .pe_loader_notfound
|
||||||
|
mov edx, [esi+PEDESCR.entry]
|
||||||
|
mov [esp+4+20h], edx
|
||||||
|
stdcall map_pe_usermode, esi, eax, ebx
|
||||||
|
cmp eax, -0x1000
|
||||||
|
ja .pe_loader_failed
|
||||||
|
add [esp+4+20h], eax
|
||||||
|
push eax
|
||||||
|
mov eax, [ebp+APP_HDR.filename_size]
|
||||||
|
add eax, [ebp+APP_HDR.cmdline_size]
|
||||||
|
add eax, sizeof.kernel_init_data + 2
|
||||||
|
stdcall user_alloc, eax
|
||||||
|
test eax, eax
|
||||||
|
jz .failed
|
||||||
|
mov ebx, eax
|
||||||
|
mov dword [eax+kernel_init_data.version], 1 + (0 shl 16) ; version, flags
|
||||||
|
mov [eax+kernel_init_data.syscall_method], SYSCALL_METHOD_I40
|
||||||
|
lea edi, [eax+sizeof.kernel_init_data]
|
||||||
|
mov [eax+kernel_init_data.exe_path], edi
|
||||||
|
mov esi, [ebp+APP_HDR.path_string]
|
||||||
|
mov ecx, [ebp+APP_HDR.filename_size]
|
||||||
|
rep movsb
|
||||||
|
mov byte [edi], 0
|
||||||
|
inc edi
|
||||||
|
mov [eax+kernel_init_data.command_line], edi
|
||||||
|
lea esi, [ebp+sizeof.APP_HDR]
|
||||||
|
mov ecx, [ebp+APP_HDR.cmdline_size]
|
||||||
|
rep movsb
|
||||||
|
mov byte [edi], 0
|
||||||
|
mov ecx, [ebp+APP_HDR.pedescr]
|
||||||
|
mov ecx, [ecx+PEDESCR.stacksize]
|
||||||
|
mov [eax+kernel_init_data.stack_size], ecx
|
||||||
|
stdcall user_alloc, ecx
|
||||||
|
test eax, eax
|
||||||
|
jz .failed
|
||||||
|
mov [ebx+kernel_init_data.stack_base], eax
|
||||||
|
add eax, [ebx+kernel_init_data.stack_size]
|
||||||
|
sub eax, 16
|
||||||
|
pop dword [eax+4]
|
||||||
|
pop [ebx+kernel_init_data.exe_base]
|
||||||
|
mov dword [eax+8], 1 ; DLL_PROCESS_ATTACH
|
||||||
|
mov dword [eax+12], ebx
|
||||||
|
mov [esp+2Ch], eax
|
||||||
|
jmp .common_tls
|
||||||
|
.pe_loader_notfound:
|
||||||
|
cmp eax, -0x1000
|
||||||
|
ja .pe_loader_failed
|
||||||
|
stdcall kernel_free, eax
|
||||||
|
.pe_loader_failed:
|
||||||
|
dbgstr 'Failed to load kolibri.dll'
|
||||||
|
.failed:
|
||||||
|
stdcall kernel_free, [ebp+APP_HDR.path_string]
|
||||||
|
jmp sys_end
|
||||||
|
.init_legacy_app:
|
||||||
|
; init MENUETxx application
|
||||||
stdcall map_process_image, [ebp+APP_HDR._emem],\
|
stdcall map_process_image, [ebp+APP_HDR._emem],\
|
||||||
[ebp+APP_HDR.img_base], [ebp+APP_HDR.img_size]
|
[ebp+APP_HDR.img_base], [ebp+APP_HDR.img_size]
|
||||||
mov esi, [ebp+APP_HDR.path_string]
|
mov esi, [ebp+APP_HDR.path_string]
|
||||||
@ -846,8 +998,9 @@ common_app_entry:
|
|||||||
mov byte [edi], 0
|
mov byte [edi], 0
|
||||||
.check_tls_header:
|
.check_tls_header:
|
||||||
cmp word [6], '02'
|
cmp word [6], '02'
|
||||||
jne .try_load_dll ;.cleanup
|
jne .try_load_dll ;.common
|
||||||
call init_heap
|
call init_heap
|
||||||
|
.common_tls:
|
||||||
stdcall user_alloc, 4096
|
stdcall user_alloc, 4096
|
||||||
mov edx, [current_slot]
|
mov edx, [current_slot]
|
||||||
mov [edx+APPDATA.tls_base], eax
|
mov [edx+APPDATA.tls_base], eax
|
||||||
@ -862,7 +1015,7 @@ common_app_entry:
|
|||||||
; Test app header version
|
; Test app header version
|
||||||
mov ecx, dword[ebp+APP_HDR.img_base]
|
mov ecx, dword[ebp+APP_HDR.img_base]
|
||||||
cmp dword[ecx+8], 2
|
cmp dword[ecx+8], 2
|
||||||
jne .cleanup
|
jne .common
|
||||||
;if APP_HEADER.version = 2 => load lib/dll.obj & change eip to APP_STARTUP_THUNK
|
;if APP_HEADER.version = 2 => load lib/dll.obj & change eip to APP_STARTUP_THUNK
|
||||||
DEBUGF 1, 'K : App header version 2\n'
|
DEBUGF 1, 'K : App header version 2\n'
|
||||||
stdcall load_library, dll_lib_path, 0
|
stdcall load_library, dll_lib_path, 0
|
||||||
@ -877,19 +1030,21 @@ common_app_entry:
|
|||||||
call fs_execute_from_sysdir_param
|
call fs_execute_from_sysdir_param
|
||||||
; Terminate process (TODO: Need jump to .cleanup after sys_end ?)
|
; Terminate process (TODO: Need jump to .cleanup after sys_end ?)
|
||||||
call sys_end
|
call sys_end
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
; Find APP_STARTUP_THUNK in DLL.OBJ
|
; Find APP_STARTUP_THUNK in DLL.OBJ
|
||||||
sub eax, 4
|
sub eax, 4
|
||||||
mov eax, [eax]
|
mov eax, [eax]
|
||||||
|
|
||||||
;.change_eip:
|
;.change_eip:
|
||||||
mov ecx, [current_slot]
|
mov ecx, [current_slot]
|
||||||
mov ecx, [ecx+APPDATA.pl0_stack]
|
mov ecx, [ecx+APPDATA.pl0_stack]
|
||||||
mov [ecx+REG_EIP], eax
|
mov [ecx+REG_EIP], eax
|
||||||
|
|
||||||
; } End patch by Coldy, For DLL autoload
|
; } End patch by Coldy, For DLL autoload
|
||||||
.cleanup:
|
mov fs, dx
|
||||||
|
|
||||||
|
.common:
|
||||||
stdcall free_kernel_space, [ebp+APP_HDR.img_base]
|
stdcall free_kernel_space, [ebp+APP_HDR.img_base]
|
||||||
stdcall kernel_free, ebp
|
stdcall kernel_free, ebp
|
||||||
mov ebx, [current_slot]
|
mov ebx, [current_slot]
|
||||||
|
@ -181,23 +181,25 @@ dev_data_path db '/RD/1/DRIVERS/DEVICES.DAT',0
|
|||||||
dll_lib_path db '/RD/1/LIB/DLL.OBJ',0
|
dll_lib_path db '/RD/1/LIB/DLL.OBJ',0
|
||||||
dll_error_msg db '"DLL.OBJ not found!\nTerminate application!" -dE',0
|
dll_error_msg db '"DLL.OBJ not found!\nTerminate application!" -dE',0
|
||||||
; } End patch by Coldy, For DLL autoload
|
; } End patch by Coldy, For DLL autoload
|
||||||
|
pe_loader_usermode db '/rd/1/lib/kolibri.dll',0
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
|
|
||||||
shmem_list:
|
shmem_list:
|
||||||
.bk dd shmem_list
|
.bk dd shmem_list
|
||||||
.fd dd shmem_list
|
.fd dd shmem_list
|
||||||
|
|
||||||
dll_list:
|
pe_list:
|
||||||
.bk dd dll_list
|
.bk dd pe_list
|
||||||
.fd dd dll_list
|
.fd dd pe_list
|
||||||
|
|
||||||
pcidev_list:
|
pcidev_list:
|
||||||
.bk dd pcidev_list
|
.bk dd pcidev_list
|
||||||
.fd dd pcidev_list
|
.fd dd pcidev_list
|
||||||
|
|
||||||
MAX_DEFAULT_DLL_ADDR = 0x80000000
|
shared_locked_list:
|
||||||
MIN_DEFAULT_DLL_ADDR = 0x70000000
|
dd shared_locked_list
|
||||||
dll_cur_addr dd MIN_DEFAULT_DLL_ADDR
|
dd shared_locked_list
|
||||||
|
|
||||||
; supported videomodes
|
; supported videomodes
|
||||||
|
|
||||||
@ -399,6 +401,12 @@ os_stack_seg dd ?
|
|||||||
srv.fd dd ?
|
srv.fd dd ?
|
||||||
srv.bk dd ?
|
srv.bk dd ?
|
||||||
|
|
||||||
|
shmem_list_mutex MUTEX
|
||||||
|
pe_list_mutex MUTEX
|
||||||
|
shared_locked_mutex MUTEX
|
||||||
|
proc_mem_mutex MUTEX
|
||||||
|
ipc_mutex MUTEX
|
||||||
|
|
||||||
LFBAddress dd ?
|
LFBAddress dd ?
|
||||||
|
|
||||||
PUTPIXEL dd ?
|
PUTPIXEL dd ?
|
||||||
@ -432,6 +440,7 @@ proc_mem_pdir dd ?
|
|||||||
proc_mem_tab dd ?
|
proc_mem_tab dd ?
|
||||||
|
|
||||||
tmp_task_ptab dd ?
|
tmp_task_ptab dd ?
|
||||||
|
zero_page_tab dd ?
|
||||||
|
|
||||||
default_io_map dd ?
|
default_io_map dd ?
|
||||||
|
|
||||||
|
@ -3660,6 +3660,67 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
|||||||
* edx = размер загруженного файла или 0
|
* edx = размер загруженного файла или 0
|
||||||
Примечания:
|
Примечания:
|
||||||
* функция загружает и, при необходимости, распаковывает файл (kunpack)
|
* функция загружает и, при необходимости, распаковывает файл (kunpack)
|
||||||
|
======================================================================
|
||||||
|
=========== Функция 68, подфункция 29 - загрузить PE-файл ============
|
||||||
|
======================================================================
|
||||||
|
Параметры:
|
||||||
|
* eax = 68 - номер функции
|
||||||
|
* ebx = 29 - номер подфункции
|
||||||
|
* ecx = указатель на строку с путём к файлу,
|
||||||
|
правила формирования строки указаны в описании функции 70.
|
||||||
|
Возвращаемое значение:
|
||||||
|
* eax > 0xFFFFF000 - произошла ошибка, -eax = код ошибки
|
||||||
|
* eax <= 0xFFFFF000 - адрес загруженного файла
|
||||||
|
Примечания:
|
||||||
|
* функция предназначена только для системного загрузчика внутри
|
||||||
|
kolibri.dll; загруженный файл ещё не готов к работе, ему требуется
|
||||||
|
донастройка. Вместо неё используйте
|
||||||
|
функцию dlopen() из kolibri.dll.
|
||||||
|
======================================================================
|
||||||
|
=========== Функция 68, подфункция 30 - выгрузить PE-файл ============
|
||||||
|
======================================================================
|
||||||
|
Параметры:
|
||||||
|
* eax = 68 - номер функции
|
||||||
|
* ebx = 30 - номер подфункции
|
||||||
|
* ecx = адрес загруженного PE-файла
|
||||||
|
Возвращаемое значение:
|
||||||
|
* eax = 0 - успешно
|
||||||
|
* eax = -1 - адрес не соответствует никакому загруженному файлу
|
||||||
|
Примечания:
|
||||||
|
* функция предназначена только для системного загрузчика внутри
|
||||||
|
kolibri.dll. Вместо неё используйте функцию dlclose()
|
||||||
|
из kolibri.dll.
|
||||||
|
======================================================================
|
||||||
|
==== Функция 68, подфункция 31 - изменить права доступа к памяти =====
|
||||||
|
======================================================================
|
||||||
|
Параметры:
|
||||||
|
* eax = 68 - номер функции
|
||||||
|
* ebx = 31 - номер подфункции
|
||||||
|
* ecx = новые права доступа: ноль или более из следующих бит:
|
||||||
|
* PROT_READ = 1 - разрешить чтение
|
||||||
|
* PROT_WRITE = 2 - разрешить запись
|
||||||
|
* PROT_EXEC = 4 - разрешить исполнение
|
||||||
|
* edx = начальный адрес участка памяти
|
||||||
|
* esi = размер участка памяти в байтах
|
||||||
|
Возвращаемое значение:
|
||||||
|
* eax = -1 - ошибка
|
||||||
|
* иначе eax = старые права доступа
|
||||||
|
Примечания:
|
||||||
|
* Функция изменяет права целым страницам (4096 байт). Функция
|
||||||
|
меняет права доступа у всех страниц, пересекающихся с запрошенным
|
||||||
|
участком.
|
||||||
|
* Функция считает ошибкой передачу участка памяти от функции 68.22.
|
||||||
|
* Если часть переданного участка памяти корректна, а часть - нет,
|
||||||
|
то функция возвращает ошибку, но не гарантируется, изменились ли
|
||||||
|
права доступа у корректной части.
|
||||||
|
* Если не было ошибки, то функция возвращает старые права доступа
|
||||||
|
у первой из запрошенных страниц.
|
||||||
|
* Текущая реализация не поддерживает разрешения исполнения отдельно
|
||||||
|
от чтения. Поэтому бит PROT_EXEC игнорируется на входе и копирует
|
||||||
|
разрешение на чтение на выходе.
|
||||||
|
---------------------- Константы для регистров: ----------------------
|
||||||
|
eax - SF_SYS_MISC (68)
|
||||||
|
ebx - SSF_MPROTECT (31)
|
||||||
|
|
||||||
======================================================================
|
======================================================================
|
||||||
======================== Функция 69 - отладка. =======================
|
======================== Функция 69 - отладка. =======================
|
||||||
|
@ -3645,6 +3645,68 @@ Remarks:
|
|||||||
---------------------- Constants for registers: ----------------------
|
---------------------- Constants for registers: ----------------------
|
||||||
eax - SF_SYS_MISC (68)
|
eax - SF_SYS_MISC (68)
|
||||||
ebx - SSF_MEM_ALLOC_RING (29)
|
ebx - SSF_MEM_ALLOC_RING (29)
|
||||||
|
======================================================================
|
||||||
|
============ Function 68, subfunction 30 - load PE-file ==============
|
||||||
|
======================================================================
|
||||||
|
Parameters:
|
||||||
|
* eax = 68 - function number
|
||||||
|
* ebx = 30 - subfunction number
|
||||||
|
* ecx = pointer to the string with path to file,
|
||||||
|
rules of path forming can be found in function 70 description.
|
||||||
|
Returned value:
|
||||||
|
* eax > 0xFFFFF000 - error, -eax = error code
|
||||||
|
* eax <= 0xFFFFF000 - pointer to the loaded file
|
||||||
|
Remarks:
|
||||||
|
* This function is to be called only by system loader from
|
||||||
|
kolibri.dll; the file loaded is not ready yet, it requires further
|
||||||
|
configuration. Use dlopen() from kolibri.dll instead of this
|
||||||
|
function.
|
||||||
|
======================================================================
|
||||||
|
=========== Function 68, subfunction 31 - unload PE-file =============
|
||||||
|
======================================================================
|
||||||
|
Parameters:
|
||||||
|
* eax = 68 - function number
|
||||||
|
* ebx = 31 - subfunction number
|
||||||
|
* ecx = pointer to the loaded file
|
||||||
|
Returned value:
|
||||||
|
* eax = 0 - success
|
||||||
|
* eax = -1 - provided address does not correspond to any loaded file
|
||||||
|
Remarks:
|
||||||
|
* This function is to be called only by system loader from
|
||||||
|
kolibri.dll. Use dlclose() from kolibri.dll instead of this
|
||||||
|
function.
|
||||||
|
======================================================================
|
||||||
|
===== Function 68, subfunction 32 - modify memory access rights ======
|
||||||
|
======================================================================
|
||||||
|
Parameters:
|
||||||
|
* eax = 68 - function number
|
||||||
|
* ebx = 32 - subfunction number
|
||||||
|
* ecx = new access rights: zero or more of the following bits:
|
||||||
|
* PROT_READ = 1 - allow reading
|
||||||
|
* PROT_WRITE = 2 - allow writing
|
||||||
|
* PROT_EXEC = 4 - allow execution
|
||||||
|
* edx = pointer to begin of memory region
|
||||||
|
* esi = size of memory region in bytes
|
||||||
|
Returned value:
|
||||||
|
* eax = -1 - error
|
||||||
|
* else eax = old access rights
|
||||||
|
Remarks:
|
||||||
|
* The function modifies access rights to whole pages (4096 bytes).
|
||||||
|
* The function modifies access rights to all the pages intersecting
|
||||||
|
provided memory region.
|
||||||
|
* It is considered an error if a memory region returned by function
|
||||||
|
68.22 is passed to this function.
|
||||||
|
* If any part of the passed memory region is incorrect, then the
|
||||||
|
function returns an error. However it is not guaranteed that
|
||||||
|
access rights of the correct part have been changed.
|
||||||
|
* If there was no error, the function returns old access rights of
|
||||||
|
the first provided page.
|
||||||
|
* Current implementation does not support execution access rights
|
||||||
|
without reading rights. Therefore bit PROT_EXEC is ignored on
|
||||||
|
entering the function, and becomes a copy of PROT_READ at exit.
|
||||||
|
---------------------- Constants for registers: ----------------------
|
||||||
|
eax - SF_SYS_MISC (68)
|
||||||
|
ebx - SSF_MPROTECT (32)
|
||||||
|
|
||||||
======================================================================
|
======================================================================
|
||||||
====================== Function 69 - debugging. ======================
|
====================== Function 69 - debugging. ======================
|
||||||
|
@ -322,6 +322,17 @@ high_code:
|
|||||||
mov ecx, application_table_mutex
|
mov ecx, application_table_mutex
|
||||||
call mutex_init
|
call mutex_init
|
||||||
|
|
||||||
|
mov ecx, shmem_list_mutex
|
||||||
|
call mutex_init
|
||||||
|
mov ecx, pe_list_mutex
|
||||||
|
call mutex_init
|
||||||
|
mov ecx, shared_locked_mutex
|
||||||
|
call mutex_init
|
||||||
|
mov ecx, proc_mem_mutex
|
||||||
|
call mutex_init
|
||||||
|
mov ecx, ipc_mutex
|
||||||
|
call mutex_init
|
||||||
|
|
||||||
mov ecx, ide_mutex
|
mov ecx, ide_mutex
|
||||||
call mutex_init
|
call mutex_init
|
||||||
mov ecx, ide_channel1_mutex
|
mov ecx, ide_channel1_mutex
|
||||||
@ -513,6 +524,9 @@ high_code:
|
|||||||
add eax, ebx
|
add eax, ebx
|
||||||
mov [ipc_ptab], eax
|
mov [ipc_ptab], eax
|
||||||
|
|
||||||
|
add eax, ebx
|
||||||
|
mov [zero_page_tab], eax
|
||||||
|
|
||||||
stdcall kernel_alloc, (unpack.LZMA_BASE_SIZE+(unpack.LZMA_LIT_SIZE shl \
|
stdcall kernel_alloc, (unpack.LZMA_BASE_SIZE+(unpack.LZMA_LIT_SIZE shl \
|
||||||
(unpack.lc+unpack.lp)))*4
|
(unpack.lc+unpack.lp)))*4
|
||||||
|
|
||||||
@ -2879,40 +2893,39 @@ align 4
|
|||||||
mov [bgrlockpid], eax
|
mov [bgrlockpid], eax
|
||||||
cmp [img_background], static_background_data
|
cmp [img_background], static_background_data
|
||||||
jz .nomem
|
jz .nomem
|
||||||
stdcall user_alloc, [mem_BACKGROUND]
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_lock
|
||||||
|
stdcall user_alloc_nolock, [mem_BACKGROUND]
|
||||||
mov [esp+32], eax
|
mov [esp+32], eax
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .nomem
|
jz .nomem_unlock
|
||||||
mov ebx, eax
|
mov ebx, eax
|
||||||
shr ebx, 12
|
shr ebx, 12
|
||||||
or dword [page_tabs+(ebx-1)*4], MEM_BLOCK_DONT_FREE
|
|
||||||
mov esi, [img_background]
|
mov esi, [img_background]
|
||||||
shr esi, 12
|
shr esi, 12
|
||||||
mov ecx, [mem_BACKGROUND]
|
mov ecx, [mem_BACKGROUND]
|
||||||
add ecx, 0xFFF
|
add ecx, 0xFFF
|
||||||
shr ecx, 12
|
shr ecx, 12
|
||||||
;--------------------------------------
|
|
||||||
align 4
|
|
||||||
.z:
|
.z:
|
||||||
mov eax, [page_tabs+ebx*4]
|
|
||||||
test al, 1
|
|
||||||
jz @f
|
|
||||||
call free_page
|
|
||||||
;--------------------------------------
|
|
||||||
align 4
|
|
||||||
@@:
|
|
||||||
mov eax, [page_tabs+esi*4]
|
mov eax, [page_tabs+esi*4]
|
||||||
or al, PG_UWR
|
or eax, PG_UWR+PG_SHARED
|
||||||
mov [page_tabs+ebx*4], eax
|
mov [page_tabs+ebx*4], eax
|
||||||
mov eax, ebx
|
mov eax, ebx
|
||||||
shl eax, 12
|
shl eax, 12
|
||||||
invlpg [eax]
|
invlpg [eax]
|
||||||
inc ebx
|
inc ebx
|
||||||
inc esi
|
inc esi
|
||||||
loop .z
|
dec ecx
|
||||||
|
jnz .z
|
||||||
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
ret
|
ret
|
||||||
;--------------------------------------
|
.nomem_unlock:
|
||||||
align 4
|
mov ecx, [current_process]
|
||||||
|
add ecx, PROC.heap_lock
|
||||||
|
call mutex_unlock
|
||||||
.nomem:
|
.nomem:
|
||||||
and [bgrlockpid], 0
|
and [bgrlockpid], 0
|
||||||
mov [bgrlock], 0
|
mov [bgrlock], 0
|
||||||
@ -2926,30 +2939,7 @@ nosb6:
|
|||||||
mov eax, [current_slot_idx]
|
mov eax, [current_slot_idx]
|
||||||
cmp [bgrlockpid], eax
|
cmp [bgrlockpid], eax
|
||||||
jnz .err
|
jnz .err
|
||||||
mov eax, ecx
|
stdcall user_free, ecx
|
||||||
mov ebx, ecx
|
|
||||||
shr eax, 12
|
|
||||||
mov ecx, [page_tabs+(eax-1)*4]
|
|
||||||
test cl, MEM_BLOCK_USED or MEM_BLOCK_DONT_FREE
|
|
||||||
jz .err
|
|
||||||
jnp .err
|
|
||||||
push eax
|
|
||||||
shr ecx, 12
|
|
||||||
dec ecx
|
|
||||||
;--------------------------------------
|
|
||||||
align 4
|
|
||||||
@@:
|
|
||||||
and dword [page_tabs+eax*4], 0
|
|
||||||
mov edx, eax
|
|
||||||
shl edx, 12
|
|
||||||
push eax
|
|
||||||
invlpg [edx]
|
|
||||||
pop eax
|
|
||||||
inc eax
|
|
||||||
loop @b
|
|
||||||
pop eax
|
|
||||||
and dword [page_tabs+(eax-1)*4], not MEM_BLOCK_DONT_FREE
|
|
||||||
stdcall user_free, ebx
|
|
||||||
mov [esp+32], eax
|
mov [esp+32], eax
|
||||||
and [bgrlockpid], 0
|
and [bgrlockpid], 0
|
||||||
mov [bgrlock], 0
|
mov [bgrlock], 0
|
||||||
@ -4925,6 +4915,14 @@ if defined debug_com_base
|
|||||||
pop ax dx
|
pop ax dx
|
||||||
end if
|
end if
|
||||||
|
|
||||||
|
if 0
|
||||||
|
push eax edx
|
||||||
|
mov al, bl
|
||||||
|
mov dx, 0x402
|
||||||
|
out dx, al
|
||||||
|
pop edx eax
|
||||||
|
end if
|
||||||
|
|
||||||
mov [msg_board_data+ecx], bl
|
mov [msg_board_data+ecx], bl
|
||||||
cmp byte [debug_direct_print], 1
|
cmp byte [debug_direct_print], 1
|
||||||
jnz .end
|
jnz .end
|
||||||
|
@ -15,6 +15,7 @@ include "core/fpu.inc" ; all fpu/sse support
|
|||||||
include "core/memory.inc"
|
include "core/memory.inc"
|
||||||
include "core/mtrr.inc"
|
include "core/mtrr.inc"
|
||||||
include "core/heap.inc"
|
include "core/heap.inc"
|
||||||
|
include "core/peuser.inc"
|
||||||
include "core/malloc.inc" ; small kernel heap
|
include "core/malloc.inc" ; small kernel heap
|
||||||
include "core/taskman.inc"
|
include "core/taskman.inc"
|
||||||
include "core/dll.inc"
|
include "core/dll.inc"
|
||||||
|
Loading…
Reference in New Issue
Block a user