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