1 // Copyright (c) 2006, 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 // minidump.cc: A minidump reader.
31 //
32 // See minidump.h for documentation.
33 //
34 // Author: Mark Mentovai
35 
36 #ifdef _WIN32
37 #define NOMINMAX
38 #endif
39 
40 #include <fcntl.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <time.h>
44 
45 #include <cassert>
46 #include <limits>
47 #include <map>
48 #include <vector>
49 
50 #include "processor/range_map-inl.h"
51 
52 #include "google_breakpad/processor/minidump.h"
53 #include "processor/basic_code_module.h"
54 #include "processor/basic_code_modules.h"
55 #include "processor/logging.h"
56 #include "processor/scoped_ptr.h"
57 
58 #ifdef _WIN32
59 #include <io.h>
60 #include <stdint.h>
61 typedef SSIZE_T ssize_t;
62 #define open _open
63 #define read _read
64 #define lseek _lseek
65 #define snprintf _snprintf
66 #define gmtime_r(d, res) { struct tm* _t = gmtime(d); memcpy(res, _t, sizeof(tm)); }
67 #else  // _WIN32
68 #include <unistd.h>
69 #define O_BINARY 0
70 #endif  // _WIN32
71 
72 
73 namespace google_breakpad {
74 
75 
76 using std::numeric_limits;
77 using std::vector;
78 
79 
80 //
81 // Swapping routines
82 //
83 // Inlining these doesn't increase code size significantly, and it saves
84 // a whole lot of unnecessary jumping back and forth.
85 //
86 
87 
88 // Swapping an 8-bit quantity is a no-op.  This function is only provided
89 // to account for certain templatized operations that require swapping for
90 // wider types but handle u_int8_t too
91 // (MinidumpMemoryRegion::GetMemoryAtAddressInternal).
Swap(u_int8_t * value)92 static inline void Swap(u_int8_t* value) {
93 }
94 
95 
96 // Optimization: don't need to AND the furthest right shift, because we're
97 // shifting an unsigned quantity.  The standard requires zero-filling in this
98 // case.  If the quantities were signed, a bitmask whould be needed for this
99 // right shift to avoid an arithmetic shift (which retains the sign bit).
100 // The furthest left shift never needs to be ANDed bitmask.
101 
102 
Swap(u_int16_t * value)103 static inline void Swap(u_int16_t* value) {
104   *value = (*value >> 8) |
105            (*value << 8);
106 }
107 
108 
Swap(u_int32_t * value)109 static inline void Swap(u_int32_t* value) {
110   *value =  (*value >> 24) |
111            ((*value >> 8)  & 0x0000ff00) |
112            ((*value << 8)  & 0x00ff0000) |
113             (*value << 24);
114 }
115 
116 
Swap(u_int64_t * value)117 static inline void Swap(u_int64_t* value) {
118   u_int32_t* value32 = reinterpret_cast<u_int32_t*>(value);
119   Swap(&value32[0]);
120   Swap(&value32[1]);
121   u_int32_t temp = value32[0];
122   value32[0] = value32[1];
123   value32[1] = temp;
124 }
125 
126 
127 // Given a pointer to a 128-bit int in the minidump data, set the "low"
128 // and "high" fields appropriately.
Normalize128(u_int128_t * value,bool is_big_endian)129 static void Normalize128(u_int128_t* value, bool is_big_endian) {
130   // The struct format is [high, low], so if the format is big-endian,
131   // the most significant bytes will already be in the high field.
132   if (!is_big_endian) {
133     u_int64_t temp = value->low;
134     value->low = value->high;
135     value->high = temp;
136   }
137 }
138 
139 // This just swaps each int64 half of the 128-bit value.
140 // The value should also be normalized by calling Normalize128().
Swap(u_int128_t * value)141 static void Swap(u_int128_t* value) {
142   Swap(&value->low);
143   Swap(&value->high);
144 }
145 
146 
Swap(MDLocationDescriptor * location_descriptor)147 static inline void Swap(MDLocationDescriptor* location_descriptor) {
148   Swap(&location_descriptor->data_size);
149   Swap(&location_descriptor->rva);
150 }
151 
152 
Swap(MDMemoryDescriptor * memory_descriptor)153 static inline void Swap(MDMemoryDescriptor* memory_descriptor) {
154   Swap(&memory_descriptor->start_of_memory_range);
155   Swap(&memory_descriptor->memory);
156 }
157 
158 
Swap(MDGUID * guid)159 static inline void Swap(MDGUID* guid) {
160   Swap(&guid->data1);
161   Swap(&guid->data2);
162   Swap(&guid->data3);
163   // Don't swap guid->data4[] because it contains 8-bit quantities.
164 }
165 
166 
167 //
168 // Character conversion routines
169 //
170 
171 
172 // Standard wide-character conversion routines depend on the system's own
173 // idea of what width a wide character should be: some use 16 bits, and
174 // some use 32 bits.  For the purposes of a minidump, wide strings are
175 // always represented with 16-bit UTF-16 chracters.  iconv isn't available
176 // everywhere, and its interface varies where it is available.  iconv also
177 // deals purely with char* pointers, so in addition to considering the swap
178 // parameter, a converter that uses iconv would also need to take the host
179 // CPU's endianness into consideration.  It doesn't seems worth the trouble
180 // of making it a dependency when we don't care about anything but UTF-16.
UTF16ToUTF8(const vector<u_int16_t> & in,bool swap)181 static string* UTF16ToUTF8(const vector<u_int16_t>& in,
182                            bool                     swap) {
183   scoped_ptr<string> out(new string());
184 
185   // Set the string's initial capacity to the number of UTF-16 characters,
186   // because the UTF-8 representation will always be at least this long.
187   // If the UTF-8 representation is longer, the string will grow dynamically.
188   out->reserve(in.size());
189 
190   for (vector<u_int16_t>::const_iterator iterator = in.begin();
191        iterator != in.end();
192        ++iterator) {
193     // Get a 16-bit value from the input
194     u_int16_t in_word = *iterator;
195     if (swap)
196       Swap(&in_word);
197 
198     // Convert the input value (in_word) into a Unicode code point (unichar).
199     u_int32_t unichar;
200     if (in_word >= 0xdc00 && in_word <= 0xdcff) {
201       BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " <<
202                       HexString(in_word) << " without high";
203       return NULL;
204     } else if (in_word >= 0xd800 && in_word <= 0xdbff) {
205       // High surrogate.
206       unichar = (in_word - 0xd7c0) << 10;
207       if (++iterator == in.end()) {
208         BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
209                         HexString(in_word) << " at end of string";
210         return NULL;
211       }
212       u_int32_t high_word = in_word;
213       in_word = *iterator;
214       if (in_word < 0xdc00 || in_word > 0xdcff) {
215         BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
216                         HexString(high_word) << " without low " <<
217                         HexString(in_word);
218         return NULL;
219       }
220       unichar |= in_word & 0x03ff;
221     } else {
222       // The ordinary case, a single non-surrogate Unicode character encoded
223       // as a single 16-bit value.
224       unichar = in_word;
225     }
226 
227     // Convert the Unicode code point (unichar) into its UTF-8 representation,
228     // appending it to the out string.
229     if (unichar < 0x80) {
230       (*out) += unichar;
231     } else if (unichar < 0x800) {
232       (*out) += 0xc0 | (unichar >> 6);
233       (*out) += 0x80 | (unichar & 0x3f);
234     } else if (unichar < 0x10000) {
235       (*out) += 0xe0 | (unichar >> 12);
236       (*out) += 0x80 | ((unichar >> 6) & 0x3f);
237       (*out) += 0x80 | (unichar & 0x3f);
238     } else if (unichar < 0x200000) {
239       (*out) += 0xf0 | (unichar >> 18);
240       (*out) += 0x80 | ((unichar >> 12) & 0x3f);
241       (*out) += 0x80 | ((unichar >> 6) & 0x3f);
242       (*out) += 0x80 | (unichar & 0x3f);
243     } else {
244       BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " <<
245                       HexString(unichar) << " in UTF-8";
246       return NULL;
247     }
248   }
249 
250   return out.release();
251 }
252 
253 
254 //
255 // MinidumpObject
256 //
257 
258 
MinidumpObject(Minidump * minidump)259 MinidumpObject::MinidumpObject(Minidump* minidump)
260     : minidump_(minidump),
261       valid_(false) {
262 }
263 
264 
265 //
266 // MinidumpStream
267 //
268 
269 
MinidumpStream(Minidump * minidump)270 MinidumpStream::MinidumpStream(Minidump* minidump)
271     : MinidumpObject(minidump) {
272 }
273 
274 
275 //
276 // MinidumpContext
277 //
278 
279 
MinidumpContext(Minidump * minidump)280 MinidumpContext::MinidumpContext(Minidump* minidump)
281     : MinidumpStream(minidump),
282       context_flags_(0),
283       context_() {
284 }
285 
286 
~MinidumpContext()287 MinidumpContext::~MinidumpContext() {
288   FreeContext();
289 }
290 
291 
Read(u_int32_t expected_size)292 bool MinidumpContext::Read(u_int32_t expected_size) {
293   valid_ = false;
294 
295   FreeContext();
296 
297   // First, figure out what type of CPU this context structure is for.
298   // For some reason, the AMD64 Context doesn't have context_flags
299   // at the beginning of the structure, so special case it here.
300   if (expected_size == sizeof(MDRawContextAMD64)) {
301     BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
302 
303     scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
304     if (!minidump_->ReadBytes(context_amd64.get(),
305                               sizeof(MDRawContextAMD64))) {
306       BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
307       return false;
308     }
309 
310     if (minidump_->swap())
311       Swap(&context_amd64->context_flags);
312 
313     u_int32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK;
314 
315     if (cpu_type != MD_CONTEXT_AMD64) {
316       //TODO: fall through to switch below?
317       // need a Tell method to be able to SeekSet back to beginning
318       // http://code.google.com/p/google-breakpad/issues/detail?id=224
319       BPLOG(ERROR) << "MinidumpContext not actually amd64 context";
320       return false;
321     }
322 
323     // Do this after reading the entire MDRawContext structure because
324     // GetSystemInfo may seek minidump to a new position.
325     if (!CheckAgainstSystemInfo(cpu_type)) {
326       BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
327       return false;
328     }
329 
330     // Normalize the 128-bit types in the dump.
331     // Since this is AMD64, by definition, the values are little-endian.
332     for (unsigned int vr_index = 0;
333          vr_index < MD_CONTEXT_AMD64_VR_COUNT;
334          ++vr_index)
335       Normalize128(&context_amd64->vector_register[vr_index], false);
336 
337     if (minidump_->swap()) {
338       Swap(&context_amd64->p1_home);
339       Swap(&context_amd64->p2_home);
340       Swap(&context_amd64->p3_home);
341       Swap(&context_amd64->p4_home);
342       Swap(&context_amd64->p5_home);
343       Swap(&context_amd64->p6_home);
344       // context_flags is already swapped
345       Swap(&context_amd64->mx_csr);
346       Swap(&context_amd64->cs);
347       Swap(&context_amd64->ds);
348       Swap(&context_amd64->es);
349       Swap(&context_amd64->fs);
350       Swap(&context_amd64->ss);
351       Swap(&context_amd64->eflags);
352       Swap(&context_amd64->dr0);
353       Swap(&context_amd64->dr1);
354       Swap(&context_amd64->dr2);
355       Swap(&context_amd64->dr3);
356       Swap(&context_amd64->dr6);
357       Swap(&context_amd64->dr7);
358       Swap(&context_amd64->rax);
359       Swap(&context_amd64->rcx);
360       Swap(&context_amd64->rdx);
361       Swap(&context_amd64->rbx);
362       Swap(&context_amd64->rsp);
363       Swap(&context_amd64->rbp);
364       Swap(&context_amd64->rsi);
365       Swap(&context_amd64->rdi);
366       Swap(&context_amd64->r8);
367       Swap(&context_amd64->r9);
368       Swap(&context_amd64->r10);
369       Swap(&context_amd64->r11);
370       Swap(&context_amd64->r12);
371       Swap(&context_amd64->r13);
372       Swap(&context_amd64->r14);
373       Swap(&context_amd64->r15);
374       Swap(&context_amd64->rip);
375       //FIXME: I'm not sure what actually determines
376       // which member of the union {flt_save, sse_registers}
377       // is valid.  We're not currently using either,
378       // but it would be good to have them swapped properly.
379 
380       for (unsigned int vr_index = 0;
381            vr_index < MD_CONTEXT_AMD64_VR_COUNT;
382            ++vr_index)
383         Swap(&context_amd64->vector_register[vr_index]);
384       Swap(&context_amd64->vector_control);
385       Swap(&context_amd64->debug_control);
386       Swap(&context_amd64->last_branch_to_rip);
387       Swap(&context_amd64->last_branch_from_rip);
388       Swap(&context_amd64->last_exception_to_rip);
389       Swap(&context_amd64->last_exception_from_rip);
390     }
391 
392     context_flags_ = context_amd64->context_flags;
393 
394     context_.amd64 = context_amd64.release();
395   }
396   else {
397     u_int32_t context_flags;
398     if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
399       BPLOG(ERROR) << "MinidumpContext could not read context flags";
400       return false;
401     }
402     if (minidump_->swap())
403       Swap(&context_flags);
404 
405     u_int32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
406 
407     // Allocate the context structure for the correct CPU and fill it.  The
408     // casts are slightly unorthodox, but it seems better to do that than to
409     // maintain a separate pointer for each type of CPU context structure
410     // when only one of them will be used.
411     switch (cpu_type) {
412       case MD_CONTEXT_X86: {
413         if (expected_size != sizeof(MDRawContextX86)) {
414           BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
415             expected_size << " != " << sizeof(MDRawContextX86);
416           return false;
417         }
418 
419         scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
420 
421         // Set the context_flags member, which has already been read, and
422         // read the rest of the structure beginning with the first member
423         // after context_flags.
424         context_x86->context_flags = context_flags;
425 
426         size_t flags_size = sizeof(context_x86->context_flags);
427         u_int8_t* context_after_flags =
428           reinterpret_cast<u_int8_t*>(context_x86.get()) + flags_size;
429         if (!minidump_->ReadBytes(context_after_flags,
430                                   sizeof(MDRawContextX86) - flags_size)) {
431           BPLOG(ERROR) << "MinidumpContext could not read x86 context";
432           return false;
433         }
434 
435         // Do this after reading the entire MDRawContext structure because
436         // GetSystemInfo may seek minidump to a new position.
437         if (!CheckAgainstSystemInfo(cpu_type)) {
438           BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
439           return false;
440         }
441 
442         if (minidump_->swap()) {
443           // context_x86->context_flags was already swapped.
444           Swap(&context_x86->dr0);
445           Swap(&context_x86->dr1);
446           Swap(&context_x86->dr2);
447           Swap(&context_x86->dr3);
448           Swap(&context_x86->dr6);
449           Swap(&context_x86->dr7);
450           Swap(&context_x86->float_save.control_word);
451           Swap(&context_x86->float_save.status_word);
452           Swap(&context_x86->float_save.tag_word);
453           Swap(&context_x86->float_save.error_offset);
454           Swap(&context_x86->float_save.error_selector);
455           Swap(&context_x86->float_save.data_offset);
456           Swap(&context_x86->float_save.data_selector);
457           // context_x86->float_save.register_area[] contains 8-bit quantities
458           // and does not need to be swapped.
459           Swap(&context_x86->float_save.cr0_npx_state);
460           Swap(&context_x86->gs);
461           Swap(&context_x86->fs);
462           Swap(&context_x86->es);
463           Swap(&context_x86->ds);
464           Swap(&context_x86->edi);
465           Swap(&context_x86->esi);
466           Swap(&context_x86->ebx);
467           Swap(&context_x86->edx);
468           Swap(&context_x86->ecx);
469           Swap(&context_x86->eax);
470           Swap(&context_x86->ebp);
471           Swap(&context_x86->eip);
472           Swap(&context_x86->cs);
473           Swap(&context_x86->eflags);
474           Swap(&context_x86->esp);
475           Swap(&context_x86->ss);
476           // context_x86->extended_registers[] contains 8-bit quantities and
477           // does not need to be swapped.
478         }
479 
480         context_.x86 = context_x86.release();
481 
482         break;
483       }
484 
485       case MD_CONTEXT_PPC: {
486         if (expected_size != sizeof(MDRawContextPPC)) {
487           BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
488             expected_size << " != " << sizeof(MDRawContextPPC);
489           return false;
490         }
491 
492         scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
493 
494         // Set the context_flags member, which has already been read, and
495         // read the rest of the structure beginning with the first member
496         // after context_flags.
497         context_ppc->context_flags = context_flags;
498 
499         size_t flags_size = sizeof(context_ppc->context_flags);
500         u_int8_t* context_after_flags =
501           reinterpret_cast<u_int8_t*>(context_ppc.get()) + flags_size;
502         if (!minidump_->ReadBytes(context_after_flags,
503                                   sizeof(MDRawContextPPC) - flags_size)) {
504           BPLOG(ERROR) << "MinidumpContext could not read ppc context";
505           return false;
506         }
507 
508         // Do this after reading the entire MDRawContext structure because
509         // GetSystemInfo may seek minidump to a new position.
510         if (!CheckAgainstSystemInfo(cpu_type)) {
511           BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
512           return false;
513         }
514 
515         // Normalize the 128-bit types in the dump.
516         // Since this is PowerPC, by definition, the values are big-endian.
517         for (unsigned int vr_index = 0;
518              vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
519              ++vr_index) {
520           Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
521         }
522 
523         if (minidump_->swap()) {
524           // context_ppc->context_flags was already swapped.
525           Swap(&context_ppc->srr0);
526           Swap(&context_ppc->srr1);
527           for (unsigned int gpr_index = 0;
528                gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
529                ++gpr_index) {
530             Swap(&context_ppc->gpr[gpr_index]);
531           }
532           Swap(&context_ppc->cr);
533           Swap(&context_ppc->xer);
534           Swap(&context_ppc->lr);
535           Swap(&context_ppc->ctr);
536           Swap(&context_ppc->mq);
537           Swap(&context_ppc->vrsave);
538           for (unsigned int fpr_index = 0;
539                fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
540                ++fpr_index) {
541             Swap(&context_ppc->float_save.fpregs[fpr_index]);
542           }
543           // Don't swap context_ppc->float_save.fpscr_pad because it is only
544           // used for padding.
545           Swap(&context_ppc->float_save.fpscr);
546           for (unsigned int vr_index = 0;
547                vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
548                ++vr_index) {
549             Swap(&context_ppc->vector_save.save_vr[vr_index]);
550           }
551           Swap(&context_ppc->vector_save.save_vscr);
552           // Don't swap the padding fields in vector_save.
553           Swap(&context_ppc->vector_save.save_vrvalid);
554         }
555 
556         context_.ppc = context_ppc.release();
557 
558         break;
559       }
560 
561       case MD_CONTEXT_SPARC: {
562         if (expected_size != sizeof(MDRawContextSPARC)) {
563           BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " <<
564             expected_size << " != " << sizeof(MDRawContextSPARC);
565           return false;
566         }
567 
568         scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC());
569 
570         // Set the context_flags member, which has already been read, and
571         // read the rest of the structure beginning with the first member
572         // after context_flags.
573         context_sparc->context_flags = context_flags;
574 
575         size_t flags_size = sizeof(context_sparc->context_flags);
576         u_int8_t* context_after_flags =
577             reinterpret_cast<u_int8_t*>(context_sparc.get()) + flags_size;
578         if (!minidump_->ReadBytes(context_after_flags,
579                                   sizeof(MDRawContextSPARC) - flags_size)) {
580           BPLOG(ERROR) << "MinidumpContext could not read sparc context";
581           return false;
582         }
583 
584         // Do this after reading the entire MDRawContext structure because
585         // GetSystemInfo may seek minidump to a new position.
586         if (!CheckAgainstSystemInfo(cpu_type)) {
587           BPLOG(ERROR) << "MinidumpContext sparc does not match system info";
588           return false;
589         }
590 
591         if (minidump_->swap()) {
592           // context_sparc->context_flags was already swapped.
593           for (unsigned int gpr_index = 0;
594                gpr_index < MD_CONTEXT_SPARC_GPR_COUNT;
595                ++gpr_index) {
596             Swap(&context_sparc->g_r[gpr_index]);
597           }
598           Swap(&context_sparc->ccr);
599           Swap(&context_sparc->pc);
600           Swap(&context_sparc->npc);
601           Swap(&context_sparc->y);
602           Swap(&context_sparc->asi);
603           Swap(&context_sparc->fprs);
604           for (unsigned int fpr_index = 0;
605                fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
606                ++fpr_index) {
607             Swap(&context_sparc->float_save.regs[fpr_index]);
608           }
609           Swap(&context_sparc->float_save.filler);
610           Swap(&context_sparc->float_save.fsr);
611         }
612         context_.ctx_sparc = context_sparc.release();
613 
614         break;
615       }
616 
617       default: {
618         // Unknown context type
619         BPLOG(ERROR) << "MinidumpContext unknown context type " <<
620           HexString(cpu_type);
621         return false;
622         break;
623       }
624     }
625     context_flags_ = context_flags;
626   }
627 
628   valid_ = true;
629   return true;
630 }
631 
632 
GetContextCPU() const633 u_int32_t MinidumpContext::GetContextCPU() const {
634   if (!valid_) {
635     // Don't log a message, GetContextCPU can be legitimately called with
636     // valid_ false by FreeContext, which is called by Read.
637     return 0;
638   }
639 
640   return context_flags_ & MD_CONTEXT_CPU_MASK;
641 }
642 
643 
GetContextX86() const644 const MDRawContextX86* MinidumpContext::GetContextX86() const {
645   if (GetContextCPU() != MD_CONTEXT_X86) {
646     BPLOG(ERROR) << "MinidumpContext cannot get x86 context";
647     return NULL;
648   }
649 
650   return context_.x86;
651 }
652 
653 
GetContextPPC() const654 const MDRawContextPPC* MinidumpContext::GetContextPPC() const {
655   if (GetContextCPU() != MD_CONTEXT_PPC) {
656     BPLOG(ERROR) << "MinidumpContext cannot get ppc context";
657     return NULL;
658   }
659 
660   return context_.ppc;
661 }
662 
GetContextAMD64() const663 const MDRawContextAMD64* MinidumpContext::GetContextAMD64() const {
664   if (GetContextCPU() != MD_CONTEXT_AMD64) {
665     BPLOG(ERROR) << "MinidumpContext cannot get amd64 context";
666     return NULL;
667   }
668 
669   return context_.amd64;
670 }
671 
GetContextSPARC() const672 const MDRawContextSPARC* MinidumpContext::GetContextSPARC() const {
673   if (GetContextCPU() != MD_CONTEXT_SPARC) {
674     BPLOG(ERROR) << "MinidumpContext cannot get sparc context";
675     return NULL;
676   }
677 
678   return context_.ctx_sparc;
679 }
680 
FreeContext()681 void MinidumpContext::FreeContext() {
682   switch (GetContextCPU()) {
683     case MD_CONTEXT_X86:
684       delete context_.x86;
685       break;
686 
687     case MD_CONTEXT_PPC:
688       delete context_.ppc;
689       break;
690 
691     case MD_CONTEXT_AMD64:
692       delete context_.amd64;
693       break;
694 
695     case MD_CONTEXT_SPARC:
696       delete context_.ctx_sparc;
697       break;
698 
699     default:
700       // There is no context record (valid_ is false) or there's a
701       // context record for an unknown CPU (shouldn't happen, only known
702       // records are stored by Read).
703       break;
704   }
705 
706   context_flags_ = 0;
707   context_.base = NULL;
708 }
709 
710 
CheckAgainstSystemInfo(u_int32_t context_cpu_type)711 bool MinidumpContext::CheckAgainstSystemInfo(u_int32_t context_cpu_type) {
712   // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM,
713   // as this function just implements a sanity check.
714   MinidumpSystemInfo* system_info = minidump_->GetSystemInfo();
715   if (!system_info) {
716     BPLOG(INFO) << "MinidumpContext could not be compared against "
717                    "MinidumpSystemInfo";
718     return true;
719   }
720 
721   // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info.
722   const MDRawSystemInfo* raw_system_info = system_info->system_info();
723   if (!raw_system_info) {
724     BPLOG(INFO) << "MinidumpContext could not be compared against "
725                    "MDRawSystemInfo";
726     return false;
727   }
728 
729   MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>(
730       raw_system_info->processor_architecture);
731 
732   // Compare the CPU type of the context record to the CPU type in the
733   // minidump's system info stream.
734   bool return_value = false;
735   switch (context_cpu_type) {
736     case MD_CONTEXT_X86:
737       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 ||
738           system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 ||
739           system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) {
740         return_value = true;
741       }
742       break;
743 
744     case MD_CONTEXT_PPC:
745       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC)
746         return_value = true;
747       break;
748 
749     case MD_CONTEXT_AMD64:
750       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64)
751         return_value = true;
752       break;
753 
754     case MD_CONTEXT_SPARC:
755       if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC)
756         return_value = true;
757       break;
758   }
759 
760   BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " <<
761                                     HexString(context_cpu_type) <<
762                                     " wrong for MinidumpSysmtemInfo CPU " <<
763                                     HexString(system_info_cpu_type);
764 
765   return return_value;
766 }
767 
768 
Print()769 void MinidumpContext::Print() {
770   if (!valid_) {
771     BPLOG(ERROR) << "MinidumpContext cannot print invalid data";
772     return;
773   }
774 
775   switch (GetContextCPU()) {
776     case MD_CONTEXT_X86: {
777       const MDRawContextX86* context_x86 = GetContextX86();
778       printf("MDRawContextX86\n");
779       printf("  context_flags                = 0x%x\n",
780              context_x86->context_flags);
781       printf("  dr0                          = 0x%x\n", context_x86->dr0);
782       printf("  dr1                          = 0x%x\n", context_x86->dr1);
783       printf("  dr2                          = 0x%x\n", context_x86->dr2);
784       printf("  dr3                          = 0x%x\n", context_x86->dr3);
785       printf("  dr6                          = 0x%x\n", context_x86->dr6);
786       printf("  dr7                          = 0x%x\n", context_x86->dr7);
787       printf("  float_save.control_word      = 0x%x\n",
788              context_x86->float_save.control_word);
789       printf("  float_save.status_word       = 0x%x\n",
790              context_x86->float_save.status_word);
791       printf("  float_save.tag_word          = 0x%x\n",
792              context_x86->float_save.tag_word);
793       printf("  float_save.error_offset      = 0x%x\n",
794              context_x86->float_save.error_offset);
795       printf("  float_save.error_selector    = 0x%x\n",
796              context_x86->float_save.error_selector);
797       printf("  float_save.data_offset       = 0x%x\n",
798              context_x86->float_save.data_offset);
799       printf("  float_save.data_selector     = 0x%x\n",
800              context_x86->float_save.data_selector);
801       printf("  float_save.register_area[%2d] = 0x",
802              MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE);
803       for (unsigned int register_index = 0;
804            register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE;
805            ++register_index) {
806         printf("%02x", context_x86->float_save.register_area[register_index]);
807       }
808       printf("\n");
809       printf("  float_save.cr0_npx_state     = 0x%x\n",
810              context_x86->float_save.cr0_npx_state);
811       printf("  gs                           = 0x%x\n", context_x86->gs);
812       printf("  fs                           = 0x%x\n", context_x86->fs);
813       printf("  es                           = 0x%x\n", context_x86->es);
814       printf("  ds                           = 0x%x\n", context_x86->ds);
815       printf("  edi                          = 0x%x\n", context_x86->edi);
816       printf("  esi                          = 0x%x\n", context_x86->esi);
817       printf("  ebx                          = 0x%x\n", context_x86->ebx);
818       printf("  edx                          = 0x%x\n", context_x86->edx);
819       printf("  ecx                          = 0x%x\n", context_x86->ecx);
820       printf("  eax                          = 0x%x\n", context_x86->eax);
821       printf("  ebp                          = 0x%x\n", context_x86->ebp);
822       printf("  eip                          = 0x%x\n", context_x86->eip);
823       printf("  cs                           = 0x%x\n", context_x86->cs);
824       printf("  eflags                       = 0x%x\n", context_x86->eflags);
825       printf("  esp                          = 0x%x\n", context_x86->esp);
826       printf("  ss                           = 0x%x\n", context_x86->ss);
827       printf("  extended_registers[%3d]      = 0x",
828              MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE);
829       for (unsigned int register_index = 0;
830            register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE;
831            ++register_index) {
832         printf("%02x", context_x86->extended_registers[register_index]);
833       }
834       printf("\n\n");
835 
836       break;
837     }
838 
839     case MD_CONTEXT_PPC: {
840       const MDRawContextPPC* context_ppc = GetContextPPC();
841       printf("MDRawContextPPC\n");
842       printf("  context_flags            = 0x%x\n",
843              context_ppc->context_flags);
844       printf("  srr0                     = 0x%x\n", context_ppc->srr0);
845       printf("  srr1                     = 0x%x\n", context_ppc->srr1);
846       for (unsigned int gpr_index = 0;
847            gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
848            ++gpr_index) {
849         printf("  gpr[%2d]                  = 0x%x\n",
850                gpr_index, context_ppc->gpr[gpr_index]);
851       }
852       printf("  cr                       = 0x%x\n", context_ppc->cr);
853       printf("  xer                      = 0x%x\n", context_ppc->xer);
854       printf("  lr                       = 0x%x\n", context_ppc->lr);
855       printf("  ctr                      = 0x%x\n", context_ppc->ctr);
856       printf("  mq                       = 0x%x\n", context_ppc->mq);
857       printf("  vrsave                   = 0x%x\n", context_ppc->vrsave);
858       for (unsigned int fpr_index = 0;
859            fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
860            ++fpr_index) {
861         printf("  float_save.fpregs[%2d]    = 0x%" PRIx64 "\n",
862                fpr_index, context_ppc->float_save.fpregs[fpr_index]);
863       }
864       printf("  float_save.fpscr         = 0x%x\n",
865              context_ppc->float_save.fpscr);
866       // TODO(mmentovai): print the 128-bit quantities in
867       // context_ppc->vector_save.  This isn't done yet because printf
868       // doesn't support 128-bit quantities, and printing them using
869       // PRIx64 as two 64-bit quantities requires knowledge of the CPU's
870       // byte ordering.
871       printf("  vector_save.save_vrvalid = 0x%x\n",
872              context_ppc->vector_save.save_vrvalid);
873       printf("\n");
874 
875       break;
876     }
877 
878     case MD_CONTEXT_AMD64: {
879       const MDRawContextAMD64* context_amd64 = GetContextAMD64();
880       printf("MDRawContextAMD64\n");
881       printf("  p1_home       = 0x%" PRIx64 "\n",
882              context_amd64->p1_home);
883       printf("  p2_home       = 0x%" PRIx64 "\n",
884              context_amd64->p2_home);
885       printf("  p3_home       = 0x%" PRIx64 "\n",
886              context_amd64->p3_home);
887       printf("  p4_home       = 0x%" PRIx64 "\n",
888              context_amd64->p4_home);
889       printf("  p5_home       = 0x%" PRIx64 "\n",
890              context_amd64->p5_home);
891       printf("  p6_home       = 0x%" PRIx64 "\n",
892              context_amd64->p6_home);
893       printf("  context_flags = 0x%x\n",
894              context_amd64->context_flags);
895       printf("  mx_csr        = 0x%x\n",
896              context_amd64->mx_csr);
897       printf("  cs            = 0x%x\n", context_amd64->cs);
898       printf("  ds            = 0x%x\n", context_amd64->ds);
899       printf("  es            = 0x%x\n", context_amd64->es);
900       printf("  fs            = 0x%x\n", context_amd64->fs);
901       printf("  gs            = 0x%x\n", context_amd64->gs);
902       printf("  ss            = 0x%x\n", context_amd64->ss);
903       printf("  eflags        = 0x%x\n", context_amd64->eflags);
904       printf("  dr0           = 0x%" PRIx64 "\n", context_amd64->dr0);
905       printf("  dr1           = 0x%" PRIx64 "\n", context_amd64->dr1);
906       printf("  dr2           = 0x%" PRIx64 "\n", context_amd64->dr2);
907       printf("  dr3           = 0x%" PRIx64 "\n", context_amd64->dr3);
908       printf("  dr6           = 0x%" PRIx64 "\n", context_amd64->dr6);
909       printf("  dr7           = 0x%" PRIx64 "\n", context_amd64->dr7);
910       printf("  rax           = 0x%" PRIx64 "\n", context_amd64->rax);
911       printf("  rcx           = 0x%" PRIx64 "\n", context_amd64->rcx);
912       printf("  rdx           = 0x%" PRIx64 "\n", context_amd64->rdx);
913       printf("  rbx           = 0x%" PRIx64 "\n", context_amd64->rbx);
914       printf("  rsp           = 0x%" PRIx64 "\n", context_amd64->rsp);
915       printf("  rbp           = 0x%" PRIx64 "\n", context_amd64->rbp);
916       printf("  rsi           = 0x%" PRIx64 "\n", context_amd64->rsi);
917       printf("  rdi           = 0x%" PRIx64 "\n", context_amd64->rdi);
918       printf("  r8            = 0x%" PRIx64 "\n", context_amd64->r8);
919       printf("  r9            = 0x%" PRIx64 "\n", context_amd64->r9);
920       printf("  r10           = 0x%" PRIx64 "\n", context_amd64->r10);
921       printf("  r11           = 0x%" PRIx64 "\n", context_amd64->r11);
922       printf("  r12           = 0x%" PRIx64 "\n", context_amd64->r12);
923       printf("  r13           = 0x%" PRIx64 "\n", context_amd64->r13);
924       printf("  r14           = 0x%" PRIx64 "\n", context_amd64->r14);
925       printf("  r15           = 0x%" PRIx64 "\n", context_amd64->r15);
926       printf("  rip           = 0x%" PRIx64 "\n", context_amd64->rip);
927       //TODO: print xmm, vector, debug registers
928       printf("\n");
929       break;
930     }
931 
932     case MD_CONTEXT_SPARC: {
933       const MDRawContextSPARC* context_sparc = GetContextSPARC();
934       printf("MDRawContextSPARC\n");
935       printf("  context_flags       = 0x%x\n",
936              context_sparc->context_flags);
937       for (unsigned int g_r_index = 0;
938            g_r_index < MD_CONTEXT_SPARC_GPR_COUNT;
939            ++g_r_index) {
940         printf("  g_r[%2d]             = 0x%" PRIx64 "\n",
941                g_r_index, context_sparc->g_r[g_r_index]);
942       }
943       printf("  ccr                 = 0x%" PRIx64 "\n", context_sparc->ccr);
944       printf("  pc                  = 0x%" PRIx64 "\n", context_sparc->pc);
945       printf("  npc                 = 0x%" PRIx64 "\n", context_sparc->npc);
946       printf("  y                   = 0x%" PRIx64 "\n", context_sparc->y);
947       printf("  asi                 = 0x%" PRIx64 "\n", context_sparc->asi);
948       printf("  fprs                = 0x%" PRIx64 "\n", context_sparc->fprs);
949 
950       for (unsigned int fpr_index = 0;
951            fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
952            ++fpr_index) {
953         printf("  float_save.regs[%2d] = 0x%" PRIx64 "\n",
954                fpr_index, context_sparc->float_save.regs[fpr_index]);
955       }
956       printf("  float_save.filler   = 0x%" PRIx64 "\n",
957              context_sparc->float_save.filler);
958       printf("  float_save.fsr      = 0x%" PRIx64 "\n",
959              context_sparc->float_save.fsr);
960       break;
961     }
962 
963     default: {
964       break;
965     }
966   }
967 }
968 
969 
970 //
971 // MinidumpMemoryRegion
972 //
973 
974 
975 u_int32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024;  // 1MB
976 
977 
MinidumpMemoryRegion(Minidump * minidump)978 MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
979     : MinidumpObject(minidump),
980       descriptor_(NULL),
981       memory_(NULL) {
982 }
983 
984 
~MinidumpMemoryRegion()985 MinidumpMemoryRegion::~MinidumpMemoryRegion() {
986   delete memory_;
987 }
988 
989 
SetDescriptor(MDMemoryDescriptor * descriptor)990 void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) {
991   descriptor_ = descriptor;
992   valid_ = descriptor &&
993            descriptor_->memory.data_size <=
994                numeric_limits<uint64_t>::max() -
995                descriptor_->start_of_memory_range;
996 }
997 
998 
GetMemory()999 const u_int8_t* MinidumpMemoryRegion::GetMemory() {
1000   if (!valid_) {
1001     BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory";
1002     return NULL;
1003   }
1004 
1005   if (!memory_) {
1006     if (descriptor_->memory.data_size == 0) {
1007       BPLOG(ERROR) << "MinidumpMemoryRegion is empty";
1008       return NULL;
1009     }
1010 
1011     if (!minidump_->SeekSet(descriptor_->memory.rva)) {
1012       BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region";
1013       return NULL;
1014     }
1015 
1016     if (descriptor_->memory.data_size > max_bytes_) {
1017       BPLOG(ERROR) << "MinidumpMemoryRegion size " <<
1018                       descriptor_->memory.data_size << " exceeds maximum " <<
1019                       max_bytes_;
1020       return NULL;
1021     }
1022 
1023     scoped_ptr< vector<u_int8_t> > memory(
1024         new vector<u_int8_t>(descriptor_->memory.data_size));
1025 
1026     if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) {
1027       BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region";
1028       return NULL;
1029     }
1030 
1031     memory_ = memory.release();
1032   }
1033 
1034   return &(*memory_)[0];
1035 }
1036 
1037 
GetBase()1038 u_int64_t MinidumpMemoryRegion::GetBase() {
1039   if (!valid_) {
1040     BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase";
1041     return static_cast<u_int64_t>(-1);
1042   }
1043 
1044   return descriptor_->start_of_memory_range;
1045 }
1046 
1047 
GetSize()1048 u_int32_t MinidumpMemoryRegion::GetSize() {
1049   if (!valid_) {
1050     BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize";
1051     return 0;
1052   }
1053 
1054   return descriptor_->memory.data_size;
1055 }
1056 
1057 
FreeMemory()1058 void MinidumpMemoryRegion::FreeMemory() {
1059   delete memory_;
1060   memory_ = NULL;
1061 }
1062 
1063 
1064 template<typename T>
GetMemoryAtAddressInternal(u_int64_t address,T * value)1065 bool MinidumpMemoryRegion::GetMemoryAtAddressInternal(u_int64_t address,
1066                                                       T*        value) {
1067   BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal "
1068                              "requires |value|";
1069   assert(value);
1070   *value = 0;
1071 
1072   if (!valid_) {
1073     BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for "
1074                     "GetMemoryAtAddressInternal";
1075     return false;
1076   }
1077 
1078   if (address < descriptor_->start_of_memory_range ||
1079       sizeof(T) > numeric_limits<u_int64_t>::max() - address ||
1080       address + sizeof(T) > descriptor_->start_of_memory_range +
1081                             descriptor_->memory.data_size) {
1082     BPLOG(ERROR) << "MinidumpMemoryRegion request out of range: " <<
1083                     HexString(address) << "+" << sizeof(T) << "/" <<
1084                     HexString(descriptor_->start_of_memory_range) << "+" <<
1085                     HexString(descriptor_->memory.data_size);
1086     return false;
1087   }
1088 
1089   const u_int8_t* memory = GetMemory();
1090   if (!memory) {
1091     // GetMemory already logged a perfectly good message.
1092     return false;
1093   }
1094 
1095   // If the CPU requires memory accesses to be aligned, this can crash.
1096   // x86 and ppc are able to cope, though.
1097   *value = *reinterpret_cast<const T*>(
1098       &memory[address - descriptor_->start_of_memory_range]);
1099 
1100   if (minidump_->swap())
1101     Swap(value);
1102 
1103   return true;
1104 }
1105 
1106 
GetMemoryAtAddress(u_int64_t address,u_int8_t * value)1107 bool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
1108                                               u_int8_t*  value) {
1109   return GetMemoryAtAddressInternal(address, value);
1110 }
1111 
1112 
GetMemoryAtAddress(u_int64_t address,u_int16_t * value)1113 bool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
1114                                               u_int16_t* value) {
1115   return GetMemoryAtAddressInternal(address, value);
1116 }
1117 
1118 
GetMemoryAtAddress(u_int64_t address,u_int32_t * value)1119 bool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
1120                                               u_int32_t* value) {
1121   return GetMemoryAtAddressInternal(address, value);
1122 }
1123 
1124 
GetMemoryAtAddress(u_int64_t address,u_int64_t * value)1125 bool MinidumpMemoryRegion::GetMemoryAtAddress(u_int64_t  address,
1126                                               u_int64_t* value) {
1127   return GetMemoryAtAddressInternal(address, value);
1128 }
1129 
1130 
Print()1131 void MinidumpMemoryRegion::Print() {
1132   if (!valid_) {
1133     BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data";
1134     return;
1135   }
1136 
1137   const u_int8_t* memory = GetMemory();
1138   if (memory) {
1139     printf("0x");
1140     for (unsigned int byte_index = 0;
1141          byte_index < descriptor_->memory.data_size;
1142          byte_index++) {
1143       printf("%02x", memory[byte_index]);
1144     }
1145     printf("\n");
1146   } else {
1147     printf("No memory\n");
1148   }
1149 }
1150 
1151 
1152 //
1153 // MinidumpThread
1154 //
1155 
1156 
MinidumpThread(Minidump * minidump)1157 MinidumpThread::MinidumpThread(Minidump* minidump)
1158     : MinidumpObject(minidump),
1159       thread_(),
1160       memory_(NULL),
1161       context_(NULL) {
1162 }
1163 
1164 
~MinidumpThread()1165 MinidumpThread::~MinidumpThread() {
1166   delete memory_;
1167   delete context_;
1168 }
1169 
1170 
Read()1171 bool MinidumpThread::Read() {
1172   // Invalidate cached data.
1173   delete memory_;
1174   memory_ = NULL;
1175   delete context_;
1176   context_ = NULL;
1177 
1178   valid_ = false;
1179 
1180   if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) {
1181     BPLOG(ERROR) << "MinidumpThread cannot read thread";
1182     return false;
1183   }
1184 
1185   if (minidump_->swap()) {
1186     Swap(&thread_.thread_id);
1187     Swap(&thread_.suspend_count);
1188     Swap(&thread_.priority_class);
1189     Swap(&thread_.priority);
1190     Swap(&thread_.teb);
1191     Swap(&thread_.stack);
1192     Swap(&thread_.thread_context);
1193   }
1194 
1195   // Check for base + size overflow or undersize.
1196   if (thread_.stack.memory.data_size == 0 ||
1197       thread_.stack.memory.data_size > numeric_limits<u_int64_t>::max() -
1198                                        thread_.stack.start_of_memory_range) {
1199     BPLOG(ERROR) << "MinidumpThread has a memory region problem, " <<
1200                     HexString(thread_.stack.start_of_memory_range) << "+" <<
1201                     HexString(thread_.stack.memory.data_size);
1202     return false;
1203   }
1204 
1205   memory_ = new MinidumpMemoryRegion(minidump_);
1206   memory_->SetDescriptor(&thread_.stack);
1207 
1208   valid_ = true;
1209   return true;
1210 }
1211 
1212 
GetMemory()1213 MinidumpMemoryRegion* MinidumpThread::GetMemory() {
1214   if (!valid_) {
1215     BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory";
1216     return NULL;
1217   }
1218 
1219   return memory_;
1220 }
1221 
1222 
GetContext()1223 MinidumpContext* MinidumpThread::GetContext() {
1224   if (!valid_) {
1225     BPLOG(ERROR) << "Invalid MinidumpThread for GetContext";
1226     return NULL;
1227   }
1228 
1229   if (!context_) {
1230     if (!minidump_->SeekSet(thread_.thread_context.rva)) {
1231       BPLOG(ERROR) << "MinidumpThread cannot seek to context";
1232       return NULL;
1233     }
1234 
1235     scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
1236 
1237     if (!context->Read(thread_.thread_context.data_size)) {
1238       BPLOG(ERROR) << "MinidumpThread cannot read context";
1239       return NULL;
1240     }
1241 
1242     context_ = context.release();
1243   }
1244 
1245   return context_;
1246 }
1247 
1248 
GetThreadID(u_int32_t * thread_id) const1249 bool MinidumpThread::GetThreadID(u_int32_t *thread_id) const {
1250   BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires "
1251                                  "|thread_id|";
1252   assert(thread_id);
1253   *thread_id = 0;
1254 
1255   if (!valid_) {
1256     BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID";
1257     return false;
1258   }
1259 
1260   *thread_id = thread_.thread_id;
1261   return true;
1262 }
1263 
1264 
Print()1265 void MinidumpThread::Print() {
1266   if (!valid_) {
1267     BPLOG(ERROR) << "MinidumpThread cannot print invalid data";
1268     return;
1269   }
1270 
1271   printf("MDRawThread\n");
1272   printf("  thread_id                   = 0x%x\n",   thread_.thread_id);
1273   printf("  suspend_count               = %d\n",     thread_.suspend_count);
1274   printf("  priority_class              = 0x%x\n",   thread_.priority_class);
1275   printf("  priority                    = 0x%x\n",   thread_.priority);
1276   printf("  teb                         = 0x%" PRIx64 "\n", thread_.teb);
1277   printf("  stack.start_of_memory_range = 0x%" PRIx64 "\n",
1278          thread_.stack.start_of_memory_range);
1279   printf("  stack.memory.data_size      = 0x%x\n",
1280          thread_.stack.memory.data_size);
1281   printf("  stack.memory.rva            = 0x%x\n",   thread_.stack.memory.rva);
1282   printf("  thread_context.data_size    = 0x%x\n",
1283          thread_.thread_context.data_size);
1284   printf("  thread_context.rva          = 0x%x\n",
1285          thread_.thread_context.rva);
1286 
1287   MinidumpContext* context = GetContext();
1288   if (context) {
1289     printf("\n");
1290     context->Print();
1291   } else {
1292     printf("  (no context)\n");
1293     printf("\n");
1294   }
1295 
1296   MinidumpMemoryRegion* memory = GetMemory();
1297   if (memory) {
1298     printf("Stack\n");
1299     memory->Print();
1300   } else {
1301     printf("No stack\n");
1302   }
1303   printf("\n");
1304 }
1305 
1306 
1307 //
1308 // MinidumpThreadList
1309 //
1310 
1311 
1312 u_int32_t MinidumpThreadList::max_threads_ = 4096;
1313 
1314 
MinidumpThreadList(Minidump * minidump)1315 MinidumpThreadList::MinidumpThreadList(Minidump* minidump)
1316     : MinidumpStream(minidump),
1317       id_to_thread_map_(),
1318       threads_(NULL),
1319       thread_count_(0) {
1320 }
1321 
1322 
~MinidumpThreadList()1323 MinidumpThreadList::~MinidumpThreadList() {
1324   delete threads_;
1325 }
1326 
1327 
Read(u_int32_t expected_size)1328 bool MinidumpThreadList::Read(u_int32_t expected_size) {
1329   // Invalidate cached data.
1330   id_to_thread_map_.clear();
1331   delete threads_;
1332   threads_ = NULL;
1333   thread_count_ = 0;
1334 
1335   valid_ = false;
1336 
1337   u_int32_t thread_count;
1338   if (expected_size < sizeof(thread_count)) {
1339     BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " <<
1340                     expected_size << " < " << sizeof(thread_count);
1341     return false;
1342   }
1343   if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) {
1344     BPLOG(ERROR) << "MinidumpThreadList cannot read thread count";
1345     return false;
1346   }
1347 
1348   if (minidump_->swap())
1349     Swap(&thread_count);
1350 
1351   if (thread_count > numeric_limits<u_int32_t>::max() / sizeof(MDRawThread)) {
1352     BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count <<
1353                     " would cause multiplication overflow";
1354     return false;
1355   }
1356 
1357   if (expected_size != sizeof(thread_count) +
1358                        thread_count * sizeof(MDRawThread)) {
1359     // may be padded with 4 bytes on 64bit ABIs for alignment
1360     if (expected_size == sizeof(thread_count) + 4 +
1361                          thread_count * sizeof(MDRawThread)) {
1362       u_int32_t useless;
1363       if (!minidump_->ReadBytes(&useless, 4)) {
1364         BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded bytes";
1365         return false;
1366       }
1367     } else {
1368       BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size <<
1369                     " != " << sizeof(thread_count) +
1370                     thread_count * sizeof(MDRawThread);
1371       return false;
1372     }
1373   }
1374 
1375 
1376   if (thread_count > max_threads_) {
1377     BPLOG(ERROR) << "MinidumpThreadList count " << thread_count <<
1378                     " exceeds maximum " << max_threads_;
1379     return false;
1380   }
1381 
1382   if (thread_count != 0) {
1383     scoped_ptr<MinidumpThreads> threads(
1384         new MinidumpThreads(thread_count, MinidumpThread(minidump_)));
1385 
1386     for (unsigned int thread_index = 0;
1387          thread_index < thread_count;
1388          ++thread_index) {
1389       MinidumpThread* thread = &(*threads)[thread_index];
1390 
1391       // Assume that the file offset is correct after the last read.
1392       if (!thread->Read()) {
1393         BPLOG(ERROR) << "MinidumpThreadList cannot read thread " <<
1394                         thread_index << "/" << thread_count;
1395         return false;
1396       }
1397 
1398       u_int32_t thread_id;
1399       if (!thread->GetThreadID(&thread_id)) {
1400         BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " <<
1401                         thread_index << "/" << thread_count;
1402         return false;
1403       }
1404 
1405       if (GetThreadByID(thread_id)) {
1406         // Another thread with this ID is already in the list.  Data error.
1407         BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " <<
1408                         HexString(thread_id) << " at thread " <<
1409                         thread_index << "/" << thread_count;
1410         return false;
1411       }
1412       id_to_thread_map_[thread_id] = thread;
1413     }
1414 
1415     threads_ = threads.release();
1416   }
1417 
1418   thread_count_ = thread_count;
1419 
1420   valid_ = true;
1421   return true;
1422 }
1423 
1424 
GetThreadAtIndex(unsigned int index) const1425 MinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index)
1426     const {
1427   if (!valid_) {
1428     BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex";
1429     return NULL;
1430   }
1431 
1432   if (index >= thread_count_) {
1433     BPLOG(ERROR) << "MinidumpThreadList index out of range: " <<
1434                     index << "/" << thread_count_;
1435     return NULL;
1436   }
1437 
1438   return &(*threads_)[index];
1439 }
1440 
1441 
GetThreadByID(u_int32_t thread_id)1442 MinidumpThread* MinidumpThreadList::GetThreadByID(u_int32_t thread_id) {
1443   // Don't check valid_.  Read calls this method before everything is
1444   // validated.  It is safe to not check valid_ here.
1445   return id_to_thread_map_[thread_id];
1446 }
1447 
1448 
Print()1449 void MinidumpThreadList::Print() {
1450   if (!valid_) {
1451     BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data";
1452     return;
1453   }
1454 
1455   printf("MinidumpThreadList\n");
1456   printf("  thread_count = %d\n", thread_count_);
1457   printf("\n");
1458 
1459   for (unsigned int thread_index = 0;
1460        thread_index < thread_count_;
1461        ++thread_index) {
1462     printf("thread[%d]\n", thread_index);
1463 
1464     (*threads_)[thread_index].Print();
1465   }
1466 }
1467 
1468 
1469 //
1470 // MinidumpModule
1471 //
1472 
1473 
1474 u_int32_t MinidumpModule::max_cv_bytes_ = 32768;
1475 u_int32_t MinidumpModule::max_misc_bytes_ = 32768;
1476 
1477 
MinidumpModule(Minidump * minidump)1478 MinidumpModule::MinidumpModule(Minidump* minidump)
1479     : MinidumpObject(minidump),
1480       module_valid_(false),
1481       has_debug_info_(false),
1482       module_(),
1483       name_(NULL),
1484       cv_record_(NULL),
1485       cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE),
1486       misc_record_(NULL) {
1487 }
1488 
1489 
~MinidumpModule()1490 MinidumpModule::~MinidumpModule() {
1491   delete name_;
1492   delete cv_record_;
1493   delete misc_record_;
1494 }
1495 
1496 
Read()1497 bool MinidumpModule::Read() {
1498   // Invalidate cached data.
1499   delete name_;
1500   name_ = NULL;
1501   delete cv_record_;
1502   cv_record_ = NULL;
1503   cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE;
1504   delete misc_record_;
1505   misc_record_ = NULL;
1506 
1507   module_valid_ = false;
1508   has_debug_info_ = false;
1509   valid_ = false;
1510 
1511   if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) {
1512     BPLOG(ERROR) << "MinidumpModule cannot read module";
1513     return false;
1514   }
1515 
1516   if (minidump_->swap()) {
1517     Swap(&module_.base_of_image);
1518     Swap(&module_.size_of_image);
1519     Swap(&module_.checksum);
1520     Swap(&module_.time_date_stamp);
1521     Swap(&module_.module_name_rva);
1522     Swap(&module_.version_info.signature);
1523     Swap(&module_.version_info.struct_version);
1524     Swap(&module_.version_info.file_version_hi);
1525     Swap(&module_.version_info.file_version_lo);
1526     Swap(&module_.version_info.product_version_hi);
1527     Swap(&module_.version_info.product_version_lo);
1528     Swap(&module_.version_info.file_flags_mask);
1529     Swap(&module_.version_info.file_flags);
1530     Swap(&module_.version_info.file_os);
1531     Swap(&module_.version_info.file_type);
1532     Swap(&module_.version_info.file_subtype);
1533     Swap(&module_.version_info.file_date_hi);
1534     Swap(&module_.version_info.file_date_lo);
1535     Swap(&module_.cv_record);
1536     Swap(&module_.misc_record);
1537     // Don't swap reserved fields because their contents are unknown (as
1538     // are their proper widths).
1539   }
1540 
1541   // Check for base + size overflow or undersize.
1542   if (module_.size_of_image == 0 ||
1543       module_.size_of_image >
1544           numeric_limits<u_int64_t>::max() - module_.base_of_image) {
1545     BPLOG(ERROR) << "MinidumpModule has a module problem, " <<
1546                     HexString(module_.base_of_image) << "+" <<
1547                     HexString(module_.size_of_image);
1548     return false;
1549   }
1550 
1551   module_valid_ = true;
1552   return true;
1553 }
1554 
1555 
ReadAuxiliaryData()1556 bool MinidumpModule::ReadAuxiliaryData() {
1557   if (!module_valid_) {
1558     BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData";
1559     return false;
1560   }
1561 
1562   // Each module must have a name.
1563   name_ = minidump_->ReadString(module_.module_name_rva);
1564   if (!name_) {
1565     BPLOG(ERROR) << "MinidumpModule could not read name";
1566     return false;
1567   }
1568 
1569   // At this point, we have enough info for the module to be valid.
1570   valid_ = true;
1571 
1572   // CodeView and miscellaneous debug records are only required if the
1573   // module indicates that they exist.
1574   if (module_.cv_record.data_size && !GetCVRecord(NULL)) {
1575     BPLOG(ERROR) << "MinidumpModule has no CodeView record, "
1576                     "but one was expected";
1577     return false;
1578   }
1579 
1580   if (module_.misc_record.data_size && !GetMiscRecord(NULL)) {
1581     BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, "
1582                     "but one was expected";
1583     return false;
1584   }
1585 
1586   has_debug_info_ = true;
1587   return true;
1588 }
1589 
1590 
code_file() const1591 string MinidumpModule::code_file() const {
1592   if (!valid_) {
1593     BPLOG(ERROR) << "Invalid MinidumpModule for code_file";
1594     return "";
1595   }
1596 
1597   return *name_;
1598 }
1599 
1600 
code_identifier() const1601 string MinidumpModule::code_identifier() const {
1602   if (!valid_) {
1603     BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier";
1604     return "";
1605   }
1606 
1607   if (!has_debug_info_)
1608     return "";
1609 
1610   MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo();
1611   if (!minidump_system_info) {
1612     BPLOG(ERROR) << "MinidumpModule code_identifier requires "
1613                     "MinidumpSystemInfo";
1614     return "";
1615   }
1616 
1617   const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info();
1618   if (!raw_system_info) {
1619     BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo";
1620     return "";
1621   }
1622 
1623   string identifier;
1624 
1625   switch (raw_system_info->platform_id) {
1626     case MD_OS_WIN32_NT:
1627     case MD_OS_WIN32_WINDOWS: {
1628       // Use the same format that the MS symbol server uses in filesystem
1629       // hierarchies.
1630       char identifier_string[17];
1631       snprintf(identifier_string, sizeof(identifier_string), "%08X%x",
1632                module_.time_date_stamp, module_.size_of_image);
1633       identifier = identifier_string;
1634       break;
1635     }
1636 
1637     case MD_OS_MAC_OS_X:
1638     case MD_OS_SOLARIS:
1639     case MD_OS_LINUX: {
1640       // TODO(mmentovai): support uuid extension if present, otherwise fall
1641       // back to version (from LC_ID_DYLIB?), otherwise fall back to something
1642       // else.
1643       identifier = "id";
1644       break;
1645     }
1646 
1647     default: {
1648       // Without knowing what OS generated the dump, we can't generate a good
1649       // identifier.  Return an empty string, signalling failure.
1650       BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, "
1651                       "found " << HexString(raw_system_info->platform_id);
1652       break;
1653     }
1654   }
1655 
1656   return identifier;
1657 }
1658 
1659 
debug_file() const1660 string MinidumpModule::debug_file() const {
1661   if (!valid_) {
1662     BPLOG(ERROR) << "Invalid MinidumpModule for debug_file";
1663     return "";
1664   }
1665 
1666   if (!has_debug_info_)
1667     return "";
1668 
1669   string file;
1670   // Prefer the CodeView record if present.
1671   if (cv_record_) {
1672     if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
1673       // It's actually an MDCVInfoPDB70 structure.
1674       const MDCVInfoPDB70* cv_record_70 =
1675           reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
1676       assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
1677 
1678       // GetCVRecord guarantees pdb_file_name is null-terminated.
1679       file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name);
1680     } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
1681       // It's actually an MDCVInfoPDB20 structure.
1682       const MDCVInfoPDB20* cv_record_20 =
1683           reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
1684       assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
1685 
1686       // GetCVRecord guarantees pdb_file_name is null-terminated.
1687       file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
1688     }
1689 
1690     // If there's a CodeView record but it doesn't match a known signature,
1691     // try the miscellaneous record.
1692   }
1693 
1694   if (file.empty()) {
1695     // No usable CodeView record.  Try the miscellaneous debug record.
1696     if (misc_record_) {
1697       const MDImageDebugMisc* misc_record =
1698           reinterpret_cast<const MDImageDebugMisc *>(&(*misc_record_)[0]);
1699       if (!misc_record->unicode) {
1700         // If it's not Unicode, just stuff it into the string.  It's unclear
1701         // if misc_record->data is 0-terminated, so use an explicit size.
1702         file = string(
1703             reinterpret_cast<const char*>(misc_record->data),
1704             module_.misc_record.data_size - MDImageDebugMisc_minsize);
1705       } else {
1706         // There's a misc_record but it encodes the debug filename in UTF-16.
1707         // (Actually, because miscellaneous records are so old, it's probably
1708         // UCS-2.)  Convert it to UTF-8 for congruity with the other strings
1709         // that this method (and all other methods in the Minidump family)
1710         // return.
1711 
1712         unsigned int bytes =
1713             module_.misc_record.data_size - MDImageDebugMisc_minsize;
1714         if (bytes % 2 == 0) {
1715           unsigned int utf16_words = bytes / 2;
1716 
1717           // UTF16ToUTF8 expects a vector<u_int16_t>, so create a temporary one
1718           // and copy the UTF-16 data into it.
1719           vector<u_int16_t> string_utf16(utf16_words);
1720           if (utf16_words)
1721             memcpy(&string_utf16[0], &misc_record->data, bytes);
1722 
1723           // GetMiscRecord already byte-swapped the data[] field if it contains
1724           // UTF-16, so pass false as the swap argument.
1725           scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false));
1726           file = *new_file;
1727         }
1728       }
1729     }
1730   }
1731 
1732   BPLOG_IF(ERROR, file.empty()) << "MinidumpModule could not determine "
1733                                    "debug_file for " << *name_;
1734 
1735   return file;
1736 }
1737 
1738 
debug_identifier() const1739 string MinidumpModule::debug_identifier() const {
1740   if (!valid_) {
1741     BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier";
1742     return "";
1743   }
1744 
1745   if (!has_debug_info_)
1746     return "";
1747 
1748   string identifier;
1749 
1750   // Use the CodeView record if present.
1751   if (cv_record_) {
1752     if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
1753       // It's actually an MDCVInfoPDB70 structure.
1754       const MDCVInfoPDB70* cv_record_70 =
1755           reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
1756       assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
1757 
1758       // Use the same format that the MS symbol server uses in filesystem
1759       // hierarchies.
1760       char identifier_string[41];
1761       snprintf(identifier_string, sizeof(identifier_string),
1762                "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
1763                cv_record_70->signature.data1,
1764                cv_record_70->signature.data2,
1765                cv_record_70->signature.data3,
1766                cv_record_70->signature.data4[0],
1767                cv_record_70->signature.data4[1],
1768                cv_record_70->signature.data4[2],
1769                cv_record_70->signature.data4[3],
1770                cv_record_70->signature.data4[4],
1771                cv_record_70->signature.data4[5],
1772                cv_record_70->signature.data4[6],
1773                cv_record_70->signature.data4[7],
1774                cv_record_70->age);
1775       identifier = identifier_string;
1776     } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
1777       // It's actually an MDCVInfoPDB20 structure.
1778       const MDCVInfoPDB20* cv_record_20 =
1779           reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
1780       assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
1781 
1782       // Use the same format that the MS symbol server uses in filesystem
1783       // hierarchies.
1784       char identifier_string[17];
1785       snprintf(identifier_string, sizeof(identifier_string),
1786                "%08X%x", cv_record_20->signature, cv_record_20->age);
1787       identifier = identifier_string;
1788     }
1789   }
1790 
1791   // TODO(mmentovai): if there's no usable CodeView record, there might be a
1792   // miscellaneous debug record.  It only carries a filename, though, and no
1793   // identifier.  I'm not sure what the right thing to do for the identifier
1794   // is in that case, but I don't expect to find many modules without a
1795   // CodeView record (or some other Breakpad extension structure in place of
1796   // a CodeView record).  Treat it as an error (empty identifier) for now.
1797 
1798   // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier().
1799 
1800   BPLOG_IF(ERROR, identifier.empty()) << "MinidumpModule could not determine "
1801                                          "debug_identifier for " << *name_;
1802 
1803   return identifier;
1804 }
1805 
1806 
version() const1807 string MinidumpModule::version() const {
1808   if (!valid_) {
1809     BPLOG(ERROR) << "Invalid MinidumpModule for version";
1810     return "";
1811   }
1812 
1813   string version;
1814 
1815   if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE &&
1816       module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION) {
1817     char version_string[24];
1818     snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u",
1819              module_.version_info.file_version_hi >> 16,
1820              module_.version_info.file_version_hi & 0xffff,
1821              module_.version_info.file_version_lo >> 16,
1822              module_.version_info.file_version_lo & 0xffff);
1823     version = version_string;
1824   }
1825 
1826   // TODO(mmentovai): possibly support other struct types in place of
1827   // the one used with MD_VSFIXEDFILEINFO_SIGNATURE.  We can possibly use
1828   // a different structure that better represents versioning facilities on
1829   // Mac OS X and Linux, instead of forcing them to adhere to the dotted
1830   // quad of 16-bit ints that Windows uses.
1831 
1832   BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine "
1833                                      "version for " << *name_;
1834 
1835   return version;
1836 }
1837 
1838 
Copy() const1839 const CodeModule* MinidumpModule::Copy() const {
1840   return new BasicCodeModule(this);
1841 }
1842 
1843 
GetCVRecord(u_int32_t * size)1844 const u_int8_t* MinidumpModule::GetCVRecord(u_int32_t* size) {
1845   if (!module_valid_) {
1846     BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord";
1847     return NULL;
1848   }
1849 
1850   if (!cv_record_) {
1851     // This just guards against 0-sized CodeView records; more specific checks
1852     // are used when the signature is checked against various structure types.
1853     if (module_.cv_record.data_size == 0) {
1854       return NULL;
1855     }
1856 
1857     if (!minidump_->SeekSet(module_.cv_record.rva)) {
1858       BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record";
1859       return NULL;
1860     }
1861 
1862     if (module_.cv_record.data_size > max_cv_bytes_) {
1863       BPLOG(ERROR) << "MinidumpModule CodeView record size " <<
1864                       module_.cv_record.data_size << " exceeds maximum " <<
1865                       max_cv_bytes_;
1866       return NULL;
1867     }
1868 
1869     // Allocating something that will be accessed as MDCVInfoPDB70 or
1870     // MDCVInfoPDB20 but is allocated as u_int8_t[] can cause alignment
1871     // problems.  x86 and ppc are able to cope, though.  This allocation
1872     // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are
1873     // variable-sized due to their pdb_file_name fields; these structures
1874     // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating
1875     // them as such would result in incomplete structures or overruns.
1876     scoped_ptr< vector<u_int8_t> > cv_record(
1877         new vector<u_int8_t>(module_.cv_record.data_size));
1878 
1879     if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) {
1880       BPLOG(ERROR) << "MinidumpModule could not read CodeView record";
1881       return NULL;
1882     }
1883 
1884     u_int32_t signature = MD_CVINFOUNKNOWN_SIGNATURE;
1885     if (module_.cv_record.data_size > sizeof(signature)) {
1886       MDCVInfoPDB70* cv_record_signature =
1887           reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
1888       signature = cv_record_signature->cv_signature;
1889       if (minidump_->swap())
1890         Swap(&signature);
1891     }
1892 
1893     if (signature == MD_CVINFOPDB70_SIGNATURE) {
1894       // Now that the structure type is known, recheck the size.
1895       if (MDCVInfoPDB70_minsize > module_.cv_record.data_size) {
1896         BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " <<
1897                         MDCVInfoPDB70_minsize << " > " <<
1898                         module_.cv_record.data_size;
1899         return NULL;
1900       }
1901 
1902       if (minidump_->swap()) {
1903         MDCVInfoPDB70* cv_record_70 =
1904             reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
1905         Swap(&cv_record_70->cv_signature);
1906         Swap(&cv_record_70->signature);
1907         Swap(&cv_record_70->age);
1908         // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit
1909         // quantities.  (It's a path, is it UTF-8?)
1910       }
1911 
1912       // The last field of either structure is null-terminated 8-bit character
1913       // data.  Ensure that it's null-terminated.
1914       if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
1915         BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not "
1916                         "0-terminated";
1917         return NULL;
1918       }
1919     } else if (signature == MD_CVINFOPDB20_SIGNATURE) {
1920       // Now that the structure type is known, recheck the size.
1921       if (MDCVInfoPDB20_minsize > module_.cv_record.data_size) {
1922         BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " <<
1923                         MDCVInfoPDB20_minsize << " > " <<
1924                         module_.cv_record.data_size;
1925         return NULL;
1926       }
1927       if (minidump_->swap()) {
1928         MDCVInfoPDB20* cv_record_20 =
1929             reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]);
1930         Swap(&cv_record_20->cv_header.signature);
1931         Swap(&cv_record_20->cv_header.offset);
1932         Swap(&cv_record_20->signature);
1933         Swap(&cv_record_20->age);
1934         // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit
1935         // quantities.  (It's a path, is it UTF-8?)
1936       }
1937 
1938       // The last field of either structure is null-terminated 8-bit character
1939       // data.  Ensure that it's null-terminated.
1940       if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
1941         BPLOG(ERROR) << "MindumpModule CodeView2 record string is not "
1942                         "0-terminated";
1943         return NULL;
1944       }
1945     }
1946 
1947     // If the signature doesn't match something above, it's not something
1948     // that Breakpad can presently handle directly.  Because some modules in
1949     // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE,
1950     // don't bail out here - allow the data to be returned to the user,
1951     // although byte-swapping can't be done.
1952 
1953     // Store the vector type because that's how storage was allocated, but
1954     // return it casted to u_int8_t*.
1955     cv_record_ = cv_record.release();
1956     cv_record_signature_ = signature;
1957   }
1958 
1959   if (size)
1960     *size = module_.cv_record.data_size;
1961 
1962   return &(*cv_record_)[0];
1963 }
1964 
1965 
GetMiscRecord(u_int32_t * size)1966 const MDImageDebugMisc* MinidumpModule::GetMiscRecord(u_int32_t* size) {
1967   if (!module_valid_) {
1968     BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord";
1969     return NULL;
1970   }
1971 
1972   if (!misc_record_) {
1973     if (module_.misc_record.data_size == 0) {
1974       return NULL;
1975     }
1976 
1977     if (MDImageDebugMisc_minsize > module_.misc_record.data_size) {
1978       BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record "
1979                       "size mismatch, " << MDImageDebugMisc_minsize << " > " <<
1980                       module_.misc_record.data_size;
1981       return NULL;
1982     }
1983 
1984     if (!minidump_->SeekSet(module_.misc_record.rva)) {
1985       BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous "
1986                       "debugging record";
1987       return NULL;
1988     }
1989 
1990     if (module_.misc_record.data_size > max_misc_bytes_) {
1991       BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " <<
1992                       module_.misc_record.data_size << " exceeds maximum " <<
1993                       max_misc_bytes_;
1994       return NULL;
1995     }
1996 
1997     // Allocating something that will be accessed as MDImageDebugMisc but
1998     // is allocated as u_int8_t[] can cause alignment problems.  x86 and
1999     // ppc are able to cope, though.  This allocation style is needed
2000     // because the MDImageDebugMisc is variable-sized due to its data field;
2001     // this structure is not MDImageDebugMisc_minsize and treating it as such
2002     // would result in an incomplete structure or an overrun.
2003     scoped_ptr< vector<u_int8_t> > misc_record_mem(
2004         new vector<u_int8_t>(module_.misc_record.data_size));
2005     MDImageDebugMisc* misc_record =
2006         reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]);
2007 
2008     if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) {
2009       BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging "
2010                       "record";
2011       return NULL;
2012     }
2013 
2014     if (minidump_->swap()) {
2015       Swap(&misc_record->data_type);
2016       Swap(&misc_record->length);
2017       // Don't swap misc_record.unicode because it's an 8-bit quantity.
2018       // Don't swap the reserved fields for the same reason, and because
2019       // they don't contain any valid data.
2020       if (misc_record->unicode) {
2021         // There is a potential alignment problem, but shouldn't be a problem
2022         // in practice due to the layout of MDImageDebugMisc.
2023         u_int16_t* data16 = reinterpret_cast<u_int16_t*>(&(misc_record->data));
2024         unsigned int dataBytes = module_.misc_record.data_size -
2025                                  MDImageDebugMisc_minsize;
2026         unsigned int dataLength = dataBytes / 2;
2027         for (unsigned int characterIndex = 0;
2028              characterIndex < dataLength;
2029              ++characterIndex) {
2030           Swap(&data16[characterIndex]);
2031         }
2032       }
2033     }
2034 
2035     if (module_.misc_record.data_size != misc_record->length) {
2036       BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data "
2037                       "size mismatch, " << module_.misc_record.data_size <<
2038                       " != " << misc_record->length;
2039       return NULL;
2040     }
2041 
2042     // Store the vector type because that's how storage was allocated, but
2043     // return it casted to MDImageDebugMisc*.
2044     misc_record_ = misc_record_mem.release();
2045   }
2046 
2047   if (size)
2048     *size = module_.misc_record.data_size;
2049 
2050   return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]);
2051 }
2052 
2053 
Print()2054 void MinidumpModule::Print() {
2055   if (!valid_) {
2056     BPLOG(ERROR) << "MinidumpModule cannot print invalid data";
2057     return;
2058   }
2059 
2060   printf("MDRawModule\n");
2061   printf("  base_of_image                   = 0x%" PRIx64 "\n",
2062          module_.base_of_image);
2063   printf("  size_of_image                   = 0x%x\n",
2064          module_.size_of_image);
2065   printf("  checksum                        = 0x%x\n",
2066          module_.checksum);
2067   printf("  time_date_stamp                 = 0x%x\n",
2068          module_.time_date_stamp);
2069   printf("  module_name_rva                 = 0x%x\n",
2070          module_.module_name_rva);
2071   printf("  version_info.signature          = 0x%x\n",
2072          module_.version_info.signature);
2073   printf("  version_info.struct_version     = 0x%x\n",
2074          module_.version_info.struct_version);
2075   printf("  version_info.file_version       = 0x%x:0x%x\n",
2076          module_.version_info.file_version_hi,
2077          module_.version_info.file_version_lo);
2078   printf("  version_info.product_version    = 0x%x:0x%x\n",
2079          module_.version_info.product_version_hi,
2080          module_.version_info.product_version_lo);
2081   printf("  version_info.file_flags_mask    = 0x%x\n",
2082          module_.version_info.file_flags_mask);
2083   printf("  version_info.file_flags         = 0x%x\n",
2084          module_.version_info.file_flags);
2085   printf("  version_info.file_os            = 0x%x\n",
2086          module_.version_info.file_os);
2087   printf("  version_info.file_type          = 0x%x\n",
2088          module_.version_info.file_type);
2089   printf("  version_info.file_subtype       = 0x%x\n",
2090          module_.version_info.file_subtype);
2091   printf("  version_info.file_date          = 0x%x:0x%x\n",
2092          module_.version_info.file_date_hi,
2093          module_.version_info.file_date_lo);
2094   printf("  cv_record.data_size             = %d\n",
2095          module_.cv_record.data_size);
2096   printf("  cv_record.rva                   = 0x%x\n",
2097          module_.cv_record.rva);
2098   printf("  misc_record.data_size           = %d\n",
2099          module_.misc_record.data_size);
2100   printf("  misc_record.rva                 = 0x%x\n",
2101          module_.misc_record.rva);
2102 
2103   printf("  (code_file)                     = \"%s\"\n", code_file().c_str());
2104   printf("  (code_identifier)               = \"%s\"\n",
2105          code_identifier().c_str());
2106 
2107   u_int32_t cv_record_size;
2108   const u_int8_t *cv_record = GetCVRecord(&cv_record_size);
2109   if (cv_record) {
2110     if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
2111       const MDCVInfoPDB70* cv_record_70 =
2112           reinterpret_cast<const MDCVInfoPDB70*>(cv_record);
2113       assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
2114 
2115       printf("  (cv_record).cv_signature        = 0x%x\n",
2116              cv_record_70->cv_signature);
2117       printf("  (cv_record).signature           = %08x-%04x-%04x-%02x%02x-",
2118              cv_record_70->signature.data1,
2119              cv_record_70->signature.data2,
2120              cv_record_70->signature.data3,
2121              cv_record_70->signature.data4[0],
2122              cv_record_70->signature.data4[1]);
2123       for (unsigned int guidIndex = 2;
2124            guidIndex < 8;
2125            ++guidIndex) {
2126         printf("%02x", cv_record_70->signature.data4[guidIndex]);
2127       }
2128       printf("\n");
2129       printf("  (cv_record).age                 = %d\n",
2130              cv_record_70->age);
2131       printf("  (cv_record).pdb_file_name       = \"%s\"\n",
2132              cv_record_70->pdb_file_name);
2133     } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
2134       const MDCVInfoPDB20* cv_record_20 =
2135           reinterpret_cast<const MDCVInfoPDB20*>(cv_record);
2136       assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
2137 
2138       printf("  (cv_record).cv_header.signature = 0x%x\n",
2139              cv_record_20->cv_header.signature);
2140       printf("  (cv_record).cv_header.offset    = 0x%x\n",
2141              cv_record_20->cv_header.offset);
2142       printf("  (cv_record).signature           = 0x%x\n",
2143              cv_record_20->signature);
2144       printf("  (cv_record).age                 = %d\n",
2145              cv_record_20->age);
2146       printf("  (cv_record).pdb_file_name       = \"%s\"\n",
2147              cv_record_20->pdb_file_name);
2148     } else {
2149       printf("  (cv_record)                     = ");
2150       for (unsigned int cv_byte_index = 0;
2151            cv_byte_index < cv_record_size;
2152            ++cv_byte_index) {
2153         printf("%02x", cv_record[cv_byte_index]);
2154       }
2155       printf("\n");
2156     }
2157   } else {
2158     printf("  (cv_record)                     = (null)\n");
2159   }
2160 
2161   const MDImageDebugMisc* misc_record = GetMiscRecord(NULL);
2162   if (misc_record) {
2163     printf("  (misc_record).data_type         = 0x%x\n",
2164            misc_record->data_type);
2165     printf("  (misc_record).length            = 0x%x\n",
2166            misc_record->length);
2167     printf("  (misc_record).unicode           = %d\n",
2168            misc_record->unicode);
2169     // Don't bother printing the UTF-16, we don't really even expect to ever
2170     // see this misc_record anyway.
2171     if (misc_record->unicode)
2172       printf("  (misc_record).data              = \"%s\"\n",
2173              misc_record->data);
2174     else
2175       printf("  (misc_record).data              = (UTF-16)\n");
2176   } else {
2177     printf("  (misc_record)                   = (null)\n");
2178   }
2179 
2180   printf("  (debug_file)                    = \"%s\"\n", debug_file().c_str());
2181   printf("  (debug_identifier)              = \"%s\"\n",
2182          debug_identifier().c_str());
2183   printf("  (version)                       = \"%s\"\n", version().c_str());
2184   printf("\n");
2185 }
2186 
2187 
2188 //
2189 // MinidumpModuleList
2190 //
2191 
2192 
2193 u_int32_t MinidumpModuleList::max_modules_ = 1024;
2194 
2195 
MinidumpModuleList(Minidump * minidump)2196 MinidumpModuleList::MinidumpModuleList(Minidump* minidump)
2197     : MinidumpStream(minidump),
2198       range_map_(new RangeMap<u_int64_t, unsigned int>()),
2199       modules_(NULL),
2200       module_count_(0) {
2201 }
2202 
2203 
~MinidumpModuleList()2204 MinidumpModuleList::~MinidumpModuleList() {
2205   delete range_map_;
2206   delete modules_;
2207 }
2208 
2209 
Read(u_int32_t expected_size)2210 bool MinidumpModuleList::Read(u_int32_t expected_size) {
2211   // Invalidate cached data.
2212   range_map_->Clear();
2213   delete modules_;
2214   modules_ = NULL;
2215   module_count_ = 0;
2216 
2217   valid_ = false;
2218 
2219   u_int32_t module_count;
2220   if (expected_size < sizeof(module_count)) {
2221     BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " <<
2222                     expected_size << " < " << sizeof(module_count);
2223     return false;
2224   }
2225   if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) {
2226     BPLOG(ERROR) << "MinidumpModuleList could not read module count";
2227     return false;
2228   }
2229 
2230   if (minidump_->swap())
2231     Swap(&module_count);
2232 
2233   if (module_count > numeric_limits<u_int32_t>::max() / MD_MODULE_SIZE) {
2234     BPLOG(ERROR) << "MinidumpModuleList module count " << module_count <<
2235                     " would cause multiplication overflow";
2236     return false;
2237   }
2238 
2239   if (expected_size != sizeof(module_count) +
2240                        module_count * MD_MODULE_SIZE) {
2241     // may be padded with 4 bytes on 64bit ABIs for alignment
2242     if (expected_size == sizeof(module_count) + 4 +
2243                          module_count * MD_MODULE_SIZE) {
2244       u_int32_t useless;
2245       if (!minidump_->ReadBytes(&useless, 4)) {
2246         BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded bytes";
2247         return false;
2248       }
2249     } else {
2250       BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size <<
2251                       " != " << sizeof(module_count) +
2252                       module_count * MD_MODULE_SIZE;
2253       return false;
2254     }
2255   }
2256 
2257   if (module_count > max_modules_) {
2258     BPLOG(ERROR) << "MinidumpModuleList count " << module_count_ <<
2259                     " exceeds maximum " << max_modules_;
2260     return false;
2261   }
2262 
2263   if (module_count != 0) {
2264     scoped_ptr<MinidumpModules> modules(
2265         new MinidumpModules(module_count, MinidumpModule(minidump_)));
2266 
2267     for (unsigned int module_index = 0;
2268          module_index < module_count;
2269          ++module_index) {
2270       MinidumpModule* module = &(*modules)[module_index];
2271 
2272       // Assume that the file offset is correct after the last read.
2273       if (!module->Read()) {
2274         BPLOG(ERROR) << "MinidumpModuleList could not read module " <<
2275                         module_index << "/" << module_count;
2276         return false;
2277       }
2278     }
2279 
2280     // Loop through the module list once more to read additional data and
2281     // build the range map.  This is done in a second pass because
2282     // MinidumpModule::ReadAuxiliaryData seeks around, and if it were
2283     // included in the loop above, additional seeks would be needed where
2284     // none are now to read contiguous data.
2285     for (unsigned int module_index = 0;
2286          module_index < module_count;
2287          ++module_index) {
2288       MinidumpModule* module = &(*modules)[module_index];
2289 
2290       // ReadAuxiliaryData fails if any data that the module indicates should
2291       // exist is missing, but we treat some such cases as valid anyway.  See
2292       // issue #222: if a debugging record is of a format that's too large to
2293       // handle, it shouldn't render the entire dump invalid.  Check module
2294       // validity before giving up.
2295       if (!module->ReadAuxiliaryData() && !module->valid()) {
2296         BPLOG(ERROR) << "MinidumpModuleList could not read required module "
2297                         "auxiliary data for module " <<
2298                         module_index << "/" << module_count;
2299         return false;
2300       }
2301 
2302       // It is safe to use module->code_file() after successfully calling
2303       // module->ReadAuxiliaryData or noting that the module is valid.
2304 
2305       u_int64_t base_address = module->base_address();
2306       u_int64_t module_size = module->size();
2307       if (base_address == static_cast<u_int64_t>(-1)) {
2308         BPLOG(ERROR) << "MinidumpModuleList found bad base address "
2309                         "for module " << module_index << "/" << module_count <<
2310                         ", " << module->code_file();
2311         return false;
2312       }
2313 
2314       if (!range_map_->StoreRange(base_address, module_size, module_index)) {
2315         BPLOG(ERROR) << "MinidumpModuleList could not store module " <<
2316                         module_index << "/" << module_count << ", " <<
2317                         module->code_file() << ", " <<
2318                         HexString(base_address) << "+" <<
2319                         HexString(module_size);
2320         return false;
2321       }
2322     }
2323 
2324     modules_ = modules.release();
2325   }
2326 
2327   module_count_ = module_count;
2328 
2329   valid_ = true;
2330   return true;
2331 }
2332 
2333 
GetModuleForAddress(u_int64_t address) const2334 const MinidumpModule* MinidumpModuleList::GetModuleForAddress(
2335     u_int64_t address) const {
2336   if (!valid_) {
2337     BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress";
2338     return NULL;
2339   }
2340 
2341   unsigned int module_index;
2342   if (!range_map_->RetrieveRange(address, &module_index, NULL, NULL)) {
2343     BPLOG(INFO) << "MinidumpModuleList has no module at " <<
2344                    HexString(address);
2345     return NULL;
2346   }
2347 
2348   return GetModuleAtIndex(module_index);
2349 }
2350 
2351 
GetMainModule() const2352 const MinidumpModule* MinidumpModuleList::GetMainModule() const {
2353   if (!valid_) {
2354     BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule";
2355     return NULL;
2356   }
2357 
2358   // The main code module is the first one present in a minidump file's
2359   // MDRawModuleList.
2360   return GetModuleAtSequence(0);
2361 }
2362 
2363 
GetModuleAtSequence(unsigned int sequence) const2364 const MinidumpModule* MinidumpModuleList::GetModuleAtSequence(
2365     unsigned int sequence) const {
2366   if (!valid_) {
2367     BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence";
2368     return NULL;
2369   }
2370 
2371   if (sequence >= module_count_) {
2372     BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " <<
2373                     sequence << "/" << module_count_;
2374     return NULL;
2375   }
2376 
2377   unsigned int module_index;
2378   if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, NULL, NULL)) {
2379     BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence;
2380     return NULL;
2381   }
2382 
2383   return GetModuleAtIndex(module_index);
2384 }
2385 
2386 
GetModuleAtIndex(unsigned int index) const2387 const MinidumpModule* MinidumpModuleList::GetModuleAtIndex(
2388     unsigned int index) const {
2389   if (!valid_) {
2390     BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex";
2391     return NULL;
2392   }
2393 
2394   if (index >= module_count_) {
2395     BPLOG(ERROR) << "MinidumpModuleList index out of range: " <<
2396                     index << "/" << module_count_;
2397     return NULL;
2398   }
2399 
2400   return &(*modules_)[index];
2401 }
2402 
2403 
Copy() const2404 const CodeModules* MinidumpModuleList::Copy() const {
2405   return new BasicCodeModules(this);
2406 }
2407 
2408 
Print()2409 void MinidumpModuleList::Print() {
2410   if (!valid_) {
2411     BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data";
2412     return;
2413   }
2414 
2415   printf("MinidumpModuleList\n");
2416   printf("  module_count = %d\n", module_count_);
2417   printf("\n");
2418 
2419   for (unsigned int module_index = 0;
2420        module_index < module_count_;
2421        ++module_index) {
2422     printf("module[%d]\n", module_index);
2423 
2424     (*modules_)[module_index].Print();
2425   }
2426 }
2427 
2428 
2429 //
2430 // MinidumpMemoryList
2431 //
2432 
2433 
2434 u_int32_t MinidumpMemoryList::max_regions_ = 4096;
2435 
2436 
MinidumpMemoryList(Minidump * minidump)2437 MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump)
2438     : MinidumpStream(minidump),
2439       range_map_(new RangeMap<u_int64_t, unsigned int>()),
2440       descriptors_(NULL),
2441       regions_(NULL),
2442       region_count_(0) {
2443 }
2444 
2445 
~MinidumpMemoryList()2446 MinidumpMemoryList::~MinidumpMemoryList() {
2447   delete range_map_;
2448   delete descriptors_;
2449   delete regions_;
2450 }
2451 
2452 
Read(u_int32_t expected_size)2453 bool MinidumpMemoryList::Read(u_int32_t expected_size) {
2454   // Invalidate cached data.
2455   delete descriptors_;
2456   descriptors_ = NULL;
2457   delete regions_;
2458   regions_ = NULL;
2459   range_map_->Clear();
2460   region_count_ = 0;
2461 
2462   valid_ = false;
2463 
2464   u_int32_t region_count;
2465   if (expected_size < sizeof(region_count)) {
2466     BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " <<
2467                     expected_size << " < " << sizeof(region_count);
2468     return false;
2469   }
2470   if (!minidump_->ReadBytes(&region_count, sizeof(region_count))) {
2471     BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count";
2472     return false;
2473   }
2474 
2475   if (minidump_->swap())
2476     Swap(&region_count);
2477 
2478   if (region_count >
2479           numeric_limits<u_int32_t>::max() / sizeof(MDMemoryDescriptor)) {
2480     BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count <<
2481                     " would cause multiplication overflow";
2482     return false;
2483   }
2484 
2485   if (expected_size != sizeof(region_count) +
2486                        region_count * sizeof(MDMemoryDescriptor)) {
2487     // may be padded with 4 bytes on 64bit ABIs for alignment
2488     if (expected_size == sizeof(region_count) + 4 +
2489                          region_count * sizeof(MDMemoryDescriptor)) {
2490       u_int32_t useless;
2491       if (!minidump_->ReadBytes(&useless, 4)) {
2492         BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded bytes";
2493         return false;
2494       }
2495     } else {
2496       BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size <<
2497                       " != " << sizeof(region_count) +
2498                       region_count * sizeof(MDMemoryDescriptor);
2499       return false;
2500     }
2501   }
2502 
2503   if (region_count > max_regions_) {
2504     BPLOG(ERROR) << "MinidumpMemoryList count " << region_count <<
2505                     " exceeds maximum " << max_regions_;
2506     return false;
2507   }
2508 
2509   if (region_count != 0) {
2510     scoped_ptr<MemoryDescriptors> descriptors(
2511         new MemoryDescriptors(region_count));
2512 
2513     // Read the entire array in one fell swoop, instead of reading one entry
2514     // at a time in the loop.
2515     if (!minidump_->ReadBytes(&(*descriptors)[0],
2516                               sizeof(MDMemoryDescriptor) * region_count)) {
2517       BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list";
2518       return false;
2519     }
2520 
2521     scoped_ptr<MemoryRegions> regions(
2522         new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_)));
2523 
2524     for (unsigned int region_index = 0;
2525          region_index < region_count;
2526          ++region_index) {
2527       MDMemoryDescriptor* descriptor = &(*descriptors)[region_index];
2528 
2529       if (minidump_->swap())
2530         Swap(descriptor);
2531 
2532       u_int64_t base_address = descriptor->start_of_memory_range;
2533       u_int32_t region_size = descriptor->memory.data_size;
2534 
2535       // Check for base + size overflow or undersize.
2536       if (region_size == 0 ||
2537           region_size > numeric_limits<u_int64_t>::max() - base_address) {
2538         BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " <<
2539                         " region " << region_index << "/" << region_count <<
2540                         ", " << HexString(base_address) << "+" <<
2541                         HexString(region_size);
2542         return false;
2543       }
2544 
2545       if (!range_map_->StoreRange(base_address, region_size, region_index)) {
2546         BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " <<
2547                         region_index << "/" << region_count << ", " <<
2548                         HexString(base_address) << "+" <<
2549                         HexString(region_size);
2550         return false;
2551       }
2552 
2553       (*regions)[region_index].SetDescriptor(descriptor);
2554     }
2555 
2556     descriptors_ = descriptors.release();
2557     regions_ = regions.release();
2558   }
2559 
2560   region_count_ = region_count;
2561 
2562   valid_ = true;
2563   return true;
2564 }
2565 
2566 
GetMemoryRegionAtIndex(unsigned int index)2567 MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex(
2568       unsigned int index) {
2569   if (!valid_) {
2570     BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex";
2571     return NULL;
2572   }
2573 
2574   if (index >= region_count_) {
2575     BPLOG(ERROR) << "MinidumpMemoryList index out of range: " <<
2576                     index << "/" << region_count_;
2577     return NULL;
2578   }
2579 
2580   return &(*regions_)[index];
2581 }
2582 
2583 
GetMemoryRegionForAddress(u_int64_t address)2584 MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress(
2585     u_int64_t address) {
2586   if (!valid_) {
2587     BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress";
2588     return NULL;
2589   }
2590 
2591   unsigned int region_index;
2592   if (!range_map_->RetrieveRange(address, &region_index, NULL, NULL)) {
2593     BPLOG(INFO) << "MinidumpMemoryList has no memory region at " <<
2594                    HexString(address);
2595     return NULL;
2596   }
2597 
2598   return GetMemoryRegionAtIndex(region_index);
2599 }
2600 
2601 
Print()2602 void MinidumpMemoryList::Print() {
2603   if (!valid_) {
2604     BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data";
2605     return;
2606   }
2607 
2608   printf("MinidumpMemoryList\n");
2609   printf("  region_count = %d\n", region_count_);
2610   printf("\n");
2611 
2612   for (unsigned int region_index = 0;
2613        region_index < region_count_;
2614        ++region_index) {
2615     MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index];
2616     printf("region[%d]\n", region_index);
2617     printf("MDMemoryDescriptor\n");
2618     printf("  start_of_memory_range = 0x%" PRIx64 "\n",
2619            descriptor->start_of_memory_range);
2620     printf("  memory.data_size      = 0x%x\n", descriptor->memory.data_size);
2621     printf("  memory.rva            = 0x%x\n", descriptor->memory.rva);
2622     MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index);
2623     if (region) {
2624       printf("Memory\n");
2625       region->Print();
2626     } else {
2627       printf("No memory\n");
2628     }
2629     printf("\n");
2630   }
2631 }
2632 
2633 
2634 //
2635 // MinidumpException
2636 //
2637 
2638 
MinidumpException(Minidump * minidump)2639 MinidumpException::MinidumpException(Minidump* minidump)
2640     : MinidumpStream(minidump),
2641       exception_(),
2642       context_(NULL) {
2643 }
2644 
2645 
~MinidumpException()2646 MinidumpException::~MinidumpException() {
2647   delete context_;
2648 }
2649 
2650 
Read(u_int32_t expected_size)2651 bool MinidumpException::Read(u_int32_t expected_size) {
2652   // Invalidate cached data.
2653   delete context_;
2654   context_ = NULL;
2655 
2656   valid_ = false;
2657 
2658   if (expected_size != sizeof(exception_)) {
2659     BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size <<
2660                     " != " << sizeof(exception_);
2661     return false;
2662   }
2663 
2664   if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) {
2665     BPLOG(ERROR) << "MinidumpException cannot read exception";
2666     return false;
2667   }
2668 
2669   if (minidump_->swap()) {
2670     Swap(&exception_.thread_id);
2671     // exception_.__align is for alignment only and does not need to be
2672     // swapped.
2673     Swap(&exception_.exception_record.exception_code);
2674     Swap(&exception_.exception_record.exception_flags);
2675     Swap(&exception_.exception_record.exception_record);
2676     Swap(&exception_.exception_record.exception_address);
2677     Swap(&exception_.exception_record.number_parameters);
2678     // exception_.exception_record.__align is for alignment only and does not
2679     // need to be swapped.
2680     for (unsigned int parameter_index = 0;
2681          parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS;
2682          ++parameter_index) {
2683       Swap(&exception_.exception_record.exception_information[parameter_index]);
2684     }
2685     Swap(&exception_.thread_context);
2686   }
2687 
2688   valid_ = true;
2689   return true;
2690 }
2691 
2692 
GetThreadID(u_int32_t * thread_id) const2693 bool MinidumpException::GetThreadID(u_int32_t *thread_id) const {
2694   BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires "
2695                                  "|thread_id|";
2696   assert(thread_id);
2697   *thread_id = 0;
2698 
2699   if (!valid_) {
2700     BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID";
2701     return false;
2702   }
2703 
2704   *thread_id = exception_.thread_id;
2705   return true;
2706 }
2707 
2708 
GetContext()2709 MinidumpContext* MinidumpException::GetContext() {
2710   if (!valid_) {
2711     BPLOG(ERROR) << "Invalid MinidumpException for GetContext";
2712     return NULL;
2713   }
2714 
2715   if (!context_) {
2716     if (!minidump_->SeekSet(exception_.thread_context.rva)) {
2717       BPLOG(ERROR) << "MinidumpException cannot seek to context";
2718       return NULL;
2719     }
2720 
2721     scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
2722 
2723     if (!context->Read(exception_.thread_context.data_size)) {
2724       BPLOG(ERROR) << "MinidumpException cannot read context";
2725       return NULL;
2726     }
2727 
2728     context_ = context.release();
2729   }
2730 
2731   return context_;
2732 }
2733 
2734 
Print()2735 void MinidumpException::Print() {
2736   if (!valid_) {
2737     BPLOG(ERROR) << "MinidumpException cannot print invalid data";
2738     return;
2739   }
2740 
2741   printf("MDException\n");
2742   printf("  thread_id                                  = 0x%x\n",
2743          exception_.thread_id);
2744   printf("  exception_record.exception_code            = 0x%x\n",
2745          exception_.exception_record.exception_code);
2746   printf("  exception_record.exception_flags           = 0x%x\n",
2747          exception_.exception_record.exception_flags);
2748   printf("  exception_record.exception_record          = 0x%" PRIx64 "\n",
2749          exception_.exception_record.exception_record);
2750   printf("  exception_record.exception_address         = 0x%" PRIx64 "\n",
2751          exception_.exception_record.exception_address);
2752   printf("  exception_record.number_parameters         = %d\n",
2753          exception_.exception_record.number_parameters);
2754   for (unsigned int parameterIndex = 0;
2755        parameterIndex < exception_.exception_record.number_parameters;
2756        ++parameterIndex) {
2757     printf("  exception_record.exception_information[%2d] = 0x%" PRIx64 "\n",
2758            parameterIndex,
2759            exception_.exception_record.exception_information[parameterIndex]);
2760   }
2761   printf("  thread_context.data_size                   = %d\n",
2762          exception_.thread_context.data_size);
2763   printf("  thread_context.rva                         = 0x%x\n",
2764          exception_.thread_context.rva);
2765   MinidumpContext* context = GetContext();
2766   if (context) {
2767     printf("\n");
2768     context->Print();
2769   } else {
2770     printf("  (no context)\n");
2771     printf("\n");
2772   }
2773 }
2774 
2775 
2776 //
2777 // MinidumpSystemInfo
2778 //
2779 
2780 
MinidumpSystemInfo(Minidump * minidump)2781 MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump)
2782     : MinidumpStream(minidump),
2783       system_info_(),
2784       csd_version_(NULL),
2785       cpu_vendor_(NULL) {
2786 }
2787 
2788 
~MinidumpSystemInfo()2789 MinidumpSystemInfo::~MinidumpSystemInfo() {
2790   delete csd_version_;
2791   delete cpu_vendor_;
2792 }
2793 
2794 
Read(u_int32_t expected_size)2795 bool MinidumpSystemInfo::Read(u_int32_t expected_size) {
2796   // Invalidate cached data.
2797   delete csd_version_;
2798   csd_version_ = NULL;
2799   delete cpu_vendor_;
2800   cpu_vendor_ = NULL;
2801 
2802   valid_ = false;
2803 
2804   if (expected_size != sizeof(system_info_)) {
2805     BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size <<
2806                     " != " << sizeof(system_info_);
2807     return false;
2808   }
2809 
2810   if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) {
2811     BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info";
2812     return false;
2813   }
2814 
2815   if (minidump_->swap()) {
2816     Swap(&system_info_.processor_architecture);
2817     Swap(&system_info_.processor_level);
2818     Swap(&system_info_.processor_revision);
2819     // number_of_processors and product_type are 8-bit quantities and need no
2820     // swapping.
2821     Swap(&system_info_.major_version);
2822     Swap(&system_info_.minor_version);
2823     Swap(&system_info_.build_number);
2824     Swap(&system_info_.platform_id);
2825     Swap(&system_info_.csd_version_rva);
2826     Swap(&system_info_.suite_mask);
2827     // Don't swap the reserved2 field because its contents are unknown.
2828 
2829     if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
2830         system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
2831       for (unsigned int i = 0; i < 3; ++i)
2832         Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]);
2833       Swap(&system_info_.cpu.x86_cpu_info.version_information);
2834       Swap(&system_info_.cpu.x86_cpu_info.feature_information);
2835       Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
2836     } else {
2837       for (unsigned int i = 0; i < 2; ++i)
2838         Swap(&system_info_.cpu.other_cpu_info.processor_features[i]);
2839     }
2840   }
2841 
2842   valid_ = true;
2843   return true;
2844 }
2845 
2846 
GetOS()2847 string MinidumpSystemInfo::GetOS() {
2848   if (!valid_) {
2849     BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS";
2850     return NULL;
2851   }
2852 
2853   string os;
2854 
2855   switch (system_info_.platform_id) {
2856     case MD_OS_WIN32_NT:
2857     case MD_OS_WIN32_WINDOWS:
2858       os = "windows";
2859       break;
2860 
2861     case MD_OS_MAC_OS_X:
2862       os = "mac";
2863       break;
2864 
2865     case MD_OS_LINUX:
2866       os = "linux";
2867       break;
2868 
2869     case MD_OS_SOLARIS:
2870       os = "solaris";
2871       break;
2872 
2873     default:
2874       BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " <<
2875                       HexString(system_info_.platform_id);
2876       break;
2877   }
2878 
2879   return os;
2880 }
2881 
2882 
GetCPU()2883 string MinidumpSystemInfo::GetCPU() {
2884   if (!valid_) {
2885     BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU";
2886     return "";
2887   }
2888 
2889   string cpu;
2890 
2891   switch (system_info_.processor_architecture) {
2892     case MD_CPU_ARCHITECTURE_X86:
2893     case MD_CPU_ARCHITECTURE_X86_WIN64:
2894       cpu = "x86";
2895       break;
2896 
2897     case MD_CPU_ARCHITECTURE_PPC:
2898       cpu = "ppc";
2899       break;
2900 
2901     case MD_CPU_ARCHITECTURE_SPARC:
2902       cpu = "sparc";
2903       break;
2904 
2905     default:
2906       BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " <<
2907                       HexString(system_info_.processor_architecture);
2908       break;
2909   }
2910 
2911   return cpu;
2912 }
2913 
2914 
GetCSDVersion()2915 const string* MinidumpSystemInfo::GetCSDVersion() {
2916   if (!valid_) {
2917     BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion";
2918     return NULL;
2919   }
2920 
2921   if (!csd_version_)
2922     csd_version_ = minidump_->ReadString(system_info_.csd_version_rva);
2923 
2924   BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read "
2925                                     "CSD version";
2926 
2927   return csd_version_;
2928 }
2929 
2930 
GetCPUVendor()2931 const string* MinidumpSystemInfo::GetCPUVendor() {
2932   if (!valid_) {
2933     BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor";
2934     return NULL;
2935   }
2936 
2937   // CPU vendor information can only be determined from x86 minidumps.
2938   if (!cpu_vendor_ &&
2939       (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
2940        system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) {
2941     char cpu_vendor_string[13];
2942     snprintf(cpu_vendor_string, sizeof(cpu_vendor_string),
2943              "%c%c%c%c%c%c%c%c%c%c%c%c",
2944               system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff,
2945              (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff,
2946              (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff,
2947              (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff,
2948               system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff,
2949              (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff,
2950              (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff,
2951              (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff,
2952               system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff,
2953              (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff,
2954              (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff,
2955              (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff);
2956     cpu_vendor_ = new string(cpu_vendor_string);
2957   }
2958 
2959   return cpu_vendor_;
2960 }
2961 
2962 
Print()2963 void MinidumpSystemInfo::Print() {
2964   if (!valid_) {
2965     BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data";
2966     return;
2967   }
2968 
2969   printf("MDRawSystemInfo\n");
2970   printf("  processor_architecture                     = %d\n",
2971          system_info_.processor_architecture);
2972   printf("  processor_level                            = %d\n",
2973          system_info_.processor_level);
2974   printf("  processor_revision                         = 0x%x\n",
2975          system_info_.processor_revision);
2976   printf("  number_of_processors                       = %d\n",
2977          system_info_.number_of_processors);
2978   printf("  product_type                               = %d\n",
2979          system_info_.product_type);
2980   printf("  major_version                              = %d\n",
2981          system_info_.major_version);
2982   printf("  minor_version                              = %d\n",
2983          system_info_.minor_version);
2984   printf("  build_number                               = %d\n",
2985          system_info_.build_number);
2986   printf("  platform_id                                = %d\n",
2987          system_info_.platform_id);
2988   printf("  csd_version_rva                            = 0x%x\n",
2989          system_info_.csd_version_rva);
2990   printf("  suite_mask                                 = 0x%x\n",
2991          system_info_.suite_mask);
2992   for (unsigned int i = 0; i < 3; ++i) {
2993     printf("  cpu.x86_cpu_info.vendor_id[%d]              = 0x%x\n",
2994            i, system_info_.cpu.x86_cpu_info.vendor_id[i]);
2995   }
2996   printf("  cpu.x86_cpu_info.version_information       = 0x%x\n",
2997          system_info_.cpu.x86_cpu_info.version_information);
2998   printf("  cpu.x86_cpu_info.feature_information       = 0x%x\n",
2999          system_info_.cpu.x86_cpu_info.feature_information);
3000   printf("  cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n",
3001          system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
3002   const string* csd_version = GetCSDVersion();
3003   if (csd_version) {
3004     printf("  (csd_version)                              = \"%s\"\n",
3005            csd_version->c_str());
3006   } else {
3007     printf("  (csd_version)                              = (null)\n");
3008   }
3009   const string* cpu_vendor = GetCPUVendor();
3010   if (cpu_vendor) {
3011     printf("  (cpu_vendor)                               = \"%s\"\n",
3012            cpu_vendor->c_str());
3013   } else {
3014     printf("  (cpu_vendor)                               = (null)\n");
3015   }
3016   printf("\n");
3017 }
3018 
3019 
3020 //
3021 // MinidumpMiscInfo
3022 //
3023 
3024 
MinidumpMiscInfo(Minidump * minidump)3025 MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
3026     : MinidumpStream(minidump),
3027       misc_info_() {
3028 }
3029 
3030 
Read(u_int32_t expected_size)3031 bool MinidumpMiscInfo::Read(u_int32_t expected_size) {
3032   valid_ = false;
3033 
3034   if (expected_size != MD_MISCINFO_SIZE &&
3035       expected_size != MD_MISCINFO2_SIZE) {
3036     BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size <<
3037                     " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE <<
3038                     ")";
3039     return false;
3040   }
3041 
3042   if (!minidump_->ReadBytes(&misc_info_, expected_size)) {
3043     BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info";
3044     return false;
3045   }
3046 
3047   if (minidump_->swap()) {
3048     Swap(&misc_info_.size_of_info);
3049     Swap(&misc_info_.flags1);
3050     Swap(&misc_info_.process_id);
3051     Swap(&misc_info_.process_create_time);
3052     Swap(&misc_info_.process_user_time);
3053     Swap(&misc_info_.process_kernel_time);
3054     if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
3055       Swap(&misc_info_.processor_max_mhz);
3056       Swap(&misc_info_.processor_current_mhz);
3057       Swap(&misc_info_.processor_mhz_limit);
3058       Swap(&misc_info_.processor_max_idle_state);
3059       Swap(&misc_info_.processor_current_idle_state);
3060     }
3061   }
3062 
3063   if (expected_size != misc_info_.size_of_info) {
3064     BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " <<
3065                     expected_size << " != " << misc_info_.size_of_info;
3066     return false;
3067   }
3068 
3069   valid_ = true;
3070   return true;
3071 }
3072 
3073 
Print()3074 void MinidumpMiscInfo::Print() {
3075   if (!valid_) {
3076     BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data";
3077     return;
3078   }
3079 
3080   printf("MDRawMiscInfo\n");
3081   printf("  size_of_info                 = %d\n",   misc_info_.size_of_info);
3082   printf("  flags1                       = 0x%x\n", misc_info_.flags1);
3083   printf("  process_id                   = 0x%x\n", misc_info_.process_id);
3084   printf("  process_create_time          = 0x%x\n",
3085          misc_info_.process_create_time);
3086   printf("  process_user_time            = 0x%x\n",
3087          misc_info_.process_user_time);
3088   printf("  process_kernel_time          = 0x%x\n",
3089          misc_info_.process_kernel_time);
3090   if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
3091     printf("  processor_max_mhz            = %d\n",
3092            misc_info_.processor_max_mhz);
3093     printf("  processor_current_mhz        = %d\n",
3094            misc_info_.processor_current_mhz);
3095     printf("  processor_mhz_limit          = %d\n",
3096            misc_info_.processor_mhz_limit);
3097     printf("  processor_max_idle_state     = 0x%x\n",
3098            misc_info_.processor_max_idle_state);
3099     printf("  processor_current_idle_state = 0x%x\n",
3100            misc_info_.processor_current_idle_state);
3101   }
3102   printf("\n");
3103 }
3104 
3105 
3106 //
3107 // MinidumpBreakpadInfo
3108 //
3109 
3110 
MinidumpBreakpadInfo(Minidump * minidump)3111 MinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump)
3112     : MinidumpStream(minidump),
3113       breakpad_info_() {
3114 }
3115 
3116 
Read(u_int32_t expected_size)3117 bool MinidumpBreakpadInfo::Read(u_int32_t expected_size) {
3118   valid_ = false;
3119 
3120   if (expected_size != sizeof(breakpad_info_)) {
3121     BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size <<
3122                     " != " << sizeof(breakpad_info_);
3123     return false;
3124   }
3125 
3126   if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) {
3127     BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info";
3128     return false;
3129   }
3130 
3131   if (minidump_->swap()) {
3132     Swap(&breakpad_info_.validity);
3133     Swap(&breakpad_info_.dump_thread_id);
3134     Swap(&breakpad_info_.requesting_thread_id);
3135   }
3136 
3137   valid_ = true;
3138   return true;
3139 }
3140 
3141 
GetDumpThreadID(u_int32_t * thread_id) const3142 bool MinidumpBreakpadInfo::GetDumpThreadID(u_int32_t *thread_id) const {
3143   BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID "
3144                                  "requires |thread_id|";
3145   assert(thread_id);
3146   *thread_id = 0;
3147 
3148   if (!valid_) {
3149     BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID";
3150     return false;
3151   }
3152 
3153   if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) {
3154     BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread";
3155     return false;
3156   }
3157 
3158   *thread_id = breakpad_info_.dump_thread_id;
3159   return true;
3160 }
3161 
3162 
GetRequestingThreadID(u_int32_t * thread_id) const3163 bool MinidumpBreakpadInfo::GetRequestingThreadID(u_int32_t *thread_id)
3164     const {
3165   BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID "
3166                                  "requires |thread_id|";
3167   assert(thread_id);
3168   *thread_id = 0;
3169 
3170   if (!thread_id || !valid_) {
3171     BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID";
3172     return false;
3173   }
3174 
3175   if (!(breakpad_info_.validity &
3176             MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) {
3177     BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread";
3178     return false;
3179   }
3180 
3181   *thread_id = breakpad_info_.requesting_thread_id;
3182   return true;
3183 }
3184 
3185 
Print()3186 void MinidumpBreakpadInfo::Print() {
3187   if (!valid_) {
3188     BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data";
3189     return;
3190   }
3191 
3192   printf("MDRawBreakpadInfo\n");
3193   printf("  validity             = 0x%x\n", breakpad_info_.validity);
3194 
3195   if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) {
3196     printf("  dump_thread_id       = 0x%x\n", breakpad_info_.dump_thread_id);
3197   } else {
3198     printf("  dump_thread_id       = (invalid)\n");
3199   }
3200 
3201   if (breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID) {
3202     printf("  requesting_thread_id = 0x%x\n",
3203            breakpad_info_.requesting_thread_id);
3204   } else {
3205     printf("  requesting_thread_id = (invalid)\n");
3206   }
3207 
3208   printf("\n");
3209 }
3210 
3211 
3212 //
3213 // Minidump
3214 //
3215 
3216 
3217 u_int32_t Minidump::max_streams_ = 128;
3218 unsigned int Minidump::max_string_length_ = 1024;
3219 
3220 
Minidump(const string & path)3221 Minidump::Minidump(const string& path)
3222     : header_(),
3223       directory_(NULL),
3224       stream_map_(new MinidumpStreamMap()),
3225       path_(path),
3226       fd_(-1),
3227       swap_(false),
3228       valid_(false) {
3229 }
3230 
3231 
~Minidump()3232 Minidump::~Minidump() {
3233   delete directory_;
3234   delete stream_map_;
3235   if (fd_ != -1) {
3236     BPLOG(INFO) << "Minidump closing minidump on fd " << fd_;
3237     close(fd_);
3238   }
3239 }
3240 
3241 
Open()3242 bool Minidump::Open() {
3243   if (fd_ != -1) {
3244     BPLOG(INFO) << "Minidump reopening minidump " << path_ << " on fd " << fd_;
3245 
3246     // The file is already open.  Seek to the beginning, which is the position
3247     // the file would be at if it were opened anew.
3248     return SeekSet(0);
3249   }
3250 
3251   // O_BINARY is useful (and defined) on Windows.  On other platforms, it's
3252   // useless, and because it's defined as 0 above, harmless.
3253   fd_ = open(path_.c_str(), O_RDONLY | O_BINARY);
3254   if (fd_ == -1) {
3255     string error_string;
3256     int error_code = ErrnoString(&error_string);
3257     BPLOG(ERROR) << "Minidump could not open minidump " << path_ <<
3258                     ", error " << error_code << ": " << error_string;
3259     return false;
3260   }
3261 
3262   BPLOG(INFO) << "Minidump opened minidump " << path_ << " on fd " << fd_;
3263   return true;
3264 }
3265 
3266 
Read()3267 bool Minidump::Read() {
3268   // Invalidate cached data.
3269   delete directory_;
3270   directory_ = NULL;
3271   stream_map_->clear();
3272 
3273   valid_ = false;
3274 
3275   if (!Open()) {
3276     BPLOG(ERROR) << "Minidump cannot open minidump";
3277     return false;
3278   }
3279 
3280   if (!ReadBytes(&header_, sizeof(MDRawHeader))) {
3281     BPLOG(ERROR) << "Minidump cannot read header";
3282     return false;
3283   }
3284 
3285   if (header_.signature != MD_HEADER_SIGNATURE) {
3286     // The file may be byte-swapped.  Under the present architecture, these
3287     // classes don't know or need to know what CPU (or endianness) the
3288     // minidump was produced on in order to parse it.  Use the signature as
3289     // a byte order marker.
3290     u_int32_t signature_swapped = header_.signature;
3291     Swap(&signature_swapped);
3292     if (signature_swapped != MD_HEADER_SIGNATURE) {
3293       // This isn't a minidump or a byte-swapped minidump.
3294       BPLOG(ERROR) << "Minidump header signature mismatch: (" <<
3295                       HexString(header_.signature) << ", " <<
3296                       HexString(signature_swapped) << ") != " <<
3297                       HexString(MD_HEADER_SIGNATURE);
3298       return false;
3299     }
3300     swap_ = true;
3301   } else {
3302     // The file is not byte-swapped.  Set swap_ false (it may have been true
3303     // if the object is being reused?)
3304     swap_ = false;
3305   }
3306 
3307   BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") <<
3308                  "byte-swapping minidump";
3309 
3310   if (swap_) {
3311     Swap(&header_.signature);
3312     Swap(&header_.version);
3313     Swap(&header_.stream_count);
3314     Swap(&header_.stream_directory_rva);
3315     Swap(&header_.checksum);
3316     Swap(&header_.time_date_stamp);
3317     Swap(&header_.flags);
3318   }
3319 
3320   // Version check.  The high 16 bits of header_.version contain something
3321   // else "implementation specific."
3322   if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) {
3323     BPLOG(ERROR) << "Minidump version mismatch: " <<
3324                     HexString(header_.version & 0x0000ffff) << " != " <<
3325                     HexString(MD_HEADER_VERSION);
3326     return false;
3327   }
3328 
3329   if (!SeekSet(header_.stream_directory_rva)) {
3330     BPLOG(ERROR) << "Minidump cannot seek to stream directory";
3331     return false;
3332   }
3333 
3334   if (header_.stream_count > max_streams_) {
3335     BPLOG(ERROR) << "Minidump stream count " << header_.stream_count <<
3336                     " exceeds maximum " << max_streams_;
3337     return false;
3338   }
3339 
3340   if (header_.stream_count != 0) {
3341     scoped_ptr<MinidumpDirectoryEntries> directory(
3342         new MinidumpDirectoryEntries(header_.stream_count));
3343 
3344     // Read the entire array in one fell swoop, instead of reading one entry
3345     // at a time in the loop.
3346     if (!ReadBytes(&(*directory)[0],
3347                    sizeof(MDRawDirectory) * header_.stream_count)) {
3348       BPLOG(ERROR) << "Minidump cannot read stream directory";
3349       return false;
3350     }
3351 
3352     for (unsigned int stream_index = 0;
3353          stream_index < header_.stream_count;
3354          ++stream_index) {
3355       MDRawDirectory* directory_entry = &(*directory)[stream_index];
3356 
3357       if (swap_) {
3358         Swap(&directory_entry->stream_type);
3359         Swap(&directory_entry->location);
3360       }
3361 
3362       // Initialize the stream_map_ map, which speeds locating a stream by
3363       // type.
3364       unsigned int stream_type = directory_entry->stream_type;
3365       switch (stream_type) {
3366         case MD_THREAD_LIST_STREAM:
3367         case MD_MODULE_LIST_STREAM:
3368         case MD_MEMORY_LIST_STREAM:
3369         case MD_EXCEPTION_STREAM:
3370         case MD_SYSTEM_INFO_STREAM:
3371         case MD_MISC_INFO_STREAM:
3372         case MD_BREAKPAD_INFO_STREAM: {
3373           if (stream_map_->find(stream_type) != stream_map_->end()) {
3374             // Another stream with this type was already found.  A minidump
3375             // file should contain at most one of each of these stream types.
3376             BPLOG(ERROR) << "Minidump found multiple streams of type " <<
3377                             stream_type << ", but can only deal with one";
3378             return false;
3379           }
3380           // Fall through to default
3381         }
3382 
3383         default: {
3384           // Overwrites for stream types other than those above, but it's
3385           // expected to be the user's burden in that case.
3386           (*stream_map_)[stream_type].stream_index = stream_index;
3387         }
3388       }
3389     }
3390 
3391     directory_ = directory.release();
3392   }
3393 
3394   valid_ = true;
3395   return true;
3396 }
3397 
3398 
GetThreadList()3399 MinidumpThreadList* Minidump::GetThreadList() {
3400   MinidumpThreadList* thread_list;
3401   return GetStream(&thread_list);
3402 }
3403 
3404 
GetModuleList()3405 MinidumpModuleList* Minidump::GetModuleList() {
3406   MinidumpModuleList* module_list;
3407   return GetStream(&module_list);
3408 }
3409 
3410 
GetMemoryList()3411 MinidumpMemoryList* Minidump::GetMemoryList() {
3412   MinidumpMemoryList* memory_list;
3413   return GetStream(&memory_list);
3414 }
3415 
3416 
GetException()3417 MinidumpException* Minidump::GetException() {
3418   MinidumpException* exception;
3419   return GetStream(&exception);
3420 }
3421 
3422 
GetSystemInfo()3423 MinidumpSystemInfo* Minidump::GetSystemInfo() {
3424   MinidumpSystemInfo* system_info;
3425   return GetStream(&system_info);
3426 }
3427 
3428 
GetMiscInfo()3429 MinidumpMiscInfo* Minidump::GetMiscInfo() {
3430   MinidumpMiscInfo* misc_info;
3431   return GetStream(&misc_info);
3432 }
3433 
3434 
GetBreakpadInfo()3435 MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
3436   MinidumpBreakpadInfo* breakpad_info;
3437   return GetStream(&breakpad_info);
3438 }
3439 
3440 
Print()3441 void Minidump::Print() {
3442   if (!valid_) {
3443     BPLOG(ERROR) << "Minidump cannot print invalid data";
3444     return;
3445   }
3446 
3447   printf("MDRawHeader\n");
3448   printf("  signature            = 0x%x\n",    header_.signature);
3449   printf("  version              = 0x%x\n",    header_.version);
3450   printf("  stream_count         = %d\n",      header_.stream_count);
3451   printf("  stream_directory_rva = 0x%x\n",    header_.stream_directory_rva);
3452   printf("  checksum             = 0x%x\n",    header_.checksum);
3453   struct tm timestruct;
3454   gmtime_r(reinterpret_cast<time_t*>(&header_.time_date_stamp), &timestruct);
3455   char timestr[20];
3456   strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
3457   printf("  time_date_stamp      = 0x%x %s\n", header_.time_date_stamp,
3458                                                timestr);
3459   printf("  flags                = 0x%" PRIx64 "\n",  header_.flags);
3460   printf("\n");
3461 
3462   for (unsigned int stream_index = 0;
3463        stream_index < header_.stream_count;
3464        ++stream_index) {
3465     MDRawDirectory* directory_entry = &(*directory_)[stream_index];
3466 
3467     printf("mDirectory[%d]\n", stream_index);
3468     printf("MDRawDirectory\n");
3469     printf("  stream_type        = %d\n",   directory_entry->stream_type);
3470     printf("  location.data_size = %d\n",
3471            directory_entry->location.data_size);
3472     printf("  location.rva       = 0x%x\n", directory_entry->location.rva);
3473     printf("\n");
3474   }
3475 
3476   printf("Streams:\n");
3477   for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin();
3478        iterator != stream_map_->end();
3479        ++iterator) {
3480     u_int32_t stream_type = iterator->first;
3481     MinidumpStreamInfo info = iterator->second;
3482     printf("  stream type 0x%x at index %d\n", stream_type, info.stream_index);
3483   }
3484   printf("\n");
3485 }
3486 
3487 
GetDirectoryEntryAtIndex(unsigned int index) const3488 const MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index)
3489       const {
3490   if (!valid_) {
3491     BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex";
3492     return NULL;
3493   }
3494 
3495   if (index >= header_.stream_count) {
3496     BPLOG(ERROR) << "Minidump stream directory index out of range: " <<
3497                     index << "/" << header_.stream_count;
3498     return NULL;
3499   }
3500 
3501   return &(*directory_)[index];
3502 }
3503 
3504 
ReadBytes(void * bytes,size_t count)3505 bool Minidump::ReadBytes(void* bytes, size_t count) {
3506   // Can't check valid_ because Read needs to call this method before
3507   // validity can be determined.  The only member that this method
3508   // depends on is mFD, and an unset or invalid fd may generate an
3509   // error but should not cause a crash.
3510   ssize_t bytes_read = read(fd_, bytes, count);
3511   if (static_cast<size_t>(bytes_read) != count) {
3512     if (bytes_read == -1) {
3513       string error_string;
3514       int error_code = ErrnoString(&error_string);
3515       BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string;
3516     } else {
3517       BPLOG(ERROR) << "ReadBytes: read " << bytes_read << "/" << count;
3518     }
3519     return false;
3520   }
3521   return true;
3522 }
3523 
3524 
SeekSet(off_t offset)3525 bool Minidump::SeekSet(off_t offset) {
3526   // Can't check valid_ because Read needs to call this method before
3527   // validity can be determined.  The only member that this method
3528   // depends on is mFD, and an unset or invalid fd may generate an
3529   // error but should not cause a crash.
3530   off_t sought = lseek(fd_, offset, SEEK_SET);
3531   if (sought != offset) {
3532     if (sought == -1) {
3533       string error_string;
3534       int error_code = ErrnoString(&error_string);
3535       BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string;
3536     } else {
3537       BPLOG(ERROR) << "SeekSet: sought " << sought << "/" << offset;
3538     }
3539     return false;
3540   }
3541   return true;
3542 }
3543 
3544 
ReadString(off_t offset)3545 string* Minidump::ReadString(off_t offset) {
3546   if (!valid_) {
3547     BPLOG(ERROR) << "Invalid Minidump for ReadString";
3548     return NULL;
3549   }
3550   if (!SeekSet(offset)) {
3551     BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset;
3552     return NULL;
3553   }
3554 
3555   u_int32_t bytes;
3556   if (!ReadBytes(&bytes, sizeof(bytes))) {
3557     BPLOG(ERROR) << "ReadString could not read string size at offset " <<
3558                     offset;
3559     return NULL;
3560   }
3561   if (swap_)
3562     Swap(&bytes);
3563 
3564   if (bytes % 2 != 0) {
3565     BPLOG(ERROR) << "ReadString found odd-sized " << bytes <<
3566                     "-byte string at offset " << offset;
3567     return NULL;
3568   }
3569   unsigned int utf16_words = bytes / 2;
3570 
3571   if (utf16_words > max_string_length_) {
3572     BPLOG(ERROR) << "ReadString string length " << utf16_words <<
3573                     " exceeds maximum " << max_string_length_ <<
3574                     " at offset " << offset;
3575     return NULL;
3576   }
3577 
3578   vector<u_int16_t> string_utf16(utf16_words);
3579 
3580   if (utf16_words) {
3581     if (!ReadBytes(&string_utf16[0], bytes)) {
3582       BPLOG(ERROR) << "ReadString could not read " << bytes <<
3583                       "-byte string at offset " << offset;
3584       return NULL;
3585     }
3586   }
3587 
3588   return UTF16ToUTF8(string_utf16, swap_);
3589 }
3590 
3591 
SeekToStreamType(u_int32_t stream_type,u_int32_t * stream_length)3592 bool Minidump::SeekToStreamType(u_int32_t  stream_type,
3593                                 u_int32_t* stream_length) {
3594   BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires "
3595                                      "|stream_length|";
3596   assert(stream_length);
3597   *stream_length = 0;
3598 
3599   if (!valid_) {
3600     BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType";
3601     return false;
3602   }
3603 
3604   MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type);
3605   if (iterator == stream_map_->end()) {
3606     // This stream type didn't exist in the directory.
3607     BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present";
3608     return false;
3609   }
3610 
3611   MinidumpStreamInfo info = iterator->second;
3612   if (info.stream_index >= header_.stream_count) {
3613     BPLOG(ERROR) << "SeekToStreamType: type " << stream_type <<
3614                     " out of range: " <<
3615                     info.stream_index << "/" << header_.stream_count;
3616     return false;
3617   }
3618 
3619   MDRawDirectory* directory_entry = &(*directory_)[info.stream_index];
3620   if (!SeekSet(directory_entry->location.rva)) {
3621     BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " <<
3622                     stream_type;
3623     return false;
3624   }
3625 
3626   *stream_length = directory_entry->location.data_size;
3627 
3628   return true;
3629 }
3630 
3631 
3632 template<typename T>
GetStream(T ** stream)3633 T* Minidump::GetStream(T** stream) {
3634   // stream is a garbage parameter that's present only to account for C++'s
3635   // inability to overload a method based solely on its return type.
3636 
3637   const u_int32_t stream_type = T::kStreamType;
3638 
3639   BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type <<
3640                               " requires |stream|";
3641   assert(stream);
3642   *stream = NULL;
3643 
3644   if (!valid_) {
3645     BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type;
3646     return NULL;
3647   }
3648 
3649   MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type);
3650   if (iterator == stream_map_->end()) {
3651     // This stream type didn't exist in the directory.
3652     BPLOG(INFO) << "GetStream: type " << stream_type << " not present";
3653     return NULL;
3654   }
3655 
3656   // Get a pointer so that the stored stream field can be altered.
3657   MinidumpStreamInfo* info = &iterator->second;
3658 
3659   if (info->stream) {
3660     // This cast is safe because info.stream is only populated by this
3661     // method, and there is a direct correlation between T and stream_type.
3662     *stream = static_cast<T*>(info->stream);
3663     return *stream;
3664   }
3665 
3666   u_int32_t stream_length;
3667   if (!SeekToStreamType(stream_type, &stream_length)) {
3668     BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type;
3669     return NULL;
3670   }
3671 
3672   scoped_ptr<T> new_stream(new T(this));
3673 
3674   if (!new_stream->Read(stream_length)) {
3675     BPLOG(ERROR) << "GetStream could not read stream type " << stream_type;
3676     return NULL;
3677   }
3678 
3679   *stream = new_stream.release();
3680   info->stream = *stream;
3681   return *stream;
3682 }
3683 
3684 
3685 }  // namespace google_breakpad
3686