From bd87726db47eb83032b456d062e936bfc3b3bcaa Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Wed, 3 May 2017 17:30:56 +0000 Subject: [PATCH] [bpf] add relocation support . there should be no runtime relocation inside the bpf function. . relocation supported here mostly for debugging. . a test case is added. Signed-off-by: Yonghong Song Signed-off-by: Alexei Starovoitov git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302055 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../RuntimeDyld/RuntimeDyldELF.cpp | 32 ++++++++++++++ .../RuntimeDyld/RuntimeDyldELF.h | 3 ++ lib/MC/MCObjectFileInfo.cpp | 4 ++ test/CodeGen/BPF/reloc.ll | 43 +++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 test/CodeGen/BPF/reloc.ll diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index f780137d087..50f63fb8dd3 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -819,6 +819,34 @@ void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section, } } +void RuntimeDyldELF::resolveBPFRelocation(const SectionEntry &Section, + uint64_t Offset, uint64_t Value, + uint32_t Type, int64_t Addend) { + bool isBE = Arch == Triple::bpfeb; + + switch (Type) { + default: + llvm_unreachable("Relocation type not implemented yet!"); + break; + case ELF::R_BPF_NONE: + break; + case ELF::R_BPF_64_64: { + write(isBE, Section.getAddressWithOffset(Offset), Value + Addend); + DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at " + << format("%p\n", Section.getAddressWithOffset(Offset))); + break; + } + case ELF::R_BPF_64_32: { + Value += Addend; + assert(Value <= UINT32_MAX); + write(isBE, Section.getAddressWithOffset(Offset), static_cast(Value)); + DEBUG(dbgs() << "Writing " << format("%p", Value) << " at " + << format("%p\n", Section.getAddressWithOffset(Offset))); + break; + } + } +} + // The target location for the relocation is described by RE.SectionID and // RE.Offset. RE.SectionID can be used to find the SectionEntry. Each // SectionEntry has three members describing its location. @@ -879,6 +907,10 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, case Triple::systemz: resolveSystemZRelocation(Section, Offset, Value, Type, Addend); break; + case Triple::bpfel: + case Triple::bpfeb: + resolveBPFRelocation(Section, Offset, Value, Type, Addend); + break; default: llvm_unreachable("Unsupported CPU type!"); } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 498979705b7..84dd810101f 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -58,6 +58,9 @@ class RuntimeDyldELF : public RuntimeDyldImpl { void resolveSystemZRelocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend); + void resolveBPFRelocation(const SectionEntry &Section, uint64_t Offset, + uint64_t Value, uint32_t Type, int64_t Addend); + unsigned getMaxStubSize() override { if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) return 20; // movz; movk; movk; movk; br diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index 9f94264684f..b685790910d 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -286,6 +286,10 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T) { ((CMModel == CodeModel::Large) ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4); break; + case Triple::bpfel: + case Triple::bpfeb: + FDECFIEncoding = dwarf::DW_EH_PE_sdata8; + break; default: FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; break; diff --git a/test/CodeGen/BPF/reloc.ll b/test/CodeGen/BPF/reloc.ll new file mode 100644 index 00000000000..75dbebf311e --- /dev/null +++ b/test/CodeGen/BPF/reloc.ll @@ -0,0 +1,43 @@ +; RUN: llc -march=bpfel -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-RELOC %s + +%struct.bpf_context = type { i64, i64, i64, i64, i64, i64, i64 } +%struct.sk_buff = type { i64, i64, i64, i64, i64, i64, i64 } +%struct.net_device = type { i64, i64, i64, i64, i64, i64, i64 } + +@bpf_prog1.devname = private unnamed_addr constant [3 x i8] c"lo\00", align 1 +@bpf_prog1.fmt = private unnamed_addr constant [15 x i8] c"skb %x dev %x\0A\00", align 1 + +; Function Attrs: norecurse +define i32 @bpf_prog1(%struct.bpf_context* nocapture %ctx) #0 section "events/net/netif_receive_skb" { + %devname = alloca [3 x i8], align 1 + %fmt = alloca [15 x i8], align 1 + %1 = getelementptr inbounds [3 x i8], [3 x i8]* %devname, i64 0, i64 0 + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @bpf_prog1.devname, i64 0, i64 0), i64 3, i32 1, i1 false) + %2 = getelementptr inbounds %struct.bpf_context, %struct.bpf_context* %ctx, i64 0, i32 0 + %3 = load i64, i64* %2, align 8 + %4 = inttoptr i64 %3 to %struct.sk_buff* + %5 = getelementptr inbounds %struct.sk_buff, %struct.sk_buff* %4, i64 0, i32 2 + %6 = bitcast i64* %5 to i8* + %7 = call i8* inttoptr (i64 4 to i8* (i8*)*)(i8* %6) #1 + %8 = call i32 inttoptr (i64 9 to i32 (i8*, i8*, i32)*)(i8* %7, i8* %1, i32 2) #1 + %9 = icmp eq i32 %8, 0 + br i1 %9, label %10, label %13 + +;