Skip to content

Commit 6795bfc

Browse files
authored
[BOLT][RISCV] Handle CIE's produced by GNU as (#69578)
On RISC-V, GNU as produces the following initial instruction in CIE's: ``` DW_CFA_def_cfa_register: r2 ``` While I believe it is technically illegal to use this instruction without first using a `DW_CFA_def_cfa` (since the offset is undefined), both `readelf` and `llvm-dwarfdump` accept this and implicitly set the offset to 0. In BOLT, however, this triggers an assert (in `CFISnapshot::advanceTo`) as it (correctly) believes the offset is not set. This patch fixes this by setting the offset to 0 whenever executing `DW_CFA_def_cfa_register` while the offset is undefined. Note that this is probably the simplest workaround but it has a downside: while emitting CFI start, we check if the initial instructions are contained within `MCAsmInfo::getInitialFrameState` and omit them if they are. This will not be true for GNU CIE's (since they differ from LLVM's) which causes an unnecessary `DW_CFA_def_cfa_register` to be emitted. While technically correct, it would probably be better to replace the GNU CIE with the one used by LLVM to avoid this situation. This would solve the problem this patch solves while also preventing unnecessary CFI instructions. However, this is a bit trickier to implement correctly so I propose to keep this for a later time. Note on testing: the test creates a simple function with three basic blocks and forces the CFI state of the last one to be different from the others using an arbitrary CFI instruction. Then, `--reorder-blocks=reverse` is used to force `CFISnapshot::advanceTo` to be called. This causes an assert on the current main branch.
1 parent 3c07a21 commit 6795bfc

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2462,6 +2462,13 @@ struct CFISnapshot {
24622462
case MCCFIInstruction::OpDefCfaRegister:
24632463
CFAReg = Instr.getRegister();
24642464
CFARule = UNKNOWN;
2465+
2466+
// This shouldn't happen according to the spec but GNU binutils on RISC-V
2467+
// emits a DW_CFA_def_cfa_register in CIE's which leaves the offset
2468+
// unspecified. Both readelf and llvm-dwarfdump interpret the offset as 0
2469+
// in this case so let's do the same.
2470+
if (CFAOffset == UNKNOWN)
2471+
CFAOffset = 0;
24652472
break;
24662473
case MCCFIInstruction::OpDefCfaOffset:
24672474
CFAOffset = Instr.getOffset();

bolt/test/RISCV/Inputs/cie-gnu.yaml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
## Compiled and stripped-down version of:
2+
## (riscv64-linux-gnu-gcc -nostdlib -static -Wl,-q cie-gnu.s)
3+
# .text
4+
# .globl _start
5+
# .type _start, @function
6+
# _start:
7+
# .cfi_startproc
8+
# beq a0, a1, 1f
9+
# ret
10+
# 1:
11+
# .cfi_undefined t0 # Arbitrary cfi command to force a new state
12+
# ret
13+
# .cfi_endproc
14+
# .size _start, .-_start
15+
16+
--- !ELF
17+
FileHeader:
18+
Class: ELFCLASS64
19+
Data: ELFDATA2LSB
20+
Type: ET_EXEC
21+
Machine: EM_RISCV
22+
Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_DOUBLE ]
23+
Entry: 0x10144
24+
ProgramHeaders:
25+
- Type: PT_LOAD
26+
Flags: [ PF_X, PF_R ]
27+
FirstSec: .text
28+
LastSec: .eh_frame
29+
VAddr: 0x10000
30+
Align: 0x1000
31+
Offset: 0x0
32+
Sections:
33+
- Name: .text
34+
Type: SHT_PROGBITS
35+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
36+
Address: 0x10144
37+
AddressAlign: 0x2
38+
Offset: 0x144
39+
Content: 6303B50082808280
40+
- Name: .eh_frame
41+
Type: SHT_PROGBITS
42+
Flags: [ SHF_ALLOC ]
43+
Address: 0x10150
44+
AddressAlign: 0x8
45+
Content: 1000000000000000037A5200017C01011B0D02001000000018000000D8FFFFFF0800000000460705
46+
- Name: .rela.text
47+
Type: SHT_RELA
48+
Flags: [ SHF_INFO_LINK ]
49+
Link: .symtab
50+
AddressAlign: 0x8
51+
Info: .text
52+
Relocations:
53+
- Offset: 0x10144
54+
Symbol: ".L1\x021"
55+
Type: R_RISCV_BRANCH
56+
- Name: .rela.eh_frame
57+
Type: SHT_RELA
58+
Flags: [ SHF_INFO_LINK ]
59+
Link: .symtab
60+
AddressAlign: 0x8
61+
Info: .eh_frame
62+
Relocations:
63+
- Offset: 0x1016C
64+
Symbol: '.L0 '
65+
Type: R_RISCV_32_PCREL
66+
- Offset: 0x10170
67+
Symbol: '.L0 (1)'
68+
Type: R_RISCV_ADD32
69+
- Offset: 0x10170
70+
Symbol: '.L0 '
71+
Type: R_RISCV_SUB32
72+
- Offset: 0x10175
73+
Symbol: '.L0 (2)'
74+
Type: R_RISCV_SET6
75+
- Offset: 0x10175
76+
Symbol: '.L0 '
77+
Type: R_RISCV_SUB6
78+
- Type: SectionHeaderTable
79+
Sections:
80+
- Name: .text
81+
- Name: .rela.text
82+
- Name: .eh_frame
83+
- Name: .rela.eh_frame
84+
- Name: .symtab
85+
- Name: .strtab
86+
- Name: .shstrtab
87+
Symbols:
88+
- Name: '$x'
89+
Section: .text
90+
Value: 0x10144
91+
- Name: ".L1\x021"
92+
Section: .text
93+
Value: 0x1014A
94+
- Name: '.L0 '
95+
Section: .text
96+
Value: 0x10144
97+
- Name: '.L0 (1)'
98+
Section: .text
99+
Value: 0x1014C
100+
- Name: '.L0 (2)'
101+
Section: .text
102+
Value: 0x1014A
103+
- Name: _start
104+
Type: STT_FUNC
105+
Section: .text
106+
Binding: STB_GLOBAL
107+
Value: 0x10144
108+
Size: 0x8
109+
...

bolt/test/RISCV/cie-gnu.test

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Test that BOLT can handle CIE's produced by GNU as. On RISC-V, GNU as produces
2+
# the following initial instruction:
3+
# DW_CFA_def_cfa_register: r2
4+
# While I believe it is technically incorrect to use this instruction without
5+
# first using a DW_CFA_def_cfa (since the offset is unspecified), both readelf
6+
# and llvm-dwarfdump accept this and implicitly set the offset to 0.
7+
# In BOLT, this used to trigger an assert, however, since it (correctly)
8+
# believed the offset was not set. This test checks we can handle this
9+
# situation.
10+
11+
RUN: yaml2obj -o %t %p/Inputs/cie-gnu.yaml
12+
RUN: llvm-bolt -o %t.bolt %t --reorder-blocks=reverse
13+
RUN: llvm-dwarfdump --debug-frame %t.bolt | FileCheck %s
14+
15+
CHECK: 0x400000: CFA=X2
16+
CHECK: 0x400004: CFA=X2: X5=undefined
17+
CHECK: 0x400006: CFA=X2

0 commit comments

Comments
 (0)