1 //===------- ELF_ppc64.cpp -JIT linker implementation for ELF/ppc64 -------===//
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
7 //===----------------------------------------------------------------------===//
9 // ELF/ppc64 jit-link implementation.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h"
14 #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
15 #include "llvm/ExecutionEngine/JITLink/TableManager.h"
16 #include "llvm/ExecutionEngine/JITLink/ppc64.h"
17 #include "llvm/Object/ELFObjectFile.h"
19 #include "EHFrameSupportImpl.h"
20 #include "ELFLinkGraphBuilder.h"
21 #include "JITLinkGeneric.h"
23 #define DEBUG_TYPE "jitlink"
28 using namespace llvm::jitlink
;
30 constexpr StringRef ELFTOCSymbolName
= ".TOC.";
31 constexpr StringRef TOCSymbolAliasIdent
= "__TOC__";
32 constexpr uint64_t ELFTOCBaseOffset
= 0x8000;
33 constexpr StringRef ELFTLSInfoSectionName
= "$__TLSINFO";
35 template <llvm::endianness Endianness
>
36 class TLSInfoTableManager_ELF_ppc64
37 : public TableManager
<TLSInfoTableManager_ELF_ppc64
<Endianness
>> {
39 static const uint8_t TLSInfoEntryContent
[16];
41 static StringRef
getSectionName() { return ELFTLSInfoSectionName
; }
43 bool visitEdge(LinkGraph
&G
, Block
*B
, Edge
&E
) {
44 Edge::Kind K
= E
.getKind();
46 case ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16HA
:
47 E
.setKind(ppc64::TOCDelta16HA
);
48 E
.setTarget(this->getEntryForTarget(G
, E
.getTarget()));
50 case ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16LO
:
51 E
.setKind(ppc64::TOCDelta16LO
);
52 E
.setTarget(this->getEntryForTarget(G
, E
.getTarget()));
54 case ppc64::RequestTLSDescInGOTAndTransformToDelta34
:
55 E
.setKind(ppc64::Delta34
);
56 E
.setTarget(this->getEntryForTarget(G
, E
.getTarget()));
63 Symbol
&createEntry(LinkGraph
&G
, Symbol
&Target
) {
64 // The TLS Info entry's key value will be written by
65 // `fixTLVSectionsAndEdges`, so create mutable content.
66 auto &TLSInfoEntry
= G
.createMutableContentBlock(
67 getTLSInfoSection(G
), G
.allocateContent(getTLSInfoEntryContent()),
68 orc::ExecutorAddr(), 8, 0);
69 TLSInfoEntry
.addEdge(ppc64::Pointer64
, 8, Target
, 0);
70 return G
.addAnonymousSymbol(TLSInfoEntry
, 0, 16, false, false);
74 Section
&getTLSInfoSection(LinkGraph
&G
) {
77 &G
.createSection(ELFTLSInfoSectionName
, orc::MemProt::Read
);
81 ArrayRef
<char> getTLSInfoEntryContent() const {
82 return {reinterpret_cast<const char *>(TLSInfoEntryContent
),
83 sizeof(TLSInfoEntryContent
)};
86 Section
*TLSInfoTable
= nullptr;
90 const uint8_t TLSInfoTableManager_ELF_ppc64
<
91 llvm::endianness::little
>::TLSInfoEntryContent
[16] = {
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/
97 const uint8_t TLSInfoTableManager_ELF_ppc64
<
98 llvm::endianness::big
>::TLSInfoEntryContent
[16] = {
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/
103 template <llvm::endianness Endianness
>
104 Symbol
&createELFGOTHeader(LinkGraph
&G
,
105 ppc64::TOCTableManager
<Endianness
> &TOC
) {
106 Symbol
*TOCSymbol
= nullptr;
108 for (Symbol
*Sym
: G
.defined_symbols())
109 if (LLVM_UNLIKELY(Sym
->getName() == ELFTOCSymbolName
)) {
114 if (LLVM_LIKELY(TOCSymbol
== nullptr)) {
115 for (Symbol
*Sym
: G
.external_symbols())
116 if (Sym
->getName() == ELFTOCSymbolName
) {
123 TOCSymbol
= &G
.addExternalSymbol(ELFTOCSymbolName
, 0, false);
125 return TOC
.getEntryForTarget(G
, *TOCSymbol
);
128 // Register preexisting GOT entries with TOC table manager.
129 template <llvm::endianness Endianness
>
131 registerExistingGOTEntries(LinkGraph
&G
,
132 ppc64::TOCTableManager
<Endianness
> &TOC
) {
133 auto isGOTEntry
= [](const Edge
&E
) {
134 return E
.getKind() == ppc64::Pointer64
&& E
.getTarget().isExternal();
136 if (Section
*dotTOCSection
= G
.findSectionByName(".toc")) {
137 for (Block
*B
: dotTOCSection
->blocks())
138 for (Edge
&E
: B
->edges())
140 TOC
.registerPreExistingEntry(E
.getTarget(),
141 G
.addAnonymousSymbol(*B
, E
.getOffset(),
147 template <llvm::endianness Endianness
>
148 Error
buildTables_ELF_ppc64(LinkGraph
&G
) {
149 LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
150 ppc64::TOCTableManager
<Endianness
> TOC
;
151 // Before visiting edges, we create a header containing the address of TOC
152 // base as ELFABIv2 suggests:
153 // > The GOT consists of an 8-byte header that contains the TOC base (the
154 // first TOC base when multiple TOCs are present), followed by an array of
156 createELFGOTHeader(G
, TOC
);
158 // There might be compiler-generated GOT entries in ELF relocatable file.
159 registerExistingGOTEntries(G
, TOC
);
161 ppc64::PLTTableManager
<Endianness
> PLT(TOC
);
162 TLSInfoTableManager_ELF_ppc64
<Endianness
> TLSInfo
;
163 visitExistingEdges(G
, TOC
, PLT
, TLSInfo
);
165 // After visiting edges in LinkGraph, we have GOT entries built in the
166 // synthesized section.
167 // Merge sections included in TOC into synthesized TOC section,
168 // thus TOC is compact and reducing chances of relocation
170 if (Section
*TOCSection
= G
.findSectionByName(TOC
.getSectionName())) {
171 // .got and .plt are not normally present in a relocatable object file
172 // because they are linker generated.
173 if (Section
*gotSection
= G
.findSectionByName(".got"))
174 G
.mergeSections(*TOCSection
, *gotSection
);
175 if (Section
*tocSection
= G
.findSectionByName(".toc"))
176 G
.mergeSections(*TOCSection
, *tocSection
);
177 if (Section
*sdataSection
= G
.findSectionByName(".sdata"))
178 G
.mergeSections(*TOCSection
, *sdataSection
);
179 if (Section
*sbssSection
= G
.findSectionByName(".sbss"))
180 G
.mergeSections(*TOCSection
, *sbssSection
);
181 // .tocbss no longer appears in ELFABIv2. Leave it here to be compatible
183 if (Section
*tocbssSection
= G
.findSectionByName(".tocbss"))
184 G
.mergeSections(*TOCSection
, *tocbssSection
);
185 if (Section
*pltSection
= G
.findSectionByName(".plt"))
186 G
.mergeSections(*TOCSection
, *pltSection
);
189 return Error::success();
194 namespace llvm::jitlink
{
196 template <llvm::endianness Endianness
>
197 class ELFLinkGraphBuilder_ppc64
198 : public ELFLinkGraphBuilder
<object::ELFType
<Endianness
, true>> {
200 using ELFT
= object::ELFType
<Endianness
, true>;
201 using Base
= ELFLinkGraphBuilder
<ELFT
>;
203 using Base::G
; // Use LinkGraph pointer from base class.
205 Error
addRelocations() override
{
206 LLVM_DEBUG(dbgs() << "Processing relocations:\n");
208 using Self
= ELFLinkGraphBuilder_ppc64
<Endianness
>;
209 for (const auto &RelSect
: Base::Sections
) {
210 // Validate the section to read relocation entries from.
211 if (RelSect
.sh_type
== ELF::SHT_REL
)
212 return make_error
<StringError
>("No SHT_REL in valid " +
213 G
->getTargetTriple().getArchName() +
215 inconvertibleErrorCode());
217 if (Error Err
= Base::forEachRelaRelocation(RelSect
, this,
218 &Self::addSingleRelocation
))
222 return Error::success();
225 Error
addSingleRelocation(const typename
ELFT::Rela
&Rel
,
226 const typename
ELFT::Shdr
&FixupSection
,
228 using Base
= ELFLinkGraphBuilder
<ELFT
>;
229 auto ELFReloc
= Rel
.getType(false);
231 // R_PPC64_NONE is a no-op.
232 if (LLVM_UNLIKELY(ELFReloc
== ELF::R_PPC64_NONE
))
233 return Error::success();
235 // TLS model markers. We only support global-dynamic model now.
236 if (ELFReloc
== ELF::R_PPC64_TLSGD
)
237 return Error::success();
238 if (ELFReloc
== ELF::R_PPC64_TLSLD
)
239 return make_error
<StringError
>("Local-dynamic TLS model is not supported",
240 inconvertibleErrorCode());
242 if (ELFReloc
== ELF::R_PPC64_PCREL_OPT
)
243 // TODO: Support PCREL optimization, now ignore it.
244 return Error::success();
246 if (ELFReloc
== ELF::R_PPC64_TPREL34
)
247 return make_error
<StringError
>("Local-exec TLS model is not supported",
248 inconvertibleErrorCode());
250 auto ObjSymbol
= Base::Obj
.getRelocationSymbol(Rel
, Base::SymTabSec
);
252 return ObjSymbol
.takeError();
254 uint32_t SymbolIndex
= Rel
.getSymbol(false);
255 Symbol
*GraphSymbol
= Base::getGraphSymbol(SymbolIndex
);
257 return make_error
<StringError
>(
258 formatv("Could not find symbol at given index, did you add it to "
259 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
260 SymbolIndex
, (*ObjSymbol
)->st_shndx
,
261 Base::GraphSymbols
.size()),
262 inconvertibleErrorCode());
264 int64_t Addend
= Rel
.r_addend
;
265 orc::ExecutorAddr FixupAddress
=
266 orc::ExecutorAddr(FixupSection
.sh_addr
) + Rel
.r_offset
;
267 Edge::OffsetT Offset
= FixupAddress
- BlockToFix
.getAddress();
268 Edge::Kind Kind
= Edge::Invalid
;
272 return make_error
<JITLinkError
>(
273 "In " + G
->getName() + ": Unsupported ppc64 relocation type " +
274 object::getELFRelocationTypeName(ELF::EM_PPC64
, ELFReloc
));
275 case ELF::R_PPC64_ADDR64
:
276 Kind
= ppc64::Pointer64
;
278 case ELF::R_PPC64_ADDR32
:
279 Kind
= ppc64::Pointer32
;
281 case ELF::R_PPC64_ADDR16
:
282 Kind
= ppc64::Pointer16
;
284 case ELF::R_PPC64_ADDR16_DS
:
285 Kind
= ppc64::Pointer16DS
;
287 case ELF::R_PPC64_ADDR16_HA
:
288 Kind
= ppc64::Pointer16HA
;
290 case ELF::R_PPC64_ADDR16_HI
:
291 Kind
= ppc64::Pointer16HI
;
293 case ELF::R_PPC64_ADDR16_HIGH
:
294 Kind
= ppc64::Pointer16HIGH
;
296 case ELF::R_PPC64_ADDR16_HIGHA
:
297 Kind
= ppc64::Pointer16HIGHA
;
299 case ELF::R_PPC64_ADDR16_HIGHER
:
300 Kind
= ppc64::Pointer16HIGHER
;
302 case ELF::R_PPC64_ADDR16_HIGHERA
:
303 Kind
= ppc64::Pointer16HIGHERA
;
305 case ELF::R_PPC64_ADDR16_HIGHEST
:
306 Kind
= ppc64::Pointer16HIGHEST
;
308 case ELF::R_PPC64_ADDR16_HIGHESTA
:
309 Kind
= ppc64::Pointer16HIGHESTA
;
311 case ELF::R_PPC64_ADDR16_LO
:
312 Kind
= ppc64::Pointer16LO
;
314 case ELF::R_PPC64_ADDR16_LO_DS
:
315 Kind
= ppc64::Pointer16LODS
;
317 case ELF::R_PPC64_ADDR14
:
318 Kind
= ppc64::Pointer14
;
320 case ELF::R_PPC64_TOC
:
323 case ELF::R_PPC64_TOC16
:
324 Kind
= ppc64::TOCDelta16
;
326 case ELF::R_PPC64_TOC16_HA
:
327 Kind
= ppc64::TOCDelta16HA
;
329 case ELF::R_PPC64_TOC16_HI
:
330 Kind
= ppc64::TOCDelta16HI
;
332 case ELF::R_PPC64_TOC16_DS
:
333 Kind
= ppc64::TOCDelta16DS
;
335 case ELF::R_PPC64_TOC16_LO
:
336 Kind
= ppc64::TOCDelta16LO
;
338 case ELF::R_PPC64_TOC16_LO_DS
:
339 Kind
= ppc64::TOCDelta16LODS
;
341 case ELF::R_PPC64_REL16
:
342 Kind
= ppc64::Delta16
;
344 case ELF::R_PPC64_REL16_HA
:
345 Kind
= ppc64::Delta16HA
;
347 case ELF::R_PPC64_REL16_HI
:
348 Kind
= ppc64::Delta16HI
;
350 case ELF::R_PPC64_REL16_LO
:
351 Kind
= ppc64::Delta16LO
;
353 case ELF::R_PPC64_REL32
:
354 Kind
= ppc64::Delta32
;
356 case ELF::R_PPC64_REL24_NOTOC
:
357 Kind
= ppc64::RequestCallNoTOC
;
359 case ELF::R_PPC64_REL24
:
360 Kind
= ppc64::RequestCall
;
361 // Determining a target is external or not is deferred in PostPrunePass.
362 // We assume branching to local entry by default, since in PostPrunePass,
363 // we don't have any context to determine LocalEntryOffset. If it finally
364 // turns out to be an external call, we'll have a stub for the external
365 // target, the target of this edge will be the stub and its addend will be
367 Addend
+= ELF::decodePPC64LocalEntryOffset((*ObjSymbol
)->st_other
);
369 case ELF::R_PPC64_REL64
:
370 Kind
= ppc64::Delta64
;
372 case ELF::R_PPC64_PCREL34
:
373 Kind
= ppc64::Delta34
;
375 case ELF::R_PPC64_GOT_PCREL34
:
376 Kind
= ppc64::RequestGOTAndTransformToDelta34
;
378 case ELF::R_PPC64_GOT_TLSGD16_HA
:
379 Kind
= ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16HA
;
381 case ELF::R_PPC64_GOT_TLSGD16_LO
:
382 Kind
= ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16LO
;
384 case ELF::R_PPC64_GOT_TLSGD_PCREL34
:
385 Kind
= ppc64::RequestTLSDescInGOTAndTransformToDelta34
;
389 Edge
GE(Kind
, Offset
, *GraphSymbol
, Addend
);
390 BlockToFix
.addEdge(std::move(GE
));
391 return Error::success();
395 ELFLinkGraphBuilder_ppc64(StringRef FileName
,
396 const object::ELFFile
<ELFT
> &Obj
, Triple TT
,
397 SubtargetFeatures Features
)
398 : ELFLinkGraphBuilder
<ELFT
>(Obj
, std::move(TT
), std::move(Features
),
399 FileName
, ppc64::getEdgeKindName
) {}
402 template <llvm::endianness Endianness
>
403 class ELFJITLinker_ppc64
: public JITLinker
<ELFJITLinker_ppc64
<Endianness
>> {
404 using JITLinkerBase
= JITLinker
<ELFJITLinker_ppc64
<Endianness
>>;
405 friend JITLinkerBase
;
408 ELFJITLinker_ppc64(std::unique_ptr
<JITLinkContext
> Ctx
,
409 std::unique_ptr
<LinkGraph
> G
, PassConfiguration PassConfig
)
410 : JITLinkerBase(std::move(Ctx
), std::move(G
), std::move(PassConfig
)) {
411 JITLinkerBase::getPassConfig().PostAllocationPasses
.push_back(
412 [this](LinkGraph
&G
) { return defineTOCBase(G
); });
416 Symbol
*TOCSymbol
= nullptr;
418 Error
defineTOCBase(LinkGraph
&G
) {
419 for (Symbol
*Sym
: G
.defined_symbols()) {
420 if (LLVM_UNLIKELY(Sym
->getName() == ELFTOCSymbolName
)) {
422 return Error::success();
426 assert(TOCSymbol
== nullptr &&
427 "TOCSymbol should not be defined at this point");
429 for (Symbol
*Sym
: G
.external_symbols()) {
430 if (Sym
->getName() == ELFTOCSymbolName
) {
436 if (Section
*TOCSection
= G
.findSectionByName(
437 ppc64::TOCTableManager
<Endianness
>::getSectionName())) {
438 assert(!TOCSection
->empty() && "TOC section should have reserved an "
439 "entry for containing the TOC base");
441 SectionRange
SR(*TOCSection
);
442 orc::ExecutorAddr
TOCBaseAddr(SR
.getFirstBlock()->getAddress() +
444 assert(TOCSymbol
&& TOCSymbol
->isExternal() &&
445 ".TOC. should be a external symbol at this point");
446 G
.makeAbsolute(*TOCSymbol
, TOCBaseAddr
);
447 // Create an alias of .TOC. so that rtdyld checker can recognize.
448 G
.addAbsoluteSymbol(TOCSymbolAliasIdent
, TOCSymbol
->getAddress(),
449 TOCSymbol
->getSize(), TOCSymbol
->getLinkage(),
450 TOCSymbol
->getScope(), TOCSymbol
->isLive());
451 return Error::success();
454 // If TOC section doesn't exist, which means no TOC relocation is found, we
455 // don't need a TOCSymbol.
456 return Error::success();
459 Error
applyFixup(LinkGraph
&G
, Block
&B
, const Edge
&E
) const {
460 return ppc64::applyFixup
<Endianness
>(G
, B
, E
, TOCSymbol
);
464 template <llvm::endianness Endianness
>
465 Expected
<std::unique_ptr
<LinkGraph
>>
466 createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer
) {
468 dbgs() << "Building jitlink graph for new input "
469 << ObjectBuffer
.getBufferIdentifier() << "...\n";
472 auto ELFObj
= object::ObjectFile::createELFObjectFile(ObjectBuffer
);
474 return ELFObj
.takeError();
476 auto Features
= (*ELFObj
)->getFeatures();
478 return Features
.takeError();
480 using ELFT
= object::ELFType
<Endianness
, true>;
481 auto &ELFObjFile
= cast
<object::ELFObjectFile
<ELFT
>>(**ELFObj
);
482 return ELFLinkGraphBuilder_ppc64
<Endianness
>(
483 (*ELFObj
)->getFileName(), ELFObjFile
.getELFFile(),
484 (*ELFObj
)->makeTriple(), std::move(*Features
))
488 template <llvm::endianness Endianness
>
489 void link_ELF_ppc64(std::unique_ptr
<LinkGraph
> G
,
490 std::unique_ptr
<JITLinkContext
> Ctx
) {
491 PassConfiguration Config
;
493 if (Ctx
->shouldAddDefaultTargetPasses(G
->getTargetTriple())) {
494 // Construct a JITLinker and run the link function.
496 // Add eh-frame passes.
497 Config
.PrePrunePasses
.push_back(DWARFRecordSectionSplitter(".eh_frame"));
498 Config
.PrePrunePasses
.push_back(EHFrameEdgeFixer(
499 ".eh_frame", G
->getPointerSize(), ppc64::Pointer32
, ppc64::Pointer64
,
500 ppc64::Delta32
, ppc64::Delta64
, ppc64::NegDelta32
));
501 Config
.PrePrunePasses
.push_back(EHFrameNullTerminator(".eh_frame"));
503 // Add a mark-live pass.
504 if (auto MarkLive
= Ctx
->getMarkLivePass(G
->getTargetTriple()))
505 Config
.PrePrunePasses
.push_back(std::move(MarkLive
));
507 Config
.PrePrunePasses
.push_back(markAllSymbolsLive
);
510 Config
.PostPrunePasses
.push_back(buildTables_ELF_ppc64
<Endianness
>);
512 if (auto Err
= Ctx
->modifyPassConfig(*G
, Config
))
513 return Ctx
->notifyFailed(std::move(Err
));
515 ELFJITLinker_ppc64
<Endianness
>::link(std::move(Ctx
), std::move(G
),
519 Expected
<std::unique_ptr
<LinkGraph
>>
520 createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer
) {
521 return createLinkGraphFromELFObject_ppc64
<llvm::endianness::big
>(
522 std::move(ObjectBuffer
));
525 Expected
<std::unique_ptr
<LinkGraph
>>
526 createLinkGraphFromELFObject_ppc64le(MemoryBufferRef ObjectBuffer
) {
527 return createLinkGraphFromELFObject_ppc64
<llvm::endianness::little
>(
528 std::move(ObjectBuffer
));
531 /// jit-link the given object buffer, which must be a ELF ppc64 object file.
532 void link_ELF_ppc64(std::unique_ptr
<LinkGraph
> G
,
533 std::unique_ptr
<JITLinkContext
> Ctx
) {
534 return link_ELF_ppc64
<llvm::endianness::big
>(std::move(G
), std::move(Ctx
));
537 /// jit-link the given object buffer, which must be a ELF ppc64le object file.
538 void link_ELF_ppc64le(std::unique_ptr
<LinkGraph
> G
,
539 std::unique_ptr
<JITLinkContext
> Ctx
) {
540 return link_ELF_ppc64
<llvm::endianness::little
>(std::move(G
), std::move(Ctx
));
543 } // end namespace llvm::jitlink