19 #define DEBUG_TYPE "orc"
39 static constexpr
const uint32_t SegmentCmd = MachO::LC_SEGMENT_64;
42 class MachODebugObjectSynthesizerBase
50 :
G(
G), RegisterActionAddr(RegisterActionAddr) {}
51 virtual ~MachODebugObjectSynthesizerBase() =
default;
53 Error preserveDebugSections() {
56 dbgs() <<
"MachODebugObjectSynthesizer skipping graph " <<
G.getName()
57 <<
" which contains an unexpected existing "
64 dbgs() <<
"MachODebugObjectSynthesizer visiting graph " <<
G.getName()
67 for (
auto &Sec :
G.sections()) {
74 dbgs() <<
" Preserving debug section " << Sec.
getName() <<
"\n";
77 for (
auto *Sym : Sec.
symbols()) {
78 bool NewPreservedBlock =
79 PreservedBlocks.
insert(&Sym->getBlock()).second;
80 if (NewPreservedBlock)
84 if (!PreservedBlocks.count(
B))
85 G.addAnonymousSymbol(*
B, 0, 0,
false,
true);
95 template <
typename MachOTraits>
96 class MachODebugObjectSynthesizer :
public MachODebugObjectSynthesizerBase {
98 class MachOStructWriter {
102 size_t getOffset()
const {
return Offset; }
104 template <
typename MachOStruct>
void write(MachOStruct
S) {
106 "Container block overflow while constructing debug MachO");
119 using MachODebugObjectSynthesizerBase::MachODebugObjectSynthesizerBase;
121 Error startSynthesis()
override {
128 struct DebugSectionInfo {
138 size_t NumSections = 0;
139 for (
auto &Sec :
G.sections()) {
145 size_t SepPos = Sec.getName().find(
',');
146 if (SepPos > 16 || (Sec.getName().size() - (SepPos + 1) > 16)) {
148 dbgs() <<
"Skipping debug object synthesis for graph "
150 <<
": encountered non-standard DWARF section name \""
151 << Sec.getName() <<
"\"\n";
155 DebugSecInfos.push_back({&Sec, Sec.getName().substr(0, SepPos),
156 Sec.getName().substr(SepPos + 1), 0,
159 NonDebugSections.push_back(&Sec);
166 auto &FB = *R.getFirstBlock();
167 if (FB.getAlignmentOffset() != 0) {
168 auto Padding =
G.allocateBuffer(FB.getAlignmentOffset());
169 memset(Padding.data(), 0, Padding.size());
170 G.createContentBlock(Sec, Padding,
171 FB.getAddress() - FB.getAlignmentOffset(),
172 FB.getAlignment(), 0);
179 size_t SectionsCmdSize =
181 size_t SegmentLCSize =
182 sizeof(
typename MachOTraits::SegmentLC) + SectionsCmdSize;
183 size_t ContainerBlockSize =
184 sizeof(
typename MachOTraits::Header) + SegmentLCSize;
185 auto ContainerBlockContent =
G.allocateBuffer(ContainerBlockSize);
186 MachOContainerBlock = &
G.createMutableContentBlock(
191 for (
auto &
SI : DebugSecInfos) {
196 dbgs() <<
" Appending " <<
SI.Sec->getName() <<
" ("
197 <<
SI.Sec->blocks_size() <<
" block(s)) at "
198 <<
formatv(
"{0:x8}", NextBlockAddr) <<
"\n";
200 for (
auto *
B :
SI.Sec->blocks()) {
202 B->setAddress(NextBlockAddr);
203 NextBlockAddr +=
B->getSize();
206 auto &FirstBlock = **
SI.Sec->blocks().begin();
207 if (FirstBlock.getAlignmentOffset() != 0)
208 return make_error<StringError>(
209 "First block in " +
SI.Sec->getName() +
210 " section has non-zero alignment offset",
213 return make_error<StringError>(
"First block in " +
SI.Sec->getName() +
214 " has alignment >4Gb",
217 SI.Alignment = FirstBlock.getAlignment();
218 SI.StartAddr = FirstBlock.getAddress();
219 SI.Size = NextBlockAddr -
SI.StartAddr;
220 G.mergeSections(SDOSec, *
SI.Sec);
223 size_t DebugSectionsSize =
227 MachOStructWriter Writer(MachOContainerBlock->getAlreadyMutableContent());
228 typename MachOTraits::Header Hdr;
229 memset(&Hdr, 0,
sizeof(Hdr));
231 switch (
G.getTargetTriple().getArch()) {
245 Hdr.sizeofcmds = SegmentLCSize;
249 typename MachOTraits::SegmentLC SegLC;
250 memset(&SegLC, 0,
sizeof(SegLC));
251 SegLC.cmd = MachOTraits::SegmentCmd;
252 SegLC.cmdsize = SegmentLCSize;
253 SegLC.vmaddr = ContainerBlockSize;
254 SegLC.vmsize = DebugSectionsSize;
255 SegLC.fileoff = ContainerBlockSize;
256 SegLC.filesize = DebugSectionsSize;
261 SegLC.nsects = NumSections;
266 for (
auto &
SI : DebugSecInfos) {
268 memset(&Sec, 0,
sizeof(Sec));
269 memcpy(Sec.sectname,
SI.SecName.data(),
SI.SecName.size());
270 memcpy(Sec.segname,
SI.SegName.data(),
SI.SegName.size());
271 Sec.addr =
SI.StartAddr.getValue();
273 Sec.offset =
SI.StartAddr.getValue();
274 Sec.align =
SI.Alignment;
283 NonDebugSectionsStart = Writer.getOffset();
287 Error completeSynthesisAndRegister()
override {
288 if (!MachOContainerBlock) {
290 dbgs() <<
"Not writing MachO debug object header for " <<
G.getName()
291 <<
" since createDebugSection failed\n";
297 dbgs() <<
"Writing MachO debug object header for " <<
G.getName() <<
"\n";
300 MachOStructWriter Writer(
301 MachOContainerBlock->getAlreadyMutableContent().drop_front(
302 NonDebugSectionsStart));
304 unsigned LongSectionNameIdx = 0;
305 for (
auto *Sec : NonDebugSections) {
306 size_t SepPos = Sec->getName().find(
',');
308 std::string CustomSecName;
312 SegName =
"__JITLINK_CUSTOM";
313 SecName = Sec->getName();
314 }
else if (SepPos < 16 && (Sec->getName().size() - (SepPos + 1) <= 16)) {
316 SegName = Sec->getName().
substr(0, SepPos);
317 SecName = Sec->getName().
substr(SepPos + 1);
320 assert(Sec->getName().size() > 16 &&
321 "Short section name should have been handled above");
322 SegName =
"__JITLINK_CUSTOM";
324 CustomSecName = Sec->getName().substr(0, 15 - IdxStr.size()).str();
325 CustomSecName +=
".";
326 CustomSecName += IdxStr;
327 SecName =
StringRef(CustomSecName.data(), 16);
331 if (R.getFirstBlock()->getAlignmentOffset() != 0)
332 return make_error<StringError>(
333 "While building MachO debug object for " +
G.getName() +
334 " first block has non-zero alignment offset",
338 memset(&SecCmd, 0,
sizeof(SecCmd));
341 SecCmd.addr = R.getStart().getValue();
342 SecCmd.size = R.getSize();
344 SecCmd.align = R.getFirstBlock()->getAlignment();
348 Writer.write(SecCmd);
352 G.allocActions().push_back(
353 {
cantFail(shared::WrapperFunctionCall::Create<
355 RegisterActionAddr, R.getRange())),
361 Block *MachOContainerBlock =
nullptr;
363 size_t NonDebugSectionsStart = 0;
375 auto RegisterActionAddr =
376 TT.isOSBinFormatMachO()
377 ? ES.
intern(
"_llvm_orc_registerJITLoaderGDBAllocAction")
378 : ES.
intern(
"llvm_orc_registerJITLoaderGDBAllocAction");
380 if (
auto Addr = ES.
lookup({&ProcessJD}, RegisterActionAddr))
381 return std::make_unique<GDBJITDebugInfoRegistrationPlugin>(
384 return Addr.takeError();
387 Error GDBJITDebugInfoRegistrationPlugin::notifyFailed(
392 Error GDBJITDebugInfoRegistrationPlugin::notifyRemovingResources(
397 void GDBJITDebugInfoRegistrationPlugin::notifyTransferringResources(
400 void GDBJITDebugInfoRegistrationPlugin::modifyPassConfig(
405 modifyPassConfigForMachO(MR, LG, PassConfig);
408 dbgs() <<
"GDBJITDebugInfoRegistrationPlugin skipping unspported graph "
415 void GDBJITDebugInfoRegistrationPlugin::modifyPassConfigForMachO(
425 "Graph has incorrect endianness");
430 dbgs() <<
"GDBJITDebugInfoRegistrationPlugin skipping unsupported "
431 <<
"MachO graph " << LG.
getName()
433 <<
", pointer size = " << LG.
getPointerSize() <<
", endianness = "
441 bool HasDebugSections =
false;
444 HasDebugSections =
true;
448 if (HasDebugSections) {
450 dbgs() <<
"GDBJITDebugInfoRegistrationPlugin: Graph " << LG.
getName()
451 <<
" contains debug info. Installing debugger support passes.\n";
454 auto MDOS = std::make_shared<MachODebugObjectSynthesizer<MachO64LE>>(
455 LG, RegisterActionAddr);
457 [=](
LinkGraph &
G) {
return MDOS->preserveDebugSections(); });
459 [=](
LinkGraph &
G) {
return MDOS->startSynthesis(); });
461 [=](
LinkGraph &
G) {
return MDOS->completeSynthesisAndRegister(); });
464 dbgs() <<
"GDBJITDebugInfoRegistrationPlugin: Graph " << LG.getName()
465 <<
" contains no debug info. Skipping.\n";