mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
adbf373fb6
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
45 lines
2.1 KiB
LLVM
45 lines
2.1 KiB
LLVM
; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s
|
|
; Control Flow Guard is currently only available on Windows
|
|
|
|
declare dllimport i32 @target_func1()
|
|
declare dllimport i32 @target_func2()
|
|
declare dllimport i32 @target_func3()
|
|
@ptrs = dso_local local_unnamed_addr global [2 x void ()*] [void ()* bitcast (i32 ()* @target_func2 to void ()*), void ()* bitcast (i32 ()* @target_func3 to void ()*)], align 16
|
|
|
|
; Test address-taken functions from imported DLLs are correctly added to the
|
|
; Guard Address-Taken IAT Entry (.giats) and Guard Function ID (.gfids) sections.
|
|
define i32 @func_cf_giats1() {
|
|
entry:
|
|
; Since it is a dllimport, target_func1 will be represented as "__imp_target_func1" when it is
|
|
; stored in the function pointer. Therefore, the .giats section must contain "__imp_target_func1".
|
|
; Unlike MSVC, we also have "target_func1" in the .gfids section, since this is not a security risk.
|
|
%func_ptr = alloca i32 ()*, align 8
|
|
store i32 ()* @target_func1, i32 ()** %func_ptr, align 8
|
|
%0 = load i32 ()*, i32 ()** %func_ptr, align 8
|
|
%1 = call i32 %0()
|
|
; target_func2 is called directly from a global array, so should only appear in the .gfids section.
|
|
%2 = load i32 ()*, i32 ()** bitcast ([2 x void ()*]* @ptrs to i32 ()**), align 8
|
|
%3 = call i32 %2()
|
|
; target_func3 is called both via a stored function pointer (as with target_func1) and via a gloabl
|
|
; array (as with target_func2), so "target_func3" must appear in .gfids and "__imp_target_func3" in .giats.
|
|
store i32 ()* @target_func3, i32 ()** %func_ptr, align 8
|
|
%4 = load i32 ()*, i32 ()** %func_ptr, align 8
|
|
%5 = call i32 %4()
|
|
%6 = load i32 ()*, i32 ()** bitcast (void ()** getelementptr inbounds ([2 x void ()*], [2 x void ()*]* @ptrs, i64 0, i64 1) to i32 ()**), align 8
|
|
%7 = call i32 %6()
|
|
ret i32 %5
|
|
}
|
|
|
|
; CHECK-LABEL: .section .gfids$y,"dr"
|
|
; CHECK-NEXT: .symidx target_func1
|
|
; CHECK-NEXT: .symidx target_func2
|
|
; CHECK-NEXT: .symidx target_func3
|
|
; CHECK-NOT: .symidx
|
|
; CHECK-LABEL: .section .giats$y,"dr"
|
|
; CHECK-NEXT: .symidx __imp_target_func1
|
|
; CHECK-NEXT: .symidx __imp_target_func3
|
|
; CHECK-NOT: .symidx
|
|
|
|
!llvm.module.flags = !{!0}
|
|
!0 = !{i32 2, !"cfguard", i32 2}
|