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 @@ -950,6 +950,7 @@ default: report_fatal_error("Relocation type not implemented yet!"); break; + case ELF::R_BPF_64_NODYLD32: case ELF::R_BPF_NONE: break; case ELF::R_BPF_64_64: { 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-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/btf-relocations.s b/llvm/test/ExecutionEngine/RuntimeDyld/BPF/btf-relocations.s new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/RuntimeDyld/BPF/btf-relocations.s @@ -0,0 +1,68 @@ +# RUN: llvm-mc -triple=bpfel -filetype=obj -o %t %s +# RUN: llvm-rtdyld -triple=bpfel -verify -check=%s %t + + .globl _main + .p2align 3 + .type _main,@function +_main: # @_main + r1 = a ll + r0 = *(u32 *)(r1 + 0) + exit +.Lfunc_end0: + .size _main, .Lfunc_end0-_main + # -- End function + +# rtdyld-check: *{4}a = 0 + + .type a,@object # @a + .section .bss,"aw",@nobits + .globl a + .p2align 2 +a: + .long 0 # 0x0 + .size a, 4 + + .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 + .long a + .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 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