mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2026-03-18 10:39:26 +00:00
Added riscv and riscv64 support for Linux
Change-Id: I62cd157d00a87720db001072662a81d8eb9112b0 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/3873291 Reviewed-by: Mike Frysinger <vapier@chromium.org>
This commit is contained in:
committed by
Mike Frysinger
parent
e059dad5ea
commit
28cf16bc34
@@ -43,6 +43,14 @@ typedef MDRawContextARM RawContextCPU;
|
||||
typedef MDRawContextARM64_Old RawContextCPU;
|
||||
#elif defined(__mips__)
|
||||
typedef MDRawContextMIPS RawContextCPU;
|
||||
#elif defined(__riscv)
|
||||
# if __riscv_xlen == 32
|
||||
typedef MDRawContextRISCV RawContextCPU;
|
||||
# elif __riscv_xlen == 64
|
||||
typedef MDRawContextRISCV64 RawContextCPU;
|
||||
# else
|
||||
# error "Unexpected __riscv_xlen"
|
||||
# endif
|
||||
#else
|
||||
#error "This code has not been ported to your platform yet."
|
||||
#endif
|
||||
|
||||
@@ -269,7 +269,74 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
|
||||
out->float_save.fir = mcontext.fpc_eir;
|
||||
#endif
|
||||
}
|
||||
#endif // __mips__
|
||||
|
||||
#elif defined(__riscv)
|
||||
|
||||
uintptr_t ThreadInfo::GetInstructionPointer() const {
|
||||
return mcontext.__gregs[0];
|
||||
}
|
||||
|
||||
void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
|
||||
# if __riscv__xlen == 32
|
||||
out->context_flags = MD_CONTEXT_RISCV_FULL;
|
||||
# elif __riscv_xlen == 64
|
||||
out->context_flags = MD_CONTEXT_RISCV64_FULL;
|
||||
# else
|
||||
# error "Unexpected __riscv_xlen"
|
||||
# endif
|
||||
|
||||
out->pc = mcontext.__gregs[0];
|
||||
out->ra = mcontext.__gregs[1];
|
||||
out->sp = mcontext.__gregs[2];
|
||||
out->gp = mcontext.__gregs[3];
|
||||
out->tp = mcontext.__gregs[4];
|
||||
out->t0 = mcontext.__gregs[5];
|
||||
out->t1 = mcontext.__gregs[6];
|
||||
out->t2 = mcontext.__gregs[7];
|
||||
out->s0 = mcontext.__gregs[8];
|
||||
out->s1 = mcontext.__gregs[9];
|
||||
out->a0 = mcontext.__gregs[10];
|
||||
out->a1 = mcontext.__gregs[11];
|
||||
out->a2 = mcontext.__gregs[12];
|
||||
out->a3 = mcontext.__gregs[13];
|
||||
out->a4 = mcontext.__gregs[14];
|
||||
out->a5 = mcontext.__gregs[15];
|
||||
out->a6 = mcontext.__gregs[16];
|
||||
out->a7 = mcontext.__gregs[17];
|
||||
out->s2 = mcontext.__gregs[18];
|
||||
out->s3 = mcontext.__gregs[19];
|
||||
out->s4 = mcontext.__gregs[20];
|
||||
out->s5 = mcontext.__gregs[21];
|
||||
out->s6 = mcontext.__gregs[22];
|
||||
out->s7 = mcontext.__gregs[23];
|
||||
out->s8 = mcontext.__gregs[24];
|
||||
out->s9 = mcontext.__gregs[25];
|
||||
out->s10 = mcontext.__gregs[26];
|
||||
out->s11 = mcontext.__gregs[27];
|
||||
out->t3 = mcontext.__gregs[28];
|
||||
out->t4 = mcontext.__gregs[29];
|
||||
out->t5 = mcontext.__gregs[30];
|
||||
out->t6 = mcontext.__gregs[31];
|
||||
|
||||
# if __riscv_flen == 32
|
||||
for(int i = 0; i < MD_FLOATINGSAVEAREA_RISCV_FPR_COUNT; i++)
|
||||
out->float_save.regs[i] = mcontext.__fpregs.__f.__f[i];
|
||||
out->float_save.fpcsr = mcontext.__fpregs.__f.__fcsr;
|
||||
# elif __riscv_flen == 64
|
||||
for(int i = 0; i < MD_FLOATINGSAVEAREA_RISCV_FPR_COUNT; i++)
|
||||
out->float_save.regs[i] = mcontext.__fpregs.__d.__f[i];
|
||||
out->float_save.fpcsr = mcontext.__fpregs.__d.__fcsr;
|
||||
# elif __riscv_flen == 128
|
||||
for(int i = 0; i < MD_FLOATINGSAVEAREA_RISCV_FPR_COUNT; i++) {
|
||||
out->float_save.regs[i].high = mcontext.__fpregs.__q.__f[2*i];
|
||||
out->float_save.regs[i].low = mcontext.__fpregs.__q.__f[2*i+1];
|
||||
}
|
||||
out->float_save.fpcsr = mcontext.__fpregs.__q.__fcsr;
|
||||
# else
|
||||
# error "Unexpected __riscv_flen"
|
||||
# endif
|
||||
}
|
||||
#endif // __riscv
|
||||
|
||||
void ThreadInfo::GetGeneralPurposeRegisters(void** gp_regs, size_t* size) {
|
||||
assert(gp_regs || size);
|
||||
@@ -278,6 +345,11 @@ void ThreadInfo::GetGeneralPurposeRegisters(void** gp_regs, size_t* size) {
|
||||
*gp_regs = mcontext.gregs;
|
||||
if (size)
|
||||
*size = sizeof(mcontext.gregs);
|
||||
#elif defined(__riscv)
|
||||
if (gp_regs)
|
||||
*gp_regs = mcontext.__gregs;
|
||||
if (size)
|
||||
*size = sizeof(mcontext.__gregs);
|
||||
#else
|
||||
if (gp_regs)
|
||||
*gp_regs = ®s;
|
||||
@@ -293,6 +365,25 @@ void ThreadInfo::GetFloatingPointRegisters(void** fp_regs, size_t* size) {
|
||||
*fp_regs = &mcontext.fpregs;
|
||||
if (size)
|
||||
*size = sizeof(mcontext.fpregs);
|
||||
#elif defined(__riscv)
|
||||
# if __riscv_flen == 32
|
||||
if (fp_regs)
|
||||
*fp_regs = &mcontext.__fpregs.__f.__f;
|
||||
if (size)
|
||||
*size = sizeof(mcontext.__fpregs.__f.__f);
|
||||
# elif __riscv_flen == 64
|
||||
if (fp_regs)
|
||||
*fp_regs = &mcontext.__fpregs.__d.__f;
|
||||
if (size)
|
||||
*size = sizeof(mcontext.__fpregs.__d.__f);
|
||||
# elif __riscv_flen == 128
|
||||
if (fp_regs)
|
||||
*fp_regs = &mcontext.__fpregs.__q.__f;
|
||||
if (size)
|
||||
*size = sizeof(mcontext.__fpregs.__q.__f);
|
||||
# else
|
||||
# error "Unexpected __riscv_flen"
|
||||
# endif
|
||||
#else
|
||||
if (fp_regs)
|
||||
*fp_regs = &fpregs;
|
||||
|
||||
@@ -67,7 +67,7 @@ struct ThreadInfo {
|
||||
// Use the structures defined in <sys/user.h>
|
||||
struct user_regs_struct regs;
|
||||
struct user_fpsimd_struct fpregs;
|
||||
#elif defined(__mips__)
|
||||
#elif defined(__mips__) || defined(__riscv)
|
||||
// Use the structure defined in <sys/ucontext.h>.
|
||||
mcontext_t mcontext;
|
||||
#endif
|
||||
|
||||
@@ -253,6 +253,75 @@ void UContextReader::FillCPUContext(RawContextCPU* out, const ucontext_t* uc) {
|
||||
out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(__riscv)
|
||||
|
||||
uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
|
||||
return uc->uc_mcontext.__gregs[MD_CONTEXT_RISCV_REG_SP];
|
||||
}
|
||||
|
||||
uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
|
||||
return uc->uc_mcontext.__gregs[MD_CONTEXT_RISCV_REG_PC];
|
||||
}
|
||||
|
||||
void UContextReader::FillCPUContext(RawContextCPU* out, const ucontext_t* uc) {
|
||||
# if __riscv__xlen == 32
|
||||
out->context_flags = MD_CONTEXT_RISCV_FULL;
|
||||
# elif __riscv_xlen == 64
|
||||
out->context_flags = MD_CONTEXT_RISCV64_FULL;
|
||||
# else
|
||||
# error "Unexpected __riscv_xlen"
|
||||
# endif
|
||||
|
||||
out->pc = uc->uc_mcontext.__gregs[0];
|
||||
out->ra = uc->uc_mcontext.__gregs[1];
|
||||
out->sp = uc->uc_mcontext.__gregs[2];
|
||||
out->gp = uc->uc_mcontext.__gregs[3];
|
||||
out->tp = uc->uc_mcontext.__gregs[4];
|
||||
out->t0 = uc->uc_mcontext.__gregs[5];
|
||||
out->t1 = uc->uc_mcontext.__gregs[6];
|
||||
out->t2 = uc->uc_mcontext.__gregs[7];
|
||||
out->s0 = uc->uc_mcontext.__gregs[8];
|
||||
out->s1 = uc->uc_mcontext.__gregs[9];
|
||||
out->a0 = uc->uc_mcontext.__gregs[10];
|
||||
out->a1 = uc->uc_mcontext.__gregs[11];
|
||||
out->a2 = uc->uc_mcontext.__gregs[12];
|
||||
out->a3 = uc->uc_mcontext.__gregs[13];
|
||||
out->a4 = uc->uc_mcontext.__gregs[14];
|
||||
out->a5 = uc->uc_mcontext.__gregs[15];
|
||||
out->a6 = uc->uc_mcontext.__gregs[16];
|
||||
out->a7 = uc->uc_mcontext.__gregs[17];
|
||||
out->s2 = uc->uc_mcontext.__gregs[18];
|
||||
out->s3 = uc->uc_mcontext.__gregs[19];
|
||||
out->s4 = uc->uc_mcontext.__gregs[20];
|
||||
out->s5 = uc->uc_mcontext.__gregs[21];
|
||||
out->s6 = uc->uc_mcontext.__gregs[22];
|
||||
out->s7 = uc->uc_mcontext.__gregs[23];
|
||||
out->s8 = uc->uc_mcontext.__gregs[24];
|
||||
out->s9 = uc->uc_mcontext.__gregs[25];
|
||||
out->s10 = uc->uc_mcontext.__gregs[26];
|
||||
out->s11 = uc->uc_mcontext.__gregs[27];
|
||||
out->t3 = uc->uc_mcontext.__gregs[28];
|
||||
out->t4 = uc->uc_mcontext.__gregs[29];
|
||||
out->t5 = uc->uc_mcontext.__gregs[30];
|
||||
out->t6 = uc->uc_mcontext.__gregs[31];
|
||||
|
||||
# if __riscv_flen == 32
|
||||
for(int i = 0; i < MD_FLOATINGSAVEAREA_RISCV_FPR_COUNT; i++)
|
||||
out->float_save.regs[i] = uc->uc_mcontext.__fpregs.__f.__f[i];
|
||||
out->float_save.fpcsr = uc->uc_mcontext.__fpregs.__f.__fcsr;
|
||||
# elif __riscv_flen == 64
|
||||
for(int i = 0; i < MD_FLOATINGSAVEAREA_RISCV_FPR_COUNT; i++)
|
||||
out->float_save.regs[i] = uc->uc_mcontext.__fpregs.__d.__f[i];
|
||||
out->float_save.fpcsr = uc->uc_mcontext.__fpregs.__d.__fcsr;
|
||||
# elif __riscv_flen == 128
|
||||
for(int i = 0; i < MD_FLOATINGSAVEAREA_RISCV_FPR_COUNT; i++) {
|
||||
out->float_save.regs[i].high = uc->uc_mcontext.__fpregs.__q.__f[2*i];
|
||||
out->float_save.regs[i].low = uc->uc_mcontext.__fpregs.__q.__f[2*i+1];
|
||||
}
|
||||
out->float_save.fpcsr = uc->uc_mcontext.__fpregs.__q.__fcsr;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
@@ -461,9 +461,6 @@ bool ExceptionHandler::HandleSignal(int /*sig*/, siginfo_t* info, void* uc) {
|
||||
sizeof(g_crash_context_.float_state));
|
||||
}
|
||||
#elif GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE
|
||||
// FP state is not part of user ABI on ARM Linux.
|
||||
// In case of MIPS Linux FP state is already part of ucontext_t
|
||||
// and 'float_state' is not a member of CrashContext.
|
||||
ucontext_t* uc_ptr = (ucontext_t*)uc;
|
||||
if (uc_ptr->uc_mcontext.fpregs) {
|
||||
memcpy(&g_crash_context_.float_state, uc_ptr->uc_mcontext.fpregs,
|
||||
@@ -701,7 +698,6 @@ bool ExceptionHandler::WriteMinidump() {
|
||||
#endif
|
||||
|
||||
#if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE && !defined(__aarch64__)
|
||||
// FPU state is not part of ARM EABI ucontext_t.
|
||||
memcpy(&context.float_state, context.context.uc_mcontext.fpregs,
|
||||
sizeof(context.float_state));
|
||||
#endif
|
||||
@@ -725,8 +721,11 @@ bool ExceptionHandler::WriteMinidump() {
|
||||
#elif defined(__mips__)
|
||||
context.siginfo.si_addr =
|
||||
reinterpret_cast<void*>(context.context.uc_mcontext.pc);
|
||||
#elif defined(__riscv)
|
||||
context.siginfo.si_addr =
|
||||
reinterpret_cast<void*>(context.context.uc_mcontext.__gregs[REG_PC]);
|
||||
#else
|
||||
#error "This code has not been ported to your platform yet."
|
||||
# error "This code has not been ported to your platform yet."
|
||||
#endif
|
||||
|
||||
return GenerateDump(&context);
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include "common/using_std_string.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__) && !defined(__riscv)
|
||||
// FP state is not part of user ABI for Linux ARM.
|
||||
// In case of MIPS and RISCV Linux FP state is already part of ucontext_t
|
||||
// so 'float_state' is not required.
|
||||
|
||||
@@ -335,9 +335,17 @@ class MicrodumpWriter {
|
||||
const char kArch[] = "mips64";
|
||||
# else
|
||||
# error "This mips ABI is currently not supported (n32)"
|
||||
#endif
|
||||
# endif
|
||||
#elif defined(__riscv)
|
||||
# if __riscv_xlen == 32
|
||||
const char kArch[] = "riscv32";
|
||||
# elif __riscv_xlen == 64
|
||||
const char kArch[] = "riscv64";
|
||||
# else
|
||||
# error "Unexpected __riscv_xlen"
|
||||
# endif
|
||||
#else
|
||||
#error "This code has not been ported to your platform yet"
|
||||
# error "This code has not been ported to your platform yet"
|
||||
#endif
|
||||
|
||||
LogAppend("O ");
|
||||
|
||||
@@ -111,8 +111,11 @@ bool LinuxCoreDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
|
||||
#elif defined(__mips__)
|
||||
stack_pointer =
|
||||
reinterpret_cast<uint8_t*>(info->mcontext.gregs[MD_CONTEXT_MIPS_REG_SP]);
|
||||
#elif defined(__riscv)
|
||||
stack_pointer = reinterpret_cast<uint8_t*>(
|
||||
info->mcontext.__gregs[MD_CONTEXT_RISCV_REG_SP]);
|
||||
#else
|
||||
#error "This code hasn't been ported to your platform yet."
|
||||
# error "This code hasn't been ported to your platform yet."
|
||||
#endif
|
||||
info->stack_pointer = reinterpret_cast<uintptr_t>(stack_pointer);
|
||||
return true;
|
||||
@@ -207,19 +210,22 @@ bool LinuxCoreDumper::EnumerateThreads() {
|
||||
info.tgid = status->pr_pgrp;
|
||||
info.ppid = status->pr_ppid;
|
||||
#if defined(__mips__)
|
||||
#if defined(__ANDROID__)
|
||||
# if defined(__ANDROID__)
|
||||
for (int i = EF_R0; i <= EF_R31; i++)
|
||||
info.mcontext.gregs[i - EF_R0] = status->pr_reg[i];
|
||||
#else // __ANDROID__
|
||||
# else // __ANDROID__
|
||||
for (int i = EF_REG0; i <= EF_REG31; i++)
|
||||
info.mcontext.gregs[i - EF_REG0] = status->pr_reg[i];
|
||||
#endif // __ANDROID__
|
||||
# endif // __ANDROID__
|
||||
info.mcontext.mdlo = status->pr_reg[EF_LO];
|
||||
info.mcontext.mdhi = status->pr_reg[EF_HI];
|
||||
info.mcontext.pc = status->pr_reg[EF_CP0_EPC];
|
||||
#else // __mips__
|
||||
#elif defined(__riscv)
|
||||
memcpy(&info.mcontext.__gregs, status->pr_reg,
|
||||
sizeof(info.mcontext.__gregs));
|
||||
#else // __riscv
|
||||
memcpy(&info.regs, status->pr_reg, sizeof(info.regs));
|
||||
#endif // __mips__
|
||||
#endif
|
||||
if (first_thread) {
|
||||
crash_thread_ = pid;
|
||||
crash_signal_ = status->pr_info.si_signo;
|
||||
|
||||
@@ -59,10 +59,12 @@ namespace google_breakpad {
|
||||
|
||||
// Typedef for our parsing of the auxv variables in /proc/pid/auxv.
|
||||
#if defined(__i386) || defined(__ARM_EABI__) || \
|
||||
(defined(__mips__) && _MIPS_SIM == _ABIO32)
|
||||
(defined(__mips__) && _MIPS_SIM == _ABIO32) || \
|
||||
(defined(__riscv) && __riscv_xlen == 32)
|
||||
typedef Elf32_auxv_t elf_aux_entry;
|
||||
#elif defined(__x86_64) || defined(__aarch64__) || \
|
||||
(defined(__mips__) && _MIPS_SIM != _ABIO32)
|
||||
(defined(__mips__) && _MIPS_SIM != _ABIO32) || \
|
||||
(defined(__riscv) && __riscv_xlen == 64)
|
||||
typedef Elf64_auxv_t elf_aux_entry;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
#define TID_PTR_REGISTER "rcx"
|
||||
#elif defined(__mips__)
|
||||
#define TID_PTR_REGISTER "$1"
|
||||
#elif defined(__riscv)
|
||||
#define TID_PTR_REGISTER "x4"
|
||||
#else
|
||||
#error This test has not been ported to this platform.
|
||||
#endif
|
||||
|
||||
@@ -297,8 +297,11 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
|
||||
#elif defined(__mips__)
|
||||
stack_pointer =
|
||||
reinterpret_cast<uint8_t*>(info->mcontext.gregs[MD_CONTEXT_MIPS_REG_SP]);
|
||||
#elif defined(__riscv)
|
||||
stack_pointer = reinterpret_cast<uint8_t*>(
|
||||
info->mcontext.__gregs[MD_CONTEXT_RISCV_REG_SP]);
|
||||
#else
|
||||
#error "This code hasn't been ported to your platform yet."
|
||||
# error "This code hasn't been ported to your platform yet."
|
||||
#endif
|
||||
info->stack_pointer = reinterpret_cast<uintptr_t>(stack_pointer);
|
||||
|
||||
|
||||
@@ -463,6 +463,9 @@ TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) {
|
||||
#elif defined(__mips__)
|
||||
pid_t* process_tid_location =
|
||||
reinterpret_cast<pid_t*>(one_thread.mcontext.gregs[1]);
|
||||
#elif defined(__riscv)
|
||||
pid_t* process_tid_location =
|
||||
reinterpret_cast<pid_t*>(one_thread.mcontext.__gregs[4]);
|
||||
#else
|
||||
#error This test has not been ported to this platform.
|
||||
#endif
|
||||
@@ -560,6 +563,8 @@ TEST_F(LinuxPtraceDumperTest, SanitizeStackCopy) {
|
||||
uintptr_t heap_addr = thread_info.regs.rcx;
|
||||
#elif defined(__mips__)
|
||||
uintptr_t heap_addr = thread_info.mcontext.gregs[1];
|
||||
#elif defined(__riscv)
|
||||
uintptr_t heap_addr = thread_info.mcontext.__gregs[4];
|
||||
#else
|
||||
#error This test has not been ported to this platform.
|
||||
#endif
|
||||
|
||||
@@ -1137,9 +1137,7 @@ class MinidumpWriter {
|
||||
sys_close(fd);
|
||||
|
||||
cpus_present.IntersectWith(cpus_possible);
|
||||
int cpu_count = cpus_present.GetCount();
|
||||
if (cpu_count > 255)
|
||||
cpu_count = 255;
|
||||
int cpu_count = std::min(255, cpus_present.GetCount());
|
||||
sys_info->number_of_processors = static_cast<uint8_t>(cpu_count);
|
||||
}
|
||||
}
|
||||
@@ -1255,6 +1253,59 @@ class MinidumpWriter {
|
||||
sys_close(fd);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#elif defined(__riscv)
|
||||
bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
|
||||
// processor_architecture should always be set, do this first
|
||||
# if __riscv_xlen == 32
|
||||
sys_info->processor_architecture = MD_CPU_ARCHITECTURE_RISCV;
|
||||
# elif __riscv_xlen == 64
|
||||
sys_info->processor_architecture = MD_CPU_ARCHITECTURE_RISCV64;
|
||||
# else
|
||||
# error "Unexpected __riscv_xlen"
|
||||
# endif
|
||||
|
||||
// /proc/cpuinfo is not readable under various sandboxed environments
|
||||
// (e.g. Android services with the android:isolatedProcess attribute)
|
||||
// prepare for this by setting default values now, which will be
|
||||
// returned when this happens.
|
||||
//
|
||||
// Note: Bogus values are used to distinguish between failures (to
|
||||
// read /sys and /proc files) and really badly configured kernels.
|
||||
sys_info->number_of_processors = 0;
|
||||
sys_info->processor_level = 0U;
|
||||
sys_info->processor_revision = 42;
|
||||
sys_info->cpu.other_cpu_info.processor_features[0] = 0;
|
||||
sys_info->cpu.other_cpu_info.processor_features[1] = 0;
|
||||
|
||||
// Counting the number of CPUs involves parsing two sysfs files,
|
||||
// because the content of /proc/cpuinfo will only mirror the number
|
||||
// of 'online' cores, and thus will vary with time.
|
||||
// See http://www.kernel.org/doc/Documentation/cputopology.txt
|
||||
{
|
||||
CpuSet cpus_present;
|
||||
CpuSet cpus_possible;
|
||||
|
||||
int fd = sys_open("/sys/devices/system/cpu/present",
|
||||
O_RDONLY | O_CLOEXEC, 0);
|
||||
if (fd >= 0) {
|
||||
cpus_present.ParseSysFile(fd);
|
||||
sys_close(fd);
|
||||
|
||||
fd = sys_open("/sys/devices/system/cpu/possible",
|
||||
O_RDONLY | O_CLOEXEC, 0);
|
||||
if (fd >= 0) {
|
||||
cpus_possible.ParseSysFile(fd);
|
||||
sys_close(fd);
|
||||
|
||||
cpus_present.IntersectWith(cpus_possible);
|
||||
int cpu_count = std::min(255, cpus_present.GetCount());
|
||||
sys_info->number_of_processors = static_cast<uint8_t>(cpu_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -716,6 +716,9 @@ TEST(MinidumpWriterTest, InvalidStackPointer) {
|
||||
#elif defined(__mips__)
|
||||
context.context.uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP] =
|
||||
invalid_stack_pointer;
|
||||
#elif defined(__riscv)
|
||||
context.context.uc_mcontext.__gregs[MD_CONTEXT_RISCV_REG_SP] =
|
||||
invalid_stack_pointer;
|
||||
#else
|
||||
# error "This code has not been ported to your platform yet."
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user