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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/client/linux/microdump_writer/microdump_writer.cc
diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc
index d459d9ec441370c2e06e2e2f9a365bedf10e6353..ee089c9510014a191bb9a735e799a4a3afe84f9e 100644
--- a/src/client/linux/microdump_writer/microdump_writer.cc
+++ b/src/client/linux/microdump_writer/microdump_writer.cc
@@ -34,8 +34,6 @@
#include <sys/utsname.h>
-#include <algorithm>
-
#include "client/linux/dump_writer_common/thread_info.h"
#include "client/linux/dump_writer_common/ucontext_reader.h"
#include "client/linux/handler/exception_handler.h"
@@ -44,6 +42,7 @@
#include "client/linux/minidump_writer/linux_ptrace_dumper.h"
#include "common/linux/file_id.h"
#include "common/linux/linux_libc_support.h"
+#include "common/memory.h"
namespace {
@@ -61,6 +60,58 @@ using google_breakpad::UContextReader;
const size_t kLineBufferSize = 2048;
+int Log2Floor(uint64_t n) {
+ // Copied from chromium src/base/bits.h
+ if (n == 0)
+ return -1;
+ int log = 0;
+ uint64_t value = n;
+ for (int i = 5; i >= 0; --i) {
+ int shift = (1 << i);
+ uint64_t x = value >> shift;
+ if (x != 0) {
+ value = x;
+ log += shift;
+ }
+ }
+ assert(value == 1u);
+ return log;
+}
+
+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.
+ // Because of load biasing, we can end up with a situation where two
+ // mappings actually overlap. So we will define adjacency to also include a
+ // b start address that lies within a's address range (including starting
+ // immediately after a).
+ // Because load biasing only ever moves the start address backwards, the end
+ // address should still increase.
+ return a->start_addr <= b->start_addr &&
+ a->start_addr + a->size >= b->start_addr;
+}
+
+bool MappingLessThan(const MappingInfo* a, const MappingInfo* b) {
+ // Return true if mapping a is before mapping b.
+ // For the same reason (load biasing) we compare end addresses, which - unlike
+ // start addresses - will not have been modified.
+ return a->start_addr + a->size < b->start_addr + b->size;
+}
+
+size_t NextOrderedMapping(
+ const google_breakpad::wasteful_vector<MappingInfo*>& mappings,
+ size_t curr) {
+ // Find the mapping that directly follows mappings[curr].
+ // If no such mapping exists, return mappings.size() to indicate this.
+ 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.
+ size_t best = invalid;
+ for (size_t next = 0; next < mappings.size(); ++next) {
+ if (MappingLessThan(mappings[curr], mappings[next]) &&
+ (best == invalid || MappingLessThan(mappings[next], mappings[best]))) {
+ best = next;
+ }
+ }
+ return best;
+}
+
class MicrodumpWriter {
public:
MicrodumpWriter(const ExceptionHandler::CrashContext* context,
@@ -98,6 +149,9 @@ class MicrodumpWriter {
DumpProductInformation();
DumpOSInformation();
DumpGPUInformation();
+#if !defined(__LP64__)
+ DumpFreeSpace();
+#endif
success = DumpCrashingThread();
if (success)
success = DumpMappings();
@@ -391,6 +445,84 @@ class MicrodumpWriter {
LogCommitLine();
}
+#if !defined(__LP64__)
+ 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.
+ const google_breakpad::wasteful_vector<MappingInfo*>& mappings =
+ dumper_->mappings();
+ if (mappings.size() == 0) return false;
+
+ // This is complicated by the fact that mappings is not in order. It should
+ // be mostly in order, however the mapping that contains the entry point for
+ // the process is always at the front of the vector.
+
+ static const int HBITS = sizeof(size_t) * 8;
+ uint8_t hole_histogram[HBITS];
+ my_memset(hole_histogram, 0, sizeof(hole_histogram));
+
+ // Find the lowest address mapping.
+ size_t curr = 0;
+ for (size_t i = 1; i < mappings.size(); ++i) {
+ if (mappings[i]->start_addr < mappings[curr]->start_addr) curr = i;
+ }
+
+ uintptr_t lo_addr = mappings[curr]->start_addr;
+
+ 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.
+ size_t hole_max = 0;
+ size_t hole_sum = 0;
+
+ while (true) {
+ // Skip to the end of an adjacent run of mappings. This is an optimization
+ // for the fact that mappings is mostly sorted.
+ 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=
+ MappingsAreAdjacent(mappings[curr], mappings[curr + 1])) {
+ ++curr;
+ }
+
+ size_t next = NextOrderedMapping(mappings, curr);
+ if (next == mappings.size())
+ break;
+
+ uintptr_t hole_lo = mappings[curr]->start_addr + mappings[curr]->size;
+ uintptr_t hole_hi = mappings[next]->start_addr;
+
+ if (hole_hi > hole_lo) {
+ size_t hole_sz = hole_hi - hole_lo;
+ int log2_hole_sz = Log2Floor(hole_sz);
+ hole_sum += hole_sz;
+ hole_max = std::max(hole_sz, hole_max);
+ ++hole_cnt;
+ if (hole_histogram[log2_hole_sz] != 0xff) {
+ ++hole_histogram[Log2Floor(hole_sz)];
+ }
+ }
+ curr = next;
+ }
+
+ uintptr_t hi_addr = mappings[curr]->start_addr + mappings[curr]->size;
+
+ LogAppend("H ");
+ LogAppend(lo_addr);
+ LogAppend(" ");
+ LogAppend(hi_addr);
+ LogAppend(" ");
+ 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.
+ LogAppend(" ");
+ LogAppend(hole_max);
+ LogAppend(" ");
+ LogAppend(hole_sum);
+ for (unsigned int i = 0; i < HBITS; ++i) {
+ if (!hole_histogram[i]) continue;
+ LogAppend(" ");
+ 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.
+ LogAppend(":");
+ LogAppend(hole_histogram[i]);
+ }
+ LogCommitLine();
+ return true;
+ }
+#endif
+
// Write information about the mappings in effect.
bool DumpMappings() {
// First write all the mappings from the dumper
« 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