diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp index ee219724ee469..a7118eb9b563f 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp @@ -344,6 +344,9 @@ void jitLink_ELF_x86_64(std::unique_ptr Ctx) { else Config.PrePrunePasses.push_back(markAllSymbolsLive); + if (auto Err = Ctx->modifyPassConfig(TT, Config)) + return Ctx->notifyFailed(std::move(Err)); + ELFJITLinker_x86_64::link(std::move(Ctx), std::move(Config)); } diff --git a/llvm/tools/llvm-jitlink/CMakeLists.txt b/llvm/tools/llvm-jitlink/CMakeLists.txt index 5e022f1d2a576..bfe691d976ba7 100644 --- a/llvm/tools/llvm-jitlink/CMakeLists.txt +++ b/llvm/tools/llvm-jitlink/CMakeLists.txt @@ -14,6 +14,7 @@ set(LLVM_LINK_COMPONENTS add_llvm_tool(llvm-jitlink llvm-jitlink.cpp + llvm-jitlink-elf.cpp llvm-jitlink-macho.cpp ) diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp new file mode 100644 index 0000000000000..1b74f1016ae99 --- /dev/null +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp @@ -0,0 +1,100 @@ +//===---- llvm-jitlink-elf.cpp -- ELF parsing support for llvm-jitlink ----===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// ELF parsing support for llvm-jitlink. +// +//===----------------------------------------------------------------------===// + +#include "llvm-jitlink.h" + +#include "llvm/Support/Error.h" +#include "llvm/Support/Path.h" + +#define DEBUG_TYPE "llvm_jitlink" + +using namespace llvm; +using namespace llvm::jitlink; + +namespace llvm { + +Error registerELFGraphInfo(Session &S, LinkGraph &G) { + auto FileName = sys::path::filename(G.getName()); + if (S.FileInfos.count(FileName)) { + return make_error("When -check is passed, file names must be " + "distinct (duplicate: \"" + + FileName + "\")", + inconvertibleErrorCode()); + } + + auto &FileInfo = S.FileInfos[FileName]; + LLVM_DEBUG({ + dbgs() << "Registering ELF file info for \"" << FileName << "\"\n"; + }); + for (auto &Sec : G.sections()) { + LLVM_DEBUG({ + dbgs() << " Section \"" << Sec.getName() << "\": " + << (llvm::empty(Sec.symbols()) ? "empty. skipping." + : "processing...") + << "\n"; + }); + + // Skip empty sections. + if (llvm::empty(Sec.symbols())) + continue; + + if (FileInfo.SectionInfos.count(Sec.getName())) + return make_error("Encountered duplicate section name \"" + + Sec.getName() + "\" in \"" + FileName + + "\"", + inconvertibleErrorCode()); + + bool SectionContainsContent = false; + bool SectionContainsZeroFill = false; + + auto *FirstSym = *Sec.symbols().begin(); + auto *LastSym = FirstSym; + for (auto *Sym : Sec.symbols()) { + if (Sym->getAddress() < FirstSym->getAddress()) + FirstSym = Sym; + if (Sym->getAddress() > LastSym->getAddress()) + LastSym = Sym; + + if (Sym->hasName()) { + dbgs() << "Symbol: " << Sym->getName() << "\n"; + if (Sym->isSymbolZeroFill()) { + S.SymbolInfos[Sym->getName()] = {Sym->getSize(), Sym->getAddress()}; + SectionContainsZeroFill = true; + } else { + S.SymbolInfos[Sym->getName()] = {Sym->getSymbolContent(), + Sym->getAddress()}; + SectionContainsContent = true; + } + } + } + + JITTargetAddress SecAddr = FirstSym->getAddress(); + uint64_t SecSize = + (LastSym->getBlock().getAddress() + LastSym->getBlock().getSize()) - + SecAddr; + + if (SectionContainsZeroFill && SectionContainsContent) + return make_error("Mixed zero-fill and content sections not " + "supported yet", + inconvertibleErrorCode()); + if (SectionContainsZeroFill) + FileInfo.SectionInfos[Sec.getName()] = {SecSize, SecAddr}; + else + FileInfo.SectionInfos[Sec.getName()] = { + StringRef(FirstSym->getBlock().getContent().data(), SecSize), + SecAddr}; + } + + return Error::success(); +} + +} // end namespace llvm diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp index d68c9e6952836..18584e55d0f5c 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp @@ -74,7 +74,7 @@ static Expected getMachOStubTarget(LinkGraph &G, Block &B) { namespace llvm { -Error registerMachOStubsAndGOT(Session &S, LinkGraph &G) { +Error registerMachOGraphInfo(Session &S, LinkGraph &G) { auto FileName = sys::path::filename(G.getName()); if (S.FileInfos.count(FileName)) { return make_error("When -check is passed, file names must be " diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp index 961cd77c0ecbd..b44a56e0ac925 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp @@ -467,8 +467,13 @@ void Session::modifyPassConfig(const Triple &FTT, PassConfiguration &PassConfig) { if (!CheckFiles.empty()) PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) { + + if (TT.getObjectFormat() == Triple::ELF) + return registerELFGraphInfo(*this, G); + if (TT.getObjectFormat() == Triple::MachO) - return registerMachOStubsAndGOT(*this, G); + return registerMachOGraphInfo(*this, G); + return make_error("Unsupported object format for GOT/stub " "registration", inconvertibleErrorCode()); diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.h b/llvm/tools/llvm-jitlink/llvm-jitlink.h index c888baec9adf4..5884e164a44d1 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.h +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.h @@ -69,7 +69,11 @@ struct Session { Session(Triple TT, Error &Err); }; -Error registerMachOStubsAndGOT(Session &S, jitlink::LinkGraph &G); +/// Record symbols, GOT entries, stubs, and sections for ELF file. +Error registerELFGraphInfo(Session &S, jitlink::LinkGraph &G); + +/// Record symbols, GOT entries, stubs, and sections for MachO file. +Error registerMachOGraphInfo(Session &S, jitlink::LinkGraph &G); } // end namespace llvm