dynamic libraries now share unmodified pages

git-svn-id: svn://kolibrios.org@1289 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Evgeny Grechnikov (Diamond) 2009-11-27 23:49:47 +00:00
parent 2beb55bd3a
commit e463f78e27
8 changed files with 664 additions and 95 deletions

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -513,6 +513,47 @@ virtual at 0
SMAP SMAP SMAP SMAP
end virtual end virtual
struc 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:
.sizeof:
}
struc HDLL
{
.magic dd ? ; HDLL
.destroy dd ? ;internal destructor
.fd dd ? ;next object in list
.bk dd ? ;prev object in list
.pid dd ? ;owner id
.base dd ? ;mapped base
.size dd ? ;mapped size
.refcount dd ? ;reference counter for this process and this lib
.parent dd ? ;DLLDESCR
.sizeof:
}
virtual at 0
DLLDESCR DLLDESCR
end virtual
virtual at 0
HDLL HDLL
end virtual
struc display_t struc display_t
{ {
.x dd ? .x dd ?

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -474,8 +474,8 @@ proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword
xor eax, eax xor eax, eax
ret ret
.ok: .ok:
mov ebx, [pSym] mov eax, [pSym]
mov eax, [ebx+8] mov eax, [eax+8]
ret ret
endp endp
@ -681,7 +681,7 @@ proc get_proc_ex stdcall, proc_name:dword, imports:dword
endp endp
align 4 align 4
proc fix_coff_symbols stdcall, sec:dword, symbols:dword,\ proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\
sym_count:dword, strings:dword, imports:dword sym_count:dword, strings:dword, imports:dword
locals locals
retval dd ? retval dd ?
@ -743,7 +743,8 @@ proc fix_coff_symbols stdcall, sec:dword, symbols:dword,\
endp endp
align 4 align 4
proc fix_coff_relocs stdcall, coff:dword, sec:dword, sym:dword proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \
delta:dword
locals locals
n_sec dd ? n_sec dd ?
endl endl
@ -751,15 +752,15 @@ proc fix_coff_relocs stdcall, coff:dword, sec:dword, sym:dword
mov eax, [coff] mov eax, [coff]
movzx ebx, [eax+CFH.nSections] movzx ebx, [eax+CFH.nSections]
mov [n_sec], ebx mov [n_sec], ebx
lea esi, [eax+20]
.fix_sec: .fix_sec:
mov esi, [sec]
mov edi, [esi+CFS.PtrReloc] mov edi, [esi+CFS.PtrReloc]
add edi, [coff] add edi, [coff]
movzx ecx, [esi+CFS.NumReloc] movzx ecx, [esi+CFS.NumReloc]
test ecx, ecx test ecx, ecx
jz .next jz .next
.next_reloc: .reloc_loop:
mov ebx, [edi+CRELOC.SymIndex] mov ebx, [edi+CRELOC.SymIndex]
add ebx,ebx add ebx,ebx
lea ebx,[ebx+ebx*8] lea ebx,[ebx+ebx*8]
@ -782,12 +783,51 @@ proc fix_coff_relocs stdcall, coff:dword, sec:dword, sym:dword
mov eax, [edi+CRELOC.VirtualAddress] mov eax, [edi+CRELOC.VirtualAddress]
add eax, [esi+CFS.VirtualAddress] add eax, [esi+CFS.VirtualAddress]
.fix: .fix:
add eax, [delta]
add [eax], edx add [eax], edx
.next_reloc:
add edi, 10 add edi, 10
dec ecx dec ecx
jnz .next_reloc jnz .reloc_loop
.next: .next:
add [sec], COFF_SECTION_SIZE add esi, COFF_SECTION_SIZE
dec [n_sec]
jnz .fix_sec
.exit:
ret
endp
proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \
delta:dword
locals
n_sec dd ?
endl
mov eax, [coff]
movzx ebx, [eax+CFH.nSections]
mov [n_sec], ebx
lea esi, [eax+20]
mov edx, [delta]
.fix_sec:
mov edi, [esi+CFS.PtrReloc]
add edi, [coff]
movzx ecx, [esi+CFS.NumReloc]
test ecx, ecx
jz .next
.reloc_loop:
cmp [edi+CRELOC.Type], 6
jne .next_reloc
.dir_32:
mov eax, [edi+CRELOC.VirtualAddress]
add eax, [esi+CFS.VirtualAddress]
add [eax+edx], edx
.next_reloc:
add edi, 10
dec ecx
jnz .reloc_loop
.next:
add esi, COFF_SECTION_SIZE
dec [n_sec] dec [n_sec]
jnz .fix_sec jnz .fix_sec
.exit: .exit:
@ -905,10 +945,8 @@ proc load_driver stdcall, driver_name:dword
jz .link_fail jz .link_fail
mov ebx, [coff] mov ebx, [coff]
add ebx, 20 stdcall fix_coff_relocs, ebx, [sym], 0
stdcall fix_coff_relocs, [coff], ebx, [sym]
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szVersion stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szVersion
test eax, eax test eax, eax
jz .link_fail jz .link_fail
@ -983,25 +1021,120 @@ endp
align 4 align 4
proc load_library stdcall, file_name:dword proc load_library stdcall, file_name:dword
locals locals
fullname rb 260
fileinfo rb 40
coff dd ? coff dd ?
sym dd ?
strings dd ?
img_size dd ?
img_base dd ? img_base dd ?
exports dd ?
endl endl
cli cli
stdcall load_file, [file_name] ; resolve file name
test eax, eax mov ebx, [file_name]
lea edi, [fullname+1]
mov byte [edi-1], '/'
stdcall get_full_file_name, edi, 259
test al, al
jz .fail jz .fail
; scan for required DLL in list of already loaded for this process,
; ignore timestamp
mov esi, [CURRENT_TASK]
shl esi, 8
lea ebx, [esi+SLOT_BASE+APP_OBJ_OFFSET]
mov esi, [ebx+APPOBJ.fd]
lea edi, [fullname]
.scan_in_process:
cmp esi, ebx
jz .not_in_process
cmp dword [esi+APPOBJ.magic], 'HDLL'
jnz .next_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]
ret
.next_in_process:
mov esi, [esi+APPOBJ.fd]
jmp .scan_in_process
.not_in_process:
; scan in full list, compare timestamp
lea eax, [fileinfo]
stdcall get_fileinfo, edi, eax
test eax, eax
jnz .fail
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:
; load file
stdcall load_file, edi
test eax, eax
jz .fail
mov [coff], eax mov [coff], eax
movzx ecx, [eax+CFH.nSections] mov dword [fileinfo+32], 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+DLLDESCR.sizeof]
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
; 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
; calculate size of loaded DLL
mov edx, [coff]
movzx ecx, [edx+CFH.nSections]
xor ebx, ebx xor ebx, ebx
lea edx, [eax+20] add edx, 20
@@: @@:
add ebx, [edx+CFS.SizeOfRawData] add ebx, [edx+CFS.SizeOfRawData]
add ebx, 15 add ebx, 15
@ -1009,85 +1142,294 @@ proc load_library stdcall, file_name:dword
add edx, COFF_SECTION_SIZE add edx, COFF_SECTION_SIZE
dec ecx dec ecx
jnz @B jnz @B
mov [img_size], ebx ; it must be nonzero and not too big
mov [esi+DLLDESCR.size], ebx
call init_heap test ebx, ebx
stdcall user_alloc, [img_size] jz .fail_and_free_dll
cmp ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
ja .fail_and_free_dll
; allocate memory for kernel-side image
stdcall kernel_alloc, ebx
test eax, eax test eax, eax
jz .fail jz .fail_and_free_dll
mov [img_base], eax mov [esi+DLLDESCR.data], 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
push esi
mov edx, [coff] mov edx, [coff]
movzx ebx, [edx+CFH.nSections] movzx ebx, [edx+CFH.nSections]
mov edi, [img_base] mov edi, eax
lea eax, [edx+20] add edx, 20
xor eax, eax
cld
@@: @@:
mov [eax+CFS.VirtualAddress], edi mov [edx+CFS.VirtualAddress], ecx
mov esi, [eax+CFS.PtrRawData] add ecx, [edx+CFS.SizeOfRawData]
mov esi, [edx+CFS.PtrRawData]
push ecx
mov ecx, [edx+CFS.SizeOfRawData]
test esi, esi test esi, esi
jnz .copy jnz .copy
add edi, [eax+CFS.SizeOfRawData] rep stosb
jmp .next jmp .next
.copy: .copy:
add esi, edx add esi, [coff]
mov ecx, [eax+CFS.SizeOfRawData]
cld
rep movsb rep movsb
.next: .next:
pop ecx
add edi, 15 ;-new_app_base add edi, 15 ;-new_app_base
add ecx, 15
and edi, -16 and edi, -16
add eax, COFF_SECTION_SIZE and ecx, -16
add edx, COFF_SECTION_SIZE
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 ebx, [edx+CFH.pSymTable] mov ebx, [edx+CFH.pSymTable]
mov edi, dword [fileinfo+32]
sub edi, ebx
jc .fail_and_free_data
mov [esi+DLLDESCR.symbols_lim], edi
add ebx, edx add ebx, edx
mov [sym], ebx movzx ecx, [edx+CFH.nSections]
lea ecx, [ecx*5]
lea edi, [edi+ecx*8+20]
add edx, 20
@@:
movzx eax, [edx+CFS.NumReloc]
lea eax, [eax*5]
lea edi, [edi+eax*2]
add edx, COFF_SECTION_SIZE
sub ecx, 5
jnz @b
stdcall kernel_alloc, edi
test eax, eax
jz .fail_and_free_data
mov edx, [coff]
movzx ecx, [edx+CFH.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+CFH.nSymbols] mov ecx, [edx+CFH.nSymbols]
add ecx,ecx mov [esi+DLLDESCR.symbols_num], ecx
lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE mov ecx, [esi+DLLDESCR.symbols_lim]
add ecx, [sym] mov esi, ebx
mov [strings], ecx rep movsb
pop esi
mov ebx, [esi+DLLDESCR.coff_hdr]
push esi
movzx eax, [edx+CFH.nSections]
lea edx, [ebx+20]
@@:
movzx ecx, [edx+CFS.NumReloc]
lea ecx, [ecx*5]
mov esi, [edx+CFS.PtrReloc]
mov [edx+CFS.PtrReloc], edi
sub [edx+CFS.PtrReloc], ebx
add esi, [coff]
shr ecx, 1
rep movsd
adc ecx, ecx
rep movsw
add edx, COFF_SECTION_SIZE
dec eax
jnz @b
pop esi
lea eax, [edx+20] ; fixup symbols
mov edx, ebx
mov eax, [ebx+CFH.nSymbols]
add edx, 20
mov ecx, [esi+DLLDESCR.symbols_num]
lea ecx, [ecx*9]
add ecx, ecx
add ecx, [esi+DLLDESCR.symbols_ptr]
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\ stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax,\
[strings], dword 0 ecx, 0
; test eax, eax
; jnz @F
;
;@@:
stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],szEXPORTS
test eax, eax test eax, eax
jnz @F jnz @F
stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],sz_EXPORTS
@@: @@:
mov edx, [coff] mov [esi+DLLDESCR.exports], eax
movzx ebx, [edx+CFH.nSections]
mov edi, new_app_base
lea eax, [edx+20]
@@:
add [eax+CFS.VirtualAddress], edi ;patch user space offset
add eax, COFF_SECTION_SIZE
dec ebx
jnz @B
add edx, 20 ; fix relocs in the hidden copy in kernel memory to default address
stdcall fix_coff_relocs, [coff], edx, [sym] ; 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
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szEXPORTS
test eax, eax
jnz @F
mov ebx, [coff]
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],sz_EXPORTS
@@:
mov [exports], eax
stdcall kernel_free, [coff] stdcall kernel_free, [coff]
mov eax, [exports]
.dll_already_loaded:
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 ebx, [CURRENT_TASK]
shl ebx, 5
add ebx, [CURRENT_TASK+ebx+TASKDATA.pid]
mov eax, HDLL.sizeof
call create_kernel_object
test eax, eax
jz .fail_and_free_user
mov [eax+APPOBJ.magic], 'HDLL'
mov [eax+APPOBJ.destroy], destroy_hdll
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], DONT_FREE_BLOCK
; 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_USER
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 ebx, [img_base]
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]
ret ret
.fail_and_free_data:
stdcall kernel_free, [esi+DLLDESCR.data]
.fail_and_free_dll:
mov eax, esi
call free
.fail_and_free_coff:
stdcall kernel_free, [coff]
.fail: .fail:
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
xor eax, eax
ret
endp endp
; 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.symbols_ptr]
stdcall kernel_free, [esi+DLLDESCR.data]
mov eax, esi
call free
.ret:
ret
destroy_hdll:
push ebx esi edi
push eax
mov ebx, [eax+HDLL.base]
push ebx ; argument for user_free
push eax
mov esi, [eax+HDLL.parent]
mov edx, [esi+DLLDESCR.size]
mov eax, ebx
shr ebx, 12
push ebx
mov esi, [esi+DLLDESCR.data]
shr esi, 12
.unmap_loop:
push eax
mov eax, 2
xchg eax, [page_tabs+ebx*4]
cmp eax, [page_tabs+esi*4]
jnz @f
call free_page
@@:
pop eax
invlpg [eax]
add eax, 0x1000
inc ebx
inc esi
sub edx, 0x1000
ja .unmap_loop
pop ebx eax
and dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
mov esi, [eax+HDLL.parent]
mov eax, [eax+HDLL.refcount]
call dereference_dll
call user_free
pop eax
call destroy_kernel_object
pop edi esi ebx
ret
align 4 align 4
stop_all_services: stop_all_services:
push ebp push ebp

View File

@ -13,7 +13,9 @@
$Revision$ $Revision$
if 0
; The code currently does not work. Kill "if 0/end if" only after correcting
; to current kernel (dll.inc).
macro library [name,fname] macro library [name,fname]
{ {
forward forward
@ -315,3 +317,4 @@ endp
uglobal uglobal
s_libname db 64 dup (0) s_libname db 64 dup (0)
endg endg
end if

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -755,6 +755,102 @@ m_exit:
ret ret
endp endp
align 4
proc user_alloc_at stdcall, address:dword, alloc_size:dword
push ebx
push esi
push edi
mov ebx, [current_slot]
mov edx, [address]
and edx, not 0xFFF
mov [address], edx
sub edx, 0x1000
jb .error
mov esi, [ebx+APPDATA.heap_base]
mov edi, [ebx+APPDATA.heap_top]
cmp edx, esi
jb .error
.scan:
cmp esi, edi
jae .error
mov ebx, esi
shr ebx, 12
mov eax, [page_tabs+ebx*4]
mov ecx, eax
and ecx, 0xFFFFF000
add ecx, esi
cmp edx, ecx
jb .found
mov esi, ecx
jmp .scan
.error:
xor eax, eax
pop edi
pop esi
pop ebx
ret
.found:
test al, FREE_BLOCK
jz .error
mov eax, ecx
sub eax, edx
sub eax, 0x1000
cmp eax, [alloc_size]
jb .error
; Here we have 1 big free block which includes requested area.
; In general, 3 other blocks must be created instead:
; free at [esi, edx);
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
; First or third block (or both) may be absent.
mov eax, edx
sub eax, esi
jz .nofirst
or al, FREE_BLOCK
mov [page_tabs+ebx*4], eax
.nofirst:
mov eax, [alloc_size]
add eax, 0x1FFF
and eax, not 0xFFF
mov ebx, edx
add edx, eax
shr ebx, 12
or al, USED_BLOCK
mov [page_tabs+ebx*4], eax
shr eax, 12
dec eax
jz .second_nofill
inc ebx
.fill:
mov dword [page_tabs+ebx*4], 2
inc ebx
dec eax
jnz .fill
.second_nofill:
sub ecx, edx
jz .nothird
or cl, FREE_BLOCK
mov [page_tabs+ebx*4], ecx
.nothird:
mov edx, [current_slot]
mov ebx, [alloc_size]
add ebx, 0xFFF
and ebx, not 0xFFF
add ebx, [edx+APPDATA.mem_size]
call update_mem_size
mov eax, [address]
pop edi
pop esi
pop ebx
ret
endp
align 4 align 4
proc user_free stdcall, base:dword proc user_free stdcall, base:dword

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -614,7 +614,7 @@ end if
test eax, eax test eax, eax
jz .fail jz .fail
stdcall map_page,[.err_addr],eax,dword PG_UW stdcall map_page,[.err_addr],eax,PG_UW
mov edi, [.err_addr] mov edi, [.err_addr]
and edi, 0xFFFFF000 and edi, 0xFFFFF000
@ -627,9 +627,40 @@ end if
restore_ring3_context restore_ring3_context
iretd iretd
.err_access = .fail .err_access:
;íèêîãäà íå ïðîèñõîäèò ; access denied? this may be a result of copy-on-write protection for DLL
;jmp .fail ; check list of HDLLs
and ebx, not 0xFFF
mov eax, [CURRENT_TASK]
shl eax, 8
lea eax, [SLOT_BASE+eax+APP_OBJ_OFFSET]
mov esi, [eax+APPOBJ.fd]
.scan_hdll:
cmp esi, eax
jz .fail
cmp [esi+APPOBJ.magic], 'HDLL'
jnz .scan_hdll.next
mov edx, ebx
sub edx, [esi+HDLL.base]
cmp edx, [esi+HDLL.size]
jb .fault_in_hdll
.scan_hdll.next:
mov esi, [esi+APPOBJ.fd]
jmp .scan_hdll
.fault_in_hdll:
; allocate new page, map it as rw and copy data
call alloc_page
test eax, eax
jz .fail
stdcall map_page,ebx,eax,PG_UW
mov edi, ebx
mov ecx, 1024
sub ebx, [esi+HDLL.base]
mov esi, [esi+HDLL.parent]
mov esi, [esi+DLLDESCR.data]
add esi, ebx
rep movsd
jmp .exit
.kernel_space: .kernel_space:
test eax, PG_MAP test eax, PG_MAP

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -119,6 +119,14 @@ shmem_list:
.bk dd shmem_list .bk dd shmem_list
.fd dd shmem_list .fd dd shmem_list
dll_list:
.bk dd dll_list
.fd dd dll_list
MAX_DEFAULT_DLL_ADDR = 0x20000000
MIN_DEFAULT_DLL_ADDR = 0x10000000
dll_cur_addr dd MIN_DEFAULT_DLL_ADDR
; supported videomodes ; supported videomodes
;mode_1280_1024_32: ;mode_1280_1024_32:

View File

@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; Distributed under terms of the GNU General Public License ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -1004,6 +1004,19 @@ sys_current_directory:
.set: .set:
; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string ; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string
; for our code: ebx->string to set ; for our code: ebx->string to set
; use generic resolver with APPDATA.cur_dir as destination
push 0x1000
push edx
call get_full_file_name
ret
; in: ebx = file name, [esp+4] = destination, [esp+8] = sizeof destination
; destroys all registers except ebp,esp
get_full_file_name:
push ebp
mov esi, [current_slot]
mov esi, [esi+APPDATA.cur_dir]
mov edx, esi
@@: @@:
inc esi inc esi
cmp byte [esi-1], 0 cmp byte [esi-1], 0
@ -1012,6 +1025,7 @@ sys_current_directory:
cmp byte [ebx], '/' cmp byte [ebx], '/'
jz .set_absolute jz .set_absolute
; string gives relative path ; string gives relative path
mov edi, [esp+8] ; destination
.relative: .relative:
cmp byte [ebx], 0 cmp byte [ebx], 0
jz .set_ok jz .set_ok
@ -1032,33 +1046,67 @@ sys_current_directory:
dec esi dec esi
cmp byte [esi], '/' cmp byte [esi], '/'
jnz @b jnz @b
mov byte [esi], 0
add ebx, 3 add ebx, 3
jmp .relative jmp .relative
.set_ok:
cmp edx, edi ; is destination equal to APPDATA.cur_dir?
jz .set_ok.cur_dir
sub esi, edx
cmp esi, [esp+12]
jb .set_ok.copy
.fail:
mov byte [edi], 0
xor eax, eax ; fail
pop ebp
ret 8
.set_ok.copy:
mov ecx, esi
mov esi, edx
rep movsb
mov byte [edi], 0
.ret.ok:
mov al, 1 ; ok
pop ebp
ret 8
.set_ok.cur_dir:
mov byte [esi], 0
jmp .ret.ok
.doset_relative: .doset_relative:
add edx, 0x1000 cmp edx, edi
mov byte [esi], '/' jz .doset_relative.cur_dir
inc esi sub esi, edx
cmp esi, edx cmp esi, [esp+12]
jae .overflow_esi jae .fail
mov ecx, esi
mov esi, edx
mov edx, edi
rep movsb
jmp .doset_relative.copy
.doset_relative.cur_dir:
mov edi, esi
.doset_relative.copy:
add edx, [esp+12]
mov byte [edi], '/'
inc edi
cmp edi, edx
jae .overflow
@@: @@:
mov al, [ebx] mov al, [ebx]
inc ebx inc ebx
mov [esi], al stosb
inc esi
test al, al test al, al
jz .set_ok jz .ret.ok
cmp esi, edx cmp edi, edx
jb @b jb @b
.overflow_esi: .overflow:
mov byte [esi-1], 0 ; force null-terminated string dec edi
.set_ok: jmp .fail
ret
.set_absolute: .set_absolute:
lea esi, [ebx+1] lea esi, [ebx+1]
call process_replace_file_name call process_replace_file_name
mov edi, edx mov edi, [esp+8]
add edx, 0x1000 mov edx, [esp+12]
add edx, edi
.set_copy: .set_copy:
lodsb lodsb
stosb stosb
@ -1067,13 +1115,11 @@ sys_current_directory:
.set_copy_cont: .set_copy_cont:
cmp edi, edx cmp edi, edx
jb .set_copy jb .set_copy
.overflow_edi: jmp .overflow
mov byte [edi-1], 0
ret
.set_part2: .set_part2:
mov esi, ebp mov esi, ebp
xor ebp, ebp xor ebp, ebp
test esi, esi test esi, esi
jz .set_ok jz .ret.ok
mov byte [edi-1], '/' mov byte [edi-1], '/'
jmp .set_copy_cont jmp .set_copy_cont

View File

@ -613,6 +613,7 @@ include 'boot/rdload.inc'
include 'vmodeld.inc' include 'vmodeld.inc'
;!!!!!!!!!!!!!!!!!!!!!!! ;!!!!!!!!!!!!!!!!!!!!!!!
if 0
mov ax,[OS_BASE+0x10000+bx_from_load] mov ax,[OS_BASE+0x10000+bx_from_load]
cmp ax,'r1' ; if using not ram disk, then load librares and parameters {SPraid.simba} cmp ax,'r1' ; if using not ram disk, then load librares and parameters {SPraid.simba}
je no_lib_load je no_lib_load
@ -621,6 +622,7 @@ include 'vmodeld.inc'
call load_file_parse_table ; prepare file parse table call load_file_parse_table ; prepare file parse table
call set_kernel_conf ; configure devices and gui call set_kernel_conf ; configure devices and gui
no_lib_load: no_lib_load:
end if
; LOAD FONTS I and II ; LOAD FONTS I and II