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