Index: llvm/include/llvm/ExecutionEngine/JITLink/riscv.h =================================================================== --- llvm/include/llvm/ExecutionEngine/JITLink/riscv.h +++ llvm/include/llvm/ExecutionEngine/JITLink/riscv.h @@ -214,6 +214,24 @@ /// Linker relaxation will use this to ensure all code sequences are properly /// aligned and then remove these edges from the graph. AlignRelaxable, + + /// 32-bit delta. + /// + /// Fixup expression: + /// Fixup <- Target - Fixup + Addend + Delta32, + + /// 64-bit delta. + /// + /// Fixup expression: + /// Fixup <- Target - Fixup + Addend + Delta64, + + /// 32-bit negative delta. + /// + /// Fixup expression: + /// Fixup <- Fixup - Target + Addend + NegDelta32, }; /// Returns a string name for the given riscv edge. For debugging purposes Index: llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp =================================================================== --- llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp +++ llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp @@ -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" @@ -22,6 +24,7 @@ #include "llvm/Support/Endian.h" #define DEBUG_TYPE "jitlink" + using namespace llvm; using namespace llvm::jitlink; using namespace llvm::jitlink::riscv; @@ -456,6 +459,21 @@ case AlignRelaxable: // Ignore when the relaxation pass did not run break; + case Delta32: { + int64_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend(); + *(little32_t *)FixupPtr = static_cast(Value); + break; + } + case Delta64: { + int64_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend(); + *(little64_t *)FixupPtr = static_cast(Value); + break; + } + case NegDelta32: { + int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend(); + *(little32_t *)FixupPtr = static_cast(Value); + break; + } } return Error::success(); } @@ -959,6 +977,13 @@ 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(), R_RISCV_32, R_RISCV_64, + Delta32, Delta64, NegDelta32)); + Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); + if (auto MarkLive = Ctx->getMarkLivePass(TT)) Config.PrePrunePasses.push_back(std::move(MarkLive)); else Index: llvm/lib/ExecutionEngine/JITLink/riscv.cpp =================================================================== --- llvm/lib/ExecutionEngine/JITLink/riscv.cpp +++ llvm/lib/ExecutionEngine/JITLink/riscv.cpp @@ -82,6 +82,12 @@ return "CallRelaxable"; case AlignRelaxable: return "AlignRelaxable"; + case Delta32: + return "Delta32"; + case Delta64: + return "Delta64"; + case NegDelta32: + return "NegDelta32"; } return getGenericEdgeKindName(K); } Index: llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.s =================================================================== --- /dev/null +++ llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.s @@ -0,0 +1,120 @@ +# REQUIRES: asserts +# RUN: llvm-mc -triple=riscv64-linux-gnu -filetype=obj -o %t %s +# RUN: llvm-jitlink -noexec -phony-externals -debug-only=jitlink %t 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: Processing CFI record at +# CHECK: Record is CIE +# CHECK: Processing block at +# CHECK: Processing CFI record 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 {{.*}} + + .text + .attribute 4, 16 + .attribute 5, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0" + .file "catch.cpp" + .globl main # -- Begin function main + .p2align 1 + .type main,@function +main: # @main +.Lfunc_begin0: + .cfi_startproc + .cfi_personality 155, DW.ref.__gxx_personality_v0 + .cfi_lsda 27, .Lexception0 +# %bb.0: + addi sp, sp, -16 + .cfi_def_cfa_offset 16 + sd ra, 8(sp) # 8-byte Folded Spill + .cfi_offset ra, -8 + li a0, 4 + call __cxa_allocate_exception@plt + li a1, 1 + sw a1, 0(a0) +.Ltmp0: +.Lpcrel_hi0: + auipc a1, %got_pcrel_hi(_ZTIi) + ld a1, %pcrel_lo(.Lpcrel_hi0)(a1) + li a2, 0 + call __cxa_throw@plt +.Ltmp1: +# %bb.1: +.LBB0_2: +.Ltmp2: + call __cxa_begin_catch@plt +.Lpcrel_hi1: + auipc a0, %pcrel_hi(.Lstr) + addi a0, a0, %pcrel_lo(.Lpcrel_hi1) + call puts@plt + call __cxa_end_catch@plt + li a0, 0 + ld ra, 8(sp) # 8-byte Folded Reload + addi sp, sp, 16 + ret +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + .section .gcc_except_table,"a",@progbits + .p2align 2, 0x0 +GCC_except_table0: +.Lexception0: + .byte 255 # @LPStart Encoding = omit + .byte 155 # @TType Encoding = indirect pcrel sdata4 + .uleb128 .Lttbase0-.Lttbaseref0 +.Lttbaseref0: + .byte 3 # Call site Encoding = udata4 + .uleb128 .Lcst_end0-.Lcst_begin0 +.Lcst_begin0: + .word .Lfunc_begin0-.Lfunc_begin0 # >> Call Site 1 << + .word .Ltmp0-.Lfunc_begin0 # Call between .Lfunc_begin0 and .Ltmp0 + .word 0 # has no landing pad + .byte 0 # On action: cleanup + .word .Ltmp0-.Lfunc_begin0 # >> Call Site 2 << + .word .Ltmp1-.Ltmp0 # Call between .Ltmp0 and .Ltmp1 + .word .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 + .byte 1 # On action: 1 + .word .Ltmp1-.Lfunc_begin0 # >> Call Site 3 << + .word .Lfunc_end0-.Ltmp1 # Call between .Ltmp1 and .Lfunc_end0 + .word 0 # has no landing pad + .byte 0 # On action: cleanup +.Lcst_end0: + .byte 1 # >> Action Record 1 << + # Catch TypeInfo 1 + .byte 0 # No further actions + .p2align 2, 0x0 + # >> Catch TypeInfos << + .word 0 # TypeInfo 1 +.Lttbase0: + .p2align 2, 0x0 + # -- End function + .type .Lstr,@object # @str + .section .rodata.str1.1,"aMS",@progbits,1 +.Lstr: + .asciz "Caught!" + .size .Lstr, 8 + + .hidden DW.ref.__gxx_personality_v0 + .weak DW.ref.__gxx_personality_v0 + .section .data.DW.ref.__gxx_personality_v0,"aGw",@progbits,DW.ref.__gxx_personality_v0,comdat + .p2align 3, 0x0 + .type DW.ref.__gxx_personality_v0,@object + .size DW.ref.__gxx_personality_v0, 8 +DW.ref.__gxx_personality_v0: + .quad __gxx_personality_v0 + .ident "clang version 18.0.0" + .section ".note.GNU-stack","",@progbits + .addrsig + .addrsig_sym __gxx_personality_v0 + .addrsig_sym _ZTIi