aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h')
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h199
1 files changed, 199 insertions, 0 deletions
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
new file mode 100644
index 000000000000..4dc1b14dc4a2
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
@@ -0,0 +1,199 @@
+//===----- COFFLinkGraphBuilder.h - COFF LinkGraph builder ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic COFF LinkGraph building code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
+#define LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/Object/COFF.h"
+
+#include "EHFrameSupportImpl.h"
+#include "JITLinkGeneric.h"
+
+#define DEBUG_TYPE "jitlink"
+
+#include <list>
+
+namespace llvm {
+namespace jitlink {
+
+class COFFLinkGraphBuilder {
+public:
+ virtual ~COFFLinkGraphBuilder();
+ Expected<std::unique_ptr<LinkGraph>> buildGraph();
+
+protected:
+ using COFFSectionIndex = int32_t;
+ using COFFSymbolIndex = int32_t;
+
+ COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT,
+ LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
+
+ LinkGraph &getGraph() const { return *G; }
+
+ const object::COFFObjectFile &getObject() const { return Obj; }
+
+ virtual Error addRelocations() = 0;
+
+ Error graphifySections();
+ Error graphifySymbols();
+
+ void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex,
+ Symbol &Sym) {
+ assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index");
+ GraphSymbols[SymIndex] = &Sym;
+ if (!COFF::isReservedSectionNumber(SecIndex))
+ SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym});
+ }
+
+ Symbol *getGraphSymbol(COFFSymbolIndex SymIndex) const {
+ if (SymIndex < 0 ||
+ SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size()))
+ return nullptr;
+ return GraphSymbols[SymIndex];
+ }
+
+ void setGraphBlock(COFFSectionIndex SecIndex, Block *B) {
+ assert(!GraphBlocks[SecIndex] && "Duplicate section at index");
+ assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index");
+ GraphBlocks[SecIndex] = B;
+ }
+
+ Block *getGraphBlock(COFFSectionIndex SecIndex) const {
+ if (SecIndex <= 0 ||
+ SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size()))
+ return nullptr;
+ return GraphBlocks[SecIndex];
+ }
+
+ object::COFFObjectFile::section_iterator_range sections() const {
+ return Obj.sections();
+ }
+
+ /// Traverse all matching relocation records in the given section. The handler
+ /// function Func should be callable with this signature:
+ /// Error(const object::RelocationRef&,
+ /// const object::SectionRef&, Section &)
+ ///
+ template <typename RelocHandlerFunction>
+ Error forEachRelocation(const object::SectionRef &RelSec,
+ RelocHandlerFunction &&Func,
+ bool ProcessDebugSections = false);
+
+ /// Traverse all matching relocation records in the given section. Convenience
+ /// wrapper to allow passing a member function for the handler.
+ ///
+ template <typename ClassT, typename RelocHandlerMethod>
+ Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance,
+ RelocHandlerMethod &&Method,
+ bool ProcessDebugSections = false) {
+ return forEachRelocation(
+ RelSec,
+ [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
+ return (Instance->*Method)(Rel, Target, GS);
+ },
+ ProcessDebugSections);
+ }
+
+private:
+ // Pending comdat symbol export that is initiated by the first symbol of
+ // COMDAT sequence.
+ struct ComdatExportRequest {
+ COFFSymbolIndex SymbolIndex;
+ COFFSectionIndex SectionIndex;
+ jitlink::Linkage Linkage;
+ };
+ Optional<ComdatExportRequest> PendingComdatExport;
+
+ // This represents a pending request to create a weak external symbol with a
+ // name.
+ struct WeakAliasRequest {
+ COFFSymbolIndex Alias;
+ COFFSymbolIndex Target;
+ StringRef SymbolName;
+ };
+ std::vector<WeakAliasRequest> WeakAliasRequests;
+
+ // Per COFF section jitlink symbol set sorted by offset.
+ // Used for calculating implicit size of defined symbols.
+ using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>;
+ std::vector<SymbolSet> SymbolSets;
+
+ Section &getCommonSection();
+
+ Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex,
+ StringRef SymbolName,
+ object::COFFSymbolRef Symbol,
+ const object::coff_section *Section);
+ Expected<Symbol *> createCOMDATExportRequest(
+ COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
+ const object::coff_aux_section_definition *Definition);
+ Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex,
+ StringRef SymbolName,
+ object::COFFSymbolRef Symbol);
+ Error flushWeakAliasRequests();
+ Error calculateImplicitSizeOfSymbols();
+
+ static uint64_t getSectionAddress(const object::COFFObjectFile &Obj,
+ const object::coff_section *Section);
+ static uint64_t getSectionSize(const object::COFFObjectFile &Obj,
+ const object::coff_section *Section);
+ static bool isComdatSection(const object::coff_section *Section);
+ static unsigned getPointerSize(const object::COFFObjectFile &Obj);
+ static support::endianness getEndianness(const object::COFFObjectFile &Obj);
+ StringRef getCOFFSectionName(COFFSectionIndex SectionIndex,
+ const object::coff_section *Sec,
+ object::COFFSymbolRef Sym);
+
+ const object::COFFObjectFile &Obj;
+ std::unique_ptr<LinkGraph> G;
+
+ Section *CommonSection = nullptr;
+ std::vector<Block *> GraphBlocks;
+ std::vector<Symbol *> GraphSymbols;
+};
+
+template <typename RelocHandlerFunction>
+Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec,
+ RelocHandlerFunction &&Func,
+ bool ProcessDebugSections) {
+
+ auto COFFRelSect = Obj.getCOFFSection(RelSec);
+
+ // Target sections have names in valid COFF object files.
+ Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);
+ if (!Name)
+ return Name.takeError();
+ LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
+
+ // Lookup the link-graph node corresponding to the target section name.
+ auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);
+ if (!BlockToFix)
+ return make_error<StringError>(
+ "Referencing a section that wasn't added to the graph: " + *Name,
+ inconvertibleErrorCode());
+
+ // Let the callee process relocation entries one by one.
+ for (const auto &R : RelSec.relocations())
+ if (Error Err = Func(R, RelSec, *BlockToFix))
+ return Err;
+
+ LLVM_DEBUG(dbgs() << "\n");
+ return Error::success();
+}
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H