| Issue |
178058
|
| Summary |
[BOLT] Gadget scanner reports incomplete CFG in exception-handling functions
|
| Labels |
BOLT
|
| Assignees |
|
| Reporter |
atrosinenko
|
When C++ function contains exception-handling logic, core BOLT is able to
recognize basic blocks as landing pads, but Pointer Authentication analyzer
in `llvm-bolt-binary-analysis` does not make use of such information yet.
As a result, "Warning: possibly imprecise CFG, ..." reports may be
produced for such functions (at most once per function), even though CFG
information may be perfectly valid.
## How to reproduce
Compile the following source
```cpp
void throwing_fn();
void callback(int);
class my_exception {};
int catching_fn() {
try {
throwing_fn();
} catch (const my_exception &) {
callback(1);
}
return 42;
}
```
with recent version of Clang:
```
clang -target aarch64-linux-pauthtest -march=v8.3-a -fuse-ld=lld \
-O3 --shared -nostdlib -Wl,--emit-relocs \
eh-test.cpp -o eh-test.so
```
Please note that `--shared` and `-nostdlib` options here are mostly used not to
require custom sysroots to reproduce this bug.
This results in the following report generated by gadget scanner (built from
recent mainline commit 3de4d32a7228519312a844bcd48a34124b1a718b):
```
$ ./bin/llvm-bolt-binary-analysis --scanners=pauth ./eh-test.so
BOLT-INFO: shared object or position-independent executable detected
BOLT-INFO: Target architecture: aarch64
BOLT-INFO: BOLT version: 3de4d32a7228519312a844bcd48a34124b1a718b
BOLT-INFO: first alloc address is 0x0
BOLT-INFO: creating new program header table at address 0x200000, offset 0x200000
BOLT-INFO: enabling relocation mode
BOLT-WARNING: Failed to analyze 2 relocations
GS-PAUTH: Warning: possibly imprecise CFG, the analysis quality may be degraded in this function. According to BOLT, unreachable code is found in function _Z11catching_fnv, basic block .LLP0, at address 10764
The instruction is 00010764: cmp w1, #0x1
```
<details>
<summary>Disassembled `jump_table_test_func` dumped with `-debug-_only_=bolt-pauth-scanner`</summary>
```
Binary Function "_Z11catching_fnv" {
Number : 1
State : CFG constructed
Address : 0x10740
Size : 0x68
MaxSize : 0x68
Offset : 0x740
Section : .text
Orc Section : .local.text._Z11catching_fnv
LSDA : 0x640
IsSimple : 1
IsMultiEntry: 0
IsSplit : 0
BB Count : 6
Personality : DW.ref.__gxx_personality_v0/1
Hash : 2767dbf2af332197
CFI Instrs : 21
BB Layout : .LBB00, .LLP0, .LFT0, .LLP1, .Ltmp0, .LLP2
}
.LBB00 (26 instructions, align : 1)
Entry Point
CFI State : 0
00000000: pacibsp
00000004: stp x29, x30, [sp, #-0x20]!
00000008: !CFI $0 ; OpDefCfaOffset 32
00000008: str x19, [sp, #0x10]
0000000c: mov x29, sp
00000010: !CFI $1 ; OpDefCfa Reg29 32
00000010: !CFI $2 ; OpOffset Reg19 -16
00000010: !CFI $3 ; OpOffset Reg30 -24
00000010: !CFI $4 ; OpOffset Reg29 -32
00000010: !CFI $5 ; OpRememberState
00000010: bl _Z11throwing_fnv@PLT # handler: .LLP0; action: 1
00000014: mov w0, #0x2a
00000018: !CFI $6 ; OpDefCfa Reg31 32
00000018: ldr x19, [sp, #0x10]
0000001c: ldp x29, x30, [sp], #0x20
00000020: !CFI $7 ; OpDefCfaOffset 0
00000020: !CFI $8 ; OpRestore Reg19
00000020: !CFI $9 ; OpRestore Reg30
00000020: !CFI $10 ; OpRestore Reg29
00000020: retab
00000024: !CFI $19 ; OpDefCfa Reg29 32
00000024: !CFI $2 ; OpOffset Reg19 -16
00000024: !CFI $3 ; OpOffset Reg30 -24
00000024: !CFI $4 ; OpOffset Reg29 -32
00000024: !CFI $11 ; OpRestoreState
00000024: !CFI $12 ; OpRememberState
Landing Pads: .LLP0
CFI State: 13
.LLP0 (3 instructions, align : 1)
Landing Pad
CFI State : 13
Throwers: .LBB00
00000024: cmp w1, #0x1
00000028: mov x19, x0
0000002c: b.ne .Ltmp0
Successors: .Ltmp0, .LFT0
CFI State: 13
.LFT0 (19 instructions, align : 1)
CFI State : 13
Predecessors: .LLP0
00000030: mov x0, x19
00000034: bl __cxa_begin_catch@PLT # handler: 0; action: 0
00000038: mov w0, #0x1
0000003c: bl _Z8callbacki@PLT # handler: .LLP1; action: 0
00000040: bl __cxa_end_catch@PLT # handler: 0; action: 0
00000044: mov w0, #0x2a
00000048: !CFI $13 ; OpDefCfa Reg31 32
00000048: ldr x19, [sp, #0x10]
0000004c: ldp x29, x30, [sp], #0x20
00000050: !CFI $14 ; OpDefCfaOffset 0
00000050: !CFI $15 ; OpRestore Reg19
00000050: !CFI $16 ; OpRestore Reg30
00000050: !CFI $17 ; OpRestore Reg29
00000050: retab
00000054: !CFI $20 ; OpDefCfa Reg29 32
00000054: !CFI $2 ; OpOffset Reg19 -16
00000054: !CFI $3 ; OpOffset Reg30 -24
00000054: !CFI $4 ; OpOffset Reg29 -32
00000054: !CFI $18 ; OpRestoreState
Landing Pads: .LLP1
CFI State: 5
.LLP1 (2 instructions, align : 1)
Landing Pad
CFI State : 5
Throwers: .LFT0
00000054: mov x19, x0
00000058: bl __cxa_end_catch@PLT # handler: .LLP2; action: 3
Successors: .Ltmp0
Landing Pads: .LLP2
CFI State: 5
.Ltmp0 (2 instructions, align : 1)
CFI State : 5
Predecessors: .LLP0, .LLP1
0000005c: mov x0, x19
00000060: bl _Unwind_Resume@PLT # handler: 0; action: 0
Successors: .LLP2
CFI State: 5
.LLP2 (1 instructions, align : 1)
Landing Pad
CFI State : 5
Predecessors: .Ltmp0
Throwers: .LLP1
00000064: bl "__clang_call_terminate/1" # handler: 0; action: 0
CFI State: 5
DWARF CFI Instructions:
0: OpDefCfaOffset 32
1: OpDefCfa Reg29 32
2: OpOffset Reg19 -16
3: OpOffset Reg30 -24
4: OpOffset Reg29 -32
5: OpRememberState
6: OpDefCfa Reg31 32
7: OpDefCfaOffset 0
8: OpRestore Reg19
9: OpRestore Reg30
10: OpRestore Reg29
11: OpRestoreState
12: OpRememberState
13: OpDefCfa Reg31 32
14: OpDefCfaOffset 0
15: OpRestore Reg19
16: OpRestore Reg30
17: OpRestore Reg29
18: OpRestoreState
19: OpDefCfa Reg29 32
20: OpDefCfa Reg29 32
End of Function "_Z11catching_fnv"
```
</details>
Note that `.LLP0` basic block has no `Predecessors:` field (i.e. the list is
empty), but is marked as `Landing Pad`.
## Possible solutions
The easiest solution would probably be to initialize the state of landing pads to
all-registers-are-unsafe. This way, we would mark them as *not unexpected*.
Some registers may be marked as safe-to-dereference or trusted, according to
the ABI, but I'm not aware of any such guaranties.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs