Subversion Repositories Kolibri OS

Rev

Rev 6767 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ; Check whether PE module has been loaded at preferred address.
  2. ; If not, relocate the module.
  3. ;
  4. ; in: esi = PE base address
  5. ; in: [esp+4] = module name for debug print
  6. ; out: CF=1 - fail
  7. proc fixup_pe_relocations uses edi ebp
  8. ; 1. Fetch some data from PE header or stripped PE header.
  9. ; We need:
  10. ; * ImageBase - preferred address, compare with esi = actual load address;
  11. ;   ebp will keep the delta
  12. ; * RVA and size of fixups directory
  13. ; * flag IMAGE_FILE_RELOCS_STRIPPED from Characteristics
  14. ; If the actual address equals the preferred address, do nothing.
  15. ; If fixups directory is present, proceed to 2.
  16. ; If there is no fixups directory, there are two options:
  17. ; * either the directory has not been created
  18. ; * or the module has no fixups (data-only module, for example).
  19. ; In the first case, IMAGE_FILE_RELOCS_STRIPPED is set, and this is an error.
  20. ; In the second case, IMAGE_FILE_RELOCS_STRIPPED is not set; do nothing.
  21.         mov     ebp, esi
  22.         cmp     word [esi], 'MZ'
  23.         jz      .parse_mz
  24.         sub     ebp, [esi+STRIPPED_PE_HEADER.ImageBase]
  25.         jnz     @f
  26. .nothing:
  27.         ret
  28. @@:
  29.         mov     dl, byte [esi+STRIPPED_PE_HEADER.Characteristics]
  30.         lea     eax, [esi+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_BASERELOC*sizeof.IMAGE_DATA_DIRECTORY]
  31.         cmp     [esi+STRIPPED_PE_HEADER.NumberOfRvaAndSizes], SPE_DIRECTORY_BASERELOC
  32.         ja      .common
  33. .norelocs:
  34.         test    dl, IMAGE_FILE_RELOCS_STRIPPED
  35.         jz      .nothing
  36.         stc
  37.         ret
  38. .parse_mz:
  39.         mov     eax, [esi+3Ch]
  40.         add     eax, esi
  41.         sub     ebp, [eax+IMAGE_NT_HEADERS.OptionalHeader.ImageBase]
  42.         jz      .nothing
  43.         mov     dl, byte [esi+IMAGE_NT_HEADERS.FileHeader.Characteristics]
  44.         cmp     [eax+IMAGE_NT_HEADERS.OptionalHeader.NumberOfDirectories], IMAGE_DIRECTORY_ENTRY_BASERELOC
  45.         jbe     .norelocs
  46.         add     eax, IMAGE_NT_HEADERS.OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BASERELOC*sizeof.IMAGE_DATA_DIRECTORY
  47. .common:
  48.         mov     edi, [eax+IMAGE_DATA_DIRECTORY.VirtualAddress]
  49.         push    [eax+IMAGE_DATA_DIRECTORY.isize]
  50. virtual at esp
  51. .sizeleft       dd      ?
  52. end virtual
  53.         add     edi, esi
  54.         cmp     [.sizeleft], 0
  55.         jz      .norelocs
  56. ; 2. We need to relocate and we have the relocation table.
  57. ; esi = PE base address
  58. ; edi = pointer to current data of relocation table
  59. ; 2a. Relocation table is organized into blocks describing every page.
  60. ; End of table is defined from table size fetched from the header.
  61. ; Loop 2b-2g over all blocks until no more data is left.
  62. .pageloop:
  63. ; 2b. Load the header of the current block: address and size.
  64. ; Advance total size.
  65. ; Size in the block includes size of the header, subtract it.
  66. ; If there is no data in this block, go to 2g.
  67.         mov     edx, [edi+IMAGE_BASE_RELOCATION.VirtualAddress]
  68.         mov     ecx, [edi+IMAGE_BASE_RELOCATION.SizeOfBlock]
  69.         sub     [.sizeleft], ecx
  70.         add     edi, sizeof.IMAGE_BASE_RELOCATION
  71.         sub     ecx, sizeof.IMAGE_BASE_RELOCATION
  72.         jbe     .pagedone
  73. ; 2c. We are going to modify data, so mprotect the current page to be writable.
  74. ; Save the old protection, we will restore it after the block is processed.
  75. ; Ignore any error.
  76. PROT_READ = 1
  77. PROT_WRITE = 2
  78. PROT_EXEC = 4
  79.         push    esi ecx
  80.         mov     eax, 68
  81.         mov     ebx, 30
  82.         mov     ecx, PROT_READ+PROT_WRITE
  83.         add     edx, esi
  84.         mov     esi, 0x1000
  85.         call    FS_SYSCALL_PTR
  86.         pop     ecx
  87.         push    eax
  88. ; 2d. Block data is an array of word values. Repeat 2e for every of those.
  89. .relocloop:
  90.         sub     ecx, 2
  91.         jb      .relocdone
  92. ; 2e. Every value consists of a 4-bit type and 12-bit offset in the page.
  93. ; x86 uses two types: 0 = no data (used for padding), 3 = 32-bit relative.
  94.         movzx   eax, word [edi]
  95.         add     edi, 2
  96.         mov     ebx, eax
  97.         and     ebx, 0xFFF
  98.         shr     eax, 12
  99.         jz      .relocloop
  100.         cmp     al, IMAGE_REL_BASED_HIGHLOW
  101.         jnz     .badreloc
  102.         add     [edx+ebx], ebp
  103.         jmp     .relocloop
  104. .relocdone:
  105. ; 2f. Restore memory protection changed in 2c.
  106.         pop     ecx
  107.         cmp     ecx, -1
  108.         jz      @f
  109.         mov     eax, 68
  110.         mov     ebx, 30
  111.         mov     esi, 0x1000
  112.         call    FS_SYSCALL_PTR
  113. @@:
  114.         pop     esi
  115. .pagedone:
  116.         cmp     [.sizeleft], 0
  117.         jnz     .pageloop
  118.         pop     eax ; pop .sizeleft
  119. ; 3. For performance reasons, relocation should be avoided
  120. ; by choosing an appropriate preferred address.
  121. ; If we have actually relocated something, yell to the debug board,
  122. ; so the programmer can notice that.
  123.         mov     ecx, msg_relocated1
  124.         call    sys_msg_board_str
  125.         mov     ecx, [esp+4]
  126.         call    sys_msg_board_str
  127.         mov     ecx, msg_relocated2
  128.         call    sys_msg_board_str
  129.         clc
  130.         ret
  131. .badreloc:
  132.         pop     eax
  133.         mov     ecx, msg_bad_relocation1
  134.         call    sys_msg_board_str
  135.         mov     ecx, [esp+4]
  136.         call    sys_msg_board_str
  137.         mov     ecx, msg_newline
  138.         call    sys_msg_board_str
  139.         stc
  140.         ret
  141. endp
  142.