1e4c8c807SAlexei Starovoitov //===-- BPFELFObjectWriter.cpp - BPF ELF Writer ---------------------------===//
2e4c8c807SAlexei Starovoitov //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e4c8c807SAlexei Starovoitov //
7e4c8c807SAlexei Starovoitov //===----------------------------------------------------------------------===//
8e4c8c807SAlexei Starovoitov
9e4c8c807SAlexei Starovoitov #include "MCTargetDesc/BPFMCTargetDesc.h"
10264b5d9eSZachary Turner #include "llvm/BinaryFormat/ELF.h"
11e4c8c807SAlexei Starovoitov #include "llvm/MC/MCELFObjectWriter.h"
12e4c8c807SAlexei Starovoitov #include "llvm/MC/MCFixup.h"
1360fbc7ccSLang Hames #include "llvm/MC/MCObjectWriter.h"
14821c93d5SYonghong Song #include "llvm/MC/MCValue.h"
15e4c8c807SAlexei Starovoitov #include "llvm/Support/ErrorHandling.h"
164282c404SEugene Zelenko #include <cstdint>
17e4c8c807SAlexei Starovoitov
18e4c8c807SAlexei Starovoitov using namespace llvm;
19e4c8c807SAlexei Starovoitov
20e4c8c807SAlexei Starovoitov namespace {
214282c404SEugene Zelenko
22e4c8c807SAlexei Starovoitov class BPFELFObjectWriter : public MCELFObjectTargetWriter {
23e4c8c807SAlexei Starovoitov public:
24e4c8c807SAlexei Starovoitov BPFELFObjectWriter(uint8_t OSABI);
254282c404SEugene Zelenko ~BPFELFObjectWriter() override = default;
26e4c8c807SAlexei Starovoitov
27e4c8c807SAlexei Starovoitov protected:
288340f94dSRafael Espindola unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
298340f94dSRafael Espindola const MCFixup &Fixup, bool IsPCRel) const override;
30e4c8c807SAlexei Starovoitov };
314282c404SEugene Zelenko
324282c404SEugene Zelenko } // end anonymous namespace
33e4c8c807SAlexei Starovoitov
BPFELFObjectWriter(uint8_t OSABI)34e4c8c807SAlexei Starovoitov BPFELFObjectWriter::BPFELFObjectWriter(uint8_t OSABI)
35cfb51f54SAlexei Starovoitov : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_BPF,
36e4c8c807SAlexei Starovoitov /*HasRelocationAddend*/ false) {}
37e4c8c807SAlexei Starovoitov
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const388340f94dSRafael Espindola unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
39e4c8c807SAlexei Starovoitov const MCFixup &Fixup,
40e4c8c807SAlexei Starovoitov bool IsPCRel) const {
41e4c8c807SAlexei Starovoitov // determine the type of the relocation
4290b6bb75SSam Clegg switch (Fixup.getKind()) {
43e4c8c807SAlexei Starovoitov default:
44e4c8c807SAlexei Starovoitov llvm_unreachable("invalid fixup kind!");
45e4c8c807SAlexei Starovoitov case FK_SecRel_8:
46*6a2ea846SYonghong Song // LD_imm64 instruction.
477ab125dbSAlexei Starovoitov return ELF::R_BPF_64_64;
489a67245dSAlexei Starovoitov case FK_PCRel_4:
49*6a2ea846SYonghong Song // CALL instruction.
507ab125dbSAlexei Starovoitov return ELF::R_BPF_64_32;
5101886a05SAlexei Starovoitov case FK_Data_8:
52*6a2ea846SYonghong Song return ELF::R_BPF_64_ABS64;
5301886a05SAlexei Starovoitov case FK_Data_4:
54e698958aSYonghong Song if (const MCSymbolRefExpr *A = Target.getSymA()) {
55e698958aSYonghong Song const MCSymbol &Sym = A->getSymbol();
56e698958aSYonghong Song
57e698958aSYonghong Song if (Sym.isDefined()) {
58e698958aSYonghong Song MCSection &Section = Sym.getSection();
59e698958aSYonghong Song const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section);
60e698958aSYonghong Song assert(SectionELF && "Null section for reloc symbol");
61e698958aSYonghong Song
62e698958aSYonghong Song unsigned Flags = SectionELF->getFlags();
63e698958aSYonghong Song
64e698958aSYonghong Song if (Sym.isTemporary()) {
65821c93d5SYonghong Song // .BTF.ext generates FK_Data_4 relocations for
66821c93d5SYonghong Song // insn offset by creating temporary labels.
670d99031dSYonghong Song // The reloc symbol should be in text section.
68*6a2ea846SYonghong Song // Use a different relocation to instruct ExecutionEngine
69*6a2ea846SYonghong Song // RuntimeDyld not to do relocation for it, yet still to
70*6a2ea846SYonghong Song // allow lld to do proper adjustment when merging sections.
710d99031dSYonghong Song if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_EXECINSTR))
72*6a2ea846SYonghong Song return ELF::R_BPF_64_NODYLD32;
73e698958aSYonghong Song } else {
74e698958aSYonghong Song // .BTF generates FK_Data_4 relocations for variable
75*6a2ea846SYonghong Song // offset in DataSec kind.
76e698958aSYonghong Song // The reloc symbol should be in data section.
77e698958aSYonghong Song if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_WRITE))
78*6a2ea846SYonghong Song return ELF::R_BPF_64_NODYLD32;
79e698958aSYonghong Song }
80821c93d5SYonghong Song }
810d99031dSYonghong Song }
82*6a2ea846SYonghong Song return ELF::R_BPF_64_ABS32;
83e4c8c807SAlexei Starovoitov }
84e4c8c807SAlexei Starovoitov }
85e4c8c807SAlexei Starovoitov
86dcd7d6c3SPeter Collingbourne std::unique_ptr<MCObjectTargetWriter>
createBPFELFObjectWriter(uint8_t OSABI)87dcd7d6c3SPeter Collingbourne llvm::createBPFELFObjectWriter(uint8_t OSABI) {
880eaee545SJonas Devlieghere return std::make_unique<BPFELFObjectWriter>(OSABI);
89e4c8c807SAlexei Starovoitov }
90