PageRenderTime 55ms CodeModel.GetById 19ms app.highlight 30ms RepoModel.GetById 2ms app.codeStats 0ms

/thirdparty/breakpad/processor/synth_minidump.cc

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