/ src / processor / stackwalk_common.cc
stackwalk_common.cc
   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
  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.
  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.
 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.
 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  
 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.
 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.
 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|.
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.
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.
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}
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  
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  
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  
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