[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