10b57cec5SDimitry Andric //===-- BPFELFObjectWriter.cpp - BPF ELF Writer ---------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "MCTargetDesc/BPFMCTargetDesc.h"
100b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
110b57cec5SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h"
120b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
150b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
160b57cec5SDimitry Andric #include <cstdint>
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric using namespace llvm;
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric namespace {
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric class BPFELFObjectWriter : public MCELFObjectTargetWriter {
230b57cec5SDimitry Andric public:
240b57cec5SDimitry Andric BPFELFObjectWriter(uint8_t OSABI);
250b57cec5SDimitry Andric ~BPFELFObjectWriter() override = default;
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric protected:
280b57cec5SDimitry Andric unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
290b57cec5SDimitry Andric const MCFixup &Fixup, bool IsPCRel) const override;
300b57cec5SDimitry Andric };
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric } // end anonymous namespace
330b57cec5SDimitry Andric
BPFELFObjectWriter(uint8_t OSABI)340b57cec5SDimitry Andric BPFELFObjectWriter::BPFELFObjectWriter(uint8_t OSABI)
350b57cec5SDimitry Andric : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_BPF,
360b57cec5SDimitry Andric /*HasRelocationAddend*/ false) {}
370b57cec5SDimitry Andric
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const380b57cec5SDimitry Andric unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
390b57cec5SDimitry Andric const MCFixup &Fixup,
400b57cec5SDimitry Andric bool IsPCRel) const {
410b57cec5SDimitry Andric // determine the type of the relocation
428bcb0991SDimitry Andric switch (Fixup.getKind()) {
430b57cec5SDimitry Andric default:
440b57cec5SDimitry Andric llvm_unreachable("invalid fixup kind!");
450b57cec5SDimitry Andric case FK_SecRel_8:
46*fe6060f1SDimitry Andric // LD_imm64 instruction.
470b57cec5SDimitry Andric return ELF::R_BPF_64_64;
480b57cec5SDimitry Andric case FK_PCRel_4:
49*fe6060f1SDimitry Andric // CALL instruction.
500b57cec5SDimitry Andric return ELF::R_BPF_64_32;
510b57cec5SDimitry Andric case FK_Data_8:
52*fe6060f1SDimitry Andric return ELF::R_BPF_64_ABS64;
530b57cec5SDimitry Andric case FK_Data_4:
540b57cec5SDimitry Andric if (const MCSymbolRefExpr *A = Target.getSymA()) {
550b57cec5SDimitry Andric const MCSymbol &Sym = A->getSymbol();
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric if (Sym.isDefined()) {
580b57cec5SDimitry Andric MCSection &Section = Sym.getSection();
590b57cec5SDimitry Andric const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section);
600b57cec5SDimitry Andric assert(SectionELF && "Null section for reloc symbol");
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric unsigned Flags = SectionELF->getFlags();
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric if (Sym.isTemporary()) {
650b57cec5SDimitry Andric // .BTF.ext generates FK_Data_4 relocations for
660b57cec5SDimitry Andric // insn offset by creating temporary labels.
670b57cec5SDimitry Andric // The reloc symbol should be in text section.
68*fe6060f1SDimitry Andric // Use a different relocation to instruct ExecutionEngine
69*fe6060f1SDimitry Andric // RuntimeDyld not to do relocation for it, yet still to
70*fe6060f1SDimitry Andric // allow lld to do proper adjustment when merging sections.
710b57cec5SDimitry Andric if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_EXECINSTR))
72*fe6060f1SDimitry Andric return ELF::R_BPF_64_NODYLD32;
730b57cec5SDimitry Andric } else {
740b57cec5SDimitry Andric // .BTF generates FK_Data_4 relocations for variable
75*fe6060f1SDimitry Andric // offset in DataSec kind.
760b57cec5SDimitry Andric // The reloc symbol should be in data section.
770b57cec5SDimitry Andric if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_WRITE))
78*fe6060f1SDimitry Andric return ELF::R_BPF_64_NODYLD32;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric }
82*fe6060f1SDimitry Andric return ELF::R_BPF_64_ABS32;
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric std::unique_ptr<MCObjectTargetWriter>
createBPFELFObjectWriter(uint8_t OSABI)870b57cec5SDimitry Andric llvm::createBPFELFObjectWriter(uint8_t OSABI) {
888bcb0991SDimitry Andric return std::make_unique<BPFELFObjectWriter>(OSABI);
890b57cec5SDimitry Andric }
90