23#define DEBUG_TYPE "jitlink"
30constexpr StringRef ELFTOCSymbolName =
".TOC.";
31constexpr StringRef TOCSymbolAliasIdent =
"__TOC__";
32constexpr uint64_t ELFTOCBaseOffset = 0x8000;
33constexpr StringRef ELFTLSInfoSectionName =
"$__TLSINFO";
35template <llvm::endianness Endianness>
36class TLSInfoTableManager_ELF_ppc64
37 :
public TableManager<TLSInfoTableManager_ELF_ppc64<Endianness>> {
39 static const uint8_t TLSInfoEntryContent[16];
66 auto &TLSInfoEntry =
G.createMutableContentBlock(
67 getTLSInfoSection(
G),
G.allocateContent(getTLSInfoEntryContent()),
70 return G.addAnonymousSymbol(TLSInfoEntry, 0, 16,
false,
false);
77 &
G.createSection(ELFTLSInfoSectionName, orc::MemProt::Read);
82 return {
reinterpret_cast<const char *
>(TLSInfoEntryContent),
83 sizeof(TLSInfoEntryContent)};
86 Section *TLSInfoTable =
nullptr;
90const uint8_t TLSInfoTableManager_ELF_ppc64<
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
97const uint8_t TLSInfoTableManager_ELF_ppc64<
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
103template <llvm::endianness Endianness>
106 Symbol *TOCSymbol =
nullptr;
123 TOCSymbol = &
G.addExternalSymbol(ELFTOCSymbolName, 0,
false);
125 return TOC.getEntryForTarget(
G, *TOCSymbol);
129template <llvm::endianness Endianness>
133 auto isGOTEntry = [](
const Edge &E) {
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(),
147template <llvm::endianness Endianness>
156 createELFGOTHeader(
G, TOC);
159 registerExistingGOTEntries(
G, TOC);
162 TLSInfoTableManager_ELF_ppc64<Endianness> TLSInfo;
170 if (
Section *TOCSection =
G.findSectionByName(TOC.getSectionName())) {
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);
183 if (
Section *tocbssSection =
G.findSectionByName(
".tocbss"))
184 G.mergeSections(*TOCSection, *tocbssSection);
185 if (
Section *pltSection =
G.findSectionByName(
".plt"))
186 G.mergeSections(*TOCSection, *pltSection);
196template <llvm::endianness Endianness>
205 Error addRelocations()
override {
212 return make_error<StringError>(
"No SHT_REL in valid " +
213 G->getTargetTriple().getArchName() +
218 &Self::addSingleRelocation))
229 auto ELFReloc = Rel.getType(
false);
236 if (ELFReloc == ELF::R_PPC64_TLSGD)
238 if (ELFReloc == ELF::R_PPC64_TLSLD)
239 return make_error<StringError>(
"Local-dynamic TLS model is not supported",
242 if (ELFReloc == ELF::R_PPC64_PCREL_OPT)
246 if (ELFReloc == ELF::R_PPC64_TPREL34)
247 return make_error<StringError>(
"Local-exec TLS model is not supported",
252 return ObjSymbol.takeError();
254 uint32_t SymbolIndex = Rel.getSymbol(
false);
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,
264 int64_t Addend = Rel.r_addend;
272 return make_error<JITLinkError>(
273 "In " +
G->getName() +
": Unsupported ppc64 relocation type " +
275 case ELF::R_PPC64_ADDR64:
278 case ELF::R_PPC64_ADDR32:
281 case ELF::R_PPC64_ADDR16:
284 case ELF::R_PPC64_ADDR16_DS:
287 case ELF::R_PPC64_ADDR16_HA:
290 case ELF::R_PPC64_ADDR16_HI:
293 case ELF::R_PPC64_ADDR16_HIGH:
296 case ELF::R_PPC64_ADDR16_HIGHA:
299 case ELF::R_PPC64_ADDR16_HIGHER:
302 case ELF::R_PPC64_ADDR16_HIGHERA:
305 case ELF::R_PPC64_ADDR16_HIGHEST:
308 case ELF::R_PPC64_ADDR16_HIGHESTA:
311 case ELF::R_PPC64_ADDR16_LO:
314 case ELF::R_PPC64_ADDR16_LO_DS:
317 case ELF::R_PPC64_ADDR14:
320 case ELF::R_PPC64_TOC:
323 case ELF::R_PPC64_TOC16:
326 case ELF::R_PPC64_TOC16_HA:
329 case ELF::R_PPC64_TOC16_HI:
332 case ELF::R_PPC64_TOC16_DS:
335 case ELF::R_PPC64_TOC16_LO:
338 case ELF::R_PPC64_TOC16_LO_DS:
341 case ELF::R_PPC64_REL16:
344 case ELF::R_PPC64_REL16_HA:
347 case ELF::R_PPC64_REL16_HI:
350 case ELF::R_PPC64_REL16_LO:
353 case ELF::R_PPC64_REL32:
356 case ELF::R_PPC64_REL24_NOTOC:
359 case ELF::R_PPC64_REL24:
369 case ELF::R_PPC64_REL64:
372 case ELF::R_PPC64_PCREL34:
375 case ELF::R_PPC64_GOT_PCREL34:
378 case ELF::R_PPC64_GOT_TLSGD16_HA:
381 case ELF::R_PPC64_GOT_TLSGD16_LO:
384 case ELF::R_PPC64_GOT_TLSGD_PCREL34:
390 BlockToFix.
addEdge(std::move(GE));
399 FileName, ppc64::getEdgeKindName) {}
402template <llvm::endianness Endianness>
412 [
this](
LinkGraph &
G) {
return defineTOCBase(
G); });
416 Symbol *TOCSymbol =
nullptr;
426 assert(TOCSymbol ==
nullptr &&
427 "TOCSymbol should not be defined at this point");
436 if (
Section *TOCSection =
G.findSectionByName(
438 assert(!TOCSection->empty() &&
"TOC section should have reserved an "
439 "entry for containing the TOC base");
445 ".TOC. should be a external symbol at this point");
446 G.makeAbsolute(*TOCSymbol, TOCBaseAddr);
448 G.addAbsoluteSymbol(TOCSymbolAliasIdent, TOCSymbol->
getAddress(),
460 return ppc64::applyFixup<Endianness>(G,
B, E, TOCSymbol);
464template <llvm::endianness Endianness>
468 dbgs() <<
"Building jitlink graph for new input "
474 return ELFObj.takeError();
476 auto Features = (*ELFObj)->getFeatures();
478 return Features.takeError();
481 auto &ELFObjFile = cast<object::ELFObjectFile<ELFT>>(**ELFObj);
483 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
484 (*ELFObj)->makeTriple(), std::move(*Features))
488template <llvm::endianness Endianness>
490 std::unique_ptr<JITLinkContext> Ctx) {
493 if (Ctx->shouldAddDefaultTargetPasses(
G->getTargetTriple())) {
504 if (
auto MarkLive = Ctx->getMarkLivePass(
G->getTargetTriple()))
505 Config.PrePrunePasses.push_back(std::move(MarkLive));
510 Config.PostPrunePasses.push_back(buildTables_ELF_ppc64<Endianness>);
512 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
513 return Ctx->notifyFailed(std::move(Err));
521 return createLinkGraphFromELFObject_ppc64<llvm::endianness::big>(
522 std::move(ObjectBuffer));
527 return createLinkGraphFromELFObject_ppc64<llvm::endianness::little>(
528 std::move(ObjectBuffer));
533 std::unique_ptr<JITLinkContext> Ctx) {
534 return link_ELF_ppc64<llvm::endianness::big>(std::move(
G), std::move(Ctx));
539 std::unique_ptr<JITLinkContext> Ctx) {
540 return link_ELF_ppc64<llvm::endianness::little>(std::move(
G), std::move(Ctx));
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
StringRef getBufferIdentifier() const
StringRef - Represent a constant reference to a string, i.e.
Manages the enabling and disabling of subtarget specific features.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
orc::ExecutorAddr getAddress() const
An Addressable with content and edges.
void addEdge(Edge::Kind K, Edge::OffsetT Offset, Symbol &Target, Edge::AddendT Addend)
Add an edge to this block.
A LinkGraph pass that splits blocks in a section that follows the DWARF Record format into sub-blocks...
A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA edges.
ELFJITLinker_ppc64(std::unique_ptr< JITLinkContext > Ctx, std::unique_ptr< LinkGraph > G, PassConfiguration PassConfig)
std::unique_ptr< LinkGraph > G
ELFLinkGraphBuilder_ppc64(StringRef FileName, const object::ELFFile< ELFT > &Obj, Triple TT, SubtargetFeatures Features)
LinkGraph building code that's specific to the given ELFT, but common across all architectures.
const ELFFile::Elf_Shdr * SymTabSec
Expected< std::unique_ptr< LinkGraph > > buildGraph()
Attempt to construct and return the LinkGraph.
DenseMap< ELFSymbolIndex, Symbol * > GraphSymbols
ELFFile::Elf_Shdr_Range Sections
Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect, RelocHandlerMethod &&Func)
Traverse all matching ELFT::Rela relocation records in the given section.
Symbol * getGraphSymbol(ELFSymbolIndex SymIndex)
Represents fixups and constraints in the LinkGraph.
Symbol & getTarget() const
void setTarget(Symbol &Target)
PassConfiguration & getPassConfig()
static void link(ArgTs &&... Args)
Link constructs a LinkerImpl instance and calls linkPhase1.
Represents a section address range via a pair of Block pointers to the first and last Blocks in the s...
Represents an object file section.
bool isExternal() const
Returns true if the underlying addressable is an unresolved external.
bool isLive() const
Returns true if this symbol is live (i.e.
StringRef getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
Scope getScope() const
Get the visibility for this Symbol.
Linkage getLinkage() const
Get the linkage for this Symbol.
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
orc::ExecutorAddrDiff getSize() const
Returns the size of this symbol.
A CRTP base for tables that are built on demand, e.g.
Symbol & getEntryForTarget(LinkGraph &G, Symbol &Target)
Return the constructed entry.
Expected< const Elf_Sym * > getRelocationSymbol(const Elf_Rel &Rel, const Elf_Shdr *SymTab) const
Get the symbol for a given relocation.
static Expected< std::unique_ptr< ObjectFile > > createELFObjectFile(MemoryBufferRef Object, bool InitContent=true)
Represents an address in the executor process.
static int64_t decodePPC64LocalEntryOffset(unsigned Other)
static constexpr const StringLiteral & getSectionName(DebugSectionKind SectionKind)
Return the name of the section.
@ RequestTLSDescInGOTAndTransformToTOCDelta16HA
@ RequestGOTAndTransformToDelta34
@ RequestTLSDescInGOTAndTransformToTOCDelta16LO
@ RequestTLSDescInGOTAndTransformToDelta34
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject_ppc64le(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from an ELF/ppc64le relocatable object.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from an ELF/ppc64 relocatable object.
void visitExistingEdges(LinkGraph &G, VisitorTs &&...Vs)
For each edge in the given graph, apply a list of visitors to the edge, stopping when the first visit...
void link_ELF_ppc64le(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
jit-link the given object buffer, which must be a ELF ppc64le object file.
Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
void link_ELF_ppc64(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
jit-link the given object buffer, which must be a ELF ppc64le object file.
void visitEdge(LinkGraph &G, Block *B, Edge &E)
Base case for edge-visitors where the visitor-list is empty.
StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
This is an optimization pass for GlobalISel generic memory operations.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
LinkGraphPassList PostAllocationPasses
Post-allocation passes.