[llvm] 99e70cc - Revert "[ORC] Add a MachOBuilder utility, use it to build MachO debug objects."

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 7 10:41:02 PDT 2023


Author: Lang Hames
Date: 2023-09-07T10:40:56-07:00
New Revision: 99e70cc3a56b02ba556270fa205c04ca77de6444

URL: https://github.com/llvm/llvm-project/commit/99e70cc3a56b02ba556270fa205c04ca77de6444
DIFF: https://github.com/llvm/llvm-project/commit/99e70cc3a56b02ba556270fa205c04ca77de6444.diff

LOG: Revert "[ORC] Add a MachOBuilder utility, use it to build MachO debug objects."

This reverts commit 75c487602a8af130ec0aedf398e318cb57063f2d while I
investigate some build failures, e.g.
https://lab.llvm.org/buildbot/#/builders/217/builds/27769

Added: 
    

Modified: 
    llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp

Removed: 
    llvm/include/llvm/ExecutionEngine/Orc/MachOBuilder.h


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/MachOBuilder.h b/llvm/include/llvm/ExecutionEngine/Orc/MachOBuilder.h
deleted file mode 100644
index ed123b766d6634b..000000000000000
--- a/llvm/include/llvm/ExecutionEngine/Orc/MachOBuilder.h
+++ /dev/null
@@ -1,525 +0,0 @@
-//===------------ MachOBuilder.h -- Build MachO Objects ---------*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// Build MachO object files for interaction with the ObjC runtime and debugger.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
-#define LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H
-
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/MathExtras.h"
-
-#include <list>
-#include <map>
-#include <vector>
-
-namespace llvm {
-namespace orc {
-
-// Builds MachO objects.
-template <typename MachOTraits> class MachOBuilder {
-private:
-  struct BufferWriter {
-  public:
-    BufferWriter(MutableArrayRef<char> Buffer)
-        : Data(Buffer.data()), Size(Buffer.size()) {}
-
-    size_t tell() const { return Offset; }
-
-    void write(char C) {
-      assert(Offset < Size && "Buffer overflow");
-      Data[Offset++] = C;
-    }
-
-    void write(const char *Src, size_t SrcSize) {
-      assert(Offset + SrcSize <= Size && "Buffer overflow");
-      memcpy(&Data[Offset], Src, SrcSize);
-      Offset += SrcSize;
-    }
-
-    template <typename T> void write(const T &Value) {
-      assert(Offset + sizeof(T) <= Size && "Buffer overflow");
-      memcpy(&Data[Offset], reinterpret_cast<const char *>(&Value), sizeof(T));
-      Offset += sizeof(T);
-    }
-
-  private:
-    char *Data = 0;
-    size_t Offset = 0;
-    size_t Size = 0;
-  };
-
-  struct SymbolContainer {
-    size_t SymbolIndexBase = 0;
-    std::vector<typename MachOTraits::NList> Symbols;
-  };
-
-  static void writeMachOStruct(BufferWriter &BW, MachO::relocation_info RI) {
-    BW.write(RI);
-  }
-
-  template <typename MachOStruct>
-  static void writeMachOStruct(BufferWriter &BW, MachOStruct S) {
-    if (MachOTraits::Endianness != support::endian::system_endianness())
-      MachO::swapStruct(S);
-    BW.write(S);
-  }
-
-  struct LoadCommandBase {
-    virtual ~LoadCommandBase() {}
-    virtual size_t size() const = 0;
-    virtual void write(BufferWriter &BW) = 0;
-  };
-
-  template <MachO::LoadCommandType LCType> struct LoadCommand;
-
-#define HANDLE_LOAD_COMMAND(Name, Value, LCStruct)                             \
-  template <>                                                                  \
-  struct LoadCommand<MachO::Name> : public MachO::LCStruct,                    \
-                                    public LoadCommandBase {                   \
-    using CmdStruct = LCStruct;                                                \
-    LoadCommand() {                                                            \
-      memset(&rawStruct(), 0, sizeof(CmdStruct));                              \
-      cmd = Value;                                                             \
-      cmdsize = sizeof(CmdStruct);                                             \
-    }                                                                          \
-    template <typename... ArgTs>                                               \
-    LoadCommand(ArgTs &&...Args)                                               \
-        : CmdStruct{Value, sizeof(CmdStruct), std::forward<ArgTs>(Args)...} {} \
-    CmdStruct &rawStruct() { return static_cast<CmdStruct &>(*this); }         \
-    size_t size() const override { return cmdsize; }                           \
-    void write(BufferWriter &BW) override {                                    \
-      writeMachOStruct(BW, rawStruct());                                       \
-    }                                                                          \
-  };
-
-#include "llvm/BinaryFormat/MachO.def"
-
-#undef HANDLE_LOAD_COMMAND
-
-  struct StringTableEntry {
-    StringRef S;
-    size_t Offset;
-  };
-
-  using StringTable = std::vector<StringTableEntry>;
-
-public:
-  using StringId = size_t;
-
-  struct Section;
-
-  // Points to either an nlist entry (as a (symbol-container, index) pair), or
-  // a section.
-  class RelocTarget {
-  public:
-    RelocTarget(const Section &S) : S(&S), Idx(~0U) {}
-    RelocTarget(SymbolContainer &SC, size_t Idx) : SC(&SC), Idx(Idx) {}
-
-    bool isSymbol() { return Idx != ~0U; }
-
-    uint32_t getSymbolNum() {
-      assert(isSymbol() && "Target is not a symbol");
-      return SC->SymbolIndexBase + Idx;
-    }
-
-    uint32_t getSectionId() {
-      assert(!isSymbol() && "Target is not a section");
-      return S->SectionNumber;
-    }
-
-    typename MachOTraits::NList &nlist() {
-      assert(isSymbol() && "Target is not a symbol");
-      return SC->Symbols[Idx];
-    }
-
-  private:
-    union {
-      const Section *S;
-      SymbolContainer *SC;
-    };
-    size_t Idx;
-  };
-
-  struct Reloc : public MachO::relocation_info {
-    RelocTarget Target;
-
-    Reloc(int32_t Offset, RelocTarget Target, bool PCRel, unsigned Length,
-          unsigned Type)
-        : Target(Target) {
-      assert(Type < 16 && "Relocation type out of range");
-      r_address = Offset; // Will slide to account for sec addr during layout
-      r_symbolnum = 0;
-      r_pcrel = PCRel;
-      r_length = Length;
-      r_extern = Target.isSymbol();
-      r_type = Type;
-    }
-
-    MachO::relocation_info &rawStruct() {
-      return static_cast<MachO::relocation_info &>(*this);
-    }
-  };
-
-  struct SectionContent {
-    const char *Data = nullptr;
-    size_t Size = 0;
-  };
-
-  struct Section : public MachOTraits::Section, public RelocTarget {
-    MachOBuilder &Builder;
-    SectionContent Content;
-    size_t SectionNumber = 0;
-    SymbolContainer SC;
-    std::vector<Reloc> Relocs;
-
-    Section(MachOBuilder &Builder, StringRef SecName, StringRef SegName)
-        : RelocTarget(*this), Builder(Builder) {
-      memset(&rawStruct(), 0, sizeof(typename MachOTraits::Section));
-      assert(SecName.size() <= 16 && "SecName too long");
-      assert(SegName.size() <= 16 && "SegName too long");
-      memcpy(this->sectname, SecName.data(), SecName.size());
-      memcpy(this->segname, SegName.data(), SegName.size());
-    }
-
-    RelocTarget addSymbol(int32_t Offset, StringRef Name, uint8_t Type,
-                          uint16_t Desc) {
-      StringId SI = Builder.addString(Name);
-      typename MachOTraits::NList Sym;
-      Sym.n_strx = SI;
-      Sym.n_type = Type | MachO::N_SECT;
-      Sym.n_sect = MachO::NO_SECT; // Will be filled in later.
-      Sym.n_desc = Desc;
-      Sym.n_value = Offset;
-      SC.Symbols.push_back(Sym);
-      return {SC, SC.Symbols.size() - 1};
-    }
-
-    void addReloc(int32_t Offset, RelocTarget Target, bool PCRel,
-                  unsigned Length, unsigned Type) {
-      Relocs.push_back({Offset, Target, PCRel, Length, Type});
-    }
-
-    auto &rawStruct() {
-      return static_cast<typename MachOTraits::Section &>(*this);
-    }
-  };
-
-  struct Segment : public LoadCommand<MachOTraits::SegmentCmd> {
-    MachOBuilder &Builder;
-    std::vector<std::unique_ptr<Section>> Sections;
-
-    Segment(MachOBuilder &Builder, StringRef SegName)
-        : LoadCommand<MachOTraits::SegmentCmd>(), Builder(Builder) {
-      assert(SegName.size() <= 16 && "SegName too long");
-      memcpy(this->segname, SegName.data(), SegName.size());
-      this->maxprot =
-          MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
-      this->initprot = this->maxprot;
-    }
-
-    Section &addSection(StringRef SecName, StringRef SegName) {
-      Sections.push_back(std::make_unique<Section>(Builder, SecName, SegName));
-      return *Sections.back();
-    }
-
-    void write(BufferWriter &BW) override {
-      writeMachOStruct(BW, this->rawStruct());
-      for (auto &Sec : Sections)
-        writeMachOStruct(BW, Sec->rawStruct());
-    }
-  };
-
-  MachOBuilder(size_t PageSize) : PageSize(PageSize) {
-    memset((char *)&Header, 0, sizeof(Header));
-    Header.magic = MachOTraits::Magic;
-  }
-
-  template <MachO::LoadCommandType LCType, typename... ArgTs>
-  LoadCommand<LCType> &addLoadCommand(ArgTs &&...Args) {
-    static_assert(LCType != MachOTraits::SegmentCmd,
-                  "Use addSegment to add segment load command");
-    auto LC =
-        std::make_unique<LoadCommand<LCType>>(std::forward<ArgTs>(Args)...);
-    auto &Tmp = *LC;
-    LoadCommands.push_back(std::move(LC));
-    return Tmp;
-  }
-
-  StringId addString(StringRef Str) {
-    if (Strings.empty() && !Str.empty())
-      addString("");
-    return Strings.insert(std::make_pair(Str, Strings.size())).first->second;
-  }
-
-  Segment &addSegment(StringRef SegName) {
-    Segments.push_back(Segment(*this, SegName));
-    return Segments.back();
-  }
-
-  RelocTarget addSymbol(StringRef Name, uint8_t Type, uint8_t Sect,
-                        uint16_t Desc, typename MachOTraits::UIntPtr Value) {
-    StringId SI = addString(Name);
-    typename MachOTraits::NList Sym;
-    Sym.n_strx = SI;
-    Sym.n_type = Type;
-    Sym.n_sect = Sect;
-    Sym.n_desc = Desc;
-    Sym.n_value = Value;
-    SC.Symbols.push_back(Sym);
-    return {SC, SC.Symbols.size() - 1};
-  }
-
-  // Call to perform layout on the MachO. Returns the total size of the
-  // resulting file.
-  // This method will automatically insert some load commands (e.g.
-  // LC_SYMTAB) and fill in load command fields.
-  size_t layout() {
-
-    // Build symbol table and add LC_SYMTAB command.
-    makeStringTable();
-    LoadCommand<MachOTraits::SymTabCmd> *SymTabLC = nullptr;
-    if (!StrTab.empty())
-      SymTabLC = &addLoadCommand<MachOTraits::SymTabCmd>();
-
-    // Lay out header, segment load command, and other load commands.
-    size_t Offset = sizeof(Header);
-    for (auto &Seg : Segments) {
-      Seg.cmdsize +=
-          Seg.Sections.size() * sizeof(typename MachOTraits::Section);
-      Seg.nsects = Seg.Sections.size();
-      Offset += Seg.cmdsize;
-    }
-    for (auto &LC : LoadCommands)
-      Offset += LC->size();
-
-    Header.sizeofcmds = Offset - sizeof(Header);
-
-    // Lay out content, set segment / section addrs and offsets.
-    size_t SegVMAddr = 0;
-    for (auto &Seg : Segments) {
-      Seg.vmaddr = SegVMAddr;
-      Seg.fileoff = Offset;
-      for (auto &Sec : Seg.Sections) {
-        Offset = alignTo(Offset, 1 << Sec->align);
-        if (Sec->Content.Size)
-          Sec->offset = Offset;
-        Sec->size = Sec->Content.Size;
-        Sec->addr = SegVMAddr + Sec->offset - Seg.fileoff;
-        Offset += Sec->Content.Size;
-      }
-      size_t SegContentSize = Offset - Seg.fileoff;
-      Seg.filesize = SegContentSize;
-      Seg.vmsize = Header.filetype == MachO::MH_OBJECT
-                       ? SegContentSize
-                       : alignTo(SegContentSize, PageSize);
-      SegVMAddr += Seg.vmsize;
-    }
-
-    // Set string table offsets for non-section symbols.
-    for (auto &Sym : SC.Symbols)
-      Sym.n_strx = StrTab[Sym.n_strx].Offset;
-
-    // Number sections, set symbol section numbers and string table offsets,
-    // count relocations.
-    size_t NumSymbols = SC.Symbols.size();
-    size_t SectionNumber = 0;
-    for (auto &Seg : Segments) {
-      for (auto &Sec : Seg.Sections) {
-        ++SectionNumber;
-        Sec->SectionNumber = SectionNumber;
-        Sec->SC.SymbolIndexBase = NumSymbols;
-        NumSymbols += Sec->SC.Symbols.size();
-        for (auto &Sym : Sec->SC.Symbols) {
-          Sym.n_sect = SectionNumber;
-          Sym.n_strx = StrTab[Sym.n_strx].Offset;
-          Sym.n_value += Sec->addr;
-        }
-      }
-    }
-
-    // Handle relocations
-    bool OffsetAlignedForRelocs = false;
-    for (auto &Seg : Segments) {
-      for (auto &Sec : Seg.Sections) {
-        if (!Sec->Relocs.empty()) {
-          if (!OffsetAlignedForRelocs) {
-            Offset = alignTo(Offset, sizeof(MachO::relocation_info));
-            OffsetAlignedForRelocs = true;
-          }
-          Sec->reloff = Offset;
-          Sec->nreloc = Sec->Relocs.size();
-          Offset += Sec->Relocs.size() * sizeof(MachO::relocation_info);
-          for (auto &R : Sec->Relocs)
-            R.r_symbolnum = R.Target.isSymbol() ? R.Target.getSymbolNum()
-                                                : R.Target.getSectionId();
-        }
-      }
-    }
-
-    // Calculate offset to start of nlist and update symtab command.
-    if (NumSymbols > 0) {
-      Offset = alignTo(Offset, sizeof(typename MachOTraits::NList));
-      SymTabLC->symoff = Offset;
-      SymTabLC->nsyms = NumSymbols;
-
-      // Calculate string table bounds and update symtab command.
-      if (!StrTab.empty()) {
-        Offset += NumSymbols * sizeof(typename MachOTraits::NList);
-        size_t StringTableSize =
-            StrTab.back().Offset + StrTab.back().S.size() + 1;
-
-        SymTabLC->stroff = Offset;
-        SymTabLC->strsize = StringTableSize;
-        Offset += StringTableSize;
-      }
-    }
-
-    return Offset;
-  }
-
-  void write(MutableArrayRef<char> Buffer) {
-    BufferWriter BW(Buffer);
-    writeHeader(BW);
-    writeSegments(BW);
-    writeLoadCommands(BW);
-    writeSectionContent(BW);
-    writeRelocations(BW);
-    writeSymbols(BW);
-    writeStrings(BW);
-  }
-
-  typename MachOTraits::Header Header;
-
-private:
-  void makeStringTable() {
-    if (Strings.empty())
-      return;
-
-    StrTab.resize(Strings.size());
-    for (auto &KV : Strings)
-      StrTab[KV.second] = {KV.first, 0};
-    size_t Offset = 0;
-    for (auto &Elem : StrTab) {
-      Elem.Offset = Offset;
-      Offset += Elem.S.size() + 1;
-    }
-  }
-
-  void writeHeader(BufferWriter &BW) {
-    Header.ncmds = Segments.size() + LoadCommands.size();
-    writeMachOStruct(BW, Header);
-  }
-
-  void writeSegments(BufferWriter &BW) {
-    for (auto &Seg : Segments)
-      Seg.write(BW);
-  }
-
-  void writeLoadCommands(BufferWriter &BW) {
-    for (auto &LC : LoadCommands)
-      LC->write(BW);
-  }
-
-  void writeSectionContent(BufferWriter &BW) {
-    for (auto &Seg : Segments) {
-      for (auto &Sec : Seg.Sections) {
-        if (!Sec->Content.Data) {
-          assert(Sec->Relocs.empty() &&
-                 "Cant' have relocs for zero-fill segment");
-          continue;
-        }
-        size_t ZeroPad = Sec->offset - BW.tell();
-        while (ZeroPad--)
-          BW.write('\0');
-        BW.write(Sec->Content.Data, Sec->Content.Size);
-      }
-    }
-  }
-
-  void writeRelocations(BufferWriter &BW) {
-    for (auto &Seg : Segments) {
-      for (auto &Sec : Seg.Sections) {
-        if (!Sec->Relocs.empty()) {
-          while (BW.tell() % sizeof(MachO::relocation_info))
-            BW.write('\0');
-        }
-        for (auto &R : Sec->Relocs)
-          writeMachOStruct(BW, R.rawStruct());
-      }
-    }
-  }
-
-  void writeSymbols(BufferWriter &BW) {
-
-    // Count symbols.
-    size_t NumSymbols = SC.Symbols.size();
-    for (auto &Seg : Segments)
-      for (auto &Sec : Seg.Sections)
-        NumSymbols += Sec->SC.Symbols.size();
-
-    // If none then return.
-    if (NumSymbols == 0)
-      return;
-
-    size_t ZeroPad =
-        alignTo(BW.tell(), sizeof(typename MachOTraits::NList)) - BW.tell();
-    while (ZeroPad--)
-      BW.write('\0');
-
-    // Write non-section symbols.
-    for (auto &Sym : SC.Symbols)
-      writeMachOStruct(BW, Sym);
-
-    // Write section symbols.
-    for (auto &Seg : Segments) {
-      for (auto &Sec : Seg.Sections) {
-        for (auto &Sym : Sec->SC.Symbols) {
-          writeMachOStruct(BW, Sym);
-        }
-      }
-    }
-  }
-
-  void writeStrings(BufferWriter &BW) {
-    for (auto &Elem : StrTab) {
-      BW.write(Elem.S.data(), Elem.S.size());
-      BW.write('\0');
-    }
-  }
-
-  size_t PageSize;
-  std::list<Segment> Segments;
-  std::vector<std::unique_ptr<LoadCommandBase>> LoadCommands;
-  SymbolContainer SC;
-
-  // Maps strings to their "id" (addition order).
-  std::map<StringRef, size_t> Strings;
-  StringTable StrTab;
-};
-
-struct MachO64LE {
-  using UIntPtr = uint64_t;
-  using Header = MachO::mach_header_64;
-  using Section = MachO::section_64;
-  using NList = MachO::nlist_64;
-  using Relocation = MachO::relocation_info;
-
-  static constexpr support::endianness Endianness = support::little;
-  static constexpr uint32_t Magic = MachO::MH_MAGIC_64;
-  static constexpr MachO::LoadCommandType SegmentCmd = MachO::LC_SEGMENT_64;
-  static constexpr MachO::LoadCommandType SymTabCmd = MachO::LC_SYMTAB;
-};
-
-} // namespace orc
-} // namespace llvm
-
-#endif // LLVM_EXECUTIONENGINE_ORC_MACHOBUILDER_H

diff  --git a/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
index 63c188676d197b4..830582bb3649115 100644
--- a/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
@@ -10,7 +10,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ExecutionEngine/Orc/DebuggerSupportPlugin.h"
-#include "llvm/ExecutionEngine/Orc/MachOBuilder.h"
 
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
@@ -27,6 +26,19 @@ static const char *SynthDebugSectionName = "__jitlink_synth_debug_object";
 
 namespace {
 
+struct MachO64LE {
+  using UIntPtr = uint64_t;
+
+  using Header = MachO::mach_header_64;
+  using SegmentLC = MachO::segment_command_64;
+  using Section = MachO::section_64;
+  using NList = MachO::nlist_64;
+
+  static constexpr support::endianness Endianness = support::little;
+  static constexpr const uint32_t Magic = MachO::MH_MAGIC_64;
+  static constexpr const uint32_t SegmentCmd = MachO::LC_SEGMENT_64;
+};
+
 class MachODebugObjectSynthesizerBase
     : public GDBJITDebugInfoRegistrationPlugin::DebugSectionSynthesizer {
 public:
@@ -72,7 +84,6 @@ class MachODebugObjectSynthesizerBase
         if (!PreservedBlocks.count(B))
           G.addAnonymousSymbol(*B, 0, 0, false, true);
     }
-
     return Error::success();
   }
 
@@ -83,12 +94,28 @@ class MachODebugObjectSynthesizerBase
 
 template <typename MachOTraits>
 class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
-public:
-  MachODebugObjectSynthesizer(ExecutionSession &ES, LinkGraph &G,
-                              ExecutorAddr RegisterActionAddr)
-      : MachODebugObjectSynthesizerBase(G, RegisterActionAddr),
-        Builder(ES.getPageSize()) {}
+private:
+  class MachOStructWriter {
+  public:
+    MachOStructWriter(MutableArrayRef<char> Buffer) : Buffer(Buffer) {}
+
+    size_t getOffset() const { return Offset; }
+
+    template <typename MachOStruct> void write(MachOStruct S) {
+      assert(Offset + sizeof(S) <= Buffer.size() &&
+             "Container block overflow while constructing debug MachO");
+      if (MachOTraits::Endianness != support::endian::system_endianness())
+        MachO::swapStruct(S);
+      memcpy(Buffer.data() + Offset, &S, sizeof(S));
+      Offset += sizeof(S);
+    }
+
+  private:
+    MutableArrayRef<char> Buffer;
+    size_t Offset = 0;
+  };
 
+public:
   using MachODebugObjectSynthesizerBase::MachODebugObjectSynthesizerBase;
 
   Error startSynthesis() override {
@@ -96,79 +123,164 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
       dbgs() << "Creating " << SynthDebugSectionName << " for " << G.getName()
              << "\n";
     });
-
     auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read);
 
+    struct DebugSectionInfo {
+      Section *Sec = nullptr;
+      StringRef SegName;
+      StringRef SecName;
+      uint64_t Alignment = 0;
+      orc::ExecutorAddr StartAddr;
+      uint64_t Size = 0;
+    };
+
+    SmallVector<DebugSectionInfo, 12> DebugSecInfos;
+    size_t NumSections = 0;
     for (auto &Sec : G.sections()) {
       if (Sec.blocks().empty())
         continue;
 
-      // Skip sections whose name's don't fit the MachO standard.
-      if (Sec.getName().empty() || Sec.getName().size() > 33 ||
-          Sec.getName().find(',') > 16)
-        continue;
+      ++NumSections;
+      if (isDebugSection(Sec)) {
+        size_t SepPos = Sec.getName().find(',');
+        if (SepPos > 16 || (Sec.getName().size() - (SepPos + 1) > 16)) {
+          LLVM_DEBUG({
+            dbgs() << "Skipping debug object synthesis for graph "
+                   << G.getName()
+                   << ": encountered non-standard DWARF section name \""
+                   << Sec.getName() << "\"\n";
+          });
+          return Error::success();
+        }
+        DebugSecInfos.push_back({&Sec, Sec.getName().substr(0, SepPos),
+                                 Sec.getName().substr(SepPos + 1), 0,
+                                 orc::ExecutorAddr(), 0});
+      } else {
+        NonDebugSections.push_back(&Sec);
+
+        // If the first block in the section has a non-zero alignment offset
+        // then we need to add a padding block, since the section command in
+        // the header doesn't allow for aligment offsets.
+        SectionRange R(Sec);
+        if (!R.empty()) {
+          auto &FB = *R.getFirstBlock();
+          if (FB.getAlignmentOffset() != 0) {
+            auto Padding = G.allocateBuffer(FB.getAlignmentOffset());
+            memset(Padding.data(), 0, Padding.size());
+            G.createContentBlock(Sec, Padding,
+                                 FB.getAddress() - FB.getAlignmentOffset(),
+                                 FB.getAlignment(), 0);
+          }
+        }
+      }
+    }
+
+    // Create container block.
+    size_t SectionsCmdSize =
+        sizeof(typename MachOTraits::Section) * NumSections;
+    size_t SegmentLCSize =
+        sizeof(typename MachOTraits::SegmentLC) + SectionsCmdSize;
+    size_t ContainerBlockSize =
+        sizeof(typename MachOTraits::Header) + SegmentLCSize;
+    auto ContainerBlockContent = G.allocateBuffer(ContainerBlockSize);
+    MachOContainerBlock = &G.createMutableContentBlock(
+        SDOSec, ContainerBlockContent, orc::ExecutorAddr(), 8, 0);
+
+    // Copy debug section blocks and symbols.
+    orc::ExecutorAddr NextBlockAddr(MachOContainerBlock->getSize());
+    for (auto &SI : DebugSecInfos) {
+      assert(!SI.Sec->blocks().empty() && "Empty debug info section?");
+
+      // Update addresses in debug section.
+      LLVM_DEBUG({
+        dbgs() << "  Appending " << SI.Sec->getName() << " ("
+               << SI.Sec->blocks_size() << " block(s)) at "
+               << formatv("{0:x8}", NextBlockAddr) << "\n";
+      });
+      for (auto *B : SI.Sec->blocks()) {
+        NextBlockAddr = alignToBlock(NextBlockAddr, *B);
+        B->setAddress(NextBlockAddr);
+        NextBlockAddr += B->getSize();
+      }
 
-      if (isDebugSection(Sec))
-        DebugSections.push_back({&Sec, nullptr});
-      else if (Sec.getMemLifetimePolicy() != MemLifetimePolicy::NoAlloc)
-        NonDebugSections.push_back({&Sec, nullptr});
+      auto &FirstBlock = **SI.Sec->blocks().begin();
+      if (FirstBlock.getAlignmentOffset() != 0)
+        return make_error<StringError>(
+            "First block in " + SI.Sec->getName() +
+                " section has non-zero alignment offset",
+            inconvertibleErrorCode());
+      if (FirstBlock.getAlignment() > std::numeric_limits<uint32_t>::max())
+        return make_error<StringError>("First block in " + SI.Sec->getName() +
+                                           " has alignment >4Gb",
+                                       inconvertibleErrorCode());
+
+      SI.Alignment = FirstBlock.getAlignment();
+      SI.StartAddr = FirstBlock.getAddress();
+      SI.Size = NextBlockAddr - SI.StartAddr;
+      G.mergeSections(SDOSec, *SI.Sec);
+      SI.Sec = nullptr;
     }
+    size_t DebugSectionsSize =
+        NextBlockAddr - orc::ExecutorAddr(MachOContainerBlock->getSize());
 
     // Write MachO header and debug section load commands.
-    Builder.Header.filetype = MachO::MH_OBJECT;
+    MachOStructWriter Writer(MachOContainerBlock->getAlreadyMutableContent());
+    typename MachOTraits::Header Hdr;
+    memset(&Hdr, 0, sizeof(Hdr));
+    Hdr.magic = MachOTraits::Magic;
     switch (G.getTargetTriple().getArch()) {
     case Triple::x86_64:
-      Builder.Header.cputype = MachO::CPU_TYPE_X86_64;
-      Builder.Header.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
+      Hdr.cputype = MachO::CPU_TYPE_X86_64;
+      Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
       break;
     case Triple::aarch64:
-      Builder.Header.cputype = MachO::CPU_TYPE_ARM64;
-      Builder.Header.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
+      Hdr.cputype = MachO::CPU_TYPE_ARM64;
+      Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
       break;
     default:
       llvm_unreachable("Unsupported architecture");
     }
-
-    Seg = &Builder.addSegment("");
-
-    for (auto &DSec : DebugSections) {
-      auto [SegName, SecName] = DSec.GraphSec->getName().split(',');
-      DSec.BuilderSec = &Seg->addSection(SecName, SegName);
-
-      SectionRange SR(*DSec.GraphSec);
-      DSec.BuilderSec->Content.Size = SR.getSize();
-      if (!SR.empty())
-        DSec.BuilderSec->align = Log2_64(SR.getFirstBlock()->getAlignment());
+    Hdr.filetype = MachO::MH_OBJECT;
+    Hdr.ncmds = 1;
+    Hdr.sizeofcmds = SegmentLCSize;
+    Hdr.flags = 0;
+    Writer.write(Hdr);
+
+    typename MachOTraits::SegmentLC SegLC;
+    memset(&SegLC, 0, sizeof(SegLC));
+    SegLC.cmd = MachOTraits::SegmentCmd;
+    SegLC.cmdsize = SegmentLCSize;
+    SegLC.vmaddr = ContainerBlockSize;
+    SegLC.vmsize = DebugSectionsSize;
+    SegLC.fileoff = ContainerBlockSize;
+    SegLC.filesize = DebugSectionsSize;
+    SegLC.maxprot =
+        MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
+    SegLC.initprot =
+        MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
+    SegLC.nsects = NumSections;
+    SegLC.flags = 0;
+    Writer.write(SegLC);
+
+    StringSet<> ExistingLongNames;
+    for (auto &SI : DebugSecInfos) {
+      typename MachOTraits::Section Sec;
+      memset(&Sec, 0, sizeof(Sec));
+      memcpy(Sec.sectname, SI.SecName.data(), SI.SecName.size());
+      memcpy(Sec.segname, SI.SegName.data(), SI.SegName.size());
+      Sec.addr = SI.StartAddr.getValue();
+      Sec.size = SI.Size;
+      Sec.offset = SI.StartAddr.getValue();
+      Sec.align = SI.Alignment;
+      Sec.reloff = 0;
+      Sec.nreloc = 0;
+      Sec.flags = MachO::S_ATTR_DEBUG;
+      Writer.write(Sec);
     }
 
-    for (auto &NDSP : NonDebugSections) {
-      auto [SegName, SecName] = NDSP.GraphSec->getName().split(',');
-      NDSP.BuilderSec = &Seg->addSection(SecName, SegName);
-      SectionRange SR(*NDSP.GraphSec);
-      if (!SR.empty())
-        NDSP.BuilderSec->align = Log2_64(SR.getFirstBlock()->getAlignment());
-
-      // Add stabs.
-      for (auto *Sym : NDSP.GraphSec->symbols()) {
-        // Skip anonymous symbols.
-        if (!Sym->hasName())
-          continue;
-
-        uint8_t SymType = Sym->isCallable() ? MachO::N_FUN : MachO::N_GSYM;
-
-        Builder.addSymbol("", MachO::N_BNSYM, 1, 0, 0);
-        StabSymbols.push_back(
-            {*Sym, Builder.addSymbol(Sym->getName(), SymType, 1, 0, 0),
-             Builder.addSymbol(Sym->getName(), SymType, 0, 0, 0)});
-        Builder.addSymbol("", MachO::N_ENSYM, 1, 0, 0);
-      }
-    }
-
-    size_t DebugObjectSize = Builder.layout();
-
-    MachOContainerBlock = &G.createMutableContentBlock(
-        SDOSec, G.allocateBuffer(DebugObjectSize), orc::ExecutorAddr(), 8, 0);
-
+    // Set MachOContainerBlock to indicate success to
+    // completeSynthesisAndRegister.
+    NonDebugSectionsStart = Writer.getOffset();
     return Error::success();
   }
 
@@ -178,45 +290,63 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
         dbgs() << "Not writing MachO debug object header for " << G.getName()
                << " since createDebugSection failed\n";
       });
-
       return Error::success();
     }
-    ExecutorAddr MaxAddr;
-    for (auto &NDSec : NonDebugSections) {
-      SectionRange SR(*NDSec.GraphSec);
-      NDSec.BuilderSec->addr = SR.getStart().getValue();
-      NDSec.BuilderSec->size = SR.getSize();
-      NDSec.BuilderSec->offset = SR.getStart().getValue();
-      if (SR.getEnd() > MaxAddr)
-        MaxAddr = SR.getEnd();
-    }
-
-    for (auto &DSec : DebugSections) {
-      if (DSec.GraphSec->blocks_size() != 1)
-        return make_error<StringError>(
-            "Unexpected number of blocks in debug info section",
-            inconvertibleErrorCode());
-
-      if (ExecutorAddr(DSec.BuilderSec->addr) + DSec.BuilderSec->size > MaxAddr)
-        MaxAddr = ExecutorAddr(DSec.BuilderSec->addr) + DSec.BuilderSec->size;
-
-      auto &B = **DSec.GraphSec->blocks().begin();
-      DSec.BuilderSec->Content.Data = B.getContent().data();
-      DSec.BuilderSec->Content.Size = B.getContent().size();
-      DSec.BuilderSec->flags |= MachO::S_ATTR_DEBUG;
-    }
 
     LLVM_DEBUG({
       dbgs() << "Writing MachO debug object header for " << G.getName() << "\n";
     });
 
-    // Update stab symbol addresses.
-    for (auto &SS : StabSymbols) {
-      SS.StartStab.nlist().n_value = SS.Sym.getAddress().getValue();
-      SS.EndStab.nlist().n_value = SS.Sym.getSize();
-    }
+    MachOStructWriter Writer(
+        MachOContainerBlock->getAlreadyMutableContent().drop_front(
+            NonDebugSectionsStart));
+
+    unsigned LongSectionNameIdx = 0;
+    for (auto *Sec : NonDebugSections) {
+      size_t SepPos = Sec->getName().find(',');
+      StringRef SegName, SecName;
+      std::string CustomSecName;
+
+      if ((SepPos == StringRef::npos && Sec->getName().size() <= 16)) {
+        // No embedded segment name, short section name.
+        SegName = "__JITLINK_CUSTOM";
+        SecName = Sec->getName();
+      } else if (SepPos < 16 && (Sec->getName().size() - (SepPos + 1) <= 16)) {
+        // Canonical embedded segment and section name.
+        SegName = Sec->getName().substr(0, SepPos);
+        SecName = Sec->getName().substr(SepPos + 1);
+      } else {
+        // Long section name that needs to be truncated.
+        assert(Sec->getName().size() > 16 &&
+               "Short section name should have been handled above");
+        SegName = "__JITLINK_CUSTOM";
+        auto IdxStr = std::to_string(++LongSectionNameIdx);
+        CustomSecName = Sec->getName().substr(0, 15 - IdxStr.size()).str();
+        CustomSecName += ".";
+        CustomSecName += IdxStr;
+        SecName = StringRef(CustomSecName.data(), 16);
+      }
 
-    Builder.write(MachOContainerBlock->getAlreadyMutableContent());
+      SectionRange R(*Sec);
+      if (R.getFirstBlock()->getAlignmentOffset() != 0)
+        return make_error<StringError>(
+            "While building MachO debug object for " + G.getName() +
+                " first block has non-zero alignment offset",
+            inconvertibleErrorCode());
+
+      typename MachOTraits::Section SecCmd;
+      memset(&SecCmd, 0, sizeof(SecCmd));
+      memcpy(SecCmd.sectname, SecName.data(), SecName.size());
+      memcpy(SecCmd.segname, SegName.data(), SegName.size());
+      SecCmd.addr = R.getStart().getValue();
+      SecCmd.size = R.getSize();
+      SecCmd.offset = 0;
+      SecCmd.align = R.getFirstBlock()->getAlignment();
+      SecCmd.reloff = 0;
+      SecCmd.nreloc = 0;
+      SecCmd.flags = 0;
+      Writer.write(SecCmd);
+    }
 
     static constexpr bool AutoRegisterCode = true;
     SectionRange R(MachOContainerBlock->getSection());
@@ -225,34 +355,13 @@ class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
                   shared::SPSArgList<shared::SPSExecutorAddrRange, bool>>(
              RegisterActionAddr, R.getRange(), AutoRegisterCode)),
          {}});
-
     return Error::success();
   }
 
 private:
-  struct SectionPair {
-    Section *GraphSec = nullptr;
-    typename MachOBuilder<MachOTraits>::Section *BuilderSec = nullptr;
-  };
-
-  struct StabSymbolsEntry {
-    using RelocTarget = typename MachOBuilder<MachOTraits>::RelocTarget;
-
-    StabSymbolsEntry(Symbol &Sym, RelocTarget StartStab, RelocTarget EndStab)
-        : Sym(Sym), StartStab(StartStab), EndStab(EndStab) {}
-
-    Symbol &Sym;
-    RelocTarget StartStab, EndStab;
-  };
-
-  using BuilderType = MachOBuilder<MachOTraits>;
-
   Block *MachOContainerBlock = nullptr;
-  MachOBuilder<MachOTraits> Builder;
-  typename MachOBuilder<MachOTraits>::Segment *Seg = nullptr;
-  std::vector<StabSymbolsEntry> StabSymbols;
-  SmallVector<SectionPair, 16> DebugSections;
-  SmallVector<SectionPair, 16> NonDebugSections;
+  SmallVector<Section *, 16> NonDebugSections;
+  size_t NonDebugSectionsStart = 0;
 };
 
 } // end anonymous namespace
@@ -344,12 +453,12 @@ void GDBJITDebugInfoRegistrationPlugin::modifyPassConfigForMachO(
     });
 
     auto MDOS = std::make_shared<MachODebugObjectSynthesizer<MachO64LE>>(
-        MR.getTargetJITDylib().getExecutionSession(), LG, RegisterActionAddr);
+        LG, RegisterActionAddr);
     PassConfig.PrePrunePasses.push_back(
         [=](LinkGraph &G) { return MDOS->preserveDebugSections(); });
     PassConfig.PostPrunePasses.push_back(
         [=](LinkGraph &G) { return MDOS->startSynthesis(); });
-    PassConfig.PostFixupPasses.push_back(
+    PassConfig.PreFixupPasses.push_back(
         [=](LinkGraph &G) { return MDOS->completeSynthesisAndRegister(); });
   } else {
     LLVM_DEBUG({


        


More information about the llvm-commits mailing list