14fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// Copyright (c) 2012, Google Inc.
24fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// All rights reserved.
34fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org//
44fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// Redistribution and use in source and binary forms, with or without
54fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// modification, are permitted provided that the following conditions are
64fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// met:
74fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org//
84fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org//     * Redistributions of source code must retain the above copyright
94fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// notice, this list of conditions and the following disclaimer.
104fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org//     * Redistributions in binary form must reproduce the above
114fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// copyright notice, this list of conditions and the following disclaimer
124fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// in the documentation and/or other materials provided with the
134fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// distribution.
144fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org//     * Neither the name of Google Inc. nor the names of its
154fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// contributors may be used to endorse or promote products derived from
164fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// this software without specific prior written permission.
174fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org//
184fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
194fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
204fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
214fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
224fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
234fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
244fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
254fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
264fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
274fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
284fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
294fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
304fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// linux_core_dumper.cc: Implement google_breakpad::LinuxCoreDumper.
314fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org// See linux_core_dumper.h for details.
324fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
334fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#include "client/linux/minidump_writer/linux_core_dumper.h"
344fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
354fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#include <asm/ptrace.h>
364fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#include <assert.h>
374fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#include <elf.h>
384fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#include <stdio.h>
394fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#include <string.h>
404fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#include <sys/procfs.h>
414fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
424fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#include "common/linux/linux_libc_support.h"
434fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
444fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.orgnamespace google_breakpad {
454fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
464fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.orgLinuxCoreDumper::LinuxCoreDumper(pid_t pid,
474fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org                                 const char* core_path,
484fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org                                 const char* procfs_path)
494fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    : LinuxDumper(pid),
504fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      core_path_(core_path),
514fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      procfs_path_(procfs_path),
524fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      thread_infos_(&allocator_, 8) {
534fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  assert(core_path_);
544fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org}
554fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
564fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.orgbool LinuxCoreDumper::BuildProcPath(char* path, pid_t pid,
574fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org                                    const char* node) const {
584fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  if (!path || !node)
594fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    return false;
604fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
614fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  size_t node_len = my_strlen(node);
624fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  if (node_len == 0)
634fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    return false;
644fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
654fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  size_t procfs_path_len = my_strlen(procfs_path_);
664fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  size_t total_length = procfs_path_len + 1 + node_len;
674fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  if (total_length >= NAME_MAX)
684fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    return false;
694fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
704fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  memcpy(path, procfs_path_, procfs_path_len);
714fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  path[procfs_path_len] = '/';
724fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  memcpy(path + procfs_path_len + 1, node, node_len);
734fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  path[total_length] = '\0';
744fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  return true;
754fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org}
764fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
77e0aa94bfb6682a04f824b64d064fbb58ac5343c7benchan@chromium.orgbool LinuxCoreDumper::CopyFromProcess(void* dest, pid_t child,
784fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org                                      const void* src, size_t length) {
794fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  ElfCoreDump::Addr virtual_address = reinterpret_cast<ElfCoreDump::Addr>(src);
804fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  // TODO(benchan): Investigate whether the data to be copied could span
814fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  // across multiple segments in the core dump file. ElfCoreDump::CopyData
824fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  // and this method do not handle that case yet.
834fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  if (!core_.CopyData(dest, virtual_address, length)) {
844fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    // If the data segment is not found in the core dump, fill the result
854fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    // with marker characters.
864fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    memset(dest, 0xab, length);
87e0aa94bfb6682a04f824b64d064fbb58ac5343c7benchan@chromium.org    return false;
884fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  }
89e0aa94bfb6682a04f824b64d064fbb58ac5343c7benchan@chromium.org  return true;
904fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org}
914fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
924fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.orgbool LinuxCoreDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
934fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  if (index >= thread_infos_.size())
944fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    return false;
954fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
964fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  *info = thread_infos_[index];
974fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  const uint8_t* stack_pointer;
984fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#if defined(__i386)
994fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
1004fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#elif defined(__x86_64)
1014fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
1024fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#elif defined(__ARM_EABI__)
1034fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
1042eedc625759a8943d72711769a84fce05a23ecd0rmcilroy@chromium.org#elif defined(__aarch64__)
1052eedc625759a8943d72711769a84fce05a23ecd0rmcilroy@chromium.org  memcpy(&stack_pointer, &info->regs.sp, sizeof(info->regs.sp));
1065f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com#elif defined(__mips__)
1072eedc625759a8943d72711769a84fce05a23ecd0rmcilroy@chromium.org  stack_pointer =
1085f22d6a7f471f2352d394c188560fd06830e14f3gordana.cmiljanovic@imgtec.com      reinterpret_cast<uint8_t*>(info->regs.regs[MD_CONTEXT_MIPS_REG_SP]);
1094fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#else
1104fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#error "This code hasn't been ported to your platform yet."
1114fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#endif
112a576a63122315d8675b8ef6b43c848e627354afbmkrebs@chromium.org  info->stack_pointer = reinterpret_cast<uintptr_t>(stack_pointer);
113a576a63122315d8675b8ef6b43c848e627354afbmkrebs@chromium.org  return true;
1144fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org}
1154fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
1164fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.orgbool LinuxCoreDumper::IsPostMortem() const {
1174fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  return true;
1184fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org}
1194fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
1204fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.orgbool LinuxCoreDumper::ThreadsSuspend() {
1214fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  return true;
1224fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org}
1234fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
1244fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.orgbool LinuxCoreDumper::ThreadsResume() {
1254fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  return true;
1264fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org}
1274fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
1284fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.orgbool LinuxCoreDumper::EnumerateThreads() {
129dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org  if (!mapped_core_file_.Map(core_path_, 0)) {
1304fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    fprintf(stderr, "Could not map core dump file into memory\n");
1314fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    return false;
1324fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  }
1334fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
1344fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  core_.SetContent(mapped_core_file_.content());
1354fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  if (!core_.IsValid()) {
1364fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    fprintf(stderr, "Invalid core dump file\n");
1374fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    return false;
1384fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  }
1394fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
1404fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  ElfCoreDump::Note note = core_.GetFirstNote();
1414fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  if (!note.IsValid()) {
1424fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    fprintf(stderr, "PT_NOTE section not found\n");
1434fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    return false;
1444fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  }
1454fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
1464fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  bool first_thread = true;
1474fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  do {
1484fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    ElfCoreDump::Word type = note.GetType();
1494fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    MemoryRange name = note.GetName();
1504fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    MemoryRange description = note.GetDescription();
1514fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
1524fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    if (type == 0 || name.IsEmpty() || description.IsEmpty()) {
1534fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      fprintf(stderr, "Could not found a valid PT_NOTE.\n");
1544fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      return false;
1554fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    }
1564fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
1574fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    // Based on write_note_info() in linux/kernel/fs/binfmt_elf.c, notes are
1584fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    // ordered as follows (NT_PRXFPREG and NT_386_TLS are i386 specific):
1594fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   Thread           Name          Type
1604fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   -------------------------------------------------------------------
1614fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   1st thread       CORE          NT_PRSTATUS
1624fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   process-wide     CORE          NT_PRPSINFO
1634fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   process-wide     CORE          NT_AUXV
1644fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   1st thread       CORE          NT_FPREGSET
1654fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   1st thread       LINUX         NT_PRXFPREG
1664fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   1st thread       LINUX         NT_386_TLS
1674fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //
1684fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   2nd thread       CORE          NT_PRSTATUS
1694fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   2nd thread       CORE          NT_FPREGSET
1704fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   2nd thread       LINUX         NT_PRXFPREG
1714fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   2nd thread       LINUX         NT_386_TLS
1724fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //
1734fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   3rd thread       CORE          NT_PRSTATUS
1744fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   3rd thread       CORE          NT_FPREGSET
1754fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   3rd thread       LINUX         NT_PRXFPREG
1764fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //   3rd thread       LINUX         NT_386_TLS
1774fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    //
1784fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    // The following code only works if notes are ordered as expected.
1794fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    switch (type) {
1804fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      case NT_PRSTATUS: {
1814fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        if (description.length() != sizeof(elf_prstatus)) {
1824fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org          fprintf(stderr, "Found NT_PRSTATUS descriptor of unexpected size\n");
1834fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org          return false;
1844fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        }
1854fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
1864fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        const elf_prstatus* status =
1874fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org            reinterpret_cast<const elf_prstatus*>(description.data());
1884fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        pid_t pid = status->pr_pid;
1894fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        ThreadInfo info;
1904fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        memset(&info, 0, sizeof(ThreadInfo));
1914fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        info.tgid = status->pr_pgrp;
1924fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        info.ppid = status->pr_ppid;
193032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com#if defined(__mips__)
194032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com        for (int i = EF_REG0; i <= EF_REG31; i++)
195032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com          info.regs.regs[i - EF_REG0] = status->pr_reg[i];
196032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com
197032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com        info.regs.lo = status->pr_reg[EF_LO];
198032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com        info.regs.hi = status->pr_reg[EF_HI];
199032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com        info.regs.epc = status->pr_reg[EF_CP0_EPC];
200032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com        info.regs.badvaddr = status->pr_reg[EF_CP0_BADVADDR];
201032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com        info.regs.status = status->pr_reg[EF_CP0_STATUS];
202032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com        info.regs.cause = status->pr_reg[EF_CP0_CAUSE];
203032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com#else
2044fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        memcpy(&info.regs, status->pr_reg, sizeof(info.regs));
205032cbb80abf2e8adce5c8cc906a3fde0e20a23c6gordana.cmiljanovic@imgtec.com#endif
2064fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        if (first_thread) {
2074fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org          crash_thread_ = pid;
2084fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org          crash_signal_ = status->pr_info.si_signo;
2094fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        }
2104fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        first_thread = false;
2114fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        threads_.push_back(pid);
2124fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        thread_infos_.push_back(info);
2134fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        break;
2144fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      }
2154fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#if defined(__i386) || defined(__x86_64)
2164fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      case NT_FPREGSET: {
2174fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        if (thread_infos_.empty())
2184fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org          return false;
2194fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
2204fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        ThreadInfo* info = &thread_infos_.back();
2214fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        if (description.length() != sizeof(info->fpregs)) {
2224fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org          fprintf(stderr, "Found NT_FPREGSET descriptor of unexpected size\n");
2234fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org          return false;
2244fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        }
2254fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
2264fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        memcpy(&info->fpregs, description.data(), sizeof(info->fpregs));
2274fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        break;
2284fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      }
2294fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#endif
2304fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#if defined(__i386)
2314fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      case NT_PRXFPREG: {
2324fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        if (thread_infos_.empty())
2334fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org          return false;
2344fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
2354fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        ThreadInfo* info = &thread_infos_.back();
2364fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        if (description.length() != sizeof(info->fpxregs)) {
2374fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org          fprintf(stderr, "Found NT_PRXFPREG descriptor of unexpected size\n");
2384fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org          return false;
2394fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        }
2404fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
2414fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        memcpy(&info->fpxregs, description.data(), sizeof(info->fpxregs));
2424fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org        break;
2434fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org      }
2444fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org#endif
2454fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    }
2464fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org    note = note.GetNextNote();
2474fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  } while (note.IsValid());
2484fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
2494fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org  return true;
2504fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org}
2514fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org
2524fa638a7ecb6ab042664300767614308dbc147bbbenchan@chromium.org}  // namespace google_breakpad
253