-
Notifications
You must be signed in to change notification settings - Fork 12.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[HWASan] Port HWASan to Linux x86-64 (LLVM)
Summary: Porting HWASan to Linux x86-64, first of the three patches, LLVM part. The approach is similar to ARM case, trap signal is used to communicate memory tag check failure. int3 instruction is used to generate a signal, access parameters are stored in nop [eax + offset] instruction immediately following the int3 one. One notable difference is that x86-64 has to untag the pointer before use due to the lack of feature comparable to ARM's TBI (Top Byte Ignore). Reviewers: eugenis Subscribers: kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D44699 llvm-svn: 328342
- llvmorg-20-init
- llvmorg-19.1.6
- llvmorg-19.1.5
- llvmorg-19.1.4
- llvmorg-19.1.3
- llvmorg-19.1.2
- llvmorg-19.1.1
- llvmorg-19.1.0
- llvmorg-19.1.0-rc4
- llvmorg-19.1.0-rc3
- llvmorg-19.1.0-rc2
- llvmorg-19.1.0-rc1
- llvmorg-19-init
- llvmorg-18.1.8
- llvmorg-18.1.7
- llvmorg-18.1.6
- llvmorg-18.1.5
- llvmorg-18.1.4
- llvmorg-18.1.3
- llvmorg-18.1.2
- llvmorg-18.1.1
- llvmorg-18.1.0
- llvmorg-18.1.0-rc4
- llvmorg-18.1.0-rc3
- llvmorg-18.1.0-rc2
- llvmorg-18.1.0-rc1
- llvmorg-18-init
- llvmorg-17.0.6
- llvmorg-17.0.5
- llvmorg-17.0.4
- llvmorg-17.0.3
- llvmorg-17.0.2
- llvmorg-17.0.1
- llvmorg-17.0.0
- llvmorg-17.0.0-rc4
- llvmorg-17.0.0-rc3
- llvmorg-17.0.0-rc2
- llvmorg-17.0.0-rc1
- llvmorg-17-init
- llvmorg-16.0.6
- llvmorg-16.0.5
- llvmorg-16.0.4
- llvmorg-16.0.3
- llvmorg-16.0.2
- llvmorg-16.0.1
- llvmorg-16.0.0
- llvmorg-16.0.0-rc4
- llvmorg-16.0.0-rc3
- llvmorg-16.0.0-rc2
- llvmorg-16.0.0-rc1
- llvmorg-16-init
- llvmorg-15.0.7
- llvmorg-15.0.6
- llvmorg-15.0.5
- llvmorg-15.0.4
- llvmorg-15.0.3
- llvmorg-15.0.2
- llvmorg-15.0.1
- llvmorg-15.0.0
- llvmorg-15.0.0-rc3
- llvmorg-15.0.0-rc2
- llvmorg-15.0.0-rc1
- llvmorg-15-init
- llvmorg-14.0.6
- llvmorg-14.0.5
- llvmorg-14.0.4
- llvmorg-14.0.3
- llvmorg-14.0.2
- llvmorg-14.0.1
- llvmorg-14.0.0
- llvmorg-14.0.0-rc4
- llvmorg-14.0.0-rc3
- llvmorg-14.0.0-rc2
- llvmorg-14.0.0-rc1
- llvmorg-14-init
- llvmorg-13.0.1
- llvmorg-13.0.1-rc3
- llvmorg-13.0.1-rc2
- llvmorg-13.0.1-rc1
- llvmorg-13.0.0
- llvmorg-13.0.0-rc4
- llvmorg-13.0.0-rc3
- llvmorg-13.0.0-rc2
- llvmorg-13.0.0-rc1
- llvmorg-13-init
- llvmorg-12.0.1
- llvmorg-12.0.1-rc4
- llvmorg-12.0.1-rc3
- llvmorg-12.0.1-rc2
- llvmorg-12.0.1-rc1
- llvmorg-12.0.0
- llvmorg-12.0.0-rc5
- llvmorg-12.0.0-rc4
- llvmorg-12.0.0-rc3
- llvmorg-12.0.0-rc2
- llvmorg-12.0.0-rc1
- llvmorg-12-init
- llvmorg-11.1.0
- llvmorg-11.1.0-rc3
- llvmorg-11.1.0-rc2
- llvmorg-11.1.0-rc1
- llvmorg-11.0.1
- llvmorg-11.0.1-rc2
- llvmorg-11.0.1-rc1
- llvmorg-11.0.0
- llvmorg-11.0.0-rc6
- llvmorg-11.0.0-rc5
- llvmorg-11.0.0-rc4
- llvmorg-11.0.0-rc3
- llvmorg-11.0.0-rc2
- llvmorg-11.0.0-rc1
- llvmorg-11-init
- llvmorg-10.0.1
- llvmorg-10.0.1-rc4
- llvmorg-10.0.1-rc3
- llvmorg-10.0.1-rc2
- llvmorg-10.0.1-rc1
- llvmorg-10.0.0
- llvmorg-10.0.0-rc6
- llvmorg-10.0.0-rc5
- llvmorg-10.0.0-rc4
- llvmorg-10.0.0-rc3
- llvmorg-10.0.0-rc2
- llvmorg-10.0.0-rc1
- llvmorg-10-init
- llvmorg-9.0.1
- llvmorg-9.0.1-rc3
- llvmorg-9.0.1-rc2
- llvmorg-9.0.1-rc1
- llvmorg-9.0.0
- llvmorg-9.0.0-rc6
- llvmorg-9.0.0-rc5
- llvmorg-9.0.0-rc4
- llvmorg-9.0.0-rc3
- llvmorg-9.0.0-rc2
- llvmorg-9.0.0-rc1
- llvmorg-8.0.1
- llvmorg-8.0.1-rc4
- llvmorg-8.0.1-rc3
- llvmorg-8.0.1-rc2
- llvmorg-8.0.1-rc1
- llvmorg-8.0.0
- llvmorg-8.0.0-rc5
- llvmorg-8.0.0-rc4
- llvmorg-8.0.0-rc3
- llvmorg-8.0.0-rc2
- llvmorg-8.0.0-rc1
- llvmorg-7.1.0
- llvmorg-7.1.0-rc1
- llvmorg-7.0.1
- llvmorg-7.0.1-rc3
- llvmorg-7.0.1-rc2
- llvmorg-7.0.1-rc1
- llvmorg-7.0.0
- llvmorg-7.0.0-rc3
- llvmorg-7.0.0-rc2
- llvmorg-7.0.0-rc1
1 parent
4157380
commit 83e7841
Showing
5 changed files
with
314 additions
and
13 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
40 changes: 40 additions & 0 deletions
40
llvm/test/Instrumentation/HWAddressSanitizer/X86/atomic.ll
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,40 @@ | ||
; Test basic address sanitizer instrumentation. | ||
; | ||
; RUN: opt < %s -hwasan -S | FileCheck %s | ||
|
||
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
define void @atomicrmw(i64* %ptr) sanitize_hwaddress { | ||
; CHECK-LABEL: @atomicrmw( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64 | ||
|
||
; CHECK: call void asm sideeffect "int3\0Anopl 83(%rax)", "{rdi}"(i64 %[[A]]) | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i64* | ||
; CHECK: atomicrmw add i64* %[[UNTAGGED_PTR]], i64 1 seq_cst | ||
; CHECK: ret void | ||
|
||
entry: | ||
%0 = atomicrmw add i64* %ptr, i64 1 seq_cst | ||
ret void | ||
} | ||
|
||
define void @cmpxchg(i64* %ptr, i64 %compare_to, i64 %new_value) sanitize_hwaddress { | ||
; CHECK-LABEL: @cmpxchg( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64 | ||
|
||
; CHECK: call void asm sideeffect "int3\0Anopl 83(%rax)", "{rdi}"(i64 %[[A]]) | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i64* | ||
; CHECK: cmpxchg i64* %[[UNTAGGED_PTR]], i64 %compare_to, i64 %new_value seq_cst seq_cst | ||
; CHECK: ret void | ||
|
||
entry: | ||
%0 = cmpxchg i64* %ptr, i64 %compare_to, i64 %new_value seq_cst seq_cst | ||
ret void | ||
} |
103 changes: 103 additions & 0 deletions
103
llvm/test/Instrumentation/HWAddressSanitizer/X86/basic.ll
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,103 @@ | ||
; Test basic address sanitizer instrumentation. | ||
; Generic code is covered by ../basic.ll, only the x86_64 specific code is | ||
; tested here. | ||
; | ||
; RUN: opt < %s -hwasan -hwasan-recover=0 -S | FileCheck %s --check-prefixes=CHECK,ABORT | ||
; RUN: opt < %s -hwasan -hwasan-recover=1 -S | FileCheck %s --check-prefixes=CHECK,RECOVER | ||
|
||
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
define i8 @test_load8(i8* %a) sanitize_hwaddress { | ||
; CHECK-LABEL: @test_load8( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 | ||
|
||
; ABORT: call void asm sideeffect "int3\0Anopl 64(%rax)", "{rdi}"(i64 %[[A]]) | ||
; ABORT: unreachable | ||
; RECOVER: call void asm sideeffect "int3\0Anopl 96(%rax)", "{rdi}"(i64 %[[A]]) | ||
; RECOVER: br label | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8* | ||
; CHECK: %[[G:[^ ]*]] = load i8, i8* %[[UNTAGGED_PTR]], align 4 | ||
; CHECK: ret i8 %[[G]] | ||
|
||
entry: | ||
%b = load i8, i8* %a, align 4 | ||
ret i8 %b | ||
} | ||
|
||
define i40 @test_load40(i40* %a) sanitize_hwaddress { | ||
; CHECK-LABEL: @test_load40( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 | ||
|
||
; ABORT: call void @__hwasan_loadN(i64 %[[A]], i64 5) | ||
; RECOVER: call void @__hwasan_loadN_noabort(i64 %[[A]], i64 5) | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40* | ||
; CHECK: %[[B:[^ ]*]] = load i40, i40* %[[UNTAGGED_PTR]] | ||
; CHECK: ret i40 %[[B]] | ||
|
||
entry: | ||
%b = load i40, i40* %a, align 4 | ||
ret i40 %b | ||
} | ||
|
||
define void @test_store8(i8* %a, i8 %b) sanitize_hwaddress { | ||
; CHECK-LABEL: @test_store8( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 | ||
|
||
; ABORT: call void asm sideeffect "int3\0Anopl 80(%rax)", "{rdi}"(i64 %[[A]]) | ||
; ABORT: unreachable | ||
; RECOVER: call void asm sideeffect "int3\0Anopl 112(%rax)", "{rdi}"(i64 %[[A]]) | ||
; RECOVER: br label | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8* | ||
; CHECK: store i8 %b, i8* %[[UNTAGGED_PTR]], align 4 | ||
; CHECK: ret void | ||
|
||
entry: | ||
store i8 %b, i8* %a, align 4 | ||
ret void | ||
} | ||
|
||
define void @test_store40(i40* %a, i40 %b) sanitize_hwaddress { | ||
; CHECK-LABEL: @test_store40( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 | ||
|
||
; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 5) | ||
; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 5) | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40* | ||
; CHECK: store i40 %b, i40* %[[UNTAGGED_PTR]] | ||
; CHECK: ret void | ||
|
||
entry: | ||
store i40 %b, i40* %a, align 4 | ||
ret void | ||
} | ||
|
||
define void @test_store_unaligned(i64* %a, i64 %b) sanitize_hwaddress { | ||
; CHECK-LABEL: @test_store_unaligned( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64 | ||
|
||
; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 8) | ||
; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 8) | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i64* | ||
; CHECK: store i64 %b, i64* %[[UNTAGGED_PTR]], align 4 | ||
; CHECK: ret void | ||
|
||
entry: | ||
store i64 %b, i64* %a, align 4 | ||
ret void | ||
} |
34 changes: 34 additions & 0 deletions
34
llvm/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll
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,34 @@ | ||
; Test kernel hwasan instrumentation. | ||
; Generic code is covered by ../kernel.ll, only the x86_64 specific code is | ||
; tested here. | ||
; | ||
; RUN: opt < %s -hwasan -hwasan-kernel=1 -S | FileCheck %s --allow-empty --check-prefixes=INIT | ||
; RUN: opt < %s -hwasan -hwasan-kernel=1 -S | FileCheck %s | ||
; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-mapping-offset=12345678 -S | FileCheck %s | ||
; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-recover=0 -S | FileCheck %s --check-prefixes=CHECK,ABORT | ||
; RUN: opt < %s -hwasan -hwasan-kernel=1 -hwasan-recover=1 -S | FileCheck %s --check-prefixes=CHECK,RECOVER | ||
|
||
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
define i8 @test_load(i8* %a) sanitize_hwaddress { | ||
; CHECK-LABEL: @test_load( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 | ||
|
||
; ABORT: call void asm sideeffect "int3\0Anopl 64(%rax)", "{rdi}"(i64 %[[A]]) | ||
; ABORT: unreachable | ||
; RECOVER: call void asm sideeffect "int3\0Anopl 96(%rax)", "{rdi}"(i64 %[[A]]) | ||
; RECOVER: br label | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = or i64 %[[A]], -72057594037927936 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8* | ||
; CHECK: %[[G:[^ ]*]] = load i8, i8* %[[UNTAGGED_PTR]], align 4 | ||
; CHECK: ret i8 %[[G]] | ||
|
||
entry: | ||
%b = load i8, i8* %a, align 4 | ||
ret i8 %b | ||
} | ||
|
||
; INIT-NOT: call void @__hwasan_init |
79 changes: 79 additions & 0 deletions
79
llvm/test/Instrumentation/HWAddressSanitizer/X86/with-calls.ll
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,79 @@ | ||
; Test basic address sanitizer instrumentation. | ||
; | ||
; RUN: opt < %s -hwasan -hwasan-instrument-with-calls -S | FileCheck %s --check-prefixes=CHECK,ABORT | ||
; RUN: opt < %s -hwasan -hwasan-instrument-with-calls -hwasan-recover=1 -S | FileCheck %s --check-prefixes=CHECK,RECOVER | ||
|
||
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
define i8 @test_load8(i8* %a) sanitize_hwaddress { | ||
; CHECK-LABEL: @test_load8( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 | ||
|
||
; ABORT: call void @__hwasan_load1(i64 %[[A]]) | ||
; RECOVER: call void @__hwasan_load1_noabort(i64 %[[A]]) | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8* | ||
; CHECK: %[[B:[^ ]*]] = load i8, i8* %[[UNTAGGED_PTR]] | ||
; CHECK: ret i8 %[[B]] | ||
|
||
entry: | ||
%b = load i8, i8* %a, align 4 | ||
ret i8 %b | ||
} | ||
|
||
define i40 @test_load40(i40* %a) sanitize_hwaddress { | ||
; CHECK-LABEL: @test_load40( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 | ||
|
||
; ABORT: call void @__hwasan_loadN(i64 %[[A]], i64 5) | ||
; RECOVER: call void @__hwasan_loadN_noabort(i64 %[[A]], i64 5) | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40* | ||
; CHECK: %[[B:[^ ]*]] = load i40, i40* %[[UNTAGGED_PTR]] | ||
; CHECK: ret i40 %[[B]] | ||
|
||
entry: | ||
%b = load i40, i40* %a, align 4 | ||
ret i40 %b | ||
} | ||
|
||
define void @test_store8(i8* %a, i8 %b) sanitize_hwaddress { | ||
; CHECK-LABEL: @test_store8( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 | ||
|
||
; ABORT: call void @__hwasan_store1(i64 %[[A]]) | ||
; RECOVER: call void @__hwasan_store1_noabort(i64 %[[A]]) | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8* | ||
; CHECK: store i8 %b, i8* %[[UNTAGGED_PTR]] | ||
; CHECK: ret void | ||
|
||
entry: | ||
store i8 %b, i8* %a, align 4 | ||
ret void | ||
} | ||
|
||
define void @test_store40(i40* %a, i40 %b) sanitize_hwaddress { | ||
; CHECK-LABEL: @test_store40( | ||
; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 | ||
|
||
; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 5) | ||
; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 5) | ||
|
||
; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 | ||
; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 | ||
; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40* | ||
; CHECK: store i40 %b, i40* %[[UNTAGGED_PTR]] | ||
; CHECK: ret void | ||
|
||
entry: | ||
store i40 %b, i40* %a, align 4 | ||
ret void | ||
} |