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

Reply via email to