diff --git a/src/coreclr/debug/createdump/CMakeLists.txt b/src/coreclr/debug/createdump/CMakeLists.txt index 282412f354122..c108586ca0510 100644 --- a/src/coreclr/debug/createdump/CMakeLists.txt +++ b/src/coreclr/debug/createdump/CMakeLists.txt @@ -37,6 +37,12 @@ if(CLR_CMAKE_HOST_WIN32) else(CLR_CMAKE_HOST_WIN32) + if(NOT DEFINED ENV{ROOTFS_DIR}) + include_directories(SYSTEM /usr/local/include) + elseif (CLR_CMAKE_TARGET_FREEBSD) + include_directories(SYSTEM $ENV{ROOTFS_DIR}/usr/local/include) + endif() + include(configure.cmake) # Set the RPATH of createdump so that it can find dependencies without needing to set LD_LIBRARY_PATH @@ -64,6 +70,7 @@ else(CLR_CMAKE_HOST_WIN32) datatarget.cpp dumpwriter.cpp crashreportwriter.cpp + ${CLR_SRC_NATIVE_DIR}/minipal/utf8.c ) if(CLR_CMAKE_HOST_OSX) @@ -74,9 +81,6 @@ if(CLR_CMAKE_HOST_OSX) dumpwritermacho.cpp ${CREATEDUMP_SOURCES} ) - add_executable_clr(createdump - main.cpp - ) else() add_library_clr(createdump_static STATIC @@ -85,25 +89,21 @@ else() dumpwriterelf.cpp ${CREATEDUMP_SOURCES} ) +endif(CLR_CMAKE_HOST_OSX) + add_executable_clr(createdump main.cpp - ${PAL_REDEFINES_FILE} + createdumppal.cpp ) - add_dependencies(createdump pal_redefines_file) -endif(CLR_CMAKE_HOST_OSX) target_link_libraries(createdump PRIVATE createdump_static corguids dbgutil - # share the PAL in the dac module - mscordaccore dl ) - add_dependencies(createdump mscordaccore) - endif(CLR_CMAKE_HOST_WIN32) install_clr(TARGETS createdump DESTINATIONS . sharedFramework COMPONENT runtime) diff --git a/src/coreclr/debug/createdump/config.h.in b/src/coreclr/debug/createdump/config.h.in index ee8701be0cf9c..792d8a5988bef 100644 --- a/src/coreclr/debug/createdump/config.h.in +++ b/src/coreclr/debug/createdump/config.h.in @@ -4,3 +4,5 @@ #pragma once #cmakedefine HAVE_PROCESS_VM_READV +#cmakedefine01 HAVE_CLOCK_GETTIME_NSEC_NP +#cmakedefine01 HAVE_CLOCK_MONOTONIC diff --git a/src/coreclr/debug/createdump/configure.cmake b/src/coreclr/debug/createdump/configure.cmake index 9587b3f75f392..4ba6320f4c930 100644 --- a/src/coreclr/debug/createdump/configure.cmake +++ b/src/coreclr/debug/createdump/configure.cmake @@ -1,3 +1,22 @@ check_function_exists(process_vm_readv HAVE_PROCESS_VM_READV) +check_symbol_exists( + clock_gettime_nsec_np + time.h + HAVE_CLOCK_GETTIME_NSEC_NP) + +check_cxx_source_runs(" +#include +#include +#include + +int main() +{ + int ret; + struct timespec ts; + ret = clock_gettime(CLOCK_MONOTONIC, &ts); + + exit(ret); +}" HAVE_CLOCK_MONOTONIC) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) diff --git a/src/coreclr/debug/createdump/crashinfo.cpp b/src/coreclr/debug/createdump/crashinfo.cpp index 44294dc439bda..c9bf2238385b3 100644 --- a/src/coreclr/debug/createdump/crashinfo.cpp +++ b/src/coreclr/debug/createdump/crashinfo.cpp @@ -280,10 +280,11 @@ GetHResultString(HRESULT hr) bool CrashInfo::InitializeDAC(DumpType dumpType) { - // Don't attempt to load the DAC if the app model doesn't support it by default. The default for single-file is a - // full dump, but if the dump type requested is a mini, triage or heap and the DAC is side-by-side to the single-file - // application the core dump will be generated. - if (dumpType == DumpType::Full && (m_appModel == AppModelType::SingleFile || m_appModel == AppModelType::NativeAOT)) + // Don't attempt to load the DAC if the app model doesn't support it by default. The default for single-file is + // a full dump, but if the dump type requested is a mini, triage or heap and the DAC is next to the single-file + // application the core dump will be generated. For NativeAOT, there is currently no DAC available so never + // attempt to load it. + if ((dumpType == DumpType::Full && m_appModel == AppModelType::SingleFile) || m_appModel == AppModelType::NativeAOT) { return true; } @@ -483,19 +484,24 @@ CrashInfo::EnumerateManagedModules() bool CrashInfo::UnwindAllThreads() { - TRACE("UnwindAllThreads: STARTED (%d)\n", m_dataTargetPagesAdded); - ReleaseHolder pSos = nullptr; - if (m_pClrDataProcess != nullptr) { - m_pClrDataProcess->QueryInterface(__uuidof(ISOSDacInterface), (void**)&pSos); - } - // For each native and managed thread - for (ThreadInfo* thread : m_threads) + // Don't unwind any threads if Native AOT since there isn't a DAC to get the remote + // unwinder support and they are full dumps. + if (m_appModel != AppModelType::NativeAOT) { - if (!thread->UnwindThread(m_pClrDataProcess, pSos)) { - return false; + TRACE("UnwindAllThreads: STARTED (%d)\n", m_dataTargetPagesAdded); + ReleaseHolder pSos = nullptr; + if (m_pClrDataProcess != nullptr) { + m_pClrDataProcess->QueryInterface(__uuidof(ISOSDacInterface), (void**)&pSos); + } + // For each native and managed thread + for (ThreadInfo* thread : m_threads) + { + if (!thread->UnwindThread(m_pClrDataProcess, pSos)) { + return false; + } } + TRACE("UnwindAllThreads: FINISHED (%d)\n", m_dataTargetPagesAdded); } - TRACE("UnwindAllThreads: FINISHED (%d)\n", m_dataTargetPagesAdded); return true; } @@ -959,9 +965,9 @@ FormatString(const char* format, ...) ArrayHolder buffer = new char[MAX_LONGPATH + 1]; va_list args; va_start(args, format); - int result = vsprintf_s(buffer, MAX_LONGPATH, format, args); + int result = vsnprintf(buffer, MAX_LONGPATH, format, args); va_end(args); - return result > 0 ? std::string(buffer) : std::string(); + return result > 0 && result < MAX_LONGPATH ? std::string(buffer) : std::string(); } // @@ -971,15 +977,16 @@ std::string ConvertString(const WCHAR* str) { if (str == nullptr) - return{}; + return { }; - int len = WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr); + size_t cch = u16_strlen(str) + 1; + int len = minipal_get_length_utf16_to_utf8((CHAR16_T*)str, cch, 0); if (len == 0) - return{}; + return { }; ArrayHolder buffer = new char[len + 1]; - WideCharToMultiByte(CP_UTF8, 0, str, -1, buffer, len + 1, nullptr, nullptr); - return std::string{ buffer }; + minipal_convert_utf16_to_utf8((CHAR16_T*)str, cch, buffer, len + 1, 0); + return std::string { buffer }; } // diff --git a/src/coreclr/debug/createdump/crashinfomac.cpp b/src/coreclr/debug/createdump/crashinfomac.cpp index 97477f2918b63..90a31f106d684 100644 --- a/src/coreclr/debug/createdump/crashinfomac.cpp +++ b/src/coreclr/debug/createdump/crashinfomac.cpp @@ -288,11 +288,11 @@ void CrashInfo::VisitSegment(MachOModule& module, const segment_command_64& segm // Round to page boundary start = start & PAGE_MASK; - _ASSERTE(start > 0); + assert(start > 0); // Round up to page boundary end = (end + (PAGE_SIZE - 1)) & PAGE_MASK; - _ASSERTE(end > 0); + assert(end > 0); // Add module memory region if not already on the list MemoryRegion newModule(regionFlags, start, end, offset, module.Name()); diff --git a/src/coreclr/debug/createdump/crashinfounix.cpp b/src/coreclr/debug/createdump/crashinfounix.cpp index d4b003a20ae8b..70b2ddb270d74 100644 --- a/src/coreclr/debug/createdump/crashinfounix.cpp +++ b/src/coreclr/debug/createdump/crashinfounix.cpp @@ -17,7 +17,12 @@ bool CrashInfo::Initialize() { char memPath[128]; - _snprintf_s(memPath, sizeof(memPath), sizeof(memPath), "/proc/%u/mem", m_pid); + int chars = snprintf(memPath, sizeof(memPath), "/proc/%u/mem", m_pid); + if (chars <= 0 || (size_t)chars >= sizeof(memPath)) + { + printf_error("snprintf failed building /proc//mem name\n"); + return false; + } m_fdMem = open(memPath, O_RDONLY); if (m_fdMem == -1) @@ -42,7 +47,12 @@ CrashInfo::Initialize() { TRACE("DbgDisablePagemapUse detected - pagemap file checking is enabled\n"); char pagemapPath[128]; - _snprintf_s(pagemapPath, sizeof(pagemapPath), sizeof(pagemapPath), "/proc/%u/pagemap", m_pid); + chars = snprintf(pagemapPath, sizeof(pagemapPath), "/proc/%u/pagemap", m_pid); + if (chars <= 0 || (size_t)chars >= sizeof(pagemapPath)) + { + printf_error("snprintf failed building /proc//pagemap name\n"); + return false; + } m_fdPagemap = open(pagemapPath, O_RDONLY); if (m_fdPagemap == -1) { @@ -95,7 +105,12 @@ bool CrashInfo::EnumerateAndSuspendThreads() { char taskPath[128]; - _snprintf_s(taskPath, sizeof(taskPath), sizeof(taskPath), "/proc/%u/task", m_pid); + int chars = snprintf(taskPath, sizeof(taskPath), "/proc/%u/task", m_pid); + if (chars <= 0 || (size_t)chars >= sizeof(taskPath)) + { + printf_error("snprintf failed building /proc//task\n"); + return false; + } DIR* taskDir = opendir(taskPath); if (taskDir == nullptr) @@ -139,8 +154,12 @@ bool CrashInfo::GetAuxvEntries() { char auxvPath[128]; - _snprintf_s(auxvPath, sizeof(auxvPath), sizeof(auxvPath), "/proc/%u/auxv", m_pid); - + int chars = snprintf(auxvPath, sizeof(auxvPath), "/proc/%u/auxv", m_pid); + if (chars <= 0 || (size_t)chars >= sizeof(auxvPath)) + { + printf_error("snprintf failed building /proc//auxv\n"); + return false; + } int fd = open(auxvPath, O_RDONLY, 0); if (fd == -1) { @@ -195,9 +214,12 @@ CrashInfo::EnumerateMemoryRegions() // Making something like: /proc/123/maps char mapPath[128]; - int chars = _snprintf_s(mapPath, sizeof(mapPath), sizeof(mapPath), "/proc/%u/maps", m_pid); - assert(chars > 0 && (size_t)chars <= sizeof(mapPath)); - + int chars = snprintf(mapPath, sizeof(mapPath), "/proc/%u/maps", m_pid); + if (chars <= 0 || (size_t)chars >= sizeof(mapPath)) + { + printf_error("snprintf failed building /proc//maps\n"); + return false; + } FILE* mapsFile = fopen(mapPath, "r"); if (mapsFile == nullptr) { @@ -401,19 +423,22 @@ CrashInfo::VisitProgramHeader(uint64_t loadbias, uint64_t baseAddress, Phdr* phd TRACE("VisitProgramHeader: ehFrameHdrStart %016llx ehFrameHdrSize %08llx\n", ehFrameHdrStart, ehFrameHdrSize); InsertMemoryRegion(ehFrameHdrStart, ehFrameHdrSize); - ULONG64 ehFrameStart; - ULONG64 ehFrameSize; - if (PAL_GetUnwindInfoSize(baseAddress, ehFrameHdrStart, ReadMemoryAdapter, &ehFrameStart, &ehFrameSize)) + if (m_appModel != AppModelType::NativeAOT) { - TRACE("VisitProgramHeader: ehFrameStart %016llx ehFrameSize %08llx\n", ehFrameStart, ehFrameSize); - if (ehFrameStart != 0 && ehFrameSize != 0) + ULONG64 ehFrameStart; + ULONG64 ehFrameSize; + if (PAL_GetUnwindInfoSize(baseAddress, ehFrameHdrStart, ReadMemoryAdapter, &ehFrameStart, &ehFrameSize)) { - InsertMemoryRegion(ehFrameStart, ehFrameSize); + TRACE("VisitProgramHeader: ehFrameStart %016llx ehFrameSize %08llx\n", ehFrameStart, ehFrameSize); + if (ehFrameStart != 0 && ehFrameSize != 0) + { + InsertMemoryRegion(ehFrameStart, ehFrameSize); + } + } + else + { + TRACE("VisitProgramHeader: PAL_GetUnwindInfoSize FAILED\n"); } - } - else - { - TRACE("VisitProgramHeader: PAL_GetUnwindInfoSize FAILED\n"); } } break; @@ -489,7 +514,12 @@ bool GetStatus(pid_t pid, pid_t* ppid, pid_t* tgid, std::string* name) { char statusPath[128]; - _snprintf_s(statusPath, sizeof(statusPath), sizeof(statusPath), "/proc/%d/status", pid); + int chars = snprintf(statusPath, sizeof(statusPath), "/proc/%d/status", pid); + if (chars <= 0 || (size_t)chars >= sizeof(statusPath)) + { + printf_error("snprintf failed building /proc//status\n"); + return false; + } FILE *statusFile = fopen(statusPath, "r"); if (statusFile == nullptr) diff --git a/src/coreclr/debug/createdump/crashreportwriter.cpp b/src/coreclr/debug/createdump/crashreportwriter.cpp index 77081fad39236..a092e93b42428 100644 --- a/src/coreclr/debug/createdump/crashreportwriter.cpp +++ b/src/coreclr/debug/createdump/crashreportwriter.cpp @@ -376,7 +376,7 @@ void CrashReportWriter::WriteValue32(const char* key, uint32_t value) { char buffer[16]; - _snprintf_s(buffer, sizeof(buffer), sizeof(buffer), "0x%x", value); + snprintf(buffer, sizeof(buffer), "0x%x", value); WriteValue(key, buffer); } @@ -384,7 +384,7 @@ void CrashReportWriter::WriteValue64(const char* key, uint64_t value) { char buffer[32]; - _snprintf_s(buffer, sizeof(buffer), sizeof(buffer), "0x%" PRIx64, value); + snprintf(buffer, sizeof(buffer), "0x%" PRIx64, value); WriteValue(key, buffer); } diff --git a/src/coreclr/debug/createdump/createdump.h b/src/coreclr/debug/createdump/createdump.h index 3d796d5446ad1..e24fa94a2df20 100644 --- a/src/coreclr/debug/createdump/createdump.h +++ b/src/coreclr/debug/createdump/createdump.h @@ -53,6 +53,8 @@ typedef int T_CONTEXT; #include #include #ifdef HOST_UNIX +#include +#include #include #include #include diff --git a/src/coreclr/debug/createdump/createdumpmain.cpp b/src/coreclr/debug/createdump/createdumpmain.cpp index 503bfecc4ce07..10468394956ef 100644 --- a/src/coreclr/debug/createdump/createdumpmain.cpp +++ b/src/coreclr/debug/createdump/createdumpmain.cpp @@ -33,7 +33,8 @@ const char* g_help = "createdump [options]\n" "--crashreportonly - write crash report file only (no dump).\n" "--crashthread - the thread id of the crashing thread.\n" "--signal - the signal code of the crash.\n" -"--singlefile - enable single-file app check.\n" +"--singlefile - single-file app model.\n" +"--nativeaot - native AOT app model.\n" #endif ; @@ -126,6 +127,10 @@ int createdump_main(const int argc, const char* argv[]) { options.AppModel = AppModelType::SingleFile; } + else if (strcmp(*argv, "--nativeaot") == 0) + { + options.AppModel = AppModelType::NativeAOT; + } else if (strcmp(*argv, "--code") == 0) { options.SignalCode = atoi(*++argv); @@ -199,9 +204,8 @@ int createdump_main(const int argc, const char* argv[]) { if (::GetTempPathA(MAX_LONGPATH, tmpPath) == 0) { - //printf_error("GetTempPath failed %s", GetLastErrorString().c_str()); printf_error("GetTempPath failed\n"); - return ::GetLastError(); + return -1; } exitCode = strcat_s(tmpPath, MAX_LONGPATH, DEFAULT_DUMP_TEMPLATE); if (exitCode != 0) diff --git a/src/coreclr/debug/createdump/createdumppal.cpp b/src/coreclr/debug/createdump/createdumppal.cpp new file mode 100644 index 0000000000000..4dd7204ce91fd --- /dev/null +++ b/src/coreclr/debug/createdump/createdumppal.cpp @@ -0,0 +1,268 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "createdump.h" +#include +#include + +#define INITGUID +#include + +DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + +#if defined(__linux__) +#define PAL_FUNCTION_PREFIX "DAC_" +#else +#define PAL_FUNCTION_PREFIX +#endif + +typedef int (*PFN_PAL_InitializeDLL)(); +typedef void (*PFN_PAL_TerminateEx)(int); + +typedef BOOL (*PFN_PAL_VirtualUnwindOutOfProc)( + CONTEXT *context, + KNONVOLATILE_CONTEXT_POINTERS *contextPointers, + PULONG64 functionStart, + SIZE_T baseAddress, + UnwindReadMemoryCallback readMemoryCallback); + +typedef BOOL (*PFN_PAL_GetUnwindInfoSize)( + SIZE_T baseAddress, + ULONG64 ehFrameHdrAddr, + UnwindReadMemoryCallback readMemoryCallback, + PULONG64 ehFrameStart, + PULONG64 ehFrameSize); + +bool g_initialized = false; +PFN_PAL_InitializeDLL g_PAL_InitializeDLL = nullptr; +PFN_PAL_TerminateEx g_PAL_TerminateEx = nullptr; +PFN_PAL_VirtualUnwindOutOfProc g_PAL_VirtualUnwindOutOfProc = nullptr; +PFN_PAL_GetUnwindInfoSize g_PAL_GetUnwindInfoSize = nullptr; + +bool +InitializePAL() +{ + if (g_initialized) + { + return true; + } + g_initialized = true; + + // Get createdump's path and load the DAC next to it. + Dl_info info; + if (dladdr((PVOID)&InitializePAL, &info) == 0) + { + printf_error("InitializePAL: dladdr(&InitializePAL) FAILED %s\n", dlerror()); + return false; + } + std::string dacPath; + dacPath.append(info.dli_fname); + dacPath = GetDirectory(dacPath); + dacPath.append(MAKEDLLNAME_A("mscordaccore")); + + // Load the DAC next to createdump + void* dacModule = dlopen(dacPath.c_str(), RTLD_LAZY); + if (dacModule == nullptr) + { + printf_error("InitializePAL: dlopen(%s) FAILED %s\n", dacPath.c_str(), dlerror()); + return false; + } + + // Get the PAL entry points needed by createdump + g_PAL_InitializeDLL = (PFN_PAL_InitializeDLL)dlsym(dacModule, PAL_FUNCTION_PREFIX "PAL_InitializeDLL"); + if (g_PAL_InitializeDLL == nullptr) + { + printf_error("InitializePAL: dlsym(PAL_InitializeDLL) FAILED %s\n", dlerror()); + return false; + } + if (g_PAL_InitializeDLL() != 0) + { + printf_error("InitializePAL: PAL initialization FAILED\n"); + return false; + } + g_PAL_TerminateEx = (PFN_PAL_TerminateEx)dlsym(dacModule, PAL_FUNCTION_PREFIX "PAL_TerminateEx"); + g_PAL_VirtualUnwindOutOfProc = (PFN_PAL_VirtualUnwindOutOfProc)dlsym(dacModule, PAL_FUNCTION_PREFIX "PAL_VirtualUnwindOutOfProc"); + g_PAL_GetUnwindInfoSize = (PFN_PAL_GetUnwindInfoSize)dlsym(dacModule, PAL_FUNCTION_PREFIX "PAL_GetUnwindInfoSize"); + return true; +} + +void +UninitializePAL( + int exitCode) +{ + if (g_PAL_TerminateEx != nullptr) + { + g_PAL_TerminateEx(exitCode); + } +} + +#define tccSecondsToNanoSeconds 1000000000 // 10^9 + +BOOL +PALAPI +QueryPerformanceCounter( + OUT LARGE_INTEGER* lpPerformanceCount) +{ +#if HAVE_CLOCK_GETTIME_NSEC_NP + lpPerformanceCount->QuadPart = (LONGLONG)clock_gettime_nsec_np(CLOCK_UPTIME_RAW); +#elif HAVE_CLOCK_MONOTONIC + struct timespec ts; + int result = clock_gettime(CLOCK_MONOTONIC, &ts); + if (result != 0) + { + return TRUE; + } + else + { + lpPerformanceCount->QuadPart = ((LONGLONG)(ts.tv_sec) * (LONGLONG)(tccSecondsToNanoSeconds)) + (LONGLONG)(ts.tv_nsec); + } +#else + #error "The createdump requires either mach_absolute_time() or clock_gettime(CLOCK_MONOTONIC) to be supported." +#endif + return TRUE; +} + +BOOL +PALAPI +QueryPerformanceFrequency( + OUT LARGE_INTEGER* lpFrequency) +{ +#if HAVE_CLOCK_GETTIME_NSEC_NP + lpFrequency->QuadPart = (LONGLONG)(tccSecondsToNanoSeconds); +#elif HAVE_CLOCK_MONOTONIC + // clock_gettime() returns a result in terms of nanoseconds rather than a count. This + // means that we need to either always scale the result by the actual resolution (to + // get a count) or we need to say the resolution is in terms of nanoseconds. We prefer + // the latter since it allows the highest throughput and should minimize error propagated + // to the user. + lpFrequency->QuadPart = (LONGLONG)(tccSecondsToNanoSeconds); +#else + #error "The createdump requires either mach_absolute_time() or clock_gettime(CLOCK_MONOTONIC) to be supported." +#endif + return TRUE; +} + +#define TEMP_DIRECTORY_PATH "/tmp/" + +DWORD +PALAPI +GetTempPathA( + IN DWORD nBufferLength, + OUT LPSTR lpBuffer) +{ + DWORD dwPathLen = 0; + const char *tempDir = getenv("TMPDIR"); + if (tempDir == nullptr) + { + tempDir = TEMP_DIRECTORY_PATH; + } + size_t tempDirLen = strlen(tempDir); + if (tempDirLen < nBufferLength) + { + dwPathLen = tempDirLen; + strcpy_s(lpBuffer, nBufferLength, tempDir); + } + else + { + // Get the required length + dwPathLen = tempDirLen + 1; + } + return dwPathLen; +} + +BOOL +PALAPI +PAL_VirtualUnwindOutOfProc( + CONTEXT *context, + KNONVOLATILE_CONTEXT_POINTERS *contextPointers, + PULONG64 functionStart, + SIZE_T baseAddress, + UnwindReadMemoryCallback readMemoryCallback) +{ + if (!InitializePAL() || g_PAL_VirtualUnwindOutOfProc == nullptr) + { + return FALSE; + } + return g_PAL_VirtualUnwindOutOfProc(context, contextPointers, functionStart, baseAddress, readMemoryCallback); +} + +BOOL +PALAPI +PAL_GetUnwindInfoSize( + SIZE_T baseAddress, + ULONG64 ehFrameHdrAddr, + UnwindReadMemoryCallback readMemoryCallback, + PULONG64 ehFrameStart, + PULONG64 ehFrameSize) +{ + if (!InitializePAL() || g_PAL_GetUnwindInfoSize == nullptr) + { + return FALSE; + } + return g_PAL_GetUnwindInfoSize(baseAddress, ehFrameHdrAddr, readMemoryCallback, ehFrameStart, ehFrameSize); +} + +// +// Used in pal\inc\rt\safecrt.h's _invalid_parameter handler +// + +VOID +PALAPI +RaiseException( + IN DWORD dwExceptionCode, + IN DWORD dwExceptionFlags, + IN DWORD nNumberOfArguments, + IN CONST ULONG_PTR* lpArguments) +{ + throw; +} + +size_t u16_strlen(const WCHAR* str) +{ + size_t nChar = 0; + while (*str++) + nChar++; + return nChar; +} + +// +// Used by _ASSERTE +// + +#ifdef _DEBUG + +PAL_FILE * +__cdecl +PAL_get_stderr(int caller) +{ + return (PAL_FILE*)stderr; +} + +int +__cdecl +PAL_fprintf(PAL_FILE* stream, const char* format, ...) +{ + va_list args; + va_start(args, format); + int result = vfprintf((FILE*)stream, format, args); + fflush((FILE*)stream); + va_end(args); + return result; +} + +DWORD +PALAPI +GetCurrentProcessId() +{ + return getpid(); +} + +VOID +PALAPI +DebugBreak() +{ + abort(); +} + +#endif // DEBUG + diff --git a/src/coreclr/debug/createdump/createdumpunix.cpp b/src/coreclr/debug/createdump/createdumpunix.cpp index 0b97a3a88b36c..ea6fa5b8b94d4 100644 --- a/src/coreclr/debug/createdump/createdumpunix.cpp +++ b/src/coreclr/debug/createdump/createdumpunix.cpp @@ -30,6 +30,12 @@ CreateDump(const CreateDumpOptions& options) goto exit; } + if (options.DumpType != DumpType::Full && options.AppModel == AppModelType::NativeAOT) + { + printf_error("The app model only supports full dump generation\n"); + goto exit; + } + // Initialize the crash info if (!crashInfo->Initialize()) { diff --git a/src/coreclr/debug/createdump/datatarget.cpp b/src/coreclr/debug/createdump/datatarget.cpp index 38675532aeb78..420300e37ab74 100644 --- a/src/coreclr/debug/createdump/datatarget.cpp +++ b/src/coreclr/debug/createdump/datatarget.cpp @@ -102,12 +102,12 @@ DumpDataTarget::GetImageBase( *baseAddress = 0; char tempModuleName[MAX_PATH]; - int length = WideCharToMultiByte(CP_ACP, 0, moduleName, -1, tempModuleName, sizeof(tempModuleName), NULL, NULL); + size_t cch = u16_strlen(moduleName) + 1; + int length = minipal_convert_utf16_to_utf8((CHAR16_T*)moduleName, cch, tempModuleName, sizeof(tempModuleName), 0); if (length > 0) { *baseAddress = m_crashInfo.GetBaseAddressFromName(tempModuleName); } - return *baseAddress != 0 ? S_OK : E_FAIL; } diff --git a/src/coreclr/debug/createdump/main.cpp b/src/coreclr/debug/createdump/main.cpp index 822947271aff1..b322a3c02a45c 100644 --- a/src/coreclr/debug/createdump/main.cpp +++ b/src/coreclr/debug/createdump/main.cpp @@ -4,6 +4,7 @@ #include "createdump.h" extern int createdump_main(const int argc, const char* argv[]); +extern void UninitializePAL(int exitCode); #if defined(HOST_ARM64) // Flag to check if atomics feature is available on @@ -16,18 +17,9 @@ bool g_arm64_atomics_present = false; // int __cdecl main(const int argc, const char* argv[]) { - int exitCode = 0; + int exitCode = createdump_main(argc, argv); #ifdef HOST_UNIX - exitCode = PAL_InitializeDLL(); - if (exitCode != 0) - { - printf_error("PAL initialization FAILED %d\n", exitCode); - return exitCode; - } -#endif - exitCode = createdump_main(argc, argv); -#ifdef HOST_UNIX - PAL_TerminateEx(exitCode); + UninitializePAL(exitCode); #endif return exitCode; } diff --git a/src/coreclr/debug/createdump/threadinfounix.cpp b/src/coreclr/debug/createdump/threadinfounix.cpp index ca75a6128fee9..d1683b9b2b390 100644 --- a/src/coreclr/debug/createdump/threadinfounix.cpp +++ b/src/coreclr/debug/createdump/threadinfounix.cpp @@ -246,7 +246,7 @@ ThreadInfo::GetThreadContext(uint32_t flags, CONTEXT* context) const context->Fcsr = m_fpRegisters.fpscr; } #elif defined(__riscv) - _ASSERTE(!"TODO RISCV64 NYI"); + assert(!"TODO RISCV64 NYI"); #else #error Platform not supported #endif