Skip to content

Commit dbb333c

Browse files
author
Mike McLaughlin
authored
Add NT_SIGINFO NOTE to ELF dumps (#83059)
Linux Watson needs this to better triage ELF dumps. Add CreateDumpOptions helper struct to pass all the command options around. Add the "--code", "--errno", "--address" command line options used to fill the NT_SIGINFO NOTE. The runtime passes to createdump on a crash. Added "ExceptionType" field to "Parameters" section of the Linux crash report json.
1 parent b524e93 commit dbb333c

File tree

14 files changed

+241
-111
lines changed

14 files changed

+241
-111
lines changed

src/coreclr/debug/createdump/crashinfo.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ CrashInfo* g_crashInfo;
99

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

12-
CrashInfo::CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t signal) :
12+
CrashInfo::CrashInfo(const CreateDumpOptions& options) :
1313
m_ref(1),
14-
m_pid(pid),
14+
m_pid(options.Pid),
1515
m_ppid(-1),
1616
m_hdac(nullptr),
1717
m_pClrDataEnumRegions(nullptr),
1818
m_pClrDataProcess(nullptr),
19-
m_gatherFrames(gatherFrames),
20-
m_crashThread(crashThread),
21-
m_signal(signal),
19+
m_gatherFrames(options.CrashReport),
20+
m_crashThread(options.CrashThread),
21+
m_signal(options.Signal),
2222
m_moduleInfos(&ModuleInfoCompare),
2323
m_mainModule(nullptr),
2424
m_cbModuleMappings(0),
@@ -31,6 +31,11 @@ CrashInfo::CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t s
3131
#else
3232
m_auxvValues.fill(0);
3333
m_fd = -1;
34+
memset(&m_siginfo, 0, sizeof(m_siginfo));
35+
m_siginfo.si_signo = options.Signal;
36+
m_siginfo.si_code = options.SignalCode;
37+
m_siginfo.si_errno = options.SignalErrno;
38+
m_siginfo.si_addr = options.SignalAddress;
3439
#endif
3540
}
3641

src/coreclr/debug/createdump/crashinfo.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi
5757
#ifdef __APPLE__
5858
vm_map_t m_task; // the mach task for the process
5959
#else
60+
siginfo_t m_siginfo; // signal info (if any)
6061
bool m_canUseProcVmReadSyscall;
6162
int m_fd; // /proc/<pid>/mem handle
6263
#endif
@@ -81,7 +82,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi
8182
void operator=(const CrashInfo&) = delete;
8283

8384
public:
84-
CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t signal);
85+
CrashInfo(const CreateDumpOptions& options);
8586
virtual ~CrashInfo();
8687

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

130132
// IUnknown

src/coreclr/debug/createdump/crashreportwriter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,17 +175,17 @@ CrashReportWriter::WriteCrashReport()
175175
}
176176
CloseArray(); // threads
177177
CloseObject(); // payload
178-
#ifdef __APPLE__
179178
OpenObject("parameters");
180179
if (exceptionType != nullptr)
181180
{
182181
WriteValue("ExceptionType", exceptionType);
183182
}
183+
#ifdef __APPLE__
184184
WriteSysctl("kern.osproductversion", "OSVersion");
185185
WriteSysctl("hw.model", "SystemModel");
186186
WriteValue("SystemManufacturer", "apple");
187-
CloseObject(); // parameters
188187
#endif // __APPLE__
188+
CloseObject(); // parameters
189189
}
190190

191191
#ifdef __APPLE__

src/coreclr/debug/createdump/createdump.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ extern void trace_verbose_printf(const char* format, ...);
2020
#define TRACE_VERBOSE(args, ...)
2121
#endif
2222

23+
// Keep in sync with the definitions in dbgutil.cpp and daccess.h
24+
#define DACCESS_TABLE_SYMBOL "g_dacTable"
25+
2326
#ifdef HOST_64BIT
2427
#define PRIA "016"
2528
#else
@@ -86,6 +89,24 @@ typedef int T_CONTEXT;
8689
#include <vector>
8790
#include <array>
8891
#include <string>
92+
93+
typedef struct
94+
{
95+
const char* DumpPathTemplate;
96+
const char* DumpType;
97+
MINIDUMP_TYPE MinidumpType;
98+
bool CreateDump;
99+
bool CrashReport;
100+
int Pid;
101+
int CrashThread;
102+
int Signal;
103+
#if defined(HOST_UNIX) && !defined(HOST_OSX)
104+
int SignalCode;
105+
int SignalErrno;
106+
void* SignalAddress;
107+
#endif
108+
} CreateDumpOptions;
109+
89110
#ifdef HOST_UNIX
90111
#ifdef __APPLE__
91112
#include <mach/mach.h>
@@ -106,12 +127,9 @@ typedef int T_CONTEXT;
106127
#define MAX_LONGPATH 1024
107128
#endif
108129

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

112133
extern std::string GetLastErrorString();
113134
extern void printf_status(const char* format, ...);
114135
extern void printf_error(const char* format, ...);
115-
116-
// Keep in sync with the definitions in dbgutil.cpp and daccess.h
117-
#define DACCESS_TABLE_SYMBOL "g_dacTable"

src/coreclr/debug/createdump/createdumpunix.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ long g_pageSize = 0;
1111
// The Linux/MacOS create dump code
1212
//
1313
bool
14-
CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP_TYPE minidumpType, bool createDump, bool crashReport, int crashThread, int signal)
14+
CreateDump(const CreateDumpOptions& options)
1515
{
16-
ReleaseHolder<CrashInfo> crashInfo = new CrashInfo(pid, crashReport, crashThread, signal);
16+
ReleaseHolder<CrashInfo> crashInfo = new CrashInfo(options);
1717
DumpWriter dumpWriter(*crashInfo);
1818
std::string dumpPath;
1919
bool result = false;
@@ -29,11 +29,11 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
2929
{
3030
goto exit;
3131
}
32-
printf_status("Gathering state for process %d %s\n", pid, crashInfo->Name().c_str());
32+
printf_status("Gathering state for process %d %s\n", options.Pid, crashInfo->Name().c_str());
3333

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

3939
// Suspend all the threads in the target process and build the list of threads
@@ -42,32 +42,32 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
4242
goto exit;
4343
}
4444
// Gather all the info about the process, threads (registers, etc.) and memory regions
45-
if (!crashInfo->GatherCrashInfo(minidumpType))
45+
if (!crashInfo->GatherCrashInfo(options.MinidumpType))
4646
{
4747
goto exit;
4848
}
4949
// Format the dump pattern template now that the process name on MacOS has been obtained
50-
if (!FormatDumpName(dumpPath, dumpPathTemplate, crashInfo->Name().c_str(), pid))
50+
if (!FormatDumpName(dumpPath, options.DumpPathTemplate, crashInfo->Name().c_str(), options.Pid))
5151
{
5252
goto exit;
5353
}
5454
// Write the crash report json file if enabled
55-
if (crashReport)
55+
if (options.CrashReport)
5656
{
5757
CrashReportWriter crashReportWriter(*crashInfo);
5858
crashReportWriter.WriteCrashReport(dumpPath);
5959
}
60-
if (createDump)
60+
if (options.CreateDump)
6161
{
6262
// Gather all the useful memory regions from the DAC
63-
if (!crashInfo->EnumerateMemoryRegionsWithDAC(minidumpType))
63+
if (!crashInfo->EnumerateMemoryRegionsWithDAC(options.MinidumpType))
6464
{
6565
goto exit;
6666
}
6767
// Join all adjacent memory regions
6868
crashInfo->CombineMemoryRegions();
6969

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

7272
// Write the actual dump file
7373
if (!dumpWriter.OpenDump(dumpPath.c_str()))
@@ -85,7 +85,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
8585
}
8686
result = true;
8787
exit:
88-
if (kill(pid, 0) == 0)
88+
if (kill(options.Pid, 0) == 0)
8989
{
9090
printf_status("Target process is alive\n");
9191
}
@@ -98,7 +98,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
9898
}
9999
else
100100
{
101-
printf_error("kill(%d, 0) FAILED %s (%d)\n", pid, strerror(err), err);
101+
printf_error("kill(%d, 0) FAILED %s (%d)\n", options.Pid, strerror(err), err);
102102
}
103103
}
104104
crashInfo->CleanupAndResumeProcess();

src/coreclr/debug/createdump/createdumpwindows.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ typedef struct _PROCESS_BASIC_INFORMATION_ {
1818
// The Windows create dump code
1919
//
2020
bool
21-
CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP_TYPE minidumpType, bool createDump, bool crashReport, int crashThread, int signal)
21+
CreateDump(const CreateDumpOptions& options)
2222
{
2323
HANDLE hFile = INVALID_HANDLE_VALUE;
2424
HANDLE hProcess = NULL;
2525
bool result = false;
2626

27-
_ASSERTE(createDump);
28-
_ASSERTE(!crashReport);
27+
_ASSERTE(options.CreateDump);
28+
_ASSERTE(!options.CrashReport);
2929

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

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

6060
hFile = CreateFileA(dumpPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
6161
if (hFile == INVALID_HANDLE_VALUE)
@@ -67,7 +67,7 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP
6767
// Retry the write dump on ERROR_PARTIAL_COPY
6868
for (int i = 0; i < 5; i++)
6969
{
70-
if (MiniDumpWriteDump(hProcess, pid, hFile, minidumpType, NULL, NULL, NULL))
70+
if (MiniDumpWriteDump(hProcess, pid, hFile, options.MinidumpType, NULL, NULL, NULL))
7171
{
7272
result = true;
7373
break;

src/coreclr/debug/createdump/dumpwriterelf.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ DumpWriter::WriteDump()
148148
// Write all the thread's state and registers
149149
for (const ThreadInfo* thread : m_crashInfo.Threads())
150150
{
151-
if (!WriteThread(*thread, SIGABRT)) {
151+
if (!WriteThread(*thread)) {
152152
return false;
153153
}
154154
}
@@ -358,13 +358,20 @@ DumpWriter::WriteNTFileInfo()
358358
}
359359

360360
bool
361-
DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal)
361+
DumpWriter::WriteThread(const ThreadInfo& thread)
362362
{
363363
prstatus_t pr;
364364
memset(&pr, 0, sizeof(pr));
365+
const siginfo_t* siginfo = nullptr;
365366

366-
pr.pr_info.si_signo = fatal_signal;
367-
pr.pr_cursig = fatal_signal;
367+
if (m_crashInfo.Signal() != 0 && thread.IsCrashThread())
368+
{
369+
siginfo = m_crashInfo.SigInfo();
370+
pr.pr_info.si_signo = siginfo->si_signo;
371+
pr.pr_info.si_code = siginfo->si_code;
372+
pr.pr_info.si_errno = siginfo->si_errno;
373+
pr.pr_cursig = siginfo->si_signo;
374+
}
368375
pr.pr_pid = thread.Tid();
369376
pr.pr_ppid = thread.Ppid();
370377
pr.pr_pgrp = thread.Tgid();
@@ -395,9 +402,8 @@ DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal)
395402
return false;
396403
}
397404

398-
nhdr.n_namesz = 6;
399-
400405
#if defined(__i386__)
406+
nhdr.n_namesz = 6;
401407
nhdr.n_descsz = sizeof(user_fpxregs_struct);
402408
nhdr.n_type = NT_PRXFPREG;
403409
if (!WriteData(&nhdr, sizeof(nhdr)) ||
@@ -408,6 +414,7 @@ DumpWriter::WriteThread(const ThreadInfo& thread, int fatal_signal)
408414
#endif
409415

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

427+
if (siginfo != nullptr)
428+
{
429+
TRACE("Writing NT_SIGINFO tid %04x signo %d (%04x) code %04x errno %04x addr %p\n",
430+
thread.Tid(), siginfo->si_signo, siginfo->si_signo, siginfo->si_code, siginfo->si_errno, siginfo->si_addr);
431+
432+
nhdr.n_namesz = 5;
433+
nhdr.n_descsz = sizeof(siginfo_t);
434+
nhdr.n_type = NT_SIGINFO;
435+
if (!WriteData(&nhdr, sizeof(nhdr)) ||
436+
!WriteData("CORE\0SIG", 8) ||
437+
!WriteData(siginfo, sizeof(siginfo_t))) {
438+
return false;
439+
}
440+
}
420441
return true;
421442
}

src/coreclr/debug/createdump/dumpwriterelf.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
#define NT_FILE 0x46494c45
3232
#endif
3333

34+
#ifndef NT_SIGINFO
35+
#define NT_SIGINFO 0x53494749
36+
#endif
37+
3438
class DumpWriter
3539
{
3640
private:
@@ -54,21 +58,22 @@ class DumpWriter
5458
bool WriteAuxv();
5559
size_t GetNTFileInfoSize(size_t* alignmentBytes = nullptr);
5660
bool WriteNTFileInfo();
57-
bool WriteThread(const ThreadInfo& thread, int fatal_signal);
61+
bool WriteThread(const ThreadInfo& thread);
5862
bool WriteData(const void* buffer, size_t length) { return WriteData(m_fd, buffer, length); }
5963

6064
size_t GetProcessInfoSize() const { return sizeof(Nhdr) + 8 + sizeof(prpsinfo_t); }
6165
size_t GetAuxvInfoSize() const { return sizeof(Nhdr) + 8 + m_crashInfo.GetAuxvSize(); }
6266
size_t GetThreadInfoSize() const
6367
{
64-
return m_crashInfo.Threads().size() * ((sizeof(Nhdr) + 8 + sizeof(prstatus_t))
65-
+ sizeof(Nhdr) + 8 + sizeof(user_fpregs_struct)
68+
return (m_crashInfo.Signal() != 0 ? (sizeof(Nhdr) + 8 + sizeof(siginfo_t)) : 0)
69+
+ (m_crashInfo.Threads().size() * ((sizeof(Nhdr) + 8 + sizeof(prstatus_t))
70+
+ (sizeof(Nhdr) + 8 + sizeof(user_fpregs_struct))
6671
#if defined(__i386__)
67-
+ sizeof(Nhdr) + 8 + sizeof(user_fpxregs_struct)
72+
+ (sizeof(Nhdr) + 8 + sizeof(user_fpxregs_struct))
6873
#endif
6974
#if defined(__arm__) && defined(__VFP_FP__) && !defined(__SOFTFP__)
70-
+ sizeof(Nhdr) + 8 + sizeof(user_vfpregs_struct)
75+
+ (sizeof(Nhdr) + 8 + sizeof(user_vfpregs_struct))
7176
#endif
72-
);
77+
));
7378
}
7479
};

0 commit comments

Comments
 (0)