diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def @@ -5,4 +5,7 @@ // No relocation ELF_RELOC(R_BPF_NONE, 0) ELF_RELOC(R_BPF_64_64, 1) +ELF_RELOC(R_BPF_64_ABS64, 2) +ELF_RELOC(R_BPF_64_ABS32, 3) +ELF_RELOC(R_BPF_64_NODYLD32, 4) ELF_RELOC(R_BPF_64_32, 10) diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -951,14 +951,17 @@ report_fatal_error("Relocation type not implemented yet!"); break; case ELF::R_BPF_NONE: + case ELF::R_BPF_64_64: + case ELF::R_BPF_64_32: + case ELF::R_BPF_64_NODYLD32: break; - case ELF::R_BPF_64_64: { + case ELF::R_BPF_64_ABS64: { write(isBE, Section.getAddressWithOffset(Offset), Value + Addend); LLVM_DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at " << format("%p\n", Section.getAddressWithOffset(Offset))); break; } - case ELF::R_BPF_64_32: { + case ELF::R_BPF_64_ABS32: { Value += Addend; assert(Value <= UINT32_MAX); write(isBE, Section.getAddressWithOffset(Offset), static_cast(Value)); diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp --- a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp +++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp @@ -63,7 +63,7 @@ MutableArrayRef Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const { - if (Fixup.getKind() == FK_SecRel_4 || Fixup.getKind() == FK_SecRel_8) { + if (Fixup.getKind() == FK_SecRel_8) { // The Value is 0 for global variables, and the in-section offset // for static variables. Write to the immediate field of the inst. assert(Value <= UINT32_MAX); diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp --- a/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp +++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp @@ -43,12 +43,13 @@ default: llvm_unreachable("invalid fixup kind!"); case FK_SecRel_8: + // LD_imm64 instruction. return ELF::R_BPF_64_64; case FK_PCRel_4: - case FK_SecRel_4: + // CALL instruction. return ELF::R_BPF_64_32; case FK_Data_8: - return ELF::R_BPF_64_64; + return ELF::R_BPF_64_ABS64; case FK_Data_4: if (const MCSymbolRefExpr *A = Target.getSymA()) { const MCSymbol &Sym = A->getSymbol(); @@ -63,23 +64,22 @@ if (Sym.isTemporary()) { // .BTF.ext generates FK_Data_4 relocations for // insn offset by creating temporary labels. - // The insn offset is within the code section and - // already been fulfilled by applyFixup(). No - // further relocation is needed. // The reloc symbol should be in text section. + // Use a different relocation to instruct ExecutionEngine + // RuntimeDyld not to do relocation for it, yet still to + // allow lld to do proper adjustment when merging sections. if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_EXECINSTR)) - return ELF::R_BPF_NONE; + return ELF::R_BPF_64_NODYLD32; } else { // .BTF generates FK_Data_4 relocations for variable - // offset in DataSec kind. Similar to the above .BTF.ext - // insn offset, no further relocation is needed. + // offset in DataSec kind. // The reloc symbol should be in data section. if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_WRITE)) - return ELF::R_BPF_NONE; + return ELF::R_BPF_64_NODYLD32; } } } - return ELF::R_BPF_64_32; + return ELF::R_BPF_64_ABS32; } } diff --git a/llvm/test/CodeGen/BPF/reloc-2.ll b/llvm/test/CodeGen/BPF/reloc-2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/BPF/reloc-2.ll @@ -0,0 +1,60 @@ +; RUN: llc -march=bpfel -filetype=obj -o %t.el < %s +; RUN: llvm-objdump -r %t.el | FileCheck --check-prefix=RELOC %s +; RUN: llvm-objdump -d --no-show-raw-insn %t.el | FileCheck --check-prefix=DUMP %s +; RUN: llc -march=bpfeb -filetype=obj -o %t.eb < %s +; RUN: llvm-objdump -r %t.eb | FileCheck --check-prefix=RELOC %s +; RUN: llvm-objdump -d --no-show-raw-insn %t.eb | FileCheck --check-prefix=DUMP %s + +; source code: +; static __attribute__((noinline)) __attribute__((section("sec1"))) +; int add(int a, int b) { +; return a + b; +; } +; static __attribute__((noinline)) +; int sub(int a, int b) { +; return a - b; +; } +; int test(int a, int b) { +; return add(a, b) + sub(a, b); +; } +; compilation flag: +; clang -target bpf -O2 -emit-llvm -S test.c + +define dso_local i32 @test(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %call = tail call fastcc i32 @add(i32 %a, i32 %b) + %call1 = tail call fastcc i32 @sub(i32 %a, i32 %b) + %add = add nsw i32 %call1, %call + ret i32 %add +} + +define internal fastcc i32 @add(i32 %a, i32 %b) unnamed_addr #1 section "sec1" { +entry: + %add = add nsw i32 %b, %a + ret i32 %add +} + +; Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn mustprogress +define internal fastcc i32 @sub(i32 %a, i32 %b) unnamed_addr #1 { +entry: + %sub = sub nsw i32 %a, %b + ret i32 %sub +} + +; DUMP: .text: +; DUMP-EMPTY: +; DUMP-NEXT: +; DUMP-NEXT: r[[#]] = r[[#]] +; DUMP-NEXT: r[[#]] = r[[#]] +; DUMP-NEXT: call -1 + +; DUMP: sec1: +; DUMP-EMPTY: +; DUMP-NEXT: + +; RELOC: RELOCATION RECORDS FOR [.text]: +; RELOC: R_BPF_64_32 sec1 +; RELOC-NOT: R_BPF_64_32 + +attributes #0 = { nofree norecurse nosync nounwind readnone willreturn mustprogress "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { nofree noinline norecurse nosync nounwind readnone willreturn mustprogress "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } diff --git a/llvm/test/CodeGen/BPF/reloc-3.ll b/llvm/test/CodeGen/BPF/reloc-3.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/BPF/reloc-3.ll @@ -0,0 +1,25 @@ +; RUN: llc -march=bpfel -filetype=obj -o %t.el < %s +; RUN: llvm-readelf -r %t.el | FileCheck %s +; RUN: llc -march=bpfeb -filetype=obj -o %t.eb < %s +; RUN: llvm-readelf -r %t.eb | FileCheck %s + +; source code: +; int g() { return 0; } +; struct t { void *p; } gbl = { g }; +; compilation flag: +; clang -target bpf -O2 -emit-llvm -S test.c + +%struct.t = type { i8* } + +@gbl = dso_local local_unnamed_addr global %struct.t { i8* bitcast (i32 ()* @g to i8*) }, align 8 + +; CHECK: '.rel.data' +; CHECK: 0000000000000000 0000000200000002 R_BPF_64_ABS64 0000000000000000 g + +; Function Attrs: nofree norecurse nosync nounwind readnone willreturn mustprogress +define dso_local i32 @g() #0 { +entry: + ret i32 0 +} + +attributes #0 = { nofree norecurse nosync nounwind readnone willreturn mustprogress "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } diff --git a/llvm/test/CodeGen/BPF/reloc-btf-2.ll b/llvm/test/CodeGen/BPF/reloc-btf-2.ll --- a/llvm/test/CodeGen/BPF/reloc-btf-2.ll +++ b/llvm/test/CodeGen/BPF/reloc-btf-2.ll @@ -23,8 +23,8 @@ ; CHECK-RELOC: file format elf64-bpf ; CHECK-RELOC: RELOCATION RECORDS FOR [.BTF]: -; CHECK-RELOC: R_BPF_NONE .bss -; CHECK-RELOC: R_BPF_NONE g +; CHECK-RELOC: R_BPF_64_NODYLD32 .bss +; CHECK-RELOC: R_BPF_64_NODYLD32 g ; CHECK-RELOC: RELOCATION RECORDS FOR [.BTF.ext]: attributes #0 = { norecurse nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "frame-pointer"="all" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/llvm/test/CodeGen/BPF/reloc-btf.ll b/llvm/test/CodeGen/BPF/reloc-btf.ll --- a/llvm/test/CodeGen/BPF/reloc-btf.ll +++ b/llvm/test/CodeGen/BPF/reloc-btf.ll @@ -8,10 +8,10 @@ ; CHECK-RELOC: file format elf64-bpf ; CHECK-RELOC: RELOCATION RECORDS FOR [.debug_info]: -; CHECK-RELOC: R_BPF_64_32 .debug_abbrev -; CHECK-RELOC: R_BPF_64_64 .text +; CHECK-RELOC: R_BPF_64_ABS32 .debug_abbrev +; CHECK-RELOC: R_BPF_64_ABS64 .text ; CHECK-RELOC: RELOCATION RECORDS FOR [.BTF.ext]: -; CHECK-RELOC: R_BPF_NONE .text +; CHECK-RELOC: R_BPF_64_NODYLD32 .text attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "frame-pointer"="all" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/llvm/test/CodeGen/BPF/reloc.ll b/llvm/test/CodeGen/BPF/reloc.ll --- a/llvm/test/CodeGen/BPF/reloc.ll +++ b/llvm/test/CodeGen/BPF/reloc.ll @@ -34,7 +34,7 @@ ; CHECK-RELOC: file format elf64-bpf ; CHECK-RELOC: RELOCATION RECORDS FOR [.eh_frame]: -; CHECK-RELOC: R_BPF_64_64 events/net/netif_receive_skb +; CHECK-RELOC: R_BPF_64_ABS64 events/net/netif_receive_skb } ; Function Attrs: nounwind diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/BPF/abs64-relocation.s b/llvm/test/ExecutionEngine/RuntimeDyld/BPF/abs64-relocation.s new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/RuntimeDyld/BPF/abs64-relocation.s @@ -0,0 +1,26 @@ +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=bpfel -filetype=obj -o %t/test_reloc_abs64.o %s +# RUN: llvm-rtdyld -triple=bpfel -verify -check=%s %t/test_reloc_abs64.o + +# test R_BPF_64_ABS64 which should have relocation resolved properly. + + .text + .file "t1.c" + .globl g # -- Begin function g + .p2align 3 + .type g,@function +g: # @g + r0 = 0 + exit +.Lfunc_end0: + .size g, .Lfunc_end0-g + # -- End function + .type gbl,@object # @gbl + .data + .globl gbl + .p2align 3 +gbl: + .quad g + .size gbl, 8 + +# rtdyld-check: *{8}gbl = section_addr(test_reloc_abs64.o, .text) diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/BPF/lit.local.cfg b/llvm/test/ExecutionEngine/RuntimeDyld/BPF/lit.local.cfg new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/RuntimeDyld/BPF/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'BPF' in config.root.targets: + config.unsupported = True diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/BPF/nodyld32-64-relocations.s b/llvm/test/ExecutionEngine/RuntimeDyld/BPF/nodyld32-64-relocations.s new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/RuntimeDyld/BPF/nodyld32-64-relocations.s @@ -0,0 +1,77 @@ +# RUN: llvm-mc -triple=bpfel -filetype=obj -o %t %s +# RUN: llvm-rtdyld -triple=bpfel -verify -check=%s %t + +# test R_BPF_64_64 and R_BPF_64_NODYLD32 relocations, both should be ignored. + + .globl _main + .p2align 3 + .type _main,@function +_main: # @_main + r1 = a ll + +# rtdyld-check: decode_operand(_main, 1)[31:0] = 0x0 + + r0 = *(u32 *)(r1 + 0) + exit +.Lfunc_end0: + .size _main, .Lfunc_end0-_main + # -- End function + + .type a,@object # @a + .section .bss,"aw",@nobits + .globl a + .p2align 2 +a: + .long 0 # 0x0 + .size a, 4 + +# rtdyld-check: *{4}a = 0 + + .section .BTF,"",@progbits + .short 60319 # 0xeb9f + .byte 1 + .byte 0 + .long 24 + .long 0 + .long 80 + .long 80 + .long 87 + .long 0 # BTF_KIND_FUNC_PROTO(id = 1) + .long 218103808 # 0xd000000 + .long 2 + .long 1 # BTF_KIND_INT(id = 2) + .long 16777216 # 0x1000000 + .long 4 + .long 16777248 # 0x1000020 + .long 5 # BTF_KIND_FUNC(id = 3) + .long 201326593 # 0xc000001 + .long 1 + .long 80 # BTF_KIND_VAR(id = 4) + .long 234881024 # 0xe000000 + .long 2 + .long 1 + .long 82 # BTF_KIND_DATASEC(id = 5) + .long 251658241 # 0xf000001 + .long 0 + .long 4 +btf_a: + .long a + +# rtdyld-check: *{4}btf_a = 0 + + .long 4 + .byte 0 # string offset=0 + .ascii "int" # string offset=1 + .byte 0 + .ascii "_main" # string offset=5 + .byte 0 + .ascii ".text" # string offset=11 + .byte 0 + .ascii "/home/yhs/work/tests/llvm/rtdyld/t.c" # string offset=17 + .byte 0 + .ascii "int _main() { return a; }" # string offset=54 + .byte 0 + .byte 97 # string offset=80 + .byte 0 + .ascii ".bss" # string offset=82 + .byte 0