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_