diff options
| author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-11-11 18:49:09 +0000 |
|---|---|---|
| committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-11-11 18:49:09 +0000 |
| commit | f48ffab554fa77306246eaac63970d53229b0c0d (patch) | |
| tree | 6ba0f0313f89f1b277f04e6a72209dcd5d8fd51a /llvm/test/Transforms | |
| parent | 6285f5b441bf602319c2bc3b4ed04a1450aa8247 (diff) | |
| download | bcm5719-llvm-f48ffab554fa77306246eaac63970d53229b0c0d.tar.gz bcm5719-llvm-f48ffab554fa77306246eaac63970d53229b0c0d.zip | |
[cfi] Implement cfi-icall using inline assembly.
The current implementation is emitting a global constant that happens
to evaluate to the same bytes + relocation as a jump instruction on
X86. This does not work for PIE executables and shared libraries
though, because we end up with a wrong relocation type. And it has no
chance of working on ARM/AArch64 which use different relocation types
for jump instructions (R_ARM_JUMP24) that is never generated for
data.
This change replaces the constant with module-level inline assembly
followed by a hidden declaration of the jump table. Works fine for
ARM/AArch64, but has some drawbacks.
* Extra symbols are added to the static symbol table, which inflate
the size of the unstripped binary a little. Stripped binaries are not
affected. This happens because jump table declarations must be
external (because their body is in the inline asm).
* Original functions that were anonymous are now named
<original name>.cfi, and it affects symbolization sometimes. This is
necessary because the only user of these functions is the (inline
asm) jump table, so they had to be added to @llvm.used, which does
not allow unnamed functions.
llvm-svn: 286611
Diffstat (limited to 'llvm/test/Transforms')
4 files changed, 93 insertions, 24 deletions
diff --git a/llvm/test/Transforms/LowerTypeTests/function-disjoint.ll b/llvm/test/Transforms/LowerTypeTests/function-disjoint.ll index a5455a953fb..1d236877502 100644 --- a/llvm/test/Transforms/LowerTypeTests/function-disjoint.ll +++ b/llvm/test/Transforms/LowerTypeTests/function-disjoint.ll @@ -5,21 +5,36 @@ target datalayout = "e-p:64:64" -; X64: @[[JT0:.*]] = private constant [1 x <{ i8, i32, i8, i8, i8 }>] [<{ i8, i32, i8, i8, i8 }> <{ i8 -23, i32 trunc (i64 sub (i64 sub (i64 ptrtoint (void ()* @[[FNAME:.*]] to i64), i64 ptrtoint ([1 x <{ i8, i32, i8, i8, i8 }>]* @[[JT0]] to i64)), i64 5) to i32), i8 -52, i8 -52, i8 -52 }>], section ".text" -; X64: @[[JT1:.*]] = private constant [1 x <{ i8, i32, i8, i8, i8 }>] [<{ i8, i32, i8, i8, i8 }> <{ i8 -23, i32 trunc (i64 sub (i64 sub (i64 ptrtoint (void ()* @[[GNAME:.*]] to i64), i64 ptrtoint ([1 x <{ i8, i32, i8, i8, i8 }>]* @[[JT1]] to i64)), i64 5) to i32), i8 -52, i8 -52, i8 -52 }>], section ".text" +; X64: module asm "f = .cfi.jumptable + 0" + +; X64: module asm ".cfi.jumptable:" +; X64-NEXT: module asm "jmp f.cfi@plt" +; X64-NEXT: module asm "int3" +; X64-NEXT: module asm "int3" +; X64-NEXT: module asm "int3" + +; X64: module asm "g = .cfi.jumptable.1 + 0" + +; X64: module asm ".cfi.jumptable.1:" +; X64-NEXT: module asm "jmp g.cfi@plt" +; X64-NEXT: module asm "int3" +; X64-NEXT: module asm "int3" +; X64-NEXT: module asm "int3" + + +; X64: @.cfi.jumptable = external hidden constant [1 x [8 x i8]] +; X64: @.cfi.jumptable.1 = external hidden constant [1 x [8 x i8]] + ; WASM32: private constant [0 x i8] zeroinitializer @0 = private unnamed_addr constant [2 x void ()*] [void ()* @f, void ()* @g], align 16 -; X64: @f = alias void (), bitcast ([1 x <{ i8, i32, i8, i8, i8 }>]* @[[JT0]] to void ()*) -; X64: @g = alias void (), bitcast ([1 x <{ i8, i32, i8, i8, i8 }>]* @[[JT1]] to void ()*) - -; X64: define private void @[[FNAME]]() +; X64: define internal void @f.cfi() ; WASM32: define void @f() !type !{{[0-9]+}} !wasm.index ![[I0:[0-9]+]] define void @f() !type !0 { ret void } -; X64: define private void @[[GNAME]]() +; X64: define internal void @g.cfi() ; WASM32: define void @g() !type !{{[0-9]+}} !wasm.index ![[I1:[0-9]+]] define void @g() !type !1 { ret void @@ -31,15 +46,18 @@ define void @g() !type !1 { declare i1 @llvm.type.test(i8* %ptr, metadata %bitset) nounwind readnone define i1 @foo(i8* %p) { - ; X64: icmp eq i64 {{.*}}, ptrtoint ([1 x <{ i8, i32, i8, i8, i8 }>]* @[[JT0]] to i64) + ; X64: icmp eq i64 {{.*}}, ptrtoint ([1 x [8 x i8]]* @.cfi.jumptable to i64) ; WASM32: icmp eq i64 {{.*}}, 1 %x = call i1 @llvm.type.test(i8* %p, metadata !"typeid1") - ; X64: icmp eq i64 {{.*}}, ptrtoint ([1 x <{ i8, i32, i8, i8, i8 }>]* @[[JT1]] to i64) + ; X64: icmp eq i64 {{.*}}, ptrtoint ([1 x [8 x i8]]* @.cfi.jumptable.1 to i64) ; WASM32: icmp eq i64 {{.*}}, 2 %y = call i1 @llvm.type.test(i8* %p, metadata !"typeid2") %z = add i1 %x, %y ret i1 %z } +; X64: declare void @f() +; X64: declare void @g() + ; WASM32: ![[I0]] = !{i64 1} -; WASM32: ![[I1]] = !{i64 2} +; WASM32: ![[I1]] = !{i64 2}
\ No newline at end of file diff --git a/llvm/test/Transforms/LowerTypeTests/function-ext.ll b/llvm/test/Transforms/LowerTypeTests/function-ext.ll index 2e9ab9dba62..b3b1f776e12 100644 --- a/llvm/test/Transforms/LowerTypeTests/function-ext.ll +++ b/llvm/test/Transforms/LowerTypeTests/function-ext.ll @@ -4,14 +4,18 @@ ; Tests that we correctly handle external references, including the case where ; all functions in a bitset are external references. -; X64: @[[JT:.*]] = private constant [1 x <{ i8, i32, i8, i8, i8 }>] [<{ i8, i32, i8, i8, i8 }> <{ i8 -23, i32 trunc (i64 sub (i64 sub (i64 ptrtoint (void ()* @foo to i64), i64 ptrtoint ([1 x <{ i8, i32, i8, i8, i8 }>]* @[[JT]] to i64)), i64 5) to i32), i8 -52, i8 -52, i8 -52 }>], section ".text" +; X64: module asm ".cfi.jumptable:" +; X64-NEXT: module asm "jmp foo@plt" +; X64-NOT: module asm "jmp {{.*}}@plt" + +; X64: @.cfi.jumptable = external hidden constant [1 x [8 x i8]] ; WASM32: private constant [0 x i8] zeroinitializer ; WASM32: declare !type !{{[0-9]+}} void @foo() declare !type !0 void @foo() define i1 @bar(i8* %ptr) { - ; X64: icmp eq i64 {{.*}}, ptrtoint ([1 x <{ i8, i32, i8, i8, i8 }>]* @[[JT]] to i64) + ; X64: icmp eq i64 {{.*}}, ptrtoint ([1 x [8 x i8]]* @.cfi.jumptable to i64) ; WASM32: sub i64 {{.*}}, 0 ; WASM32: icmp ult i64 {{.*}}, 1 %p = call i1 @llvm.type.test(i8* %ptr, metadata !"void") diff --git a/llvm/test/Transforms/LowerTypeTests/function.ll b/llvm/test/Transforms/LowerTypeTests/function.ll index a9ef84acff6..7b7a6af320a 100644 --- a/llvm/test/Transforms/LowerTypeTests/function.ll +++ b/llvm/test/Transforms/LowerTypeTests/function.ll @@ -1,26 +1,65 @@ -; RUN: opt -S -lowertypetests -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck --check-prefix=X64 %s +; RUN: opt -S -lowertypetests -mtriple=i686-unknown-linux-gnu < %s | FileCheck --check-prefix=X86 %s +; RUN: opt -S -lowertypetests -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck --check-prefix=X86 %s +; RUN: opt -S -lowertypetests -mtriple=arm-unknown-linux-gnu < %s | FileCheck --check-prefix=ARM %s +; RUN: opt -S -lowertypetests -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck --check-prefix=ARM %s ; RUN: opt -S -lowertypetests -mtriple=wasm32-unknown-unknown < %s | FileCheck --check-prefix=WASM32 %s ; Tests that we correctly handle bitsets containing 2 or more functions. target datalayout = "e-p:64:64" -; X64: @[[JT:.*]] = private constant [2 x <{ i8, i32, i8, i8, i8 }>] [<{ i8, i32, i8, i8, i8 }> <{ i8 -23, i32 trunc (i64 sub (i64 sub (i64 ptrtoint (void ()* @[[FNAME:.*]] to i64), i64 ptrtoint ([2 x <{ i8, i32, i8, i8, i8 }>]* @[[JT]] to i64)), i64 5) to i32), i8 -52, i8 -52, i8 -52 }>, <{ i8, i32, i8, i8, i8 }> <{ i8 -23, i32 trunc (i64 sub (i64 sub (i64 ptrtoint (void ()* @[[GNAME:.*]] to i64), i64 ptrtoint ([2 x <{ i8, i32, i8, i8, i8 }>]* @[[JT]] to i64)), i64 13) to i32), i8 -52, i8 -52, i8 -52 }>], section ".text" +; X86: module asm ".globl f" +; X86-NEXT: module asm ".type f, function" +; X86-NEXT: module asm "f = .cfi.jumptable + 0" +; X86-NEXT: module asm ".size f, 8" +; X86-NEXT: module asm ".type g, function" +; X86-NEXT: module asm "g = .cfi.jumptable + 8" +; X86-NEXT: module asm ".size g, 8" +; X86-NEXT: module asm ".section .text.cfi, \22ax\22, @progbits" +; X86-NEXT: module asm ".balign 8" +; X86-NEXT: module asm ".cfi.jumptable:" +; X86-NEXT: module asm "jmp f.cfi@plt" +; X86-NEXT: module asm "int3" +; X86-NEXT: module asm "int3" +; X86-NEXT: module asm "int3" +; X86-NEXT: module asm "jmp g.cfi@plt" +; X86-NEXT: module asm "int3" +; X86-NEXT: module asm "int3" +; X86-NEXT: module asm "int3" + +; ARM: module asm ".globl f" +; ARM-NEXT: module asm ".type f, function" +; ARM-NEXT: module asm "f = .cfi.jumptable + 0" +; ARM-NEXT: module asm ".size f, 4" +; ARM-NEXT: module asm ".type g, function" +; ARM-NEXT: module asm "g = .cfi.jumptable + 4" +; ARM-NEXT: module asm ".size g, 4" +; ARM-NEXT: module asm ".section .text.cfi, \22ax\22, @progbits" +; ARM-NEXT: module asm ".balign 4" +; ARM-NEXT: module asm ".cfi.jumptable:" +; ARM-NEXT: module asm "b f.cfi" +; ARM-NEXT: module asm "b g.cfi" + +; X86: @.cfi.jumptable = external hidden constant [2 x [8 x i8]] +; ARM: @.cfi.jumptable = external hidden constant [2 x [4 x i8]] + ; WASM32: private constant [0 x i8] zeroinitializer @0 = private unnamed_addr constant [2 x void (...)*] [void (...)* bitcast (void ()* @f to void (...)*), void (...)* bitcast (void ()* @g to void (...)*)], align 16 -; X64: @f = alias void (), bitcast ([2 x <{ i8, i32, i8, i8, i8 }>]* @[[JT]] to void ()*) -; X64: @g = alias void (), bitcast (<{ i8, i32, i8, i8, i8 }>* getelementptr inbounds ([2 x <{ i8, i32, i8, i8, i8 }>], [2 x <{ i8, i32, i8, i8, i8 }>]* @[[JT]], i64 0, i64 1) to void ()*) +; X86: @llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @f.cfi to i8*), i8* bitcast (void ()* @g.cfi to i8*)], section "llvm.metadata" +; ARM: @llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @f.cfi to i8*), i8* bitcast (void ()* @g.cfi to i8*)], section "llvm.metadata" -; X64: define private void @[[FNAME]]() +; X86: define internal void @f.cfi() +; ARM: define internal void @f.cfi() ; WASM32: define void @f() !type !{{[0-9]+}} !wasm.index ![[I0:[0-9]+]] define void @f() !type !0 { ret void } -; X64: define private void @[[GNAME]]() -; WASM32: define void @g() !type !{{[0-9]+}} !wasm.index ![[I1:[0-9]+]] -define void @g() !type !0 { +; X86: define internal void @g.cfi() +; ARM: define internal void @g.cfi() +; WASM32: define internal void @g() !type !{{[0-9]+}} !wasm.index ![[I1:[0-9]+]] +define internal void @g() !type !0 { ret void } @@ -29,12 +68,18 @@ define void @g() !type !0 { declare i1 @llvm.type.test(i8* %ptr, metadata %bitset) nounwind readnone define i1 @foo(i8* %p) { - ; X64: sub i64 {{.*}}, ptrtoint ([2 x <{ i8, i32, i8, i8, i8 }>]* @[[JT]] to i64) + ; X86: sub i64 {{.*}}, ptrtoint ([2 x [8 x i8]]* @.cfi.jumptable to i64) + ; ARM: sub i64 {{.*}}, ptrtoint ([2 x [4 x i8]]* @.cfi.jumptable to i64) ; WASM32: sub i64 {{.*}}, 1 ; WASM32: icmp ult i64 {{.*}}, 2 %x = call i1 @llvm.type.test(i8* %p, metadata !"typeid1") ret i1 %x } +; X86: declare void @f() +; ARM: declare void @f() +; X86: declare hidden void @g() +; ARM: declare hidden void @g() + ; WASM32: ![[I0]] = !{i64 1} ; WASM32: ![[I1]] = !{i64 2} diff --git a/llvm/test/Transforms/LowerTypeTests/section.ll b/llvm/test/Transforms/LowerTypeTests/section.ll index 7884acfaec3..9dfb173d04a 100644 --- a/llvm/test/Transforms/LowerTypeTests/section.ll +++ b/llvm/test/Transforms/LowerTypeTests/section.ll @@ -5,9 +5,11 @@ target triple = "x86_64-unknown-linux-gnu" -; CHECK: @[[A:.*]] = private constant {{.*}} section ".text" -; CHECK: @f = alias void (), bitcast ({{.*}}* @[[A]] to void ()*) -; CHECK: define private void {{.*}} section "xxx" +; CHECK: module asm ".section .text.cfi, +; CHECK: module asm ".cfi.jumptable:" +; CHECK-NEXT: module asm "jmp f.cfi@plt" + +; CHECK: define internal void @f.cfi() section "xxx" define void @f() section "xxx" !type !0 { entry: |

