From 210e76c6de4c9ffbc2a66f7eaa53434288bb59f2 Mon Sep 17 00:00:00 2001 From: Dmitri Makarov Date: Thu, 4 Feb 2021 08:36:04 +0100 Subject: [PATCH] [SOL] Enable BPF shared object creation --- lld/ELF/Arch/BPF.cpp | 85 +++++++++++++++++++ lld/ELF/CMakeLists.txt | 1 + lld/ELF/Target.cpp | 2 + lld/ELF/Target.h | 1 + .../llvm/BinaryFormat/ELFRelocs/BPF.def | 1 + 5 files changed, 90 insertions(+) create mode 100644 lld/ELF/Arch/BPF.cpp diff --git a/lld/ELF/Arch/BPF.cpp b/lld/ELF/Arch/BPF.cpp new file mode 100644 index 00000000000000..aba173e22b979f --- /dev/null +++ b/lld/ELF/Arch/BPF.cpp @@ -0,0 +1,85 @@ +//===- BPF.cpp ------------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "InputFiles.h" +#include "Symbols.h" +#include "Target.h" +#include "lld/Common/ErrorHandler.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::support::endian; +using namespace llvm::ELF; + +namespace lld { +namespace elf { + +namespace { +class BPF final : public TargetInfo { +public: + BPF(); + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + RelType getDynRel(RelType type) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; +}; +} // namespace + +BPF::BPF() { + noneRel = R_BPF_NONE; + relativeRel = R_BPF_64_RELATIVE; + symbolicRel = R_BPF_64_64; +} + +RelExpr BPF::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { + case R_BPF_64_32: + return R_PC; + case R_BPF_64_64: + return R_ABS; + default: + error(getErrorLocation(loc) + "unrecognized reloc " + toString(type)); + } + return R_NONE; +} + +RelType BPF::getDynRel(RelType type) const { + return type; +} + +void BPF::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { + case R_BPF_64_32: { + // Relocation of a symbol + write32le(loc + 4, ((val - 8) / 8) & 0xFFFFFFFF); + break; + } + case R_BPF_64_64: { + // Relocation of a lddw instruction + // 64 bit address is divided into the imm of this and the following + // instructions, lower 32 first. + write32le(loc + 4, val & 0xFFFFFFFF); + write32le(loc + 8 + 4, val >> 32); + break; + } + default: + error(getErrorLocation(loc) + "unrecognized reloc " + toString(type)); + } +} + +TargetInfo *getBPFTargetInfo() { + static BPF target; + return ⌖ +} + +} // namespace elf +} // namespace lld diff --git a/lld/ELF/CMakeLists.txt b/lld/ELF/CMakeLists.txt index 83d816ddb0601e..1910343cc6a2f9 100644 --- a/lld/ELF/CMakeLists.txt +++ b/lld/ELF/CMakeLists.txt @@ -24,6 +24,7 @@ add_lld_library(lldELF Arch/AMDGPU.cpp Arch/ARM.cpp Arch/AVR.cpp + Arch/BPF.cpp Arch/Hexagon.cpp Arch/LoongArch.cpp Arch/Mips.cpp diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index b7922425a34e43..34b780c1596953 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -60,6 +60,8 @@ TargetInfo *elf::getTarget() { return getARMTargetInfo(); case EM_AVR: return getAVRTargetInfo(); + case EM_BPF: + return getBPFTargetInfo(); case EM_HEXAGON: return getHexagonTargetInfo(); case EM_LOONGARCH: diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 0cefa318135662..42d146fc1dfc9a 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -181,6 +181,7 @@ TargetInfo *getAArch64TargetInfo(); TargetInfo *getAMDGPUTargetInfo(); TargetInfo *getARMTargetInfo(); TargetInfo *getAVRTargetInfo(); +TargetInfo *getBPFTargetInfo(); TargetInfo *getHexagonTargetInfo(); TargetInfo *getLoongArchTargetInfo(); TargetInfo *getMSP430TargetInfo(); diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def index cc18a65d1fd2f7..3ec043d5896ced 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def @@ -8,4 +8,5 @@ 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_RELATIVE, 8) // B + A ELF_RELOC(R_BPF_64_32, 10)