mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-01-10 19:25:37 +00:00
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>
This commit is contained in:
parent
117aa25107
commit
e1b3620ec7
|
@ -236,6 +236,7 @@ class MinidumpMemoryRegion : public MinidumpObject,
|
||||||
|
|
||||||
// Print a human-readable representation of the object to stdout.
|
// Print a human-readable representation of the object to stdout.
|
||||||
void Print() const;
|
void Print() const;
|
||||||
|
void SetPrintMode(bool hexdump, unsigned int width);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit MinidumpMemoryRegion(Minidump* minidump);
|
explicit MinidumpMemoryRegion(Minidump* minidump);
|
||||||
|
@ -252,6 +253,10 @@ class MinidumpMemoryRegion : public MinidumpObject,
|
||||||
template<typename T> bool GetMemoryAtAddressInternal(uint64_t address,
|
template<typename T> bool GetMemoryAtAddressInternal(uint64_t address,
|
||||||
T* value) const;
|
T* value) const;
|
||||||
|
|
||||||
|
// Knobs for controlling display of memory printing.
|
||||||
|
bool hexdump_;
|
||||||
|
unsigned int hexdump_width_;
|
||||||
|
|
||||||
// The largest memory region that will be read from a minidump. The
|
// The largest memory region that will be read from a minidump. The
|
||||||
// default is 1MB.
|
// default is 1MB.
|
||||||
static uint32_t max_bytes_;
|
static uint32_t max_bytes_;
|
||||||
|
@ -1104,7 +1109,9 @@ class MinidumpLinuxMapsList : public MinidumpStream {
|
||||||
class Minidump {
|
class Minidump {
|
||||||
public:
|
public:
|
||||||
// path is the pathname of a file containing the minidump.
|
// path is the pathname of a file containing the minidump.
|
||||||
explicit Minidump(const string& path);
|
explicit Minidump(const string& path,
|
||||||
|
bool hexdump=false,
|
||||||
|
unsigned int hexdump_width=16);
|
||||||
// input is an istream wrapping minidump data. Minidump holds a
|
// input is an istream wrapping minidump data. Minidump holds a
|
||||||
// weak pointer to input, and the caller must ensure that the stream
|
// weak pointer to input, and the caller must ensure that the stream
|
||||||
// is valid as long as the Minidump object is.
|
// is valid as long as the Minidump object is.
|
||||||
|
@ -1214,6 +1221,9 @@ class Minidump {
|
||||||
// Is the OS Android.
|
// Is the OS Android.
|
||||||
bool IsAndroid();
|
bool IsAndroid();
|
||||||
|
|
||||||
|
// Get current hexdump display settings.
|
||||||
|
unsigned int HexdumpMode() const { return hexdump_ ? hexdump_width_ : 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// MinidumpStreamInfo is used in the MinidumpStreamMap. It lets
|
// MinidumpStreamInfo is used in the MinidumpStreamMap. It lets
|
||||||
// the Minidump object locate interesting streams quickly, and
|
// the Minidump object locate interesting streams quickly, and
|
||||||
|
@ -1275,6 +1285,10 @@ class Minidump {
|
||||||
// Read().
|
// Read().
|
||||||
bool valid_;
|
bool valid_;
|
||||||
|
|
||||||
|
// Knobs for controlling display of memory printing.
|
||||||
|
bool hexdump_;
|
||||||
|
unsigned int hexdump_width_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(Minidump);
|
DISALLOW_COPY_AND_ASSIGN(Minidump);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1202,6 +1202,8 @@ MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
|
||||||
: MinidumpObject(minidump),
|
: MinidumpObject(minidump),
|
||||||
descriptor_(NULL),
|
descriptor_(NULL),
|
||||||
memory_(NULL) {
|
memory_(NULL) {
|
||||||
|
hexdump_width_ = minidump->HexdumpMode();
|
||||||
|
hexdump_ = hexdump_width_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1360,19 +1362,77 @@ void MinidumpMemoryRegion::Print() const {
|
||||||
|
|
||||||
const uint8_t* memory = GetMemory();
|
const uint8_t* memory = GetMemory();
|
||||||
if (memory) {
|
if (memory) {
|
||||||
printf("0x");
|
if (hexdump_) {
|
||||||
for (unsigned int byte_index = 0;
|
// Pretty hexdump view.
|
||||||
byte_index < descriptor_->memory.data_size;
|
for (unsigned int byte_index = 0;
|
||||||
byte_index++) {
|
byte_index < descriptor_->memory.data_size;
|
||||||
printf("%02x", memory[byte_index]);
|
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 {
|
} else {
|
||||||
printf("No memory\n");
|
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
|
// MinidumpThread
|
||||||
//
|
//
|
||||||
|
@ -4694,14 +4754,16 @@ uint32_t Minidump::max_streams_ = 128;
|
||||||
unsigned int Minidump::max_string_length_ = 1024;
|
unsigned int Minidump::max_string_length_ = 1024;
|
||||||
|
|
||||||
|
|
||||||
Minidump::Minidump(const string& path)
|
Minidump::Minidump(const string& path, bool hexdump, unsigned int hexdump_width)
|
||||||
: header_(),
|
: header_(),
|
||||||
directory_(NULL),
|
directory_(NULL),
|
||||||
stream_map_(new MinidumpStreamMap()),
|
stream_map_(new MinidumpStreamMap()),
|
||||||
path_(path),
|
path_(path),
|
||||||
stream_(NULL),
|
stream_(NULL),
|
||||||
swap_(false),
|
swap_(false),
|
||||||
valid_(false) {
|
valid_(false),
|
||||||
|
hexdump_(hexdump),
|
||||||
|
hexdump_width_(hexdump_width) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Minidump::Minidump(istream& stream)
|
Minidump::Minidump(istream& stream)
|
||||||
|
|
|
@ -55,9 +55,11 @@ using google_breakpad::MinidumpBreakpadInfo;
|
||||||
|
|
||||||
struct Options {
|
struct Options {
|
||||||
Options()
|
Options()
|
||||||
: minidumpPath() {}
|
: minidumpPath(), hexdump(false), hexdump_width(hexdump_width) {}
|
||||||
|
|
||||||
string minidumpPath;
|
string minidumpPath;
|
||||||
|
bool hexdump;
|
||||||
|
unsigned int hexdump_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DumpRawStream(Minidump *minidump,
|
static void DumpRawStream(Minidump *minidump,
|
||||||
|
@ -99,8 +101,9 @@ static void DumpRawStream(Minidump *minidump,
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool PrintMinidumpDump(const string& minidump_file) {
|
static bool PrintMinidumpDump(const Options& options) {
|
||||||
Minidump minidump(minidump_file);
|
Minidump minidump(options.minidumpPath,
|
||||||
|
options.hexdump);
|
||||||
if (!minidump.Read()) {
|
if (!minidump.Read()) {
|
||||||
BPLOG(ERROR) << "minidump.Read() failed";
|
BPLOG(ERROR) << "minidump.Read() failed";
|
||||||
return false;
|
return false;
|
||||||
|
@ -218,6 +221,7 @@ Usage(int argc, const char *argv[], bool error) {
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" <minidump> should be a minidump.\n"
|
" <minidump> should be a minidump.\n"
|
||||||
|
" -x:\t Display memory in a hexdump like format\n"
|
||||||
" -h:\t Usage\n",
|
" -h:\t Usage\n",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
}
|
}
|
||||||
|
@ -227,8 +231,11 @@ static void
|
||||||
SetupOptions(int argc, const char *argv[], Options *options) {
|
SetupOptions(int argc, const char *argv[], Options *options) {
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
while ((ch = getopt(argc, (char * const *)argv, "h")) != -1) {
|
while ((ch = getopt(argc, (char * const *)argv, "xh")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
|
case 'x':
|
||||||
|
options->hexdump = true;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
Usage(argc, argv, false);
|
Usage(argc, argv, false);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -254,5 +261,5 @@ int main(int argc, const char *argv[]) {
|
||||||
Options options;
|
Options options;
|
||||||
BPLOG_INIT(&argc, &argv);
|
BPLOG_INIT(&argc, &argv);
|
||||||
SetupOptions(argc, argv, &options);
|
SetupOptions(argc, argv, &options);
|
||||||
return PrintMinidumpDump(options.minidumpPath) ? 0 : 1;
|
return PrintMinidumpDump(options) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue