Загрузка библиотек

Internal structure and you change requests/suggestions
  • IgorA wrote:Планируется ли вывод сообщений (на Board) если библиотека не найдена или функции в библиотеке нет?
    В планах если ничего не загрузится - приложение тупо не стартанет.
    В хотелках чтоб сообщило почему не стартанет, но без гарантии (надеюсь как то сделать уведомление пользователя из ядра, но поскольку не знаю как.) хотелок-реализаций.
    IgorA wrote:
    ProMiNick wrote:banner dq ?
    Сюда по возможности желательно поставить KOLIBRI1 вместо MENUET01
    элементарно. без проблем. Не вместо а добавить в мписок допустимых
  • ProMiNick wrote:В хотелках чтоб сообщило почему не стартанет, но без гарантии (надеюсь как то сделать уведомление пользователя из ядра, но поскольку не знаю как.) хотелок-реализаций.
    Делать через notify наверное не вариант, потому как она сама подключает libimg для показа картинок ...
    Потому думаю что остается через функцию 63.1 с выводом на Board.
  • ProMiNick wrote:
    IgorA wrote:
    ProMiNick wrote:banner dq ?
    Сюда по возможности желательно поставить KOLIBRI1 вместо MENUET01
    элементарно. без проблем. Не вместо а добавить в мписок допустимых

    Code: Select all

    MAX_SUPPORTED_MENUET_FILE_VERSION = 2
    align 4
    test_app_header:
           virtual at eax
             APP_HEADER_00 APP_HEADER_00_
           end virtual
           virtual at eax
             APP_HEADER_01 APP_HEADER_01_
           end virtual
    
            cmp     dword [eax], 'MENU'
            je      .menuet_may_be
            cmp     dword [eax], 'KOLI'
            jne     .fail
            cmp     dword [eax+4], 'BRI1'
            jne     .fail
            jmp     .banner_OK
      .menuet_may_be:
            cmp     word [eax+4], 'ET'
            jne     .fail
      .banner_OK:
            mov     ecx, [APP_HEADER_00.start]
            mov     [ebx+APP_HDR.eip], ecx
            mov     ecx, [APP_HEADER_00.mem_size]
            mov     edx, [APP_HEADER_00.i_end]
            cmp     ecx, edx ; {diamond}[20.08.2006] test that inited mem fit in allocated mem to prevent kernel faults
            jb      .fail
            mov     [ebx+APP_HDR._emem], ecx
            mov     [ebx+APP_HDR._edata], edx
    
            mov     dx, word [eax+6]
            cmp     dx, 'I1'
            jz      .skip_menuet_checks
            sub     dx, '00'
            jne     .check_01_header
            mov     [ebx+APP_HDR.path], 0
    
            shr     ecx, 1
            sub     ecx, 0x10
            mov     edx, [APP_HEADER_00.i_param]
            jmp     @F
     .check_01_header:
            cmp     dx, MAX_SUPPORTED_MENUET_FILE_VERSION
            ja      .fail
     .skip_menuet_checks:
            mov     ecx, [APP_HEADER_01.i_icon]
            mov     [ebx+APP_HDR.path], ecx
    
            mov     ecx, [APP_HEADER_01.stack_top]
            mov     edx, [APP_HEADER_01.i_param]
          @@:
            mov     [ebx+APP_HDR.esp], ecx
            mov     [ebx+APP_HDR.cmdline], edx
            ret
    .fail:
            xor     eax, eax
            ret
    из (root)/kernel/trunk/core/taskman.inc всего одну функцию модифицировать. (этот вариант помоему даже короче по размеру не смотря на добавленую проверку (а не колибри ли в баннере хнднра?)
  • ладно dunkaist я тут с ужасом осознал что COFF формата я не знаю совсем...
    А PE очень хорошо. (меня даже вариант исполнимые - менуэт, а либы - ПЕ ДЛЛ вполне устроит)
    готов взяться за список this list...
    ... если подсказывать будешь.

    начнем по порядку.
    вызов DllMain при загрузке/выгрузке DLL - адресс дллмайна из заголовка легко поднять, в чем именно здесь проблема? как ядро перекидывает управление в юзермод? оно параметры пробрасывать не может?
  • ProMiNick wrote:вызов DllMain при загрузке/выгрузке DLL - адресс дллмайна из заголовка легко поднять, в чем именно здесь проблема? как ядро перекидывает управление в юзермод? оно параметры пробрасывать не может?
    Well, I'm not the author of mentioned PE patch but let's think together. My understanding is that there is no bug or issue breaking features from the list, they are 'just' not implemented.
    Kernel loads PE exe, maps system library and starts app execution from dynamic linker, i.e. already in the userspace. You don't need to pass anything more from the kernel.
  • dunkaist wrote:Coldy already implemented this about a year ago.
    It wasn't merged to trunk. May be because automatic loading of libraries was also implemented for PE.
    When somebody will implement features of this list, loading of libraries will be merged to trunk automatically.
    Your approach looks like a double work which you are free to do of course.
    Привет! Действительно, в начале этого года я выкладывал модификацию ядра + dll.obj (основана на функциях dll.inc), которые реализуют автоматическую загрузку библиотек приложения (но там еще требуется доработка, чтобы загружались и зависимые библиотеки, а также реализовать вызов notify для вывода сообщения какая библиотека и функция не найдена, если что-то пошло не так). Плюс этого в том, что не нужно в каждое приложение и библиотеку включать код загрузки библиотек и вызывать функцию инициализации кучи (ф. 68.11), т.к. это все живет в dll.obj и вызывается ядром при запуске приложения, соответственно уменьшается размер приложения. Никаких реакций тогда в течении месяца не последовало, тема мной была удалена, т.к. я решил, что это никому не интересно.
  • Coldy wrote:Действительно, в начале этого года я выкладывал модификацию ядра + dll.obj (основана на функциях dll.inc), которые реализуют автоматическую загрузку библиотек приложения
    Привет! Не совсем пойму как будет работать эта загрузка. Допустим программе нужно загрузить библиотеки, она сначала должна загрузить библиотеку для загрузки библиотек, что-бы через эту библиотеку загружать остальные библиотеки? Тогда как она будет загружать эту загрузочную библиотеку?
    Coldy wrote:а также реализовать вызов notify для вывода сообщения какая библиотека и функция не найдена, если что-то пошло не так
    Это очень хорошо, может этот код пригодится для этого:
    Spoiler:

    Code: Select all

    ;description:
    ; готовим текст для показа через @notify:
    ; 1) выделяем память в [arrea_xx] но не больше одного раза
    ; 2) копируем заголовок (если есть имя функции то добавляем его к заголовку) и текст сообщения в [arrea_xx]
    ;input:
    ; ebp+8  - library name
    ; ebp+12 - 0 или имя функции, которую не удалось экспортировать
    ;output:
    ; eax = -1
    align 4
    l_lib_init_error_window:
    	push ebp
    	mov ebp,esp
    	cmp dword[arrea_xx],0
    	jne .no_msg ;если раньше было создано другое сообщение
    	pushad
    
    	mcall SF_SYS_MISC,SSF_HEAP_INIT
    	mcall SF_SYS_MISC,SSF_MEM_ALLOC,4096
    	mov [arrea_xx],eax
    
    	mov edi,eax
    	mov esi,l_lib_m2 ;сообщение если не удалось импортировать функцию
    	cmp dword[ebp+12],0
    	je @f
    	mov esi,l_lib_m1 ;сообщение если не удалось загрузить библиотеку
    align 4
    @@:
    	movsb
    	cmp byte[esi],0
    	jne @b
    	;добавляем имя библиотеки
    	mov esi,[ebp+8]
    align 4
    @@:
    	movsb
    	cmp byte[esi],0
    	jne @b
    
    	cmp dword[ebp+12],0
    	je .lp1
    	;добавляем середину сообщения
    	mov esi,l_lib_m3
    align 4
    @@:
    	movsb
    	cmp byte[esi],0
    	jne @b
    	;добавляем имя функции
    	mov esi,[ebp+12]
    align 4
    @@:
    	movsb
    	cmp byte[esi],0
    	jne @b
    	
    	.lp1: ;сообщение если не удалось загрузить библиотеку
    	;добавляем конец сообщения
    	mov esi,l_lib_m4
    align 4
    @@:
    	movsb
    	cmp byte[esi],0
    	jne @b
    	mov byte[edi],0
    
    	popad
    	.no_msg:
    	or eax,-1
    	pop ebp
    	ret 8
  • IgorA wrote:Допустим программе нужно загрузить библиотеки, она сначала должна загрузить библиотеку для загрузки библиотек, что-бы через эту библиотеку загружать остальные библиотеки? Тогда как она будет загружать эту загрузочную библиотеку?
    viewtopic.php?f=1&t=1839#p35842
  • IgorA, в программе надо просто прописать импорты, как обычно с dll.inc и дать ссылку в конце заголовка. Идея в том, что загрузка библиотек происходит точно также как с dll в форточках или so в никсах. Это обсуждение надо перенести в соответствующую тему.
  • dll.obj загружается ядром, при этом ядро же устанавливает точку входа именно в этой библиотеке. Далее dll.obj загружает нужные приложению библиотеки и затем передает управление на точку входа приложения.
  • Привет! А как это использовать?
    Изобретайте колёса каждый раз, когда хотите написать новую программу.
  • А можно в коммитах подробнее излагать изменения
    Изобретайте колёса каждый раз, когда хотите написать новую программу.
  • Привет!
    Реализовал альфа версию автозагрузки библиотек и связывания импортов.
    Ограничения:
    1) нет выдачи сообщений об ошибках в случае если библиотека или функция в библиотеки не найдена
    2) нет автозагрузки зависимых библиотек (требуется доработка формата библиотек)

    Кратко, как использовать это в своем приложении:
    1. В заголовке приложения в поле version (следует после MENUET01) необходимо указать цифру 2
    2. Следом после заголовка добавить указатель на импортируемые библиотеки
    3. Указать импортируемые библиотеки (так же, как и при использовании dll.Load)
    4. Добавить код, без подключения dll.inc и соответственно без вызова dll.Load. Функцию инициализации кучи (ф. 68.11) тоже вызывать не нужно.
    5. Скомпилировать программу и запустить.
    Если все сделано правильно, то при запуске на доске отладки будет сообщение "App header version 2". В случае отсутствия библиотеки DLL.OBJ будет показано сообщение, в т.ч. через @NOTIFY. Если получаете ошибку станицы убедитесь, что выполнены п. 2 и 3

    Code: Select all

    format binary as ""
    use32
    	org	0x0
    	db	'MENUET01'	; Signature
    	dd	2      		; Header version - for automatically load dll.obj must be 2 
    	dd	START		; Ptr to entry point
    	dd	I_END		; Image size
    	dd	MEM	         	; required memory
    	dd	STACKTOP	   	; stack pointer
    	dd	0			; command line
    	dd	0			; icon pointer
      
      	dd  @IMPORT		; pointer to import table
      	
     include '../../proc32.inc'
      include '../../macros.inc' 
      	
     START:
     	; You code here
     	invoke foo_bar1
     	
     	invoke foo_bar2, [foo_bar], eax
     	
     	; ...
     	
     	; Exit programm
     	mcall -1
     	
        align 4
     ; Import table
        @IMPORT:
        library foo_lib, 'foo.obj'
        import  foo_lib, \
          foo_bar1, 'foo_bar1',    \
          foo_bar2, 'foo2'
    
          
          foo_bar dd ?
          
    I_END:
         rb 4096        ; size of stack
         align 16       ; ?	
    STACKTOP:
    
    align 4
    MEM:
    
    ;IM_END:
    
    
  • Coldy, в помощь:
    dll.asm:

    Code: Select all

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

    Users browsing this forum: No registered users and 5 guests