Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: src/client/linux/microdump_writer/microdump_writer.cc

Issue 1796803003: Add statistics about free space to microdump format. (Closed) Base URL: https://chromium.googlesource.com/breakpad/breakpad.git@master
Patch Set: Address comments, Fix NextOrderedMapping. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, Google Inc. 1 // Copyright (c) 2014, 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 16 matching lines...) Expand all
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 29
30 // This translation unit generates microdumps into the console (logcat on 30 // This translation unit generates microdumps into the console (logcat on
31 // Android). See crbug.com/410294 for more info and design docs. 31 // Android). See crbug.com/410294 for more info and design docs.
32 32
33 #include "client/linux/microdump_writer/microdump_writer.h" 33 #include "client/linux/microdump_writer/microdump_writer.h"
34 34
35 #include <sys/utsname.h> 35 #include <sys/utsname.h>
36 36
37 #include <algorithm>
38
39 #include "client/linux/dump_writer_common/thread_info.h" 37 #include "client/linux/dump_writer_common/thread_info.h"
40 #include "client/linux/dump_writer_common/ucontext_reader.h" 38 #include "client/linux/dump_writer_common/ucontext_reader.h"
41 #include "client/linux/handler/exception_handler.h" 39 #include "client/linux/handler/exception_handler.h"
42 #include "client/linux/handler/microdump_extra_info.h" 40 #include "client/linux/handler/microdump_extra_info.h"
43 #include "client/linux/log/log.h" 41 #include "client/linux/log/log.h"
44 #include "client/linux/minidump_writer/linux_ptrace_dumper.h" 42 #include "client/linux/minidump_writer/linux_ptrace_dumper.h"
45 #include "common/linux/file_id.h" 43 #include "common/linux/file_id.h"
46 #include "common/linux/linux_libc_support.h" 44 #include "common/linux/linux_libc_support.h"
45 #include "common/memory.h"
47 46
48 namespace { 47 namespace {
49 48
50 using google_breakpad::auto_wasteful_vector; 49 using google_breakpad::auto_wasteful_vector;
51 using google_breakpad::ExceptionHandler; 50 using google_breakpad::ExceptionHandler;
52 using google_breakpad::kDefaultBuildIdSize; 51 using google_breakpad::kDefaultBuildIdSize;
53 using google_breakpad::LinuxDumper; 52 using google_breakpad::LinuxDumper;
54 using google_breakpad::LinuxPtraceDumper; 53 using google_breakpad::LinuxPtraceDumper;
55 using google_breakpad::MappingInfo; 54 using google_breakpad::MappingInfo;
56 using google_breakpad::MappingList; 55 using google_breakpad::MappingList;
57 using google_breakpad::MicrodumpExtraInfo; 56 using google_breakpad::MicrodumpExtraInfo;
58 using google_breakpad::RawContextCPU; 57 using google_breakpad::RawContextCPU;
59 using google_breakpad::ThreadInfo; 58 using google_breakpad::ThreadInfo;
60 using google_breakpad::UContextReader; 59 using google_breakpad::UContextReader;
61 60
62 const size_t kLineBufferSize = 2048; 61 const size_t kLineBufferSize = 2048;
63 62
63 int Log2Floor(uint64_t n) {
64 // Copied from chromium src/base/bits.h
65 if (n == 0)
66 return -1;
67 int log = 0;
68 uint64_t value = n;
69 for (int i = 5; i >= 0; --i) {
70 int shift = (1 << i);
71 uint64_t x = value >> shift;
72 if (x != 0) {
73 value = x;
74 log += shift;
75 }
76 }
77 assert(value == 1u);
78 return log;
79 }
80
81 bool MappingsAreAdjacent(const MappingInfo* a, const MappingInfo* b) {
Primiano Tucci (use gerrit) 2016/05/20 15:18:22 nit: just for consistency (with your own code belo
Tobias Sargeant 2016/05/23 10:51:59 Done.
82 // Because of load biasing, we can end up with a situation where two
83 // mappings actually overlap. So we will define adjacency to also include a
84 // b start address that lies within a's address range (including starting
85 // immediately after a).
86 // Because load biasing only ever moves the start address backwards, the end
87 // address should still increase.
88 return a->start_addr <= b->start_addr &&
89 a->start_addr + a->size >= b->start_addr;
90 }
91
92 bool MappingLessThan(const MappingInfo* a, const MappingInfo* b) {
93 // Return true if mapping a is before mapping b.
94 // For the same reason (load biasing) we compare end addresses, which - unlike
95 // start addresses - will not have been modified.
96 return a->start_addr + a->size < b->start_addr + b->size;
97 }
98
99 size_t NextOrderedMapping(
100 const google_breakpad::wasteful_vector<MappingInfo*>& mappings,
101 size_t curr) {
102 // Find the mapping that directly follows mappings[curr].
103 // If no such mapping exists, return mappings.size() to indicate this.
104 const size_t invalid = mappings.size();
Primiano Tucci (use gerrit) 2016/05/20 15:18:22 not a huge difference but I typically see this as
Tobias Sargeant 2016/05/23 10:51:59 Done.
105 size_t best = invalid;
106 for (size_t next = 0; next < mappings.size(); ++next) {
107 if (MappingLessThan(mappings[curr], mappings[next]) &&
108 (best == invalid || MappingLessThan(mappings[next], mappings[best]))) {
109 best = next;
110 }
111 }
112 return best;
113 }
114
64 class MicrodumpWriter { 115 class MicrodumpWriter {
65 public: 116 public:
66 MicrodumpWriter(const ExceptionHandler::CrashContext* context, 117 MicrodumpWriter(const ExceptionHandler::CrashContext* context,
67 const MappingList& mappings, 118 const MappingList& mappings,
68 const MicrodumpExtraInfo& microdump_extra_info, 119 const MicrodumpExtraInfo& microdump_extra_info,
69 LinuxDumper* dumper) 120 LinuxDumper* dumper)
70 : ucontext_(context ? &context->context : NULL), 121 : ucontext_(context ? &context->context : NULL),
71 #if !defined(__ARM_EABI__) && !defined(__mips__) 122 #if !defined(__ARM_EABI__) && !defined(__mips__)
72 float_state_(context ? &context->float_state : NULL), 123 float_state_(context ? &context->float_state : NULL),
73 #endif 124 #endif
(...skipping 17 matching lines...) Expand all
91 return false; 142 return false;
92 return dumper_->ThreadsSuspend() && dumper_->LateInit(); 143 return dumper_->ThreadsSuspend() && dumper_->LateInit();
93 } 144 }
94 145
95 bool Dump() { 146 bool Dump() {
96 bool success; 147 bool success;
97 LogLine("-----BEGIN BREAKPAD MICRODUMP-----"); 148 LogLine("-----BEGIN BREAKPAD MICRODUMP-----");
98 DumpProductInformation(); 149 DumpProductInformation();
99 DumpOSInformation(); 150 DumpOSInformation();
100 DumpGPUInformation(); 151 DumpGPUInformation();
152 #if !defined(__LP64__)
153 DumpFreeSpace();
154 #endif
101 success = DumpCrashingThread(); 155 success = DumpCrashingThread();
102 if (success) 156 if (success)
103 success = DumpMappings(); 157 success = DumpMappings();
104 LogLine("-----END BREAKPAD MICRODUMP-----"); 158 LogLine("-----END BREAKPAD MICRODUMP-----");
105 dumper_->ThreadsResume(); 159 dumper_->ThreadsResume();
106 return success; 160 return success;
107 } 161 }
108 162
109 private: 163 private:
110 // Writes one line to the system log. 164 // Writes one line to the system log.
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 LogAppend(module_identifier.data4[3]); 438 LogAppend(module_identifier.data4[3]);
385 LogAppend(module_identifier.data4[4]); 439 LogAppend(module_identifier.data4[4]);
386 LogAppend(module_identifier.data4[5]); 440 LogAppend(module_identifier.data4[5]);
387 LogAppend(module_identifier.data4[6]); 441 LogAppend(module_identifier.data4[6]);
388 LogAppend(module_identifier.data4[7]); 442 LogAppend(module_identifier.data4[7]);
389 LogAppend("0 "); // Age is always 0 on Linux. 443 LogAppend("0 "); // Age is always 0 on Linux.
390 LogAppend(file_name); 444 LogAppend(file_name);
391 LogCommitLine(); 445 LogCommitLine();
392 } 446 }
393 447
448 #if !defined(__LP64__)
449 bool DumpFreeSpace() {
Primiano Tucci (use gerrit) 2016/05/20 15:18:22 make this void. You never seeem to sue the return
Tobias Sargeant 2016/05/23 10:51:59 Done.
450 const google_breakpad::wasteful_vector<MappingInfo*>& mappings =
451 dumper_->mappings();
452 if (mappings.size() == 0) return false;
453
454 // This is complicated by the fact that mappings is not in order. It should
455 // be mostly in order, however the mapping that contains the entry point for
456 // the process is always at the front of the vector.
457
458 static const int HBITS = sizeof(size_t) * 8;
459 uint8_t hole_histogram[HBITS];
460 my_memset(hole_histogram, 0, sizeof(hole_histogram));
461
462 // Find the lowest address mapping.
463 size_t curr = 0;
464 for (size_t i = 1; i < mappings.size(); ++i) {
465 if (mappings[i]->start_addr < mappings[curr]->start_addr) curr = i;
466 }
467
468 uintptr_t lo_addr = mappings[curr]->start_addr;
469
470 unsigned int hole_cnt = 0;
Primiano Tucci (use gerrit) 2016/05/20 15:18:22 why not making this also a size_t? you are going t
Tobias Sargeant 2016/05/23 10:51:59 Done.
471 size_t hole_max = 0;
472 size_t hole_sum = 0;
473
474 while (true) {
475 // Skip to the end of an adjacent run of mappings. This is an optimization
476 // for the fact that mappings is mostly sorted.
477 while (curr != mappings.size() - 1 &&
Primiano Tucci (use gerrit) 2016/05/20 15:18:22 shouldn't this be s/-1/-2/, as below you access ma
Tobias Sargeant 2016/05/20 15:32:54 It might be better to write curr < mappings.size()
Primiano Tucci (use gerrit) 2016/05/20 17:52:48 oh ok forget my comment, I am just wrong. If size=
478 MappingsAreAdjacent(mappings[curr], mappings[curr + 1])) {
479 ++curr;
480 }
481
482 size_t next = NextOrderedMapping(mappings, curr);
483 if (next == mappings.size())
484 break;
485
486 uintptr_t hole_lo = mappings[curr]->start_addr + mappings[curr]->size;
487 uintptr_t hole_hi = mappings[next]->start_addr;
488
489 if (hole_hi > hole_lo) {
490 size_t hole_sz = hole_hi - hole_lo;
491 int log2_hole_sz = Log2Floor(hole_sz);
492 hole_sum += hole_sz;
493 hole_max = std::max(hole_sz, hole_max);
494 ++hole_cnt;
495 if (hole_histogram[log2_hole_sz] != 0xff) {
496 ++hole_histogram[Log2Floor(hole_sz)];
497 }
498 }
499 curr = next;
500 }
501
502 uintptr_t hi_addr = mappings[curr]->start_addr + mappings[curr]->size;
503
504 LogAppend("H ");
505 LogAppend(lo_addr);
506 LogAppend(" ");
507 LogAppend(hi_addr);
508 LogAppend(" ");
509 LogAppend(static_cast<uint16_t>(hole_cnt));
Primiano Tucci (use gerrit) 2016/05/20 15:18:22 maybe you could do a saturated cast (stick at UINT
Tobias Sargeant 2016/05/20 15:32:55 Can you use base::saturated_cast here, or is there
Primiano Tucci (use gerrit) 2016/05/20 17:52:48 unfortunately there is no fancy chromium base here
Tobias Sargeant 2016/05/23 10:51:59 Done.
510 LogAppend(" ");
511 LogAppend(hole_max);
512 LogAppend(" ");
513 LogAppend(hole_sum);
514 for (unsigned int i = 0; i < HBITS; ++i) {
515 if (!hole_histogram[i]) continue;
516 LogAppend(" ");
517 LogAppend(static_cast<uint8_t>(i));
Primiano Tucci (use gerrit) 2016/05/20 15:18:22 ditto hjere about saturation
Tobias Sargeant 2016/05/23 10:51:59 Done.
518 LogAppend(":");
519 LogAppend(hole_histogram[i]);
520 }
521 LogCommitLine();
522 return true;
523 }
524 #endif
525
394 // Write information about the mappings in effect. 526 // Write information about the mappings in effect.
395 bool DumpMappings() { 527 bool DumpMappings() {
396 // First write all the mappings from the dumper 528 // First write all the mappings from the dumper
397 for (unsigned i = 0; i < dumper_->mappings().size(); ++i) { 529 for (unsigned i = 0; i < dumper_->mappings().size(); ++i) {
398 const MappingInfo& mapping = *dumper_->mappings()[i]; 530 const MappingInfo& mapping = *dumper_->mappings()[i];
399 if (mapping.name[0] == 0 || // only want modules with filenames. 531 if (mapping.name[0] == 0 || // only want modules with filenames.
400 !mapping.exec || // only want executable mappings. 532 !mapping.exec || // only want executable mappings.
401 mapping.size < 4096 || // too small to get a signature for. 533 mapping.size < 4096 || // too small to get a signature for.
402 HaveMappingInfo(mapping)) { 534 HaveMappingInfo(mapping)) {
403 continue; 535 continue;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 dumper.set_crash_signal(context->siginfo.si_signo); 577 dumper.set_crash_signal(context->siginfo.si_signo);
446 dumper.set_crash_thread(context->tid); 578 dumper.set_crash_thread(context->tid);
447 } 579 }
448 MicrodumpWriter writer(context, mappings, microdump_extra_info, &dumper); 580 MicrodumpWriter writer(context, mappings, microdump_extra_info, &dumper);
449 if (!writer.Init()) 581 if (!writer.Init())
450 return false; 582 return false;
451 return writer.Dump(); 583 return writer.Dump();
452 } 584 }
453 585
454 } // namespace google_breakpad 586 } // namespace google_breakpad
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698