From 309534f959c47b1518a1a01817ad7ab4ec20a12b Mon Sep 17 00:00:00 2001 From: Ziad Youssef Date: Wed, 15 Mar 2023 15:34:30 +0000 Subject: [PATCH] Add brief flag to minidump_stackwalk The added flag will print only one line per frame for the requesting thread (This is mostly the crashing thread). Refactor the code for printing the frame so it can be reused. Bug: 1374075 Change-Id: I8a1c8b1a09740fcaa23c3cc642468622ee64ea73 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/4339771 Reviewed-by: Joshua Peraza --- src/processor/minidump_stackwalk.cc | 10 ++++- src/processor/stackwalk_common.cc | 69 ++++++++++++++++++----------- src/processor/stackwalk_common.h | 1 + 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/processor/minidump_stackwalk.cc b/src/processor/minidump_stackwalk.cc index 5ff61b3c..08c30ed3 100644 --- a/src/processor/minidump_stackwalk.cc +++ b/src/processor/minidump_stackwalk.cc @@ -61,6 +61,7 @@ struct Options { bool machine_readable; bool output_stack_contents; bool output_requesting_thread_only; + bool brief; string minidump_file; std::vector symbol_paths; @@ -114,6 +115,8 @@ bool PrintMinidumpProcess(const Options& options) { if (options.machine_readable) { PrintProcessStateMachineReadable(process_state); + } else if (options.brief) { + PrintRequestingThreadBrief(process_state); } else { PrintProcessState(process_state, options.output_stack_contents, options.output_requesting_thread_only, &resolver); @@ -135,6 +138,7 @@ static void Usage(int argc, const char *argv[], bool error) { " -m Output in machine-readable format\n" " -s Output stack contents\n" " -c Output thread that causes crash or dump only\n", + " -b Brief of the thread that causes crash or dump\n", google_breakpad::BaseName(argv[0]).c_str()); } @@ -144,14 +148,18 @@ static void SetupOptions(int argc, const char *argv[], Options* options) { options->machine_readable = false; options->output_stack_contents = false; options->output_requesting_thread_only = false; + options->brief = false; - while ((ch = getopt(argc, (char * const*)argv, "chms")) != -1) { + while ((ch = getopt(argc, (char* const*)argv, "bchms")) != -1) { switch (ch) { case 'h': Usage(argc, argv, false); exit(0); break; + case 'b': + options->brief = true; + break; case 'c': options->output_requesting_thread_only = true; break; diff --git a/src/processor/stackwalk_common.cc b/src/processor/stackwalk_common.cc index 3a842959..889931ea 100644 --- a/src/processor/stackwalk_common.cc +++ b/src/processor/stackwalk_common.cc @@ -277,6 +277,33 @@ static void PrintStackContents(const string& indent, printf("\n"); } +static void PrintFrameHeader(const StackFrame* frame, int frame_index) { + printf("%2d ", frame_index); + + uint64_t instruction_address = frame->ReturnAddress(); + + if (frame->module) { + printf("%s", PathnameStripper::File(frame->module->code_file()).c_str()); + if (!frame->function_name.empty()) { + printf("!%s", frame->function_name.c_str()); + if (!frame->source_file_name.empty()) { + string source_file = PathnameStripper::File(frame->source_file_name); + printf(" [%s : %d + 0x%" PRIx64 "]", source_file.c_str(), + frame->source_line, + instruction_address - frame->source_line_base); + } else { + printf(" + 0x%" PRIx64, instruction_address - frame->function_base); + } + } else { + printf(" + 0x%" PRIx64, + instruction_address - frame->module->base_address()); + } + } else { + printf("0x%" PRIx64, instruction_address); + } + printf("\n "); +} + // PrintStack prints the call stack in |stack| to stdout, in a reasonably // useful form. Module, function, and source file names are displayed if // they are available. The code offset to the base code address of the @@ -298,31 +325,7 @@ static void PrintStack(const CallStack* stack, } for (int frame_index = 0; frame_index < frame_count; ++frame_index) { const StackFrame* frame = stack->frames()->at(frame_index); - printf("%2d ", frame_index); - - uint64_t instruction_address = frame->ReturnAddress(); - - if (frame->module) { - printf("%s", PathnameStripper::File(frame->module->code_file()).c_str()); - if (!frame->function_name.empty()) { - printf("!%s", frame->function_name.c_str()); - if (!frame->source_file_name.empty()) { - string source_file = PathnameStripper::File(frame->source_file_name); - printf(" [%s : %d + 0x%" PRIx64 "]", - source_file.c_str(), - frame->source_line, - instruction_address - frame->source_line_base); - } else { - printf(" + 0x%" PRIx64, instruction_address - frame->function_base); - } - } else { - printf(" + 0x%" PRIx64, - instruction_address - frame->module->base_address()); - } - } else { - printf("0x%" PRIx64, instruction_address); - } - printf("\n "); + PrintFrameHeader(frame, frame_index); // Inlined frames don't have registers info. if (frame->trust != StackFrameAMD64::FRAME_TRUST_INLINE) { @@ -1281,4 +1284,20 @@ void PrintProcessStateMachineReadable(const ProcessState& process_state) { } } +void PrintRequestingThreadBrief(const ProcessState& process_state) { + int requesting_thread = process_state.requesting_thread(); + if (requesting_thread == -1) { + printf(" \n"); + return; + } + + printf("Thread %d (%s)\n", requesting_thread, + process_state.crashed() ? "crashed" : "requested dump, did not crash"); + const CallStack* stack = process_state.threads()->at(requesting_thread); + int frame_count = stack->frames()->size(); + for (int frame_index = 0; frame_index < frame_count; ++frame_index) { + PrintFrameHeader(stack->frames()->at(frame_index), frame_index); + } +} + } // namespace google_breakpad diff --git a/src/processor/stackwalk_common.h b/src/processor/stackwalk_common.h index bb12b98f..3782f987 100644 --- a/src/processor/stackwalk_common.h +++ b/src/processor/stackwalk_common.h @@ -43,6 +43,7 @@ void PrintProcessState(const ProcessState& process_state, bool output_stack_contents, bool output_requesting_thread_only, SourceLineResolverInterface* resolver); +void PrintRequestingThreadBrief(const ProcessState& process_state); } // namespace google_breakpad