23#define DEBUG_TYPE "orc"
33class MachODebugObjectSynthesizerBase
41 :
G(
G), RegisterActionAddr(RegisterActionAddr) {}
42 ~MachODebugObjectSynthesizerBase()
override =
default;
47 dbgs() <<
"MachODebugObjectSynthesizer skipping graph " <<
G.getName()
48 <<
" which contains an unexpected existing "
55 dbgs() <<
"MachODebugObjectSynthesizer visiting graph " <<
G.getName()
58 for (
auto &Sec :
G.sections()) {
65 dbgs() <<
" Preserving debug section " << Sec.
getName() <<
"\n";
68 for (
auto *Sym : Sec.
symbols()) {
69 bool NewPreservedBlock =
70 PreservedBlocks.insert(&Sym->getBlock()).second;
71 if (NewPreservedBlock)
75 if (!PreservedBlocks.count(
B))
76 G.addAnonymousSymbol(*
B, 0, 0,
false,
true);
87template <
typename MachOTraits>
88class MachODebugObjectSynthesizer :
public MachODebugObjectSynthesizerBase {
92 : MachODebugObjectSynthesizerBase(
G, RegisterActionAddr),
95 using MachODebugObjectSynthesizerBase::MachODebugObjectSynthesizerBase;
97 Error startSynthesis()
override {
103 for (
auto &Sec :
G.sections()) {
104 if (Sec.blocks().empty())
108 if (Sec.getName().empty() || Sec.getName().size() > 33 ||
109 Sec.getName().find(
',') > 16)
113 DebugSections.push_back({&Sec,
nullptr});
115 NonDebugSections.push_back({&Sec,
nullptr});
119 if (DebugSections.empty())
125 Builder.Header.cputype = *CPUType;
127 return CPUType.takeError();
129 Builder.Header.cpusubtype = *CPUSubType;
131 return CPUSubType.takeError();
133 Seg = &Builder.addSegment(
"");
137 for (
auto &DSec : DebugSections) {
138 auto [SegName, SecName] = DSec.GraphSec->getName().split(
',');
139 DSec.BuilderSec = &Seg->addSection(SecName, SegName);
142 DSec.BuilderSec->Content.Size = SR.
getSize();
147 DebugSectionMap[SecName.drop_front(2)] =
149 if (SecName ==
"__debug_line")
150 DebugLineSectionData = SectionData;
154 std::optional<StringRef> FileName;
155 if (!DebugLineSectionData.
empty()) {
158 "G.getEndianness() must be either big or little");
172 dbgs() <<
"Cannot parse line table for \"" <<
G.getName() <<
"\": ";
178 for (
auto &FN :
P.FileNames)
181 dbgs() <<
"Using FileName = \"" << *FileName
182 <<
"\" from DWARF line table\n";
193 dbgs() <<
"Could not find source name from DWARF line table. "
194 "Using FileName = \"\"\n";
200 Builder.addSymbol(*FileName,
MachO::N_SO, 0, 0, 0);
201 auto TimeStamp = std::chrono::duration_cast<std::chrono::seconds>(
202 std::chrono::system_clock::now().time_since_epoch())
206 for (
auto &NDSP : NonDebugSections) {
207 auto [SegName, SecName] = NDSP.GraphSec->getName().split(
',');
208 NDSP.BuilderSec = &Seg->addSection(SecName, SegName);
214 for (
auto *Sym : NDSP.GraphSec->symbols()) {
222 StabSymbols.push_back(
223 {*Sym, Builder.addSymbol(*Sym->getName(), SymType, 1, 0, 0),
224 Builder.addSymbol(*Sym->getName(), SymType, 0, 0, 0)});
232 size_t DebugObjectSize = Builder.layout();
235 MachOContainerBlock = &
G.createMutableContentBlock(
241 Error completeSynthesisAndRegister()
override {
242 if (!MachOContainerBlock) {
244 dbgs() <<
"Not writing MachO debug object header for " <<
G.getName()
245 <<
" since createDebugSection failed\n";
251 for (
auto &NDSec : NonDebugSections) {
254 NDSec.BuilderSec->size = SR.
getSize();
256 if (SR.
getEnd() > MaxAddr)
260 for (
auto &DSec : DebugSections) {
261 if (DSec.GraphSec->blocks_size() != 1)
263 "Unexpected number of blocks in debug info section",
266 if (
ExecutorAddr(DSec.BuilderSec->addr) + DSec.BuilderSec->size > MaxAddr)
267 MaxAddr =
ExecutorAddr(DSec.BuilderSec->addr) + DSec.BuilderSec->size;
269 auto &
B = **DSec.GraphSec->blocks().begin();
270 DSec.BuilderSec->Content.Data =
B.getContent().data();
271 DSec.BuilderSec->Content.Size =
B.getContent().size();
276 dbgs() <<
"Writing MachO debug object header for " <<
G.getName() <<
"\n";
280 for (
auto &SS : StabSymbols) {
281 SS.StartStab.nlist().n_value = SS.Sym.getAddress().getValue();
282 SS.EndStab.nlist().n_value = SS.Sym.getSize();
285 Builder.write(MachOContainerBlock->getAlreadyMutableContent());
288 G.allocActions().push_back(
291 RegisterActionAddr, R.getRange())),
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>>
333 if (
auto RegisterSym = ES.
lookup({&BootstrapJD}, RegisterActionName))
334 return std::make_unique<GDBJITDebugInfoRegistrationPlugin>(
335 RegisterSym->getAddress());
337 return RegisterSym.takeError();
358 modifyPassConfigForMachO(MR, LG, PassConfig);
361 dbgs() <<
"GDBJITDebugInfoRegistrationPlugin skipping unspported graph "
368void GDBJITDebugInfoRegistrationPlugin::modifyPassConfigForMachO(
378 "Graph has incorrect endianness");
383 dbgs() <<
"GDBJITDebugInfoRegistrationPlugin skipping unsupported "
384 <<
"MachO graph " << LG.
getName()
386 <<
", pointer size = " << LG.
getPointerSize() <<
", endianness = "
394 bool HasDebugSections =
false;
396 if (MachODebugObjectSynthesizerBase::isDebugSection(Sec)) {
397 HasDebugSections =
true;
401 if (HasDebugSections) {
403 dbgs() <<
"GDBJITDebugInfoRegistrationPlugin: Graph " << LG.
getName()
404 <<
" contains debug info. Installing debugger support passes.\n";
407 auto MDOS = std::make_shared<MachODebugObjectSynthesizer<MachO64LE>>(
410 [=](LinkGraph &
G) {
return MDOS->preserveDebugSections(); });
412 [=](LinkGraph &
G) {
return MDOS->startSynthesis(); });
414 [=](LinkGraph &
G) {
return MDOS->completeSynthesisAndRegister(); });
417 dbgs() <<
"GDBJITDebugInfoRegistrationPlugin: Graph " << LG.
getName()
418 <<
" 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",...
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
Check if the string is empty.
size_t count(char C) const
Return the number of occurrences of C in the string.
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
void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override
static Expected< std::unique_ptr< GDBJITDebugInfoRegistrationPlugin > > Create(ExecutionSession &ES, JITDylib &BootstrapJD)
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 const char * RegisterJITLoaderGDBAllocActionName
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.