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