Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright (c) 2009, Google Inc. | 1 // Copyright (c) 2009, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 17 matching lines...) Expand all Loading... | |
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | 29 |
30 // Converts a minidump file to a core file which gdb can read. | 30 // Converts a minidump file to a core file which gdb can read. |
31 // Large parts lifted from the userspace core dumper: | 31 // Large parts lifted from the userspace core dumper: |
32 // http://code.google.com/p/google-coredumper/ | 32 // http://code.google.com/p/google-coredumper/ |
33 // | 33 // |
34 // Usage: minidump-2-core [-v] 1234.dmp > core | 34 // Usage: minidump-2-core [-v] 1234.dmp > core |
35 | 35 |
36 #include <elf.h> | 36 #include <elf.h> |
37 #include <errno.h> | 37 #include <errno.h> |
38 #include <inttypes.h> | |
38 #include <link.h> | 39 #include <link.h> |
39 #include <stdio.h> | 40 #include <stdio.h> |
40 #include <stdlib.h> | 41 #include <stdlib.h> |
41 #include <string.h> | 42 #include <string.h> |
42 #include <sys/user.h> | 43 #include <sys/user.h> |
43 #include <unistd.h> | 44 #include <unistd.h> |
44 | 45 |
45 #include <map> | 46 #include <map> |
46 #include <string> | 47 #include <string> |
47 #include <vector> | 48 #include <vector> |
48 | 49 |
49 #include "common/linux/memory_mapped_file.h" | 50 #include "common/linux/memory_mapped_file.h" |
51 #include "common/minidump_type_helper.h" | |
50 #include "common/scoped_ptr.h" | 52 #include "common/scoped_ptr.h" |
51 #include "google_breakpad/common/minidump_format.h" | 53 #include "google_breakpad/common/minidump_format.h" |
52 #include "third_party/lss/linux_syscall_support.h" | 54 #include "third_party/lss/linux_syscall_support.h" |
53 #include "tools/linux/md2core/minidump_memory_range.h" | 55 #include "tools/linux/md2core/minidump_memory_range.h" |
54 | 56 |
55 #if __WORDSIZE == 64 | 57 #if __WORDSIZE == 64 |
56 #define ELF_CLASS ELFCLASS64 | 58 #define ELF_CLASS ELFCLASS64 |
57 #else | 59 #else |
58 #define ELF_CLASS ELFCLASS32 | 60 #define ELF_CLASS ELFCLASS32 |
59 #endif | 61 #endif |
(...skipping 17 matching lines...) Expand all Loading... | |
77 #if defined(__arm__) | 79 #if defined(__arm__) |
78 // GLibc/ARM and Android/ARM both use 'user_regs' for the structure type | 80 // GLibc/ARM and Android/ARM both use 'user_regs' for the structure type |
79 // containing core registers, while they use 'user_regs_struct' on other | 81 // containing core registers, while they use 'user_regs_struct' on other |
80 // architectures. This file-local typedef simplifies the source code. | 82 // architectures. This file-local typedef simplifies the source code. |
81 typedef user_regs user_regs_struct; | 83 typedef user_regs user_regs_struct; |
82 #elif defined (__mips__) | 84 #elif defined (__mips__) |
83 // This file-local typedef simplifies the source code. | 85 // This file-local typedef simplifies the source code. |
84 typedef gregset_t user_regs_struct; | 86 typedef gregset_t user_regs_struct; |
85 #endif | 87 #endif |
86 | 88 |
89 using google_breakpad::MDTypeHelper; | |
87 using google_breakpad::MemoryMappedFile; | 90 using google_breakpad::MemoryMappedFile; |
88 using google_breakpad::MinidumpMemoryRange; | 91 using google_breakpad::MinidumpMemoryRange; |
92 | |
93 typedef MDTypeHelper<sizeof(ElfW(Addr))>::MDRawDebug MDRawDebug; | |
94 typedef MDTypeHelper<sizeof(ElfW(Addr))>::MDRawLinkMap MDRawLinkMap; | |
89 | 95 |
90 static const MDRVA kInvalidMDRVA = static_cast<MDRVA>(-1); | 96 static const MDRVA kInvalidMDRVA = static_cast<MDRVA>(-1); |
91 static bool verbose; | 97 static bool verbose; |
92 static std::string g_custom_so_basedir; | 98 static std::string g_custom_so_basedir; |
93 | 99 |
94 static int usage(const char* argv0) { | 100 static int usage(const char* argv0) { |
95 fprintf(stderr, "Usage: %s [-v] <minidump file>\n", argv0); | 101 fprintf(stderr, "Usage: %s [-v] <minidump file>\n", argv0); |
96 return 1; | 102 return 1; |
97 } | 103 } |
98 | 104 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 }; | 206 }; |
201 std::map<uint64_t, Mapping> mappings; | 207 std::map<uint64_t, Mapping> mappings; |
202 | 208 |
203 pid_t crashing_tid; | 209 pid_t crashing_tid; |
204 int fatal_signal; | 210 int fatal_signal; |
205 | 211 |
206 struct Thread { | 212 struct Thread { |
207 pid_t tid; | 213 pid_t tid; |
208 #if defined(__mips__) | 214 #if defined(__mips__) |
209 mcontext_t mcontext; | 215 mcontext_t mcontext; |
210 #else | 216 #else // __mips__ |
211 user_regs_struct regs; | 217 user_regs_struct regs; |
212 #if defined(__i386__) || defined(__x86_64__) | 218 #if defined(__i386__) || defined(__x86_64__) |
213 user_fpregs_struct fpregs; | 219 user_fpregs_struct fpregs; |
214 #endif | 220 #endif // __i386__ || __x86_64__ |
rmcilroy
2015/04/08 08:02:07
please add comments describing the 'if' which each
| |
215 #if defined(__i386__) | 221 #if defined(__i386__) |
216 user_fpxregs_struct fpxregs; | 222 user_fpxregs_struct fpxregs; |
217 #endif | 223 #endif // __i386__ |
218 #endif | 224 #endif // __mips__ |
219 uintptr_t stack_addr; | 225 uintptr_t stack_addr; |
220 const uint8_t* stack; | 226 const uint8_t* stack; |
221 size_t stack_length; | 227 size_t stack_length; |
222 }; | 228 }; |
223 std::vector<Thread> threads; | 229 std::vector<Thread> threads; |
224 | 230 |
225 const uint8_t* auxv; | 231 const uint8_t* auxv; |
226 size_t auxv_length; | 232 size_t auxv_length; |
227 | 233 |
228 prpsinfo prps; | 234 prpsinfo prps; |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
372 const MDRawContextMIPS* rawregs = range.GetData<MDRawContextMIPS>(0); | 378 const MDRawContextMIPS* rawregs = range.GetData<MDRawContextMIPS>(0); |
373 | 379 |
374 for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i) | 380 for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i) |
375 thread->mcontext.gregs[i] = rawregs->iregs[i]; | 381 thread->mcontext.gregs[i] = rawregs->iregs[i]; |
376 | 382 |
377 thread->mcontext.pc = rawregs->epc; | 383 thread->mcontext.pc = rawregs->epc; |
378 | 384 |
379 thread->mcontext.mdlo = rawregs->mdlo; | 385 thread->mcontext.mdlo = rawregs->mdlo; |
380 thread->mcontext.mdhi = rawregs->mdhi; | 386 thread->mcontext.mdhi = rawregs->mdhi; |
381 | 387 |
382 thread->mcontext.hi1 = rawregs->hi[0]; | 388 thread->mcontext.hi1 = rawregs->hi[0]; |
383 thread->mcontext.lo1 = rawregs->lo[0]; | 389 thread->mcontext.lo1 = rawregs->lo[0]; |
384 thread->mcontext.hi2 = rawregs->hi[1]; | 390 thread->mcontext.hi2 = rawregs->hi[1]; |
385 thread->mcontext.lo2 = rawregs->lo[1]; | 391 thread->mcontext.lo2 = rawregs->lo[1]; |
386 thread->mcontext.hi3 = rawregs->hi[2]; | 392 thread->mcontext.hi3 = rawregs->hi[2]; |
387 thread->mcontext.lo3 = rawregs->lo[2]; | 393 thread->mcontext.lo3 = rawregs->lo[2]; |
388 | 394 |
389 for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i) | 395 for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i) { |
rmcilroy
2015/04/08 08:02:07
use '{' since this is now more than two lines (cod
| |
390 thread->mcontext.fpregs.fp_r.fp_fregs[i]._fp_fregs = | 396 thread->mcontext.fpregs.fp_r.fp_fregs[i]._fp_fregs = |
391 rawregs->float_save.regs[i]; | 397 rawregs->float_save.regs[i]; |
rmcilroy
2015/04/08 08:02:07
indent by four spaces for line continuation.
| |
398 } | |
392 | 399 |
393 thread->mcontext.fpc_csr = rawregs->float_save.fpcsr; | 400 thread->mcontext.fpc_csr = rawregs->float_save.fpcsr; |
401 #if _MIPS_SIM == _ABIO32 | |
394 thread->mcontext.fpc_eir = rawregs->float_save.fir; | 402 thread->mcontext.fpc_eir = rawregs->float_save.fir; |
403 #endif | |
395 } | 404 } |
396 #else | 405 #else |
397 #error "This code has not been ported to your platform yet" | 406 #error "This code has not been ported to your platform yet" |
398 #endif | 407 #endif |
399 | 408 |
400 static void | 409 static void |
401 ParseThreadList(CrashedProcess* crashinfo, const MinidumpMemoryRange& range, | 410 ParseThreadList(CrashedProcess* crashinfo, const MinidumpMemoryRange& range, |
402 const MinidumpMemoryRange& full_file) { | 411 const MinidumpMemoryRange& full_file) { |
403 const uint32_t num_threads = *range.GetData<uint32_t>(0); | 412 const uint32_t num_threads = *range.GetData<uint32_t>(0); |
404 if (verbose) { | 413 if (verbose) { |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
697 const MinidumpMemoryRange& full_file) { | 706 const MinidumpMemoryRange& full_file) { |
698 const MDRawDebug* debug = range.GetData<MDRawDebug>(0); | 707 const MDRawDebug* debug = range.GetData<MDRawDebug>(0); |
699 if (!debug) { | 708 if (!debug) { |
700 return; | 709 return; |
701 } | 710 } |
702 if (verbose) { | 711 if (verbose) { |
703 fprintf(stderr, | 712 fprintf(stderr, |
704 "MD_LINUX_DSO_DEBUG:\n" | 713 "MD_LINUX_DSO_DEBUG:\n" |
705 "Version: %d\n" | 714 "Version: %d\n" |
706 "Number of DSOs: %d\n" | 715 "Number of DSOs: %d\n" |
707 "Brk handler: %p\n" | 716 "Brk handler: 0x%" PRIx64 "\n" |
708 "Dynamic loader at: %p\n" | 717 "Dynamic loader at: 0x%" PRIx64 "\n" |
709 "_DYNAMIC: %p\n", | 718 "_DYNAMIC: 0x%" PRIx64 "\n", |
710 debug->version, | 719 debug->version, |
711 debug->dso_count, | 720 debug->dso_count, |
712 debug->brk, | 721 static_cast<uint64_t>(debug->brk), |
713 debug->ldbase, | 722 static_cast<uint64_t>(debug->ldbase), |
714 debug->dynamic); | 723 static_cast<uint64_t>(debug->dynamic)); |
715 } | 724 } |
716 crashinfo->debug = *debug; | 725 crashinfo->debug = *debug; |
717 if (range.length() > sizeof(MDRawDebug)) { | 726 if (range.length() > sizeof(MDRawDebug)) { |
718 char* dynamic_data = (char*)range.data() + sizeof(MDRawDebug); | 727 char* dynamic_data = (char*)range.data() + sizeof(MDRawDebug); |
719 crashinfo->dynamic_data.assign(dynamic_data, | 728 crashinfo->dynamic_data.assign(dynamic_data, |
720 range.length() - sizeof(MDRawDebug)); | 729 range.length() - sizeof(MDRawDebug)); |
721 } | 730 } |
722 if (debug->map != kInvalidMDRVA) { | 731 if (debug->map != kInvalidMDRVA) { |
723 for (unsigned int i = 0; i < debug->dso_count; ++i) { | 732 for (unsigned int i = 0; i < debug->dso_count; ++i) { |
724 const MDRawLinkMap* link_map = | 733 const MDRawLinkMap* link_map = |
725 full_file.GetArrayElement<MDRawLinkMap>(debug->map, i); | 734 full_file.GetArrayElement<MDRawLinkMap>(debug->map, i); |
726 if (link_map) { | 735 if (link_map) { |
727 if (verbose) { | 736 if (verbose) { |
728 fprintf(stderr, | 737 fprintf(stderr, |
729 "#%03d: %p, %p, \"%s\"\n", | 738 "#%03d: %" PRIx64 ", %" PRIx64 ", \"%s\"\n", |
730 i, link_map->addr, link_map->ld, | 739 i, static_cast<uint64_t>(link_map->addr), |
740 static_cast<uint64_t>(link_map->ld), | |
731 full_file.GetAsciiMDString(link_map->name).c_str()); | 741 full_file.GetAsciiMDString(link_map->name).c_str()); |
732 } | 742 } |
733 crashinfo->link_map.push_back(*link_map); | 743 crashinfo->link_map.push_back(*link_map); |
734 } | 744 } |
735 } | 745 } |
736 } | 746 } |
737 if (verbose) { | 747 if (verbose) { |
738 fputs("\n\n", stderr); | 748 fputs("\n\n", stderr); |
739 } | 749 } |
740 } | 750 } |
741 | 751 |
742 static void | 752 static void |
743 ParseExceptionStream(CrashedProcess* crashinfo, | 753 ParseExceptionStream(CrashedProcess* crashinfo, |
744 const MinidumpMemoryRange& range) { | 754 const MinidumpMemoryRange& range) { |
745 const MDRawExceptionStream* exp = range.GetData<MDRawExceptionStream>(0); | 755 const MDRawExceptionStream* exp = range.GetData<MDRawExceptionStream>(0); |
746 crashinfo->crashing_tid = exp->thread_id; | 756 crashinfo->crashing_tid = exp->thread_id; |
747 crashinfo->fatal_signal = (int) exp->exception_record.exception_code; | 757 crashinfo->fatal_signal = (int) exp->exception_record.exception_code; |
748 } | 758 } |
749 | 759 |
750 static bool | 760 static bool |
751 WriteThread(const CrashedProcess::Thread& thread, int fatal_signal) { | 761 WriteThread(const CrashedProcess::Thread& thread, int fatal_signal) { |
752 struct prstatus pr; | 762 struct prstatus pr; |
753 memset(&pr, 0, sizeof(pr)); | 763 memset(&pr, 0, sizeof(pr)); |
754 | 764 |
755 pr.pr_info.si_signo = fatal_signal; | 765 pr.pr_info.si_signo = fatal_signal; |
756 pr.pr_cursig = fatal_signal; | 766 pr.pr_cursig = fatal_signal; |
757 pr.pr_pid = thread.tid; | 767 pr.pr_pid = thread.tid; |
758 #if defined(__mips__) | 768 #if defined(__mips__) |
759 memcpy(&pr.pr_reg, &thread.mcontext.gregs, sizeof(user_regs_struct)); | 769 memcpy(&pr.pr_reg, &thread.mcontext.gregs, sizeof(user_regs_struct)); |
rmcilroy
2015/04/08 08:02:07
nit - use the getters added to thread_info for thi
| |
760 #else | 770 #else |
761 memcpy(&pr.pr_reg, &thread.regs, sizeof(user_regs_struct)); | 771 memcpy(&pr.pr_reg, &thread.regs, sizeof(user_regs_struct)); |
762 #endif | 772 #endif |
763 | 773 |
764 Nhdr nhdr; | 774 Nhdr nhdr; |
765 memset(&nhdr, 0, sizeof(nhdr)); | 775 memset(&nhdr, 0, sizeof(nhdr)); |
766 nhdr.n_namesz = 5; | 776 nhdr.n_namesz = 5; |
767 nhdr.n_descsz = sizeof(struct prstatus); | 777 nhdr.n_descsz = sizeof(struct prstatus); |
768 nhdr.n_type = NT_PRSTATUS; | 778 nhdr.n_type = NT_PRSTATUS; |
769 if (!writea(1, &nhdr, sizeof(nhdr)) || | 779 if (!writea(1, &nhdr, sizeof(nhdr)) || |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1217 iter != crashinfo.mappings.end(); ++iter) { | 1227 iter != crashinfo.mappings.end(); ++iter) { |
1218 const CrashedProcess::Mapping& mapping = iter->second; | 1228 const CrashedProcess::Mapping& mapping = iter->second; |
1219 if (mapping.data.size()) { | 1229 if (mapping.data.size()) { |
1220 if (!writea(1, mapping.data.c_str(), mapping.data.size())) | 1230 if (!writea(1, mapping.data.c_str(), mapping.data.size())) |
1221 return 1; | 1231 return 1; |
1222 } | 1232 } |
1223 } | 1233 } |
1224 | 1234 |
1225 return 0; | 1235 return 0; |
1226 } | 1236 } |
LEFT | RIGHT |