24#define DEBUG_TYPE "jitlink"
31constexpr StringRef ELFTOCSymbolName =
".TOC.";
32constexpr StringRef TOCSymbolAliasIdent =
"__TOC__";
33constexpr uint64_t ELFTOCBaseOffset = 0x8000;
34constexpr StringRef ELFTLSInfoSectionName =
"$__TLSINFO";
36template <support::endianness Endianness>
37class TLSInfoTableManager_ELF_ppc64
38 :
public TableManager<TLSInfoTableManager_ELF_ppc64<Endianness>> {
40 static const uint8_t TLSInfoEntryContent[16];
42 static StringRef getSectionName() {
return ELFTLSInfoSectionName; }
62 auto &TLSInfoEntry =
G.createMutableContentBlock(
63 getTLSInfoSection(
G),
G.allocateContent(getTLSInfoEntryContent()),
66 return G.addAnonymousSymbol(TLSInfoEntry, 0, 16,
false,
false);
73 &
G.createSection(ELFTLSInfoSectionName, orc::MemProt::Read);
78 return {
reinterpret_cast<const char *
>(TLSInfoEntryContent),
79 sizeof(TLSInfoEntryContent)};
82 Section *TLSInfoTable =
nullptr;
86const uint8_t TLSInfoTableManager_ELF_ppc64<
87 support::endianness::little>::TLSInfoEntryContent[16] = {
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
93const uint8_t TLSInfoTableManager_ELF_ppc64<
94 support::endianness::big>::TLSInfoEntryContent[16] = {
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
99template <support::endianness Endianness>
102 Symbol *TOCSymbol =
nullptr;
119 TOCSymbol = &
G.addExternalSymbol(ELFTOCSymbolName, 0,
false);
121 return TOC.getEntryForTarget(
G, *TOCSymbol);
125template <support::endianness Endianness>
129 auto isGOTEntry = [](
const Edge &
E) {
132 if (
Section *dotTOCSection =
G.findSectionByName(
".toc")) {
133 for (
Block *
B : dotTOCSection->blocks())
134 for (
Edge &
E :
B->edges())
136 TOC.registerPreExistingEntry(
E.getTarget(),
137 G.addAnonymousSymbol(*
B,
E.getOffset(),
143template <support::endianness Endianness>
152 createELFGOTHeader(
G, TOC);
155 registerExistingGOTEntries(
G, TOC);
158 TLSInfoTableManager_ELF_ppc64<Endianness> TLSInfo;
166 if (
Section *TOCSection =
G.findSectionByName(TOC.getSectionName())) {
169 if (
Section *gotSection =
G.findSectionByName(
".got"))
170 G.mergeSections(*TOCSection, *gotSection);
171 if (
Section *tocSection =
G.findSectionByName(
".toc"))
172 G.mergeSections(*TOCSection, *tocSection);
173 if (
Section *sdataSection =
G.findSectionByName(
".sdata"))
174 G.mergeSections(*TOCSection, *sdataSection);
175 if (
Section *sbssSection =
G.findSectionByName(
".sbss"))
176 G.mergeSections(*TOCSection, *sbssSection);
179 if (
Section *tocbssSection =
G.findSectionByName(
".tocbss"))
180 G.mergeSections(*TOCSection, *tocbssSection);
181 if (
Section *pltSection =
G.findSectionByName(
".plt"))
182 G.mergeSections(*TOCSection, *pltSection);
192template <support::endianness Endianness>
201 Error addRelocations()
override {
208 return make_error<StringError>(
"No SHT_REL in valid " +
209 G->getTargetTriple().getArchName() +
214 &Self::addSingleRelocation))
225 auto ELFReloc = Rel.getType(
false);
232 if (ELFReloc == ELF::R_PPC64_TLSGD)
234 if (ELFReloc == ELF::R_PPC64_TLSLD)
235 return make_error<StringError>(
"Local-dynamic TLS model is not supported",
240 return ObjSymbol.takeError();
242 uint32_t SymbolIndex = Rel.getSymbol(
false);
245 return make_error<StringError>(
246 formatv(
"Could not find symbol at given index, did you add it to "
247 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
248 SymbolIndex, (*ObjSymbol)->st_shndx,
252 int64_t Addend = Rel.r_addend;
260 return make_error<JITLinkError>(
261 "In " +
G->getName() +
": Unsupported ppc64 relocation type " +
263 case ELF::R_PPC64_ADDR64:
266 case ELF::R_PPC64_ADDR32:
269 case ELF::R_PPC64_ADDR16:
272 case ELF::R_PPC64_ADDR16_DS:
275 case ELF::R_PPC64_ADDR16_HA:
278 case ELF::R_PPC64_ADDR16_HI:
281 case ELF::R_PPC64_ADDR16_HIGH:
284 case ELF::R_PPC64_ADDR16_HIGHA:
287 case ELF::R_PPC64_ADDR16_HIGHER:
290 case ELF::R_PPC64_ADDR16_HIGHERA:
293 case ELF::R_PPC64_ADDR16_HIGHEST:
296 case ELF::R_PPC64_ADDR16_HIGHESTA:
299 case ELF::R_PPC64_ADDR16_LO:
302 case ELF::R_PPC64_ADDR16_LO_DS:
305 case ELF::R_PPC64_ADDR14:
308 case ELF::R_PPC64_TOC:
311 case ELF::R_PPC64_TOC16:
314 case ELF::R_PPC64_TOC16_HA:
317 case ELF::R_PPC64_TOC16_HI:
320 case ELF::R_PPC64_TOC16_DS:
323 case ELF::R_PPC64_TOC16_LO:
326 case ELF::R_PPC64_TOC16_LO_DS:
329 case ELF::R_PPC64_REL16:
332 case ELF::R_PPC64_REL16_HA:
335 case ELF::R_PPC64_REL16_HI:
338 case ELF::R_PPC64_REL16_LO:
341 case ELF::R_PPC64_REL32:
344 case ELF::R_PPC64_REL24_NOTOC:
347 case ELF::R_PPC64_REL24:
357 case ELF::R_PPC64_REL64:
360 case ELF::R_PPC64_PCREL34:
363 case ELF::R_PPC64_GOT_TLSGD16_HA:
366 case ELF::R_PPC64_GOT_TLSGD16_LO:
372 BlockToFix.
addEdge(std::move(GE));
381 FileName, ppc64::getEdgeKindName) {}
384template <support::endianness Endianness>
394 [
this](
LinkGraph &
G) {
return defineTOCBase(
G); });
398 Symbol *TOCSymbol =
nullptr;
408 assert(TOCSymbol ==
nullptr &&
409 "TOCSymbol should not be defined at this point");
418 if (
Section *TOCSection =
G.findSectionByName(
420 assert(!TOCSection->empty() &&
"TOC section should have reserved an "
421 "entry for containing the TOC base");
427 ".TOC. should be a external symbol at this point");
428 G.makeAbsolute(*TOCSymbol, TOCBaseAddr);
430 G.addAbsoluteSymbol(TOCSymbolAliasIdent, TOCSymbol->
getAddress(),
442 return ppc64::applyFixup<Endianness>(G,
B,
E, TOCSymbol);
446template <support::endianness Endianness>
450 dbgs() <<
"Building jitlink graph for new input "
456 return ELFObj.takeError();
458 auto Features = (*ELFObj)->getFeatures();
460 return Features.takeError();
463 auto &ELFObjFile = cast<object::ELFObjectFile<ELFT>>(**ELFObj);
465 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
466 (*ELFObj)->makeTriple(), std::move(*Features))
470template <support::endianness Endianness>
472 std::unique_ptr<JITLinkContext> Ctx) {
475 if (Ctx->shouldAddDefaultTargetPasses(
G->getTargetTriple())) {
486 if (
auto MarkLive = Ctx->getMarkLivePass(
G->getTargetTriple()))
487 Config.PrePrunePasses.push_back(std::move(MarkLive));
492 Config.PostPrunePasses.push_back(buildTables_ELF_ppc64<Endianness>);
494 if (
auto Err = Ctx->modifyPassConfig(*
G,
Config))
495 return Ctx->notifyFailed(std::move(Err));
503 return createLinkGraphFromELFObject_ppc64<support::big>(
504 std::move(ObjectBuffer));
509 return createLinkGraphFromELFObject_ppc64<support::little>(
510 std::move(ObjectBuffer));
515 std::unique_ptr<JITLinkContext> Ctx) {
516 return link_ELF_ppc64<support::big>(std::move(
G), std::move(Ctx));
521 std::unique_ptr<JITLinkContext> Ctx) {
522 return link_ELF_ppc64<support::little>(std::move(
G), std::move(Ctx));
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-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.
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)
@ RequestTLSDescInGOTAndTransformToTOCDelta16HA
@ RequestTLSDescInGOTAndTransformToTOCDelta16LO
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.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
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.