1# REQUIRES: x86 2# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj 3# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:noref -entry:main 4# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-NOGC 5# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:noref -entry:main -debug:dwarf 6# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-NOGC 7# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:ref -entry:main 8# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-GC 9 10# This assembly is meant to mimic what CL emits for this kind of C code when 11# /Gw (-fdata-sections) is enabled: 12# int f() { return 42; } 13# int g() { return 13; } 14# int (*fp1)() = &f; 15# int (*fp2)() = &g; 16# int main() { 17# return fp1(); 18# } 19# Compile with 'cl -c -guard:cf -Gw -O1' and note the two associative .gfids$y 20# sections. 21 22# Expect 3 entries: main, f, and g. 23 24# CHECK-NOGC: ImageBase: 0x140000000 25# CHECK-NOGC: LoadConfig [ 26# CHECK-NOGC: SEHandlerTable: 0x0 27# CHECK-NOGC: SEHandlerCount: 0 28# CHECK-NOGC: GuardCFCheckFunction: 0x0 29# CHECK-NOGC: GuardCFCheckDispatch: 0x0 30# CHECK-NOGC: GuardCFFunctionTable: 0x14000{{.*}} 31# CHECK-NOGC: GuardCFFunctionCount: 3 32# CHECK-NOGC: GuardFlags: 0x500 33# CHECK-NOGC: GuardAddressTakenIatEntryTable: 0x0 34# CHECK-NOGC: GuardAddressTakenIatEntryCount: 0 35# CHECK-NOGC: GuardLongJumpTargetTable: 0x0 36# CHECK-NOGC: GuardLongJumpTargetCount: 0 37# CHECK-NOGC: ] 38# CHECK-NOGC: GuardFidTable [ 39# CHECK-NOGC-NEXT: 0x14000{{.*}} 40# CHECK-NOGC-NEXT: 0x14000{{.*}} 41# CHECK-NOGC-NEXT: 0x14000{{.*}} 42# CHECK-NOGC-NEXT: ] 43 44# Expect 2 entries: main and f. fp2 was discarded, so g was only used as a 45# direct call target. 46 47# CHECK-GC: ImageBase: 0x140000000 48# CHECK-GC: LoadConfig [ 49# CHECK-GC: SEHandlerTable: 0x0 50# CHECK-GC: SEHandlerCount: 0 51# CHECK-GC: GuardCFCheckFunction: 0x0 52# CHECK-GC: GuardCFCheckDispatch: 0x0 53# CHECK-GC: GuardCFFunctionTable: 0x14000{{.*}} 54# CHECK-GC: GuardCFFunctionCount: 2 55# CHECK-GC: GuardFlags: 0x500 56# CHECK-GC: GuardAddressTakenIatEntryTable: 0x0 57# CHECK-GC: GuardAddressTakenIatEntryCount: 0 58# CHECK-GC: GuardLongJumpTargetTable: 0x0 59# CHECK-GC: GuardLongJumpTargetCount: 0 60# CHECK-GC: ] 61# CHECK-GC: GuardFidTable [ 62# CHECK-GC-NEXT: 0x14000{{.*}} 63# CHECK-GC-NEXT: 0x14000{{.*}} 64# CHECK-GC-NEXT: ] 65 66 67# We need @feat.00 to have 0x800 to indicate .gfids are present. 68 .def @feat.00; 69 .scl 3; 70 .type 0; 71 .endef 72 .globl @feat.00 73@feat.00 = 0x801 74 75 .def main; 76 .scl 2; 77 .type 32; 78 .endef 79 .section .text,"xr",one_only,main 80 .globl main 81main: 82 # Call g directly so that it is not dead stripped. 83 callq g 84 rex64 jmpq *fp1(%rip) 85 86 .def f; 87 .scl 3; 88 .type 32; 89 .endef 90 .section .text,"xr",one_only,f 91f: 92 movl $42, %eax 93 retq 94 95 .section .data,"dw",one_only,fp1 96 .globl fp1 97fp1: 98 .quad f 99 100 .section .gfids$y,"dr",associative,fp1 101 .symidx f 102 103# Section GC will remove the following, so 'g' should not be present in the 104# guard fid table. 105 106 .def g; 107 .scl 3; 108 .type 32; 109 .endef 110 .section .text,"xr",one_only,g 111g: 112 movl $13, %eax 113 retq 114 115 .section .data,"dw",one_only,fp2 116 .globl fp2 117fp2: 118 .quad g 119 120 .section .gfids$y,"dr",associative,fp2 121 .symidx g 122 123 .section .rdata,"dr" 124.globl _load_config_used 125_load_config_used: 126 .long 256 127 .fill 124, 1, 0 128 .quad __guard_fids_table 129 .quad __guard_fids_count 130 .long __guard_flags 131 .fill 128, 1, 0 132