mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2026-03-05 04:06:32 +00:00
Adding support for mips.
Support for mips cpu is added to all breakapad targets including unittests. BUG=none TEST=unittests Review URL: https://breakpad.appspot.com/614002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1212 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
@@ -396,8 +396,10 @@ bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
|
||||
CrashContext context;
|
||||
memcpy(&context.siginfo, info, sizeof(siginfo_t));
|
||||
memcpy(&context.context, uc, sizeof(struct ucontext));
|
||||
#if !defined(__ARM_EABI__)
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
// FP state is not part of user ABI on ARM Linux.
|
||||
// In case of MIPS Linux FP state is already part of struct ucontext
|
||||
// and 'float_state' is not a member of CrashContext.
|
||||
struct ucontext *uc_ptr = (struct ucontext*)uc;
|
||||
if (uc_ptr->uc_mcontext.fpregs) {
|
||||
memcpy(&context.float_state,
|
||||
@@ -602,7 +604,7 @@ bool ExceptionHandler::WriteMinidump() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(__ARM_EABI__)
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
// FPU state is not part of ARM EABI ucontext_t.
|
||||
memcpy(&context.float_state, context.context.uc_mcontext.fpregs,
|
||||
sizeof(context.float_state));
|
||||
@@ -621,6 +623,9 @@ bool ExceptionHandler::WriteMinidump() {
|
||||
#elif defined(__arm__)
|
||||
context.siginfo.si_addr =
|
||||
reinterpret_cast<void*>(context.context.uc_mcontext.arm_pc);
|
||||
#elif defined(__mips__)
|
||||
context.siginfo.si_addr =
|
||||
reinterpret_cast<void*>(context.context.uc_mcontext.pc);
|
||||
#else
|
||||
#error "This code has not been ported to your platform yet."
|
||||
#endif
|
||||
|
||||
@@ -190,8 +190,10 @@ class ExceptionHandler {
|
||||
siginfo_t siginfo;
|
||||
pid_t tid; // the crashing thread.
|
||||
struct ucontext context;
|
||||
#if !defined(__ARM_EABI__)
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
// #ifdef this out because FP state is not part of user ABI for Linux ARM.
|
||||
// In case of MIPS Linux FP state is already part of struct ucontext
|
||||
// so 'float_state' is not required.
|
||||
struct _libc_fpstate float_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
#if defined(__mips__)
|
||||
#include <sys/cachectl.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -55,7 +58,7 @@ using namespace google_breakpad;
|
||||
namespace {
|
||||
|
||||
// Flush the instruction cache for a given memory range.
|
||||
// Only required on ARM.
|
||||
// Only required on ARM and mips.
|
||||
void FlushInstructionCache(const char* memory, uint32_t memory_size) {
|
||||
#if defined(__arm__)
|
||||
long begin = reinterpret_cast<long>(memory);
|
||||
@@ -72,6 +75,13 @@ void FlushInstructionCache(const char* memory, uint32_t memory_size) {
|
||||
# else
|
||||
# error "Your operating system is not supported yet"
|
||||
# endif
|
||||
#elif defined(__mips__)
|
||||
# if defined(__linux__)
|
||||
// See http://www.linux-mips.org/wiki/Cacheflush_Syscall.
|
||||
cacheflush(const_cast<char*>(memory), memory_size, ICACHE);
|
||||
# else
|
||||
# error "Your operating system is not supported yet"
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -435,6 +445,16 @@ TEST(ExceptionHandlerTest, StackedHandlersUnhandledToBottom) {
|
||||
ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
|
||||
}
|
||||
|
||||
const unsigned char kIllegalInstruction[] = {
|
||||
#if defined(__mips__)
|
||||
// mfc2 zero,Impl - usually illegal in userspace.
|
||||
0x48, 0x00, 0x00, 0x48
|
||||
#else
|
||||
// This crashes with SIGILL on x86/x86-64/arm.
|
||||
0xff, 0xff, 0xff, 0xff
|
||||
#endif
|
||||
};
|
||||
|
||||
// Test that memory around the instruction pointer is written
|
||||
// to the dump as a MinidumpMemoryRegion.
|
||||
TEST(ExceptionHandlerTest, InstructionPointerMemory) {
|
||||
@@ -446,8 +466,6 @@ TEST(ExceptionHandlerTest, InstructionPointerMemory) {
|
||||
// data from the minidump afterwards.
|
||||
const uint32_t kMemorySize = 256; // bytes
|
||||
const int kOffset = kMemorySize / 2;
|
||||
// This crashes with SIGILL on x86/x86-64/arm.
|
||||
const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
const pid_t child = fork();
|
||||
if (child == 0) {
|
||||
@@ -469,7 +487,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemory) {
|
||||
// Write some instructions that will crash. Put them in the middle
|
||||
// of the block of memory, because the minidump should contain 128
|
||||
// bytes on either side of the instruction pointer.
|
||||
memcpy(memory + kOffset, instructions, sizeof(instructions));
|
||||
memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
|
||||
FlushInstructionCache(memory, kMemorySize);
|
||||
|
||||
// Now execute the instructions, which should crash.
|
||||
@@ -517,12 +535,13 @@ TEST(ExceptionHandlerTest, InstructionPointerMemory) {
|
||||
ASSERT_TRUE(bytes);
|
||||
|
||||
uint8_t prefix_bytes[kOffset];
|
||||
uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(instructions)];
|
||||
uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(kIllegalInstruction)];
|
||||
memset(prefix_bytes, 0, sizeof(prefix_bytes));
|
||||
memset(suffix_bytes, 0, sizeof(suffix_bytes));
|
||||
EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset, instructions, sizeof(instructions)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(instructions),
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction,
|
||||
sizeof(kIllegalInstruction)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
|
||||
suffix_bytes, sizeof(suffix_bytes)) == 0);
|
||||
|
||||
unlink(minidump_path.c_str());
|
||||
@@ -539,8 +558,6 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
|
||||
// data from the minidump afterwards.
|
||||
const uint32_t kMemorySize = 256; // bytes
|
||||
const int kOffset = 0;
|
||||
// This crashes with SIGILL on x86/x86-64/arm.
|
||||
const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
const pid_t child = fork();
|
||||
if (child == 0) {
|
||||
@@ -562,7 +579,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
|
||||
// Write some instructions that will crash. Put them in the middle
|
||||
// of the block of memory, because the minidump should contain 128
|
||||
// bytes on either side of the instruction pointer.
|
||||
memcpy(memory + kOffset, instructions, sizeof(instructions));
|
||||
memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
|
||||
FlushInstructionCache(memory, kMemorySize);
|
||||
|
||||
// Now execute the instructions, which should crash.
|
||||
@@ -609,10 +626,11 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
|
||||
const uint8_t* bytes = region->GetMemory();
|
||||
ASSERT_TRUE(bytes);
|
||||
|
||||
uint8_t suffix_bytes[kMemorySize / 2 - sizeof(instructions)];
|
||||
uint8_t suffix_bytes[kMemorySize / 2 - sizeof(kIllegalInstruction)];
|
||||
memset(suffix_bytes, 0, sizeof(suffix_bytes));
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset, instructions, sizeof(instructions)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(instructions),
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction,
|
||||
sizeof(kIllegalInstruction)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
|
||||
suffix_bytes, sizeof(suffix_bytes)) == 0);
|
||||
unlink(minidump_path.c_str());
|
||||
}
|
||||
@@ -630,9 +648,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
|
||||
// if a smaller size is requested, and this test wants to
|
||||
// test the upper bound of the memory range.
|
||||
const uint32_t kMemorySize = 4096; // bytes
|
||||
// This crashes with SIGILL on x86/x86-64/arm.
|
||||
const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
|
||||
const int kOffset = kMemorySize - sizeof(instructions);
|
||||
const int kOffset = kMemorySize - sizeof(kIllegalInstruction);
|
||||
|
||||
const pid_t child = fork();
|
||||
if (child == 0) {
|
||||
@@ -654,7 +670,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
|
||||
// Write some instructions that will crash. Put them in the middle
|
||||
// of the block of memory, because the minidump should contain 128
|
||||
// bytes on either side of the instruction pointer.
|
||||
memcpy(memory + kOffset, instructions, sizeof(instructions));
|
||||
memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
|
||||
FlushInstructionCache(memory, kMemorySize);
|
||||
|
||||
// Now execute the instructions, which should crash.
|
||||
@@ -697,7 +713,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
|
||||
ASSERT_TRUE(region);
|
||||
|
||||
const size_t kPrefixSize = 128; // bytes
|
||||
EXPECT_EQ(kPrefixSize + sizeof(instructions), region->GetSize());
|
||||
EXPECT_EQ(kPrefixSize + sizeof(kIllegalInstruction), region->GetSize());
|
||||
const uint8_t* bytes = region->GetMemory();
|
||||
ASSERT_TRUE(bytes);
|
||||
|
||||
@@ -705,7 +721,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
|
||||
memset(prefix_bytes, 0, sizeof(prefix_bytes));
|
||||
EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kPrefixSize,
|
||||
instructions, sizeof(instructions)) == 0);
|
||||
kIllegalInstruction, sizeof(kIllegalInstruction)) == 0);
|
||||
|
||||
unlink(minidump_path.c_str());
|
||||
}
|
||||
|
||||
@@ -99,6 +99,9 @@ bool LinuxCoreDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
|
||||
memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
|
||||
#elif defined(__ARM_EABI__)
|
||||
memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
|
||||
#elif defined(__mips__)
|
||||
stack_pointer =
|
||||
reinterpret_cast<uint8_t*>(info->regs.regs[MD_CONTEXT_MIPS_REG_SP]);
|
||||
#else
|
||||
#error "This code hasn't been ported to your platform yet."
|
||||
#endif
|
||||
|
||||
@@ -54,7 +54,7 @@ typedef typeof(((struct user*) 0)->u_debugreg[0]) debugreg_t;
|
||||
#endif
|
||||
|
||||
// Typedef for our parsing of the auxv variables in /proc/pid/auxv.
|
||||
#if defined(__i386) || defined(__ARM_EABI__)
|
||||
#if defined(__i386) || defined(__ARM_EABI__) || defined(__mips__)
|
||||
typedef Elf32_auxv_t elf_aux_entry;
|
||||
#elif defined(__x86_64)
|
||||
typedef Elf64_auxv_t elf_aux_entry;
|
||||
@@ -88,6 +88,12 @@ struct ThreadInfo {
|
||||
// Mimicking how strace does this(see syscall.c, search for GETREGS)
|
||||
struct user_regs regs;
|
||||
struct user_fpregs fpregs;
|
||||
#elif defined(__mips__)
|
||||
user_regs_struct regs;
|
||||
user_fpregs_struct fpregs;
|
||||
uint32_t hi[3];
|
||||
uint32_t lo[3];
|
||||
uint32_t dsp_control;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
#define TID_PTR_REGISTER "ecx"
|
||||
#elif defined(__x86_64)
|
||||
#define TID_PTR_REGISTER "rcx"
|
||||
#elif defined(__mips__)
|
||||
#define TID_PTR_REGISTER "$1"
|
||||
#else
|
||||
#error This test has not been ported to this platform.
|
||||
#endif
|
||||
|
||||
@@ -208,6 +208,17 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__mips__)
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
sys_ptrace(PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*>(DSP_BASE + (i * 2)), &info->hi[i]);
|
||||
sys_ptrace(PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*>(DSP_BASE + (i * 2) + 1), &info->lo[i]);
|
||||
}
|
||||
sys_ptrace(PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*>(DSP_CONTROL), &info->dsp_control);
|
||||
#endif
|
||||
|
||||
const uint8_t* stack_pointer;
|
||||
#if defined(__i386)
|
||||
my_memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
|
||||
@@ -215,6 +226,9 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
|
||||
my_memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
|
||||
#elif defined(__ARM_EABI__)
|
||||
my_memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
|
||||
#elif defined(__mips__)
|
||||
stack_pointer =
|
||||
reinterpret_cast<uint8_t*>(info->regs.regs[MD_CONTEXT_MIPS_REG_SP]);
|
||||
#else
|
||||
#error "This code hasn't been ported to your platform yet."
|
||||
#endif
|
||||
|
||||
@@ -266,7 +266,7 @@ TEST_F(LinuxPtraceDumperChildTest, BuildProcPath) {
|
||||
EXPECT_FALSE(dumper.BuildProcPath(maps_path, 123, long_node));
|
||||
}
|
||||
|
||||
#if !defined(__ARM_EABI__)
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
// Ensure that the linux-gate VDSO is included in the mapping list.
|
||||
TEST_F(LinuxPtraceDumperChildTest, MappingsIncludeLinuxGate) {
|
||||
LinuxPtraceDumper dumper(getppid());
|
||||
@@ -437,6 +437,9 @@ TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) {
|
||||
pid_t* process_tid_location = (pid_t*)(one_thread.regs.ecx);
|
||||
#elif defined(__x86_64)
|
||||
pid_t* process_tid_location = (pid_t*)(one_thread.regs.rcx);
|
||||
#elif defined(__mips__)
|
||||
pid_t* process_tid_location =
|
||||
reinterpret_cast<pid_t*>(one_thread.regs.regs[1]);
|
||||
#else
|
||||
#error This test has not been ported to this platform.
|
||||
#endif
|
||||
|
||||
@@ -374,6 +374,67 @@ void CPUFillFromUContext(MDRawContextARM* out, const ucontext* uc,
|
||||
my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
|
||||
}
|
||||
|
||||
#elif defined(__mips__)
|
||||
typedef MDRawContextMIPS RawContextCPU;
|
||||
|
||||
static void CPUFillFromThreadInfo(MDRawContextMIPS* out,
|
||||
const google_breakpad::ThreadInfo& info) {
|
||||
out->context_flags = MD_CONTEXT_MIPS_FULL;
|
||||
|
||||
for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
|
||||
out->iregs[i] = info.regs.regs[i];
|
||||
|
||||
out->mdhi = info.regs.hi;
|
||||
out->mdlo = info.regs.lo;
|
||||
|
||||
for (int i = 0; i < MD_CONTEXT_MIPS_DSP_COUNT; ++i) {
|
||||
out->hi[i] = info.hi[i];
|
||||
out->lo[i] = info.lo[i];
|
||||
}
|
||||
out->dsp_control = info.dsp_control;
|
||||
|
||||
out->epc = info.regs.epc;
|
||||
out->badvaddr = info.regs.badvaddr;
|
||||
out->status = info.regs.status;
|
||||
out->cause = info.regs.cause;
|
||||
|
||||
for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
|
||||
out->float_save.regs[i] = info.fpregs.regs[i];
|
||||
|
||||
out->float_save.fpcsr = info.fpregs.fpcsr;
|
||||
out->float_save.fir = info.fpregs.fir;
|
||||
}
|
||||
|
||||
static void CPUFillFromUContext(MDRawContextMIPS* out, const ucontext* uc,
|
||||
const struct _libc_fpstate* fpregs) {
|
||||
out->context_flags = MD_CONTEXT_MIPS_FULL;
|
||||
|
||||
for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
|
||||
out->iregs[i] = uc->uc_mcontext.gregs[i];
|
||||
|
||||
out->mdhi = uc->uc_mcontext.mdhi;
|
||||
out->mdlo = uc->uc_mcontext.mdlo;
|
||||
|
||||
out->hi[0] = uc->uc_mcontext.hi1;
|
||||
out->hi[1] = uc->uc_mcontext.hi2;
|
||||
out->hi[2] = uc->uc_mcontext.hi3;
|
||||
out->lo[0] = uc->uc_mcontext.lo1;
|
||||
out->lo[1] = uc->uc_mcontext.lo2;
|
||||
out->lo[2] = uc->uc_mcontext.lo3;
|
||||
out->dsp_control = uc->uc_mcontext.dsp;
|
||||
|
||||
out->epc = uc->uc_mcontext.pc;
|
||||
out->badvaddr = 0; // Not reported in signal context.
|
||||
out->status = 0; // Not reported in signal context.
|
||||
out->cause = 0; // Not reported in signal context.
|
||||
|
||||
for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
|
||||
out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i];
|
||||
|
||||
out->float_save.fpcsr = uc->uc_mcontext.fpc_csr;
|
||||
out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
|
||||
}
|
||||
|
||||
#else
|
||||
#error "This code has not been ported to your platform yet."
|
||||
#endif
|
||||
@@ -405,7 +466,7 @@ class MinidumpWriter {
|
||||
: fd_(minidump_fd),
|
||||
path_(minidump_path),
|
||||
ucontext_(context ? &context->context : NULL),
|
||||
#if !defined(__ARM_EABI__)
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
float_state_(context ? &context->float_state : NULL),
|
||||
#else
|
||||
// TODO: fix this after fixing ExceptionHandler
|
||||
@@ -1206,6 +1267,18 @@ class MinidumpWriter {
|
||||
uintptr_t GetInstructionPointer(const ThreadInfo& info) {
|
||||
return info.regs.uregs[15];
|
||||
}
|
||||
#elif defined(__mips__)
|
||||
uintptr_t GetStackPointer() {
|
||||
return ucontext_->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP];
|
||||
}
|
||||
|
||||
uintptr_t GetInstructionPointer() {
|
||||
return ucontext_->uc_mcontext.pc;
|
||||
}
|
||||
|
||||
uintptr_t GetInstructionPointer(const ThreadInfo& info) {
|
||||
return info.regs.epc;
|
||||
}
|
||||
#else
|
||||
#error "This code has not been ported to your platform yet."
|
||||
#endif
|
||||
@@ -1216,7 +1289,7 @@ class MinidumpWriter {
|
||||
dirent->location.rva = 0;
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
|
||||
bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
|
||||
char vendor_id[sizeof(sys_info->cpu.x86_cpu_info.vendor_id) + 1] = {0};
|
||||
static const char vendor_id_name[] = "vendor_id";
|
||||
@@ -1227,14 +1300,18 @@ class MinidumpWriter {
|
||||
bool found;
|
||||
} cpu_info_table[] = {
|
||||
{ "processor", -1, false },
|
||||
#if !defined(__mips__)
|
||||
{ "model", 0, false },
|
||||
{ "stepping", 0, false },
|
||||
{ "cpu family", 0, false },
|
||||
#endif
|
||||
};
|
||||
|
||||
// processor_architecture should always be set, do this first
|
||||
sys_info->processor_architecture =
|
||||
#if defined(__i386__)
|
||||
#if defined(__mips__)
|
||||
MD_CPU_ARCHITECTURE_MIPS;
|
||||
#elif defined(__i386__)
|
||||
MD_CPU_ARCHITECTURE_X86;
|
||||
#else
|
||||
MD_CPU_ARCHITECTURE_AMD64;
|
||||
@@ -1297,9 +1374,11 @@ class MinidumpWriter {
|
||||
cpu_info_table[0].value++;
|
||||
|
||||
sys_info->number_of_processors = cpu_info_table[0].value;
|
||||
#if !defined(__mips__)
|
||||
sys_info->processor_level = cpu_info_table[3].value;
|
||||
sys_info->processor_revision = cpu_info_table[1].value << 8 |
|
||||
cpu_info_table[2].value;
|
||||
#endif
|
||||
|
||||
if (vendor_id[0] != '\0') {
|
||||
my_memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id,
|
||||
|
||||
@@ -540,6 +540,12 @@ TEST(MinidumpWriterTest, InvalidStackPointer) {
|
||||
uintptr_t invalid_stack_pointer =
|
||||
reinterpret_cast<uintptr_t>(&context) - 1024*1024;
|
||||
context.context.uc_mcontext.arm_sp = invalid_stack_pointer;
|
||||
#elif defined(__mips__)
|
||||
// Try 1MB below the current stack.
|
||||
uintptr_t invalid_stack_pointer =
|
||||
reinterpret_cast<uintptr_t>(&context) - 1024 * 1024;
|
||||
context.context.uc_mcontext.gregs[MD_CONTEXT_MIPS_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