[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 <jnoorman@igalia.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// clang-format off
|
||||
// UNSUPPORTED: system-aix
|
||||
// XFAIL for arm, arm64, riscv, or running on Windows.
|
||||
// XFAIL: target={{(arm|riscv).*}}, system-windows
|
||||
// XFAIL for arm and arm64, or running on Windows.
|
||||
// XFAIL: target=arm{{.*}}, system-windows
|
||||
// RUN: cat %s | clang-repl | FileCheck %s
|
||||
|
||||
// Incompatible with msan. It passes with -O3 but fail -Oz. Interpreter
|
||||
|
||||
@@ -122,11 +122,6 @@ extern "C" int throw_exception() {
|
||||
Triple.getArch() == llvm::Triple::aarch64_32))
|
||||
GTEST_SKIP();
|
||||
|
||||
// FIXME: RISC-V fails as .eh_frame handling is not yet implemented in
|
||||
// JITLink for RISC-V. See PR #66067.
|
||||
if (Triple.isRISCV())
|
||||
GTEST_SKIP();
|
||||
|
||||
llvm::cantFail(Interp->ParseAndExecute(ExceptionCode));
|
||||
testing::internal::CaptureStdout();
|
||||
auto ThrowException =
|
||||
|
||||
@@ -214,6 +214,12 @@ enum EdgeKind_riscv : Edge::Kind {
|
||||
/// Linker relaxation will use this to ensure all code sequences are properly
|
||||
/// aligned and then remove these edges from the graph.
|
||||
AlignRelaxable,
|
||||
|
||||
/// 32-bit negative delta.
|
||||
///
|
||||
/// Fixup expression:
|
||||
/// Fixup <- Fixup - Target + Addend
|
||||
NegDelta32,
|
||||
};
|
||||
|
||||
/// Returns a string name for the given riscv edge. For debugging purposes
|
||||
|
||||
@@ -11,10 +11,12 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ExecutionEngine/JITLink/ELF_riscv.h"
|
||||
#include "EHFrameSupportImpl.h"
|
||||
#include "ELFLinkGraphBuilder.h"
|
||||
#include "JITLinkGeneric.h"
|
||||
#include "PerGraphGOTAndPLTStubsBuilder.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
|
||||
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
|
||||
#include "llvm/ExecutionEngine/JITLink/riscv.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
@@ -456,6 +458,13 @@ private:
|
||||
case AlignRelaxable:
|
||||
// Ignore when the relaxation pass did not run
|
||||
break;
|
||||
case NegDelta32: {
|
||||
int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
|
||||
if (LLVM_UNLIKELY(!isInRangeForImm(Value, 32)))
|
||||
return makeTargetOutOfRangeError(G, B, E);
|
||||
*(little32_t *)FixupPtr = static_cast<uint32_t>(Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
@@ -958,6 +967,13 @@ void link_ELF_riscv(std::unique_ptr<LinkGraph> G,
|
||||
PassConfiguration Config;
|
||||
const Triple &TT = G->getTargetTriple();
|
||||
if (Ctx->shouldAddDefaultTargetPasses(TT)) {
|
||||
|
||||
Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
|
||||
Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
|
||||
".eh_frame", G->getPointerSize(), Edge::Invalid, Edge::Invalid,
|
||||
Edge::Invalid, Edge::Invalid, NegDelta32));
|
||||
Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
|
||||
|
||||
if (auto MarkLive = Ctx->getMarkLivePass(TT))
|
||||
Config.PrePrunePasses.push_back(std::move(MarkLive));
|
||||
else
|
||||
|
||||
@@ -82,6 +82,8 @@ const char *getEdgeKindName(Edge::Kind K) {
|
||||
return "CallRelaxable";
|
||||
case AlignRelaxable:
|
||||
return "AlignRelaxable";
|
||||
case NegDelta32:
|
||||
return "NegDelta32";
|
||||
}
|
||||
return getGenericEdgeKindName(K);
|
||||
}
|
||||
|
||||
74
llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.s
Normal file
74
llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.s
Normal file
@@ -0,0 +1,74 @@
|
||||
# REQUIRES: asserts
|
||||
|
||||
# RUN: llvm-mc -triple=riscv32-linux-gnu -mattr=+relax -filetype=obj -o %t.32.o %s
|
||||
# RUN: llvm-jitlink -noexec -phony-externals -debug-only=jitlink %t.32.o 2>&1 | \
|
||||
# RUN: FileCheck %s
|
||||
|
||||
# RUN: llvm-mc -triple=riscv64-linux-gnu -mattr=+relax -filetype=obj -o %t.64.o %s
|
||||
# RUN: llvm-jitlink -noexec -phony-externals -debug-only=jitlink %t.64.o 2>&1 | \
|
||||
# RUN: FileCheck %s
|
||||
|
||||
# Check that splitting of eh-frame sections works.
|
||||
#
|
||||
# CHECK: DWARFRecordSectionSplitter: Processing .eh_frame...
|
||||
# CHECK: Processing block at
|
||||
# CHECK: Processing CFI record at
|
||||
# CHECK: Extracted {{.*}} section = .eh_frame
|
||||
# CHECK: Processing CFI record at
|
||||
# CHECK: Extracted {{.*}} section = .eh_frame
|
||||
# CHECK: EHFrameEdgeFixer: Processing .eh_frame in "{{.*}}"...
|
||||
# CHECK: Processing block at
|
||||
# CHECK: Record is CIE
|
||||
# CHECK: Processing block at
|
||||
# CHECK: Record is FDE
|
||||
# CHECK: Adding edge at {{.*}} to CIE at: {{.*}}
|
||||
# CHECK: Existing edge at {{.*}} to PC begin at {{.*}}
|
||||
# CHECK: Adding keep-alive edge from target at {{.*}} to FDE at {{.*}}
|
||||
# CHECK: Processing block at
|
||||
# CHECK: Record is FDE
|
||||
# CHECK: Adding edge at {{.*}} to CIE at: {{.*}}
|
||||
# CHECK: Existing edge at {{.*}} to PC begin at {{.*}}
|
||||
# CHECK: Adding keep-alive edge from target at {{.*}} to FDE at {{.*}}
|
||||
|
||||
## This is "int main { throw 1; }" compiled for riscv32. We use the 32-bit
|
||||
## version because it is also legal for riscv64.
|
||||
.text
|
||||
.globl main
|
||||
.p2align 1
|
||||
.type main,@function
|
||||
main:
|
||||
.cfi_startproc
|
||||
addi sp, sp, -16
|
||||
.cfi_def_cfa_offset 16
|
||||
sw ra, 12(sp)
|
||||
.cfi_offset ra, -4
|
||||
li a0, 4
|
||||
call __cxa_allocate_exception
|
||||
li a1, 1
|
||||
sw a1, 0(a0)
|
||||
lga a1, _ZTIi
|
||||
li a2, 0
|
||||
call __cxa_throw
|
||||
.Lfunc_end0:
|
||||
.size main, .Lfunc_end0-main
|
||||
.cfi_endproc
|
||||
|
||||
.globl dup
|
||||
.p2align 1
|
||||
.type dup,@function
|
||||
dup:
|
||||
.cfi_startproc
|
||||
addi sp, sp, -16
|
||||
.cfi_def_cfa_offset 16
|
||||
sw ra, 12(sp)
|
||||
.cfi_offset ra, -4
|
||||
li a0, 4
|
||||
call __cxa_allocate_exception
|
||||
li a1, 1
|
||||
sw a1, 0(a0)
|
||||
lga a1, _ZTIi
|
||||
li a2, 0
|
||||
call __cxa_throw
|
||||
.Lfunc_end1:
|
||||
.size dup, .Lfunc_end1-dup
|
||||
.cfi_endproc
|
||||
104
llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.test
Normal file
104
llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.test
Normal file
@@ -0,0 +1,104 @@
|
||||
# RUN: yaml2obj -DELFCLASS=ELFCLASS32 -o %t.32.o %s
|
||||
# RUN: llvm-jitlink -noexec -check %s %t.32.o
|
||||
# RUN: yaml2obj -DELFCLASS=ELFCLASS64 -o %t.64.o %s
|
||||
# RUN: llvm-jitlink -noexec -check %s %t.64.o
|
||||
|
||||
### Compiled from the following code with -mattr=+relax to force relocations for
|
||||
### address_range and DW_CFA_advance_loc (both needed for .balign).
|
||||
## .text
|
||||
## .globl main
|
||||
## .p2align 1
|
||||
## .type main,@function
|
||||
## main:
|
||||
## .cfi_startproc
|
||||
## .balign 8
|
||||
## addi sp, sp, -16
|
||||
## cfa_advance_loc:
|
||||
## .cfi_def_cfa_offset 16
|
||||
## nop
|
||||
## main_end:
|
||||
## .size main, main_end-main
|
||||
## .cfi_endproc
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: [[ELFCLASS]]
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_RISCV
|
||||
SectionHeaderStringTable: .strtab
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
AddressAlign: 0x8
|
||||
Content: 13000000130101FF13000000
|
||||
- Name: .eh_frame
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC ]
|
||||
AddressAlign: 0x8
|
||||
Content: 1000000000000000017A5200017801011B0C02001000000018000000000000000000000000400E10
|
||||
- Name: .rela.text
|
||||
Type: SHT_RELA
|
||||
Flags: [ SHF_INFO_LINK ]
|
||||
Link: .symtab
|
||||
AddressAlign: 0x8
|
||||
Info: .text
|
||||
Relocations:
|
||||
- Type: R_RISCV_ALIGN
|
||||
Addend: 4
|
||||
- Name: .rela.eh_frame
|
||||
Type: SHT_RELA
|
||||
Flags: [ SHF_INFO_LINK ]
|
||||
Link: .symtab
|
||||
AddressAlign: 0x8
|
||||
Info: .eh_frame
|
||||
Relocations:
|
||||
- Offset: 0x1C
|
||||
Symbol: main
|
||||
Type: R_RISCV_32_PCREL
|
||||
- Offset: 0x20
|
||||
Symbol: main_end
|
||||
Type: R_RISCV_ADD32
|
||||
- Offset: 0x20
|
||||
Symbol: main
|
||||
Type: R_RISCV_SUB32
|
||||
- Offset: 0x25
|
||||
Symbol: cfa_advance_loc
|
||||
Type: R_RISCV_SET6
|
||||
- Offset: 0x25
|
||||
Symbol: main
|
||||
Type: R_RISCV_SUB6
|
||||
- Type: SectionHeaderTable
|
||||
Sections:
|
||||
- Name: .strtab
|
||||
- Name: .text
|
||||
- Name: .rela.text
|
||||
- Name: .eh_frame
|
||||
- Name: .rela.eh_frame
|
||||
- Name: .symtab
|
||||
Symbols:
|
||||
- Name: cfa_advance_loc
|
||||
Section: .text
|
||||
Value: 0x8
|
||||
- Name: main_end
|
||||
Section: .text
|
||||
Value: 0xC
|
||||
- Name: main
|
||||
Type: STT_FUNC
|
||||
Section: .text
|
||||
Binding: STB_GLOBAL
|
||||
Size: 0xC
|
||||
- Name: eh_frame
|
||||
Type: STT_SECTION
|
||||
Binding: STB_GLOBAL
|
||||
Section: .eh_frame
|
||||
Size: 0x28
|
||||
...
|
||||
|
||||
## CIE_pointer
|
||||
# jitlink-check: *{4}(eh_frame + 0x1c) = main - (eh_frame + 0x1c)
|
||||
## address_range
|
||||
# jitlink-check: *{4}(eh_frame + 0x20) = main_end - main
|
||||
## DW_CFA_advance_loc
|
||||
# jitlink-check: (*{1}(eh_frame + 0x25)) & 0x3f = cfa_advance_loc - main
|
||||
Reference in New Issue
Block a user