diff --git a/lld/ELF/Arch/BPF.cpp b/lld/ELF/Arch/BPF.cpp new file mode 100644 index 0000000000000..aba173e22b979 --- /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 b89f4436288aa..a7b0532e7eed4 100644 --- a/lld/ELF/CMakeLists.txt +++ b/lld/ELF/CMakeLists.txt @@ -12,6 +12,7 @@ add_lld_library(lldELF Arch/AMDGPU.cpp Arch/ARM.cpp Arch/AVR.cpp + Arch/BPF.cpp Arch/Hexagon.cpp Arch/Mips.cpp Arch/MipsArchTree.cpp diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index d3899d0f18f19..555b064d98042 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -60,6 +60,8 @@ TargetInfo *getTarget() { return getARMTargetInfo(); case EM_AVR: return getAVRTargetInfo(); + case EM_BPF: + return getBPFTargetInfo(); case EM_HEXAGON: return getHexagonTargetInfo(); case EM_MIPS: diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 949a7bfdf64bd..7df2709c6872f 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -147,6 +147,7 @@ TargetInfo *getAArch64TargetInfo(); TargetInfo *getAMDGPUTargetInfo(); TargetInfo *getARMTargetInfo(); TargetInfo *getAVRTargetInfo(); +TargetInfo *getBPFTargetInfo(); TargetInfo *getHexagonTargetInfo(); TargetInfo *getMSP430TargetInfo(); TargetInfo *getPPC64TargetInfo(); diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def index 5dd7f70b6963a..83e4d60832c73 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/BPF.def @@ -5,4 +5,5 @@ // No relocation ELF_RELOC(R_BPF_NONE, 0) ELF_RELOC(R_BPF_64_64, 1) +ELF_RELOC(R_BPF_64_RELATIVE, 8) // B + A ELF_RELOC(R_BPF_64_32, 10) diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp index a77468360a37c..3bac6110d422f 100644 --- a/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp +++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp @@ -34,7 +34,7 @@ class BPFELFObjectWriter : public MCELFObjectTargetWriter { } // end anonymous namespace -// Avoid section relocations because the BPF backend can only handle +// Avoid section relocations because the BPF backend can only handle // section relocations with values (offset into the section containing // the symbol being relocated). Forcing a relocation with a symbol // will result in the symbol's index being used in the .o file instead.