From e463f78e2742cf01c3bf32aa099bbf2c79b10bfd Mon Sep 17 00:00:00 2001 From: "Evgeny Grechnikov (Diamond)" Date: Fri, 27 Nov 2009 23:49:47 +0000 Subject: [PATCH] dynamic libraries now share unmodified pages git-svn-id: svn://kolibrios.org@1289 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/const.inc | 43 +++- kernel/trunk/core/dll.inc | 472 +++++++++++++++++++++++++++++----- kernel/trunk/core/ext_lib.inc | 5 +- kernel/trunk/core/heap.inc | 98 ++++++- kernel/trunk/core/memory.inc | 41 ++- kernel/trunk/data32.inc | 10 +- kernel/trunk/fs/fs_lfn.inc | 88 +++++-- kernel/trunk/kernel.asm | 2 + 8 files changed, 664 insertions(+), 95 deletions(-) diff --git a/kernel/trunk/const.inc b/kernel/trunk/const.inc index 5e903b3833..907a5d7199 100644 --- a/kernel/trunk/const.inc +++ b/kernel/trunk/const.inc @@ -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 ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -513,6 +513,47 @@ virtual at 0 SMAP SMAP 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 { .x dd ? diff --git a/kernel/trunk/core/dll.inc b/kernel/trunk/core/dll.inc index 54813a2b61..bda4f33048 100644 --- a/kernel/trunk/core/dll.inc +++ b/kernel/trunk/core/dll.inc @@ -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 ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -474,8 +474,8 @@ proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword xor eax, eax ret .ok: - mov ebx, [pSym] - mov eax, [ebx+8] + mov eax, [pSym] + mov eax, [eax+8] ret endp @@ -681,7 +681,7 @@ proc get_proc_ex stdcall, proc_name:dword, imports:dword endp 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 locals retval dd ? @@ -743,7 +743,8 @@ proc fix_coff_symbols stdcall, sec:dword, symbols:dword,\ endp 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 n_sec dd ? endl @@ -751,15 +752,15 @@ proc fix_coff_relocs stdcall, coff:dword, sec:dword, sym:dword mov eax, [coff] movzx ebx, [eax+CFH.nSections] mov [n_sec], ebx + lea esi, [eax+20] .fix_sec: - mov esi, [sec] mov edi, [esi+CFS.PtrReloc] add edi, [coff] movzx ecx, [esi+CFS.NumReloc] test ecx, ecx jz .next -.next_reloc: +.reloc_loop: mov ebx, [edi+CRELOC.SymIndex] add ebx,ebx 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] add eax, [esi+CFS.VirtualAddress] .fix: + add eax, [delta] add [eax], edx +.next_reloc: add edi, 10 dec ecx - jnz .next_reloc + jnz .reloc_loop .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] jnz .fix_sec .exit: @@ -905,10 +945,8 @@ proc load_driver stdcall, driver_name:dword jz .link_fail mov ebx, [coff] - add ebx, 20 - stdcall fix_coff_relocs, [coff], ebx, [sym] + stdcall fix_coff_relocs, ebx, [sym], 0 - mov ebx, [coff] stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szVersion test eax, eax jz .link_fail @@ -983,25 +1021,120 @@ endp align 4 proc load_library stdcall, file_name:dword locals + fullname rb 260 + fileinfo rb 40 coff dd ? - sym dd ? - strings dd ? - img_size dd ? img_base dd ? - exports dd ? endl cli - stdcall load_file, [file_name] - test eax, eax +; resolve file name + mov ebx, [file_name] + lea edi, [fullname+1] + mov byte [edi-1], '/' + stdcall get_full_file_name, edi, 259 + test al, al 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 - 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 - lea edx, [eax+20] + add edx, 20 @@: add ebx, [edx+CFS.SizeOfRawData] add ebx, 15 @@ -1009,85 +1142,294 @@ proc load_library stdcall, file_name:dword add edx, COFF_SECTION_SIZE dec ecx jnz @B - mov [img_size], ebx - - call init_heap - stdcall user_alloc, [img_size] - +; it must be nonzero and not too big + mov [esi+DLLDESCR.size], ebx + test ebx, ebx + 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 - jz .fail - mov [img_base], eax + jz .fail_and_free_dll + 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] movzx ebx, [edx+CFH.nSections] - mov edi, [img_base] - lea eax, [edx+20] + mov edi, eax + add edx, 20 + xor eax, eax + cld @@: - mov [eax+CFS.VirtualAddress], edi - mov esi, [eax+CFS.PtrRawData] + mov [edx+CFS.VirtualAddress], ecx + add ecx, [edx+CFS.SizeOfRawData] + mov esi, [edx+CFS.PtrRawData] + push ecx + mov ecx, [edx+CFS.SizeOfRawData] test esi, esi jnz .copy - add edi, [eax+CFS.SizeOfRawData] + rep stosb jmp .next .copy: - add esi, edx - mov ecx, [eax+CFS.SizeOfRawData] - cld + add esi, [coff] rep movsb .next: + pop ecx add edi, 15 ;-new_app_base + add ecx, 15 and edi, -16 - add eax, COFF_SECTION_SIZE + and ecx, -16 + add edx, COFF_SECTION_SIZE dec ebx 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 edi, dword [fileinfo+32] + sub edi, ebx + jc .fail_and_free_data + mov [esi+DLLDESCR.symbols_lim], edi 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] - add ecx,ecx - lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE - add ecx, [sym] - mov [strings], ecx + 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+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],\ - [strings], dword 0 + stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax,\ + ecx, 0 +; test eax, eax +; jnz @F +; +;@@: + + stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],szEXPORTS test eax, eax jnz @F + stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],sz_EXPORTS @@: - mov edx, [coff] - 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 + mov [esi+DLLDESCR.exports], eax - add edx, 20 - stdcall fix_coff_relocs, [coff], edx, [sym] +; fix relocs in the hidden copy in kernel memory to default address +; 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] - 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 +.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: xor eax, eax 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 +; 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 stop_all_services: push ebp diff --git a/kernel/trunk/core/ext_lib.inc b/kernel/trunk/core/ext_lib.inc index 673bd5c6a1..db53e63264 100644 --- a/kernel/trunk/core/ext_lib.inc +++ b/kernel/trunk/core/ext_lib.inc @@ -13,7 +13,9 @@ $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] { forward @@ -315,3 +317,4 @@ endp uglobal s_libname db 64 dup (0) endg +end if diff --git a/kernel/trunk/core/heap.inc b/kernel/trunk/core/heap.inc index 6ff79cf605..2aee238a59 100644 --- a/kernel/trunk/core/heap.inc +++ b/kernel/trunk/core/heap.inc @@ -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 ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -755,6 +755,102 @@ m_exit: ret 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 proc user_free stdcall, base:dword diff --git a/kernel/trunk/core/memory.inc b/kernel/trunk/core/memory.inc index 6fac0549d7..45ca27db43 100644 --- a/kernel/trunk/core/memory.inc +++ b/kernel/trunk/core/memory.inc @@ -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 ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -614,7 +614,7 @@ end if test eax, eax jz .fail - stdcall map_page,[.err_addr],eax,dword PG_UW + stdcall map_page,[.err_addr],eax,PG_UW mov edi, [.err_addr] and edi, 0xFFFFF000 @@ -627,9 +627,40 @@ end if restore_ring3_context iretd -.err_access = .fail -;никогда не происходит - ;jmp .fail +.err_access: +; access denied? this may be a result of copy-on-write protection for DLL +; 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: test eax, PG_MAP diff --git a/kernel/trunk/data32.inc b/kernel/trunk/data32.inc index 7434e46e82..a472cf72b5 100644 --- a/kernel/trunk/data32.inc +++ b/kernel/trunk/data32.inc @@ -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 ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -119,6 +119,14 @@ shmem_list: .bk 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 ;mode_1280_1024_32: diff --git a/kernel/trunk/fs/fs_lfn.inc b/kernel/trunk/fs/fs_lfn.inc index 5dec9e4607..3c1178f16f 100644 --- a/kernel/trunk/fs/fs_lfn.inc +++ b/kernel/trunk/fs/fs_lfn.inc @@ -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 ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1004,6 +1004,19 @@ sys_current_directory: .set: ; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string ; 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 cmp byte [esi-1], 0 @@ -1012,6 +1025,7 @@ sys_current_directory: cmp byte [ebx], '/' jz .set_absolute ; string gives relative path + mov edi, [esp+8] ; destination .relative: cmp byte [ebx], 0 jz .set_ok @@ -1032,33 +1046,67 @@ sys_current_directory: dec esi cmp byte [esi], '/' jnz @b - mov byte [esi], 0 add ebx, 3 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: - add edx, 0x1000 - mov byte [esi], '/' - inc esi - cmp esi, edx - jae .overflow_esi + cmp edx, edi + jz .doset_relative.cur_dir + sub esi, edx + cmp esi, [esp+12] + 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] inc ebx - mov [esi], al - inc esi + stosb test al, al - jz .set_ok - cmp esi, edx + jz .ret.ok + cmp edi, edx jb @b -.overflow_esi: - mov byte [esi-1], 0 ; force null-terminated string -.set_ok: - ret +.overflow: + dec edi + jmp .fail .set_absolute: lea esi, [ebx+1] call process_replace_file_name - mov edi, edx - add edx, 0x1000 + mov edi, [esp+8] + mov edx, [esp+12] + add edx, edi .set_copy: lodsb stosb @@ -1067,13 +1115,11 @@ sys_current_directory: .set_copy_cont: cmp edi, edx jb .set_copy -.overflow_edi: - mov byte [edi-1], 0 - ret + jmp .overflow .set_part2: mov esi, ebp xor ebp, ebp test esi, esi - jz .set_ok + jz .ret.ok mov byte [edi-1], '/' jmp .set_copy_cont diff --git a/kernel/trunk/kernel.asm b/kernel/trunk/kernel.asm index 664c9eb10a..4ea7aaacd9 100644 --- a/kernel/trunk/kernel.asm +++ b/kernel/trunk/kernel.asm @@ -613,6 +613,7 @@ include 'boot/rdload.inc' include 'vmodeld.inc' ;!!!!!!!!!!!!!!!!!!!!!!! +if 0 mov ax,[OS_BASE+0x10000+bx_from_load] cmp ax,'r1' ; if using not ram disk, then load librares and parameters {SPraid.simba} je no_lib_load @@ -621,6 +622,7 @@ include 'vmodeld.inc' call load_file_parse_table ; prepare file parse table call set_kernel_conf ; configure devices and gui no_lib_load: +end if ; LOAD FONTS I and II