forked from OSchip/llvm-project
132 lines
3.8 KiB
ArmAsm
132 lines
3.8 KiB
ArmAsm
# REQUIRES: x86
|
|
# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj
|
|
# RUN: lld-link %t.obj -guard:cf -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 -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 -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: 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: 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
|