[Tizen] Add method to write coredump of .NET process (#384) accepted/tizen_unified_riscv accepted/tizen/unified/riscv/20240115.053917
authorMateusz Moscicki/System (PLT) /SRPOL/Engineer/Samsung Electronics <m.moscicki2@samsung.com>
Fri, 12 Jan 2024 07:46:43 +0000 (08:46 +0100)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Fri, 12 Jan 2024 07:46:43 +0000 (16:46 +0900)
This method allows to create minimal coredump (as createdump does) of a
process that is in dumping state after crush.

This is a modified version of

https://github.sec.samsung.net/dotnet/coreclr/commit/4d043d61ecacae0b9922ecc10a73749e7c8e5987

commit, adapted to .NET 8.0

Co-authored-by: Mateusz Moscicki <m.moscicki2@partner.samsung.com>
packaging/coreclr.spec
src/coreclr/debug/createdump/CMakeLists.txt
src/coreclr/debug/createdump/crashinfo.cpp
src/coreclr/debug/createdump/crashinfo.h
src/coreclr/debug/createdump/crashinfounix.cpp
src/coreclr/debug/createdump/dnetmemoryenumlib.cpp [new file with mode: 0644]
src/coreclr/debug/createdump/dnetmemoryenumlib.h [new file with mode: 0644]
src/coreclr/debug/createdump/threadinfo.cpp
src/coreclr/debug/createdump/threadinfo.h

index 6340b2f..2686211 100644 (file)
@@ -470,6 +470,7 @@ cp %{_reldir_clr}/libjitinterface_%{_tarch}.so          %{buildroot}%{_datadir}/
 cp %{_reldir_clr}/ilasm                                 %{buildroot}%{_datadir}/%{netcoreappdir}
 cp %{_reldir_clr}/ildasm                                %{buildroot}%{_datadir}/%{netcoreappdir}
 cp %{_reldir_clr}/createdump                            %{buildroot}%{_datadir}/%{netcoreappdir}
+cp %{_reldir_clr}/libdnetmemoryenum.so                  %{buildroot}%{_datadir}/%{netcoreappdir}
 
 # CoreFX native
 cp %{_reldir_fx_native}/libSystem.Globalization.Native.so                  %{buildroot}%{_datadir}/%{netcoreappdir}
@@ -718,7 +719,7 @@ cp ./nuget/*.nupkg %{buildroot}/nuget
 %{_datadir}/%{netcoreappdir}/ilasm
 %{_datadir}/%{netcoreappdir}/ildasm
 %{_datadir}/%{netcoreappdir}/createdump
-
+%{_datadir}/%{netcoreappdir}/libdnetmemoryenum.so
 %if 0%{skipmanaged}
 %else
 
index 666bd68..cbf131b 100644 (file)
@@ -107,6 +107,35 @@ endif(CLR_CMAKE_HOST_OSX)
     )
     set_target_properties(createdump PROPERTIES LINK_FLAGS -pie)
 
+    set(DNETMEMORYENUM_SOURCES
+        dumpname.cpp
+        crashinfounix.cpp
+        threadinfounix.cpp
+        createdumpunix.cpp
+        crashinfo.cpp
+        threadinfo.cpp
+        datatarget.cpp
+        dumpwriter.cpp
+        dumpwriterelf.cpp
+        crashreportwriter.cpp
+        dnetmemoryenumlib.cpp
+        createdumppal.cpp
+        ${CLR_SRC_NATIVE_DIR}/minipal/utf8.c
+    )
+
+    add_library_clr(dnetmemoryenum SHARED
+        ${DNETMEMORYENUM_SOURCES}
+    )
+
+    set_property(TARGET dnetmemoryenum PROPERTY COMPILE_FLAGS "-fPIC")
+
+    target_link_libraries(dnetmemoryenum
+        corguids
+        dbgutil
+    )
+
+    install_clr(TARGETS dnetmemoryenum DESTINATIONS . sharedFramework COMPONENT runtime)
+
 endif(CLR_CMAKE_HOST_WIN32)
 
 install_clr(TARGETS createdump DESTINATIONS . sharedFramework COMPONENT runtime)
index 8af6ec4..351e6a0 100644 (file)
@@ -147,17 +147,36 @@ CrashInfo::LogMessage(
 }
 
 //
+// Set registers for all threads
+//
+void
+CrashInfo::SetThreadsRegisters(const std::vector<elf_prstatus*> &statuses)
+{
+    for (ThreadInfo* thread : m_threads) {
+        for (elf_prstatus* status : statuses) {
+            if (thread->Tid() == status->pr_pid) {
+                thread->SetRegisters(status);
+                break;
+            }
+        }
+    }
+}
+
+//
 // Gather all the necessary crash dump info.
 //
 bool
-CrashInfo::GatherCrashInfo(DumpType dumpType)
+CrashInfo::GatherCrashInfo(DumpType dumpType, bool initialize_threads)
 {
-    // Get the info about the threads (registers, etc.)
-    for (ThreadInfo* thread : m_threads)
+    if (initialize_threads)
     {
-        if (!thread->Initialize())
+        // Get the info about the threads (registers, etc.)
+        for (ThreadInfo* thread : m_threads)
         {
-            return false;
+            if (!thread->Initialize())
+            {
+                return false;
+            }
         }
     }
 #ifdef __APPLE__
index 6673e2d..0253d2a 100644 (file)
@@ -93,8 +93,9 @@ public:
 
     bool Initialize();
     void CleanupAndResumeProcess();
-    bool EnumerateAndSuspendThreads();
-    bool GatherCrashInfo(DumpType dumpType);
+    bool EnumerateAndSuspendThreads(bool suspend = true);
+    void SetThreadsRegisters(const std::vector<elf_prstatus*> &statuses);
+    bool GatherCrashInfo(DumpType minidumpType, bool initialize_threads = true);
     void CombineMemoryRegions();
     bool EnumerateMemoryRegionsWithDAC(DumpType dumpType);
     bool ReadMemory(void* address, void* buffer, size_t size);                          // read memory and add to dump
index 70b2ddb..d373127 100644 (file)
@@ -102,7 +102,7 @@ CrashInfo::CleanupAndResumeProcess()
 // Suspends all the threads and creating a list of them. Should be the before gathering any info about the process.
 //
 bool
-CrashInfo::EnumerateAndSuspendThreads()
+CrashInfo::EnumerateAndSuspendThreads(bool suspend)
 {
     char taskPath[128];
     int chars = snprintf(taskPath, sizeof(taskPath), "/proc/%u/task", m_pid);
@@ -125,17 +125,20 @@ CrashInfo::EnumerateAndSuspendThreads()
         pid_t tid = static_cast<pid_t>(strtol(entry->d_name, nullptr, 10));
         if (tid != 0)
         {
-            //  Reference: http://stackoverflow.com/questions/18577956/how-to-use-ptrace-to-get-a-consistent-view-of-multiple-threads
-            if (ptrace(PTRACE_ATTACH, tid, nullptr, nullptr) != -1)
+            if (suspend)
             {
-                int waitStatus;
-                waitpid(tid, &waitStatus, __WALL);
-            }
-            else
-            {
-                printf_error("Problem suspending threads: ptrace(ATTACH, %d) FAILED %s (%d)\n", tid, strerror(errno), errno);
-                closedir(taskDir);
-                return false;
+                //  Reference: http://stackoverflow.com/questions/18577956/how-to-use-ptrace-to-get-a-consistent-view-of-multiple-threads
+                if (ptrace(PTRACE_ATTACH, tid, nullptr, nullptr) != -1)
+                {
+                    int waitStatus;
+                    waitpid(tid, &waitStatus, __WALL);
+                }
+                else
+                {
+                    printf_error("Problem suspending threads: ptrace(ATTACH, %d) FAILED %s (%d)\n", tid, strerror(errno), errno);
+                    closedir(taskDir);
+                    return false;
+                }
             }
             // Add to the list of threads
             ThreadInfo* thread = new ThreadInfo(*this, tid);
diff --git a/src/coreclr/debug/createdump/dnetmemoryenumlib.cpp b/src/coreclr/debug/createdump/dnetmemoryenumlib.cpp
new file mode 100644 (file)
index 0000000..0148e5d
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019-2024 Samsung Electronics Co., Ltd.
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdarg.h>
+#include <iostream>
+#include <vector>
+#include <minipal/utf8.h>
+#include "createdump.h"
+#include "dnetmemoryenumlib.h"
+
+const int DEFAULT_SIGNAL = 6;
+
+bool g_diagnostics = false;
+bool g_diagnosticsVerbose = false;
+
+#if defined(HOST_ARM64)
+// Flag to check if atomics feature is available on
+// the machine
+bool g_arm64_atomics_present = false;
+#endif
+
+std::vector<SimpleMemoryRegion> sm_regions;
+
+int
+prepare_crash_info(pid_t pid, elf_prstatus **statuses, int statuses_count,
+                        DUMP_TYPE minidump_type, ReleaseHolder<CrashInfo> &crash_info)
+{
+    g_diagnostics = true;
+
+    CreateDumpOptions options;
+    options.DumpType = DumpType::Heap;
+    options.DumpPathTemplate = nullptr;
+    options.AppModel = AppModelType::Normal;
+    options.CrashReport = false;
+    options.CreateDump = true;
+    options.Signal = DEFAULT_SIGNAL;
+    options.CrashThread = pid;
+    options.Pid = pid;
+    options.SignalCode = 0;
+    options.SignalErrno = 0;
+    options.SignalAddress = 0;
+    options.ExceptionRecord = 0;
+
+    std::vector<elf_prstatus*> stats(statuses, statuses + statuses_count);
+
+    switch (minidump_type) {
+    case DT_NORMAL:
+    default:
+        options.DumpType = DumpType::Mini;
+        break;
+    case DT_WITH_PRIV_AND_SHARED_MEM:
+        options.DumpType = DumpType::Triage;
+        break;
+    case DT_FULL:
+        options.DumpType = DumpType::Full;
+        break;
+    }
+
+    int exitCode = REGERR_OK;
+
+    if (pid != 0)
+    {
+        crash_info = new CrashInfo(options);
+
+        // Initialize PAGE_SIZE
+#if defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) || defined(__riscv)
+        g_pageSize = sysconf(_SC_PAGESIZE);
+#endif
+
+        if (!crash_info->Initialize())
+        {
+            return REGERR_CRASHINFO_INITIALIZE_ERROR;
+        }
+
+        if (!crash_info->EnumerateAndSuspendThreads(false))
+        {
+            return REGERR_ENUMERATION_ERROR;
+        }
+        crash_info->SetThreadsRegisters(stats);
+        if (!crash_info->GatherCrashInfo(options.DumpType, false))
+        {
+            return REGERR_GATHER_CRASHINFO_ERROR;
+        }
+        if (!crash_info->EnumerateMemoryRegionsWithDAC(options.DumpType))
+        {
+            return REGERR_ENUMERATIONDAC_ERROR;
+        }
+        crash_info->CombineMemoryRegions();
+    }
+    else
+    {
+        exitCode = REGERR_WRONG_PID;
+    }
+    return exitCode;
+}
+
+extern "C" DLLEXPORT int
+DotNetMemoryEnumInit()
+{
+    return 0;
+}
+
+extern "C" DLLEXPORT void
+DotNetMemoryEnumFinish()
+{
+}
+
+extern "C" DLLEXPORT int
+DotNetMemoryWriteDump(pid_t pid, elf_prstatus **statuses, int statuses_count,
+                        DUMP_TYPE minidump_type, const char *dump_path)
+{
+    ReleaseHolder<CrashInfo> crashInfo;
+    int exitCode = prepare_crash_info(pid, statuses, statuses_count, minidump_type, crashInfo);
+
+    if (exitCode != REGERR_OK)
+        return exitCode;
+
+    DumpWriter dumpWriter(*crashInfo);
+
+    if (!dumpWriter.OpenDump(dump_path))
+        exitCode = REGERR_OPENDUMP_ERROR;
+
+    if (!dumpWriter.WriteDump())
+        exitCode = REGERR_WRITEDUMP_ERROR;
+
+    return exitCode;
+}
+
+void
+printf_status(const char* format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    fprintf(stdout, "[createdump] ");
+    vfprintf(stdout, format, args);
+    fflush(stdout);
+    va_end(args);
+}
+
+void
+printf_error(const char* format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    fprintf(stderr, "[createdump] ");
+    vfprintf(stderr, format, args);
+    fflush(stderr);
+    va_end(args);
+}
+
+void
+trace_printf(const char* format, ...)
+{
+    if (g_diagnostics)
+    {
+        va_list args;
+        va_start(args, format);
+        fprintf(stdout, "[dnetmemoryenumlib] ");
+        vfprintf(stdout, format, args);
+        fflush(stdout);
+        va_end(args);
+    }
+}
+
+void
+trace_verbose_printf(const char* format, ...)
+{
+    if (g_diagnosticsVerbose)
+    {
+        va_list args;
+        va_start(args, format);
+        fprintf(stdout, "[dnetmemoryenumlib] ");
+        vfprintf(stdout, format, args);
+        fflush(stdout);
+        va_end(args);
+    }
+}
+
+#ifdef HOST_UNIX
+void
+CrashInfo::Trace(const char* format, ...)
+{
+    if (g_diagnostics)
+    {
+        va_list args;
+        va_start(args, format);
+        fprintf(stdout, "[dnetmemoryenumlib] ");
+        vfprintf(stdout, format, args);
+        fflush(stdout);
+        va_end(args);
+    }
+}
+
+void
+CrashInfo::TraceVerbose(const char* format, ...)
+{
+    if (g_diagnosticsVerbose)
+    {
+        va_list args;
+        va_start(args, format);
+        fprintf(stdout, "[dnetmemoryenumlib] ");
+        vfprintf(stdout, format, args);
+        fflush(stdout);
+        va_end(args);
+    }
+}
+#endif
+
+const char*
+GetDumpTypeString(DumpType dumpType)
+{
+    switch (dumpType)
+    {
+        case DumpType::Mini:
+            return "minidump";
+        case DumpType::Heap:
+            return "minidump with heap";
+        case DumpType::Triage:
+            return "triage minidump";
+        case DumpType::Full:
+            return "full dump";
+        default:
+            return "unknown";
+    }
+}
+
+MINIDUMP_TYPE
+GetMiniDumpType(DumpType dumpType)
+{
+    switch (dumpType)
+    {
+        case DumpType::Mini:
+            return (MINIDUMP_TYPE)(MiniDumpNormal |
+                                   MiniDumpWithDataSegs |
+                                   MiniDumpWithHandleData |
+                                   MiniDumpWithThreadInfo);
+        case DumpType::Heap:
+            return (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory |
+                                   MiniDumpWithDataSegs |
+                                   MiniDumpWithHandleData |
+                                   MiniDumpWithUnloadedModules |
+                                   MiniDumpWithFullMemoryInfo |
+                                   MiniDumpWithThreadInfo |
+                                   MiniDumpWithTokenInformation);
+        case DumpType::Triage:
+            return (MINIDUMP_TYPE)(MiniDumpFilterTriage |
+                                   MiniDumpIgnoreInaccessibleMemory |
+                                   MiniDumpWithoutOptionalData |
+                                   MiniDumpWithProcessThreadData |
+                                   MiniDumpFilterModulePaths |
+                                   MiniDumpWithUnloadedModules |
+                                   MiniDumpFilterMemory |
+                                   MiniDumpWithHandleData);
+        case DumpType::Full:
+        default:
+            return (MINIDUMP_TYPE)(MiniDumpWithFullMemory |
+                                   MiniDumpWithDataSegs |
+                                   MiniDumpWithHandleData |
+                                   MiniDumpWithUnloadedModules |
+                                   MiniDumpWithFullMemoryInfo |
+                                   MiniDumpWithThreadInfo |
+                                   MiniDumpWithTokenInformation);
+    }
+}
diff --git a/src/coreclr/debug/createdump/dnetmemoryenumlib.h b/src/coreclr/debug/createdump/dnetmemoryenumlib.h
new file mode 100644 (file)
index 0000000..0823d97
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019-2024 Samsung Electronics Co., Ltd.
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __DNETMEMORYENUMLIB_H__
+#define __DNETMEMORYENUMLIB_H__
+
+#include <stdint.h>
+#include <stdlib.h>
+
+struct SimpleMemoryRegion {
+    uintptr_t m_startAddress;
+    size_t m_size;
+};
+
+enum DUMP_TYPE {
+    DT_NORMAL = 0,
+    DT_WITH_PRIV_AND_SHARED_MEM,
+    DT_FULL
+};
+
+enum REG_ERR {
+    REGERR_OK = 0,
+    REGERR_WRONG_PID = -1,
+    REGERR_INITIALIZATION_ERROR = -2,
+    REGERR_ENUMERATION_ERROR = -3,
+    REGERR_OPENDUMP_ERROR = -4,
+    REGERR_WRITEDUMP_ERROR = -5,
+    REGERR_ENUMERATIONDAC_ERROR  = -6,
+    REGERR_CRASHINFO_INITIALIZE_ERROR = -7,
+    REGERR_GATHER_CRASHINFO_ERROR = -8,
+};
+
+extern "C" DLLEXPORT int DotNetMemoryWriteDump(pid_t pid, elf_prstatus **statuses, int statuses_count,
+                                       DUMP_TYPE minidump_type,  const char *dump_path);
+extern "C" DLLEXPORT int DotNetMemoryEnumInit();
+extern "C" DLLEXPORT void DotNetMemoryEnumFinish();
+
+#endif
index 9d4e837..9c908ad 100644 (file)
@@ -396,3 +396,99 @@ ThreadInfo::IsCrashThread() const
 {
     return m_tid == m_crashInfo.CrashThread();
 }
+
+void ThreadInfo::SetRegisters(elf_prstatus *prstatus)
+{
+#if defined(__x86_64__)
+    struct user_regs_struct *u_reg = (struct user_regs_struct *)&prstatus->pr_reg;
+    m_gpRegisters.rip = u_reg->rip;
+    m_gpRegisters.rbp = u_reg->rbp;
+    m_gpRegisters.rsp = u_reg->rsp;
+
+    m_gpRegisters.rax = u_reg->rax;
+    m_gpRegisters.rbx = u_reg->rbx;
+    m_gpRegisters.rcx = u_reg->rcx;
+    m_gpRegisters.rdx = u_reg->rdx;
+    m_gpRegisters.rsi = u_reg->rsi;
+    m_gpRegisters.rdi = u_reg->rdi;
+
+    m_gpRegisters.cs = u_reg->cs;
+    m_gpRegisters.gs = u_reg->gs;
+    m_gpRegisters.es = u_reg->es;
+    m_gpRegisters.fs = u_reg->fs;
+    m_gpRegisters.ds = u_reg->ds;
+    m_gpRegisters.ss = u_reg->ss;
+    m_gpRegisters.fs_base = u_reg->fs_base;
+    m_gpRegisters.gs_base = u_reg->gs_base;
+
+    m_gpRegisters.orig_rax = u_reg->orig_rax;
+
+    m_gpRegisters.r8 = u_reg->r8;
+    m_gpRegisters.r9 = u_reg->r9;
+    m_gpRegisters.r10 = u_reg->r10;
+    m_gpRegisters.r11 = u_reg->r11;
+    m_gpRegisters.r12 = u_reg->r12;
+    m_gpRegisters.r13 = u_reg->r13;
+    m_gpRegisters.r14 = u_reg->r14;
+    m_gpRegisters.r15 = u_reg->r15;
+
+    m_gpRegisters.eflags = u_reg->eflags;
+#elif defined(__i386__)
+    struct user_regs_struct *u_reg = (struct user_regs_struct *)&prstatus->pr_reg;
+    m_gpRegisters.ebx = u_reg->ebx;
+    m_gpRegisters.ecx = u_reg->ecx;
+    m_gpRegisters.edx = u_reg->edx;
+    m_gpRegisters.esi = u_reg->esi;
+    m_gpRegisters.edi = u_reg->edi;
+    m_gpRegisters.ebp = u_reg->ebp;
+    m_gpRegisters.eax = u_reg->eax;
+    m_gpRegisters.xds = u_reg->xds;
+    m_gpRegisters.xes = u_reg->xes;
+    m_gpRegisters.xfs = u_reg->xfs;
+    m_gpRegisters.xgs = u_reg->xgs;
+    m_gpRegisters.orig_eax = u_reg->orig_eax;
+    m_gpRegisters.eip = u_reg->eip;
+    m_gpRegisters.xcs = u_reg->xcs;
+    m_gpRegisters.eflags = u_reg->eflags;
+    m_gpRegisters.esp = u_reg->esp;
+    m_gpRegisters.xss = u_reg->xss;
+#elif defined(__arm__)
+
+#define REGS_REGULAR_NUM 13
+#define REG_FP 11
+#define REG_IP 12
+#define REG_SP 13
+#define REG_LR 14
+#define REG_PC 15
+#define REG_SPSR 16
+    struct user_regs *u_reg = (struct user_regs *)&prstatus->pr_reg;
+    m_gpRegisters.ARM_sp = u_reg->uregs[REG_SP];
+    m_gpRegisters.ARM_lr = u_reg->uregs[REG_LR];
+    m_gpRegisters.ARM_pc = u_reg->uregs[REG_PC];
+    m_gpRegisters.ARM_cpsr = u_reg->uregs[REG_SPSR];
+
+    m_gpRegisters.ARM_r0 = u_reg->uregs[0];
+    m_gpRegisters.ARM_ORIG_r0 = u_reg->uregs[0];
+    m_gpRegisters.ARM_r1 = u_reg->uregs[1];
+    m_gpRegisters.ARM_r2 = u_reg->uregs[2];
+    m_gpRegisters.ARM_r3 = u_reg->uregs[3];
+    m_gpRegisters.ARM_r4 = u_reg->uregs[4];
+    m_gpRegisters.ARM_r5 = u_reg->uregs[5];
+    m_gpRegisters.ARM_r6 = u_reg->uregs[6];
+    m_gpRegisters.ARM_r7 = u_reg->uregs[7];
+    m_gpRegisters.ARM_r8 = u_reg->uregs[8];
+    m_gpRegisters.ARM_r9 = u_reg->uregs[9];
+    m_gpRegisters.ARM_r10 = u_reg->uregs[10];
+    m_gpRegisters.ARM_fp = u_reg->uregs[REG_FP];
+    m_gpRegisters.ARM_ip = u_reg->uregs[REG_IP];
+#elif defined(__aarch64__)
+    struct user_regs_struct *u_reg = (struct user_regs_struct *)&prstatus->pr_reg;
+    memcpy(m_gpRegisters.regs, u_reg, sizeof(m_gpRegisters.regs));
+    m_gpRegisters.sp = u_reg->sp;
+    m_gpRegisters.pc = u_reg->pc;
+    m_gpRegisters.pstate = u_reg->pstate;
+#elif defined(__riscv)
+    struct user_regs_struct *u_reg = (struct user_regs_struct *)&prstatus->pr_reg;
+    memcpy(&m_gpRegisters, u_reg, sizeof(m_gpRegisters));
+#endif
+}
index d9f38a7..8d93fbe 100644 (file)
@@ -112,6 +112,7 @@ public:
     bool UnwindThread(IXCLRDataProcess* pClrDataProcess, ISOSDacInterface* pSos);
     void GetThreadStack();
     void GetThreadContext(uint32_t flags, CONTEXT* context) const;
+    void SetRegisters(elf_prstatus *prstatus);
 
     inline pid_t Tid() const { return m_tid; }
     inline pid_t Ppid() const { return m_ppid; }