1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,352 @@ 1.4 +// Copyright (c) 2010, Google Inc. 1.5 +// All rights reserved. 1.6 +// 1.7 +// Redistribution and use in source and binary forms, with or without 1.8 +// modification, are permitted provided that the following conditions are 1.9 +// met: 1.10 +// 1.11 +// * Redistributions of source code must retain the above copyright 1.12 +// notice, this list of conditions and the following disclaimer. 1.13 +// * Redistributions in binary form must reproduce the above 1.14 +// copyright notice, this list of conditions and the following disclaimer 1.15 +// in the documentation and/or other materials provided with the 1.16 +// distribution. 1.17 +// * Neither the name of Google Inc. nor the names of its 1.18 +// contributors may be used to endorse or promote products derived from 1.19 +// this software without specific prior written permission. 1.20 +// 1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + 1.33 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.34 + 1.35 +// synth_minidump.cc: Implementation of SynthMinidump. See synth_minidump.h 1.36 + 1.37 +#include "processor/synth_minidump.h" 1.38 + 1.39 +namespace google_breakpad { 1.40 + 1.41 +namespace SynthMinidump { 1.42 + 1.43 +Section::Section(const Dump &dump) 1.44 + : test_assembler::Section(dump.endianness()) { } 1.45 + 1.46 +void Section::CiteLocationIn(test_assembler::Section *section) const { 1.47 + if (this) 1.48 + (*section).D32(size_).D32(file_offset_); 1.49 + else 1.50 + (*section).D32(0).D32(0); 1.51 +} 1.52 + 1.53 +void Stream::CiteStreamIn(test_assembler::Section *section) const { 1.54 + section->D32(type_); 1.55 + CiteLocationIn(section); 1.56 +} 1.57 + 1.58 +SystemInfo::SystemInfo(const Dump &dump, 1.59 + const MDRawSystemInfo &system_info, 1.60 + const String &csd_version) 1.61 + : Stream(dump, MD_SYSTEM_INFO_STREAM) { 1.62 + D16(system_info.processor_architecture); 1.63 + D16(system_info.processor_level); 1.64 + D16(system_info.processor_revision); 1.65 + D8(system_info.number_of_processors); 1.66 + D8(system_info.product_type); 1.67 + D32(system_info.major_version); 1.68 + D32(system_info.minor_version); 1.69 + D32(system_info.build_number); 1.70 + D32(system_info.platform_id); 1.71 + csd_version.CiteStringIn(this); 1.72 + D16(system_info.suite_mask); 1.73 + D16(system_info.reserved2); // Well, why not? 1.74 + 1.75 + // MDCPUInformation cpu; 1.76 + if (system_info.processor_architecture == MD_CPU_ARCHITECTURE_X86) { 1.77 + D32(system_info.cpu.x86_cpu_info.vendor_id[0]); 1.78 + D32(system_info.cpu.x86_cpu_info.vendor_id[1]); 1.79 + D32(system_info.cpu.x86_cpu_info.vendor_id[2]); 1.80 + D32(system_info.cpu.x86_cpu_info.version_information); 1.81 + D32(system_info.cpu.x86_cpu_info.feature_information); 1.82 + D32(system_info.cpu.x86_cpu_info.amd_extended_cpu_features); 1.83 + } else { 1.84 + D64(system_info.cpu.other_cpu_info.processor_features[0]); 1.85 + D64(system_info.cpu.other_cpu_info.processor_features[1]); 1.86 + } 1.87 +} 1.88 + 1.89 +const MDRawSystemInfo SystemInfo::windows_x86 = { 1.90 + MD_CPU_ARCHITECTURE_X86, // processor_architecture 1.91 + 6, // processor_level 1.92 + 0xd08, // processor_revision 1.93 + 1, // number_of_processors 1.94 + 1, // product_type 1.95 + 5, // major_version 1.96 + 1, // minor_version 1.97 + 2600, // build_number 1.98 + 2, // platform_id 1.99 + 0xdeadbeef, // csd_version_rva 1.100 + 0x100, // suite_mask 1.101 + 0, // reserved2 1.102 + { // cpu 1.103 + { // x86_cpu_info 1.104 + { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id 1.105 + 0x6d8, // version_information 1.106 + 0xafe9fbff, // feature_information 1.107 + 0xffffffff // amd_extended_cpu_features 1.108 + } 1.109 + } 1.110 +}; 1.111 + 1.112 +const string SystemInfo::windows_x86_csd_version = "Service Pack 2"; 1.113 + 1.114 +String::String(const Dump &dump, const string &contents) : Section(dump) { 1.115 + D32(contents.size() * 2); 1.116 + for (string::const_iterator i = contents.begin(); i != contents.end(); i++) 1.117 + D16(*i); 1.118 +} 1.119 + 1.120 +void String::CiteStringIn(test_assembler::Section *section) const { 1.121 + section->D32(file_offset_); 1.122 +} 1.123 + 1.124 +void Memory::CiteMemoryIn(test_assembler::Section *section) const { 1.125 + section->D64(address_); 1.126 + CiteLocationIn(section); 1.127 +} 1.128 + 1.129 +Context::Context(const Dump &dump, const MDRawContextX86 &context) 1.130 + : Section(dump) { 1.131 + // The caller should have properly set the CPU type flag. 1.132 + // The high 24 bits identify the CPU. Note that context records with no CPU 1.133 + // type information can be valid (e.g. produced by ::RtlCaptureContext). 1.134 + assert(((context.context_flags & MD_CONTEXT_CPU_MASK) == 0) || 1.135 + (context.context_flags & MD_CONTEXT_X86)); 1.136 + // It doesn't make sense to store x86 registers in big-endian form. 1.137 + assert(dump.endianness() == kLittleEndian); 1.138 + D32(context.context_flags); 1.139 + D32(context.dr0); 1.140 + D32(context.dr1); 1.141 + D32(context.dr2); 1.142 + D32(context.dr3); 1.143 + D32(context.dr6); 1.144 + D32(context.dr7); 1.145 + D32(context.float_save.control_word); 1.146 + D32(context.float_save.status_word); 1.147 + D32(context.float_save.tag_word); 1.148 + D32(context.float_save.error_offset); 1.149 + D32(context.float_save.error_selector); 1.150 + D32(context.float_save.data_offset); 1.151 + D32(context.float_save.data_selector); 1.152 + // context.float_save.register_area[] contains 8-bit quantities and 1.153 + // does not need to be swapped. 1.154 + Append(context.float_save.register_area, 1.155 + sizeof(context.float_save.register_area)); 1.156 + D32(context.float_save.cr0_npx_state); 1.157 + D32(context.gs); 1.158 + D32(context.fs); 1.159 + D32(context.es); 1.160 + D32(context.ds); 1.161 + D32(context.edi); 1.162 + D32(context.esi); 1.163 + D32(context.ebx); 1.164 + D32(context.edx); 1.165 + D32(context.ecx); 1.166 + D32(context.eax); 1.167 + D32(context.ebp); 1.168 + D32(context.eip); 1.169 + D32(context.cs); 1.170 + D32(context.eflags); 1.171 + D32(context.esp); 1.172 + D32(context.ss); 1.173 + // context.extended_registers[] contains 8-bit quantities and does 1.174 + // not need to be swapped. 1.175 + Append(context.extended_registers, sizeof(context.extended_registers)); 1.176 + assert(Size() == sizeof(MDRawContextX86)); 1.177 +} 1.178 + 1.179 +Context::Context(const Dump &dump, const MDRawContextARM &context) 1.180 + : Section(dump) { 1.181 + // The caller should have properly set the CPU type flag. 1.182 + assert((context.context_flags & MD_CONTEXT_ARM) || 1.183 + (context.context_flags & MD_CONTEXT_ARM_OLD)); 1.184 + // It doesn't make sense to store ARM registers in big-endian form. 1.185 + assert(dump.endianness() == kLittleEndian); 1.186 + D32(context.context_flags); 1.187 + for (int i = 0; i < MD_CONTEXT_ARM_GPR_COUNT; ++i) 1.188 + D32(context.iregs[i]); 1.189 + D32(context.cpsr); 1.190 + D64(context.float_save.fpscr); 1.191 + for (int i = 0; i < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; ++i) 1.192 + D64(context.float_save.regs[i]); 1.193 + for (int i = 0; i < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; ++i) 1.194 + D32(context.float_save.extra[i]); 1.195 + assert(Size() == sizeof(MDRawContextARM)); 1.196 +} 1.197 + 1.198 +Thread::Thread(const Dump &dump, 1.199 + uint32_t thread_id, const Memory &stack, const Context &context, 1.200 + uint32_t suspend_count, uint32_t priority_class, 1.201 + uint32_t priority, uint64_t teb) : Section(dump) { 1.202 + D32(thread_id); 1.203 + D32(suspend_count); 1.204 + D32(priority_class); 1.205 + D32(priority); 1.206 + D64(teb); 1.207 + stack.CiteMemoryIn(this); 1.208 + context.CiteLocationIn(this); 1.209 + assert(Size() == sizeof(MDRawThread)); 1.210 +} 1.211 + 1.212 +Module::Module(const Dump &dump, 1.213 + uint64_t base_of_image, 1.214 + uint32_t size_of_image, 1.215 + const String &name, 1.216 + uint32_t time_date_stamp, 1.217 + uint32_t checksum, 1.218 + const MDVSFixedFileInfo &version_info, 1.219 + const Section *cv_record, 1.220 + const Section *misc_record) : Section(dump) { 1.221 + D64(base_of_image); 1.222 + D32(size_of_image); 1.223 + D32(checksum); 1.224 + D32(time_date_stamp); 1.225 + name.CiteStringIn(this); 1.226 + D32(version_info.signature); 1.227 + D32(version_info.struct_version); 1.228 + D32(version_info.file_version_hi); 1.229 + D32(version_info.file_version_lo); 1.230 + D32(version_info.product_version_hi); 1.231 + D32(version_info.product_version_lo); 1.232 + D32(version_info.file_flags_mask); 1.233 + D32(version_info.file_flags); 1.234 + D32(version_info.file_os); 1.235 + D32(version_info.file_type); 1.236 + D32(version_info.file_subtype); 1.237 + D32(version_info.file_date_hi); 1.238 + D32(version_info.file_date_lo); 1.239 + cv_record->CiteLocationIn(this); 1.240 + misc_record->CiteLocationIn(this); 1.241 + D64(0).D64(0); 1.242 +} 1.243 + 1.244 +const MDVSFixedFileInfo Module::stock_version_info = { 1.245 + MD_VSFIXEDFILEINFO_SIGNATURE, // signature 1.246 + MD_VSFIXEDFILEINFO_VERSION, // struct_version 1.247 + 0x11111111, // file_version_hi 1.248 + 0x22222222, // file_version_lo 1.249 + 0x33333333, // product_version_hi 1.250 + 0x44444444, // product_version_lo 1.251 + MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags_mask 1.252 + MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags 1.253 + MD_VSFIXEDFILEINFO_FILE_OS_NT | MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS32, 1.254 + // file_os 1.255 + MD_VSFIXEDFILEINFO_FILE_TYPE_APP, // file_type 1.256 + MD_VSFIXEDFILEINFO_FILE_SUBTYPE_UNKNOWN, // file_subtype 1.257 + 0, // file_date_hi 1.258 + 0 // file_date_lo 1.259 +}; 1.260 + 1.261 +Exception::Exception(const Dump &dump, 1.262 + const Context &context, 1.263 + uint32_t thread_id, 1.264 + uint32_t exception_code, 1.265 + uint32_t exception_flags, 1.266 + uint64_t exception_address) 1.267 + : Stream(dump, MD_EXCEPTION_STREAM) { 1.268 + D32(thread_id); 1.269 + D32(0); // __align 1.270 + D32(exception_code); 1.271 + D32(exception_flags); 1.272 + D64(0); // exception_record 1.273 + D64(exception_address); 1.274 + D32(0); // number_parameters 1.275 + D32(0); // __align 1.276 + for (int i = 0; i < MD_EXCEPTION_MAXIMUM_PARAMETERS; ++i) 1.277 + D64(0); // exception_information 1.278 + context.CiteLocationIn(this); 1.279 + assert(Size() == sizeof(MDRawExceptionStream)); 1.280 +} 1.281 + 1.282 +Dump::Dump(uint64_t flags, 1.283 + Endianness endianness, 1.284 + uint32_t version, 1.285 + uint32_t date_time_stamp) 1.286 + : test_assembler::Section(endianness), 1.287 + file_start_(0), 1.288 + stream_directory_(*this), 1.289 + stream_count_(0), 1.290 + thread_list_(*this, MD_THREAD_LIST_STREAM), 1.291 + module_list_(*this, MD_MODULE_LIST_STREAM), 1.292 + memory_list_(*this, MD_MEMORY_LIST_STREAM) 1.293 + { 1.294 + D32(MD_HEADER_SIGNATURE); 1.295 + D32(version); 1.296 + D32(stream_count_label_); 1.297 + D32(stream_directory_rva_); 1.298 + D32(0); 1.299 + D32(date_time_stamp); 1.300 + D64(flags); 1.301 + assert(Size() == sizeof(MDRawHeader)); 1.302 +} 1.303 + 1.304 +Dump &Dump::Add(SynthMinidump::Section *section) { 1.305 + section->Finish(file_start_ + Size()); 1.306 + Append(*section); 1.307 + return *this; 1.308 +} 1.309 + 1.310 +Dump &Dump::Add(Stream *stream) { 1.311 + Add(static_cast<SynthMinidump::Section *>(stream)); 1.312 + stream->CiteStreamIn(&stream_directory_); 1.313 + stream_count_++; 1.314 + return *this; 1.315 +} 1.316 + 1.317 +Dump &Dump::Add(Memory *memory) { 1.318 + // Add the memory contents themselves to the file. 1.319 + Add(static_cast<SynthMinidump::Section *>(memory)); 1.320 + 1.321 + // The memory list is a list of MDMemoryDescriptors, not of actual 1.322 + // memory elements. Produce a descriptor, and add that to the list. 1.323 + SynthMinidump::Section descriptor(*this); 1.324 + memory->CiteMemoryIn(&descriptor); 1.325 + memory_list_.Add(&descriptor); 1.326 + return *this; 1.327 +} 1.328 + 1.329 +Dump &Dump::Add(Thread *thread) { 1.330 + thread_list_.Add(thread); 1.331 + return *this; 1.332 +} 1.333 + 1.334 +Dump &Dump::Add(Module *module) { 1.335 + module_list_.Add(module); 1.336 + return *this; 1.337 +} 1.338 + 1.339 +void Dump::Finish() { 1.340 + if (!thread_list_.Empty()) Add(&thread_list_); 1.341 + if (!module_list_.Empty()) Add(&module_list_); 1.342 + if (!memory_list_.Empty()) Add(&memory_list_); 1.343 + 1.344 + // Create the stream directory. We don't use 1.345 + // stream_directory_.Finish here, because the stream directory isn't 1.346 + // cited using a location descriptor; rather, the Minidump header 1.347 + // has the stream count and MDRVA. 1.348 + stream_count_label_ = stream_count_; 1.349 + stream_directory_rva_ = file_start_ + Size(); 1.350 + Append(static_cast<test_assembler::Section &>(stream_directory_)); 1.351 +} 1.352 + 1.353 +} // namespace SynthMinidump 1.354 + 1.355 +} // namespace google_breakpad