Subversion Repositories Kolibri OS

Rev

Rev 6767 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6614 clevermous 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