Subversion Repositories Kolibri OS

Rev

Rev 6767 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6767 Rev 6810
Line 13... Line 13...
13
        cmp     byte [esi], 'M'
13
        cmp     byte [esi], 'M'
14
        jz      .parse_mz
14
        jz      .parse_mz
15
        cmp     [esi+STRIPPED_PE_HEADER.NumberOfRvaAndSizes], SPE_DIRECTORY_EXPORT
15
        cmp     [esi+STRIPPED_PE_HEADER.NumberOfRvaAndSizes], SPE_DIRECTORY_EXPORT
16
        jbe     @f
16
        jbe     @f
17
        mov     edx, [esi+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.VirtualAddress]
17
        mov     edx, [esi+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.VirtualAddress]
-
 
18
        mov     edx, [esi+edx+IMAGE_EXPORT_DIRECTORY.TimeDateStamp]
18
@@:
19
@@:
19
        mov     [eax+MODULE.timestamp], edx
20
        mov     [eax+MODULE.timestamp], edx
20
        mov     edx, esi
21
        mov     edx, esi
21
        sub     edx, [esi+STRIPPED_PE_HEADER.ImageBase]
22
        sub     edx, [esi+STRIPPED_PE_HEADER.ImageBase]
22
        mov     [eax+MODULE.basedelta], edx
23
        mov     [eax+MODULE.basedelta], edx
Line 115... Line 116...
115
        jbe     .pagedone
116
        jbe     .pagedone
116
        push    esi
117
        push    esi
117
        fpo_delta = fpo_delta + 4
118
        fpo_delta = fpo_delta + 4
118
; 2c. Check whether we have mprotect-ed the current page at the previous step.
119
; 2c. Check whether we have mprotect-ed the current page at the previous step.
119
; If so, go to 2e.
120
; If so, go to 2e.
-
 
121
        add     edx, esi
120
        cmp     [.next_page_addr+fpo_delta], edx
122
        cmp     [.next_page_addr+fpo_delta], edx
121
        jz      .mprotected_earlier
123
        jz      .mprotected_earlier
122
; 2d. We are going to modify data, so mprotect the current page to be writable.
124
; 2d. We are going to modify data, so mprotect the current page to be writable.
123
; Save the old protection, we will restore it after the block is processed.
125
; Save the old protection, we will restore it after the block is processed.
124
; Ignore any error.
126
; Ignore any error.
Line 128... Line 130...
128
PROT_EXEC = 4
130
PROT_EXEC = 4
129
        push    ecx
131
        push    ecx
130
        mov     eax, 68
132
        mov     eax, 68
131
        mov     ebx, 30
133
        mov     ebx, 30
132
        mov     ecx, PROT_READ+PROT_WRITE
134
        mov     ecx, PROT_READ+PROT_WRITE
133
        add     edx, esi
-
 
134
        mov     esi, 0x1000
135
        mov     esi, 0x1000
135
        call    FS_SYSCALL_PTR
136
        call    FS_SYSCALL_PTR
136
        pop     ecx
137
        pop     ecx
137
        jmp     .mprotected
138
        jmp     .mprotected
138
; 2e. We have already mprotect-ed the current page,
139
; 2e. We have already mprotect-ed the current page,
Line 180... Line 181...
180
        jmp     .relocloop
181
        jmp     .relocloop
181
.relocdone:
182
.relocdone:
182
; 2i. Restore memory protection changed in 2d.
183
; 2i. Restore memory protection changed in 2d.
183
        pop     ecx
184
        pop     ecx
184
        fpo_delta = fpo_delta - 4
185
        fpo_delta = fpo_delta - 4
185
        cmp     ecx, -1
-
 
186
        jz      @f
-
 
187
        mov     eax, 68
186
        mov     eax, 68
188
        mov     ebx, 30
187
        mov     ebx, 30
189
        mov     esi, 0x1000
188
        mov     esi, 0x1000
190
        call    FS_SYSCALL_PTR
189
        call    FS_SYSCALL_PTR
191
@@:
-
 
192
        pop     esi
190
        pop     esi
193
        fpo_delta = fpo_delta - 4
191
        fpo_delta = fpo_delta - 4
194
.pagedone:
192
.pagedone:
195
        cmp     [.sizeleft+fpo_delta], 0
193
        cmp     [.sizeleft+fpo_delta], 0
196
        jnz     .pageloop
194
        jnz     .pageloop
Line 240... Line 238...
240
locals
238
locals
241
export_base             dd      ?
239
export_base             dd      ?
242
export_ptr              dd      ?
240
export_ptr              dd      ?
243
export_size             dd      ?
241
export_size             dd      ?
244
import_module           dd      ?
242
import_module           dd      ?
245
import_dir              dd      ?
-
 
246
import_descriptor       dd      ?
243
import_descriptor       dd      ?
-
 
244
next_forwarder          dd      ?
-
 
245
bound_import_descriptor dd      ?
247
bound_import_dir        dd      ?
246
bound_import_dir        dd      ?
248
bound_import_cur_module dd      ?
247
bound_modules_count     dd      ?
249
relocated_bound_modules_count   dd      ?
248
bound_modules_ptr       dd      ?
-
 
249
bound_module            dd      ?
250
relocated_bound_modules_ptr     dd      ?
250
bound_modules_left      dd      ?
251
cur_page                dd      -0x1000 ; the page at 0xFFFFF000 is never allocated
251
cur_page                dd      -0x1000 ; the page at 0xFFFFF000 is never allocated
252
cur_page_old_access     dd      ?
252
cur_page_old_access     dd      ?
253
next_page               dd      -1
253
next_page               dd      -1
254
next_page_old_access    dd      ?
254
next_page_old_access    dd      ?
255
endl
255
endl
Line 279... Line 279...
279
; it is impossible to bind such a binary, but it is still valid.
279
; it is impossible to bind such a binary, but it is still valid.
280
; If OriginalFirstThunk is absent, use FirstThunk as source array.
280
; If OriginalFirstThunk is absent, use FirstThunk as source array.
281
        mov     ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
281
        mov     ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
282
        mov     ebp, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
282
        mov     ebp, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
283
        test    ebx, ebx
283
        test    ebx, ebx
284
        jnz     .label1
284
        jnz     @f
285
        mov     ebx, ebp
285
        mov     ebx, ebp
286
.label1:
286
@@:
287
; FirstThunk and OriginalFirstThunk are RVAs.
287
; FirstThunk and OriginalFirstThunk are RVAs.
288
        add     ebx, [esi+MODULE.base]
288
        add     ebx, [esi+MODULE.base]
289
        add     ebp, [esi+MODULE.base]
289
        add     ebp, [esi+MODULE.base]
290
; Source array is terminated with zero dword.
290
; Source array is terminated with zero dword.
291
.loop:
291
.loop:
Line 343... Line 343...
343
;   and forwarded exports.
343
;   and forwarded exports.
344
; * New-style bound import:
344
; * New-style bound import:
345
;   we have two parallel arrays of import descriptors and bound descriptors,
345
;   we have two parallel arrays of import descriptors and bound descriptors,
346
;   pointed to by two directories. Timestamp field has a special value -1
346
;   pointed to by two directories. Timestamp field has a special value -1
347
;   in import descriptors, real timestamps are in bound descriptors.
347
;   in import descriptors, real timestamps are in bound descriptors.
348
;   There can be different strategies; we loop over bound descriptors
-
 
349
;   and scan for corresponding import descriptors only if needed,
-
 
350
;   this accelerates the fast path where all timestamps are correct and
-
 
351
;   dependencies are not relocated.
-
 
352
; * No import: not really different from normal import with no descriptors.
348
; * No import: not really different from normal import with no descriptors.
-
 
349
; Forwarded exports are the part where binding goes really interesting.
-
 
350
; The address of forwarded export can change with any library in the chain.
-
 
351
; In old-style bound import, a descriptor can list only the library itself,
-
 
352
; so it is impossible to bind forwarded exports at all; thunks that point to
-
 
353
; forwarded exports are linked in the list starting from ForwarderChain in import descriptor.
-
 
354
; New-style bound import exists exactly to address this problem; it allows to
353
; There are two large parts in this function:
355
; list several related libraries for one imported module.
354
; step 2 handles unbound and old-style bound import, where we loop over import descriptors;
356
; However, even with new-style bound import, some forwarded exports can
-
 
357
; still remain unbound: binding tool can fail to load dependent libraries
-
 
358
; during binding time; the tool from MS SDK for unknown reason just refuses to
-
 
359
; bind forwarded exports except for built-in white list if subsystem version is
355
; step 3 handles new-style bound import, where we loop over bound descriptors.
360
; < 6.0. So even with new-style bound import, ForwarderChain still can be non-empty.
-
 
361
; Thus, we always need to look at old-style import descriptor.
356
; 1. Fetch addresses of two directories. We are not interested in their sizes.
362
; 1. Fetch addresses of two directories. We are not interested in their sizes.
357
; ebp = import RVA
363
; ebp = import RVA
358
; ebx = bound import RVA
364
; ebx = bound import RVA
359
        xor     ebx, ebx
365
        xor     ebx, ebx
360
        xor     ebp, ebp
366
        xor     ebp, ebp
Line 376... Line 382...
376
        mov     ebp, [eax+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT*sizeof.IMAGE_DATA_DIRECTORY]
382
        mov     ebp, [eax+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT*sizeof.IMAGE_DATA_DIRECTORY]
377
        cmp     [eax+IMAGE_NT_HEADERS.OptionalHeader.NumberOfDirectories], IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
383
        cmp     [eax+IMAGE_NT_HEADERS.OptionalHeader.NumberOfDirectories], IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
378
        jbe     .common
384
        jbe     .common
379
        mov     ebx, [eax+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT*sizeof.IMAGE_DATA_DIRECTORY]
385
        mov     ebx, [eax+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT*sizeof.IMAGE_DATA_DIRECTORY]
380
.common:
386
.common:
381
        mov     [import_dir], ebp
-
 
382
; If bound import is present, go to 3.
-
 
383
; If both directories are absent, no import - nothing to do.
387
; If import directory is not present, no import - nothing to do.
384
; Otherwise, advance to 2.
388
; Ignore bound import directory in this case.
385
        test    ebx, ebx
-
 
386
        jnz     .bound_import
-
 
387
        test    ebp, ebp
389
        test    ebp, ebp
388
        jz      .done
390
        jz      .done
389
; 2. Unbound import or old-style bound import.
-
 
390
; Repeat 2a-2h for all descriptors in the directory.
-
 
391
        add     ebp, [esi+MODULE.base] ; directories contain RVA
391
        add     ebp, [esi+MODULE.base] ; directories contain RVA
-
 
392
        add     ebx, [esi+MODULE.base] ; directories contain RVA
-
 
393
        mov     [bound_import_dir], ebx
-
 
394
        mov     [bound_import_descriptor], ebx
-
 
395
; Repeat remaining steps for all descriptors in the directory.
392
.normal_import_loop:
396
.descriptor_loop:
393
; 2a. Check whether this descriptor is an end mark with zero fields.
397
; 2. Check whether this descriptor is an end mark with zero fields.
394
; Look at Name field.
398
; Look at Name field.
395
        mov     edi, [ebp+IMAGE_IMPORT_DESCRIPTOR.Name]
399
        mov     edi, [ebp+IMAGE_IMPORT_DESCRIPTOR.Name]
396
        test    edi, edi
400
        test    edi, edi
397
        jz      .done
401
        jz      .done
398
; 2b. Load the target module.
402
; 3. Load the target module.
399
        add     edi, [esi+MODULE.base] ; Name field is RVA
403
        add     edi, [esi+MODULE.base] ; Name field is RVA
400
        call    load_imported_module ; should preserve esi,ebp
404
        call    load_imported_module ; should preserve esi,ebp
401
        test    eax, eax
405
        test    eax, eax
402
        jz      .failed
406
        jz      .failed
403
        mov     [import_module], eax
407
        mov     [import_module], eax
404
; 2c. Check whether the descriptor has a non-stale old-style binding.
408
; 4. Check whether the descriptor has a non-stale old-style binding.
405
; Zero timestamp means "not bound".
409
; Zero timestamp means "not bound".
-
 
410
; Timestamp 0xFFFFFFFF means "new-style binding".
406
; Mismatched timestamp means "stale binding".
411
; Mismatched timestamp means "stale binding".
407
; In both cases, go to 2g.
412
; In first and third cases, go to 9.
-
 
413
; In second case, go to 10 for further checks.
408
        mov     edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.TimeDateStamp]
414
        mov     edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.TimeDateStamp]
409
        test    edx, edx
415
        test    edx, edx
410
        jz      .resolve_normal_import
416
        jz      .resolve_generic
-
 
417
        cmp     edx, -1
-
 
418
        jz      .new_binding
411
        cmp     edx, [eax+MODULE.timestamp]
419
        cmp     edx, [eax+MODULE.timestamp]
412
        jnz     .resolve_normal_import
420
        jnz     .resolve_generic
413
; 2d. The descriptor has a non-stale old-style binding.
421
; 5. The descriptor has a non-stale old-style binding.
414
; There are two cases when we still need to do something:
422
; There are two cases when we still need to do something:
415
; * if the target module has been relocated, we need to add
423
; * if the target module has been relocated, we need to add
416
;   relocation delta to all addresses;
424
;   relocation delta to all addresses;
417
; * if some exports are forwarded, old-style binding cannot bind them:
425
; * if some exports are forwarded, we need to resolve them.
418
;   there is only one timestamp field, we can't verify timestamps
-
 
419
;   of forward targets.
-
 
420
;   Thunks for forwarded exports contain index of next forwarded export
426
;   Thunks for forwarded exports contain index of next forwarded export
421
;   instead of target address, making a single-linked list terminated by -1.
427
;   instead of target address, making a single-linked list terminated by -1.
422
;   ForwarderChain is the head of the list.
428
;   ForwarderChain is the head of the list.
423
; If both problems are present, we resort to 2g as if binding is stale,
429
; Check for the first problem first; the corresponding code can handle both.
424
; it shouldn't be encountered normally anyway: relocations should be avoided,
-
 
425
; and forwarded exports should be new-style bound.
-
 
426
; If the target module is not relocated, go to 2f.
430
; If the target module is relocated, go to 8.
427
; If the target module is relocated and there are no forwarded exports,
431
; If the target module is not relocated, but has forwarded exports, go to 7.
428
; advance to 2e.
432
; Otherwise, advance to 6.
-
 
433
.old_binding:
429
        cmp     [eax+MODULE.basedelta], 0
434
        cmp     [eax+MODULE.basedelta], 0
430
        jz      .normal_import_check_forwarders
435
        jnz     .old_binding_relocate
-
 
436
.check_forwarder_chain:
431
        cmp     [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain], -1
437
        cmp     [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain], -1
432
        jnz     .resolve_normal_import
438
        jnz     .resolve_forward_chain
433
; 2e. Binding is correct, but we need to add MODULE.basedelta
-
 
434
; to all imported addresses in FirstThunk array.
-
 
435
; For consistency with generic-case resolve_import_from_module,
-
 
436
; check for end of thunks by looking at OriginalFirstThunk array.
-
 
437
; After that, go to 2h.
439
.next_descriptor:
438
        mov     edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
-
 
439
        add     edx, [esi+MODULE.base]
440
; 6. Advance to next descriptor and continue the loop.
440
        mov     ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
441
        add     ebp, sizeof.IMAGE_IMPORT_DESCRIPTOR
441
        add     ebx, [esi+MODULE.base]
-
 
442
        mov     edi, [eax+MODULE.basedelta]
-
 
443
.normal_import_add_delta:
-
 
444
        cmp     dword [ebx], 0
-
 
445
        jz      .normal_import_next
442
        jmp     .descriptor_loop
446
        call    .ensure_writable ; should preserve esi,edi,ebp,ebx,edx
-
 
447
        add     dword [edx], edi
-
 
448
        add     edx, 4
-
 
449
        add     ebx, 4
-
 
450
        jmp     .normal_import_add_delta
-
 
451
.normal_import_check_forwarders:
443
.resolve_forward_chain:
452
; 2f. The target module is not relocated.
-
 
453
; Exports that are not forwarded are correct.
444
; 7. Resolve all thunks from ForwarderChain list.
454
; Go through ForwarderChain list and resolve all exports from it.
-
 
455
; After that, go to 2h.
-
 
456
        mov     edi, [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain]
-
 
457
        cmp     edi, -1
-
 
458
        jz      .normal_import_next ; don't prepare_import_from_module for empty list
-
 
459
        mov     eax, [import_module]
445
        mov     eax, [import_module]
460
        mov     eax, [eax+MODULE.base]
446
        mov     eax, [eax+MODULE.base]
461
        call    prepare_import_from_module
447
        call    prepare_import_from_module
-
 
448
        mov     edi, [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain]
462
.normal_import_forward_chain:
449
.resolve_forward_chain_loop:
463
        mov     ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
450
        mov     ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
464
        add     ebx, [esi+MODULE.base]
451
        add     ebx, [esi+MODULE.base]
465
        mov     ecx, [ebx+edi*4]
452
        mov     ecx, [ebx+edi*4]
466
        get_address_for_thunk ; should preserve esi,edi,ebp
453
        get_address_for_thunk ; should preserve esi,edi,ebp
467
        test    eax, eax
454
        test    eax, eax
Line 472... Line 459...
472
        lea     edx, [edx+edi*4]
459
        lea     edx, [edx+edi*4]
473
        call    .ensure_writable ; should preserve edx,ebx,esi,ebp
460
        call    .ensure_writable ; should preserve edx,ebx,esi,ebp
474
        mov     edi, [edx] ; next forwarded export
461
        mov     edi, [edx] ; next forwarded export
475
        mov     [edx], ebx ; store the address
462
        mov     [edx], ebx ; store the address
476
        cmp     edi, -1
463
        cmp     edi, -1
477
        jnz     .normal_import_forward_chain
464
        jnz     .resolve_forward_chain_loop
-
 
465
; After resolving, we are done with this import descriptor, go to 6.
-
 
466
        jmp     .next_descriptor
-
 
467
.done:
-
 
468
        call    .restore_protection
-
 
469
        xor     eax, eax
-
 
470
        ret
-
 
471
.old_binding_relocate:
-
 
472
; 8. The descriptor has a non-stale old-style binding,
-
 
473
; but the target module is relocated, so we need to add MODULE.basedelta to
-
 
474
; all addresses. Also, there can be forwarded exports.
-
 
475
; For consistency with generic-case resolve_import_from_module,
-
 
476
; check for end of thunks by looking at OriginalFirstThunk array.
-
 
477
; Note: we assume here that ForwarderChain list is ordered.
-
 
478
; After that, go to 6.
-
 
479
        mov     edi, [eax+MODULE.basedelta]
-
 
480
        cmp     [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain], -1
-
 
481
        jz      @f
-
 
482
        mov     eax, [import_module]
-
 
483
        mov     eax, [eax+MODULE.base]
-
 
484
        call    prepare_import_from_module
-
 
485
@@:
-
 
486
        mov     edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
-
 
487
        add     edx, [esi+MODULE.base]
-
 
488
        mov     ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
-
 
489
        add     ebx, [esi+MODULE.base]
-
 
490
        mov     eax, [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain]
-
 
491
        lea     eax, [edx+eax*4]
-
 
492
        mov     [next_forwarder], eax
-
 
493
.old_binding_relocate_loop:
-
 
494
        cmp     dword [ebx], 0
-
 
495
        jz      .next_descriptor
-
 
496
        call    .ensure_writable ; should preserve esi,edi,ebp,ebx,edx
-
 
497
        cmp     edx, [next_forwarder]
-
 
498
        jz      .old_binding_relocate_forwarder
-
 
499
        add     dword [edx], edi
-
 
500
.old_binding_relocate_next:
-
 
501
        add     edx, 4
-
 
502
        add     ebx, 4
-
 
503
        jmp     .old_binding_relocate_loop
-
 
504
.old_binding_relocate_forwarder:
-
 
505
        mov     ecx, [ebx]
-
 
506
        get_address_for_thunk
-
 
507
        test    eax, eax
-
 
508
        jz      .failed
-
 
509
        mov     edx, [next_forwarder]
-
 
510
        mov     ecx, [edx]
-
 
511
        mov     [edx], eax
-
 
512
        mov     eax, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
-
 
513
        add     eax, [esi+MODULE.base]
-
 
514
        lea     eax, [eax+ecx*4]
-
 
515
        mov     [next_forwarder], eax
478
        jmp     .normal_import_next
516
        jmp     .old_binding_relocate_next
479
.resolve_normal_import:
517
.resolve_generic:
480
; 2g. Run generic-case resolver.
518
; 9. Run generic-case resolver.
481
        mov     [import_descriptor], ebp
519
        mov     [import_descriptor], ebp
482
        resolve_import_from_module .failed ; should preserve esi
520
        resolve_import_from_module .failed ; should preserve esi
483
        mov     ebp, [import_descriptor]
521
        mov     ebp, [import_descriptor]
484
.normal_import_next:
522
; After that, go to 6.
485
; 2h. Advance to next descriptor and continue the loop.
-
 
486
        add     ebp, sizeof.IMAGE_IMPORT_DESCRIPTOR
-
 
487
        jmp     .normal_import_loop
523
        jmp     .next_descriptor
488
.bound_import:
524
.new_binding:
489
; 3. New-style bound import.
525
; New-style bound import.
-
 
526
; 10. Locate the new-style descriptor corresponding to the current
-
 
527
; import descriptor.
-
 
528
; 10a. Check the current new-style descriptor: the one that follows
-
 
529
; previous one, if there was the previous one, or the first one.
490
; Repeat 3a-3o for all descriptors in bound import directory.
530
; In most cases, new-style descriptors are in the same order as
-
 
531
; import descriptors, so full loop in 10b can be avoided.
491
        mov     [bound_import_dir], ebx
532
        mov     edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.Name]
492
        add     ebx, [esi+MODULE.base]
533
        add     edx, [esi+MODULE.base]
493
.bound_import_loop:
534
        mov     ebx, [bound_import_descriptor]
494
; 3a. Check whether this descriptor is an end mark with zero fields.
-
 
495
        movzx   edi, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName]
535
        movzx   edi, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName]
496
        mov     [bound_import_cur_module], edi
-
 
497
        test    edi, edi
536
        test    edi, edi
-
 
537
        jz      .look_new_binding_hard
-
 
538
        add     edi, [bound_import_dir]
-
 
539
        xor     ecx, ecx
-
 
540
@@:
-
 
541
        mov     al, [edx+ecx]
-
 
542
        cmp     al, [edi+ecx]
-
 
543
        jnz     .look_new_binding_hard
-
 
544
        test    al, al
-
 
545
        jz      .new_binding_found
-
 
546
        inc     ecx
498
        jz      .done
547
        jmp     @b
-
 
548
.look_new_binding_hard:
-
 
549
; 10b. We are out of luck with the current new-style descriptor,
-
 
550
; so loop over all of them looking for the matching one.
-
 
551
        mov     ebx, [bound_import_dir]
-
 
552
.look_new_binding_loop:
-
 
553
        movzx   edi, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName]
-
 
554
        add     edi, [bound_import_dir]
-
 
555
        xor     ecx, ecx
-
 
556
@@:
-
 
557
        mov     al, [edx+ecx]
-
 
558
        cmp     al, [edi+ecx]
-
 
559
        jnz     .look_new_binding_next
-
 
560
        test    al, al
-
 
561
        jz      .new_binding_found
-
 
562
        inc     ecx
-
 
563
        jmp     @b
-
 
564
.look_new_binding_next:
-
 
565
        movzx   ecx, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.NumberOfModuleForwarderRefs]
-
 
566
        lea     ebx, [ebx+(ecx+1)*sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR]
-
 
567
        jmp     .look_new_binding_loop
-
 
568
.new_binding_found:
-
 
569
; 10c. Store the next descriptor for subsequent scans.
-
 
570
        movzx   ecx, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.NumberOfModuleForwarderRefs]
-
 
571
        lea     eax, [ebx+(ecx+1)*sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR]
-
 
572
        mov     [bound_import_descriptor], eax
499
; Bound import descriptors come in groups.
573
; Bound import descriptors come in groups.
500
; The first descriptor in each group corresponds to the main imported module.
574
; The first descriptor in each group corresponds to the main imported module.
501
; If some exports from the module are forwarded, additional descriptors
575
; If some exports from the module are forwarded, additional descriptors
502
; are created for modules where those exports are forwarded to.
576
; are created for modules where those exports are forwarded to.
503
; Number of additional descriptors is given by one field in the first descriptor.
577
; Number of additional descriptors is given by one field in the first descriptor.
504
; 3b. Prepare for loop at 3c-3f with loading targets of all exports.
578
; 11. We have already loaded the main module, validate its timestamp.
505
; This includes the target module and all modules in chains of forwarded exports.
579
; If timestamp does not match, go to 9 to run generic-case resolver.
-
 
580
        mov     eax, [import_module]
-
 
581
        mov     edx, [eax+MODULE.timestamp]
506
        movzx   ebp, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.NumberOfModuleForwarderRefs]
582
        cmp     edx, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.TimeDateStamp]
507
        mov     [relocated_bound_modules_count], 0
583
        jnz     .resolve_generic
-
 
584
; 12. If there are no additional libraries,
-
 
585
; the situation is exactly same as old-style binding, so go to 5.
-
 
586
        test    ecx, ecx
-
 
587
        jz      .old_binding
-
 
588
; 13. Load additional libraries and validate their timestamps.
-
 
589
; If at least one timestamp is invalid, resort to generic-case resolving.
-
 
590
; 13a. Allocate memory for all bound modules, including the main module.
-
 
591
        lea     ecx, [(ecx+1)*4]
-
 
592
        stdcall malloc, ecx
-
 
593
        test    eax, eax
-
 
594
        jz      .failed
508
        mov     [relocated_bound_modules_ptr], 0
595
        mov     [bound_modules_ptr], eax
-
 
596
; 13b. Store the main module.
509
        mov     [import_module], 0
597
        mov     edx, [import_module]
510
.bound_import_forwarder_loop:
598
        mov     [eax], edx
511
; 3c. Load a referenced module.
599
        xor     ecx, ecx
512
; Names in bound import descriptors are relative to bound import directory,
600
; 13c. Loop over all additional descriptors.
-
 
601
.newstyle_load_loop:
513
; not RVAs.
602
        inc     ecx
-
 
603
        mov     [bound_modules_count], ecx
-
 
604
        movzx   edi, [ebx+ecx*sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName]
514
        add     edi, [bound_import_dir]
605
        add     edi, [bound_import_dir]
515
        call    load_imported_module ; should preserve ebx,esi,ebp
606
        call    load_imported_module ; should preserve ebx,esi,ebp
516
        test    eax, eax
607
        test    eax, eax
517
        jz      .bound_import_failed
608
        jz      .newstyle_failed
518
; The target module is first in the list.
609
        mov     ecx, [bound_modules_count]
-
 
610
        mov     edx, [ebx+ecx*sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR+IMAGE_BOUND_IMPORT_DESCRIPTOR.TimeDateStamp]
519
        cmp     [import_module], 0
611
        cmp     [eax+MODULE.timestamp], edx
520
        jnz     @f
612
        jnz     .newstyle_stale
521
        mov     [import_module], eax
613
        mov     edx, [bound_modules_ptr]
522
@@:
-
 
523
; 3d. Check whether timestamp in the descriptor matches module timestamp.
614
        mov     [edx+ecx*4], eax
524
; If not, go to 3h which after some preparations will resort to generic-case
615
        cmp     cx, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.NumberOfModuleForwarderRefs]
525
; resolve_import_from_module; in this case, we stop processing the group,
-
 
526
; resolve_import_from_module will take care about additional modules anyway.
-
 
527
        mov     edx, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.TimeDateStamp]
616
        jb      .newstyle_load_loop
528
        test    edx, edx
617
        inc     ecx
529
        jz      .bound_import_wrong_timestamp
618
        mov     [bound_modules_count], ecx
530
        cmp     edx, [eax+MODULE.timestamp]
619
; New-style binding has correct timestamp.
531
        jnz     .bound_import_wrong_timestamp
620
; There still can be same two problems as in step 5 with old-style binding.
532
; 3e. Collect all referenced modules that have been relocated.
621
; 14. Check whether at least one module is relocated. If so, go to 16.
-
 
622
.newstyle_check_reloc:
-
 
623
        mov     eax, [edx]
533
        cmp     [eax+MODULE.basedelta], 0
624
        cmp     [eax+MODULE.basedelta], 0
534
        jz      .bound_import_forwarder_next
-
 
535
        mov     edi, eax
-
 
536
; We don't want to reallocate too often, since reallocation
-
 
537
; may involve copying our data to a new place.
-
 
538
; We always reserve space that is a power of two; in this way,
-
 
539
; the wasted space is never greater than the used space,
-
 
540
; and total time of copying the data is O(number of modules).
-
 
541
        mov     eax, [relocated_bound_modules_ptr]
-
 
542
        mov     edx, [relocated_bound_modules_count]
-
 
543
; X is a power of two or zero if and only if (X and (X - 1)) is zero
-
 
544
        lea     ecx, [edx-1]
-
 
545
        test    ecx, edx
-
 
546
        jnz     .bound_import_norealloc
625
        jnz     .newstyle_need_reloc
547
; if the current size is zero, allocate 1 item,
-
 
548
; otherwise double number of items.
-
 
549
; Item size is 4 bytes.
-
 
550
        lea     edx, [edx*8]
-
 
551
        test    edx, edx
-
 
552
        jnz     @f
-
 
553
        mov     edx, 4
626
        add     edx, 4
554
@@:
-
 
555
        stdcall realloc, [relocated_bound_modules_ptr], edx
-
 
556
        test    eax, eax
-
 
557
        jz      .bound_import_failed
-
 
558
        mov     [relocated_bound_modules_ptr], eax
-
 
559
.bound_import_norealloc:
-
 
560
        mov     edx, [relocated_bound_modules_count]
-
 
561
        inc     [relocated_bound_modules_count]
-
 
562
        mov     [eax+edx*4], edi
-
 
563
.bound_import_forwarder_next:
-
 
564
; 3f. Advance to the next descriptor in the group.
-
 
565
        add     ebx, sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR
-
 
566
        movzx   edi, [ebx+IMAGE_BOUND_IMPORT_DESCRIPTOR.OffsetModuleName]
-
 
567
        dec     ebp
627
        dec     ecx
568
        jns     .bound_import_forwarder_loop
628
        jnz     .newstyle_check_reloc
569
; 3g. All timestamps are correct.
629
; 15. Bound modules are not relocated.
570
; If all targets are not relocated, then we have nothing to do
630
; The only remaining problem could be unbound forwarders.
571
; with exports from the current module, so continue loop at 3a;
631
; Free memory allocated at 13a and let steps 6 and 7 do their work.
572
; ebx already points to the next descriptor.
-
 
573
; Otherwise, go to 3i.
-
 
574
        cmp     [relocated_bound_modules_count], 0
632
        stdcall free, [bound_modules_ptr]
575
        jz      .bound_import_loop
-
 
576
        jmp     .bound_import_fix
633
        jmp     .check_forwarder_chain
577
.bound_import_wrong_timestamp:
-
 
578
; 3h. We have aborted the loop over the group;
-
 
579
; advance ebx so that it points to the first descriptor of the next group,
-
 
580
; make a mark so that 3l will know that we need to reimport everything.
-
 
581
; We don't need [relocated_bound_modules_count] in this case anymore,
-
 
582
; use zero value as a mark.
-
 
583
        lea     ebx, [ebx+(ebp+1)*sizeof.IMAGE_BOUND_IMPORT_DESCRIPTOR]
-
 
584
        mov     [relocated_bound_modules_count], 0
-
 
585
.bound_import_fix:
634
.newstyle_stale:
586
; 3i. We need to do something with exported addresses.
-
 
587
; Find corresponding import descriptors; there can be more than one.
-
 
588
; Repeat 3j-3n for all import descriptors.
-
 
589
        mov     ebp, [import_dir]
-
 
590
        add     ebp, [esi+MODULE.base]
-
 
591
.look_related_descriptors:
-
 
592
; 3j. Check whether we have reached end of import table.
-
 
593
; If so, go to 3o.
-
 
594
        mov     edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.Name]
-
 
595
        test    edx, edx
-
 
596
        jz      .bound_import_next
-
 
597
; 3k. Check whether the current import descriptor matches the current
-
 
598
; bound import descriptor. Check Name fields.
-
 
599
; If so, advance to 3l.
-
 
600
; Otherwise, advance to the next import descriptor and return to 3j.
-
 
601
        add     edx, [esi+MODULE.base]
-
 
602
        mov     edi, [bound_import_cur_module]
635
        stdcall free, [bound_modules_ptr]
603
@@:
-
 
604
        mov     al, [edx]
-
 
605
        cmp     [edi], al
-
 
606
        jnz     .next_related_descriptor
-
 
607
        test    al, al
-
 
608
        jz      .found_related_descriptor
-
 
609
        inc     edx
-
 
610
        inc     edi
-
 
611
        jmp     @b
-
 
612
.next_related_descriptor_restore:
-
 
613
        mov     ebp, [import_descriptor]
-
 
614
.next_related_descriptor:
-
 
615
        add     ebp, sizeof.IMAGE_IMPORT_DESCRIPTOR
-
 
616
        jmp     .look_related_descriptors
636
        jmp     .resolve_generic
617
.found_related_descriptor:
-
 
618
; 3l. Check what we should do:
-
 
619
; advance to 3m, if we need to reimport everything,
637
; 16. The descriptor has a non-stale new-style binding,
620
; go to 3n, if we just need to relocate something.
638
; but at least one of target modules is relocated, so we need to add
621
        mov     [import_descriptor], ebp
-
 
622
        cmp     [relocated_bound_modules_count], 0
-
 
623
        jnz     .bound_import_add_delta
-
 
624
; 3m. Apply resolve_import_from_module and return to 3j.
639
; MODULE.basedelta to addresses from relocated modules.
625
        resolve_import_from_module .bound_import_failed ; should preserve ebx,esi
-
 
626
        jmp     .next_related_descriptor_restore
-
 
627
.bound_import_add_delta:
-
 
628
; 3n. Loop over all imported symbols.
640
; Also, there can be forwarded exports.
629
; For every imported symbol, check whether it fits within one of relocated
-
 
630
; modules, and if so, apply relocation to it.
-
 
631
; For consistency with generic-case resolve_import_from_module,
641
; For consistency with generic-case resolve_import_from_module,
632
; determine end of thunks from OriginalFirstThunk array.
642
; check for end of thunks by looking at OriginalFirstThunk array.
-
 
643
; Note: we assume here that ForwarderChain list is ordered.
-
 
644
; After that, go to 6.
-
 
645
.newstyle_need_reloc:
-
 
646
        mov     eax, [import_module]
-
 
647
        mov     eax, [eax+MODULE.base]
-
 
648
        call    prepare_import_from_module
633
        mov     edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
649
        mov     edx, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
634
        add     edx, [esi+MODULE.base]
650
        add     edx, [esi+MODULE.base]
635
        mov     ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
651
        mov     ebx, [ebp+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
636
        add     ebx, [esi+MODULE.base]
652
        add     ebx, [esi+MODULE.base]
-
 
653
        mov     eax, [ebp+IMAGE_IMPORT_DESCRIPTOR.ForwarderChain]
-
 
654
        lea     eax, [edx+eax*4]
-
 
655
        mov     [next_forwarder], eax
637
.bound_import_add_delta_loop:
656
.new_binding_relocate_loop:
638
        cmp     dword [ebx], 0
657
        cmp     dword [ebx], 0
639
        jz      .next_related_descriptor_restore
658
        jz      .new_binding_relocate_done
-
 
659
        cmp     edx, [next_forwarder]
-
 
660
        jz      .new_binding_resolve_thunk
640
        mov     ecx, [relocated_bound_modules_ptr]
661
        mov     [bound_module], 0
641
        mov     ebp, [relocated_bound_modules_count]
662
        mov     eax, [bound_modules_count]
-
 
663
        mov     [bound_modules_left], eax
642
        push    esi
664
        mov     edi, [bound_modules_ptr]
-
 
665
; There should be at least one module containing address [edx].
-
 
666
; There can be more than one if preferred address ranges for two modules intersect;
-
 
667
; in this case, we are forced to resolve address from scratch.
643
.find_delta_module:
668
.new_binding_lookup_module:
644
        mov     esi, [ecx]
669
        mov     ecx, [edx]
645
        mov     eax, [edx]
670
        mov     eax, [edi]
646
        sub     eax, [esi+MODULE.base]
671
        sub     ecx, [eax+MODULE.base]
647
        add     eax, [esi+MODULE.basedelta]
672
        add     ecx, [eax+MODULE.basedelta]
648
        cmp     eax, [esi+MODULE.size]
673
        cmp     ecx, [eax+MODULE.size]
-
 
674
        jae     @f
649
        jb      .found_delta_module
675
        cmp     [bound_module], 0
-
 
676
        jnz     .new_binding_resolve_thunk
-
 
677
        mov     [bound_module], eax
-
 
678
@@:
650
        add     ecx, 4
679
        add     edi, 4
651
        dec     ebp
680
        dec     [bound_modules_left]
652
        jnz     .find_delta_module
681
        jnz     .new_binding_lookup_module
-
 
682
        mov     edi, [bound_module]
-
 
683
        mov     edi, [edi+MODULE.basedelta]
653
        pop     esi
684
        test    edi, edi
654
.bound_import_add_delta_next:
685
        jz      .new_binding_relocate_next
-
 
686
        call    .ensure_writable ; should preserve esi,edi,ebp,ebx,edx
655
        add     ebx, 4
687
        add     dword [edx], edi
-
 
688
.new_binding_relocate_next:
656
        add     edx, 4
689
        add     edx, 4
-
 
690
        add     ebx, 4
657
        jmp     .bound_import_add_delta_loop
691
        jmp     .new_binding_relocate_loop
658
.found_delta_module:
692
.new_binding_resolve_thunk:
659
        mov     ebp, [esi+MODULE.basedelta]
693
        mov     [bound_modules_left], edx
-
 
694
        call    .ensure_writable
660
        pop     esi
695
        mov     ecx, [ebx]
661
        call    .ensure_writable ; should preserve esi,ebp,ebx,edx
696
        get_address_for_thunk
662
        add     [edx], ebp
697
        test    eax, eax
-
 
698
        jz      .newstyle_failed
663
        jmp     .bound_import_add_delta_next
699
        mov     edx, [bound_modules_left]
664
.bound_import_next:
700
        mov     ecx, [edx]
665
; 3o. Free the data we might have allocated and return to 3a.
701
        mov     [edx], eax
666
        cmp     [relocated_bound_modules_ptr], 0
702
        cmp     edx, [next_forwarder]
667
        jz      .bound_import_loop
703
        jnz     .new_binding_relocate_next
668
        stdcall free, [relocated_bound_modules_ptr]
704
        mov     eax, [ebp+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
669
        jmp     .bound_import_loop
705
        add     eax, [esi+MODULE.base]
670
.done:
-
 
671
        call    .restore_protection
706
        lea     eax, [eax+ecx*4]
672
        xor     eax, eax
707
        mov     [next_forwarder], eax
673
        ret
708
        jmp     .new_binding_relocate_next
674
.bound_import_failed:
709
.new_binding_relocate_done:
675
        cmp     [relocated_bound_modules_ptr], 0
710
        stdcall free, [bound_modules_ptr]
676
        jz      .failed
711
        jmp     .next_descriptor
-
 
712
.newstyle_failed:
677
        stdcall free, [relocated_bound_modules_ptr]
713
        stdcall free, [bound_modules_ptr]
678
.failed:
714
.failed:
679
        call    .restore_protection
715
        call    .restore_protection
680
        xor     eax, eax
716
        xor     eax, eax
681
        dec     eax
717
        dec     eax
682
        ret
718
        ret
Line 795... Line 831...
795
        cmp     byte [eax], 'M'
831
        cmp     byte [eax], 'M'
796
        jz      .parse_mz
832
        jz      .parse_mz
797
        cmp     [eax+STRIPPED_PE_HEADER.NumberOfRvaAndSizes], SPE_DIRECTORY_EXPORT
833
        cmp     [eax+STRIPPED_PE_HEADER.NumberOfRvaAndSizes], SPE_DIRECTORY_EXPORT
798
        jbe     .noexport
834
        jbe     .noexport
799
        mov     edx, [eax+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.VirtualAddress]
835
        mov     edx, [eax+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.VirtualAddress]
-
 
836
        test    edx, edx
-
 
837
        jz      .noexport
800
        add     edx, eax
838
        add     edx, eax
801
        mov     [export_ptr], edx
839
        mov     [export_ptr], edx
802
        mov     edx, [eax+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.isize]
840
        mov     edx, [eax+sizeof.STRIPPED_PE_HEADER+SPE_DIRECTORY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY+IMAGE_DATA_DIRECTORY.isize]
803
        mov     [export_size], edx
841
        mov     [export_size], edx
804
        ret
842
        ret
Line 806... Line 844...
806
        mov     ecx, [eax+3Ch]
844
        mov     ecx, [eax+3Ch]
807
        add     ecx, eax
845
        add     ecx, eax
808
        cmp     [ecx+IMAGE_NT_HEADERS.OptionalHeader.NumberOfDirectories], IMAGE_DIRECTORY_ENTRY_EXPORT
846
        cmp     [ecx+IMAGE_NT_HEADERS.OptionalHeader.NumberOfDirectories], IMAGE_DIRECTORY_ENTRY_EXPORT
809
        jbe     .noexport
847
        jbe     .noexport
810
        mov     edx, [ecx+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress+IMAGE_DIRECTORY_ENTRY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY]
848
        mov     edx, [ecx+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress+IMAGE_DIRECTORY_ENTRY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY]
-
 
849
        test    edx, edx
-
 
850
        jz      .noexport
811
        add     edx, eax
851
        add     edx, eax
812
        mov     [export_ptr], edx
852
        mov     [export_ptr], edx
813
        mov     edx, [ecx+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.isize+IMAGE_DIRECTORY_ENTRY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY]
853
        mov     edx, [ecx+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.isize+IMAGE_DIRECTORY_ENTRY_EXPORT*sizeof.IMAGE_DATA_DIRECTORY]
814
        mov     [export_size], edx
854
        mov     [export_size], edx
815
        ret
855
        ret
Line 883... Line 923...
883
        mov     edi, [ebx+edx*4]
923
        mov     edi, [ebx+edx*4]
884
        add     edi, [export_base]
924
        add     edi, [export_base]
885
        push    ecx esi
925
        push    ecx esi
886
        repz cmpsb
926
        repz cmpsb
887
        pop     esi ecx
927
        pop     esi ecx
888
        jz      .found
928
        jz      .hint_ok
889
.ignore_hint:
929
.ignore_hint:
890
; 4. Binary search over name table.
930
; 4. Binary search over name table.
891
; Export names are sorted with respect to repz cmpsb.
931
; Export names are sorted with respect to repz cmpsb.
892
; edi <= (the target index) < edx
932
; edi <= (the target index) < edx
893
        xor     edi, edi
933
        xor     edi, edi
Line 919... Line 959...
919
        mov     edx, eax
959
        mov     edx, eax
920
        jmp     .export_name_search.loop
960
        jmp     .export_name_search.loop
921
; Generic error handler.
961
; Generic error handler.
922
.export_name_not_found:
962
.export_name_not_found:
923
        mov     ebx, esi
963
        mov     ebx, esi
924
        mov     esi, [module]
-
 
925
        test    esi, esi
-
 
926
        jnz     @f
-
 
927
        mutex_lock modules_mutex
-
 
928
        mov     ecx, [export_base]
-
 
929
        call    find_module_by_addr
964
        call    .get_module_name
930
        mutex_unlock modules_mutex
-
 
931
@@:
-
 
932
        mov     eax, msg_unknown
-
 
933
        test    esi, esi
-
 
934
        jz      @f
-
 
935
        mov     eax, [esi+MODULE.filename]
-
 
936
@@:
-
 
937
        ccall   loader_say_error, msg_export_name_not_found, ebx, msg_export_not_found, eax, 0
965
        ccall   loader_say_error, msg_export_name_not_found, ebx, msg_export_not_found, eax, 0
938
.return0:
966
.return0:
939
        xor     eax, eax
967
        xor     eax, eax
940
        ret
968
        ret
-
 
969
.hint_ok:
-
 
970
        mov     eax, edx
941
.found:
971
.found:
942
; 5. We have found an index in AddressOfNames/AddressOfNameOrdinals arrays,
972
; 5. We have found an index in AddressOfNames/AddressOfNameOrdinals arrays,
943
; convert it to index in AddressOfFunctions array.
973
; convert it to index in AddressOfFunctions array.
944
        mov     edx, [export_ptr]
974
        mov     edx, [export_ptr]
945
        mov     ebx, [edx+IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals]
975
        mov     ebx, [edx+IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals]
Line 956... Line 986...
956
.check_forwarded:
986
.check_forwarded:
957
; This part of code is also used by get_exported_function_by_ordinal.
987
; This part of code is also used by get_exported_function_by_ordinal.
958
; 7. Check whether the address is inside the export directory.
988
; 7. Check whether the address is inside the export directory.
959
; If not, we are done.
989
; If not, we are done.
960
        add     eax, [export_base]
990
        add     eax, [export_base]
961
        mov     esi, eax
991
        mov     ebx, eax
962
        sub     esi, edx
992
        sub     ebx, edx
963
        cmp     esi, [export_size]
993
        cmp     ebx, [export_size]
964
        jb      .export_is_forwarded
994
        jb      .export_is_forwarded
965
        ret
995
        ret
966
.export_is_forwarded:
996
.export_is_forwarded:
967
; The export is forwarded to another module.
997
; The export is forwarded to another module.
968
; The address we have got points to the string "."
998
; The address we have got points to the string "."
Line 974... Line 1004...
974
        inc     eax
1004
        inc     eax
975
        cmp     byte [eax-1], '.'
1005
        cmp     byte [eax-1], '.'
976
        jz      .dot_found
1006
        jz      .dot_found
977
        cmp     byte [eax-1], 0
1007
        cmp     byte [eax-1], 0
978
        jnz     @b
1008
        jnz     @b
979
        jmp     .export_name_not_found
1009
        call    .get_module_name
-
 
1010
        ccall   loader_say_error, msg_invalid_forwarder, eax, 0
-
 
1011
        xor     eax, eax
-
 
1012
        ret
980
.dot_found:
1013
.dot_found:
981
; 8b. Allocate the memory.
1014
; 8b. Allocate the memory.
982
        sub     eax, ebx
1015
        sub     eax, ebx
983
        mov     edi, eax
1016
        mov     edi, eax
984
        add     eax, 4 ; dll + terminating zero
1017
        add     eax, 4 ; dll + terminating zero
Line 1055... Line 1088...
1055
        mutex_unlock modules_mutex
1088
        mutex_unlock modules_mutex
1056
@@:
1089
@@:
1057
        stdcall free, edi
1090
        stdcall free, edi
1058
        xor     eax, eax
1091
        xor     eax, eax
1059
        ret
1092
        ret
-
 
1093
 
-
 
1094
        fpo_delta = fpo_delta + 4
-
 
1095
.get_module_name:
-
 
1096
        mov     esi, [module]
-
 
1097
        test    esi, esi
-
 
1098
        jnz     @f
-
 
1099
        mutex_lock modules_mutex
-
 
1100
        mov     ecx, [export_base]
-
 
1101
        call    find_module_by_addr
-
 
1102
        mutex_unlock modules_mutex
-
 
1103
@@:
-
 
1104
        mov     eax, msg_unknown
-
 
1105
        test    esi, esi
-
 
1106
        jz      @f
-
 
1107
        mov     eax, [esi+MODULE.filename]
-
 
1108
@@:
-
 
1109
        retn
1060
endp
1110
endp
Line 1061... Line 1111...
1061
 
1111
 
1062
; Resolve symbol from a module by name.
1112
; Resolve symbol from a module by name.
1063
; prepare_import_from_module should be called beforehand.
1113
; prepare_import_from_module should be called beforehand.