1# REQUIRES: x86 2 3# Make a DLL that exports exportfn1. 4# RUN: yaml2obj %p/Inputs/export.yaml -o %basename_t-exp.obj 5# RUN: lld-link /out:%basename_t-exp.dll /dll %basename_t-exp.obj /export:exportfn1 /implib:%basename_t-exp.lib 6 7# Make an object file that imports exportfn1. 8# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %basename_t.obj 9 10# Check that the Guard address-taken IAT entry tables are propagated to the final executable. 11# RUN: lld-link %basename_t.obj -guard:cf -entry:main -out:%basename_t-nodelay.exe %basename_t-exp.lib 12# RUN: llvm-readobj --file-headers --coff-load-config %basename_t-nodelay.exe | FileCheck %s --check-prefix CHECK 13 14# CHECK: ImageBase: 0x140000000 15# CHECK: LoadConfig [ 16# CHECK: GuardCFFunctionTable: 0x140002114 17# CHECK: GuardCFFunctionCount: 1 18# CHECK: GuardFlags: 0x10500 19# CHECK: GuardAddressTakenIatEntryTable: 0x140002118 20# CHECK: GuardAddressTakenIatEntryCount: 1 21# CHECK: ] 22# CHECK: GuardFidTable [ 23# CHECK-NEXT: 0x14000{{.*}} 24# CHECK-NEXT: ] 25# CHECK: GuardIatTable [ 26# CHECK-NEXT: 0x14000{{.*}} 27# CHECK-NEXT: ] 28 29 30# Check that the additional load thunk symbol is added to the GFIDs table. 31# RUN: lld-link %basename_t.obj -guard:cf -entry:main -out:%basename_t-delay.exe %basename_t-exp.lib -alternatename:__delayLoadHelper2=main -delayload:%basename_t-exp.dll 32# RUN: llvm-readobj --file-headers --coff-load-config %basename_t-delay.exe | FileCheck %s --check-prefix DELAY-CHECK 33 34# DELAY-CHECK: ImageBase: 0x140000000 35# DELAY-CHECK: LoadConfig [ 36# DELAY-CHECK: GuardCFFunctionTable: 0x140002114 37# DELAY-CHECK: GuardCFFunctionCount: 2 38# DELAY-CHECK: GuardFlags: 0x10500 39# DELAY-CHECK: GuardAddressTakenIatEntryTable: 0x14000211C 40# DELAY-CHECK: GuardAddressTakenIatEntryCount: 1 41# DELAY-CHECK: ] 42# DELAY-CHECK: GuardFidTable [ 43# DELAY-CHECK-NEXT: 0x14000{{.*}} 44# DELAY-CHECK-NEXT: 0x14000{{.*}} 45# DELAY-CHECK-NEXT: ] 46# DELAY-CHECK: GuardIatTable [ 47# DELAY-CHECK-NEXT: 0x14000{{.*}} 48# DELAY-CHECK-NEXT: ] 49 50 51# This assembly is reduced from C code like: 52# __declspec(noinline) 53# void IndirectCall(BOOL (func)(HANDLE)) { 54# (*func)(NULL); 55# } 56# int main(int argc, char** argv) { 57# IndirectCall(exportfn1); 58# } 59 60 .text 61 .def @feat.00; 62 .scl 3; 63 .type 0; 64 .endef 65 .globl @feat.00 66.set @feat.00, 2048 67 .def IndirectCall; .scl 2; .type 32; .endef 68 .globl IndirectCall # -- Begin function IndirectCall 69 .p2align 4, 0x90 70IndirectCall: # @IndirectCall 71# %bb.0: 72 subq $40, %rsp 73 movq %rcx, 32(%rsp) 74 movq 32(%rsp), %rax 75 movq %rax, %rdx # This would otherwise be: movq __guard_dispatch_icall_fptr(%rip), %rdx 76 xorl %ecx, %ecx 77 callq *%rdx 78 nop 79 addq $40, %rsp 80 retq 81 # -- End function 82 .def main; .scl 2; .type 32; .endef 83 .globl main # -- Begin function main 84 .p2align 4, 0x90 85main: # @main 86# %bb.0: 87 subq $56, %rsp 88 movq __imp_exportfn1(%rip), %rax 89 movq %rdx, 48(%rsp) 90 movl %ecx, 44(%rsp) 91 movq %rax, %rcx 92 callq IndirectCall 93 xorl %eax, %eax 94 addq $56, %rsp 95 retq 96 # -- End function 97 .section .gfids$y,"dr" 98 .section .giats$y,"dr" 99 .symidx __imp_exportfn1 100 .section .gljmp$y,"dr" 101 102# Load configuration directory entry (winnt.h _IMAGE_LOAD_CONFIG_DIRECTORY64). 103# The linker will define the __guard_* symbols. 104 .section .rdata,"dr" 105.globl _load_config_used 106_load_config_used: 107 .long 256 108 .fill 124, 1, 0 109 .quad __guard_fids_table 110 .quad __guard_fids_count 111 .long __guard_flags 112 .fill 12, 1, 0 113 .quad __guard_iat_table 114 .quad __guard_iat_count 115 .quad __guard_longjmp_table 116 .quad __guard_fids_count 117 .fill 84, 1, 0