From c103156c606d76b4f1a8d424b2f37a423ad34c47 Mon Sep 17 00:00:00 2001 From: Bob Haarman Date: Thu, 28 Jun 2018 15:22:40 +0000 Subject: [PATCH] lld-link: align sections to 16 bytes if referenced from the gfids table Summary: Control flow guard works best when targets it checks are 16-byte aligned. Microsoft's link.exe helps ensure this by aligning code from sections that are referenced from the gfids table to 16 bytes when linking with -guard:cf, even if the original section specifies a smaller alignment. This change implements that behavior in lld-link. See https://crbug.com/857012 for more details. Reviewers: ruiu, hans, thakis, zturner Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D48690 llvm-svn: 335864 --- lld/COFF/Writer.cpp | 5 +++ lld/test/COFF/Inputs/guardcf-align-foobar.yaml | 51 ++++++++++++++++++++++++++ lld/test/COFF/guardcf-align.s | 45 +++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 lld/test/COFF/Inputs/guardcf-align-foobar.yaml create mode 100644 lld/test/COFF/guardcf-align.s diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index efb471e..a9950e4 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -1045,6 +1045,11 @@ void Writer::createGuardCFTables() { if (Config->Entry) addSymbolToRVASet(AddressTakenSyms, cast(Config->Entry)); + // Ensure sections referenced in the gfid table are 16-byte aligned. + for (const ChunkAndOffset &C : AddressTakenSyms) + if (C.InputChunk->Alignment < 16) + C.InputChunk->Alignment = 16; + maybeAddRVATable(std::move(AddressTakenSyms), "__guard_fids_table", "__guard_fids_count"); diff --git a/lld/test/COFF/Inputs/guardcf-align-foobar.yaml b/lld/test/COFF/Inputs/guardcf-align-foobar.yaml new file mode 100644 index 0000000..7878c45 --- /dev/null +++ b/lld/test/COFF/Inputs/guardcf-align-foobar.yaml @@ -0,0 +1,51 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text.foo + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + SectionData: 31C0C3 + - Name: .text.bar + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + SectionData: FFE1 +symbols: + - Name: .text.foo + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 3 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 3963538403 + Number: 1 + - Name: .text.bar + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 2 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 1143549852 + Number: 2 + - Name: foo + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: bar + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/lld/test/COFF/guardcf-align.s b/lld/test/COFF/guardcf-align.s new file mode 100644 index 0000000..a0caabc --- /dev/null +++ b/lld/test/COFF/guardcf-align.s @@ -0,0 +1,45 @@ +# RUN: llvm-mc -triple x86_64-windows-msvc -filetype=obj -o %t.obj %s +# RUN: yaml2obj < %p/Inputs/guardcf-align-foobar.yaml \ +# RUN: > %T/guardcf-align-foobar.obj +# RUN: lld-link -out:%T/guardcf-align.exe -entry:main -guard:cf \ +# RUN: %t.obj %T/guardcf-align-foobar.obj +# RUN: llvm-readobj -coff-load-config %T/guardcf-align.exe | FileCheck %s + +# Check that the gfids table contains at least one entry that ends in 0 +# and no entries that end in something other than 0. +# CHECK: GuardFidTable [ +# CHECK-NOT: 0x{{[0-9A-Fa-f]+[^0]$}} +# CHECK: 0x{{[0-9A-Fa-f]+0$}} +# CHECK-NOT: 0x{{[0-9A-Fa-f]+[^0]$}} +# CHECK: ] + +# @feat.00 and _load_config_used to indicate we have gfids. + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +@feat.00 = 0x801 + + .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 + +# Functions that are called indirectly. + .section .gfids$y,"dr" + .symidx foo + + + .section .text,"rx" + .global main +main: + movq foo, %rcx + xorq %rax, %rax + callq bar + retq -- 2.7.4