Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CFGuard] Add address-taken IAT tables and delay-load support
This patch adds support for creating Guard Address-Taken IAT Entry Tables (.giats$y sections) in object files, matching the behavior of MSVC. These contain lists of address-taken imported functions, which are used by the linker to create the final GIATS table. Additionally, if any DLLs are delay-loaded, the linker must look through the .giats tables and add the respective load thunks of address-taken imports to the GFIDS table, as these are also valid call targets. Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D87544
- Loading branch information
Showing
13 changed files
with
284 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
# REQUIRES: x86 | ||
|
||
# Make a DLL that exports exportfn1. | ||
# RUN: yaml2obj %p/Inputs/export.yaml -o %basename_t-exp.obj | ||
# RUN: lld-link /out:%basename_t-exp.dll /dll %basename_t-exp.obj /export:exportfn1 /implib:%basename_t-exp.lib | ||
|
||
# Make an object file that imports exportfn1. | ||
# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %basename_t.obj | ||
|
||
# Check that the Guard address-taken IAT entry tables are propagated to the final executable. | ||
# RUN: lld-link %basename_t.obj -guard:cf -entry:main -out:%basename_t-nodelay.exe %basename_t-exp.lib | ||
# RUN: llvm-readobj --file-headers --coff-load-config %basename_t-nodelay.exe | FileCheck %s --check-prefix CHECK | ||
|
||
# CHECK: ImageBase: 0x140000000 | ||
# CHECK: LoadConfig [ | ||
# CHECK: GuardCFFunctionTable: 0x140002114 | ||
# CHECK: GuardCFFunctionCount: 1 | ||
# CHECK: GuardFlags: 0x10500 | ||
# CHECK: GuardAddressTakenIatEntryTable: 0x140002118 | ||
# CHECK: GuardAddressTakenIatEntryCount: 1 | ||
# CHECK: ] | ||
# CHECK: GuardFidTable [ | ||
# CHECK-NEXT: 0x14000{{.*}} | ||
# CHECK-NEXT: ] | ||
# CHECK: GuardIatTable [ | ||
# CHECK-NEXT: 0x14000{{.*}} | ||
# CHECK-NEXT: ] | ||
|
||
|
||
# Check that the additional load thunk symbol is added to the GFIDs table. | ||
# 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 | ||
# RUN: llvm-readobj --file-headers --coff-load-config %basename_t-delay.exe | FileCheck %s --check-prefix DELAY-CHECK | ||
|
||
# DELAY-CHECK: ImageBase: 0x140000000 | ||
# DELAY-CHECK: LoadConfig [ | ||
# DELAY-CHECK: GuardCFFunctionTable: 0x140002114 | ||
# DELAY-CHECK: GuardCFFunctionCount: 2 | ||
# DELAY-CHECK: GuardFlags: 0x10500 | ||
# DELAY-CHECK: GuardAddressTakenIatEntryTable: 0x14000211C | ||
# DELAY-CHECK: GuardAddressTakenIatEntryCount: 1 | ||
# DELAY-CHECK: ] | ||
# DELAY-CHECK: GuardFidTable [ | ||
# DELAY-CHECK-NEXT: 0x14000{{.*}} | ||
# DELAY-CHECK-NEXT: 0x14000{{.*}} | ||
# DELAY-CHECK-NEXT: ] | ||
# DELAY-CHECK: GuardIatTable [ | ||
# DELAY-CHECK-NEXT: 0x14000{{.*}} | ||
# DELAY-CHECK-NEXT: ] | ||
|
||
|
||
# This assembly is reduced from C code like: | ||
# __declspec(noinline) | ||
# void IndirectCall(BOOL (func)(HANDLE)) { | ||
# (*func)(NULL); | ||
# } | ||
# int main(int argc, char** argv) { | ||
# IndirectCall(exportfn1); | ||
# } | ||
|
||
.text | ||
.def @feat.00; | ||
.scl 3; | ||
.type 0; | ||
.endef | ||
.globl @feat.00 | ||
.set @feat.00, 2048 | ||
.def IndirectCall; .scl 2; .type 32; .endef | ||
.globl IndirectCall # -- Begin function IndirectCall | ||
.p2align 4, 0x90 | ||
IndirectCall: # @IndirectCall | ||
# %bb.0: | ||
subq $40, %rsp | ||
movq %rcx, 32(%rsp) | ||
movq 32(%rsp), %rax | ||
movq %rax, %rdx # This would otherwise be: movq __guard_dispatch_icall_fptr(%rip), %rdx | ||
xorl %ecx, %ecx | ||
callq *%rdx | ||
nop | ||
addq $40, %rsp | ||
retq | ||
# -- End function | ||
.def main; .scl 2; .type 32; .endef | ||
.globl main # -- Begin function main | ||
.p2align 4, 0x90 | ||
main: # @main | ||
# %bb.0: | ||
subq $56, %rsp | ||
movq __imp_exportfn1(%rip), %rax | ||
movq %rdx, 48(%rsp) | ||
movl %ecx, 44(%rsp) | ||
movq %rax, %rcx | ||
callq IndirectCall | ||
xorl %eax, %eax | ||
addq $56, %rsp | ||
retq | ||
# -- End function | ||
.section .gfids$y,"dr" | ||
.section .giats$y,"dr" | ||
.symidx __imp_exportfn1 | ||
.section .gljmp$y,"dr" | ||
|
||
# Load configuration directory entry (winnt.h _IMAGE_LOAD_CONFIG_DIRECTORY64). | ||
# The linker will define the __guard_* symbols. | ||
.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 12, 1, 0 | ||
.quad __guard_iat_table | ||
.quad __guard_iat_count | ||
.quad __guard_longjmp_table | ||
.quad __guard_fids_count | ||
.fill 84, 1, 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.