| # REQUIRES: x86 |
| |
| # Make a DLL that exports exportfn1. |
| # RUN: yaml2obj %p/Inputs/export.yaml -o %basename_t-exp.obj |
| # RUN: lld-link /out:%basename_t-exp.dll /dll %basename_t-exp.obj /export:exportfn1 /implib:%basename_t-exp.lib |
| |
| # Make an object file that imports exportfn1. |
| # RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %basename_t.obj |
| |
| # Check that the Guard address-taken IAT entry tables are propagated to the final executable. |
| # RUN: lld-link %basename_t.obj -guard:cf -guard:longjmp -entry:main -out:%basename_t-nodelay.exe %basename_t-exp.lib |
| # RUN: llvm-readobj --file-headers --coff-load-config %basename_t-nodelay.exe | FileCheck %s --check-prefix CHECK |
| |
| # CHECK: ImageBase: 0x140000000 |
| # CHECK: LoadConfig [ |
| # CHECK: GuardCFFunctionTable: 0x140002114 |
| # CHECK: GuardCFFunctionCount: 1 |
| # CHECK: GuardFlags: 0x10500 |
| # CHECK: GuardAddressTakenIatEntryTable: 0x140002118 |
| # CHECK: GuardAddressTakenIatEntryCount: 1 |
| # CHECK: ] |
| # CHECK: GuardFidTable [ |
| # CHECK-NEXT: 0x14000{{.*}} |
| # CHECK-NEXT: ] |
| # CHECK: GuardIatTable [ |
| # CHECK-NEXT: 0x14000{{.*}} |
| # CHECK-NEXT: ] |
| |
| |
| # Check that the additional load thunk symbol is added to the GFIDs table. |
| # RUN: lld-link %basename_t.obj -guard:cf -guard:longjmp -entry:main -out:%basename_t-delay.exe %basename_t-exp.lib -alternatename:__delayLoadHelper2=main -delayload:%basename_t-exp.dll |
| # RUN: llvm-readobj --file-headers --coff-load-config %basename_t-delay.exe | FileCheck %s --check-prefix DELAY-CHECK |
| |
| # DELAY-CHECK: ImageBase: 0x140000000 |
| # DELAY-CHECK: LoadConfig [ |
| # DELAY-CHECK: GuardCFFunctionTable: 0x140002114 |
| # DELAY-CHECK: GuardCFFunctionCount: 2 |
| # DELAY-CHECK: GuardFlags: 0x10500 |
| # DELAY-CHECK: GuardAddressTakenIatEntryTable: 0x14000211C |
| # DELAY-CHECK: GuardAddressTakenIatEntryCount: 1 |
| # DELAY-CHECK: ] |
| # DELAY-CHECK: GuardFidTable [ |
| # DELAY-CHECK-NEXT: 0x14000{{.*}} |
| # DELAY-CHECK-NEXT: 0x14000{{.*}} |
| # DELAY-CHECK-NEXT: ] |
| # DELAY-CHECK: GuardIatTable [ |
| # DELAY-CHECK-NEXT: 0x14000{{.*}} |
| # DELAY-CHECK-NEXT: ] |
| |
| |
| # This assembly is reduced from C code like: |
| # __declspec(noinline) |
| # void IndirectCall(BOOL (func)(HANDLE)) { |
| # (*func)(NULL); |
| # } |
| # int main(int argc, char** argv) { |
| # IndirectCall(exportfn1); |
| # } |
| |
| .text |
| .def @feat.00; |
| .scl 3; |
| .type 0; |
| .endef |
| .globl @feat.00 |
| .set @feat.00, 2048 |
| .def IndirectCall; .scl 2; .type 32; .endef |
| .globl IndirectCall # -- Begin function IndirectCall |
| .p2align 4, 0x90 |
| IndirectCall: # @IndirectCall |
| # %bb.0: |
| subq $40, %rsp |
| movq %rcx, 32(%rsp) |
| movq 32(%rsp), %rax |
| movq %rax, %rdx # This would otherwise be: movq __guard_dispatch_icall_fptr(%rip), %rdx |
| xorl %ecx, %ecx |
| callq *%rdx |
| nop |
| addq $40, %rsp |
| retq |
| # -- End function |
| .def main; .scl 2; .type 32; .endef |
| .globl main # -- Begin function main |
| .p2align 4, 0x90 |
| main: # @main |
| # %bb.0: |
| subq $56, %rsp |
| movq __imp_exportfn1(%rip), %rax |
| movq %rdx, 48(%rsp) |
| movl %ecx, 44(%rsp) |
| movq %rax, %rcx |
| callq IndirectCall |
| xorl %eax, %eax |
| addq $56, %rsp |
| retq |
| # -- End function |
| .section .gfids$y,"dr" |
| .section .giats$y,"dr" |
| .symidx __imp_exportfn1 |
| .section .gljmp$y,"dr" |
| |
| # Load configuration directory entry (winnt.h _IMAGE_LOAD_CONFIG_DIRECTORY64). |
| # The linker will define the __guard_* symbols. |
| .section .rdata,"dr" |
| .globl _load_config_used |
| _load_config_used: |
| .long 256 |
| .fill 124, 1, 0 |
| .quad __guard_fids_table |
| .quad __guard_fids_count |
| .long __guard_flags |
| .fill 12, 1, 0 |
| .quad __guard_iat_table |
| .quad __guard_iat_count |
| .quad __guard_longjmp_table |
| .quad __guard_fids_count |
| .fill 84, 1, 0 |