diff --git a/src/client/linux/handler/exception_handler_unittest.cc b/src/client/linux/handler/exception_handler_unittest.cc index 83af35d5..6de9b8d4 100644 --- a/src/client/linux/handler/exception_handler_unittest.cc +++ b/src/client/linux/handler/exception_handler_unittest.cc @@ -450,20 +450,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemory) { ASSERT_TRUE(context); u_int64_t instruction_pointer; - switch (context->GetContextCPU()) { - case MD_CONTEXT_X86: - instruction_pointer = context->GetContextX86()->eip; - break; - case MD_CONTEXT_AMD64: - instruction_pointer = context->GetContextAMD64()->rip; - break; - case MD_CONTEXT_ARM: - instruction_pointer = context->GetContextARM()->iregs[15]; - break; - default: - FAIL() << "Unknown context CPU: " << context->GetContextCPU(); - break; - } + ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); MinidumpMemoryRegion* region = memory_list->GetMemoryRegionForAddress(instruction_pointer); @@ -555,20 +542,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) { ASSERT_TRUE(context); u_int64_t instruction_pointer; - switch (context->GetContextCPU()) { - case MD_CONTEXT_X86: - instruction_pointer = context->GetContextX86()->eip; - break; - case MD_CONTEXT_AMD64: - instruction_pointer = context->GetContextAMD64()->rip; - break; - case MD_CONTEXT_ARM: - instruction_pointer = context->GetContextARM()->iregs[15]; - break; - default: - FAIL() << "Unknown context CPU: " << context->GetContextCPU(); - break; - } + ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); MinidumpMemoryRegion* region = memory_list->GetMemoryRegionForAddress(instruction_pointer); @@ -658,20 +632,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) { ASSERT_TRUE(context); u_int64_t instruction_pointer; - switch (context->GetContextCPU()) { - case MD_CONTEXT_X86: - instruction_pointer = context->GetContextX86()->eip; - break; - case MD_CONTEXT_AMD64: - instruction_pointer = context->GetContextAMD64()->rip; - break; - case MD_CONTEXT_ARM: - instruction_pointer = context->GetContextARM()->iregs[15]; - break; - default: - FAIL() << "Unknown context CPU: " << context->GetContextCPU(); - break; - } + ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); MinidumpMemoryRegion* region = memory_list->GetMemoryRegionForAddress(instruction_pointer); diff --git a/src/client/mac/tests/exception_handler_test.cc b/src/client/mac/tests/exception_handler_test.cc index ee3ffa5b..8325d44e 100644 --- a/src/client/mac/tests/exception_handler_test.cc +++ b/src/client/mac/tests/exception_handler_test.cc @@ -347,20 +347,7 @@ TEST_F(ExceptionHandlerTest, InstructionPointerMemory) { ASSERT_TRUE(context); u_int64_t instruction_pointer; - switch (context->GetContextCPU()) { - case MD_CONTEXT_X86: - instruction_pointer = context->GetContextX86()->eip; - break; - case MD_CONTEXT_AMD64: - instruction_pointer = context->GetContextAMD64()->rip; - break; - case MD_CONTEXT_ARM: - instruction_pointer = context->GetContextARM()->iregs[15]; - break; - default: - FAIL() << "Unknown context CPU: " << context->GetContextCPU(); - break; - } + ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); MinidumpMemoryRegion* region = memory_list->GetMemoryRegionForAddress(instruction_pointer); @@ -459,20 +446,7 @@ TEST_F(ExceptionHandlerTest, InstructionPointerMemoryMinBound) { ASSERT_TRUE(context); u_int64_t instruction_pointer; - switch (context->GetContextCPU()) { - case MD_CONTEXT_X86: - instruction_pointer = context->GetContextX86()->eip; - break; - case MD_CONTEXT_AMD64: - instruction_pointer = context->GetContextAMD64()->rip; - break; - case MD_CONTEXT_ARM: - instruction_pointer = context->GetContextARM()->iregs[15]; - break; - default: - FAIL() << "Unknown context CPU: " << context->GetContextCPU(); - break; - } + ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); MinidumpMemoryRegion* region = memory_list->GetMemoryRegionForAddress(instruction_pointer); @@ -571,20 +545,7 @@ TEST_F(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) { ASSERT_TRUE(context); u_int64_t instruction_pointer; - switch (context->GetContextCPU()) { - case MD_CONTEXT_X86: - instruction_pointer = context->GetContextX86()->eip; - break; - case MD_CONTEXT_AMD64: - instruction_pointer = context->GetContextAMD64()->rip; - break; - case MD_CONTEXT_ARM: - instruction_pointer = context->GetContextARM()->iregs[15]; - break; - default: - FAIL() << "Unknown context CPU: " << context->GetContextCPU(); - break; - } + ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); MinidumpMemoryRegion* region = memory_list->GetMemoryRegionForAddress(instruction_pointer); diff --git a/src/client/windows/unittests/exception_handler_death_test.cc b/src/client/windows/unittests/exception_handler_death_test.cc index 514ee72a..a50f9134 100644 --- a/src/client/windows/unittests/exception_handler_death_test.cc +++ b/src/client/windows/unittests/exception_handler_death_test.cc @@ -303,17 +303,7 @@ TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemory) { ASSERT_TRUE(context); u_int64_t instruction_pointer; - switch (context->GetContextCPU()) { - case MD_CONTEXT_X86: - instruction_pointer = context->GetContextX86()->eip; - break; - case MD_CONTEXT_AMD64: - instruction_pointer = context->GetContextAMD64()->rip; - break; - default: - FAIL() << "Unknown context CPU: " << context->GetContextCPU(); - break; - } + ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); MinidumpMemoryRegion* region = memory_list->GetMemoryRegionForAddress(instruction_pointer); @@ -403,17 +393,7 @@ TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMinBound) { ASSERT_TRUE(context); u_int64_t instruction_pointer; - switch (context->GetContextCPU()) { - case MD_CONTEXT_X86: - instruction_pointer = context->GetContextX86()->eip; - break; - case MD_CONTEXT_AMD64: - instruction_pointer = context->GetContextAMD64()->rip; - break; - default: - FAIL() << "Unknown context CPU: " << context->GetContextCPU(); - break; - } + ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); MinidumpMemoryRegion* region = memory_list->GetMemoryRegionForAddress(instruction_pointer); @@ -495,17 +475,7 @@ TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMaxBound) { ASSERT_TRUE(context); u_int64_t instruction_pointer; - switch (context->GetContextCPU()) { - case MD_CONTEXT_X86: - instruction_pointer = context->GetContextX86()->eip; - break; - case MD_CONTEXT_AMD64: - instruction_pointer = context->GetContextAMD64()->rip; - break; - default: - FAIL() << "Unknown context CPU: " << context->GetContextCPU(); - break; - } + ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); MinidumpMemoryRegion* region = memory_list->GetMemoryRegionForAddress(instruction_pointer); diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h index 3dfbef2b..03337796 100644 --- a/src/google_breakpad/processor/minidump.h +++ b/src/google_breakpad/processor/minidump.h @@ -178,6 +178,10 @@ class MinidumpContext : public MinidumpStream { // MD_CONTEXT_* bits masked out. Returns 0 on failure. u_int32_t GetContextCPU() const; + // A convenience method to get the instruction pointer out of the + // MDRawContext, since it varies per-CPU architecture. + bool GetInstructionPointer(u_int64_t* ip) const; + // Returns raw CPU-specific context data for the named CPU type. If the // context data does not match the CPU type or does not exist, returns // NULL. diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc index d88101f6..19ba0354 100644 --- a/src/processor/minidump.cc +++ b/src/processor/minidump.cc @@ -714,6 +714,41 @@ u_int32_t MinidumpContext::GetContextCPU() const { return context_flags_ & MD_CONTEXT_CPU_MASK; } +bool MinidumpContext::GetInstructionPointer(u_int64_t* ip) const { + BPLOG_IF(ERROR, !ip) << "MinidumpContext::GetInstructionPointer " + "requires |ip|"; + assert(ip); + *ip = 0; + + if (!valid_) { + BPLOG(ERROR) << "Invalid MinidumpContext for GetInstructionPointer"; + return false; + } + + switch (context_flags_ & MD_CONTEXT_CPU_MASK) { + case MD_CONTEXT_AMD64: + *ip = context_.amd64->rip; + break; + case MD_CONTEXT_ARM: + *ip = context_.arm->iregs[MD_CONTEXT_ARM_REG_PC]; + break; + case MD_CONTEXT_PPC: + *ip = context_.ppc->srr0; + break; + case MD_CONTEXT_SPARC: + *ip = context_.ctx_sparc->pc; + break; + case MD_CONTEXT_X86: + *ip = context_.x86->eip; + break; + default: + // This should never happen. + BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer"; + return false; + } + return true; +} + const MDRawContextX86* MinidumpContext::GetContextX86() const { if (GetContextCPU() != MD_CONTEXT_X86) { diff --git a/src/processor/minidump_unittest.cc b/src/processor/minidump_unittest.cc index ce142300..60cb37a6 100644 --- a/src/processor/minidump_unittest.cc +++ b/src/processor/minidump_unittest.cc @@ -213,6 +213,7 @@ TEST(Dump, OneThread) { stack.Append("stack for thread"); MDRawContextX86 raw_context; + const u_int32_t kExpectedEIP = 0x6913f540; raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; raw_context.edi = 0x3ecba80d; raw_context.esi = 0x382583b9; @@ -221,7 +222,7 @@ TEST(Dump, OneThread) { raw_context.ecx = 0x46a6a6a8; raw_context.eax = 0x6a5025e2; raw_context.ebp = 0xd9fabb4a; - raw_context.eip = 0x6913f540; + raw_context.eip = kExpectedEIP; raw_context.cs = 0xbffe6eda; raw_context.eflags = 0xb2ce1e2d; raw_context.esp = 0x659caaa4; @@ -273,6 +274,11 @@ TEST(Dump, OneThread) { MinidumpContext *md_context = md_thread->GetContext(); ASSERT_TRUE(md_context != NULL); ASSERT_EQ((u_int32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); + + u_int64_t eip; + ASSERT_TRUE(md_context->GetInstructionPointer(&eip)); + EXPECT_EQ(kExpectedEIP, eip); + const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); ASSERT_TRUE(md_raw_context != NULL); ASSERT_EQ((u_int32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), @@ -285,7 +291,7 @@ TEST(Dump, OneThread) { EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); EXPECT_EQ(0x6a5025e2U, raw_context.eax); EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); - EXPECT_EQ(0x6913f540U, raw_context.eip); + EXPECT_EQ(kExpectedEIP, raw_context.eip); EXPECT_EQ(0xbffe6edaU, raw_context.cs); EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); EXPECT_EQ(0x659caaa4U, raw_context.esp);