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
1 change: 1 addition & 0 deletions src/coreclr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ include(../../eng/native/configurepaths.cmake)
include(${CLR_ENG_NATIVE_DIR}/configurecompiler.cmake)

include_directories("${CLR_SRC_NATIVE_DIR}")
include_directories("${CLR_SRC_NATIVE_DIR}/inc")

if(MSVC)
set(CMAKE_CXX_STANDARD_LIBRARIES "") # do not link against standard win32 libs i.e. kernel32, uuid, user32, etc.
Expand Down
6 changes: 5 additions & 1 deletion src/coreclr/debug/createdump/crashinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ CrashInfo::CrashInfo(const CreateDumpOptions& options) :
m_gatherFrames(options.CrashReport),
m_crashThread(options.CrashThread),
m_signal(options.Signal),
m_exceptionRecord(options.ExceptionRecord),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this should be m_exceptionRecordAddr

m_moduleInfos(&ModuleInfoCompare),
m_mainModule(nullptr),
m_cbModuleMappings(0),
Expand All @@ -39,7 +40,7 @@ CrashInfo::CrashInfo(const CreateDumpOptions& options) :
m_siginfo.si_signo = options.Signal;
m_siginfo.si_code = options.SignalCode;
m_siginfo.si_errno = options.SignalErrno;
m_siginfo.si_addr = options.SignalAddress;
m_siginfo.si_addr = (void*)options.SignalAddress;
}

CrashInfo::~CrashInfo()
Expand Down Expand Up @@ -193,6 +194,9 @@ CrashInfo::GatherCrashInfo(DumpType dumpType)
{
return false;
}
// Add the special (fake) memory region for the special diagnostics info
MemoryRegion special(PF_R, SpecialDiagInfoAddress, SpecialDiagInfoAddress + PAGE_SIZE);
m_memoryRegions.insert(special);
#ifdef __APPLE__
InitializeOtherMappings();
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/debug/createdump/crashinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi
bool m_gatherFrames; // if true, add the native and managed stack frames to the thread info
pid_t m_crashThread; // crashing thread id or 0 if none
uint32_t m_signal; // crash signal code or 0 if none
uint64_t m_exceptionRecord; // exception record address or 0 if none
std::string m_name; // exe name
siginfo_t m_siginfo; // signal info (if any)
std::string m_coreclrPath; // the path of the coreclr module or empty if none
Expand Down Expand Up @@ -115,6 +116,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi
inline const bool GatherFrames() const { return m_gatherFrames; }
inline const pid_t CrashThread() const { return m_crashThread; }
inline const uint32_t Signal() const { return m_signal; }
inline const uint64_t ExceptionRecord () const { return m_exceptionRecord; }
inline const std::string& Name() const { return m_name; }
inline const ModuleInfo* MainModule() const { return m_mainModule; }
inline const uint64_t RuntimeBaseAddress() const { return m_runtimeBaseAddress; }
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/debug/createdump/createdump.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ typedef struct
int Signal;
int SignalCode;
int SignalErrno;
void* SignalAddress;
uint64_t SignalAddress;
uint64_t ExceptionRecord;
} CreateDumpOptions;

#ifdef HOST_UNIX
Expand All @@ -136,6 +137,7 @@ typedef struct
#include "crashreportwriter.h"
#include "dumpwriter.h"
#include "runtimeinfo.h"
#include "specialdiaginfo.h"
#endif

#ifndef MAX_LONGPATH
Expand Down
11 changes: 7 additions & 4 deletions src/coreclr/debug/createdump/createdumpmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,10 @@ int createdump_main(const int argc, const char* argv[])
options.Signal = 0;
options.CrashThread = 0;
options.Pid = 0;
#if defined(HOST_UNIX) && !defined(HOST_OSX)
options.SignalCode = 0;
options.SignalErrno = 0;
options.SignalAddress = nullptr;
#endif
options.SignalAddress = 0;
options.ExceptionRecord = 0;
bool help = false;
int exitCode = 0;

Expand Down Expand Up @@ -141,7 +140,11 @@ int createdump_main(const int argc, const char* argv[])
}
else if (strcmp(*argv, "--address") == 0)
{
options.SignalAddress = (void*)atoll(*++argv);
options.SignalAddress = atoll(*++argv);
}
else if (strcmp(*argv, "--exception-record") == 0)
{
options.ExceptionRecord = atoll(*++argv);
}
#endif
else if ((strcmp(*argv, "-d") == 0) || (strcmp(*argv, "--diag") == 0))
Expand Down
21 changes: 21 additions & 0 deletions src/coreclr/debug/createdump/dumpwriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,27 @@ DumpWriter::OpenDump(const char* dumpFileName)
return true;
}

bool
DumpWriter::WriteDiagInfo(size_t size)
{
// Write the diagnostics info header
SpecialDiagInfoHeader header = {
{SPECIAL_DIAGINFO_SIGNATURE},
SPECIAL_DIAGINFO_VERSION,
m_crashInfo.ExceptionRecord()
};
if (!WriteData(&header, sizeof(header))) {
return false;
}
size_t alignment = size - sizeof(header);
assert(alignment < sizeof(m_tempBuffer));
memset(m_tempBuffer, 0, alignment);
if (!WriteData(m_tempBuffer, alignment)) {
return false;
}
return true;
}

// Write all of the given buffer, handling short writes and EINTR. Return true iff successful.
bool
DumpWriter::WriteData(int fd, const void* buffer, size_t length)
Expand Down
45 changes: 27 additions & 18 deletions src/coreclr/debug/createdump/dumpwriterelf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,28 +176,37 @@ DumpWriter::WriteDump()
size_t size = memoryRegion.Size();
total += size;

while (size > 0)
if (address == SpecialDiagInfoAddress)
{
size_t bytesToRead = std::min(size, sizeof(m_tempBuffer));
size_t read = 0;

if (!m_crashInfo.ReadProcessMemory((void*)address, m_tempBuffer, bytesToRead, &read)) {
printf_error("Error reading memory at %" PRIA PRIx64 " size %08zx FAILED %s (%d)\n", address, bytesToRead, strerror(g_readProcessMemoryErrno), g_readProcessMemoryErrno);
if (!WriteDiagInfo(size)) {
return false;
}

// This can happen if the target process dies before createdump is finished
if (read == 0) {
printf_error("Error reading memory at %" PRIA PRIx64 " size %08zx returned 0 bytes read: %s (%d)\n", address, bytesToRead, strerror(g_readProcessMemoryErrno), g_readProcessMemoryErrno);
return false;
}

if (!WriteData(m_tempBuffer, read)) {
return false;
}
else
{
while (size > 0)
{
size_t bytesToRead = std::min(size, sizeof(m_tempBuffer));
size_t read = 0;

if (!m_crashInfo.ReadProcessMemory((void*)address, m_tempBuffer, bytesToRead, &read)) {
printf_error("Error reading memory at %" PRIA PRIx64 " size %08zx FAILED %s (%d)\n", address, bytesToRead, strerror(g_readProcessMemoryErrno), g_readProcessMemoryErrno);
return false;
}

// This can happen if the target process dies before createdump is finished
if (read == 0) {
printf_error("Error reading memory at %" PRIA PRIx64 " size %08zx returned 0 bytes read: %s (%d)\n", address, bytesToRead, strerror(g_readProcessMemoryErrno), g_readProcessMemoryErrno);
return false;
}

if (!WriteData(m_tempBuffer, read)) {
return false;
}

address += read;
size -= read;
}

address += read;
size -= read;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/debug/createdump/dumpwriterelf.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class DumpWriter
static bool WriteData(int fd, const void* buffer, size_t length);

private:
bool WriteDiagInfo(size_t size);
bool WriteProcessInfo();
bool WriteAuxv();
size_t GetNTFileInfoSize(size_t* alignmentBytes = nullptr);
Expand Down
8 changes: 7 additions & 1 deletion src/coreclr/debug/createdump/dumpwritermacho.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,13 @@ DumpWriter::WriteSegments()
(segment.initprot & VM_PROT_EXECUTE) ? 'x' : '-',
segment.initprot);

if (address == SpecialThreadInfoAddress)
if (address == SpecialDiagInfoAddress)
{
if (!WriteDiagInfo(size)) {
return false;
}
}
else if (address == SpecialThreadInfoAddress)
{
// Write the header
SpecialThreadInfoHeader header = {
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/debug/createdump/dumpwritermacho.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class DumpWriter
static bool WriteData(int fd, const void* buffer, size_t length);

private:
bool WriteDiagInfo(size_t size);
void BuildSegmentLoadCommands();
void BuildThreadLoadCommands();
bool WriteHeader(uint64_t* pFileOffset);
Expand Down
32 changes: 32 additions & 0 deletions src/coreclr/debug/createdump/specialdiaginfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// ******************************************************************************
// WARNING!!!: This code is also used by SOS in the diagnostics repo. Should be
// updated in a backwards and forwards compatible way.
// See: https://github.com/dotnet/diagnostics/blob/main/src/SOS/inc/specialdiaginfo.h
// ******************************************************************************

// This is a special memory region added to ELF and MachO dumps that contains extra diagnostics
// information like the exception record for a crash for a NativeAOT app. The exception record
// contains the pointer to the JSON formatted crash info.

#define SPECIAL_DIAGINFO_SIGNATURE "DIAGINFOHEADER"
#define SPECIAL_DIAGINFO_VERSION 1

#ifdef __APPLE__
const uint64_t SpecialDiagInfoAddress = 0x7fffffff10000000;
#else
#if TARGET_64BIT
const uint64_t SpecialDiagInfoAddress = 0x00007ffffff10000;
#else
const uint64_t SpecialDiagInfoAddress = 0x7fff1000;
#endif
#endif

struct SpecialDiagInfoHeader
{
char Signature[16];
int32_t Version;
uint64_t ExceptionRecordAddress;
};
1 change: 1 addition & 0 deletions src/coreclr/nativeaot/Runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ else()

list(APPEND COMMON_RUNTIME_SOURCES
unix/PalRedhawkUnix.cpp
unix/PalCreateDump.cpp
${GC_DIR}/unix/gcenv.unix.cpp
${GC_DIR}/unix/numasupport.cpp
${GC_DIR}/unix/events.cpp
Expand Down
13 changes: 13 additions & 0 deletions src/coreclr/nativeaot/Runtime/DebugHeader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "thread.h"
#include "threadstore.h"

extern uint8_t g_CrashInfoBuffer[];
GPTR_DECL(MethodTable, g_pFreeObjectEEType);

struct DebugTypeEntry
Expand Down Expand Up @@ -195,6 +196,11 @@ extern "C" void PopulateDebugHeaders()
MAKE_DEBUG_FIELD_ENTRY(ThreadBuffer, m_rgbAllocContextBuffer);
MAKE_DEBUG_FIELD_ENTRY(ThreadBuffer, m_threadId);
MAKE_DEBUG_FIELD_ENTRY(ThreadBuffer, m_pThreadStressLog);
MAKE_DEBUG_FIELD_ENTRY(ThreadBuffer, m_pExInfoStackHead);

MAKE_SIZE_ENTRY(ExInfo);
MAKE_DEBUG_FIELD_ENTRY(ExInfo, m_pPrevExInfo);
MAKE_DEBUG_FIELD_ENTRY(ExInfo, m_exception);

MAKE_SIZE_ENTRY(MethodTable);
MAKE_DEBUG_FIELD_ENTRY(MethodTable, m_uBaseSize);
Expand Down Expand Up @@ -244,6 +250,8 @@ extern "C" void PopulateDebugHeaders()
MAKE_SIZE_ENTRY(RuntimeInstance);
MAKE_DEBUG_FIELD_ENTRY(RuntimeInstance, m_pThreadStore);

MAKE_GLOBAL_ENTRY(g_CrashInfoBuffer);

RuntimeInstance *g_pTheRuntimeInstance = GetRuntimeInstance();
MAKE_GLOBAL_ENTRY(g_pTheRuntimeInstance);

Expand All @@ -269,4 +277,9 @@ extern "C" void PopulateDebugHeaders()
static_assert(MethodTable::Flags::IsGenericFlag == 0x02000000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");
static_assert(MethodTable::Flags::ElementTypeMask == 0x7C000000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");
static_assert(MethodTable::Flags::ElementTypeShift == 26, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");
static_assert(MethodTable::Flags::HasComponentSizeFlag == 0x80000000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");

static_assert(MethodTable::Kinds::CanonicalEEType == 0x00000000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Kinds. If you change this value you must bump major_version_number.");
static_assert(MethodTable::Kinds::ParameterizedEEType == 0x00020000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Kinds. If you change this value you must bump major_version_number.");
static_assert(MethodTable::Kinds::GenericTypeDefEEType == 0x00030000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Kinds. If you change this value you must bump major_version_number.");
}
10 changes: 9 additions & 1 deletion src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ bool ShouldHijackForGcStress(uintptr_t CallsiteIP, HijackType ht);
#include "shash.inl"

#define MAX_CRASHINFOBUFFER_SIZE 8192
uint8_t g_CrashInfoBuffer[MAX_CRASHINFOBUFFER_SIZE];
uint8_t g_CrashInfoBuffer[MAX_CRASHINFOBUFFER_SIZE] = { 0 };

ThreadStore * RuntimeInstance::GetThreadStore()
{
Expand All @@ -50,6 +50,14 @@ COOP_PINVOKE_HELPER(uint8_t *, RhGetCrashInfoBuffer, (int32_t* pcbMaxSize))
return g_CrashInfoBuffer;
}

#if TARGET_UNIX
#include "PalCreateDump.h"
COOP_PINVOKE_HELPER(void, RhCreateCrashDumpIfEnabled, (PEXCEPTION_RECORD pExceptionRecord, PCONTEXT pExContext))
{
PalCreateCrashDumpIfEnabled(pExceptionRecord, pExContext);
}
#endif

COOP_PINVOKE_HELPER(uint8_t *, RhGetRuntimeVersion, (int32_t* pcbLength))
{
*pcbLength = sizeof(CLR_PRODUCT_VERSION) - 1; // don't include the terminating null
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,4 +248,5 @@ ds_rt_aot_set_environment_variable (const ep_char16_t *name, const ep_char16_t *
return SetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(name), reinterpret_cast<LPCWSTR>(value)) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
#endif
}

#endif /* ENABLE_PERFTRACING */
21 changes: 19 additions & 2 deletions src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define DIAGNOSTICS_RT_AOT_H

#include <eventpipe/ds-rt-config.h>
#include <generatedumpflags.h>

#ifdef ENABLE_PERFTRACING
#include "ep-rt-aot.h"
Expand Down Expand Up @@ -181,8 +182,24 @@ ds_rt_generate_core_dump (
{
STATIC_CONTRACT_NOTHROW;

// Eventpipe driven core_dump is not currently supported in NativeAOT
return DS_IPC_E_NOTSUPPORTED;
ds_ipc_result_t result = DS_IPC_E_FAIL;
#ifdef TARGET_UNIX
uint32_t flags = ds_generate_core_dump_command_payload_get_flags(payload);
if (commandId == DS_DUMP_COMMANDID_GENERATE_CORE_DUMP)
{
// For the old commmand, this payload field is a bool of whether to enable logging
flags = flags != 0 ? GenerateDumpFlagsLoggingEnabled : 0;
}
const ep_char16_t *dumpName = ds_generate_core_dump_command_payload_get_dump_name (payload);
int32_t dumpType = static_cast<int32_t>(ds_generate_core_dump_command_payload_get_dump_type (payload));
ep_char8_t *dumpNameUtf8 = ep_rt_utf16le_to_utf8_string (dumpName, ep_rt_utf16_string_len (dumpName));
extern bool PalGenerateCoreDump(const char* dumpName, int dumpType, uint32_t flags, char* errorMessageBuffer, int cbErrorMessageBuffer);
if (PalGenerateCoreDump(dumpNameUtf8, dumpType, flags, errorMessageBuffer, cbErrorMessageBuffer))
{
result = DS_IPC_S_OK;
}
#endif
return result;
}

/*
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "UnixContext.h"
#include "HardwareExceptions.h"
#include "UnixSignals.h"
#include "PalCreateDump.h"

#if defined(HOST_APPLE)
#include <mach/mach.h>
Expand Down Expand Up @@ -559,6 +560,8 @@ void SIGSEGVHandler(int code, siginfo_t *siginfo, void *context)
// Restore the original or default handler and restart h/w exception
RestoreSignalHandler(code, &g_previousSIGSEGV);
}

PalCreateCrashDumpIfEnabled(code, siginfo);
}

// Handler for the SIGFPE signal
Expand All @@ -579,6 +582,8 @@ void SIGFPEHandler(int code, siginfo_t *siginfo, void *context)
// Restore the original or default handler and restart h/w exception
RestoreSignalHandler(code, &g_previousSIGFPE);
}

PalCreateCrashDumpIfEnabled(code, siginfo);
}

// Initialize hardware exception handling
Expand Down
Loading