/thirdparty/breakpad/processor/synth_minidump.h

http://github.com/tomahawk-player/tomahawk · C Header · 369 lines · 141 code · 46 blank · 182 comment · 1 complexity · 9d2b73db0eb2ec059298fe7f75e95f81 MD5 · raw file

  1. // -*- mode: C++ -*-
  2. // Copyright (c) 2010, Google Inc.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
  31. // synth_minidump.h: Interface to SynthMinidump: fake minidump generator.
  32. //
  33. // We treat a minidump file as the concatenation of a bunch of
  34. // test_assembler::Sections. The file header, stream directory,
  35. // streams, memory regions, strings, and so on --- each is a Section
  36. // that eventually gets appended to the minidump. Dump, Memory,
  37. // Context, Thread, and so on all inherit from test_assembler::Section.
  38. // For example:
  39. //
  40. // using google_breakpad::test_assembler::kLittleEndian;
  41. // using google_breakpad::SynthMinidump::Context;
  42. // using google_breakpad::SynthMinidump::Dump;
  43. // using google_breakpad::SynthMinidump::Memory;
  44. // using google_breakpad::SynthMinidump::Thread;
  45. //
  46. // Dump minidump(MD_NORMAL, kLittleEndian);
  47. //
  48. // Memory stack1(minidump, 0x569eb0a9);
  49. // ... build contents of stack1 with test_assembler::Section functions ...
  50. //
  51. // MDRawContextX86 x86_context1;
  52. // x86_context1.context_flags = MD_CONTEXT_X86;
  53. // x86_context1.eip = 0x7c90eb94;
  54. // x86_context1.esp = 0x569eb0a9;
  55. // x86_context1.ebp = x86_context1.esp + something appropriate;
  56. // Context context1(minidump, x86_context1);
  57. //
  58. // Thread thread1(minidump, 0xe4a4821d, stack1, context1);
  59. //
  60. // minidump.Add(&stack1);
  61. // minidump.Add(&context1);
  62. // minidump.Add(&thread1);
  63. // minidump.Finish();
  64. //
  65. // string contents;
  66. // EXPECT_TRUE(minidump.GetContents(&contents));
  67. // // contents now holds the bytes of a minidump file
  68. //
  69. // Because the test_assembler classes let us write Label references to
  70. // sections before the Labels' values are known, this gives us
  71. // flexibility in how we put the dump together: minidump pieces can
  72. // hold the file offsets of other minidump pieces before the
  73. // referents' positions have been decided. As long as everything has
  74. // been placed by the time we call dump.GetContents to obtain the
  75. // bytes, all the Labels' values will be known, and everything will
  76. // get patched up appropriately.
  77. //
  78. // The dump.Add(thing) functions append THINGS's contents to the
  79. // minidump, but they also do two other things:
  80. //
  81. // - dump.Add(thing) invokes thing->Finish, which tells *thing the
  82. // offset within the file at which it was placed, and allows *thing
  83. // to do any final content generation.
  84. //
  85. // - If THING is something which should receive an entry in some sort
  86. // of list or directory, then dump.Add(THING) automatically creates
  87. // the appropriate directory or list entry. Streams must appear in
  88. // the stream directory; memory ranges should be listed in the
  89. // memory list; threads should be placed in the thread list; and so
  90. // on.
  91. //
  92. // By convention, Section subclass constructors that take references
  93. // to other Sections do not take care of 'Add'ing their arguments to
  94. // the dump. For example, although the Thread constructor takes
  95. // references to a Memory and a Context, it does not add them to the
  96. // dump on the caller's behalf. Rather, the caller is responsible for
  97. // 'Add'ing every section they create. This allows Sections to be
  98. // cited from more than one place; for example, Memory ranges are
  99. // cited both from Thread objects (as their stack contents) and by the
  100. // memory list stream.
  101. //
  102. // If you forget to Add some Section, the Dump::GetContents call will
  103. // fail, as the test_assembler::Labels used to cite the Section's
  104. // contents from elsewhere will still be undefined.
  105. #ifndef PROCESSOR_SYNTH_MINIDUMP_H_
  106. #define PROCESSOR_SYNTH_MINIDUMP_H_
  107. #include <assert.h>
  108. #include <iostream>
  109. #include <string>
  110. #include "common/test_assembler.h"
  111. #include "google_breakpad/common/breakpad_types.h"
  112. #include "google_breakpad/common/minidump_format.h"
  113. namespace google_breakpad {
  114. namespace SynthMinidump {
  115. using std::string;
  116. using test_assembler::Endianness;
  117. using test_assembler::kBigEndian;
  118. using test_assembler::kLittleEndian;
  119. using test_assembler::kUnsetEndian;
  120. using test_assembler::Label;
  121. class Dump;
  122. class Memory;
  123. class String;
  124. // A test_assembler::Section which will be appended to a minidump.
  125. class Section: public test_assembler::Section {
  126. public:
  127. explicit Section(const Dump &dump);
  128. // Append an MDLocationDescriptor referring to this section to SECTION.
  129. // If 'this' is NULL, append a descriptor with a zero length and MDRVA.
  130. //
  131. // (I couldn't find the language in the C++ standard that says that
  132. // invoking member functions of a NULL pointer to a class type is
  133. // bad, if such language exists. Having this function handle NULL
  134. // 'this' is convenient, but if it causes trouble, it's not hard to
  135. // do differently.)
  136. void CiteLocationIn(test_assembler::Section *section) const;
  137. // Note that this section's contents are complete, and that it has
  138. // been placed in the minidump file at OFFSET. The 'Add' member
  139. // functions call the Finish member function of the object being
  140. // added for you; if you are 'Add'ing this section, you needn't Finish it.
  141. virtual void Finish(const Label &offset) {
  142. file_offset_ = offset; size_ = Size();
  143. }
  144. protected:
  145. // This section's size and offset within the minidump file.
  146. Label file_offset_, size_;
  147. };
  148. // A stream within a minidump file. 'Add'ing a stream to a minidump
  149. // creates an entry for it in the minidump's stream directory.
  150. class Stream: public Section {
  151. public:
  152. // Create a stream of type TYPE. You can append whatever contents
  153. // you like to this stream using the test_assembler::Section methods.
  154. Stream(const Dump &dump, u_int32_t type) : Section(dump), type_(type) { }
  155. // Append an MDRawDirectory referring to this stream to SECTION.
  156. void CiteStreamIn(test_assembler::Section *section) const;
  157. private:
  158. // The type of this stream.
  159. u_int32_t type_;
  160. };
  161. class SystemInfo: public Stream {
  162. public:
  163. // Create an MD_SYSTEM_INFO_STREAM stream belonging to DUMP holding
  164. // an MDRawSystem info structure initialized with the values from
  165. // SYSTEM_INFO, except that the csd_version field is replaced with
  166. // the file offset of the string CSD_VERSION, which can be 'Add'ed
  167. // to the dump at the desired location.
  168. //
  169. // Remember that you are still responsible for 'Add'ing CSD_VERSION
  170. // to the dump yourself.
  171. SystemInfo(const Dump &dump,
  172. const MDRawSystemInfo &system_info,
  173. const String &csd_version);
  174. // Stock MDRawSystemInfo information and associated strings, for
  175. // writing tests.
  176. static const MDRawSystemInfo windows_x86;
  177. static const string windows_x86_csd_version;
  178. };
  179. // An MDString: a string preceded by a 32-bit length.
  180. class String: public Section {
  181. public:
  182. String(const Dump &dump, const string &value);
  183. // Append an MDRVA referring to this string to SECTION.
  184. void CiteStringIn(test_assembler::Section *section) const;
  185. };
  186. // A range of memory contents. 'Add'ing a memory range to a minidump
  187. // creates n entry for it in the minidump's memory list. By
  188. // convention, the 'start', 'Here', and 'Mark' member functions refer
  189. // to memory addresses.
  190. class Memory: public Section {
  191. public:
  192. Memory(const Dump &dump, u_int64_t address)
  193. : Section(dump), address_(address) { start() = address; }
  194. // Append an MDMemoryDescriptor referring to this memory range to SECTION.
  195. void CiteMemoryIn(test_assembler::Section *section) const;
  196. private:
  197. // The process address from which these memory contents were taken.
  198. // Shouldn't this be a Label?
  199. u_int64_t address_;
  200. };
  201. class Context: public Section {
  202. public:
  203. // Create a context belonging to DUMP whose contents are a copy of CONTEXT.
  204. Context(const Dump &dump, const MDRawContextX86 &context);
  205. Context(const Dump &dump, const MDRawContextARM &context);
  206. // Add constructors for other architectures here. Remember to byteswap.
  207. };
  208. class Thread: public Section {
  209. public:
  210. // Create a thread belonging to DUMP with the given values, citing
  211. // STACK and CONTEXT (which you must Add to the dump separately).
  212. Thread(const Dump &dump,
  213. u_int32_t thread_id,
  214. const Memory &stack,
  215. const Context &context,
  216. u_int32_t suspend_count = 0,
  217. u_int32_t priority_class = 0,
  218. u_int32_t priority = 0,
  219. u_int64_t teb = 0);
  220. };
  221. class Module: public Section {
  222. public:
  223. // Create a module with the given values. Note that CV_RECORD and
  224. // MISC_RECORD can be NULL, in which case the corresponding location
  225. // descriptior in the minidump will have a length of zero.
  226. Module(const Dump &dump,
  227. u_int64_t base_of_image,
  228. u_int32_t size_of_image,
  229. const String &name,
  230. u_int32_t time_date_stamp = 1262805309,
  231. u_int32_t checksum = 0,
  232. const MDVSFixedFileInfo &version_info = Module::stock_version_info,
  233. const Section *cv_record = NULL,
  234. const Section *misc_record = NULL);
  235. private:
  236. // A standard MDVSFixedFileInfo structure to use as a default for
  237. // minidumps. There's no reason to make users write out all this crap
  238. // over and over.
  239. static const MDVSFixedFileInfo stock_version_info;
  240. };
  241. class Exception : public Stream {
  242. public:
  243. Exception(const Dump &dump,
  244. const Context &context,
  245. u_int32_t thread_id = 0,
  246. u_int32_t exception_code = 0,
  247. u_int32_t exception_flags = 0,
  248. u_int64_t exception_address = 0);
  249. };
  250. // A list of entries starting with a 32-bit count, like a memory list
  251. // or a thread list.
  252. template<typename Element>
  253. class List: public Stream {
  254. public:
  255. List(const Dump &dump, u_int32_t type) : Stream(dump, type), count_(0) {
  256. D32(count_label_);
  257. }
  258. // Add ELEMENT to this list.
  259. void Add(Element *element) {
  260. element->Finish(file_offset_ + Size());
  261. Append(*element);
  262. count_++;
  263. }
  264. // Return true if this List is empty, false otherwise.
  265. bool Empty() { return count_ == 0; }
  266. // Finish up the contents of this section, mark it as having been
  267. // placed at OFFSET.
  268. virtual void Finish(const Label &offset) {
  269. Stream::Finish(offset);
  270. count_label_ = count_;
  271. }
  272. private:
  273. size_t count_;
  274. Label count_label_;
  275. };
  276. class Dump: public test_assembler::Section {
  277. public:
  278. // Create a test_assembler::Section containing a minidump file whose
  279. // header uses the given values. ENDIANNESS determines the
  280. // endianness of the signature; we set this section's default
  281. // endianness by this.
  282. Dump(u_int64_t flags,
  283. Endianness endianness = kLittleEndian,
  284. u_int32_t version = MD_HEADER_VERSION,
  285. u_int32_t date_time_stamp = 1262805309);
  286. // The following functions call OBJECT->Finish(), and append the
  287. // contents of OBJECT to this minidump. They also record OBJECT in
  288. // whatever directory or list is appropriate for its type. The
  289. // stream directory, memory list, thread list, and module list are
  290. // accumulated this way.
  291. Dump &Add(SynthMinidump::Section *object); // simply append data
  292. Dump &Add(Stream *object); // append, record in stream directory
  293. Dump &Add(Memory *object); // append, record in memory list
  294. Dump &Add(Thread *object); // append, record in thread list
  295. Dump &Add(Module *object); // append, record in module list
  296. // Complete the construction of the minidump, given the Add calls
  297. // we've seen up to this point. After this call, this Dump's
  298. // contents are complete, all labels should be defined if everything
  299. // Cited has been Added, and you may call GetContents on it.
  300. void Finish();
  301. private:
  302. // A label representing the start of the minidump file.
  303. Label file_start_;
  304. // The stream directory. We construct this incrementally from
  305. // Add(Stream *) calls.
  306. SynthMinidump::Section stream_directory_; // The directory's contents.
  307. size_t stream_count_; // The number of streams so far.
  308. Label stream_count_label_; // Cited in file header.
  309. Label stream_directory_rva_; // The directory's file offset.
  310. // This minidump's thread list. We construct this incrementally from
  311. // Add(Thread *) calls.
  312. List<Thread> thread_list_;
  313. // This minidump's module list. We construct this incrementally from
  314. // Add(Module *) calls.
  315. List<Module> module_list_;
  316. // This minidump's memory list. We construct this incrementally from
  317. // Add(Memory *) calls. This is actually a list of MDMemoryDescriptors,
  318. // not memory ranges --- thus the odd type.
  319. List<SynthMinidump::Section> memory_list_;
  320. };
  321. } // namespace SynthMinidump
  322. } // namespace google_breakpad
  323. #endif // PROCESSOR_SYNTH_MINIDUMP_H_