From ea2bba970675e01f9964f82d3f44960c1aad05dc Mon Sep 17 00:00:00 2001 From: mmentovai Date: Wed, 26 Sep 2007 18:28:05 +0000 Subject: Add SPARC/Solaris support to client handler and processor (#201, 200). Patch by Michael shang . r=me, r=Alfred Peng. http://groups.google.com/group/google-breakpad-discuss/browse_thread/thread/2fba07577f1fa35e git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@215 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/processor/minidump.cc | 163 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 152 insertions(+), 11 deletions(-) (limited to 'src/processor/minidump.cc') diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc index 93d4eb05..f4817044 100644 --- a/src/processor/minidump.cc +++ b/src/processor/minidump.cc @@ -450,6 +450,62 @@ bool MinidumpContext::Read(u_int32_t expected_size) { break; } + case MD_CONTEXT_SPARC: { + if (expected_size != sizeof(MDRawContextSPARC)) { + BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " << + expected_size << " != " << sizeof(MDRawContextSPARC); + return false; + } + + scoped_ptr context_sparc(new MDRawContextSPARC()); + + // Set the context_flags member, which has already been read, and + // read the rest of the structure beginning with the first member + // after context_flags. + context_sparc->context_flags = context_flags; + + size_t flags_size = sizeof(context_sparc->context_flags); + u_int8_t* context_after_flags = + reinterpret_cast(context_sparc.get()) + flags_size; + if (!minidump_->ReadBytes(context_after_flags, + sizeof(MDRawContextSPARC) - flags_size)) { + BPLOG(ERROR) << "MinidumpContext could not read sparc context"; + return false; + } + + // Do this after reading the entire MDRawContext structure because + // GetSystemInfo may seek minidump to a new position. + if (!CheckAgainstSystemInfo(cpu_type)) { + BPLOG(ERROR) << "MinidumpContext sparc does not match system info"; + return false; + } + + if (minidump_->swap()) { + // context_sparc->context_flags was already swapped. + for (unsigned int gpr_index = 0; + gpr_index < MD_CONTEXT_SPARC_GPR_COUNT; + ++gpr_index) { + Swap(&context_sparc->g_r[gpr_index]); + } + Swap(&context_sparc->ccr); + Swap(&context_sparc->pc); + Swap(&context_sparc->npc); + Swap(&context_sparc->y); + Swap(&context_sparc->asi); + Swap(&context_sparc->fprs); + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; + ++fpr_index) { + Swap(&context_sparc->float_save.regs[fpr_index]); + } + Swap(&context_sparc->float_save.filler); + Swap(&context_sparc->float_save.fsr); + } + context_.ctx_sparc = context_sparc.release(); + + break; + } + default: { // Unknown context type BPLOG(ERROR) << "MinidumpContext unknown context type " << @@ -494,6 +550,14 @@ const MDRawContextPPC* MinidumpContext::GetContextPPC() const { return context_.ppc; } +const MDRawContextSPARC* MinidumpContext::GetContextSPARC() const { + if (GetContextCPU() != MD_CONTEXT_SPARC) { + BPLOG(ERROR) << "MinidumpContext cannot get sparc context"; + return NULL; + } + + return context_.ctx_sparc; +} void MinidumpContext::FreeContext() { switch (GetContextCPU()) { @@ -505,6 +569,10 @@ void MinidumpContext::FreeContext() { delete context_.ppc; break; + case MD_CONTEXT_SPARC: + delete context_.ctx_sparc; + break; + default: // There is no context record (valid_ is false) or there's a // context record for an unknown CPU (shouldn't happen, only known @@ -552,6 +620,11 @@ bool MinidumpContext::CheckAgainstSystemInfo(u_int32_t context_cpu_type) { if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC) return_value = true; break; + + case MD_CONTEXT_SPARC: + if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC) + return_value = true; + break; } BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " << @@ -672,6 +745,37 @@ void MinidumpContext::Print() { break; } + case MD_CONTEXT_SPARC: { + const MDRawContextSPARC* context_sparc = GetContextSPARC(); + printf("MDRawContextSPARC\n"); + printf(" context_flags = 0x%x\n", + context_sparc->context_flags); + for (unsigned int g_r_index = 0; + g_r_index < MD_CONTEXT_SPARC_GPR_COUNT; + ++g_r_index) { + printf(" g_r[%2d] = 0x%llx\n", + g_r_index, context_sparc->g_r[g_r_index]); + } + printf(" ccr = 0x%llx\n", context_sparc->ccr); + printf(" pc = 0x%llx\n", context_sparc->pc); + printf(" npc = 0x%llx\n", context_sparc->npc); + printf(" y = 0x%llx\n", context_sparc->y); + printf(" asi = 0x%llx\n", context_sparc->asi); + printf(" fprs = 0x%llx\n", context_sparc->fprs); + + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; + ++fpr_index) { + printf(" float_save.regs[%2d] = 0x%llx\n", + fpr_index, context_sparc->float_save.regs[fpr_index]); + } + printf(" float_save.filler = 0x%llx\n", + context_sparc->float_save.filler); + printf(" float_save.fsr = 0x%llx\n", + context_sparc->float_save.fsr); + break; + } + default: { break; } @@ -1068,12 +1172,23 @@ bool MinidumpThreadList::Read(u_int32_t expected_size) { if (expected_size != sizeof(thread_count) + thread_count * sizeof(MDRawThread)) { - BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size << - " != " << - sizeof(thread_count) + thread_count * sizeof(MDRawThread); - return false; + // may be padded with 4 bytes on 64bit ABIs for alignment + if (expected_size == sizeof(thread_count) + 4 + + thread_count * sizeof(MDRawThread)) { + u_int32_t useless; + if (!minidump_->ReadBytes(&useless, 4)) { + BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded bytes"; + return false; + } + } else { + BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size << + " != " << sizeof(thread_count) + + thread_count * sizeof(MDRawThread); + return false; + } } + if (thread_count > max_threads_) { BPLOG(ERROR) << "MinidumpThreadList count " << thread_count << " exceeds maximum " << max_threads_; @@ -1328,6 +1443,7 @@ string MinidumpModule::code_identifier() const { } case MD_OS_MAC_OS_X: + case MD_OS_SOLARIS: case MD_OS_LINUX: { // TODO(mmentovai): support uuid extension if present, otherwise fall // back to version (from LC_ID_DYLIB?), otherwise fall back to something @@ -1924,10 +2040,20 @@ bool MinidumpModuleList::Read(u_int32_t expected_size) { if (expected_size != sizeof(module_count) + module_count * MD_MODULE_SIZE) { - BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size << - " != " << - sizeof(module_count) + module_count * MD_MODULE_SIZE; - return false; + // may be padded with 4 bytes on 64bit ABIs for alignment + if (expected_size == sizeof(module_count) + 4 + + module_count * MD_MODULE_SIZE) { + u_int32_t useless; + if (!minidump_->ReadBytes(&useless, 4)) { + BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded bytes"; + return false; + } + } else { + BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size << + " != " << sizeof(module_count) + + module_count * MD_MODULE_SIZE; + return false; + } } if (module_count > max_modules_) { @@ -2155,9 +2281,20 @@ bool MinidumpMemoryList::Read(u_int32_t expected_size) { if (expected_size != sizeof(region_count) + region_count * sizeof(MDMemoryDescriptor)) { - BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size << - " != " << region_count * sizeof(MDMemoryDescriptor); - return false; + // may be padded with 4 bytes on 64bit ABIs for alignment + if (expected_size == sizeof(region_count) + 4 + + region_count * sizeof(MDMemoryDescriptor)) { + u_int32_t useless; + if (!minidump_->ReadBytes(&useless, 4)) { + BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded bytes"; + return false; + } + } else { + BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size << + " != " << sizeof(region_count) + + region_count * sizeof(MDMemoryDescriptor); + return false; + } } if (region_count > max_regions_) { @@ -2526,6 +2663,10 @@ string MinidumpSystemInfo::GetOS() { os = "linux"; break; + case MD_OS_SOLARIS: + os = "solaris"; + break; + default: BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " << HexString(system_info_.platform_id); -- cgit v1.2.1