xref: /aosp_15_r20/external/google-breakpad/src/processor/stackwalk_common.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 // Copyright 2010 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //     * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 // stackwalk_common.cc: Module shared by the {micro,mini}dump_stackwalck
30 // executables to print the content of dumps (w/ stack traces) on the console.
31 //
32 // Author: Mark Mentovai
33 
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>  // Must come first
36 #endif
37 
38 #include "processor/stackwalk_common.h"
39 
40 #include <assert.h>
41 #include <stdlib.h>
42 #include <string.h>
43 
44 #include <string>
45 #include <vector>
46 
47 #include "common/stdio_wrapper.h"
48 #include "common/using_std_string.h"
49 #include "google_breakpad/processor/call_stack.h"
50 #include "google_breakpad/processor/code_module.h"
51 #include "google_breakpad/processor/code_modules.h"
52 #include "google_breakpad/processor/process_state.h"
53 #include "google_breakpad/processor/source_line_resolver_interface.h"
54 #include "google_breakpad/processor/stack_frame_cpu.h"
55 #include "processor/logging.h"
56 #include "processor/pathname_stripper.h"
57 
58 namespace google_breakpad {
59 
60 namespace {
61 
62 using std::vector;
63 using std::unique_ptr;
64 
65 // Separator character for machine readable output.
66 static const char kOutputSeparator = '|';
67 
68 // PrintRegister prints a register's name and value to stdout.  It will
69 // print four registers on a line.  For the first register in a set,
70 // pass 0 for |start_col|.  For registers in a set, pass the most recent
71 // return value of PrintRegister.
72 // The caller is responsible for printing the final newline after a set
73 // of registers is completely printed, regardless of the number of calls
74 // to PrintRegister.
75 static const int kMaxWidth = 80;  // optimize for an 80-column terminal
PrintRegister(const char * name,uint32_t value,int start_col)76 static int PrintRegister(const char* name, uint32_t value, int start_col) {
77   char buffer[64];
78   snprintf(buffer, sizeof(buffer), " %5s = 0x%08x", name, value);
79 
80   if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
81     start_col = 0;
82     printf("\n ");
83   }
84   fputs(buffer, stdout);
85 
86   return start_col + strlen(buffer);
87 }
88 
89 // PrintRegister64 does the same thing, but for 64-bit registers.
PrintRegister64(const char * name,uint64_t value,int start_col)90 static int PrintRegister64(const char* name, uint64_t value, int start_col) {
91   char buffer[64];
92   snprintf(buffer, sizeof(buffer), " %5s = 0x%016" PRIx64 , name, value);
93 
94   if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
95     start_col = 0;
96     printf("\n ");
97   }
98   fputs(buffer, stdout);
99 
100   return start_col + strlen(buffer);
101 }
102 
103 // StripSeparator takes a string |original| and returns a copy
104 // of the string with all occurences of |kOutputSeparator| removed.
StripSeparator(const string & original)105 static string StripSeparator(const string& original) {
106   string result = original;
107   string::size_type position = 0;
108   while ((position = result.find(kOutputSeparator, position)) != string::npos) {
109     result.erase(position, 1);
110   }
111   position = 0;
112   while ((position = result.find('\n', position)) != string::npos) {
113     result.erase(position, 1);
114   }
115   return result;
116 }
117 
118 // PrintStackContents prints the stack contents of the current frame to stdout.
PrintStackContents(const string & indent,const StackFrame * frame,const StackFrame * prev_frame,const string & cpu,const MemoryRegion * memory,const CodeModules * modules,SourceLineResolverInterface * resolver)119 static void PrintStackContents(const string& indent,
120                                const StackFrame* frame,
121                                const StackFrame* prev_frame,
122                                const string& cpu,
123                                const MemoryRegion* memory,
124                                const CodeModules* modules,
125                                SourceLineResolverInterface* resolver) {
126   // Find stack range.
127   int word_length = 0;
128   uint64_t stack_begin = 0, stack_end = 0;
129   if (cpu == "x86") {
130     word_length = 4;
131     const StackFrameX86* frame_x86 = static_cast<const StackFrameX86*>(frame);
132     const StackFrameX86* prev_frame_x86 =
133         static_cast<const StackFrameX86*>(prev_frame);
134     if ((frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP) &&
135         (prev_frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)) {
136       stack_begin = frame_x86->context.esp;
137       stack_end = prev_frame_x86->context.esp;
138     }
139   } else if (cpu == "amd64") {
140     word_length = 8;
141     const StackFrameAMD64* frame_amd64 =
142         static_cast<const StackFrameAMD64*>(frame);
143     const StackFrameAMD64* prev_frame_amd64 =
144         static_cast<const StackFrameAMD64*>(prev_frame);
145     if ((frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP) &&
146         (prev_frame_amd64->context_validity &
147          StackFrameAMD64::CONTEXT_VALID_RSP)) {
148       stack_begin = frame_amd64->context.rsp;
149       stack_end = prev_frame_amd64->context.rsp;
150     }
151   } else if (cpu == "arm") {
152     word_length = 4;
153     const StackFrameARM* frame_arm = static_cast<const StackFrameARM*>(frame);
154     const StackFrameARM* prev_frame_arm =
155         static_cast<const StackFrameARM*>(prev_frame);
156     if ((frame_arm->context_validity &
157          StackFrameARM::CONTEXT_VALID_SP) &&
158         (prev_frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
159       stack_begin = frame_arm->context.iregs[13];
160       stack_end = prev_frame_arm->context.iregs[13];
161     }
162   } else if (cpu == "arm64") {
163     word_length = 8;
164     const StackFrameARM64* frame_arm64 =
165         static_cast<const StackFrameARM64*>(frame);
166     const StackFrameARM64* prev_frame_arm64 =
167         static_cast<const StackFrameARM64*>(prev_frame);
168     if ((frame_arm64->context_validity &
169          StackFrameARM64::CONTEXT_VALID_SP) &&
170         (prev_frame_arm64->context_validity &
171          StackFrameARM64::CONTEXT_VALID_SP)) {
172       stack_begin = frame_arm64->context.iregs[31];
173       stack_end = prev_frame_arm64->context.iregs[31];
174     }
175   } else if (cpu == "riscv") {
176     word_length = 4;
177     const StackFrameRISCV* frame_riscv =
178         static_cast<const StackFrameRISCV*>(frame);
179     const StackFrameRISCV* prev_frame_riscv =
180         static_cast<const StackFrameRISCV*>(prev_frame);
181     if ((frame_riscv->context_validity &
182          StackFrameRISCV::CONTEXT_VALID_SP) &&
183         (prev_frame_riscv->context_validity &
184          StackFrameRISCV::CONTEXT_VALID_SP)) {
185       stack_begin = frame_riscv->context.sp;
186       stack_end = prev_frame_riscv->context.sp;
187     }
188   } else if (cpu == "riscv64") {
189     word_length = 8;
190     const StackFrameRISCV64* frame_riscv64 =
191         static_cast<const StackFrameRISCV64*>(frame);
192     const StackFrameRISCV64* prev_frame_riscv64 =
193         static_cast<const StackFrameRISCV64*>(prev_frame);
194     if ((frame_riscv64->context_validity &
195          StackFrameRISCV64::CONTEXT_VALID_SP) &&
196         (prev_frame_riscv64->context_validity &
197          StackFrameRISCV64::CONTEXT_VALID_SP)) {
198       stack_begin = frame_riscv64->context.sp;
199       stack_end = prev_frame_riscv64->context.sp;
200     }
201   }
202   if (!word_length || !stack_begin || !stack_end)
203     return;
204 
205   // Print stack contents.
206   printf("\n%sStack contents:", indent.c_str());
207   for(uint64_t address = stack_begin; address < stack_end; ) {
208     // Print the start address of this row.
209     if (word_length == 4)
210       printf("\n%s %08x", indent.c_str(), static_cast<uint32_t>(address));
211     else
212       printf("\n%s %016" PRIx64, indent.c_str(), address);
213 
214     // Print data in hex.
215     const int kBytesPerRow = 16;
216     string data_as_string;
217     for (int i = 0; i < kBytesPerRow; ++i, ++address) {
218       uint8_t value = 0;
219       if (address < stack_end &&
220           memory->GetMemoryAtAddress(address, &value)) {
221         printf(" %02x", value);
222         data_as_string.push_back(isprint(value) ? value : '.');
223       } else {
224         printf("   ");
225         data_as_string.push_back(' ');
226       }
227     }
228     // Print data as string.
229     printf("  %s", data_as_string.c_str());
230   }
231 
232   // Try to find instruction pointers from stack.
233   printf("\n%sPossible instruction pointers:\n", indent.c_str());
234   for (uint64_t address = stack_begin; address < stack_end;
235        address += word_length) {
236     StackFrame pointee_frame;
237 
238     // Read a word (possible instruction pointer) from stack.
239     if (word_length == 4) {
240       uint32_t data32 = 0;
241       memory->GetMemoryAtAddress(address, &data32);
242       pointee_frame.instruction = data32;
243     } else {
244       uint64_t data64 = 0;
245       memory->GetMemoryAtAddress(address, &data64);
246       pointee_frame.instruction = data64;
247     }
248     pointee_frame.module =
249         modules->GetModuleForAddress(pointee_frame.instruction);
250 
251     // Try to look up the function name.
252     std::deque<unique_ptr<StackFrame>> inlined_frames;
253     if (pointee_frame.module)
254       resolver->FillSourceLineInfo(&pointee_frame, &inlined_frames);
255 
256     // Print function name.
257     auto print_function_name = [&](StackFrame* frame) {
258       if (!frame->function_name.empty()) {
259         if (word_length == 4) {
260           printf("%s *(0x%08x) = 0x%08x", indent.c_str(),
261                  static_cast<uint32_t>(address),
262                  static_cast<uint32_t>(frame->instruction));
263         } else {
264           printf("%s *(0x%016" PRIx64 ") = 0x%016" PRIx64, indent.c_str(),
265                  address, frame->instruction);
266         }
267         printf(
268             " <%s> [%s : %d + 0x%" PRIx64 "]\n", frame->function_name.c_str(),
269             PathnameStripper::File(frame->source_file_name).c_str(),
270             frame->source_line, frame->instruction - frame->source_line_base);
271       }
272     };
273     print_function_name(&pointee_frame);
274     for (unique_ptr<StackFrame> &frame : inlined_frames)
275       print_function_name(frame.get());
276   }
277   printf("\n");
278 }
279 
PrintFrameHeader(const StackFrame * frame,int frame_index)280 static void PrintFrameHeader(const StackFrame* frame, int frame_index) {
281   printf("%2d  ", frame_index);
282 
283   uint64_t instruction_address = frame->ReturnAddress();
284 
285   if (frame->module) {
286     printf("%s", PathnameStripper::File(frame->module->code_file()).c_str());
287     if (!frame->function_name.empty()) {
288       printf("!%s", frame->function_name.c_str());
289       if (!frame->source_file_name.empty()) {
290         string source_file = PathnameStripper::File(frame->source_file_name);
291         printf(" [%s : %d + 0x%" PRIx64 "]", source_file.c_str(),
292                frame->source_line,
293                instruction_address - frame->source_line_base);
294       } else {
295         printf(" + 0x%" PRIx64, instruction_address - frame->function_base);
296       }
297     } else {
298       printf(" + 0x%" PRIx64,
299              instruction_address - frame->module->base_address());
300     }
301   } else {
302     printf("0x%" PRIx64, instruction_address);
303   }
304 }
305 
306 // PrintStack prints the call stack in |stack| to stdout, in a reasonably
307 // useful form.  Module, function, and source file names are displayed if
308 // they are available.  The code offset to the base code address of the
309 // source line, function, or module is printed, preferring them in that
310 // order.  If no source line, function, or module information is available,
311 // an absolute code offset is printed.
312 //
313 // If |cpu| is a recognized CPU name, relevant register state for each stack
314 // frame printed is also output, if available.
PrintStack(const CallStack * stack,const string & cpu,bool output_stack_contents,const MemoryRegion * memory,const CodeModules * modules,SourceLineResolverInterface * resolver)315 static void PrintStack(const CallStack* stack,
316                        const string& cpu,
317                        bool output_stack_contents,
318                        const MemoryRegion* memory,
319                        const CodeModules* modules,
320                        SourceLineResolverInterface* resolver) {
321   int frame_count = stack->frames()->size();
322   if (frame_count == 0) {
323     printf(" <no frames>\n");
324   }
325   for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
326     const StackFrame* frame = stack->frames()->at(frame_index);
327     PrintFrameHeader(frame, frame_index);
328     printf("\n ");
329 
330     // Inlined frames don't have registers info.
331     if (frame->trust != StackFrameAMD64::FRAME_TRUST_INLINE) {
332       int sequence = 0;
333       if (cpu == "x86") {
334         const StackFrameX86* frame_x86 =
335             reinterpret_cast<const StackFrameX86*>(frame);
336 
337         if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP)
338           sequence = PrintRegister("eip", frame_x86->context.eip, sequence);
339         if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)
340           sequence = PrintRegister("esp", frame_x86->context.esp, sequence);
341         if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP)
342           sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence);
343         if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX)
344           sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence);
345         if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI)
346           sequence = PrintRegister("esi", frame_x86->context.esi, sequence);
347         if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI)
348           sequence = PrintRegister("edi", frame_x86->context.edi, sequence);
349         if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) {
350           sequence = PrintRegister("eax", frame_x86->context.eax, sequence);
351           sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence);
352           sequence = PrintRegister("edx", frame_x86->context.edx, sequence);
353           sequence = PrintRegister("efl", frame_x86->context.eflags, sequence);
354         }
355       } else if (cpu == "ppc") {
356         const StackFramePPC* frame_ppc =
357             reinterpret_cast<const StackFramePPC*>(frame);
358 
359         if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0)
360           sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
361         if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1)
362           sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence);
363       } else if (cpu == "amd64") {
364         const StackFrameAMD64* frame_amd64 =
365             reinterpret_cast<const StackFrameAMD64*>(frame);
366 
367         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RAX)
368           sequence = PrintRegister64("rax", frame_amd64->context.rax, sequence);
369         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDX)
370           sequence = PrintRegister64("rdx", frame_amd64->context.rdx, sequence);
371         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RCX)
372           sequence = PrintRegister64("rcx", frame_amd64->context.rcx, sequence);
373         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBX)
374           sequence = PrintRegister64("rbx", frame_amd64->context.rbx, sequence);
375         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSI)
376           sequence = PrintRegister64("rsi", frame_amd64->context.rsi, sequence);
377         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDI)
378           sequence = PrintRegister64("rdi", frame_amd64->context.rdi, sequence);
379         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP)
380           sequence = PrintRegister64("rbp", frame_amd64->context.rbp, sequence);
381         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP)
382           sequence = PrintRegister64("rsp", frame_amd64->context.rsp, sequence);
383         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R8)
384           sequence = PrintRegister64("r8", frame_amd64->context.r8, sequence);
385         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R9)
386           sequence = PrintRegister64("r9", frame_amd64->context.r9, sequence);
387         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R10)
388           sequence = PrintRegister64("r10", frame_amd64->context.r10, sequence);
389         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R11)
390           sequence = PrintRegister64("r11", frame_amd64->context.r11, sequence);
391         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R12)
392           sequence = PrintRegister64("r12", frame_amd64->context.r12, sequence);
393         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R13)
394           sequence = PrintRegister64("r13", frame_amd64->context.r13, sequence);
395         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R14)
396           sequence = PrintRegister64("r14", frame_amd64->context.r14, sequence);
397         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R15)
398           sequence = PrintRegister64("r15", frame_amd64->context.r15, sequence);
399         if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RIP)
400           sequence = PrintRegister64("rip", frame_amd64->context.rip, sequence);
401       } else if (cpu == "sparc") {
402         const StackFrameSPARC* frame_sparc =
403             reinterpret_cast<const StackFrameSPARC*>(frame);
404 
405         if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_SP)
406           sequence =
407               PrintRegister("sp", frame_sparc->context.g_r[14], sequence);
408         if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_FP)
409           sequence =
410               PrintRegister("fp", frame_sparc->context.g_r[30], sequence);
411         if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_PC)
412           sequence = PrintRegister("pc", frame_sparc->context.pc, sequence);
413       } else if (cpu == "arm") {
414         const StackFrameARM* frame_arm =
415             reinterpret_cast<const StackFrameARM*>(frame);
416 
417         // Argument registers (caller-saves), which will likely only be valid
418         // for the youngest frame.
419         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R0)
420           sequence = PrintRegister("r0", frame_arm->context.iregs[0], sequence);
421         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R1)
422           sequence = PrintRegister("r1", frame_arm->context.iregs[1], sequence);
423         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R2)
424           sequence = PrintRegister("r2", frame_arm->context.iregs[2], sequence);
425         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R3)
426           sequence = PrintRegister("r3", frame_arm->context.iregs[3], sequence);
427 
428         // General-purpose callee-saves registers.
429         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R4)
430           sequence = PrintRegister("r4", frame_arm->context.iregs[4], sequence);
431         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R5)
432           sequence = PrintRegister("r5", frame_arm->context.iregs[5], sequence);
433         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R6)
434           sequence = PrintRegister("r6", frame_arm->context.iregs[6], sequence);
435         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R7)
436           sequence = PrintRegister("r7", frame_arm->context.iregs[7], sequence);
437         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R8)
438           sequence = PrintRegister("r8", frame_arm->context.iregs[8], sequence);
439         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R9)
440           sequence = PrintRegister("r9", frame_arm->context.iregs[9], sequence);
441         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R10)
442           sequence =
443               PrintRegister("r10", frame_arm->context.iregs[10], sequence);
444         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R12)
445           sequence =
446               PrintRegister("r12", frame_arm->context.iregs[12], sequence);
447 
448         // Registers with a dedicated or conventional purpose.
449         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_FP)
450           sequence =
451               PrintRegister("fp", frame_arm->context.iregs[11], sequence);
452         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP)
453           sequence =
454               PrintRegister("sp", frame_arm->context.iregs[13], sequence);
455         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_LR)
456           sequence =
457               PrintRegister("lr", frame_arm->context.iregs[14], sequence);
458         if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_PC)
459           sequence =
460               PrintRegister("pc", frame_arm->context.iregs[15], sequence);
461       } else if (cpu == "arm64") {
462         const StackFrameARM64* frame_arm64 =
463             reinterpret_cast<const StackFrameARM64*>(frame);
464 
465         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X0) {
466           sequence =
467               PrintRegister64("x0", frame_arm64->context.iregs[0], sequence);
468         }
469         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X1) {
470           sequence =
471               PrintRegister64("x1", frame_arm64->context.iregs[1], sequence);
472         }
473         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X2) {
474           sequence =
475               PrintRegister64("x2", frame_arm64->context.iregs[2], sequence);
476         }
477         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X3) {
478           sequence =
479               PrintRegister64("x3", frame_arm64->context.iregs[3], sequence);
480         }
481         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X4) {
482           sequence =
483               PrintRegister64("x4", frame_arm64->context.iregs[4], sequence);
484         }
485         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X5) {
486           sequence =
487               PrintRegister64("x5", frame_arm64->context.iregs[5], sequence);
488         }
489         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X6) {
490           sequence =
491               PrintRegister64("x6", frame_arm64->context.iregs[6], sequence);
492         }
493         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X7) {
494           sequence =
495               PrintRegister64("x7", frame_arm64->context.iregs[7], sequence);
496         }
497         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X8) {
498           sequence =
499               PrintRegister64("x8", frame_arm64->context.iregs[8], sequence);
500         }
501         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X9) {
502           sequence =
503               PrintRegister64("x9", frame_arm64->context.iregs[9], sequence);
504         }
505         if (frame_arm64->context_validity &
506             StackFrameARM64::CONTEXT_VALID_X10) {
507           sequence =
508               PrintRegister64("x10", frame_arm64->context.iregs[10], sequence);
509         }
510         if (frame_arm64->context_validity &
511             StackFrameARM64::CONTEXT_VALID_X11) {
512           sequence =
513               PrintRegister64("x11", frame_arm64->context.iregs[11], sequence);
514         }
515         if (frame_arm64->context_validity &
516             StackFrameARM64::CONTEXT_VALID_X12) {
517           sequence =
518               PrintRegister64("x12", frame_arm64->context.iregs[12], sequence);
519         }
520         if (frame_arm64->context_validity &
521             StackFrameARM64::CONTEXT_VALID_X13) {
522           sequence =
523               PrintRegister64("x13", frame_arm64->context.iregs[13], sequence);
524         }
525         if (frame_arm64->context_validity &
526             StackFrameARM64::CONTEXT_VALID_X14) {
527           sequence =
528               PrintRegister64("x14", frame_arm64->context.iregs[14], sequence);
529         }
530         if (frame_arm64->context_validity &
531             StackFrameARM64::CONTEXT_VALID_X15) {
532           sequence =
533               PrintRegister64("x15", frame_arm64->context.iregs[15], sequence);
534         }
535         if (frame_arm64->context_validity &
536             StackFrameARM64::CONTEXT_VALID_X16) {
537           sequence =
538               PrintRegister64("x16", frame_arm64->context.iregs[16], sequence);
539         }
540         if (frame_arm64->context_validity &
541             StackFrameARM64::CONTEXT_VALID_X17) {
542           sequence =
543               PrintRegister64("x17", frame_arm64->context.iregs[17], sequence);
544         }
545         if (frame_arm64->context_validity &
546             StackFrameARM64::CONTEXT_VALID_X18) {
547           sequence =
548               PrintRegister64("x18", frame_arm64->context.iregs[18], sequence);
549         }
550         if (frame_arm64->context_validity &
551             StackFrameARM64::CONTEXT_VALID_X19) {
552           sequence =
553               PrintRegister64("x19", frame_arm64->context.iregs[19], sequence);
554         }
555         if (frame_arm64->context_validity &
556             StackFrameARM64::CONTEXT_VALID_X20) {
557           sequence =
558               PrintRegister64("x20", frame_arm64->context.iregs[20], sequence);
559         }
560         if (frame_arm64->context_validity &
561             StackFrameARM64::CONTEXT_VALID_X21) {
562           sequence =
563               PrintRegister64("x21", frame_arm64->context.iregs[21], sequence);
564         }
565         if (frame_arm64->context_validity &
566             StackFrameARM64::CONTEXT_VALID_X22) {
567           sequence =
568               PrintRegister64("x22", frame_arm64->context.iregs[22], sequence);
569         }
570         if (frame_arm64->context_validity &
571             StackFrameARM64::CONTEXT_VALID_X23) {
572           sequence =
573               PrintRegister64("x23", frame_arm64->context.iregs[23], sequence);
574         }
575         if (frame_arm64->context_validity &
576             StackFrameARM64::CONTEXT_VALID_X24) {
577           sequence =
578               PrintRegister64("x24", frame_arm64->context.iregs[24], sequence);
579         }
580         if (frame_arm64->context_validity &
581             StackFrameARM64::CONTEXT_VALID_X25) {
582           sequence =
583               PrintRegister64("x25", frame_arm64->context.iregs[25], sequence);
584         }
585         if (frame_arm64->context_validity &
586             StackFrameARM64::CONTEXT_VALID_X26) {
587           sequence =
588               PrintRegister64("x26", frame_arm64->context.iregs[26], sequence);
589         }
590         if (frame_arm64->context_validity &
591             StackFrameARM64::CONTEXT_VALID_X27) {
592           sequence =
593               PrintRegister64("x27", frame_arm64->context.iregs[27], sequence);
594         }
595         if (frame_arm64->context_validity &
596             StackFrameARM64::CONTEXT_VALID_X28) {
597           sequence =
598               PrintRegister64("x28", frame_arm64->context.iregs[28], sequence);
599         }
600 
601         // Registers with a dedicated or conventional purpose.
602         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_FP) {
603           sequence =
604               PrintRegister64("fp", frame_arm64->context.iregs[29], sequence);
605         }
606         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_LR) {
607           sequence =
608               PrintRegister64("lr", frame_arm64->context.iregs[30], sequence);
609         }
610         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_SP) {
611           sequence =
612               PrintRegister64("sp", frame_arm64->context.iregs[31], sequence);
613         }
614         if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_PC) {
615           sequence =
616               PrintRegister64("pc", frame_arm64->context.iregs[32], sequence);
617         }
618       } else if ((cpu == "mips") || (cpu == "mips64")) {
619         const StackFrameMIPS* frame_mips =
620             reinterpret_cast<const StackFrameMIPS*>(frame);
621 
622         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_GP)
623           sequence = PrintRegister64(
624               "gp", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_GP],
625               sequence);
626         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_SP)
627           sequence = PrintRegister64(
628               "sp", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_SP],
629               sequence);
630         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_FP)
631           sequence = PrintRegister64(
632               "fp", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_FP],
633               sequence);
634         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_RA)
635           sequence = PrintRegister64(
636               "ra", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_RA],
637               sequence);
638         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_PC)
639           sequence = PrintRegister64("pc", frame_mips->context.epc, sequence);
640 
641         // Save registers s0-s7
642         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S0)
643           sequence = PrintRegister64(
644               "s0", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S0],
645               sequence);
646         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S1)
647           sequence = PrintRegister64(
648               "s1", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S1],
649               sequence);
650         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S2)
651           sequence = PrintRegister64(
652               "s2", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S2],
653               sequence);
654         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S3)
655           sequence = PrintRegister64(
656               "s3", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S3],
657               sequence);
658         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S4)
659           sequence = PrintRegister64(
660               "s4", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S4],
661               sequence);
662         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S5)
663           sequence = PrintRegister64(
664               "s5", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S5],
665               sequence);
666         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S6)
667           sequence = PrintRegister64(
668               "s6", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S6],
669               sequence);
670         if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S7)
671           sequence = PrintRegister64(
672               "s7", frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S7],
673               sequence);
674       } else if (cpu == "riscv") {
675         const StackFrameRISCV* frame_riscv =
676             reinterpret_cast<const StackFrameRISCV*>(frame);
677 
678         if (frame_riscv->context_validity &
679             StackFrameRISCV::CONTEXT_VALID_PC)
680           sequence = PrintRegister(
681               "pc", frame_riscv->context.pc, sequence);
682         if (frame_riscv->context_validity &
683             StackFrameRISCV::CONTEXT_VALID_RA)
684           sequence = PrintRegister(
685               "ra", frame_riscv->context.ra, sequence);
686         if (frame_riscv->context_validity &
687             StackFrameRISCV::CONTEXT_VALID_SP)
688           sequence = PrintRegister(
689               "sp", frame_riscv->context.sp, sequence);
690         if (frame_riscv->context_validity &
691             StackFrameRISCV::CONTEXT_VALID_GP)
692           sequence = PrintRegister(
693               "gp", frame_riscv->context.gp, sequence);
694         if (frame_riscv->context_validity &
695             StackFrameRISCV::CONTEXT_VALID_TP)
696           sequence = PrintRegister(
697               "tp", frame_riscv->context.tp, sequence);
698         if (frame_riscv->context_validity &
699             StackFrameRISCV::CONTEXT_VALID_T0)
700           sequence = PrintRegister(
701               "t0", frame_riscv->context.t0, sequence);
702         if (frame_riscv->context_validity &
703             StackFrameRISCV::CONTEXT_VALID_T1)
704           sequence = PrintRegister(
705               "t1", frame_riscv->context.t1, sequence);
706         if (frame_riscv->context_validity &
707             StackFrameRISCV::CONTEXT_VALID_T2)
708           sequence = PrintRegister(
709               "t2", frame_riscv->context.t2, sequence);
710         if (frame_riscv->context_validity &
711             StackFrameRISCV::CONTEXT_VALID_S0)
712           sequence = PrintRegister(
713               "s0", frame_riscv->context.s0, sequence);
714         if (frame_riscv->context_validity &
715             StackFrameRISCV::CONTEXT_VALID_S1)
716           sequence = PrintRegister(
717               "s1", frame_riscv->context.s1, sequence);
718         if (frame_riscv->context_validity &
719             StackFrameRISCV::CONTEXT_VALID_A0)
720           sequence = PrintRegister(
721               "a0", frame_riscv->context.a0, sequence);
722         if (frame_riscv->context_validity &
723             StackFrameRISCV::CONTEXT_VALID_A1)
724           sequence = PrintRegister(
725               "a1", frame_riscv->context.a1, sequence);
726         if (frame_riscv->context_validity &
727             StackFrameRISCV::CONTEXT_VALID_A2)
728           sequence = PrintRegister(
729               "a2", frame_riscv->context.a2, sequence);
730         if (frame_riscv->context_validity &
731             StackFrameRISCV::CONTEXT_VALID_A3)
732           sequence = PrintRegister(
733               "a3", frame_riscv->context.a3, sequence);
734         if (frame_riscv->context_validity &
735             StackFrameRISCV::CONTEXT_VALID_A4)
736           sequence = PrintRegister(
737               "a4", frame_riscv->context.a4, sequence);
738         if (frame_riscv->context_validity &
739             StackFrameRISCV::CONTEXT_VALID_A5)
740           sequence = PrintRegister(
741               "a5", frame_riscv->context.a5, sequence);
742         if (frame_riscv->context_validity &
743             StackFrameRISCV::CONTEXT_VALID_A6)
744           sequence = PrintRegister(
745               "a6", frame_riscv->context.a6, sequence);
746         if (frame_riscv->context_validity &
747             StackFrameRISCV::CONTEXT_VALID_A7)
748           sequence = PrintRegister(
749               "a7", frame_riscv->context.a7, sequence);
750         if (frame_riscv->context_validity &
751             StackFrameRISCV::CONTEXT_VALID_S2)
752           sequence = PrintRegister(
753               "s2", frame_riscv->context.s2, sequence);
754         if (frame_riscv->context_validity &
755             StackFrameRISCV::CONTEXT_VALID_S3)
756           sequence = PrintRegister(
757               "s3", frame_riscv->context.s3, sequence);
758         if (frame_riscv->context_validity &
759             StackFrameRISCV::CONTEXT_VALID_S4)
760           sequence = PrintRegister(
761               "s4", frame_riscv->context.s4, sequence);
762         if (frame_riscv->context_validity &
763             StackFrameRISCV::CONTEXT_VALID_S5)
764           sequence = PrintRegister(
765               "s5", frame_riscv->context.s5, sequence);
766         if (frame_riscv->context_validity &
767             StackFrameRISCV::CONTEXT_VALID_S6)
768           sequence = PrintRegister(
769               "s6", frame_riscv->context.s6, sequence);
770         if (frame_riscv->context_validity &
771             StackFrameRISCV::CONTEXT_VALID_S7)
772           sequence = PrintRegister(
773               "s7", frame_riscv->context.s7, sequence);
774         if (frame_riscv->context_validity &
775             StackFrameRISCV::CONTEXT_VALID_S8)
776           sequence = PrintRegister(
777               "s8", frame_riscv->context.s8, sequence);
778         if (frame_riscv->context_validity &
779             StackFrameRISCV::CONTEXT_VALID_S9)
780           sequence = PrintRegister(
781               "s9", frame_riscv->context.s9, sequence);
782         if (frame_riscv->context_validity &
783             StackFrameRISCV::CONTEXT_VALID_S10)
784           sequence = PrintRegister(
785               "s10", frame_riscv->context.s10, sequence);
786         if (frame_riscv->context_validity &
787             StackFrameRISCV::CONTEXT_VALID_S11)
788           sequence = PrintRegister(
789               "s11", frame_riscv->context.s11, sequence);
790         if (frame_riscv->context_validity &
791             StackFrameRISCV::CONTEXT_VALID_T3)
792           sequence = PrintRegister(
793               "t3", frame_riscv->context.t3, sequence);
794         if (frame_riscv->context_validity &
795             StackFrameRISCV::CONTEXT_VALID_T4)
796           sequence = PrintRegister(
797               "t4", frame_riscv->context.t4, sequence);
798         if (frame_riscv->context_validity &
799             StackFrameRISCV::CONTEXT_VALID_T5)
800           sequence = PrintRegister(
801               "t5", frame_riscv->context.t5, sequence);
802         if (frame_riscv->context_validity &
803             StackFrameRISCV::CONTEXT_VALID_T6)
804           sequence = PrintRegister(
805               "t6", frame_riscv->context.t6, sequence);
806       } else if (cpu == "riscv64") {
807         const StackFrameRISCV64* frame_riscv64 =
808             reinterpret_cast<const StackFrameRISCV64*>(frame);
809 
810         if (frame_riscv64->context_validity &
811             StackFrameRISCV64::CONTEXT_VALID_PC)
812           sequence = PrintRegister64(
813               "pc", frame_riscv64->context.pc, sequence);
814         if (frame_riscv64->context_validity &
815             StackFrameRISCV64::CONTEXT_VALID_RA)
816           sequence = PrintRegister64(
817               "ra", frame_riscv64->context.ra, sequence);
818         if (frame_riscv64->context_validity &
819             StackFrameRISCV64::CONTEXT_VALID_SP)
820           sequence = PrintRegister64(
821               "sp", frame_riscv64->context.sp, sequence);
822         if (frame_riscv64->context_validity &
823             StackFrameRISCV64::CONTEXT_VALID_GP)
824           sequence = PrintRegister64(
825               "gp", frame_riscv64->context.gp, sequence);
826         if (frame_riscv64->context_validity &
827             StackFrameRISCV64::CONTEXT_VALID_TP)
828           sequence = PrintRegister64(
829               "tp", frame_riscv64->context.tp, sequence);
830         if (frame_riscv64->context_validity &
831             StackFrameRISCV64::CONTEXT_VALID_T0)
832           sequence = PrintRegister64(
833               "t0", frame_riscv64->context.t0, sequence);
834         if (frame_riscv64->context_validity &
835             StackFrameRISCV64::CONTEXT_VALID_T1)
836           sequence = PrintRegister64(
837               "t1", frame_riscv64->context.t1, sequence);
838         if (frame_riscv64->context_validity &
839             StackFrameRISCV64::CONTEXT_VALID_T2)
840           sequence = PrintRegister64(
841               "t2", frame_riscv64->context.t2, sequence);
842         if (frame_riscv64->context_validity &
843             StackFrameRISCV64::CONTEXT_VALID_S0)
844           sequence = PrintRegister64(
845               "s0", frame_riscv64->context.s0, sequence);
846         if (frame_riscv64->context_validity &
847             StackFrameRISCV64::CONTEXT_VALID_S1)
848           sequence = PrintRegister64(
849               "s1", frame_riscv64->context.s1, sequence);
850         if (frame_riscv64->context_validity &
851             StackFrameRISCV64::CONTEXT_VALID_A0)
852           sequence = PrintRegister64(
853               "a0", frame_riscv64->context.a0, sequence);
854         if (frame_riscv64->context_validity &
855             StackFrameRISCV64::CONTEXT_VALID_A1)
856           sequence = PrintRegister64(
857               "a1", frame_riscv64->context.a1, sequence);
858         if (frame_riscv64->context_validity &
859             StackFrameRISCV64::CONTEXT_VALID_A2)
860           sequence = PrintRegister64(
861               "a2", frame_riscv64->context.a2, sequence);
862         if (frame_riscv64->context_validity &
863             StackFrameRISCV64::CONTEXT_VALID_A3)
864           sequence = PrintRegister64(
865               "a3", frame_riscv64->context.a3, sequence);
866         if (frame_riscv64->context_validity &
867             StackFrameRISCV64::CONTEXT_VALID_A4)
868           sequence = PrintRegister64(
869               "a4", frame_riscv64->context.a4, sequence);
870         if (frame_riscv64->context_validity &
871             StackFrameRISCV64::CONTEXT_VALID_A5)
872           sequence = PrintRegister64(
873               "a5", frame_riscv64->context.a5, sequence);
874         if (frame_riscv64->context_validity &
875             StackFrameRISCV64::CONTEXT_VALID_A6)
876           sequence = PrintRegister64(
877               "a6", frame_riscv64->context.a6, sequence);
878         if (frame_riscv64->context_validity &
879             StackFrameRISCV64::CONTEXT_VALID_A7)
880           sequence = PrintRegister64(
881               "a7", frame_riscv64->context.a7, sequence);
882         if (frame_riscv64->context_validity &
883             StackFrameRISCV64::CONTEXT_VALID_S2)
884           sequence = PrintRegister64(
885               "s2", frame_riscv64->context.s2, sequence);
886         if (frame_riscv64->context_validity &
887             StackFrameRISCV64::CONTEXT_VALID_S3)
888           sequence = PrintRegister64(
889               "s3", frame_riscv64->context.s3, sequence);
890         if (frame_riscv64->context_validity &
891             StackFrameRISCV64::CONTEXT_VALID_S4)
892           sequence = PrintRegister64(
893               "s4", frame_riscv64->context.s4, sequence);
894         if (frame_riscv64->context_validity &
895             StackFrameRISCV64::CONTEXT_VALID_S5)
896           sequence = PrintRegister64(
897               "s5", frame_riscv64->context.s5, sequence);
898         if (frame_riscv64->context_validity &
899             StackFrameRISCV64::CONTEXT_VALID_S6)
900           sequence = PrintRegister64(
901               "s6", frame_riscv64->context.s6, sequence);
902         if (frame_riscv64->context_validity &
903             StackFrameRISCV64::CONTEXT_VALID_S7)
904           sequence = PrintRegister64(
905               "s7", frame_riscv64->context.s7, sequence);
906         if (frame_riscv64->context_validity &
907             StackFrameRISCV64::CONTEXT_VALID_S8)
908           sequence = PrintRegister64(
909               "s8", frame_riscv64->context.s8, sequence);
910         if (frame_riscv64->context_validity &
911             StackFrameRISCV64::CONTEXT_VALID_S9)
912           sequence = PrintRegister64(
913               "s9", frame_riscv64->context.s9, sequence);
914         if (frame_riscv64->context_validity &
915             StackFrameRISCV64::CONTEXT_VALID_S10)
916           sequence = PrintRegister64(
917               "s10", frame_riscv64->context.s10, sequence);
918         if (frame_riscv64->context_validity &
919             StackFrameRISCV64::CONTEXT_VALID_S11)
920           sequence = PrintRegister64(
921               "s11", frame_riscv64->context.s11, sequence);
922         if (frame_riscv64->context_validity &
923             StackFrameRISCV64::CONTEXT_VALID_T3)
924           sequence = PrintRegister64(
925               "t3", frame_riscv64->context.t3, sequence);
926         if (frame_riscv64->context_validity &
927             StackFrameRISCV64::CONTEXT_VALID_T4)
928           sequence = PrintRegister64(
929               "t4", frame_riscv64->context.t4, sequence);
930         if (frame_riscv64->context_validity &
931             StackFrameRISCV64::CONTEXT_VALID_T5)
932           sequence = PrintRegister64(
933               "t5", frame_riscv64->context.t5, sequence);
934         if (frame_riscv64->context_validity &
935             StackFrameRISCV64::CONTEXT_VALID_T6)
936           sequence = PrintRegister64(
937               "t6", frame_riscv64->context.t6, sequence);
938       }
939     }
940     printf("\n    Found by: %s\n", frame->trust_description().c_str());
941 
942     // Print stack contents.
943     if (output_stack_contents && frame_index + 1 < frame_count) {
944       const string indent("    ");
945       PrintStackContents(indent, frame, stack->frames()->at(frame_index + 1),
946                          cpu, memory, modules, resolver);
947     }
948   }
949 }
950 
951 // PrintStackMachineReadable prints the call stack in |stack| to stdout,
952 // in the following machine readable pipe-delimited text format:
953 // thread number|frame number|module|function|source file|line|offset
954 //
955 // Module, function, source file, and source line may all be empty
956 // depending on availability.  The code offset follows the same rules as
957 // PrintStack above.
PrintStackMachineReadable(int thread_num,const CallStack * stack)958 static void PrintStackMachineReadable(int thread_num, const CallStack* stack) {
959   int frame_count = stack->frames()->size();
960   for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
961     const StackFrame* frame = stack->frames()->at(frame_index);
962     printf("%d%c%d%c", thread_num, kOutputSeparator, frame_index,
963            kOutputSeparator);
964 
965     uint64_t instruction_address = frame->ReturnAddress();
966 
967     if (frame->module) {
968       assert(!frame->module->code_file().empty());
969       printf("%s", StripSeparator(PathnameStripper::File(
970                      frame->module->code_file())).c_str());
971       if (!frame->function_name.empty()) {
972         printf("%c%s", kOutputSeparator,
973                StripSeparator(frame->function_name).c_str());
974         if (!frame->source_file_name.empty()) {
975           printf("%c%s%c%d%c0x%" PRIx64,
976                  kOutputSeparator,
977                  StripSeparator(frame->source_file_name).c_str(),
978                  kOutputSeparator,
979                  frame->source_line,
980                  kOutputSeparator,
981                  instruction_address - frame->source_line_base);
982         } else {
983           printf("%c%c%c0x%" PRIx64,
984                  kOutputSeparator,  // empty source file
985                  kOutputSeparator,  // empty source line
986                  kOutputSeparator,
987                  instruction_address - frame->function_base);
988         }
989       } else {
990         printf("%c%c%c%c0x%" PRIx64,
991                kOutputSeparator,  // empty function name
992                kOutputSeparator,  // empty source file
993                kOutputSeparator,  // empty source line
994                kOutputSeparator,
995                instruction_address - frame->module->base_address());
996       }
997     } else {
998       // the printf before this prints a trailing separator for module name
999       printf("%c%c%c%c0x%" PRIx64,
1000              kOutputSeparator,  // empty function name
1001              kOutputSeparator,  // empty source file
1002              kOutputSeparator,  // empty source line
1003              kOutputSeparator,
1004              instruction_address);
1005     }
1006     printf("\n");
1007   }
1008 }
1009 
1010 // ContainsModule checks whether a given |module| is in the vector
1011 // |modules_without_symbols|.
ContainsModule(const vector<const CodeModule * > * modules,const CodeModule * module)1012 static bool ContainsModule(
1013     const vector<const CodeModule*>* modules,
1014     const CodeModule* module) {
1015   assert(modules);
1016   assert(module);
1017   vector<const CodeModule*>::const_iterator iter;
1018   for (iter = modules->begin(); iter != modules->end(); ++iter) {
1019     if (module->debug_file().compare((*iter)->debug_file()) == 0 &&
1020         module->debug_identifier().compare((*iter)->debug_identifier()) == 0) {
1021       return true;
1022     }
1023   }
1024   return false;
1025 }
1026 
1027 // PrintModule prints a single |module| to stdout.
1028 // |modules_without_symbols| should contain the list of modules that were
1029 // confirmed to be missing their symbols during the stack walk.
PrintModule(const CodeModule * module,const vector<const CodeModule * > * modules_without_symbols,const vector<const CodeModule * > * modules_with_corrupt_symbols,uint64_t main_address)1030 static void PrintModule(
1031     const CodeModule* module,
1032     const vector<const CodeModule*>* modules_without_symbols,
1033     const vector<const CodeModule*>* modules_with_corrupt_symbols,
1034     uint64_t main_address) {
1035   string symbol_issues;
1036   if (ContainsModule(modules_without_symbols, module)) {
1037     symbol_issues = "  (WARNING: No symbols, " +
1038         PathnameStripper::File(module->debug_file()) + ", " +
1039         module->debug_identifier() + ")";
1040   } else if (ContainsModule(modules_with_corrupt_symbols, module)) {
1041     symbol_issues = "  (WARNING: Corrupt symbols, " +
1042         PathnameStripper::File(module->debug_file()) + ", " +
1043         module->debug_identifier() + ")";
1044   }
1045   uint64_t base_address = module->base_address();
1046   printf("0x%08" PRIx64 " - 0x%08" PRIx64 "  %s  %s%s%s\n",
1047          base_address, base_address + module->size() - 1,
1048          PathnameStripper::File(module->code_file()).c_str(),
1049          module->version().empty() ? "???" : module->version().c_str(),
1050          main_address != 0 && base_address == main_address ? "  (main)" : "",
1051          symbol_issues.c_str());
1052 }
1053 
1054 // PrintModules prints the list of all loaded |modules| to stdout.
1055 // |modules_without_symbols| should contain the list of modules that were
1056 // confirmed to be missing their symbols during the stack walk.
PrintModules(const CodeModules * modules,const vector<const CodeModule * > * modules_without_symbols,const vector<const CodeModule * > * modules_with_corrupt_symbols)1057 static void PrintModules(
1058     const CodeModules* modules,
1059     const vector<const CodeModule*>* modules_without_symbols,
1060     const vector<const CodeModule*>* modules_with_corrupt_symbols) {
1061   if (!modules)
1062     return;
1063 
1064   printf("\n");
1065   printf("Loaded modules:\n");
1066 
1067   uint64_t main_address = 0;
1068   const CodeModule* main_module = modules->GetMainModule();
1069   if (main_module) {
1070     main_address = main_module->base_address();
1071   }
1072 
1073   unsigned int module_count = modules->module_count();
1074   for (unsigned int module_sequence = 0;
1075        module_sequence < module_count;
1076        ++module_sequence) {
1077     const CodeModule* module = modules->GetModuleAtSequence(module_sequence);
1078     PrintModule(module, modules_without_symbols, modules_with_corrupt_symbols,
1079                 main_address);
1080   }
1081 }
1082 
1083 // PrintModulesMachineReadable outputs a list of loaded modules,
1084 // one per line, in the following machine-readable pipe-delimited
1085 // text format:
1086 // Module|{Module Filename}|{Version}|{Debug Filename}|{Debug Identifier}|
1087 // {Base Address}|{Max Address}|{Main}
PrintModulesMachineReadable(const CodeModules * modules)1088 static void PrintModulesMachineReadable(const CodeModules* modules) {
1089   if (!modules)
1090     return;
1091 
1092   uint64_t main_address = 0;
1093   const CodeModule* main_module = modules->GetMainModule();
1094   if (main_module) {
1095     main_address = main_module->base_address();
1096   }
1097 
1098   unsigned int module_count = modules->module_count();
1099   for (unsigned int module_sequence = 0;
1100        module_sequence < module_count;
1101        ++module_sequence) {
1102     const CodeModule* module = modules->GetModuleAtSequence(module_sequence);
1103     uint64_t base_address = module->base_address();
1104     printf("Module%c%s%c%s%c%s%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n",
1105            kOutputSeparator,
1106            StripSeparator(PathnameStripper::File(module->code_file())).c_str(),
1107            kOutputSeparator, StripSeparator(module->version()).c_str(),
1108            kOutputSeparator,
1109            StripSeparator(PathnameStripper::File(module->debug_file())).c_str(),
1110            kOutputSeparator,
1111            StripSeparator(module->debug_identifier()).c_str(),
1112            kOutputSeparator, base_address,
1113            kOutputSeparator, base_address + module->size() - 1,
1114            kOutputSeparator,
1115            main_module != NULL && base_address == main_address ? 1 : 0);
1116   }
1117 }
1118 
1119 }  // namespace
1120 
PrintProcessState(const ProcessState & process_state,bool output_stack_contents,bool output_requesting_thread_only,SourceLineResolverInterface * resolver)1121 void PrintProcessState(const ProcessState& process_state,
1122                        bool output_stack_contents,
1123                        bool output_requesting_thread_only,
1124                        SourceLineResolverInterface* resolver) {
1125   // Print OS and CPU information.
1126   string cpu = process_state.system_info()->cpu;
1127   string cpu_info = process_state.system_info()->cpu_info;
1128   printf("Operating system: %s\n", process_state.system_info()->os.c_str());
1129   printf("                  %s\n",
1130          process_state.system_info()->os_version.c_str());
1131   printf("CPU: %s\n", cpu.c_str());
1132   if (!cpu_info.empty()) {
1133     // This field is optional.
1134     printf("     %s\n", cpu_info.c_str());
1135   }
1136   printf("     %d CPU%s\n",
1137          process_state.system_info()->cpu_count,
1138          process_state.system_info()->cpu_count != 1 ? "s" : "");
1139   printf("\n");
1140 
1141   // Print GPU information
1142   string gl_version = process_state.system_info()->gl_version;
1143   string gl_vendor = process_state.system_info()->gl_vendor;
1144   string gl_renderer = process_state.system_info()->gl_renderer;
1145   printf("GPU:");
1146   if (!gl_version.empty() || !gl_vendor.empty() || !gl_renderer.empty()) {
1147     printf(" %s\n", gl_version.c_str());
1148     printf("     %s\n", gl_vendor.c_str());
1149     printf("     %s\n", gl_renderer.c_str());
1150   } else {
1151     printf(" UNKNOWN\n");
1152   }
1153   printf("\n");
1154 
1155   // Print crash information.
1156   if (process_state.crashed()) {
1157     printf("Crash reason:  %s\n", process_state.crash_reason().c_str());
1158     printf("Crash address: 0x%" PRIx64 "\n", process_state.crash_address());
1159   } else {
1160     printf("No crash\n");
1161   }
1162 
1163   string assertion = process_state.assertion();
1164   if (!assertion.empty()) {
1165     printf("Assertion: %s\n", assertion.c_str());
1166   }
1167 
1168   // Compute process uptime if the process creation and crash times are
1169   // available in the dump.
1170   if (process_state.time_date_stamp() != 0 &&
1171       process_state.process_create_time() != 0 &&
1172       process_state.time_date_stamp() >= process_state.process_create_time()) {
1173     printf("Process uptime: %d seconds\n",
1174            process_state.time_date_stamp() -
1175                process_state.process_create_time());
1176   } else {
1177     printf("Process uptime: not available\n");
1178   }
1179 
1180   // If the thread that requested the dump is known, print it first.
1181   int requesting_thread = process_state.requesting_thread();
1182   if (requesting_thread != -1) {
1183     printf("\n");
1184     printf("Thread %d (%s)\n",
1185           requesting_thread,
1186           process_state.crashed() ? "crashed" :
1187                                     "requested dump, did not crash");
1188     PrintStack(process_state.threads()->at(requesting_thread), cpu,
1189                output_stack_contents,
1190                process_state.thread_memory_regions()->at(requesting_thread),
1191                process_state.modules(), resolver);
1192   }
1193 
1194   if (!output_requesting_thread_only) {
1195     // Print all of the threads in the dump.
1196     int thread_count = process_state.threads()->size();
1197     for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
1198       if (thread_index != requesting_thread) {
1199         // Don't print the crash thread again, it was already printed.
1200         printf("\n");
1201         printf("Thread %d\n", thread_index);
1202         PrintStack(process_state.threads()->at(thread_index), cpu,
1203                   output_stack_contents,
1204                   process_state.thread_memory_regions()->at(thread_index),
1205                   process_state.modules(), resolver);
1206       }
1207     }
1208   }
1209 
1210   PrintModules(process_state.modules(),
1211                process_state.modules_without_symbols(),
1212                process_state.modules_with_corrupt_symbols());
1213 }
1214 
PrintProcessStateMachineReadable(const ProcessState & process_state)1215 void PrintProcessStateMachineReadable(const ProcessState& process_state) {
1216   // Print OS and CPU information.
1217   // OS|{OS Name}|{OS Version}
1218   // CPU|{CPU Name}|{CPU Info}|{Number of CPUs}
1219   // GPU|{GPU version}|{GPU vendor}|{GPU renderer}
1220   printf("OS%c%s%c%s\n", kOutputSeparator,
1221          StripSeparator(process_state.system_info()->os).c_str(),
1222          kOutputSeparator,
1223          StripSeparator(process_state.system_info()->os_version).c_str());
1224   printf("CPU%c%s%c%s%c%d\n", kOutputSeparator,
1225          StripSeparator(process_state.system_info()->cpu).c_str(),
1226          kOutputSeparator,
1227          // this may be empty
1228          StripSeparator(process_state.system_info()->cpu_info).c_str(),
1229          kOutputSeparator,
1230          process_state.system_info()->cpu_count);
1231   printf("GPU%c%s%c%s%c%s\n", kOutputSeparator,
1232          StripSeparator(process_state.system_info()->gl_version).c_str(),
1233          kOutputSeparator,
1234          StripSeparator(process_state.system_info()->gl_vendor).c_str(),
1235          kOutputSeparator,
1236          StripSeparator(process_state.system_info()->gl_renderer).c_str());
1237 
1238   int requesting_thread = process_state.requesting_thread();
1239 
1240   // Print crash information.
1241   // Crash|{Crash Reason}|{Crash Address}|{Crashed Thread}
1242   printf("Crash%c", kOutputSeparator);
1243   if (process_state.crashed()) {
1244     printf("%s%c0x%" PRIx64 "%c",
1245            StripSeparator(process_state.crash_reason()).c_str(),
1246            kOutputSeparator, process_state.crash_address(), kOutputSeparator);
1247   } else {
1248     // print assertion info, if available, in place of crash reason,
1249     // instead of the unhelpful "No crash"
1250     string assertion = process_state.assertion();
1251     if (!assertion.empty()) {
1252       printf("%s%c%c", StripSeparator(assertion).c_str(),
1253              kOutputSeparator, kOutputSeparator);
1254     } else {
1255       printf("No crash%c%c", kOutputSeparator, kOutputSeparator);
1256     }
1257   }
1258 
1259   if (requesting_thread != -1) {
1260     printf("%d\n", requesting_thread);
1261   } else {
1262     printf("\n");
1263   }
1264 
1265   PrintModulesMachineReadable(process_state.modules());
1266 
1267   // blank line to indicate start of threads
1268   printf("\n");
1269 
1270   // If the thread that requested the dump is known, print it first.
1271   if (requesting_thread != -1) {
1272     PrintStackMachineReadable(requesting_thread,
1273                               process_state.threads()->at(requesting_thread));
1274   }
1275 
1276   // Print all of the threads in the dump.
1277   int thread_count = process_state.threads()->size();
1278   for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
1279     if (thread_index != requesting_thread) {
1280       // Don't print the crash thread again, it was already printed.
1281       PrintStackMachineReadable(thread_index,
1282                                 process_state.threads()->at(thread_index));
1283     }
1284   }
1285 }
1286 
PrintRequestingThreadBrief(const ProcessState & process_state)1287 void PrintRequestingThreadBrief(const ProcessState& process_state) {
1288   int requesting_thread = process_state.requesting_thread();
1289   if (requesting_thread == -1) {
1290     printf(" <no crashing or requesting dump thread identified>\n");
1291     return;
1292   }
1293 
1294   printf("Thread %d (%s)\n", requesting_thread,
1295          process_state.crashed() ? "crashed" : "requested dump, did not crash");
1296   const CallStack* stack = process_state.threads()->at(requesting_thread);
1297   int frame_count = stack->frames()->size();
1298   for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
1299     PrintFrameHeader(stack->frames()->at(frame_index), frame_index);
1300     printf("\n");
1301   }
1302 }
1303 
1304 }  // namespace google_breakpad
1305