#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();
}
template <typename RelocHandlerFunction>
Error forEachRelocation(const object::SectionRef &RelSec,
RelocHandlerFunction &&Func,
bool ProcessDebugSections = false);
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:
struct ComdatExportRequest {
COFFSymbolIndex SymbolIndex;
jitlink::Linkage Linkage;
};
std::vector<Optional<ComdatExportRequest>> PendingComdatExports;
struct WeakExternalRequest {
COFFSymbolIndex Alias;
COFFSymbolIndex Target;
uint32_t Characteristics;
StringRef SymbolName;
};
std::vector<WeakExternalRequest> WeakExternalRequests;
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;
DenseMap<StringRef, Symbol *> ExternalSymbols;
};
template <typename RelocHandlerFunction>
Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec,
RelocHandlerFunction &&Func,
bool ProcessDebugSections) {
auto COFFRelSect = Obj.getCOFFSection(RelSec);
Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);
if (!Name)
return Name.takeError();
LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);
if (!BlockToFix)
return make_error<StringError>(
"Referencing a section that wasn't added to the graph: " + *Name,
inconvertibleErrorCode());
for (const auto &R : RelSec.relocations())
if (Error Err = Func(R, RelSec, *BlockToFix))
return Err;
LLVM_DEBUG(dbgs() << "\n");
return Error::success();
}
} }
#endif