aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/handler/exception_handler_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/linux/handler/exception_handler_unittest.cc')
-rw-r--r--src/client/linux/handler/exception_handler_unittest.cc54
1 files changed, 35 insertions, 19 deletions
diff --git a/src/client/linux/handler/exception_handler_unittest.cc b/src/client/linux/handler/exception_handler_unittest.cc
index 0ba52163..702a3adb 100644
--- a/src/client/linux/handler/exception_handler_unittest.cc
+++ b/src/client/linux/handler/exception_handler_unittest.cc
@@ -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());
}