summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc')
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc421
1 files changed, 421 insertions, 0 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc
new file mode 100644
index 0000000000..aa86d248ae
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc
@@ -0,0 +1,421 @@
+// Copyright (c) 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
+
+// synth_minidump.cc: Implementation of SynthMinidump. See synth_minidump.h
+
+#include "processor/synth_minidump.h"
+
+namespace google_breakpad {
+
+namespace SynthMinidump {
+
+Section::Section(const Dump &dump)
+ : test_assembler::Section(dump.endianness()) { }
+
+void Section::CiteLocationIn(test_assembler::Section *section) const {
+ (*section).D32(size_).D32(file_offset_);
+}
+
+void Stream::CiteStreamIn(test_assembler::Section *section) const {
+ section->D32(type_);
+ CiteLocationIn(section);
+}
+
+SystemInfo::SystemInfo(const Dump &dump,
+ const MDRawSystemInfo &system_info,
+ const String &csd_version)
+ : Stream(dump, MD_SYSTEM_INFO_STREAM) {
+ D16(system_info.processor_architecture);
+ D16(system_info.processor_level);
+ D16(system_info.processor_revision);
+ D8(system_info.number_of_processors);
+ D8(system_info.product_type);
+ D32(system_info.major_version);
+ D32(system_info.minor_version);
+ D32(system_info.build_number);
+ D32(system_info.platform_id);
+ csd_version.CiteStringIn(this);
+ D16(system_info.suite_mask);
+ D16(system_info.reserved2); // Well, why not?
+
+ // MDCPUInformation cpu;
+ if (system_info.processor_architecture == MD_CPU_ARCHITECTURE_X86) {
+ D32(system_info.cpu.x86_cpu_info.vendor_id[0]);
+ D32(system_info.cpu.x86_cpu_info.vendor_id[1]);
+ D32(system_info.cpu.x86_cpu_info.vendor_id[2]);
+ D32(system_info.cpu.x86_cpu_info.version_information);
+ D32(system_info.cpu.x86_cpu_info.feature_information);
+ D32(system_info.cpu.x86_cpu_info.amd_extended_cpu_features);
+ } else if (system_info.processor_architecture == MD_CPU_ARCHITECTURE_ARM) {
+ D32(system_info.cpu.arm_cpu_info.cpuid);
+ D32(system_info.cpu.arm_cpu_info.elf_hwcaps);
+ } else {
+ D64(system_info.cpu.other_cpu_info.processor_features[0]);
+ D64(system_info.cpu.other_cpu_info.processor_features[1]);
+ }
+}
+
+const MDRawSystemInfo SystemInfo::windows_x86 = {
+ MD_CPU_ARCHITECTURE_X86, // processor_architecture
+ 6, // processor_level
+ 0xd08, // processor_revision
+ 1, // number_of_processors
+ 1, // product_type
+ 5, // major_version
+ 1, // minor_version
+ 2600, // build_number
+ 2, // platform_id
+ 0xdeadbeef, // csd_version_rva
+ 0x100, // suite_mask
+ 0, // reserved2
+ { // cpu
+ { // x86_cpu_info
+ { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
+ 0x6d8, // version_information
+ 0xafe9fbff, // feature_information
+ 0xffffffff // amd_extended_cpu_features
+ }
+ }
+};
+
+const string SystemInfo::windows_x86_csd_version = "Service Pack 2";
+
+String::String(const Dump &dump, const string &contents) : Section(dump) {
+ D32(contents.size() * 2);
+ for (string::const_iterator i = contents.begin(); i != contents.end(); i++)
+ D16(*i);
+}
+
+void String::CiteStringIn(test_assembler::Section *section) const {
+ section->D32(file_offset_);
+}
+
+void Memory::CiteMemoryIn(test_assembler::Section *section) const {
+ section->D64(address_);
+ CiteLocationIn(section);
+}
+
+Context::Context(const Dump &dump, const MDRawContextX86 &context)
+ : Section(dump) {
+ // The caller should have properly set the CPU type flag.
+ // The high 24 bits identify the CPU. Note that context records with no CPU
+ // type information can be valid (e.g. produced by ::RtlCaptureContext).
+ assert(((context.context_flags & MD_CONTEXT_CPU_MASK) == 0) ||
+ (context.context_flags & MD_CONTEXT_X86));
+ // It doesn't make sense to store x86 registers in big-endian form.
+ assert(dump.endianness() == kLittleEndian);
+ D32(context.context_flags);
+ D32(context.dr0);
+ D32(context.dr1);
+ D32(context.dr2);
+ D32(context.dr3);
+ D32(context.dr6);
+ D32(context.dr7);
+ D32(context.float_save.control_word);
+ D32(context.float_save.status_word);
+ D32(context.float_save.tag_word);
+ D32(context.float_save.error_offset);
+ D32(context.float_save.error_selector);
+ D32(context.float_save.data_offset);
+ D32(context.float_save.data_selector);
+ // context.float_save.register_area[] contains 8-bit quantities and
+ // does not need to be swapped.
+ Append(context.float_save.register_area,
+ sizeof(context.float_save.register_area));
+ D32(context.float_save.cr0_npx_state);
+ D32(context.gs);
+ D32(context.fs);
+ D32(context.es);
+ D32(context.ds);
+ D32(context.edi);
+ D32(context.esi);
+ D32(context.ebx);
+ D32(context.edx);
+ D32(context.ecx);
+ D32(context.eax);
+ D32(context.ebp);
+ D32(context.eip);
+ D32(context.cs);
+ D32(context.eflags);
+ D32(context.esp);
+ D32(context.ss);
+ // context.extended_registers[] contains 8-bit quantities and does
+ // not need to be swapped.
+ Append(context.extended_registers, sizeof(context.extended_registers));
+ assert(Size() == sizeof(MDRawContextX86));
+}
+
+Context::Context(const Dump &dump, const MDRawContextARM &context)
+ : Section(dump) {
+ // The caller should have properly set the CPU type flag.
+ assert((context.context_flags & MD_CONTEXT_ARM) ||
+ (context.context_flags & MD_CONTEXT_ARM_OLD));
+ // It doesn't make sense to store ARM registers in big-endian form.
+ assert(dump.endianness() == kLittleEndian);
+ D32(context.context_flags);
+ for (int i = 0; i < MD_CONTEXT_ARM_GPR_COUNT; ++i)
+ D32(context.iregs[i]);
+ D32(context.cpsr);
+ D64(context.float_save.fpscr);
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; ++i)
+ D64(context.float_save.regs[i]);
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; ++i)
+ D32(context.float_save.extra[i]);
+ assert(Size() == sizeof(MDRawContextARM));
+}
+
+Context::Context(const Dump &dump, const MDRawContextMIPS &context)
+ : Section(dump) {
+ // The caller should have properly set the CPU type flag.
+ assert(context.context_flags & MD_CONTEXT_MIPS);
+ D32(context.context_flags);
+ D32(context._pad0);
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
+ D64(context.iregs[i]);
+
+ D64(context.mdhi);
+ D64(context.mdlo);
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_DSP_COUNT; ++i)
+ D32(context.hi[i]);
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_DSP_COUNT; ++i)
+ D32(context.lo[i]);
+
+ D32(context.dsp_control);
+ D32(context._pad1);
+
+ D64(context.epc);
+ D64(context.badvaddr);
+ D32(context.status);
+ D32(context.cause);
+
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
+ D64(context.float_save.regs[i]);
+
+ D32(context.float_save.fpcsr);
+ D32(context.float_save.fir);
+
+ assert(Size() == sizeof(MDRawContextMIPS));
+}
+
+Thread::Thread(const Dump &dump,
+ uint32_t thread_id, const Memory &stack, const Context &context,
+ uint32_t suspend_count, uint32_t priority_class,
+ uint32_t priority, uint64_t teb) : Section(dump) {
+ D32(thread_id);
+ D32(suspend_count);
+ D32(priority_class);
+ D32(priority);
+ D64(teb);
+ stack.CiteMemoryIn(this);
+ context.CiteLocationIn(this);
+ assert(Size() == sizeof(MDRawThread));
+}
+
+Module::Module(const Dump &dump,
+ uint64_t base_of_image,
+ uint32_t size_of_image,
+ const String &name,
+ uint32_t time_date_stamp,
+ uint32_t checksum,
+ const MDVSFixedFileInfo &version_info,
+ const Section *cv_record,
+ const Section *misc_record) : Section(dump) {
+ D64(base_of_image);
+ D32(size_of_image);
+ D32(checksum);
+ D32(time_date_stamp);
+ name.CiteStringIn(this);
+ D32(version_info.signature);
+ D32(version_info.struct_version);
+ D32(version_info.file_version_hi);
+ D32(version_info.file_version_lo);
+ D32(version_info.product_version_hi);
+ D32(version_info.product_version_lo);
+ D32(version_info.file_flags_mask);
+ D32(version_info.file_flags);
+ D32(version_info.file_os);
+ D32(version_info.file_type);
+ D32(version_info.file_subtype);
+ D32(version_info.file_date_hi);
+ D32(version_info.file_date_lo);
+ if (cv_record)
+ cv_record->CiteLocationIn(this);
+ else
+ D32(0).D32(0);
+ if (misc_record)
+ misc_record->CiteLocationIn(this);
+ else
+ D32(0).D32(0);
+ D64(0).D64(0);
+}
+
+const MDVSFixedFileInfo Module::stock_version_info = {
+ MD_VSFIXEDFILEINFO_SIGNATURE, // signature
+ MD_VSFIXEDFILEINFO_VERSION, // struct_version
+ 0x11111111, // file_version_hi
+ 0x22222222, // file_version_lo
+ 0x33333333, // product_version_hi
+ 0x44444444, // product_version_lo
+ MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags_mask
+ MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags
+ MD_VSFIXEDFILEINFO_FILE_OS_NT | MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS32,
+ // file_os
+ MD_VSFIXEDFILEINFO_FILE_TYPE_APP, // file_type
+ MD_VSFIXEDFILEINFO_FILE_SUBTYPE_UNKNOWN, // file_subtype
+ 0, // file_date_hi
+ 0 // file_date_lo
+};
+
+UnloadedModule::UnloadedModule(const Dump &dump,
+ uint64_t base_of_image,
+ uint32_t size_of_image,
+ const String &name,
+ uint32_t checksum,
+ uint32_t time_date_stamp) : Section(dump) {
+ D64(base_of_image);
+ D32(size_of_image);
+ D32(checksum);
+ D32(time_date_stamp);
+ name.CiteStringIn(this);
+}
+
+UnloadedModuleList::UnloadedModuleList(const Dump &dump, uint32_t type)
+ : List<UnloadedModule>(dump, type, false) {
+ D32(sizeof(MDRawUnloadedModuleList));
+ D32(sizeof(MDRawUnloadedModule));
+ D32(count_label_);
+}
+
+Exception::Exception(const Dump &dump,
+ const Context &context,
+ uint32_t thread_id,
+ uint32_t exception_code,
+ uint32_t exception_flags,
+ uint64_t exception_address)
+ : Stream(dump, MD_EXCEPTION_STREAM) {
+ D32(thread_id);
+ D32(0); // __align
+ D32(exception_code);
+ D32(exception_flags);
+ D64(0); // exception_record
+ D64(exception_address);
+ D32(0); // number_parameters
+ D32(0); // __align
+ for (int i = 0; i < MD_EXCEPTION_MAXIMUM_PARAMETERS; ++i)
+ D64(0); // exception_information
+ context.CiteLocationIn(this);
+ assert(Size() == sizeof(MDRawExceptionStream));
+}
+
+Dump::Dump(uint64_t flags,
+ Endianness endianness,
+ uint32_t version,
+ uint32_t date_time_stamp)
+ : test_assembler::Section(endianness),
+ file_start_(0),
+ stream_directory_(*this),
+ stream_count_(0),
+ thread_list_(*this, MD_THREAD_LIST_STREAM),
+ module_list_(*this, MD_MODULE_LIST_STREAM),
+ unloaded_module_list_(*this, MD_UNLOADED_MODULE_LIST_STREAM),
+ memory_list_(*this, MD_MEMORY_LIST_STREAM)
+ {
+ D32(MD_HEADER_SIGNATURE);
+ D32(version);
+ D32(stream_count_label_);
+ D32(stream_directory_rva_);
+ D32(0);
+ D32(date_time_stamp);
+ D64(flags);
+ assert(Size() == sizeof(MDRawHeader));
+}
+
+Dump &Dump::Add(SynthMinidump::Section *section) {
+ section->Finish(file_start_ + Size());
+ Append(*section);
+ return *this;
+}
+
+Dump &Dump::Add(Stream *stream) {
+ Add(static_cast<SynthMinidump::Section *>(stream));
+ stream->CiteStreamIn(&stream_directory_);
+ stream_count_++;
+ return *this;
+}
+
+Dump &Dump::Add(Memory *memory) {
+ // Add the memory contents themselves to the file.
+ Add(static_cast<SynthMinidump::Section *>(memory));
+
+ // The memory list is a list of MDMemoryDescriptors, not of actual
+ // memory elements. Produce a descriptor, and add that to the list.
+ SynthMinidump::Section descriptor(*this);
+ memory->CiteMemoryIn(&descriptor);
+ memory_list_.Add(&descriptor);
+ return *this;
+}
+
+Dump &Dump::Add(Thread *thread) {
+ thread_list_.Add(thread);
+ return *this;
+}
+
+Dump &Dump::Add(Module *module) {
+ module_list_.Add(module);
+ return *this;
+}
+
+Dump &Dump::Add(UnloadedModule *unloaded_module) {
+ unloaded_module_list_.Add(unloaded_module);
+ return *this;
+}
+
+void Dump::Finish() {
+ if (!thread_list_.Empty()) Add(&thread_list_);
+ if (!module_list_.Empty()) Add(&module_list_);
+ if (!unloaded_module_list_.Empty()) Add(&unloaded_module_list_);
+ if (!memory_list_.Empty()) Add(&memory_list_);
+
+ // Create the stream directory. We don't use
+ // stream_directory_.Finish here, because the stream directory isn't
+ // cited using a location descriptor; rather, the Minidump header
+ // has the stream count and MDRVA.
+ stream_count_label_ = stream_count_;
+ stream_directory_rva_ = file_start_ + Size();
+ Append(static_cast<test_assembler::Section &>(stream_directory_));
+}
+
+} // namespace SynthMinidump
+
+} // namespace google_breakpad