Skip to content

Add NT_SIGINFO NOTE to ELF dumps #83059

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 8, 2023
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
15 changes: 10 additions & 5 deletions src/coreclr/debug/createdump/crashinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ CrashInfo* g_crashInfo;

static bool ModuleInfoCompare(const ModuleInfo* lhs, const ModuleInfo* rhs) { return lhs->BaseAddress() < rhs->BaseAddress(); }

CrashInfo::CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t signal) :
CrashInfo::CrashInfo(const CreateDumpOptions& options) :
m_ref(1),
m_pid(pid),
m_pid(options.Pid),
m_ppid(-1),
m_hdac(nullptr),
m_pClrDataEnumRegions(nullptr),
m_pClrDataProcess(nullptr),
m_gatherFrames(gatherFrames),
m_crashThread(crashThread),
m_signal(signal),
m_gatherFrames(options.CrashReport),
m_crashThread(options.CrashThread),
m_signal(options.Signal),
m_moduleInfos(&ModuleInfoCompare),
m_mainModule(nullptr),
m_cbModuleMappings(0),
Expand All @@ -31,6 +31,11 @@ CrashInfo::CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t s
#else
m_auxvValues.fill(0);
m_fd = -1;
memset(&m_siginfo, 0, sizeof(m_siginfo));
m_siginfo.si_signo = options.Signal;
m_siginfo.si_code = options.SignalCode;
m_siginfo.si_errno = options.SignalErrno;
m_siginfo.si_addr = options.SignalAddress;
#endif
}

Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/debug/createdump/crashinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi
#ifdef __APPLE__
vm_map_t m_task; // the mach task for the process
#else
siginfo_t m_siginfo; // signal info (if any)
bool m_canUseProcVmReadSyscall;
int m_fd; // /proc/<pid>/mem handle
#endif
Expand All @@ -81,7 +82,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi
void operator=(const CrashInfo&) = delete;

public:
CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t signal);
CrashInfo(const CreateDumpOptions& options);
virtual ~CrashInfo();

// Memory usage stats
Expand Down Expand Up @@ -125,6 +126,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi
#ifndef __APPLE__
inline const std::vector<elf_aux_entry>& AuxvEntries() const { return m_auxvEntries; }
inline size_t GetAuxvSize() const { return m_auxvEntries.size() * sizeof(elf_aux_entry); }
inline const siginfo_t* SigInfo() const { return &m_siginfo; }
#endif

// IUnknown
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/debug/createdump/crashreportwriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,17 +175,17 @@ CrashReportWriter::WriteCrashReport()
}
CloseArray(); // threads
CloseObject(); // payload
#ifdef __APPLE__
OpenObject("parameters");
if (exceptionType != nullptr)
{
WriteValue("ExceptionType", exceptionType);
}
#ifdef __APPLE__
WriteSysctl("kern.osproductversion", "OSVersion");
WriteSysctl("hw.model", "SystemModel");
WriteValue("SystemManufacturer", "apple");
CloseObject(); // parameters
#endif // __APPLE__
CloseObject(); // parameters
}

#ifdef __APPLE__
Expand Down
26 changes: 22 additions & 4 deletions src/coreclr/debug/createdump/createdump.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ extern void trace_verbose_printf(const char* format, ...);
#define TRACE_VERBOSE(args, ...)
#endif

// Keep in sync with the definitions in dbgutil.cpp and daccess.h
#define DACCESS_TABLE_SYMBOL "g_dacTable"

#ifdef HOST_64BIT
#define PRIA "016"
#else
Expand Down Expand Up @@ -86,6 +89,24 @@ typedef int T_CONTEXT;
#include <vector>
#include <array>
#include <string>

typedef struct
{
const char* DumpPathTemplate;
const char* DumpType;
MINIDUMP_TYPE MinidumpType;
bool CreateDump;
bool CrashReport;
int Pid;
int CrashThread;
int Signal;
#if defined(HOST_UNIX) && !defined(HOST_OSX)
int SignalCode;
int SignalErrno;
void* SignalAddress;
#endif
} CreateDumpOptions;

#ifdef HOST_UNIX
#ifdef __APPLE__
#include <mach/mach.h>
Expand All @@ -106,12 +127,9 @@ typedef int T_CONTEXT;
#define MAX_LONGPATH 1024
#endif

extern bool CreateDump(const CreateDumpOptions& options);
extern bool FormatDumpName(std::string& name, const char* pattern, const char* exename, int pid);
extern bool CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP_TYPE minidumpType, bool createDump, bool crashReport, int crashThread, int signal);

extern std::string GetLastErrorString();
extern void printf_status(const char* format, ...);
extern void printf_error(const char* format, ...);

// Keep in sync with the definitions in dbgutil.cpp and daccess.h
#define DACCESS_TABLE_SYMBOL "g_dacTable"
26 changes: 13 additions & 13 deletions src/coreclr/debug/createdump/createdumpunix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ long g_pageSize = 0;
// The Linux/MacOS create dump code
//
bool
CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP_TYPE minidumpType, bool createDump, bool crashReport, int crashThread, int signal)
CreateDump(const CreateDumpOptions& options)
{
ReleaseHolder<CrashInfo> crashInfo = new CrashInfo(pid, crashReport, crashThread, signal);
ReleaseHolder<CrashInfo> crashInfo = new CrashInfo(options);
DumpWriter dumpWriter(*crashInfo);
std::string dumpPath;
bool result = false;
Expand All @@ -29,11 +29,11 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
{
goto exit;
}
printf_status("Gathering state for process %d %s\n", pid, crashInfo->Name().c_str());
printf_status("Gathering state for process %d %s\n", options.Pid, crashInfo->Name().c_str());

if (signal != 0 || crashThread != 0)
if (options.Signal != 0 || options.CrashThread != 0)
{
printf_status("Crashing thread %08x signal %08x\n", crashThread, signal);
printf_status("Crashing thread %04x signal %d (%04x)\n", options.CrashThread, options.Signal, options.Signal);
}

// Suspend all the threads in the target process and build the list of threads
Expand All @@ -42,32 +42,32 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
goto exit;
}
// Gather all the info about the process, threads (registers, etc.) and memory regions
if (!crashInfo->GatherCrashInfo(minidumpType))
if (!crashInfo->GatherCrashInfo(options.MinidumpType))
{
goto exit;
}
// Format the dump pattern template now that the process name on MacOS has been obtained
if (!FormatDumpName(dumpPath, dumpPathTemplate, crashInfo->Name().c_str(), pid))
if (!FormatDumpName(dumpPath, options.DumpPathTemplate, crashInfo->Name().c_str(), options.Pid))
{
goto exit;
}
// Write the crash report json file if enabled
if (crashReport)
if (options.CrashReport)
{
CrashReportWriter crashReportWriter(*crashInfo);
crashReportWriter.WriteCrashReport(dumpPath);
}
if (createDump)
if (options.CreateDump)
{
// Gather all the useful memory regions from the DAC
if (!crashInfo->EnumerateMemoryRegionsWithDAC(minidumpType))
if (!crashInfo->EnumerateMemoryRegionsWithDAC(options.MinidumpType))
{
goto exit;
}
// Join all adjacent memory regions
crashInfo->CombineMemoryRegions();

printf_status("Writing %s to file %s\n", dumpType, dumpPath.c_str());
printf_status("Writing %s to file %s\n", options.DumpType, dumpPath.c_str());

// Write the actual dump file
if (!dumpWriter.OpenDump(dumpPath.c_str()))
Expand All @@ -85,7 +85,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
}
result = true;
exit:
if (kill(pid, 0) == 0)
if (kill(options.Pid, 0) == 0)
{
printf_status("Target process is alive\n");
}
Expand All @@ -98,7 +98,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
}
else
{
printf_error("kill(%d, 0) FAILED %s (%d)\n", pid, strerror(err), err);
printf_error("kill(%d, 0) FAILED %s (%d)\n", options.Pid, strerror(err), err);
}
}
crashInfo->CleanupAndResumeProcess();
Expand Down
14 changes: 7 additions & 7 deletions src/coreclr/debug/createdump/createdumpwindows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ typedef struct _PROCESS_BASIC_INFORMATION_ {
// The Windows create dump code
//
bool
CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP_TYPE minidumpType, bool createDump, bool crashReport, int crashThread, int signal)
CreateDump(const CreateDumpOptions& options)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hProcess = NULL;
bool result = false;

_ASSERTE(createDump);
_ASSERTE(!crashReport);
_ASSERTE(options.CreateDump);
_ASSERTE(!options.CrashReport);

ArrayHolder<char> pszName = new char[MAX_LONGPATH + 1];
std::string dumpPath;
Expand All @@ -38,7 +38,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
printf_error("Failed to get parent process id status %d\n", status);
goto exit;
}
pid = (int)processInformation.InheritedFromUniqueProcessId;
int pid = (int)processInformation.InheritedFromUniqueProcessId;

hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (hProcess == NULL)
Expand All @@ -51,11 +51,11 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
printf_error("Get process name FAILED - %s\n", GetLastErrorString().c_str());
goto exit;
}
if (!FormatDumpName(dumpPath, dumpPathTemplate, pszName, pid))
if (!FormatDumpName(dumpPath, options.DumpPathTemplate, pszName, pid))
{
goto exit;
}
printf_status("Writing %s for process %d to file %s\n", dumpType, pid, dumpPath.c_str());
printf_status("Writing %s for process %d to file %s\n", options.DumpType, pid, dumpPath.c_str());

hFile = CreateFileA(dumpPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
Expand All @@ -67,7 +67,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
// Retry the write dump on ERROR_PARTIAL_COPY
for (int i = 0; i < 5; i++)
{
if (MiniDumpWriteDump(hProcess, pid, hFile, minidumpType, NULL, NULL, NULL))
if (MiniDumpWriteDump(hProcess, pid, hFile, options.MinidumpType, NULL, NULL, NULL))
{
result = true;
break;
Expand Down
33 changes: 27 additions & 6 deletions src/coreclr/debug/createdump/dumpwriterelf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ DumpWriter::WriteDump()
// Write all the thread's state and registers
for (const ThreadInfo* thread : m_crashInfo.Threads())
{
if (!WriteThread(*thread, SIGABRT)) {
if (!WriteThread(*thread)) {
return false;
}
}
Expand Down Expand Up @@ -358,13 +358,20 @@ DumpWriter::WriteNTFileInfo()
}

bool
DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal)
DumpWriter::WriteThread(const ThreadInfo& thread)
{
prstatus_t pr;
memset(&pr, 0, sizeof(pr));
const siginfo_t* siginfo = nullptr;

pr.pr_info.si_signo = fatal_signal;
pr.pr_cursig = fatal_signal;
if (m_crashInfo.Signal() != 0 && thread.IsCrashThread())
{
siginfo = m_crashInfo.SigInfo();
pr.pr_info.si_signo = siginfo->si_signo;
pr.pr_info.si_code = siginfo->si_code;
pr.pr_info.si_errno = siginfo->si_errno;
pr.pr_cursig = siginfo->si_signo;
}
pr.pr_pid = thread.Tid();
pr.pr_ppid = thread.Ppid();
pr.pr_pgrp = thread.Tgid();
Expand Down Expand Up @@ -395,9 +402,8 @@ DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal)
return false;
}

nhdr.n_namesz = 6;

#if defined(__i386__)
nhdr.n_namesz = 6;
nhdr.n_descsz = sizeof(user_fpxregs_struct);
nhdr.n_type = NT_PRXFPREG;
if (!WriteData(&nhdr, sizeof(nhdr)) ||
Expand All @@ -408,6 +414,7 @@ DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal)
#endif

#if defined(__arm__) && defined(__VFP_FP__) && !defined(__SOFTFP__)
nhdr.n_namesz = 6;
nhdr.n_descsz = sizeof(user_vfpregs_struct);
nhdr.n_type = NT_ARM_VFP;
if (!WriteData(&nhdr, sizeof(nhdr)) ||
Expand All @@ -417,5 +424,19 @@ DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal)
}
#endif

if (siginfo != nullptr)
{
TRACE("Writing NT_SIGINFO tid %04x signo %d (%04x) code %04x errno %04x addr %p\n",
thread.Tid(), siginfo->si_signo, siginfo->si_signo, siginfo->si_code, siginfo->si_errno, siginfo->si_addr);

nhdr.n_namesz = 5;
nhdr.n_descsz = sizeof(siginfo_t);
nhdr.n_type = NT_SIGINFO;
if (!WriteData(&nhdr, sizeof(nhdr)) ||
!WriteData("CORE\0SIG", 8) ||
!WriteData(siginfo, sizeof(siginfo_t))) {
return false;
}
}
return true;
}
17 changes: 11 additions & 6 deletions src/coreclr/debug/createdump/dumpwriterelf.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
#define NT_FILE 0x46494c45
#endif

#ifndef NT_SIGINFO
#define NT_SIGINFO 0x53494749
#endif

class DumpWriter
{
private:
Expand All @@ -54,21 +58,22 @@ class DumpWriter
bool WriteAuxv();
size_t GetNTFileInfoSize(size_t* alignmentBytes = nullptr);
bool WriteNTFileInfo();
bool WriteThread(const ThreadInfo& thread, int fatal_signal);
bool WriteThread(const ThreadInfo& thread);
bool WriteData(const void* buffer, size_t length) { return WriteData(m_fd, buffer, length); }

size_t GetProcessInfoSize() const { return sizeof(Nhdr) + 8 + sizeof(prpsinfo_t); }
size_t GetAuxvInfoSize() const { return sizeof(Nhdr) + 8 + m_crashInfo.GetAuxvSize(); }
size_t GetThreadInfoSize() const
{
return m_crashInfo.Threads().size() * ((sizeof(Nhdr) + 8 + sizeof(prstatus_t))
+ sizeof(Nhdr) + 8 + sizeof(user_fpregs_struct)
return (m_crashInfo.Signal() != 0 ? (sizeof(Nhdr) + 8 + sizeof(siginfo_t)) : 0)
+ (m_crashInfo.Threads().size() * ((sizeof(Nhdr) + 8 + sizeof(prstatus_t))
+ (sizeof(Nhdr) + 8 + sizeof(user_fpregs_struct))
#if defined(__i386__)
+ sizeof(Nhdr) + 8 + sizeof(user_fpxregs_struct)
+ (sizeof(Nhdr) + 8 + sizeof(user_fpxregs_struct))
#endif
#if defined(__arm__) && defined(__VFP_FP__) && !defined(__SOFTFP__)
+ sizeof(Nhdr) + 8 + sizeof(user_vfpregs_struct)
+ (sizeof(Nhdr) + 8 + sizeof(user_vfpregs_struct))
#endif
);
));
}
};
Loading