1//===-- ELF_mips.cpp - JIT linker implementation for ELF/MIPS ------------===//
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#include "llvm/ExecutionEngine/JITLink/ELF_mips.h"
10
11#include "EHFrameSupportImpl.h"
12#include "ELFLinkGraphBuilder.h"
13#include "JITLinkGeneric.h"
14#include "llvm/ADT/DenseMap.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/BinaryFormat/ELF.h"
18#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
19#include "llvm/ExecutionEngine/JITLink/mips.h"
20#include "llvm/Object/ELF.h"
21#include "llvm/Object/ELFObjectFile.h"
22#include "llvm/Support/Endian.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Support/MathExtras.h"
25#include "llvm/Support/MipsABIFlags.h"
26#include "llvm/Support/raw_ostream.h"
27
28#include <tuple>
29
30#define DEBUG_TYPE "jitlink"
31
32using namespace llvm;
33using namespace llvm::jitlink;
34using namespace llvm::jitlink::mips;
35
36namespace {
37
38constexpr StringRef GOTSectionName = "$__GOT";
39constexpr StringRef StubsSectionName = "$__STUBS";
40constexpr StringRef TLSInfoSectionName = "$__TLSINFO";
41constexpr StringRef TLSBaseName = "__jitlink_mips_tls_base";
42constexpr StringRef GOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
43constexpr StringRef GPName = "_gp";
44constexpr StringRef GPDispName = "_gp_disp";
45constexpr StringRef LocalGPName = "__gnu_local_gp";
46constexpr unsigned RelocationTypeBits = 8;
47constexpr unsigned MaxRelocationOperations = 3;
48constexpr int64_t CompactBranchPCBias = InstructionSize;
49// The MIPS psABI defines $gp as 0x7ff0 bytes past the GOT base.
50constexpr uint64_t GPAnchorOffset = 0x7ff0;
51
52enum class MipsABI { O32, N32, N64 };
53
54static Edge::Kind getPagePointerEdgeKind(const LinkGraph &G) {
55 return G.getPointerSize() == 8 ? PagePointer64 : PagePointer32;
56}
57
58template <unsigned Bits, unsigned Shift>
59static int64_t decodeInstructionImmediate(uint32_t Instruction) {
60 static_assert(Bits + Shift <= 32);
61 uint32_t Value = (Instruction & maskTrailingOnes<uint32_t>(N: Bits)) << Shift;
62 return SignExtend64<Bits + Shift>(Value);
63}
64
65static uint8_t getPackedRelocationField(uint32_t Packed, unsigned Index) {
66 return static_cast<uint8_t>((Packed >> (Index * RelocationTypeBits)) &
67 maskTrailingOnes<uint32_t>(N: RelocationTypeBits));
68}
69
70static std::string getRelocationChainName(ArrayRef<uint8_t> Types) {
71 std::string Result;
72 raw_string_ostream OS(Result);
73 for (auto [Index, Type] : llvm::enumerate(First&: Types)) {
74 if (Index)
75 OS << '/';
76 OS << object::getELFRelocationTypeName(Machine: ELF::EM_MIPS, Type);
77 }
78 return Result;
79}
80
81static unsigned getFixupSize(Edge::Kind K) {
82 switch (K) {
83 case Abs16:
84 return sizeof(uint16_t);
85 case Pointer64:
86 case PagePointer64:
87 case Delta64:
88 case GPRel64:
89 case DTPRel64:
90 return sizeof(uint64_t);
91 case Pointer32:
92 case PagePointer32:
93 case Delta32:
94 case NegDelta32:
95 case Hi16:
96 case Lo16:
97 case Higher16:
98 case Highest16:
99 case Jump26:
100 case PC16:
101 case PC32:
102 case PC18S3:
103 case PC19S2:
104 case PC21S2:
105 case PC26S2:
106 case PCHi16:
107 case PCLo16:
108 case GPDispHi16:
109 case GPDispLo16:
110 case GPRel16:
111 case GPRel32:
112 case GOTOffset16:
113 case GOTOffsetHi16:
114 case GOTOffsetLo16:
115 case GOTPageOffset16:
116 case DTPRelHi16:
117 case DTPRelLo16:
118 case DTPRel32:
119 case NegGPRelHi16:
120 case NegGPRelLo16:
121 case RequestGOTAndTransformToOffset16:
122 case RequestGOTPageAndTransformToOffset16:
123 case RequestGOTAndTransformToOffsetHi16:
124 case RequestGOTAndTransformToOffsetLo16:
125 case RequestTLSGDAndTransformToOffset16:
126 case RequestTLSLDMAndTransformToOffset16:
127 return sizeof(uint32_t);
128 default:
129 llvm_unreachable("not a MIPS relocation edge");
130 }
131}
132
133class ELFJITLinker_mips : public JITLinker<ELFJITLinker_mips> {
134 friend class JITLinker<ELFJITLinker_mips>;
135
136public:
137 ELFJITLinker_mips(std::unique_ptr<JITLinkContext> Ctx,
138 std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig)
139 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
140 getPassConfig().PreFixupPasses.push_back(x: [this](LinkGraph &G) {
141 GPSymbol = G.findDefinedSymbolByName(Name: G.intern(SymbolName: GPName));
142 TLSBaseSymbol = G.findDefinedSymbolByName(Name: G.intern(SymbolName: TLSBaseName));
143 return Error::success();
144 });
145 }
146
147private:
148 Symbol *GPSymbol = nullptr;
149 Symbol *TLSBaseSymbol = nullptr;
150
151 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
152 return mips::applyFixup(G, B, E, GPSymbol, TLSBaseSymbol);
153 }
154};
155
156template <typename ELFT>
157class ELFLinkGraphBuilder_mips : public ELFLinkGraphBuilder<ELFT> {
158 using Base = ELFLinkGraphBuilder<ELFT>;
159 using Rel = typename ELFT::Rel;
160 using Rela = typename ELFT::Rela;
161
162 struct Reloc {
163 uint64_t Offset;
164 uint32_t Symbol;
165 SmallVector<uint8_t, MaxRelocationOperations> Types;
166 int64_t Addend;
167 };
168
169public:
170 ELFLinkGraphBuilder_mips(StringRef FileName, const object::ELFFile<ELFT> &Obj,
171 std::shared_ptr<orc::SymbolStringPool> SSP,
172 Triple TT, SubtargetFeatures Features, MipsABI ABI)
173 : Base(Obj, std::move(SSP), std::move(TT), std::move(Features), FileName,
174 mips::getEdgeKindName),
175 ABI(ABI) {}
176
177private:
178 MipsABI ABI;
179
180 bool excludeSection(const typename ELFT::Shdr &Sec) const override {
181 return Sec.sh_type == ELF::SHT_MIPS_ABIFLAGS ||
182 Sec.sh_type == ELF::SHT_MIPS_REGINFO ||
183 Sec.sh_type == ELF::SHT_MIPS_OPTIONS;
184 }
185
186 Error error(const typename ELFT::Shdr &FixupSect, uint64_t Offset,
187 const Twine &Message) const {
188 auto Name = Base::Obj.getSectionName(FixupSect);
189 if (!Name)
190 return Name.takeError();
191 return make_error<JITLinkError>(Base::G->getName() + ": section " + *Name +
192 "+0x" + utohexstr(X: Offset) + ": " + Message);
193 }
194
195 Expected<int64_t> implicitAddend(const typename ELFT::Shdr &RelSect,
196 uint8_t Type, const Block &B,
197 uint64_t Offset) const {
198 if (Type == ELF::R_MIPS_NONE || Type == ELF::R_MIPS_JALR)
199 return 0;
200
201 unsigned FixupSize = Type == ELF::R_MIPS_16 ? sizeof(uint16_t)
202 : Type == ELF::R_MIPS_64 ? sizeof(uint64_t)
203 : sizeof(uint32_t);
204 if (Offset > B.getSize() || FixupSize > B.getSize() - Offset)
205 return error(FixupSect: RelSect, Offset,
206 Message: "relocation fixup extends past the end of its block");
207
208 const char *P = B.getContent().data() + Offset;
209 if (Type == ELF::R_MIPS_16)
210 return SignExtend64<16>(support::endian::read16<ELFT::Endianness>(P));
211
212 if (Type == ELF::R_MIPS_64)
213 return support::endian::read64<ELFT::Endianness>(P);
214
215 uint32_t W = support::endian::read32<ELFT::Endianness>(P);
216 switch (Type) {
217 case ELF::R_MIPS_32:
218 case ELF::R_MIPS_GPREL32:
219 case ELF::R_MIPS_PC32:
220 case ELF::R_MIPS_TLS_DTPREL32:
221 return SignExtend64<32>(x: W);
222 case ELF::R_MIPS_26:
223 return decodeInstructionImmediate<26, 2>(Instruction: W);
224 case ELF::R_MIPS_HI16:
225 case ELF::R_MIPS_PCHI16:
226 case ELF::R_MIPS_GOT16:
227 case ELF::R_MIPS_GOT_HI16:
228 case ELF::R_MIPS_CALL_HI16:
229 return decodeInstructionImmediate<16, 16>(Instruction: W);
230 case ELF::R_MIPS_PC16:
231 return decodeInstructionImmediate<16, 2>(Instruction: W);
232 case ELF::R_MIPS_PC18_S3:
233 return decodeInstructionImmediate<18, 3>(Instruction: W);
234 case ELF::R_MIPS_PC19_S2:
235 return decodeInstructionImmediate<19, 2>(Instruction: W);
236 case ELF::R_MIPS_PC21_S2:
237 return decodeInstructionImmediate<21, 2>(Instruction: W);
238 case ELF::R_MIPS_PC26_S2:
239 return decodeInstructionImmediate<26, 2>(Instruction: W);
240 default:
241 return decodeInstructionImmediate<16, 0>(Instruction: W);
242 }
243 }
244
245 static uint8_t matchingLow(uint8_t Type, bool IsLocal) {
246 switch (Type) {
247 case ELF::R_MIPS_HI16:
248 return ELF::R_MIPS_LO16;
249 case ELF::R_MIPS_PCHI16:
250 return ELF::R_MIPS_PCLO16;
251 case ELF::R_MIPS_GOT16:
252 return IsLocal ? ELF::R_MIPS_LO16 : ELF::R_MIPS_NONE;
253 default:
254 return ELF::R_MIPS_NONE;
255 }
256 }
257
258 Error validateSymbols() {
259 if (!Base::SymTabSec)
260 return Error::success();
261 auto Symbols = Base::Obj.symbols(Base::SymTabSec);
262 if (!Symbols)
263 return Symbols.takeError();
264 for (const auto &Sym : *Symbols)
265 if ((Sym.st_other & ELF::STO_MIPS_MICROMIPS) ||
266 (Sym.st_other & ELF::STO_MIPS_MIPS16) == ELF::STO_MIPS_MIPS16)
267 return make_error<JITLinkError>(
268 Base::G->getName() +
269 ": compact-mode MIPS16/microMIPS symbols are unsupported");
270 return Error::success();
271 }
272
273 Error collectRelocs(const typename ELFT::Shdr &RelSect, Block &B,
274 SmallVectorImpl<Reloc> &Out) {
275 if (RelSect.sh_type == ELF::SHT_RELA) {
276 auto Rs = Base::Obj.relas(RelSect);
277 if (!Rs)
278 return Rs.takeError();
279 for (auto I = Rs->begin(), E = Rs->end(); I != E;) {
280 const Rela &R = *I++;
281 if (ABI == MipsABI::N32) {
282 Reloc RR{R.r_offset, R.getSymbol(false), {}, R.r_addend};
283 RR.Types.push_back(R.getType(false));
284 while (I != E && I->r_offset == R.r_offset) {
285 if (RR.Types.size() == MaxRelocationOperations)
286 return error(FixupSect: RelSect, Offset: R.r_offset,
287 Message: "more than three N32 relocation operations");
288 if (I->getSymbol(false) != 0)
289 return error(FixupSect: RelSect, Offset: R.r_offset,
290 Message: "non-zero symbol in a secondary N32 relocation");
291 RR.Types.push_back(I->getType(false));
292 ++I;
293 }
294 Out.push_back(std::move(RR));
295 } else {
296 uint32_t PackedType = R.getType(Base::Obj.isMips64EL());
297 Reloc RR{
298 R.r_offset, R.getSymbol(Base::Obj.isMips64EL()), {}, R.r_addend};
299 uint8_t T2 = getPackedRelocationField(Packed: PackedType, Index: 1);
300 uint8_t T3 = getPackedRelocationField(Packed: PackedType, Index: 2);
301 RR.Types.push_back(getPackedRelocationField(Packed: PackedType, Index: 0));
302 if (T2 || T3)
303 RR.Types.push_back(T2);
304 if (T3)
305 RR.Types.push_back(T3);
306 uint8_t SSym = getPackedRelocationField(Packed: PackedType, Index: 3);
307 if (SSym != ELF::RSS_UNDEF)
308 return error(FixupSect: RelSect, Offset: R.r_offset,
309 Message: "unsupported packed relocation special symbol " +
310 Twine(SSym));
311 Out.push_back(std::move(RR));
312 }
313 }
314 return Error::success();
315 }
316
317 auto Rs = Base::Obj.rels(RelSect);
318 if (!Rs)
319 return Rs.takeError();
320 for (auto I = Rs->begin(), E = Rs->end(); I != E;) {
321 const Rel &R = *I++;
322 Reloc RR{R.r_offset, R.getSymbol(false), {}, 0};
323 RR.Types.push_back(R.getType(false));
324 if (ABI == MipsABI::N32) {
325 while (I != E && I->r_offset == R.r_offset) {
326 if (RR.Types.size() == MaxRelocationOperations)
327 return error(FixupSect: RelSect, Offset: R.r_offset,
328 Message: "more than three N32 relocation operations");
329 if (I->getSymbol(false) != 0)
330 return error(FixupSect: RelSect, Offset: R.r_offset,
331 Message: "non-zero symbol in a secondary N32 relocation");
332 RR.Types.push_back(I->getType(false));
333 ++I;
334 }
335 }
336 Out.push_back(std::move(RR));
337 }
338
339 for (size_t I = 0; I != Out.size(); ++I) {
340 auto &R = Out[I];
341 uint8_t FinalType = R.Types.back();
342 auto Addend = implicitAddend(RelSect, Type: FinalType, B, Offset: R.Offset);
343 if (!Addend)
344 return Addend.takeError();
345 R.Addend = *Addend;
346 bool IsLocal = false;
347 if (auto *S = Base::getGraphSymbol(R.Symbol))
348 IsLocal = S->getScope() == Scope::Local;
349 uint8_t LowType = matchingLow(Type: R.Types.front(), IsLocal);
350 if (LowType == ELF::R_MIPS_NONE)
351 continue;
352 bool Found = false;
353 for (size_t J = I + 1; J != Out.size(); ++J)
354 if (Out[J].Types.front() == LowType && Out[J].Symbol == R.Symbol) {
355 auto LowAddend = implicitAddend(RelSect, Type: LowType, B, Offset: Out[J].Offset);
356 if (!LowAddend)
357 return LowAddend.takeError();
358 R.Addend += *LowAddend;
359 Found = true;
360 break;
361 }
362 if (!Found)
363 return error(FixupSect: RelSect, Offset: R.Offset,
364 Message: "unmatched " +
365 Twine(object::getELFRelocationTypeName(
366 Machine: ELF::EM_MIPS, Type: R.Types.front())) +
367 " relocation");
368 }
369 return Error::success();
370 }
371
372 Expected<Edge::Kind> edgeKind(const Reloc &R, Symbol &Target) const {
373 if (R.Types.size() > 1) {
374 if (R.Types.size() == 2 && R.Types[1] == ELF::R_MIPS_64) {
375 switch (R.Types[0]) {
376 case ELF::R_MIPS_32:
377 case ELF::R_MIPS_64:
378 return Pointer64;
379 case ELF::R_MIPS_PC32:
380 return Delta64;
381 case ELF::R_MIPS_GPREL32:
382 return GPRel64;
383 default:
384 break;
385 }
386 }
387 if (R.Types.size() == 3 && R.Types[0] == ELF::R_MIPS_GPREL16 &&
388 R.Types[1] == ELF::R_MIPS_SUB && R.Types[2] == ELF::R_MIPS_HI16)
389 return NegGPRelHi16;
390 if (R.Types.size() == 3 && R.Types[0] == ELF::R_MIPS_GPREL16 &&
391 R.Types[1] == ELF::R_MIPS_SUB && R.Types[2] == ELF::R_MIPS_LO16)
392 return NegGPRelLo16;
393 return make_error<JITLinkError>("unsupported packed MIPS relocation " +
394 getRelocationChainName(R.Types));
395 }
396
397 StringRef Name = Target.hasName() ? *Target.getName() : StringRef();
398 switch (R.Types.front()) {
399 case ELF::R_MIPS_16:
400 return Abs16;
401 case ELF::R_MIPS_32:
402 return Pointer32;
403 case ELF::R_MIPS_64:
404 return Pointer64;
405 case ELF::R_MIPS_HI16:
406 return Name == GPDispName ? GPDispHi16 : Hi16;
407 case ELF::R_MIPS_LO16:
408 return Name == GPDispName ? GPDispLo16 : Lo16;
409 case ELF::R_MIPS_HIGHER:
410 return Higher16;
411 case ELF::R_MIPS_HIGHEST:
412 return Highest16;
413 case ELF::R_MIPS_26:
414 return Jump26;
415 case ELF::R_MIPS_PC16:
416 return PC16;
417 case ELF::R_MIPS_PC32:
418 return PC32;
419 case ELF::R_MIPS_PC18_S3:
420 return PC18S3;
421 case ELF::R_MIPS_PC19_S2:
422 return PC19S2;
423 case ELF::R_MIPS_PC21_S2:
424 return PC21S2;
425 case ELF::R_MIPS_PC26_S2:
426 return PC26S2;
427 case ELF::R_MIPS_PCHI16:
428 return PCHi16;
429 case ELF::R_MIPS_PCLO16:
430 return PCLo16;
431 case ELF::R_MIPS_GPREL16:
432 return GPRel16;
433 case ELF::R_MIPS_GPREL32:
434 return GPRel32;
435 case ELF::R_MIPS_GOT16:
436 return Target.getScope() == Scope::Local
437 ? RequestGOTPageAndTransformToOffset16
438 : RequestGOTAndTransformToOffset16;
439 case ELF::R_MIPS_CALL16:
440 case ELF::R_MIPS_GOT_DISP:
441 return RequestGOTAndTransformToOffset16;
442 case ELF::R_MIPS_GOT_PAGE:
443 return RequestGOTPageAndTransformToOffset16;
444 case ELF::R_MIPS_GOT_OFST:
445 return GOTPageOffset16;
446 case ELF::R_MIPS_GOT_HI16:
447 case ELF::R_MIPS_CALL_HI16:
448 return RequestGOTAndTransformToOffsetHi16;
449 case ELF::R_MIPS_GOT_LO16:
450 case ELF::R_MIPS_CALL_LO16:
451 return RequestGOTAndTransformToOffsetLo16;
452 case ELF::R_MIPS_TLS_GD:
453 return RequestTLSGDAndTransformToOffset16;
454 case ELF::R_MIPS_TLS_LDM:
455 return RequestTLSLDMAndTransformToOffset16;
456 case ELF::R_MIPS_TLS_DTPREL_HI16:
457 return DTPRelHi16;
458 case ELF::R_MIPS_TLS_DTPREL_LO16:
459 return DTPRelLo16;
460 case ELF::R_MIPS_TLS_DTPREL32:
461 return DTPRel32;
462 case ELF::R_MIPS_TLS_DTPREL64:
463 return DTPRel64;
464 case ELF::R_MIPS_TLS_GOTTPREL:
465 case ELF::R_MIPS_TLS_TPREL32:
466 case ELF::R_MIPS_TLS_TPREL64:
467 case ELF::R_MIPS_TLS_TPREL_HI16:
468 case ELF::R_MIPS_TLS_TPREL_LO16:
469 return make_error<JITLinkError>(
470 Args: "initial/local-exec MIPS TLS relocations are unsupported");
471 default:
472 return make_error<JITLinkError>(Args: "unsupported MIPS relocation " +
473 Twine(object::getELFRelocationTypeName(
474 Machine: ELF::EM_MIPS, Type: R.Types.front())));
475 }
476 }
477
478 Error addRelocations() override {
479 if (auto Err = validateSymbols())
480 return Err;
481 for (const auto &RelSect : Base::Sections) {
482 if (RelSect.sh_type != ELF::SHT_REL && RelSect.sh_type != ELF::SHT_RELA)
483 continue;
484 if ((ABI != MipsABI::O32) != (RelSect.sh_type == ELF::SHT_RELA))
485 return make_error<JITLinkError>(
486 Base::G->getName() +
487 ": invalid MIPS relocation-section format for ABI");
488 auto FixupSect = Base::Obj.getSection(RelSect.sh_info);
489 if (!FixupSect)
490 return FixupSect.takeError();
491 Block *B = Base::getGraphBlock(RelSect.sh_info);
492 if (!B)
493 continue;
494 SmallVector<Reloc> Rs;
495 if (auto Err = collectRelocs(RelSect, B&: *B, Out&: Rs))
496 return Err;
497 for (const Reloc &R : Rs) {
498 uint8_t Primary = R.Types.front();
499 if (Primary == ELF::R_MIPS_NONE || Primary == ELF::R_MIPS_JALR)
500 continue;
501 Symbol *Target = Base::getGraphSymbol(R.Symbol);
502 if (!Target)
503 return error(FixupSect: **FixupSect, Offset: R.Offset,
504 Message: "relocation references missing symbol index " +
505 Twine(R.Symbol));
506 auto Kind = edgeKind(R, Target&: *Target);
507 if (!Kind)
508 return joinErrors(
509 error(FixupSect: **FixupSect, Offset: R.Offset, Message: "cannot lower relocation"),
510 Kind.takeError());
511 auto FixupAddress = orc::ExecutorAddr((*FixupSect)->sh_addr) + R.Offset;
512 Edge::OffsetT Offset = FixupAddress - B->getAddress();
513 unsigned FixupSize = getFixupSize(*Kind);
514 if (Offset > B->getSize() || FixupSize > B->getSize() - Offset)
515 return error(FixupSect: **FixupSect, Offset: R.Offset,
516 Message: "relocation fixup extends past the end of its block");
517 B->addEdge(*Kind, Offset, *Target, R.Addend);
518 }
519 }
520 return Error::success();
521 }
522};
523
524static Symbol &getOrCreateTLSBase(LinkGraph &G) {
525 auto Name = G.intern(SymbolName: TLSBaseName);
526 if (auto *S = G.findDefinedSymbolByName(Name))
527 return *S;
528 Section *TLS = G.findSectionByName(Name: ".tdata");
529 if (!TLS || TLS->empty())
530 TLS = G.findSectionByName(Name: ".tbss");
531 if (!TLS || TLS->empty()) {
532 auto &S =
533 G.createSection(Name: ".tdata", Prot: orc::MemProt::Read | orc::MemProt::Write);
534 auto &B = G.createMutableContentBlock(Parent&: S, ContentSize: 0, Address: orc::ExecutorAddr(), Alignment: 1, AlignmentOffset: 0);
535 return G.addDefinedSymbol(Content&: B, Offset: 0, Name, Size: 0, L: Linkage::Strong, S: Scope::Local,
536 IsCallable: false, IsLive: true);
537 }
538 auto &B = **TLS->blocks().begin();
539 return G.addDefinedSymbol(Content&: B, Offset: 0, Name, Size: 0, L: Linkage::Strong, S: Scope::Local, IsCallable: false,
540 IsLive: true);
541}
542
543class MipsTableManager {
544public:
545 explicit MipsTableManager(LinkGraph &G) : G(G) {}
546
547 bool visitEdge(LinkGraph &, Block *, Edge &E) {
548 switch (E.getKind()) {
549 case RequestGOTAndTransformToOffset16:
550 rewriteGOT(E, EntryKind: GOTEntryKind::Exact, NewKind: GOTOffset16);
551 return true;
552 case RequestGOTPageAndTransformToOffset16:
553 rewriteGOT(E, EntryKind: GOTEntryKind::Page, NewKind: GOTOffset16);
554 return true;
555 case RequestGOTAndTransformToOffsetHi16:
556 rewriteGOT(E, EntryKind: GOTEntryKind::Exact, NewKind: GOTOffsetHi16);
557 return true;
558 case RequestGOTAndTransformToOffsetLo16:
559 rewriteGOT(E, EntryKind: GOTEntryKind::Exact, NewKind: GOTOffsetLo16);
560 return true;
561 case RequestTLSGDAndTransformToOffset16:
562 rewriteTLS(E, Kind: TLSDescriptorKind::GeneralDynamic);
563 return true;
564 case RequestTLSLDMAndTransformToOffset16:
565 rewriteTLS(E, Kind: TLSDescriptorKind::LocalDynamic);
566 return true;
567 case Jump26:
568 if (!E.getTarget().isDefined()) {
569 rewriteBranchToStub(E);
570 return true;
571 }
572 return false;
573 case PC26S2:
574 if (mips::isR6(G) && !E.getTarget().isDefined()) {
575 rewriteBranchToStub(E);
576 return true;
577 }
578 return false;
579 default:
580 return false;
581 }
582 }
583
584private:
585 enum class GOTEntryKind { Exact, Page };
586 enum class TLSDescriptorKind { GeneralDynamic, LocalDynamic };
587
588 using GOTKey = std::tuple<Symbol *, int64_t, GOTEntryKind>;
589 using StubKey = std::tuple<Symbol *, int64_t>;
590 LinkGraph &G;
591 DenseMap<GOTKey, Symbol *> GOTEntries;
592 DenseMap<StubKey, Symbol *> Stubs;
593 DenseMap<std::pair<Symbol *, int64_t>, Symbol *> TLSGDEntries;
594 Symbol *TLSLDMEntry = nullptr;
595
596 Section &getSection(StringRef Name, orc::MemProt Prot) {
597 if (auto *S = G.findSectionByName(Name))
598 return *S;
599 return G.createSection(Name, Prot);
600 }
601
602 Symbol &getGOT(Symbol &Target, int64_t Addend, GOTEntryKind Kind) {
603 GOTKey Key{&Target, Addend, Kind};
604 auto I = GOTEntries.find(Val: Key);
605 if (I != GOTEntries.end())
606 return *I->second;
607 auto &Sec =
608 getSection(Name: GOTSectionName, Prot: orc::MemProt::Read | orc::MemProt::Write);
609 auto &Entry = mips::createAnonymousPointer(G, PointerSection&: Sec);
610 Edge::Kind PointerKind = Kind == GOTEntryKind::Page
611 ? getPagePointerEdgeKind(G)
612 : mips::getPointerEdgeKind(G);
613 Entry.getBlock().addEdge(K: PointerKind, Offset: 0, Target, Addend);
614 GOTEntries[Key] = &Entry;
615 return Entry;
616 }
617
618 void rewriteGOT(Edge &E, GOTEntryKind EntryKind, Edge::Kind NewKind) {
619 Symbol &Entry = getGOT(Target&: E.getTarget(), Addend: E.getAddend(), Kind: EntryKind);
620 E.setKind(NewKind);
621 E.setTarget(Entry);
622 E.setAddend(0);
623 }
624
625 Symbol &createTLSInfo(Symbol &Target, int64_t Addend) {
626 auto &Sec = getSection(Name: TLSInfoSectionName,
627 Prot: orc::MemProt::Read | orc::MemProt::Write);
628 auto &B =
629 G.createMutableContentBlock(Parent&: Sec, ContentSize: 2 * G.getPointerSize(),
630 Address: orc::ExecutorAddr(), Alignment: G.getPointerSize(), AlignmentOffset: 0);
631 B.addEdge(K: mips::getPointerEdgeKind(G), Offset: G.getPointerSize(), Target, Addend);
632 return G.addAnonymousSymbol(Content&: B, Offset: 0, Size: B.getSize(), IsCallable: false, IsLive: false);
633 }
634
635 void rewriteTLS(Edge &E, TLSDescriptorKind Kind) {
636 Symbol *Entry = nullptr;
637 if (Kind == TLSDescriptorKind::LocalDynamic) {
638 if (!TLSLDMEntry)
639 TLSLDMEntry = &createTLSInfo(Target&: getOrCreateTLSBase(G), Addend: 0);
640 Entry = TLSLDMEntry;
641 } else {
642 auto Key = std::make_pair(x: &E.getTarget(), y: E.getAddend());
643 auto I = TLSGDEntries.find(Val: Key);
644 if (I == TLSGDEntries.end())
645 I = TLSGDEntries
646 .try_emplace(Key, Args: &createTLSInfo(Target&: E.getTarget(), Addend: E.getAddend()))
647 .first;
648 Entry = I->second;
649 }
650 E.setKind(GOTOffset16);
651 E.setTarget(*Entry);
652 E.setAddend(0);
653 }
654
655 void rewriteBranchToStub(Edge &E) {
656 // PC26_S2 uses PC + 4; JITLink edges use the fixup address.
657 int64_t PointerAddend = E.getAddend();
658 int64_t BranchAddend = 0;
659 if (E.getKind() == PC26S2) {
660 PointerAddend += CompactBranchPCBias;
661 BranchAddend = -CompactBranchPCBias;
662 }
663
664 StubKey Key{&E.getTarget(), PointerAddend};
665 auto I = Stubs.find(Val: Key);
666 if (I == Stubs.end()) {
667 auto &Ptr = getGOT(Target&: E.getTarget(), Addend: PointerAddend, Kind: GOTEntryKind::Exact);
668 auto &Sec =
669 getSection(Name: StubsSectionName, Prot: orc::MemProt::Read | orc::MemProt::Exec);
670 I = Stubs
671 .try_emplace(Key,
672 Args: &mips::createAnonymousPointerJumpStub(G, StubSection&: Sec, PointerSymbol&: Ptr))
673 .first;
674 }
675 E.setTarget(*I->second);
676 E.setAddend(BranchAddend);
677 }
678};
679
680static Error buildTables(LinkGraph &G) {
681 MipsTableManager Tables(G);
682 visitExistingEdges(G, Vs&: Tables);
683 return Error::success();
684}
685
686static Symbol &defineMagic(LinkGraph &G, Block &Anchor, StringRef Name,
687 uint64_t Offset) {
688 auto N = G.intern(SymbolName: Name);
689 if (auto *S = G.findDefinedSymbolByName(Name: N)) {
690 S->setLive(true);
691 return *S;
692 }
693 if (auto *S = G.findExternalSymbolByName(Name: N)) {
694 G.makeDefined(Sym&: *S, Content&: Anchor, Offset, Size: 0, L: Linkage::Strong, S: Scope::Local, IsLive: true);
695 return *S;
696 }
697 return G.addDefinedSymbol(Content&: Anchor, Offset, Name: N, Size: 0, L: Linkage::Strong, S: Scope::Local,
698 IsCallable: false, IsLive: true);
699}
700
701static void prepareGPRegion(LinkGraph &G,
702 ArrayRef<std::string> GPRelSectionNames) {
703 Section *GOT = G.findSectionByName(Name: GOTSectionName);
704 if (!GOT)
705 GOT = &G.createSection(Name: GOTSectionName,
706 Prot: orc::MemProt::Read | orc::MemProt::Write);
707 // Keep the reserved GP window as content so it can share the GOT section.
708 auto &Anchor = G.createMutableContentBlock(
709 Parent&: *GOT, ContentSize: GPAnchorOffset, Address: orc::ExecutorAddr(), Alignment: G.getPointerSize(), AlignmentOffset: 0);
710 defineMagic(G, Anchor, Name: GOTSymbolName, Offset: 0);
711 defineMagic(G, Anchor, Name: GPName, Offset: GPAnchorOffset);
712 defineMagic(G, Anchor, Name: GPDispName, Offset: GPAnchorOffset);
713 defineMagic(G, Anchor, Name: LocalGPName, Offset: GPAnchorOffset);
714
715 for (const std::string &Name : GPRelSectionNames)
716 if (auto *S = G.findSectionByName(Name)) {
717 SmallVector<Block *> Blocks(S->blocks().begin(), S->blocks().end());
718 for (auto *B : Blocks)
719 G.transferBlock(B&: *B, NewSection&: *GOT);
720 }
721}
722
723static Error orderGPRegion(LinkGraph &G) {
724 auto *GOT = G.findSectionByName(Name: GOTSectionName);
725 if (!GOT)
726 return Error::success();
727
728 if (auto *TLSInfo = G.findSectionByName(Name: TLSInfoSectionName))
729 G.mergeSections(DstSection&: *GOT, SrcSection&: *TLSInfo);
730
731 auto *GOTBase = G.findDefinedSymbolByName(Name: G.intern(SymbolName: GOTSymbolName));
732 assert(GOTBase && &GOTBase->getBlock().getSection() == GOT &&
733 GOTBase->getOffset() == 0 && "invalid MIPS GOT base");
734
735 // BasicLayout orders equal-address blocks by size. Give synthesized entries
736 // the anchor's end address to keep the reserved GP window first.
737 Block &Anchor = GOTBase->getBlock();
738 Anchor.setAddress(orc::ExecutorAddr());
739 for (auto *B : GOT->blocks())
740 if (B != &Anchor)
741 B->setAddress(orc::ExecutorAddr(Anchor.getSize()));
742
743 return Error::success();
744}
745
746template <typename ELFT>
747Error validateABIFlags(const object::ELFFile<ELFT> &Obj, MipsABI ABI,
748 StringRef FileName) {
749 auto Sections = Obj.sections();
750 if (!Sections)
751 return Sections.takeError();
752 const typename ELFT::Shdr *ABIFlagsSec = nullptr;
753 for (const auto &Sec : *Sections)
754 if (Sec.sh_type == ELF::SHT_MIPS_ABIFLAGS) {
755 if (ABIFlagsSec)
756 return make_error<JITLinkError>(Args: FileName.str() +
757 ": multiple .MIPS.abiflags sections");
758 ABIFlagsSec = &Sec;
759 }
760 if (!ABIFlagsSec)
761 return Error::success();
762 auto Contents = Obj.template getSectionContentsAsArray<char>(*ABIFlagsSec);
763 if (!Contents)
764 return Contents.takeError();
765 if (Contents->size() != sizeof(object::Elf_Mips_ABIFlags<ELFT>))
766 return make_error<JITLinkError>(Args: FileName.str() +
767 ": invalid .MIPS.abiflags size");
768 const auto &AF = *reinterpret_cast<const object::Elf_Mips_ABIFlags<ELFT> *>(
769 Contents->data());
770 if (AF.version != 0)
771 return make_error<JITLinkError>(Args: FileName.str() +
772 ": unsupported .MIPS.abiflags version");
773 if ((ABI == MipsABI::N32 || ABI == MipsABI::N64) &&
774 AF.gpr_size != Mips::AFL_REG_64)
775 return make_error<JITLinkError>(
776 Args: FileName.str() + ": N32/N64 requires 64-bit general registers");
777 if (static_cast<uint32_t>(AF.ases) &
778 (Mips::AFL_ASE_MIPS16 | Mips::AFL_ASE_MICROMIPS))
779 return make_error<JITLinkError>(
780 Args: FileName.str() +
781 ": MIPS16 and microMIPS ABI flags are unsupported by JITLink");
782 return Error::success();
783}
784
785template <typename ELFT>
786Expected<std::unique_ptr<LinkGraph>>
787buildGraph(object::ELFObjectFile<ELFT> &ObjFile,
788 std::shared_ptr<orc::SymbolStringPool> SSP, MipsABI ABI, Triple TT,
789 SubtargetFeatures Features) {
790 auto &Obj = ObjFile.getELFFile();
791 if (auto Err = validateABIFlags(Obj, ABI, ObjFile.getFileName()))
792 return std::move(Err);
793 ELFLinkGraphBuilder_mips<ELFT> Builder(ObjFile.getFileName(), Obj,
794 std::move(SSP), std::move(TT),
795 std::move(Features), ABI);
796 auto G = Builder.buildGraph();
797 if (!G)
798 return G.takeError();
799
800 SmallVector<std::string> GPRelSections;
801 auto Sections = Obj.sections();
802 if (!Sections)
803 return Sections.takeError();
804 for (const auto &Sec : *Sections)
805 if (Sec.sh_flags & ELF::SHF_MIPS_GPREL) {
806 auto Name = Obj.getSectionName(Sec);
807 if (!Name)
808 return Name.takeError();
809 GPRelSections.push_back(Name->str());
810 }
811 prepareGPRegion(**G, GPRelSections);
812 return G;
813}
814
815static Expected<MipsABI> validateHeader(const object::ELFObjectFileBase &Obj,
816 uint8_t ELFClass, StringRef FileName) {
817 uint32_t Flags = Obj.getPlatformFlags();
818 if (Flags & (ELF::EF_MIPS_ARCH_ASE_M16 | ELF::EF_MIPS_MICROMIPS))
819 return make_error<JITLinkError>(
820 Args: FileName.str() +
821 ": MIPS16 and microMIPS objects are unsupported by JITLink");
822
823 uint32_t ABIFlag = Flags & ELF::EF_MIPS_ABI;
824 if (ELFClass == ELF::ELFCLASS64) {
825 if ((Flags & ELF::EF_MIPS_ABI2) || ABIFlag != 0)
826 return make_error<JITLinkError>(
827 Args: FileName.str() + ": inconsistent MIPS N64 ELF class/ABI flags");
828 return MipsABI::N64;
829 }
830 if (Flags & ELF::EF_MIPS_ABI2) {
831 if (ABIFlag != 0)
832 return make_error<JITLinkError>(
833 Args: FileName.str() + ": inconsistent MIPS N32 ELF class/ABI flags");
834 return MipsABI::N32;
835 }
836 if (ABIFlag != 0 && ABIFlag != ELF::EF_MIPS_ABI_O32)
837 return make_error<JITLinkError>(Args: FileName.str() +
838 ": unsupported 32-bit MIPS ABI flags");
839 return MipsABI::O32;
840}
841
842} // namespace
843
844namespace llvm {
845namespace jitlink {
846
847Expected<std::unique_ptr<LinkGraph>>
848createLinkGraphFromELFObject_mips(MemoryBufferRef ObjectBuffer,
849 std::shared_ptr<orc::SymbolStringPool> SSP) {
850 StringRef FileName = ObjectBuffer.getBufferIdentifier();
851 auto ELFObj = object::ObjectFile::createELFObjectFile(Object: ObjectBuffer);
852 if (!ELFObj)
853 return ELFObj.takeError();
854 auto &Base = cast<object::ELFObjectFileBase>(Val&: **ELFObj);
855 assert(Base.getEMachine() == ELF::EM_MIPS && "expected an ELF/MIPS object");
856
857 StringRef Buf = ObjectBuffer.getBuffer();
858 uint8_t Class = Buf[ELF::EI_CLASS];
859 uint8_t Data = Buf[ELF::EI_DATA];
860 auto ABI = validateHeader(Obj: Base, ELFClass: Class, FileName);
861 if (!ABI)
862 return ABI.takeError();
863 auto Features = Base.getFeatures();
864 if (!Features)
865 return Features.takeError();
866
867 Triple TT = Base.makeTriple();
868 if (*ABI == MipsABI::N32) {
869 TT.setArch(Kind: Data == ELF::ELFDATA2LSB ? Triple::mips64el : Triple::mips64);
870 TT.setEnvironment(Triple::GNUABIN32);
871 }
872
873 if (Class == ELF::ELFCLASS32 && Data == ELF::ELFDATA2LSB)
874 return buildGraph(ObjFile&: cast<object::ELFObjectFile<object::ELF32LE>>(Val&: **ELFObj),
875 SSP: std::move(SSP), ABI: *ABI, TT, Features: std::move(*Features));
876 if (Class == ELF::ELFCLASS32 && Data == ELF::ELFDATA2MSB)
877 return buildGraph(ObjFile&: cast<object::ELFObjectFile<object::ELF32BE>>(Val&: **ELFObj),
878 SSP: std::move(SSP), ABI: *ABI, TT, Features: std::move(*Features));
879 if (Class == ELF::ELFCLASS64 && Data == ELF::ELFDATA2LSB)
880 return buildGraph(ObjFile&: cast<object::ELFObjectFile<object::ELF64LE>>(Val&: **ELFObj),
881 SSP: std::move(SSP), ABI: *ABI, TT, Features: std::move(*Features));
882 if (Class == ELF::ELFCLASS64 && Data == ELF::ELFDATA2MSB)
883 return buildGraph(ObjFile&: cast<object::ELFObjectFile<object::ELF64BE>>(Val&: **ELFObj),
884 SSP: std::move(SSP), ABI: *ABI, TT, Features: std::move(*Features));
885 llvm_unreachable("invalid ELF/MIPS class or byte order");
886}
887
888void link_ELF_mips(std::unique_ptr<LinkGraph> G,
889 std::unique_ptr<JITLinkContext> Ctx) {
890 PassConfiguration Config;
891 const Triple &TT = G->getTargetTriple();
892 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
893 Config.PrePrunePasses.push_back(x: DWARFRecordSectionSplitter(".eh_frame"));
894 Config.PrePrunePasses.push_back(
895 x: EHFrameEdgeFixer(".eh_frame", G->getPointerSize(), Pointer32, Pointer64,
896 Delta32, Delta64, NegDelta32));
897 Config.PrePrunePasses.push_back(x: EHFrameNullTerminator(".eh_frame"));
898 if (auto MarkLive = Ctx->getMarkLivePass(TT))
899 Config.PrePrunePasses.push_back(x: std::move(MarkLive));
900 else
901 Config.PrePrunePasses.push_back(x: markAllSymbolsLive);
902 Config.PostPrunePasses.push_back(x: buildTables);
903 }
904 if (auto Err = Ctx->modifyPassConfig(G&: *G, Config))
905 return Ctx->notifyFailed(Err: std::move(Err));
906 if (Ctx->shouldAddDefaultTargetPasses(TT))
907 Config.PostPrunePasses.push_back(x: orderGPRegion);
908 ELFJITLinker_mips::link(Args: std::move(Ctx), Args: std::move(G), Args: std::move(Config));
909}
910
911} // namespace jitlink
912} // namespace llvm
913