toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 // Copyright (c) 2010, Google Inc.
michael@0 2 // All rights reserved.
michael@0 3 //
michael@0 4 // Redistribution and use in source and binary forms, with or without
michael@0 5 // modification, are permitted provided that the following conditions are
michael@0 6 // met:
michael@0 7 //
michael@0 8 // * Redistributions of source code must retain the above copyright
michael@0 9 // notice, this list of conditions and the following disclaimer.
michael@0 10 // * Redistributions in binary form must reproduce the above
michael@0 11 // copyright notice, this list of conditions and the following disclaimer
michael@0 12 // in the documentation and/or other materials provided with the
michael@0 13 // distribution.
michael@0 14 // * Neither the name of Google Inc. nor the names of its
michael@0 15 // contributors may be used to endorse or promote products derived from
michael@0 16 // this software without specific prior written permission.
michael@0 17 //
michael@0 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
michael@0 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
michael@0 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
michael@0 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@0 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@0 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
michael@0 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 29
michael@0 30 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
michael@0 31
michael@0 32 // synth_minidump.cc: Implementation of SynthMinidump. See synth_minidump.h
michael@0 33
michael@0 34 #include "processor/synth_minidump.h"
michael@0 35
michael@0 36 namespace google_breakpad {
michael@0 37
michael@0 38 namespace SynthMinidump {
michael@0 39
michael@0 40 Section::Section(const Dump &dump)
michael@0 41 : test_assembler::Section(dump.endianness()) { }
michael@0 42
michael@0 43 void Section::CiteLocationIn(test_assembler::Section *section) const {
michael@0 44 if (this)
michael@0 45 (*section).D32(size_).D32(file_offset_);
michael@0 46 else
michael@0 47 (*section).D32(0).D32(0);
michael@0 48 }
michael@0 49
michael@0 50 void Stream::CiteStreamIn(test_assembler::Section *section) const {
michael@0 51 section->D32(type_);
michael@0 52 CiteLocationIn(section);
michael@0 53 }
michael@0 54
michael@0 55 SystemInfo::SystemInfo(const Dump &dump,
michael@0 56 const MDRawSystemInfo &system_info,
michael@0 57 const String &csd_version)
michael@0 58 : Stream(dump, MD_SYSTEM_INFO_STREAM) {
michael@0 59 D16(system_info.processor_architecture);
michael@0 60 D16(system_info.processor_level);
michael@0 61 D16(system_info.processor_revision);
michael@0 62 D8(system_info.number_of_processors);
michael@0 63 D8(system_info.product_type);
michael@0 64 D32(system_info.major_version);
michael@0 65 D32(system_info.minor_version);
michael@0 66 D32(system_info.build_number);
michael@0 67 D32(system_info.platform_id);
michael@0 68 csd_version.CiteStringIn(this);
michael@0 69 D16(system_info.suite_mask);
michael@0 70 D16(system_info.reserved2); // Well, why not?
michael@0 71
michael@0 72 // MDCPUInformation cpu;
michael@0 73 if (system_info.processor_architecture == MD_CPU_ARCHITECTURE_X86) {
michael@0 74 D32(system_info.cpu.x86_cpu_info.vendor_id[0]);
michael@0 75 D32(system_info.cpu.x86_cpu_info.vendor_id[1]);
michael@0 76 D32(system_info.cpu.x86_cpu_info.vendor_id[2]);
michael@0 77 D32(system_info.cpu.x86_cpu_info.version_information);
michael@0 78 D32(system_info.cpu.x86_cpu_info.feature_information);
michael@0 79 D32(system_info.cpu.x86_cpu_info.amd_extended_cpu_features);
michael@0 80 } else {
michael@0 81 D64(system_info.cpu.other_cpu_info.processor_features[0]);
michael@0 82 D64(system_info.cpu.other_cpu_info.processor_features[1]);
michael@0 83 }
michael@0 84 }
michael@0 85
michael@0 86 const MDRawSystemInfo SystemInfo::windows_x86 = {
michael@0 87 MD_CPU_ARCHITECTURE_X86, // processor_architecture
michael@0 88 6, // processor_level
michael@0 89 0xd08, // processor_revision
michael@0 90 1, // number_of_processors
michael@0 91 1, // product_type
michael@0 92 5, // major_version
michael@0 93 1, // minor_version
michael@0 94 2600, // build_number
michael@0 95 2, // platform_id
michael@0 96 0xdeadbeef, // csd_version_rva
michael@0 97 0x100, // suite_mask
michael@0 98 0, // reserved2
michael@0 99 { // cpu
michael@0 100 { // x86_cpu_info
michael@0 101 { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
michael@0 102 0x6d8, // version_information
michael@0 103 0xafe9fbff, // feature_information
michael@0 104 0xffffffff // amd_extended_cpu_features
michael@0 105 }
michael@0 106 }
michael@0 107 };
michael@0 108
michael@0 109 const string SystemInfo::windows_x86_csd_version = "Service Pack 2";
michael@0 110
michael@0 111 String::String(const Dump &dump, const string &contents) : Section(dump) {
michael@0 112 D32(contents.size() * 2);
michael@0 113 for (string::const_iterator i = contents.begin(); i != contents.end(); i++)
michael@0 114 D16(*i);
michael@0 115 }
michael@0 116
michael@0 117 void String::CiteStringIn(test_assembler::Section *section) const {
michael@0 118 section->D32(file_offset_);
michael@0 119 }
michael@0 120
michael@0 121 void Memory::CiteMemoryIn(test_assembler::Section *section) const {
michael@0 122 section->D64(address_);
michael@0 123 CiteLocationIn(section);
michael@0 124 }
michael@0 125
michael@0 126 Context::Context(const Dump &dump, const MDRawContextX86 &context)
michael@0 127 : Section(dump) {
michael@0 128 // The caller should have properly set the CPU type flag.
michael@0 129 // The high 24 bits identify the CPU. Note that context records with no CPU
michael@0 130 // type information can be valid (e.g. produced by ::RtlCaptureContext).
michael@0 131 assert(((context.context_flags & MD_CONTEXT_CPU_MASK) == 0) ||
michael@0 132 (context.context_flags & MD_CONTEXT_X86));
michael@0 133 // It doesn't make sense to store x86 registers in big-endian form.
michael@0 134 assert(dump.endianness() == kLittleEndian);
michael@0 135 D32(context.context_flags);
michael@0 136 D32(context.dr0);
michael@0 137 D32(context.dr1);
michael@0 138 D32(context.dr2);
michael@0 139 D32(context.dr3);
michael@0 140 D32(context.dr6);
michael@0 141 D32(context.dr7);
michael@0 142 D32(context.float_save.control_word);
michael@0 143 D32(context.float_save.status_word);
michael@0 144 D32(context.float_save.tag_word);
michael@0 145 D32(context.float_save.error_offset);
michael@0 146 D32(context.float_save.error_selector);
michael@0 147 D32(context.float_save.data_offset);
michael@0 148 D32(context.float_save.data_selector);
michael@0 149 // context.float_save.register_area[] contains 8-bit quantities and
michael@0 150 // does not need to be swapped.
michael@0 151 Append(context.float_save.register_area,
michael@0 152 sizeof(context.float_save.register_area));
michael@0 153 D32(context.float_save.cr0_npx_state);
michael@0 154 D32(context.gs);
michael@0 155 D32(context.fs);
michael@0 156 D32(context.es);
michael@0 157 D32(context.ds);
michael@0 158 D32(context.edi);
michael@0 159 D32(context.esi);
michael@0 160 D32(context.ebx);
michael@0 161 D32(context.edx);
michael@0 162 D32(context.ecx);
michael@0 163 D32(context.eax);
michael@0 164 D32(context.ebp);
michael@0 165 D32(context.eip);
michael@0 166 D32(context.cs);
michael@0 167 D32(context.eflags);
michael@0 168 D32(context.esp);
michael@0 169 D32(context.ss);
michael@0 170 // context.extended_registers[] contains 8-bit quantities and does
michael@0 171 // not need to be swapped.
michael@0 172 Append(context.extended_registers, sizeof(context.extended_registers));
michael@0 173 assert(Size() == sizeof(MDRawContextX86));
michael@0 174 }
michael@0 175
michael@0 176 Context::Context(const Dump &dump, const MDRawContextARM &context)
michael@0 177 : Section(dump) {
michael@0 178 // The caller should have properly set the CPU type flag.
michael@0 179 assert((context.context_flags & MD_CONTEXT_ARM) ||
michael@0 180 (context.context_flags & MD_CONTEXT_ARM_OLD));
michael@0 181 // It doesn't make sense to store ARM registers in big-endian form.
michael@0 182 assert(dump.endianness() == kLittleEndian);
michael@0 183 D32(context.context_flags);
michael@0 184 for (int i = 0; i < MD_CONTEXT_ARM_GPR_COUNT; ++i)
michael@0 185 D32(context.iregs[i]);
michael@0 186 D32(context.cpsr);
michael@0 187 D64(context.float_save.fpscr);
michael@0 188 for (int i = 0; i < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; ++i)
michael@0 189 D64(context.float_save.regs[i]);
michael@0 190 for (int i = 0; i < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; ++i)
michael@0 191 D32(context.float_save.extra[i]);
michael@0 192 assert(Size() == sizeof(MDRawContextARM));
michael@0 193 }
michael@0 194
michael@0 195 Thread::Thread(const Dump &dump,
michael@0 196 uint32_t thread_id, const Memory &stack, const Context &context,
michael@0 197 uint32_t suspend_count, uint32_t priority_class,
michael@0 198 uint32_t priority, uint64_t teb) : Section(dump) {
michael@0 199 D32(thread_id);
michael@0 200 D32(suspend_count);
michael@0 201 D32(priority_class);
michael@0 202 D32(priority);
michael@0 203 D64(teb);
michael@0 204 stack.CiteMemoryIn(this);
michael@0 205 context.CiteLocationIn(this);
michael@0 206 assert(Size() == sizeof(MDRawThread));
michael@0 207 }
michael@0 208
michael@0 209 Module::Module(const Dump &dump,
michael@0 210 uint64_t base_of_image,
michael@0 211 uint32_t size_of_image,
michael@0 212 const String &name,
michael@0 213 uint32_t time_date_stamp,
michael@0 214 uint32_t checksum,
michael@0 215 const MDVSFixedFileInfo &version_info,
michael@0 216 const Section *cv_record,
michael@0 217 const Section *misc_record) : Section(dump) {
michael@0 218 D64(base_of_image);
michael@0 219 D32(size_of_image);
michael@0 220 D32(checksum);
michael@0 221 D32(time_date_stamp);
michael@0 222 name.CiteStringIn(this);
michael@0 223 D32(version_info.signature);
michael@0 224 D32(version_info.struct_version);
michael@0 225 D32(version_info.file_version_hi);
michael@0 226 D32(version_info.file_version_lo);
michael@0 227 D32(version_info.product_version_hi);
michael@0 228 D32(version_info.product_version_lo);
michael@0 229 D32(version_info.file_flags_mask);
michael@0 230 D32(version_info.file_flags);
michael@0 231 D32(version_info.file_os);
michael@0 232 D32(version_info.file_type);
michael@0 233 D32(version_info.file_subtype);
michael@0 234 D32(version_info.file_date_hi);
michael@0 235 D32(version_info.file_date_lo);
michael@0 236 cv_record->CiteLocationIn(this);
michael@0 237 misc_record->CiteLocationIn(this);
michael@0 238 D64(0).D64(0);
michael@0 239 }
michael@0 240
michael@0 241 const MDVSFixedFileInfo Module::stock_version_info = {
michael@0 242 MD_VSFIXEDFILEINFO_SIGNATURE, // signature
michael@0 243 MD_VSFIXEDFILEINFO_VERSION, // struct_version
michael@0 244 0x11111111, // file_version_hi
michael@0 245 0x22222222, // file_version_lo
michael@0 246 0x33333333, // product_version_hi
michael@0 247 0x44444444, // product_version_lo
michael@0 248 MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags_mask
michael@0 249 MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags
michael@0 250 MD_VSFIXEDFILEINFO_FILE_OS_NT | MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS32,
michael@0 251 // file_os
michael@0 252 MD_VSFIXEDFILEINFO_FILE_TYPE_APP, // file_type
michael@0 253 MD_VSFIXEDFILEINFO_FILE_SUBTYPE_UNKNOWN, // file_subtype
michael@0 254 0, // file_date_hi
michael@0 255 0 // file_date_lo
michael@0 256 };
michael@0 257
michael@0 258 Exception::Exception(const Dump &dump,
michael@0 259 const Context &context,
michael@0 260 uint32_t thread_id,
michael@0 261 uint32_t exception_code,
michael@0 262 uint32_t exception_flags,
michael@0 263 uint64_t exception_address)
michael@0 264 : Stream(dump, MD_EXCEPTION_STREAM) {
michael@0 265 D32(thread_id);
michael@0 266 D32(0); // __align
michael@0 267 D32(exception_code);
michael@0 268 D32(exception_flags);
michael@0 269 D64(0); // exception_record
michael@0 270 D64(exception_address);
michael@0 271 D32(0); // number_parameters
michael@0 272 D32(0); // __align
michael@0 273 for (int i = 0; i < MD_EXCEPTION_MAXIMUM_PARAMETERS; ++i)
michael@0 274 D64(0); // exception_information
michael@0 275 context.CiteLocationIn(this);
michael@0 276 assert(Size() == sizeof(MDRawExceptionStream));
michael@0 277 }
michael@0 278
michael@0 279 Dump::Dump(uint64_t flags,
michael@0 280 Endianness endianness,
michael@0 281 uint32_t version,
michael@0 282 uint32_t date_time_stamp)
michael@0 283 : test_assembler::Section(endianness),
michael@0 284 file_start_(0),
michael@0 285 stream_directory_(*this),
michael@0 286 stream_count_(0),
michael@0 287 thread_list_(*this, MD_THREAD_LIST_STREAM),
michael@0 288 module_list_(*this, MD_MODULE_LIST_STREAM),
michael@0 289 memory_list_(*this, MD_MEMORY_LIST_STREAM)
michael@0 290 {
michael@0 291 D32(MD_HEADER_SIGNATURE);
michael@0 292 D32(version);
michael@0 293 D32(stream_count_label_);
michael@0 294 D32(stream_directory_rva_);
michael@0 295 D32(0);
michael@0 296 D32(date_time_stamp);
michael@0 297 D64(flags);
michael@0 298 assert(Size() == sizeof(MDRawHeader));
michael@0 299 }
michael@0 300
michael@0 301 Dump &Dump::Add(SynthMinidump::Section *section) {
michael@0 302 section->Finish(file_start_ + Size());
michael@0 303 Append(*section);
michael@0 304 return *this;
michael@0 305 }
michael@0 306
michael@0 307 Dump &Dump::Add(Stream *stream) {
michael@0 308 Add(static_cast<SynthMinidump::Section *>(stream));
michael@0 309 stream->CiteStreamIn(&stream_directory_);
michael@0 310 stream_count_++;
michael@0 311 return *this;
michael@0 312 }
michael@0 313
michael@0 314 Dump &Dump::Add(Memory *memory) {
michael@0 315 // Add the memory contents themselves to the file.
michael@0 316 Add(static_cast<SynthMinidump::Section *>(memory));
michael@0 317
michael@0 318 // The memory list is a list of MDMemoryDescriptors, not of actual
michael@0 319 // memory elements. Produce a descriptor, and add that to the list.
michael@0 320 SynthMinidump::Section descriptor(*this);
michael@0 321 memory->CiteMemoryIn(&descriptor);
michael@0 322 memory_list_.Add(&descriptor);
michael@0 323 return *this;
michael@0 324 }
michael@0 325
michael@0 326 Dump &Dump::Add(Thread *thread) {
michael@0 327 thread_list_.Add(thread);
michael@0 328 return *this;
michael@0 329 }
michael@0 330
michael@0 331 Dump &Dump::Add(Module *module) {
michael@0 332 module_list_.Add(module);
michael@0 333 return *this;
michael@0 334 }
michael@0 335
michael@0 336 void Dump::Finish() {
michael@0 337 if (!thread_list_.Empty()) Add(&thread_list_);
michael@0 338 if (!module_list_.Empty()) Add(&module_list_);
michael@0 339 if (!memory_list_.Empty()) Add(&memory_list_);
michael@0 340
michael@0 341 // Create the stream directory. We don't use
michael@0 342 // stream_directory_.Finish here, because the stream directory isn't
michael@0 343 // cited using a location descriptor; rather, the Minidump header
michael@0 344 // has the stream count and MDRVA.
michael@0 345 stream_count_label_ = stream_count_;
michael@0 346 stream_directory_rva_ = file_start_ + Size();
michael@0 347 Append(static_cast<test_assembler::Section &>(stream_directory_));
michael@0 348 }
michael@0 349
michael@0 350 } // namespace SynthMinidump
michael@0 351
michael@0 352 } // namespace google_breakpad

mercurial