Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/coreclr/debug/createdump/dumpwritermacho.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ DumpWriter::WriteDump()

BuildThreadLoadCommands();

BuildProcessMetadataNote();

uint64_t fileOffset = 0;
if (!WriteHeader(&fileOffset)) {
return false;
}

m_processMetadataNote.offset = fileOffset;
fileOffset += m_processMetadataNote.size;

TRACE("Writing %zd thread commands to core file\n", m_threadLoadCommands.size());

// Write thread commands
Expand Down Expand Up @@ -54,6 +59,14 @@ DumpWriter::WriteDump()
}
}

// Write the process metadata note as the final load command
if (!WriteData(&m_processMetadataNote, m_processMetadataNote.cmdsize)) {
return false;
}
if (!WriteData(m_processMetadata.data(), m_processMetadata.size())) {
return false;
}

// Write any segment alignment required to the core file
if (alignment > 0)
{
Expand Down Expand Up @@ -87,6 +100,33 @@ ConvertFlags(uint32_t flags)
return prot;
}

void
DumpWriter::BuildProcessMetadataNote()
{
// LLDB specifies the "process metadata" LC_NOTE as compact JSON whose
// thread entries correspond by position to the LC_THREAD commands.
m_processMetadata = "{\"threads\":[";
bool first = true;
for (const ThreadInfo* thread : m_crashInfo.Threads())
{
if (!first)
{
m_processMetadata.push_back(',');
}
first = false;
m_processMetadata.append("{\"thread_id\":");
m_processMetadata.append(std::to_string(thread->Tid()));
m_processMetadata.push_back('}');
}
m_processMetadata.append("]}");

m_processMetadataNote.cmd = LC_NOTE;
m_processMetadataNote.cmdsize = sizeof(note_command);
static_assert(sizeof(m_processMetadataNote.data_owner) == sizeof("process metadata") - 1);
memcpy(m_processMetadataNote.data_owner, "process metadata", sizeof(m_processMetadataNote.data_owner));
m_processMetadataNote.size = m_processMetadata.size();
}

void
DumpWriter::BuildSegmentLoadCommands()
{
Expand Down Expand Up @@ -190,6 +230,9 @@ DumpWriter::WriteHeader(uint64_t* pFileOffset)
header.sizeofcmds += segment.cmdsize;
}

header.ncmds++;
header.sizeofcmds += m_processMetadataNote.cmdsize;

*pFileOffset = sizeof(mach_header_64) + header.sizeofcmds;

TRACE("Macho header: magic %08x cputype %08x cpusubtype %08x filetype %08x ncmds %08x sizeofcmds %08x flags %08x reserved %08x\n",
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/debug/createdump/dumpwritermacho.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class DumpWriter

std::vector<segment_command_64> m_segmentLoadCommands;
std::vector<ThreadCommand> m_threadLoadCommands;
note_command m_processMetadataNote{};
std::string m_processMetadata;
BYTE m_tempBuffer[0x4000];

// no public copy constructor
Expand All @@ -43,6 +45,7 @@ class DumpWriter

private:
bool WriteDiagInfo(size_t size);
void BuildProcessMetadataNote();
void BuildSegmentLoadCommands();
void BuildThreadLoadCommands();
bool WriteHeader(uint64_t* pFileOffset);
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/debug/createdump/specialthreadinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@

#define SPECIAL_THREADINFO_SIGNATURE "THREADINFO"

#if defined(HOST_ARM64) || defined(__arm64__) || defined(__aarch64__)
// Apple Silicon (arm64) macOS user-space VM is 47 bits. lldb's core reader
// rejects segments above 0x7FFF_FFFF_FFFF, so use a 47-bit-valid address.
const uint64_t SpecialThreadInfoAddress = 0x00007ffffff00000;
#else
const uint64_t SpecialThreadInfoAddress = 0x7fffffff00000000;
#endif

struct SpecialThreadInfoHeader
{
Expand Down
Loading