aboutsummaryrefslogtreecommitdiff
path: root/src/processor
diff options
context:
space:
mode:
authorMike Frysinger <vapier@chromium.org>2016-10-25 20:12:09 -0400
committerMike Frysinger <vapier@chromium.org>2017-03-24 16:22:21 +0000
commite1b3620ec763cf3cd116570556cc3d7ca1771ad2 (patch)
tree1236c1cb0f5cd2abb637bde41b85122f03b68525 /src/processor
parentminidump_dump: add proper cli processing (diff)
downloadbreakpad-e1b3620ec763cf3cd116570556cc3d7ca1771ad2.tar.xz
minidump_dump: dump stack memory like hexdump
The current stack output is one line byte string which is not easy for humans to parse. Extend the print mode to support a hexdump-like view and switch to that by default. Now we get something like: Stack 00000000 20 67 7b 53 94 7f 00 00 01 00 00 00 00 00 00 00 | g{S...........| 00000010 00 70 c4 44 9a 25 00 00 08 65 7a 53 94 7f 00 00 |.p.D.%...ezS...| BUG=chromium:598947 Change-Id: I868e1cf4faa435a14c5f1c35f94a5db4a49b6a6d Reviewed-on: https://chromium-review.googlesource.com/404008 Reviewed-by: Mark Mentovai <mark@chromium.org>
Diffstat (limited to 'src/processor')
-rw-r--r--src/processor/minidump.cc78
-rw-r--r--src/processor/minidump_dump.cc17
2 files changed, 82 insertions, 13 deletions
diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
index 10400047..7fae7fb7 100644
--- a/src/processor/minidump.cc
+++ b/src/processor/minidump.cc
@@ -1202,6 +1202,8 @@ MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
: MinidumpObject(minidump),
descriptor_(NULL),
memory_(NULL) {
+ hexdump_width_ = minidump->HexdumpMode();
+ hexdump_ = hexdump_width_ != 0;
}
@@ -1360,19 +1362,77 @@ void MinidumpMemoryRegion::Print() const {
const uint8_t* memory = GetMemory();
if (memory) {
- printf("0x");
- for (unsigned int byte_index = 0;
- byte_index < descriptor_->memory.data_size;
- byte_index++) {
- printf("%02x", memory[byte_index]);
+ if (hexdump_) {
+ // Pretty hexdump view.
+ for (unsigned int byte_index = 0;
+ byte_index < descriptor_->memory.data_size;
+ byte_index += hexdump_width_) {
+ // In case the memory won't fill a whole line.
+ unsigned int num_bytes = std::min(
+ descriptor_->memory.data_size - byte_index, hexdump_width_);
+
+ // Display the leading address.
+ printf("%08x ", byte_index);
+
+ // Show the bytes in hex.
+ for (unsigned int i = 0; i < hexdump_width_; ++i) {
+ if (i < num_bytes) {
+ // Show the single byte of memory in hex.
+ printf("%02x ", memory[byte_index + i]);
+ } else {
+ // If this line doesn't fill up, pad it out.
+ printf(" ");
+ }
+
+ // Insert a space every 8 bytes to make it more readable.
+ if (((i + 1) % 8) == 0) {
+ printf(" ");
+ }
+ }
+
+ // Decode the line as ASCII.
+ printf("|");
+ for (unsigned int i = 0; i < hexdump_width_; ++i) {
+ if (i < num_bytes) {
+ uint8_t byte = memory[byte_index + i];
+ printf("%c", isprint(byte) ? byte : '.');
+ } else {
+ // If this line doesn't fill up, pad it out.
+ printf(" ");
+ }
+ }
+ printf("|\n");
+ }
+ } else {
+ // Ugly raw string view.
+ printf("0x");
+ for (unsigned int i = 0;
+ i < descriptor_->memory.data_size;
+ i++) {
+ printf("%02x", memory[i]);
+ }
+ printf("\n");
}
- printf("\n");
} else {
printf("No memory\n");
}
}
+void MinidumpMemoryRegion::SetPrintMode(bool hexdump,
+ unsigned int hexdump_width) {
+ // Require the width to be a multiple of 8 bytes.
+ if (hexdump_width == 0 || (hexdump_width % 8) != 0) {
+ BPLOG(ERROR) << "MinidumpMemoryRegion print hexdump_width must be "
+ "multiple of 8, not " << hexdump_width;
+ return;
+ }
+
+ hexdump_ = hexdump;
+ hexdump_width_ = hexdump_width;
+}
+
+
//
// MinidumpThread
//
@@ -4694,14 +4754,16 @@ uint32_t Minidump::max_streams_ = 128;
unsigned int Minidump::max_string_length_ = 1024;
-Minidump::Minidump(const string& path)
+Minidump::Minidump(const string& path, bool hexdump, unsigned int hexdump_width)
: header_(),
directory_(NULL),
stream_map_(new MinidumpStreamMap()),
path_(path),
stream_(NULL),
swap_(false),
- valid_(false) {
+ valid_(false),
+ hexdump_(hexdump),
+ hexdump_width_(hexdump_width) {
}
Minidump::Minidump(istream& stream)
diff --git a/src/processor/minidump_dump.cc b/src/processor/minidump_dump.cc
index d6342cc4..a21ae5a7 100644
--- a/src/processor/minidump_dump.cc
+++ b/src/processor/minidump_dump.cc
@@ -55,9 +55,11 @@ using google_breakpad::MinidumpBreakpadInfo;
struct Options {
Options()
- : minidumpPath() {}
+ : minidumpPath(), hexdump(false), hexdump_width(hexdump_width) {}
string minidumpPath;
+ bool hexdump;
+ unsigned int hexdump_width;
};
static void DumpRawStream(Minidump *minidump,
@@ -99,8 +101,9 @@ static void DumpRawStream(Minidump *minidump,
printf("\n\n");
}
-static bool PrintMinidumpDump(const string& minidump_file) {
- Minidump minidump(minidump_file);
+static bool PrintMinidumpDump(const Options& options) {
+ Minidump minidump(options.minidumpPath,
+ options.hexdump);
if (!minidump.Read()) {
BPLOG(ERROR) << "minidump.Read() failed";
return false;
@@ -218,6 +221,7 @@ Usage(int argc, const char *argv[], bool error) {
"\n"
"Options:\n"
" <minidump> should be a minidump.\n"
+ " -x:\t Display memory in a hexdump like format\n"
" -h:\t Usage\n",
argv[0]);
}
@@ -227,8 +231,11 @@ static void
SetupOptions(int argc, const char *argv[], Options *options) {
int ch;
- while ((ch = getopt(argc, (char * const *)argv, "h")) != -1) {
+ while ((ch = getopt(argc, (char * const *)argv, "xh")) != -1) {
switch (ch) {
+ case 'x':
+ options->hexdump = true;
+ break;
case 'h':
Usage(argc, argv, false);
exit(0);
@@ -254,5 +261,5 @@ int main(int argc, const char *argv[]) {
Options options;
BPLOG_INIT(&argc, &argv);
SetupOptions(argc, argv, &options);
- return PrintMinidumpDump(options.minidumpPath) ? 0 : 1;
+ return PrintMinidumpDump(options) ? 0 : 1;
}