22#define DEBUG_TYPE "orc" 
   32class MachODebugObjectSynthesizerBase
 
   40      : 
G(
G), RegisterActionAddr(RegisterActionAddr) {}
 
   41  ~MachODebugObjectSynthesizerBase() 
override = 
default;
 
   46        dbgs() << 
"MachODebugObjectSynthesizer skipping graph " << 
G.getName()
 
   47               << 
" which contains an unexpected existing " 
   54      dbgs() << 
"MachODebugObjectSynthesizer visiting graph " << 
G.getName()
 
   57    for (
auto &Sec : 
G.sections()) {
 
   64        dbgs() << 
"  Preserving debug section " << Sec.
getName() << 
"\n";
 
   67      for (
auto *Sym : Sec.
symbols()) {
 
   68        bool NewPreservedBlock =
 
   69            PreservedBlocks.insert(&Sym->getBlock()).second;
 
   70        if (NewPreservedBlock)
 
   74        if (!PreservedBlocks.count(
B))
 
   75          G.addAnonymousSymbol(*
B, 0, 0, 
false, 
true);
 
   86template <
typename MachOTraits>
 
   87class MachODebugObjectSynthesizer : 
public MachODebugObjectSynthesizerBase {
 
   91      : MachODebugObjectSynthesizerBase(
G, RegisterActionAddr),
 
   94  using MachODebugObjectSynthesizerBase::MachODebugObjectSynthesizerBase;
 
   96  Error startSynthesis()
 override {
 
  102    for (
auto &Sec : 
G.sections()) {
 
  103      if (Sec.blocks().empty())
 
  107      if (Sec.getName().empty() || Sec.getName().size() > 33 ||
 
  108          Sec.getName().find(
',') > 16)
 
  112        DebugSections.push_back({&Sec, 
nullptr});
 
  114        NonDebugSections.push_back({&Sec, 
nullptr});
 
  118    if (DebugSections.empty())
 
  124      Builder.Header.cputype = *CPUType;
 
  126      return CPUType.takeError();
 
  128      Builder.Header.cpusubtype = *CPUSubType;
 
  130      return CPUSubType.takeError();
 
  132    Seg = &Builder.addSegment(
"");
 
  136    for (
auto &DSec : DebugSections) {
 
  137      auto [SegName, SecName] = DSec.GraphSec->getName().split(
',');
 
  138      DSec.BuilderSec = &Seg->addSection(SecName, SegName);
 
  141      DSec.BuilderSec->Content.Size = SR.
getSize();
 
  146        DebugSectionMap[SecName.drop_front(2)] = 
 
  148        if (SecName == 
"__debug_line")
 
  149          DebugLineSectionData = SectionData;
 
  153    std::optional<StringRef> FileName;
 
  154    if (!DebugLineSectionData.
empty()) {
 
  157             "G.getEndianness() must be either big or little");
 
  171            dbgs() << 
"Cannot parse line table for \"" << 
G.getName() << 
"\": ";
 
  177        for (
auto &FN : 
P.FileNames)
 
  180              dbgs() << 
"Using FileName = \"" << *FileName
 
  181                     << 
"\" from DWARF line table\n";
 
  192        dbgs() << 
"Could not find source name from DWARF line table. " 
  193                  "Using FileName = \"\"\n";
 
  199    Builder.addSymbol(*FileName, 
MachO::N_SO, 0, 0, 0);
 
  200    auto TimeStamp = std::chrono::duration_cast<std::chrono::seconds>(
 
  201                         std::chrono::system_clock::now().time_since_epoch())
 
  205    for (
auto &NDSP : NonDebugSections) {
 
  206      auto [SegName, SecName] = NDSP.GraphSec->getName().split(
',');
 
  207      NDSP.BuilderSec = &Seg->addSection(SecName, SegName);
 
  213      for (
auto *Sym : NDSP.GraphSec->symbols()) {
 
  221        StabSymbols.push_back(
 
  222            {*Sym, Builder.addSymbol(*Sym->getName(), SymType, 1, 0, 0),
 
  223             Builder.addSymbol(*Sym->getName(), SymType, 0, 0, 0)});
 
  231    size_t DebugObjectSize = Builder.layout();
 
  234    MachOContainerBlock = &
G.createMutableContentBlock(
 
  240  Error completeSynthesisAndRegister()
 override {
 
  241    if (!MachOContainerBlock) {
 
  243        dbgs() << 
"Not writing MachO debug object header for " << 
G.getName()
 
  244               << 
" since createDebugSection failed\n";
 
  250    for (
auto &NDSec : NonDebugSections) {
 
  253      NDSec.BuilderSec->size = SR.
getSize();
 
  255      if (SR.
getEnd() > MaxAddr)
 
  259    for (
auto &DSec : DebugSections) {
 
  260      if (DSec.GraphSec->blocks_size() != 1)
 
  262            "Unexpected number of blocks in debug info section",
 
  265      if (
ExecutorAddr(DSec.BuilderSec->addr) + DSec.BuilderSec->size > MaxAddr)
 
  266        MaxAddr = 
ExecutorAddr(DSec.BuilderSec->addr) + DSec.BuilderSec->size;
 
  268      auto &
B = **DSec.GraphSec->blocks().begin();
 
  269      DSec.BuilderSec->Content.Data = 
B.getContent().data();
 
  270      DSec.BuilderSec->Content.Size = 
B.getContent().size();
 
  275      dbgs() << 
"Writing MachO debug object header for " << 
G.getName() << 
"\n";
 
  279    for (
auto &SS : StabSymbols) {
 
  280      SS.StartStab.nlist().n_value = SS.Sym.getAddress().getValue();
 
  281      SS.EndStab.nlist().n_value = SS.Sym.getSize();
 
  284    Builder.write(MachOContainerBlock->getAlreadyMutableContent());
 
  286    static constexpr bool AutoRegisterCode = 
true;
 
  288    G.allocActions().push_back(
 
  291             RegisterActionAddr, R.getRange(), AutoRegisterCode)),
 
  303  struct StabSymbolsEntry {
 
  306    StabSymbolsEntry(
Symbol &Sym, RelocTarget StartStab, RelocTarget EndStab)
 
  307        : Sym(Sym), StartStab(StartStab), EndStab(EndStab) {}
 
  310    RelocTarget StartStab, EndStab;
 
  315  Block *MachOContainerBlock = 
nullptr;
 
  318  std::vector<StabSymbolsEntry> StabSymbols;
 
  328Expected<std::unique_ptr<GDBJITDebugInfoRegistrationPlugin>>
 
  332  auto RegisterActionAddr =
 
  333      TT.isOSBinFormatMachO()
 
  334          ? ES.
intern(
"_llvm_orc_registerJITLoaderGDBAllocAction")
 
  335          : ES.
intern(
"llvm_orc_registerJITLoaderGDBAllocAction");
 
  337  if (
auto RegisterSym = ES.
lookup({&ProcessJD}, RegisterActionAddr))
 
  338    return std::make_unique<GDBJITDebugInfoRegistrationPlugin>(
 
  339        RegisterSym->getAddress());
 
  341    return RegisterSym.takeError();
 
 
  362    modifyPassConfigForMachO(MR, LG, PassConfig);
 
  365      dbgs() << 
"GDBJITDebugInfoRegistrationPlugin skipping unspported graph " 
 
  372void GDBJITDebugInfoRegistrationPlugin::modifyPassConfigForMachO(
 
  382           "Graph has incorrect endianness");
 
  387      dbgs() << 
"GDBJITDebugInfoRegistrationPlugin skipping unsupported " 
  388             << 
"MachO graph " << LG.
getName()
 
  390             << 
", pointer size = " << LG.
getPointerSize() << 
", endianness = " 
  400    if (MachODebugObjectSynthesizerBase::isDebugSection(Sec)) {
 
  407      dbgs() << 
"GDBJITDebugInfoRegistrationPlugin: Graph " << LG.
getName()
 
  408             << 
" contains debug info. Installing debugger support passes.\n";
 
  411    auto MDOS = std::make_shared<MachODebugObjectSynthesizer<MachO64LE>>(
 
  414        [=](LinkGraph &
G) { 
return MDOS->preserveDebugSections(); });
 
  416        [=](LinkGraph &
G) { 
return MDOS->startSynthesis(); });
 
  418        [=](LinkGraph &
G) { 
return MDOS->completeSynthesisAndRegister(); });
 
  421      dbgs() << 
"GDBJITDebugInfoRegistrationPlugin: Graph " << LG.
getName()
 
  422             << 
" contains no debug info. Skipping.\n";
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
 
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
 
static const char * SynthDebugSectionName
 
static bool isDebugSection(const SectionBase &Sec)
 
This file defines the SmallVector class.
 
static std::unique_ptr< DWARFContext > create(const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction=ProcessDebugRelocations::Process, const LoadedObjectInfo *L=nullptr, std::string DWPName="", std::function< void(Error)> RecoverableErrorHandler=WithColor::defaultErrorHandler, std::function< void(Error)> WarningHandler=WithColor::defaultWarningHandler, bool ThreadSafe=false)
 
Base class for error info classes.
 
virtual void log(raw_ostream &OS) const =0
Print an error message to an output stream.
 
Lightweight error class with error context and mandatory checking.
 
static ErrorSuccess success()
Create a success value.
 
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
 
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
 
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
 
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
 
StringRef - Represent a constant reference to a string, i.e.
 
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
 
constexpr bool empty() const
empty - Check if the string is empty.
 
size_t count(char C) const
Return the number of occurrences of C in the string.
 
Triple - Helper class for working with autoconf configuration names.
 
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
 
ArchType getArch() const
Get the parsed architecture type of this triple.
 
const std::string & str() const
 
An Addressable with content and edges.
 
ArrayRef< char > getContent() const
Get the content for this block. Block must not be a zero-fill block.
 
uint64_t getAlignment() const
Get the alignment for this content.
 
size_t getSize() const
Returns the size of this defined addressable.
 
const std::string & getName() const
Returns the name of this graph (usually the name of the original underlying MemoryBuffer).
 
unsigned getPointerSize() const
Returns the pointer size for use in this graph.
 
iterator_range< section_iterator > sections()
 
const Triple & getTargetTriple() const
Returns the target triple for this Graph.
 
llvm::endianness getEndianness() const
Returns the endianness of content in this graph.
 
Represents a section address range via a pair of Block pointers to the first and last Blocks in the s...
 
Block * getFirstBlock() const
 
orc::ExecutorAddr getEnd() const
 
orc::ExecutorAddrDiff getSize() const
 
orc::ExecutorAddr getStart() const
 
Represents an object file section.
 
iterator_range< symbol_iterator > symbols()
Returns an iterator over the symbols defined in this section.
 
StringRef getName() const
Returns the name of this section.
 
iterator_range< block_iterator > blocks()
Returns an iterator over the blocks defined in this section.
 
An ExecutionSession represents a running JIT program.
 
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
 
LLVM_ABI void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder, SymbolLookupSet Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies)
Search the given JITDylibs for the given symbols.
 
size_t getPageSize() const
 
Represents an address in the executor process.
 
uint64_t getValue() const
 
void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &LG, jitlink::PassConfiguration &PassConfig) override
 
static Expected< std::unique_ptr< GDBJITDebugInfoRegistrationPlugin > > Create(ExecutionSession &ES, JITDylib &ProcessJD, const Triple &TT)
 
void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override
 
Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override
 
Error notifyFailed(MaterializationResponsibility &MR) override
 
Represents a JIT'd dynamic library.
 
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
 
JITDylib & getTargetJITDylib() const
Returns the target JITDylib that these symbols are being materialized into.
 
A utility class for serializing to a blob from a variadic list.
 
static Expected< WrapperFunctionCall > Create(ExecutorAddr FnAddr, const ArgTs &...Args)
Create a WrapperFunctionCall using the given SPS serializer to serialize the arguments.
 
LLVM_ABI Expected< uint32_t > getCPUSubType(const Triple &T)
 
LLVM_ABI Expected< uint32_t > getCPUType(const Triple &T)
 
@ S_ATTR_DEBUG
S_ATTR_DEBUG - A debug section.
 
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
 
LLVM_ABI Error preserveDebugSections(jitlink::LinkGraph &G)
 
@ NoAlloc
NoAlloc memory should not be allocated by the JITLinkMemoryManager at all.
 
This is an optimization pass for GlobalISel generic memory operations.
 
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
 
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
 
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
 
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
 
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
 
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
 
void consumeError(Error Err)
Consume a Error without doing anything.
 
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
 
LinkGraphPassList PostFixupPasses
Post-fixup passes.
 
LinkGraphPassList PostPrunePasses
Post-prune passes.
 
LinkGraphPassList PrePrunePasses
Pre-prune passes.