[llvm] 6a2ea84 - BPF: Add more relocation kinds

Yonghong Song via llvm-commits llvm-commits at lists.llvm.org
Tue May 25 08:20:17 PDT 2021


Author: Yonghong Song
Date: 2021-05-25T08:19:13-07:00
New Revision: 6a2ea84600ba4bd3b2733bd8f08f5115eb32164b

URL: https://github.com/llvm/llvm-project/commit/6a2ea84600ba4bd3b2733bd8f08f5115eb32164b
DIFF: https://github.com/llvm/llvm-project/commit/6a2ea84600ba4bd3b2733bd8f08f5115eb32164b.diff

LOG: BPF: Add more relocation kinds

Currently, BPF only contains three relocations:
  R_BPF_NONE   for no relocation
  R_BPF_64_64  for LD_imm64 and normal 64-bit data relocation
  R_BPF_64_32  for call insn and normal 32-bit data relocation

Also .BTF and .BTF.ext sections contain symbols in allocated
program and data sections. These two sections reserved 32bit
space to hold the offset relative to the symbol's section.
When LLVM JIT is used, the LLVM ExecutionEngine RuntimeDyld
may attempt to resolve relocations for .BTF and .BTF.ext,
which we want to prevent. So we used R_BPF_NONE for such relocations.

This all works fine until when we try to do linking of
multiple objects.
  . R_BPF_64_64 handling of LD_imm64 vs. normal 64-bit data
    is different, so lld target->relocate() needs more context
    to do a correct job.
  . The same for R_BPF_64_32. More context is needed for
    lld target->relocate() to differentiate call insn vs.
    normal 32-bit data relocation.
  . Since relocations in .BTF and .BTF.ext are set to R_BPF_NONE,
    they will not be relocated properly when multiple .BTF/.BTF.ext
    sections are merged by lld.

This patch intends to address this issue by adding additional
relocation kinds:
  R_BPF_64_ABS64     for normal 64-bit data relocation
  R_BPF_64_ABS32     for normal 32-bit data relocation
  R_BPF_64_NODYLD32  for .BTF and .BTF.ext style relocations.
The old R_BPF_64_{64,32} semantics:
  R_BPF_64_64        for LD_imm64 relocation
  R_BPF_64_32        for call insn relocation

The existing R_BPF_64_64/R_BPF_64_32 mapping to numeric values
is maintained. They are the most common use cases for
bpf programs and we want to maintain backward compatibility
as much as possible.

ExecutionEngine RuntimeDyld BPF relocations are adjusted as well.
R_BPF_64_{ABS64,ABS32} relocations will be resolved properly and
other relocations will be ignored.
Two tests are added for RuntimeDyld. Not handling R_BPF_64_NODYLD32 in
RuntimeDyldELF.cpp will result in "Relocation type not implemented yet!"
fatal error.

FK_SecRel_4 usages in BPFAsmBackend.cpp and BPFELFObjectWriter.cpp
are removed as they are not triggered in BPF backend.
BPF backend used FK_SecRel_8 for LD_imm64 instruction operands.

Differential Revision: https://reviews.llvm.org/D102712

Added: 
    llvm/test/CodeGen/BPF/reloc-2.ll
    llvm/test/CodeGen/BPF/reloc-3.ll
    llvm/test/ExecutionEngine/RuntimeDyld/BPF/abs64-relocation.s
    llvm/test/ExecutionEngine/RuntimeDyld/BPF/lit.local.cfg
    llvm/test/ExecutionEngine/RuntimeDyld/BPF/nodyld32-64-relocations.s

Modified: 
    llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def
    llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
    llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
    llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
    llvm/test/CodeGen/BPF/reloc-btf-2.ll
    llvm/test/CodeGen/BPF/reloc-btf.ll
    llvm/test/CodeGen/BPF/reloc.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def
index 5dd7f70b6963..cc18a65d1fd2 100644
--- 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
index 30c3856f77eb..efe0b9cd61cd 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -951,14 +951,17 @@ void RuntimeDyldELF::resolveBPFRelocation(const SectionEntry &Section,
     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<uint32_t>(Value));

diff  --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
index 29e9d5da0836..6687dbe25364 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
@@ -63,7 +63,7 @@ void BPFAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
                                MutableArrayRef<char> 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
index ef4e324c3bdd..7c0c23a86de8 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
@@ -43,12 +43,13 @@ unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
   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 @@ unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
         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 
diff erent 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
index 000000000000..301ac3e164db
--- /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:  <test>
+; DUMP-NEXT:  r[[#]] = r[[#]]
+; DUMP-NEXT:  r[[#]] = r[[#]]
+; DUMP-NEXT:  call -1
+
+; DUMP:       sec1:
+; DUMP-EMPTY:
+; DUMP-NEXT:  <add>
+
+; 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
index 000000000000..0acf2d938562
--- /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* }
+
+ at 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
index 68f00081d7d7..7a287ae2ce58 100644
--- a/llvm/test/CodeGen/BPF/reloc-btf-2.ll
+++ b/llvm/test/CodeGen/BPF/reloc-btf-2.ll
@@ -23,8 +23,8 @@ define dso_local i32 @test() local_unnamed_addr #0 !dbg !14 {
 
 ; 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
index c6f34fbde46e..aa929257e039 100644
--- a/llvm/test/CodeGen/BPF/reloc-btf.ll
+++ b/llvm/test/CodeGen/BPF/reloc-btf.ll
@@ -8,10 +8,10 @@ entry:
 
 ; 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
index e00dfdb5d2fc..123de4851746 100644
--- a/llvm/test/CodeGen/BPF/reloc.ll
+++ b/llvm/test/CodeGen/BPF/reloc.ll
@@ -34,7 +34,7 @@ define i32 @bpf_prog1(%struct.bpf_context* nocapture %ctx) #0 section "events/ne
 
 ; 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
index 000000000000..6e7d1c16e351
--- /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, at function
+g:                                      # @g
+	r0 = 0
+	exit
+.Lfunc_end0:
+	.size	g, .Lfunc_end0-g
+                                        # -- End function
+	.type	gbl, at 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
index 000000000000..a4ab2624af61
--- /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
index 000000000000..fbb140725eae
--- /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, at 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, at object                       # @a
+	.section	.bss,"aw", at nobits
+	.globl	a
+	.p2align	2
+a:
+	.long	0                               # 0x0
+	.size	a, 4
+
+# rtdyld-check: *{4}a = 0
+
+	.section	.BTF,"", at 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


        


More information about the llvm-commits mailing list