Skip to content

Commit 4f6757c

Browse files
hahnjomtvec
andauthored
[JITLink][RISCV] Implement eh_frame handling (#68253)
This requires adding a `NegDelta32` edge kind that cannot be mapped to existing relocations. Co-authored-by: Job Noorman <[email protected]>
1 parent fc6bdb8 commit 4f6757c

File tree

7 files changed

+204
-7
lines changed

7 files changed

+204
-7
lines changed

clang/test/Interpreter/simple-exception.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// clang-format off
22
// UNSUPPORTED: system-aix
3-
// XFAIL for arm, arm64, riscv, or running on Windows.
4-
// XFAIL: target={{(arm|riscv).*}}, system-windows
3+
// XFAIL for arm and arm64, or running on Windows.
4+
// XFAIL: target=arm{{.*}}, system-windows
55
// RUN: cat %s | clang-repl | FileCheck %s
66

77
// Incompatible with msan. It passes with -O3 but fail -Oz. Interpreter

clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,6 @@ extern "C" int throw_exception() {
122122
Triple.getArch() == llvm::Triple::aarch64_32))
123123
GTEST_SKIP();
124124

125-
// FIXME: RISC-V fails as .eh_frame handling is not yet implemented in
126-
// JITLink for RISC-V. See PR #66067.
127-
if (Triple.isRISCV())
128-
GTEST_SKIP();
129-
130125
llvm::cantFail(Interp->ParseAndExecute(ExceptionCode));
131126
testing::internal::CaptureStdout();
132127
auto ThrowException =

llvm/include/llvm/ExecutionEngine/JITLink/riscv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,12 @@ enum EdgeKind_riscv : Edge::Kind {
214214
/// Linker relaxation will use this to ensure all code sequences are properly
215215
/// aligned and then remove these edges from the graph.
216216
AlignRelaxable,
217+
218+
/// 32-bit negative delta.
219+
///
220+
/// Fixup expression:
221+
/// Fixup <- Fixup - Target + Addend
222+
NegDelta32,
217223
};
218224

219225
/// Returns a string name for the given riscv edge. For debugging purposes

llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "llvm/ExecutionEngine/JITLink/ELF_riscv.h"
14+
#include "EHFrameSupportImpl.h"
1415
#include "ELFLinkGraphBuilder.h"
1516
#include "JITLinkGeneric.h"
1617
#include "PerGraphGOTAndPLTStubsBuilder.h"
1718
#include "llvm/BinaryFormat/ELF.h"
19+
#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
1820
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
1921
#include "llvm/ExecutionEngine/JITLink/riscv.h"
2022
#include "llvm/Object/ELF.h"
@@ -456,6 +458,13 @@ class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
456458
case AlignRelaxable:
457459
// Ignore when the relaxation pass did not run
458460
break;
461+
case NegDelta32: {
462+
int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
463+
if (LLVM_UNLIKELY(!isInRangeForImm(Value, 32)))
464+
return makeTargetOutOfRangeError(G, B, E);
465+
*(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
466+
break;
467+
}
459468
}
460469
return Error::success();
461470
}
@@ -958,6 +967,13 @@ void link_ELF_riscv(std::unique_ptr<LinkGraph> G,
958967
PassConfiguration Config;
959968
const Triple &TT = G->getTargetTriple();
960969
if (Ctx->shouldAddDefaultTargetPasses(TT)) {
970+
971+
Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
972+
Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
973+
".eh_frame", G->getPointerSize(), Edge::Invalid, Edge::Invalid,
974+
Edge::Invalid, Edge::Invalid, NegDelta32));
975+
Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
976+
961977
if (auto MarkLive = Ctx->getMarkLivePass(TT))
962978
Config.PrePrunePasses.push_back(std::move(MarkLive));
963979
else

llvm/lib/ExecutionEngine/JITLink/riscv.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ const char *getEdgeKindName(Edge::Kind K) {
8282
return "CallRelaxable";
8383
case AlignRelaxable:
8484
return "AlignRelaxable";
85+
case NegDelta32:
86+
return "NegDelta32";
8587
}
8688
return getGenericEdgeKindName(K);
8789
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# REQUIRES: asserts
2+
3+
# RUN: llvm-mc -triple=riscv32-linux-gnu -mattr=+relax -filetype=obj -o %t.32.o %s
4+
# RUN: llvm-jitlink -noexec -phony-externals -debug-only=jitlink %t.32.o 2>&1 | \
5+
# RUN: FileCheck %s
6+
7+
# RUN: llvm-mc -triple=riscv64-linux-gnu -mattr=+relax -filetype=obj -o %t.64.o %s
8+
# RUN: llvm-jitlink -noexec -phony-externals -debug-only=jitlink %t.64.o 2>&1 | \
9+
# RUN: FileCheck %s
10+
11+
# Check that splitting of eh-frame sections works.
12+
#
13+
# CHECK: DWARFRecordSectionSplitter: Processing .eh_frame...
14+
# CHECK: Processing block at
15+
# CHECK: Processing CFI record at
16+
# CHECK: Extracted {{.*}} section = .eh_frame
17+
# CHECK: Processing CFI record at
18+
# CHECK: Extracted {{.*}} section = .eh_frame
19+
# CHECK: EHFrameEdgeFixer: Processing .eh_frame in "{{.*}}"...
20+
# CHECK: Processing block at
21+
# CHECK: Record is CIE
22+
# CHECK: Processing block at
23+
# CHECK: Record is FDE
24+
# CHECK: Adding edge at {{.*}} to CIE at: {{.*}}
25+
# CHECK: Existing edge at {{.*}} to PC begin at {{.*}}
26+
# CHECK: Adding keep-alive edge from target at {{.*}} to FDE at {{.*}}
27+
# CHECK: Processing block at
28+
# CHECK: Record is FDE
29+
# CHECK: Adding edge at {{.*}} to CIE at: {{.*}}
30+
# CHECK: Existing edge at {{.*}} to PC begin at {{.*}}
31+
# CHECK: Adding keep-alive edge from target at {{.*}} to FDE at {{.*}}
32+
33+
## This is "int main { throw 1; }" compiled for riscv32. We use the 32-bit
34+
## version because it is also legal for riscv64.
35+
.text
36+
.globl main
37+
.p2align 1
38+
.type main,@function
39+
main:
40+
.cfi_startproc
41+
addi sp, sp, -16
42+
.cfi_def_cfa_offset 16
43+
sw ra, 12(sp)
44+
.cfi_offset ra, -4
45+
li a0, 4
46+
call __cxa_allocate_exception
47+
li a1, 1
48+
sw a1, 0(a0)
49+
lga a1, _ZTIi
50+
li a2, 0
51+
call __cxa_throw
52+
.Lfunc_end0:
53+
.size main, .Lfunc_end0-main
54+
.cfi_endproc
55+
56+
.globl dup
57+
.p2align 1
58+
.type dup,@function
59+
dup:
60+
.cfi_startproc
61+
addi sp, sp, -16
62+
.cfi_def_cfa_offset 16
63+
sw ra, 12(sp)
64+
.cfi_offset ra, -4
65+
li a0, 4
66+
call __cxa_allocate_exception
67+
li a1, 1
68+
sw a1, 0(a0)
69+
lga a1, _ZTIi
70+
li a2, 0
71+
call __cxa_throw
72+
.Lfunc_end1:
73+
.size dup, .Lfunc_end1-dup
74+
.cfi_endproc
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# RUN: yaml2obj -DELFCLASS=ELFCLASS32 -o %t.32.o %s
2+
# RUN: llvm-jitlink -noexec -check %s %t.32.o
3+
# RUN: yaml2obj -DELFCLASS=ELFCLASS64 -o %t.64.o %s
4+
# RUN: llvm-jitlink -noexec -check %s %t.64.o
5+
6+
### Compiled from the following code with -mattr=+relax to force relocations for
7+
### address_range and DW_CFA_advance_loc (both needed for .balign).
8+
## .text
9+
## .globl main
10+
## .p2align 1
11+
## .type main,@function
12+
## main:
13+
## .cfi_startproc
14+
## .balign 8
15+
## addi sp, sp, -16
16+
## cfa_advance_loc:
17+
## .cfi_def_cfa_offset 16
18+
## nop
19+
## main_end:
20+
## .size main, main_end-main
21+
## .cfi_endproc
22+
23+
--- !ELF
24+
FileHeader:
25+
Class: [[ELFCLASS]]
26+
Data: ELFDATA2LSB
27+
Type: ET_REL
28+
Machine: EM_RISCV
29+
SectionHeaderStringTable: .strtab
30+
Sections:
31+
- Name: .text
32+
Type: SHT_PROGBITS
33+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
34+
AddressAlign: 0x8
35+
Content: 13000000130101FF13000000
36+
- Name: .eh_frame
37+
Type: SHT_PROGBITS
38+
Flags: [ SHF_ALLOC ]
39+
AddressAlign: 0x8
40+
Content: 1000000000000000017A5200017801011B0C02001000000018000000000000000000000000400E10
41+
- Name: .rela.text
42+
Type: SHT_RELA
43+
Flags: [ SHF_INFO_LINK ]
44+
Link: .symtab
45+
AddressAlign: 0x8
46+
Info: .text
47+
Relocations:
48+
- Type: R_RISCV_ALIGN
49+
Addend: 4
50+
- Name: .rela.eh_frame
51+
Type: SHT_RELA
52+
Flags: [ SHF_INFO_LINK ]
53+
Link: .symtab
54+
AddressAlign: 0x8
55+
Info: .eh_frame
56+
Relocations:
57+
- Offset: 0x1C
58+
Symbol: main
59+
Type: R_RISCV_32_PCREL
60+
- Offset: 0x20
61+
Symbol: main_end
62+
Type: R_RISCV_ADD32
63+
- Offset: 0x20
64+
Symbol: main
65+
Type: R_RISCV_SUB32
66+
- Offset: 0x25
67+
Symbol: cfa_advance_loc
68+
Type: R_RISCV_SET6
69+
- Offset: 0x25
70+
Symbol: main
71+
Type: R_RISCV_SUB6
72+
- Type: SectionHeaderTable
73+
Sections:
74+
- Name: .strtab
75+
- Name: .text
76+
- Name: .rela.text
77+
- Name: .eh_frame
78+
- Name: .rela.eh_frame
79+
- Name: .symtab
80+
Symbols:
81+
- Name: cfa_advance_loc
82+
Section: .text
83+
Value: 0x8
84+
- Name: main_end
85+
Section: .text
86+
Value: 0xC
87+
- Name: main
88+
Type: STT_FUNC
89+
Section: .text
90+
Binding: STB_GLOBAL
91+
Size: 0xC
92+
- Name: eh_frame
93+
Type: STT_SECTION
94+
Binding: STB_GLOBAL
95+
Section: .eh_frame
96+
Size: 0x28
97+
...
98+
99+
## CIE_pointer
100+
# jitlink-check: *{4}(eh_frame + 0x1c) = main - (eh_frame + 0x1c)
101+
## address_range
102+
# jitlink-check: *{4}(eh_frame + 0x20) = main_end - main
103+
## DW_CFA_advance_loc
104+
# jitlink-check: (*{1}(eh_frame + 0x25)) & 0x3f = cfa_advance_loc - main

0 commit comments

Comments
 (0)