Skip to content

Commit

Permalink
[BPF] Don't fail for static variables
Browse files Browse the repository at this point in the history
Currently, the LLVM will print an error like
  Unsupported relocation: try to compile with -O2 or above,
  or check your static variable usage
if user defines more than one static variables in a single
ELF section (e.g., .bss or .data).

There is ongoing effort to support static and global
variables in libbpf and kernel. This patch removed the
assertion so user programs with static variables won't
fail compilation.

The static variable in-section offset is written to
the "imm" field of the corresponding to-be-relocated
bpf instruction. Below is an example to show how the
application (e.g., libbpf) can relate variable to relocations.

  -bash-4.4$ cat g1.c
  static volatile long a = 2;
  static volatile int b = 3;
  int test() { return a + b; }
  -bash-4.4$ clang -target bpf -O2 -c g1.c
  -bash-4.4$ llvm-readelf -r g1.o

  Relocation section '.rel.text' at offset 0x158 contains 2 entries:
      Offset             Info             Type               Symbol's Value  Symbol's Name
  0000000000000000  0000000400000001 R_BPF_64_64            0000000000000000 .data
  0000000000000018  0000000400000001 R_BPF_64_64            0000000000000000 .data
  -bash-4.4$ llvm-readelf -s g1.o

  Symbol table '.symtab' contains 6 entries:
     Num:    Value          Size Type    Bind   Vis      Ndx Name
       0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
       1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS g1.c
       2: 0000000000000000     8 OBJECT  LOCAL  DEFAULT    4 a
       3: 0000000000000008     4 OBJECT  LOCAL  DEFAULT    4 b
       4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
       5: 0000000000000000    64 FUNC    GLOBAL DEFAULT    2 test
  -bash-4.4$ llvm-objdump -d g1.o

  g1.o:   file format ELF64-BPF

  Disassembly of section .text:
  0000000000000000 test:
       0:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00         r1 = 0 ll
       2:       79 11 00 00 00 00 00 00         r1 = *(u64 *)(r1 + 0)
       3:       18 02 00 00 08 00 00 00 00 00 00 00 00 00 00 00         r2 = 8 ll
       5:       61 20 00 00 00 00 00 00         r0 = *(u32 *)(r2 + 0)
       6:       0f 10 00 00 00 00 00 00         r0 += r1
       7:       95 00 00 00 00 00 00 00         exit
  -bash-4.4$

  . from symbol table, static variable "a" is in section #4, offset 0.
  . from symbol table, static variable "b" is in section #4, offset 8.
  . the first relocation is against symbol #4:
    4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
    and in-section offset 0 (see llvm-objdump result)
  . the second relocation is against symbol #4:
    4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
    and in-section offset 8 (see llvm-objdump result)
  . therefore, the first relocation is for variable "a", and
    the second relocation is for variable "b".

Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Yonghong Song <yhs@fb.com>
llvm-svn: 354954
  • Loading branch information
yonghong-song committed Feb 27, 2019
1 parent c016430 commit cc290a9
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
12 changes: 6 additions & 6 deletions llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ void BPFAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
bool IsResolved,
const MCSubtargetInfo *STI) const {
if (Fixup.getKind() == FK_SecRel_4 || Fixup.getKind() == FK_SecRel_8) {
if (Value) {
MCContext &Ctx = Asm.getContext();
Ctx.reportError(Fixup.getLoc(),
"Unsupported relocation: try to compile with -O2 or above, "
"or check your static variable usage");
}
// 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);
support::endian::write<uint32_t>(&Data[Fixup.getOffset() + 4],
static_cast<uint32_t>(Value),
Endian);
} else if (Fixup.getKind() == FK_Data_4) {
support::endian::write<uint32_t>(&Data[Fixup.getOffset()], Value, Endian);
} else if (Fixup.getKind() == FK_Data_8) {
Expand Down
38 changes: 38 additions & 0 deletions llvm/test/CodeGen/BPF/objdump_static_var.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-objdump -d - | FileCheck --check-prefix=CHECK %s
; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-objdump -d - | FileCheck --check-prefix=CHECK %s

; src:
; static volatile long a = 2;
; static volatile int b = 3;
; int test() { return a + b; }
@a = internal global i64 2, align 8
@b = internal global i32 3, align 4

; Function Attrs: norecurse nounwind
define dso_local i32 @test() local_unnamed_addr #0 {
%1 = load volatile i64, i64* @a, align 8, !tbaa !2
; CHECK: r1 = 0 ll
; CHECK: r1 = *(u64 *)(r1 + 0)
%2 = load volatile i32, i32* @b, align 4, !tbaa !6
; CHECK: r2 = 8 ll
; CHECK: r0 = *(u32 *)(r2 + 0)
%3 = trunc i64 %1 to i32
%4 = add i32 %2, %3
; CHECK: r0 += r1
ret i32 %4
; CHECK: exit
}

attributes #0 = { norecurse nounwind }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 8.0.20181009 "}
!2 = !{!3, !3, i64 0}
!3 = !{!"long", !4, i64 0}
!4 = !{!"omnipotent char", !5, i64 0}
!5 = !{!"Simple C/C++ TBAA"}
!6 = !{!7, !7, i64 0}
!7 = !{!"int", !4, i64 0}

0 comments on commit cc290a9

Please sign in to comment.