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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,371 @@
     1.4 +// -*- mode: C++ -*-
     1.5 +
     1.6 +// Copyright (c) 2010, Google Inc.
     1.7 +// All rights reserved.
     1.8 +//
     1.9 +// Redistribution and use in source and binary forms, with or without
    1.10 +// modification, are permitted provided that the following conditions are
    1.11 +// met:
    1.12 +//
    1.13 +//     * Redistributions of source code must retain the above copyright
    1.14 +// notice, this list of conditions and the following disclaimer.
    1.15 +//     * Redistributions in binary form must reproduce the above
    1.16 +// copyright notice, this list of conditions and the following disclaimer
    1.17 +// in the documentation and/or other materials provided with the
    1.18 +// distribution.
    1.19 +//     * Neither the name of Google Inc. nor the names of its
    1.20 +// contributors may be used to endorse or promote products derived from
    1.21 +// this software without specific prior written permission.
    1.22 +//
    1.23 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.24 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.25 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.26 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.27 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.28 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.29 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.30 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.31 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.32 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.33 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.34 +
    1.35 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
    1.36 +
    1.37 +// synth_minidump.h: Interface to SynthMinidump: fake minidump generator.
    1.38 +//
    1.39 +// We treat a minidump file as the concatenation of a bunch of
    1.40 +// test_assembler::Sections. The file header, stream directory,
    1.41 +// streams, memory regions, strings, and so on --- each is a Section
    1.42 +// that eventually gets appended to the minidump. Dump, Memory,
    1.43 +// Context, Thread, and so on all inherit from test_assembler::Section.
    1.44 +// For example:
    1.45 +//
    1.46 +//    using google_breakpad::test_assembler::kLittleEndian;
    1.47 +//    using google_breakpad::SynthMinidump::Context;
    1.48 +//    using google_breakpad::SynthMinidump::Dump;
    1.49 +//    using google_breakpad::SynthMinidump::Memory;
    1.50 +//    using google_breakpad::SynthMinidump::Thread;
    1.51 +//    
    1.52 +//    Dump minidump(MD_NORMAL, kLittleEndian);
    1.53 +//    
    1.54 +//    Memory stack1(minidump, 0x569eb0a9);
    1.55 +//    ... build contents of stack1 with test_assembler::Section functions ...
    1.56 +//    
    1.57 +//    MDRawContextX86 x86_context1;
    1.58 +//    x86_context1.context_flags = MD_CONTEXT_X86;
    1.59 +//    x86_context1.eip = 0x7c90eb94;
    1.60 +//    x86_context1.esp = 0x569eb0a9;
    1.61 +//    x86_context1.ebp = x86_context1.esp + something appropriate;
    1.62 +//    Context context1(minidump, x86_context1);
    1.63 +//    
    1.64 +//    Thread thread1(minidump, 0xe4a4821d, stack1, context1);
    1.65 +//    
    1.66 +//    minidump.Add(&stack1);
    1.67 +//    minidump.Add(&context1);
    1.68 +//    minidump.Add(&thread1);
    1.69 +//    minidump.Finish();
    1.70 +//    
    1.71 +//    string contents;
    1.72 +//    EXPECT_TRUE(minidump.GetContents(&contents));
    1.73 +//    // contents now holds the bytes of a minidump file
    1.74 +//
    1.75 +// Because the test_assembler classes let us write Label references to
    1.76 +// sections before the Labels' values are known, this gives us
    1.77 +// flexibility in how we put the dump together: minidump pieces can
    1.78 +// hold the file offsets of other minidump pieces before the
    1.79 +// referents' positions have been decided. As long as everything has
    1.80 +// been placed by the time we call dump.GetContents to obtain the
    1.81 +// bytes, all the Labels' values will be known, and everything will
    1.82 +// get patched up appropriately.
    1.83 +//   
    1.84 +// The dump.Add(thing) functions append THINGS's contents to the
    1.85 +// minidump, but they also do two other things:
    1.86 +//
    1.87 +// - dump.Add(thing) invokes thing->Finish, which tells *thing the
    1.88 +//   offset within the file at which it was placed, and allows *thing
    1.89 +//   to do any final content generation.
    1.90 +//
    1.91 +// - If THING is something which should receive an entry in some sort
    1.92 +//   of list or directory, then dump.Add(THING) automatically creates
    1.93 +//   the appropriate directory or list entry. Streams must appear in
    1.94 +//   the stream directory; memory ranges should be listed in the
    1.95 +//   memory list; threads should be placed in the thread list; and so
    1.96 +//   on.
    1.97 +//
    1.98 +// By convention, Section subclass constructors that take references
    1.99 +// to other Sections do not take care of 'Add'ing their arguments to
   1.100 +// the dump. For example, although the Thread constructor takes
   1.101 +// references to a Memory and a Context, it does not add them to the
   1.102 +// dump on the caller's behalf. Rather, the caller is responsible for
   1.103 +// 'Add'ing every section they create. This allows Sections to be
   1.104 +// cited from more than one place; for example, Memory ranges are
   1.105 +// cited both from Thread objects (as their stack contents) and by the
   1.106 +// memory list stream.
   1.107 +//
   1.108 +// If you forget to Add some Section, the Dump::GetContents call will
   1.109 +// fail, as the test_assembler::Labels used to cite the Section's
   1.110 +// contents from elsewhere will still be undefined.
   1.111 +#ifndef PROCESSOR_SYNTH_MINIDUMP_H_
   1.112 +#define PROCESSOR_SYNTH_MINIDUMP_H_
   1.113 +
   1.114 +#include <assert.h>
   1.115 +
   1.116 +#include <iostream>
   1.117 +#include <string>
   1.118 +
   1.119 +#include "common/test_assembler.h"
   1.120 +#include "common/using_std_string.h"
   1.121 +#include "google_breakpad/common/breakpad_types.h"
   1.122 +#include "google_breakpad/common/minidump_format.h"
   1.123 +
   1.124 +namespace google_breakpad {
   1.125 +
   1.126 +namespace SynthMinidump {
   1.127 +
   1.128 +using test_assembler::Endianness;
   1.129 +using test_assembler::kBigEndian;
   1.130 +using test_assembler::kLittleEndian;
   1.131 +using test_assembler::kUnsetEndian;
   1.132 +using test_assembler::Label;
   1.133 +
   1.134 +class Dump;
   1.135 +class Memory;
   1.136 +class String;
   1.137 +
   1.138 +// A test_assembler::Section which will be appended to a minidump.
   1.139 +class Section: public test_assembler::Section {
   1.140 + public:
   1.141 +  explicit Section(const Dump &dump);
   1.142 +
   1.143 +  // Append an MDLocationDescriptor referring to this section to SECTION.
   1.144 +  // If 'this' is NULL, append a descriptor with a zero length and MDRVA.
   1.145 +  //
   1.146 +  // (I couldn't find the language in the C++ standard that says that
   1.147 +  // invoking member functions of a NULL pointer to a class type is
   1.148 +  // bad, if such language exists. Having this function handle NULL
   1.149 +  // 'this' is convenient, but if it causes trouble, it's not hard to
   1.150 +  // do differently.)
   1.151 +  void CiteLocationIn(test_assembler::Section *section) const;
   1.152 +
   1.153 +  // Note that this section's contents are complete, and that it has
   1.154 +  // been placed in the minidump file at OFFSET. The 'Add' member
   1.155 +  // functions call the Finish member function of the object being
   1.156 +  // added for you; if you are 'Add'ing this section, you needn't Finish it.
   1.157 +  virtual void Finish(const Label &offset) { 
   1.158 +    file_offset_ = offset; size_ = Size();
   1.159 +  }
   1.160 +
   1.161 + protected:
   1.162 +  // This section's size and offset within the minidump file.
   1.163 +  Label file_offset_, size_;
   1.164 +};
   1.165 +
   1.166 +// A stream within a minidump file. 'Add'ing a stream to a minidump
   1.167 +// creates an entry for it in the minidump's stream directory.
   1.168 +class Stream: public Section {
   1.169 + public:
   1.170 +  // Create a stream of type TYPE.  You can append whatever contents
   1.171 +  // you like to this stream using the test_assembler::Section methods.
   1.172 +  Stream(const Dump &dump, uint32_t type) : Section(dump), type_(type) { }
   1.173 +
   1.174 +  // Append an MDRawDirectory referring to this stream to SECTION.
   1.175 +  void CiteStreamIn(test_assembler::Section *section) const;
   1.176 +
   1.177 + private:
   1.178 +  // The type of this stream.
   1.179 +  uint32_t type_;
   1.180 +};
   1.181 +
   1.182 +class SystemInfo: public Stream {
   1.183 + public:
   1.184 +  // Create an MD_SYSTEM_INFO_STREAM stream belonging to DUMP holding
   1.185 +  // an MDRawSystem info structure initialized with the values from
   1.186 +  // SYSTEM_INFO, except that the csd_version field is replaced with
   1.187 +  // the file offset of the string CSD_VERSION, which can be 'Add'ed
   1.188 +  // to the dump at the desired location.
   1.189 +  // 
   1.190 +  // Remember that you are still responsible for 'Add'ing CSD_VERSION
   1.191 +  // to the dump yourself.
   1.192 +  SystemInfo(const Dump &dump,
   1.193 +             const MDRawSystemInfo &system_info,
   1.194 +             const String &csd_version);
   1.195 +
   1.196 +  // Stock MDRawSystemInfo information and associated strings, for
   1.197 +  // writing tests.
   1.198 +  static const MDRawSystemInfo windows_x86;
   1.199 +  static const string windows_x86_csd_version;
   1.200 +};
   1.201 +
   1.202 +// An MDString: a string preceded by a 32-bit length.
   1.203 +class String: public Section {
   1.204 + public:
   1.205 +  String(const Dump &dump, const string &value);
   1.206 +
   1.207 +  // Append an MDRVA referring to this string to SECTION.
   1.208 +  void CiteStringIn(test_assembler::Section *section) const;
   1.209 +};
   1.210 +
   1.211 +// A range of memory contents. 'Add'ing a memory range to a minidump
   1.212 +// creates n entry for it in the minidump's memory list. By
   1.213 +// convention, the 'start', 'Here', and 'Mark' member functions refer
   1.214 +// to memory addresses.
   1.215 +class Memory: public Section {
   1.216 + public:
   1.217 +  Memory(const Dump &dump, uint64_t address)
   1.218 +      : Section(dump), address_(address) { start() = address; }
   1.219 +
   1.220 +  // Append an MDMemoryDescriptor referring to this memory range to SECTION.
   1.221 +  void CiteMemoryIn(test_assembler::Section *section) const;
   1.222 +
   1.223 + private:
   1.224 +  // The process address from which these memory contents were taken.
   1.225 +  // Shouldn't this be a Label?
   1.226 +  uint64_t address_;
   1.227 +};
   1.228 +
   1.229 +class Context: public Section {
   1.230 + public:
   1.231 +  // Create a context belonging to DUMP whose contents are a copy of CONTEXT.
   1.232 +  Context(const Dump &dump, const MDRawContextX86 &context);
   1.233 +  Context(const Dump &dump, const MDRawContextARM &context);
   1.234 +  // Add an empty context to the dump.
   1.235 +  Context(const Dump &dump) : Section(dump) {}
   1.236 +  // Add constructors for other architectures here. Remember to byteswap.
   1.237 +};
   1.238 +
   1.239 +class Thread: public Section {
   1.240 + public:
   1.241 +  // Create a thread belonging to DUMP with the given values, citing
   1.242 +  // STACK and CONTEXT (which you must Add to the dump separately).
   1.243 +  Thread(const Dump &dump,
   1.244 +         uint32_t thread_id,
   1.245 +         const Memory &stack,
   1.246 +         const Context &context,
   1.247 +         uint32_t suspend_count = 0,
   1.248 +         uint32_t priority_class = 0,
   1.249 +         uint32_t priority = 0,
   1.250 +         uint64_t teb = 0);
   1.251 +};
   1.252 +
   1.253 +class Module: public Section {
   1.254 + public:
   1.255 +  // Create a module with the given values. Note that CV_RECORD and
   1.256 +  // MISC_RECORD can be NULL, in which case the corresponding location
   1.257 +  // descriptior in the minidump will have a length of zero.
   1.258 +  Module(const Dump &dump,
   1.259 +         uint64_t base_of_image,
   1.260 +         uint32_t size_of_image,
   1.261 +         const String &name,
   1.262 +         uint32_t time_date_stamp = 1262805309,
   1.263 +         uint32_t checksum = 0,
   1.264 +         const MDVSFixedFileInfo &version_info = Module::stock_version_info,
   1.265 +         const Section *cv_record = NULL,
   1.266 +         const Section *misc_record = NULL);
   1.267 +
   1.268 + private:
   1.269 +  // A standard MDVSFixedFileInfo structure to use as a default for
   1.270 +  // minidumps.  There's no reason to make users write out all this crap
   1.271 +  // over and over.
   1.272 +  static const MDVSFixedFileInfo stock_version_info;
   1.273 +};
   1.274 +
   1.275 +class Exception : public Stream {
   1.276 +public:
   1.277 +  Exception(const Dump &dump,
   1.278 +            const Context &context,
   1.279 +            uint32_t thread_id = 0,
   1.280 +            uint32_t exception_code = 0,
   1.281 +            uint32_t exception_flags = 0,
   1.282 +            uint64_t exception_address = 0);
   1.283 +};
   1.284 +
   1.285 +// A list of entries starting with a 32-bit count, like a memory list
   1.286 +// or a thread list.
   1.287 +template<typename Element>
   1.288 +class List: public Stream {
   1.289 + public:
   1.290 +  List(const Dump &dump, uint32_t type) : Stream(dump, type), count_(0) {
   1.291 +    D32(count_label_);
   1.292 +  }
   1.293 +
   1.294 +  // Add ELEMENT to this list.
   1.295 +  void Add(Element *element) {
   1.296 +    element->Finish(file_offset_ + Size());
   1.297 +    Append(*element);
   1.298 +    count_++;
   1.299 +  }
   1.300 +
   1.301 +  // Return true if this List is empty, false otherwise.
   1.302 +  bool Empty() { return count_ == 0; }
   1.303 +
   1.304 +  // Finish up the contents of this section, mark it as having been
   1.305 +  // placed at OFFSET.
   1.306 +  virtual void Finish(const Label &offset) {
   1.307 +    Stream::Finish(offset);
   1.308 +    count_label_ = count_;
   1.309 +  }
   1.310 +
   1.311 + private:
   1.312 +  size_t count_;
   1.313 +  Label count_label_;
   1.314 +};
   1.315 +
   1.316 +class Dump: public test_assembler::Section {
   1.317 + public:
   1.318 +
   1.319 +  // Create a test_assembler::Section containing a minidump file whose
   1.320 +  // header uses the given values. ENDIANNESS determines the
   1.321 +  // endianness of the signature; we set this section's default
   1.322 +  // endianness by this.
   1.323 +  Dump(uint64_t flags,
   1.324 +       Endianness endianness = kLittleEndian,
   1.325 +       uint32_t version = MD_HEADER_VERSION,
   1.326 +       uint32_t date_time_stamp = 1262805309);
   1.327 +
   1.328 +  // The following functions call OBJECT->Finish(), and append the
   1.329 +  // contents of OBJECT to this minidump. They also record OBJECT in
   1.330 +  // whatever directory or list is appropriate for its type. The
   1.331 +  // stream directory, memory list, thread list, and module list are
   1.332 +  // accumulated this way.
   1.333 +  Dump &Add(SynthMinidump::Section *object); // simply append data
   1.334 +  Dump &Add(Stream *object); // append, record in stream directory
   1.335 +  Dump &Add(Memory *object); // append, record in memory list
   1.336 +  Dump &Add(Thread *object); // append, record in thread list
   1.337 +  Dump &Add(Module *object); // append, record in module list
   1.338 +
   1.339 +  // Complete the construction of the minidump, given the Add calls
   1.340 +  // we've seen up to this point. After this call, this Dump's
   1.341 +  // contents are complete, all labels should be defined if everything
   1.342 +  // Cited has been Added, and you may call GetContents on it.
   1.343 +  void Finish();
   1.344 +
   1.345 + private:
   1.346 +  // A label representing the start of the minidump file.
   1.347 +  Label file_start_;
   1.348 +
   1.349 +  // The stream directory.  We construct this incrementally from
   1.350 +  // Add(Stream *) calls.
   1.351 +  SynthMinidump::Section stream_directory_; // The directory's contents.
   1.352 +  size_t stream_count_;                 // The number of streams so far.
   1.353 +  Label stream_count_label_;            // Cited in file header.
   1.354 +  Label stream_directory_rva_;          // The directory's file offset.
   1.355 +
   1.356 +  // This minidump's thread list. We construct this incrementally from
   1.357 +  // Add(Thread *) calls.
   1.358 +  List<Thread> thread_list_;
   1.359 +
   1.360 +  // This minidump's module list. We construct this incrementally from
   1.361 +  // Add(Module *) calls.
   1.362 +  List<Module> module_list_;
   1.363 +
   1.364 +  // This minidump's memory list. We construct this incrementally from
   1.365 +  // Add(Memory *) calls. This is actually a list of MDMemoryDescriptors,
   1.366 +  // not memory ranges --- thus the odd type.
   1.367 +  List<SynthMinidump::Section> memory_list_;
   1.368 +};
   1.369 +
   1.370 +} // namespace SynthMinidump
   1.371 +
   1.372 +} // namespace google_breakpad
   1.373 +
   1.374 +#endif  // PROCESSOR_SYNTH_MINIDUMP_H_

mercurial