Wed, 31 Dec 2014 06:09:35 +0100
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 |