Issue 178232
Summary [BOLT][Gadget scanner] CFG is constructed when it should not in relocation mode
Labels BOLT
Assignees
Reporter atrosinenko
    Various tests under `bolt/test/binary-analysis/AArch64/` use the same pattern to inhibit CFG reconstruction in `*_nocfg` test cases:

```asm
  adr xN, 1f
 br  xN
1:
  ; ... actual test case ...
```

Adding a recommended `-Wl,--emit-relocs` option to the `RUN: %clang ...` line breaks the tests, as CFG is now formally reconstructed for these functions (but `br xN` is still annotated with an `# UNKNOWN CONTROL FLOW` comment, that is why I say "formally").

For a function to be affected, it does not necessarily have to contain relocation, but relocations have to be emitted for any function in the binary.

## How to reproduce

Compile the following source:

```asm
  .text

  .globl  func
  .type func,@function
func:
  adr     x1, 1f
  br      x1
1:
  ret     x0
 .size   func, .-func

  .globl  other_func
  .type other_func,@function
other_func:
  adr     x0, sym
  ret
  .size other_func, .-other_func
```

without `-Wl,--emit-relocs`:

```
clang -target aarch64-linux-gnu -march=armv8.3-a -fuse-ld=lld \
 -Wl,--unresolved-symbols=ignore-all -nostdlib \
      nocfg-test.s -o nocfg-test
```

As expected, a report for non-protected `ret x0` is generated. Note that it does not mention `..., basic block <name>, ...` in the first line of the report:

```
$ ./bin/llvm-bolt-binary-analysis --scanners=pauth ./nocfg-test
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-WARNING: non-relocation mode for AArch64 is not fully supported

GS-PAUTH: non-protected ret found in function func, at address 102b8
  The instruction is     000102b8:      ret     x0 # Offset: 8
  The 0 instructions that write to the affected registers after any authentication are:
```

<details>
<summary>Disassembled function dumped with `-no-threads -debug-_only_=bolt-pauth-scanner`</summary>

`func` has `State: disassembled`, `IsSimple: 0` and `BB Count: 0`.

```
Binary Function "func"  {
  Number      : 1
  State       : disassembled
  Address     : 0x102b0
  Size        : 0xc
  MaxSize     : 0xc
  Offset      : 0x2b0
 Section     : .text
  Orc Section : .local.text.func
  LSDA        : 0x0
 IsSimple    : 0
  IsMultiEntry: 1
  IsSplit     : 0
  BB Count    : 0
 Secondary Entry Points : __ENTRY_func@0x102b8
}
.LBB00:
    00000000: adr     x1, __ENTRY_func@0x102b8
    00000004:   br      x1 # UNKNOWN CONTROL FLOW # Offset: 4
__ENTRY_func@0x102b8 (Entry Point):
.Ltmp0:
 00000008:   ret     x0 # Offset: 8
DWARF CFI Instructions:
    <empty>
End of Function "func"

# ...

Binary Function "other_func"  {
  Number : 2
  State       : CFG constructed
  Address     : 0x102bc
  Size : 0x8
  MaxSize     : 0x8
  Offset      : 0x2bc
  Section     : .text
 Orc Section : .local.text.other_func
  LSDA        : 0x0
  IsSimple    : 1
  IsMultiEntry: 0
  IsSplit     : 0
  BB Count    : 1
  Hash        : 3cab5d975d7c2f39
  BB Layout   : .LBB01
}
.LBB01 (2 instructions, align : 1)
  Entry Point
    00000000:   adr     x0, other_func
    00000004: ret

DWARF CFI Instructions:
    <empty>
End of Function "other_func"
```

</details>

Then, recompile `nocfg-test` binary with `-Wl,--emit-relocs` option. The output of gadget scanner is now

```
$ ./bin/llvm-bolt-binary-analysis --scanners=pauth ./nocfg-test
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

GS-PAUTH: non-protected ret found in function func, basic block .Ltmp0, at address 102b8
  The instruction is     000102b8:      ret     x0
  The 0 instructions that write to the affected registers after any authentication are:
```

CFG information is formally available now, which can be seen by the basic block name being mentioned in the report.

<details>
<summary>Disassembled function dumped with `-no-threads -debug-_only_=bolt-pauth-scanner`</summary>

`func` has `State: CFG constructed`, `IsSimple: 0` and `BB Count: 2`.

```
Binary Function "func"  {
  Number      : 1
  State       : CFG constructed
  Address : 0x102b0
  Size        : 0xc
  MaxSize     : 0xc
  Offset      : 0x2b0
 Section     : .text
  Orc Section : .local.text.func
  LSDA        : 0x0
 IsSimple    : 0
  IsMultiEntry: 1
  IsSplit     : 0
  BB Count    : 2
 Hash        : 592111a3fb9ca883
  Secondary Entry Points : __ENTRY_func@0x102b8
  BB Layout   : .LBB00, .Ltmp0
}
.LBB00 (2 instructions, align : 1)
  Entry Point
    00000000:   adr     x1, __ENTRY_func@0x102b8
    00000004:   br      x1 # UNKNOWN CONTROL FLOW

.Ltmp0 (1 instructions, align : 1)
  Secondary Entry Point: __ENTRY_func@0x102b8
    00000008:   ret     x0

DWARF CFI Instructions:
 <empty>
End of Function "func"

# ...

Binary Function "other_func"  {
  Number      : 2
  State       : CFG constructed
 Address     : 0x102bc
  Size        : 0x8
  MaxSize     : 0x8
  Offset : 0x2bc
  Section     : .text
  Orc Section : .local.text.other_func
 LSDA        : 0x0
  IsSimple    : 1
  IsMultiEntry: 0
  IsSplit     : 0
 BB Count    : 1
  Hash        : 3cab5d975d7c2f39
  BB Layout   : .LBB01
}
.LBB01 (2 instructions, align : 1)
  Entry Point
    00000000: adr     x0, other_func
    00000004:   ret

DWARF CFI Instructions:
 <empty>
End of Function "other_func"
```

</details>

Removing `other_func` eliminates the only emitted relocation from `nocfg-test` binary, resulting in restoring the original behavior of treating `func` as not having a valid CFG (whether `-Wl,--emit-relocs` is passed or not).

<details>
<summary>Disassembled function dumped with `-no-threads -debug-_only_=bolt-pauth-scanner`</summary>

```
Binary Function "func" {
  Number      : 1
  State       : disassembled
  Address     : 0x102b0
 Size        : 0xc
  MaxSize     : 0xc
  Offset      : 0x2b0
  Section : .text
  Orc Section : .local.text.func
  LSDA        : 0x0
  IsSimple : 0
  IsMultiEntry: 1
  IsSplit     : 0
  BB Count    : 0
  Secondary Entry Points : __ENTRY_func@0x102b8
}
.LBB00:
    00000000:   adr     x1, __ENTRY_func@0x102b8
    00000004:   br      x1 # UNKNOWN CONTROL FLOW # Offset: 4
__ENTRY_func@0x102b8 (Entry Point):
.Ltmp0:
    00000008:   ret x0 # Offset: 8
DWARF CFI Instructions:
    <empty>
End of Function "func"
```

</details>
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to