1283625Sdim//===-- BPFELFObjectWriter.cpp - BPF ELF Writer ---------------------------===// 2283625Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6283625Sdim// 7283625Sdim//===----------------------------------------------------------------------===// 8283625Sdim 9283625Sdim#include "MCTargetDesc/BPFMCTargetDesc.h" 10321369Sdim#include "llvm/BinaryFormat/ELF.h" 11283625Sdim#include "llvm/MC/MCELFObjectWriter.h" 12283625Sdim#include "llvm/MC/MCFixup.h" 13327952Sdim#include "llvm/MC/MCObjectWriter.h" 14344779Sdim#include "llvm/MC/MCValue.h" 15283625Sdim#include "llvm/Support/ErrorHandling.h" 16314564Sdim#include <cstdint> 17283625Sdim 18283625Sdimusing namespace llvm; 19283625Sdim 20283625Sdimnamespace { 21314564Sdim 22283625Sdimclass BPFELFObjectWriter : public MCELFObjectTargetWriter { 23283625Sdimpublic: 24283625Sdim BPFELFObjectWriter(uint8_t OSABI); 25314564Sdim ~BPFELFObjectWriter() override = default; 26283625Sdim 27283625Sdimprotected: 28309124Sdim unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 29309124Sdim const MCFixup &Fixup, bool IsPCRel) const override; 30283625Sdim}; 31283625Sdim 32314564Sdim} // end anonymous namespace 33314564Sdim 34283625SdimBPFELFObjectWriter::BPFELFObjectWriter(uint8_t OSABI) 35309124Sdim : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_BPF, 36283625Sdim /*HasRelocationAddend*/ false) {} 37283625Sdim 38309124Sdimunsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, 39283625Sdim const MCFixup &Fixup, 40283625Sdim bool IsPCRel) const { 41283625Sdim // determine the type of the relocation 42360784Sdim switch (Fixup.getKind()) { 43283625Sdim default: 44283625Sdim llvm_unreachable("invalid fixup kind!"); 45283625Sdim case FK_SecRel_8: 46314564Sdim return ELF::R_BPF_64_64; 47327952Sdim case FK_PCRel_4: 48283625Sdim case FK_SecRel_4: 49314564Sdim return ELF::R_BPF_64_32; 50296417Sdim case FK_Data_8: 51314564Sdim return ELF::R_BPF_64_64; 52296417Sdim case FK_Data_4: 53344779Sdim if (const MCSymbolRefExpr *A = Target.getSymA()) { 54353358Sdim const MCSymbol &Sym = A->getSymbol(); 55353358Sdim 56353358Sdim if (Sym.isDefined()) { 57353358Sdim MCSection &Section = Sym.getSection(); 58344779Sdim const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section); 59344779Sdim assert(SectionELF && "Null section for reloc symbol"); 60344779Sdim 61344779Sdim unsigned Flags = SectionELF->getFlags(); 62353358Sdim 63353358Sdim if (Sym.isTemporary()) { 64353358Sdim // .BTF.ext generates FK_Data_4 relocations for 65353358Sdim // insn offset by creating temporary labels. 66353358Sdim // The insn offset is within the code section and 67353358Sdim // already been fulfilled by applyFixup(). No 68353358Sdim // further relocation is needed. 69353358Sdim // The reloc symbol should be in text section. 70353358Sdim if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_EXECINSTR)) 71353358Sdim return ELF::R_BPF_NONE; 72353358Sdim } else { 73353358Sdim // .BTF generates FK_Data_4 relocations for variable 74353358Sdim // offset in DataSec kind. Similar to the above .BTF.ext 75353358Sdim // insn offset, no further relocation is needed. 76353358Sdim // The reloc symbol should be in data section. 77353358Sdim if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_WRITE)) 78353358Sdim return ELF::R_BPF_NONE; 79353358Sdim } 80344779Sdim } 81344779Sdim } 82314564Sdim return ELF::R_BPF_64_32; 83283625Sdim } 84283625Sdim} 85283625Sdim 86341825Sdimstd::unique_ptr<MCObjectTargetWriter> 87341825Sdimllvm::createBPFELFObjectWriter(uint8_t OSABI) { 88360784Sdim return std::make_unique<BPFELFObjectWriter>(OSABI); 89283625Sdim} 90