Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
35271 views
1
//===--- ELF_loongarch.cpp - JIT linker implementation for ELF/loongarch --===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// ELF/loongarch jit-link implementation.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/ExecutionEngine/JITLink/ELF_loongarch.h"
14
#include "llvm/BinaryFormat/ELF.h"
15
#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
16
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
17
#include "llvm/ExecutionEngine/JITLink/loongarch.h"
18
#include "llvm/Object/ELF.h"
19
#include "llvm/Object/ELFObjectFile.h"
20
21
#include "EHFrameSupportImpl.h"
22
#include "ELFLinkGraphBuilder.h"
23
#include "JITLinkGeneric.h"
24
25
#define DEBUG_TYPE "jitlink"
26
27
using namespace llvm;
28
using namespace llvm::jitlink;
29
using namespace llvm::jitlink::loongarch;
30
31
namespace {
32
33
class ELFJITLinker_loongarch : public JITLinker<ELFJITLinker_loongarch> {
34
friend class JITLinker<ELFJITLinker_loongarch>;
35
36
public:
37
ELFJITLinker_loongarch(std::unique_ptr<JITLinkContext> Ctx,
38
std::unique_ptr<LinkGraph> G,
39
PassConfiguration PassConfig)
40
: JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
41
42
private:
43
Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
44
return loongarch::applyFixup(G, B, E);
45
}
46
};
47
48
template <typename ELFT>
49
class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
50
private:
51
static Expected<loongarch::EdgeKind_loongarch>
52
getRelocationKind(const uint32_t Type) {
53
using namespace loongarch;
54
switch (Type) {
55
case ELF::R_LARCH_64:
56
return Pointer64;
57
case ELF::R_LARCH_32:
58
return Pointer32;
59
case ELF::R_LARCH_32_PCREL:
60
return Delta32;
61
case ELF::R_LARCH_B26:
62
return Branch26PCRel;
63
case ELF::R_LARCH_PCALA_HI20:
64
return Page20;
65
case ELF::R_LARCH_PCALA_LO12:
66
return PageOffset12;
67
case ELF::R_LARCH_GOT_PC_HI20:
68
return RequestGOTAndTransformToPage20;
69
case ELF::R_LARCH_GOT_PC_LO12:
70
return RequestGOTAndTransformToPageOffset12;
71
}
72
73
return make_error<JITLinkError>(
74
"Unsupported loongarch relocation:" + formatv("{0:d}: ", Type) +
75
object::getELFRelocationTypeName(ELF::EM_LOONGARCH, Type));
76
}
77
78
Error addRelocations() override {
79
LLVM_DEBUG(dbgs() << "Processing relocations:\n");
80
81
using Base = ELFLinkGraphBuilder<ELFT>;
82
using Self = ELFLinkGraphBuilder_loongarch<ELFT>;
83
for (const auto &RelSect : Base::Sections)
84
if (Error Err = Base::forEachRelaRelocation(RelSect, this,
85
&Self::addSingleRelocation))
86
return Err;
87
88
return Error::success();
89
}
90
91
Error addSingleRelocation(const typename ELFT::Rela &Rel,
92
const typename ELFT::Shdr &FixupSect,
93
Block &BlockToFix) {
94
using Base = ELFLinkGraphBuilder<ELFT>;
95
96
uint32_t SymbolIndex = Rel.getSymbol(false);
97
auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
98
if (!ObjSymbol)
99
return ObjSymbol.takeError();
100
101
Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
102
if (!GraphSymbol)
103
return make_error<StringError>(
104
formatv("Could not find symbol at given index, did you add it to "
105
"JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
106
SymbolIndex, (*ObjSymbol)->st_shndx,
107
Base::GraphSymbols.size()),
108
inconvertibleErrorCode());
109
110
uint32_t Type = Rel.getType(false);
111
Expected<loongarch::EdgeKind_loongarch> Kind = getRelocationKind(Type);
112
if (!Kind)
113
return Kind.takeError();
114
115
int64_t Addend = Rel.r_addend;
116
auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
117
Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
118
Edge GE(*Kind, Offset, *GraphSymbol, Addend);
119
LLVM_DEBUG({
120
dbgs() << " ";
121
printEdge(dbgs(), BlockToFix, GE, loongarch::getEdgeKindName(*Kind));
122
dbgs() << "\n";
123
});
124
125
BlockToFix.addEdge(std::move(GE));
126
127
return Error::success();
128
}
129
130
public:
131
ELFLinkGraphBuilder_loongarch(StringRef FileName,
132
const object::ELFFile<ELFT> &Obj, Triple TT,
133
SubtargetFeatures Features)
134
: ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
135
FileName, loongarch::getEdgeKindName) {}
136
};
137
138
Error buildTables_ELF_loongarch(LinkGraph &G) {
139
LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
140
141
GOTTableManager GOT;
142
PLTTableManager PLT(GOT);
143
visitExistingEdges(G, GOT, PLT);
144
return Error::success();
145
}
146
147
} // namespace
148
149
namespace llvm {
150
namespace jitlink {
151
152
Expected<std::unique_ptr<LinkGraph>>
153
createLinkGraphFromELFObject_loongarch(MemoryBufferRef ObjectBuffer) {
154
LLVM_DEBUG({
155
dbgs() << "Building jitlink graph for new input "
156
<< ObjectBuffer.getBufferIdentifier() << "...\n";
157
});
158
159
auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
160
if (!ELFObj)
161
return ELFObj.takeError();
162
163
auto Features = (*ELFObj)->getFeatures();
164
if (!Features)
165
return Features.takeError();
166
167
if ((*ELFObj)->getArch() == Triple::loongarch64) {
168
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
169
return ELFLinkGraphBuilder_loongarch<object::ELF64LE>(
170
(*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
171
(*ELFObj)->makeTriple(), std::move(*Features))
172
.buildGraph();
173
}
174
175
assert((*ELFObj)->getArch() == Triple::loongarch32 &&
176
"Invalid triple for LoongArch ELF object file");
177
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
178
return ELFLinkGraphBuilder_loongarch<object::ELF32LE>(
179
(*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
180
(*ELFObj)->makeTriple(), std::move(*Features))
181
.buildGraph();
182
}
183
184
void link_ELF_loongarch(std::unique_ptr<LinkGraph> G,
185
std::unique_ptr<JITLinkContext> Ctx) {
186
PassConfiguration Config;
187
const Triple &TT = G->getTargetTriple();
188
if (Ctx->shouldAddDefaultTargetPasses(TT)) {
189
// Add eh-frame passes.
190
Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
191
Config.PrePrunePasses.push_back(
192
EHFrameEdgeFixer(".eh_frame", G->getPointerSize(), Pointer32, Pointer64,
193
Delta32, Delta64, NegDelta32));
194
Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
195
196
// Add a mark-live pass.
197
if (auto MarkLive = Ctx->getMarkLivePass(TT))
198
Config.PrePrunePasses.push_back(std::move(MarkLive));
199
else
200
Config.PrePrunePasses.push_back(markAllSymbolsLive);
201
202
// Add an in-place GOT/PLTStubs build pass.
203
Config.PostPrunePasses.push_back(buildTables_ELF_loongarch);
204
}
205
206
if (auto Err = Ctx->modifyPassConfig(*G, Config))
207
return Ctx->notifyFailed(std::move(Err));
208
209
ELFJITLinker_loongarch::link(std::move(Ctx), std::move(G), std::move(Config));
210
}
211
212
} // namespace jitlink
213
} // namespace llvm
214
215