mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 13:36:07 +00:00

Scanning functions without CFG information as well as the detection of authentication oracles requires introducing more classes related to register state analysis. To make the future code easier to understand, rename several classes beforehand. To detect authentication oracles, one has to query the properties of *output* operands of authentication instructions *after* the instruction is executed - this requires adding another analysis that iterates over the instructions in reverse order, and a corresponding state class. As the main difference of the existing `State` class is that it stores the properties of source register operands of the instructions before the instruction's execution, rename it to `SrcState` and `PacRetAnalysis` to `SrcSafetyAnalysis`. Apply minor adjustments to the debug output along the way.
172 lines
8.9 KiB
ArmAsm
172 lines
8.9 KiB
ArmAsm
// REQUIRES: asserts
|
|
//
|
|
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
|
|
// RUN: llvm-bolt-binary-analysis --scanners=pacret -no-threads \
|
|
// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck %s
|
|
// RUN: llvm-bolt-binary-analysis --scanners=pauth -no-threads \
|
|
// RUN: -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck -check-prefixes=CHECK,PAUTH %s
|
|
|
|
// Check the debug output generated by PAuth gadget scanner to make sure the
|
|
// that output is kept meaningful and to provide an overview of what happens
|
|
// inside the scanner.
|
|
|
|
.globl simple
|
|
.type simple,@function
|
|
simple:
|
|
paciasp
|
|
stp x29, x30, [sp, #-0x10]!
|
|
b 1f
|
|
1:
|
|
autiza x0
|
|
blr x0
|
|
ldp x29, x30, [sp], #0x10
|
|
autiasp
|
|
ret
|
|
.size simple, .-simple
|
|
|
|
// CHECK-LABEL:Analyzing in function simple, AllocatorId 1
|
|
// CHECK-NEXT: Binary Function "simple" {
|
|
// CHECK-NEXT: Number : 1
|
|
// CHECK-NEXT: State : CFG constructed
|
|
// ...
|
|
// CHECK: BB Layout : [[BB0:[0-9a-zA-Z.]+]], [[BB1:[0-9a-zA-Z.]+]]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: [[BB0]] (3 instructions, align : 1)
|
|
// CHECK-NEXT: Entry Point
|
|
// CHECK-NEXT: 00000000: paciasp
|
|
// CHECK-NEXT: 00000004: stp x29, x30, [sp, #-0x10]!
|
|
// CHECK-NEXT: 00000008: b [[BB1]]
|
|
// CHECK-NEXT: Successors: [[BB1]]
|
|
// CHECK-EMPTY:
|
|
// CHECK-NEXT: [[BB1]] (5 instructions, align : 1)
|
|
// CHECK-NEXT: Predecessors: [[BB0]]
|
|
// CHECK-NEXT: 0000000c: autiza x0
|
|
// CHECK-NEXT: 00000010: blr x0
|
|
// CHECK-NEXT: 00000014: ldp x29, x30, [sp], #0x10
|
|
// CHECK-NEXT: 00000018: autiasp
|
|
// CHECK-NEXT: 0000001c: ret
|
|
// CHECK-EMPTY:
|
|
// CHECK-NEXT: DWARF CFI Instructions:
|
|
// CHECK-NEXT: <empty>
|
|
// CHECK-NEXT: End of Function "simple"
|
|
// CHECK-EMPTY:
|
|
// CHECK-NEXT: Running src register safety analysis...
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( hint #25, src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( stp x29, x30, [sp, #-0x10]!, src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( b [[BB1]], src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::Confluence(
|
|
// CHECK-NEXT: State 1: src-state<empty>
|
|
// CHECK-NEXT: State 2: src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: merged state: src-state<SafeToDerefRegs: , Insts: >
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( autiza x0, src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( blr x0, src-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( hint #29, src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::Confluence(
|
|
// CHECK-NEXT: State 1: src-state<SafeToDerefRegs: , Insts: >
|
|
// CHECK-NEXT: State 2: src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: merged state: src-state<SafeToDerefRegs: , Insts: >
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( autiza x0, src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( blr x0, src-state<SafeToDerefRegs: W0 X0 W0_HI , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ldp x29, x30, [sp], #0x10, src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( hint #29, src-state<SafeToDerefRegs: , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
|
|
// CHECK-NEXT: After src register safety analysis:
|
|
// CHECK-NEXT: Binary Function "simple" {
|
|
// CHECK-NEXT: Number : 1
|
|
// CHECK-NEXT: State : CFG constructed
|
|
// ...
|
|
// CHECK: BB Layout : [[BB0]], [[BB1]]
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: [[BB0]] (3 instructions, align : 1)
|
|
// CHECK-NEXT: Entry Point
|
|
// CHECK-NEXT: 00000000: paciasp # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// CHECK-NEXT: 00000004: stp x29, x30, [sp, #-0x10]! # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// CHECK-NEXT: 00000008: b [[BB1]] # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// CHECK-NEXT: Successors: [[BB1]]
|
|
// CHECK-EMPTY:
|
|
// CHECK-NEXT: [[BB1]] (5 instructions, align : 1)
|
|
// CHECK-NEXT: Predecessors: [[BB0]]
|
|
// CHECK-NEXT: 0000000c: autiza x0 # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// CHECK-NEXT: 00000010: blr x0 # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// CHECK-NEXT: 00000014: ldp x29, x30, [sp], #0x10 # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// CHECK-NEXT: 00000018: autiasp # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// CHECK-NEXT: 0000001c: ret # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// CHECK-EMPTY:
|
|
// CHECK-NEXT: DWARF CFI Instructions:
|
|
// CHECK-NEXT: <empty>
|
|
// CHECK-NEXT: End of Function "simple"
|
|
// CHECK-EMPTY:
|
|
// PAUTH-NEXT: Found call inst: 00000000: blr x0 # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// PAUTH-NEXT: Call destination reg: X0
|
|
// PAUTH-NEXT: SafeToDerefRegs: W0 X0 W0_HI{{[ \t]*$}}
|
|
// CHECK-NEXT: Found RET inst: 00000000: ret # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// CHECK-NEXT: RetReg: LR
|
|
// CHECK-NEXT: Authenticated reg: (none)
|
|
// CHECK-NEXT: SafeToDerefRegs: LR W30 W30_HI{{[ \t]*$}}
|
|
|
|
.globl clobber
|
|
.type clobber,@function
|
|
clobber:
|
|
mov w30, #0
|
|
ret
|
|
.size clobber, .-clobber
|
|
|
|
// CHECK-LABEL:Analyzing in function clobber, AllocatorId 1
|
|
// ...
|
|
// CHECK: Running src register safety analysis...
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( mov w30, #0x0, src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W30_HI , Insts: >)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: W30_HI , Insts: >)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W30_HI , Insts: >)
|
|
// CHECK-NEXT: After src register safety analysis:
|
|
// CHECK-NEXT: Binary Function "clobber" {
|
|
// ...
|
|
// CHECK: End of Function "clobber"
|
|
|
|
// The above output was printed after first run of analysis
|
|
|
|
// CHECK-EMPTY:
|
|
// CHECK-NEXT: Found RET inst: 00000000: ret # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: >
|
|
// CHECK-NEXT: RetReg: LR
|
|
// CHECK-NEXT: Authenticated reg: (none)
|
|
// CHECK-NEXT: SafeToDerefRegs: W30_HI{{[ \t]*$}}
|
|
// CHECK-EMPTY:
|
|
// CHECK-NEXT: Running detailed src register safety analysis...
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( mov w30, #0x0, src-state<SafeToDerefRegs: LR W30 W30_HI , Insts: [0]()>)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
|
|
// CHECK-NEXT: SrcSafetyAnalysis::ComputeNext( ret x30, src-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
|
|
// CHECK-NEXT: .. result: (src-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
|
|
// CHECK-NEXT: After detailed src register safety analysis:
|
|
// CHECK-NEXT: Binary Function "clobber" {
|
|
// ...
|
|
// CHECK: End of Function "clobber"
|
|
|
|
// The analysis was re-computed with register tracking, as an issue was found in this function.
|
|
// Iterating over the reports and attaching clobbering info:
|
|
|
|
// CHECK-EMPTY:
|
|
// CHECK-NEXT: Attaching clobbering info to: 00000000: ret # SrcSafetyAnalysis: src-state<SafeToDerefRegs: BitVector, Insts: [0](0x{{[0-9a-f]+}} )>
|
|
|
|
|
|
// CHECK-LABEL:Analyzing in function main, AllocatorId 1
|
|
.globl main
|
|
.type main,@function
|
|
main:
|
|
ret
|
|
.size main, .-main
|