115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// Copyright (c) 2014 Google Inc.
215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// All rights reserved.
315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// Redistribution and use in source and binary forms, with or without
515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// modification, are permitted provided that the following conditions are
615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// met:
715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//     * Redistributions of source code must retain the above copyright
915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// notice, this list of conditions and the following disclaimer.
1015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//     * Redistributions in binary form must reproduce the above
1115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// copyright notice, this list of conditions and the following disclaimer
1215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// in the documentation and/or other materials provided with the
1315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// distribution.
1415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//     * Neither the name of Google Inc. nor the names of its
1515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// contributors may be used to endorse or promote products derived from
1615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// this software without specific prior written permission.
1715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
1815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
3015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// microdump.cc: A microdump reader.
3115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
3215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// See microdump.h for documentation.
3315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
3415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include "google_breakpad/processor/microdump.h"
3515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
3615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include <stdio.h>
3715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include <string.h>
3815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
3915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include <memory>
4015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include <sstream>
4115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include <string>
4215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include <vector>
4315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
4415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include "google_breakpad/common/minidump_cpu_arm.h"
4515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include "google_breakpad/processor/code_module.h"
4615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include "processor/basic_code_module.h"
4715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include "processor/linked_ptr.h"
4815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include "processor/logging.h"
4915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org#include "processor/range_map-inl.h"
5015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
5115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgnamespace {
52864edfddf4fcbee028e243d73ad795a83d919886primiano@chromium.orgstatic const char kGoogleBreakpadKey[] = "google-breakpad";
5315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgstatic const char kMicrodumpBegin[] = "-----BEGIN BREAKPAD MICRODUMP-----";
5415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgstatic const char kMicrodumpEnd[] = "-----END BREAKPAD MICRODUMP-----";
5515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgstatic const char kOsKey[] = ": O ";
5615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgstatic const char kCpuKey[] = ": C ";
5715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgstatic const char kMmapKey[] = ": M ";
5815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgstatic const char kStackKey[] = ": S ";
5915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgstatic const char kStackFirstLineKey[] = ": S 0 ";
602aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.orgstatic const char kArmArchitecture[] = "arm";
612aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.orgstatic const char kArm64Architecture[] = "arm64";
6215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
6315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgtemplate<typename T>
6415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgT HexStrToL(const string& str) {
6515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  uint64_t res = 0;
6615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  std::istringstream ss(str);
6715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  ss >> std::hex >> res;
6815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  return static_cast<T>(res);
6915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
7015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
7115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgstd::vector<uint8_t> ParseHexBuf(const string& str) {
7215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  std::vector<uint8_t> buf;
7315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  for (size_t i = 0; i < str.length(); i += 2) {
7415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    buf.push_back(HexStrToL<uint8_t>(str.substr(i, 2)));
7515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  }
7615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  return buf;
7715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
7815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
7915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}  // namespace
8015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
8115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgnamespace google_breakpad {
8215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
8315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
8415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// MicrodumpModules
8515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
8615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
8715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgvoid MicrodumpModules::Add(const CodeModule* module) {
8815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  linked_ptr<const CodeModule> module_ptr(module);
8915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  if (!map_->StoreRange(module->base_address(), module->size(), module_ptr)) {
9015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    BPLOG(ERROR) << "Module " << module->code_file() <<
9115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org                    " could not be stored";
9215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  }
9315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
9415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
9515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
9615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
9715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// MicrodumpContext
9815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
9915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
10015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgvoid MicrodumpContext::SetContextARM(MDRawContextARM* arm) {
10115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  DumpContext::SetContextFlags(MD_CONTEXT_ARM);
10215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  DumpContext::SetContextARM(arm);
10315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  valid_ = true;
10415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
10515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
1062aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.orgvoid MicrodumpContext::SetContextARM64(MDRawContextARM64* arm64) {
1072aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org  DumpContext::SetContextFlags(MD_CONTEXT_ARM64);
1082aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org  DumpContext::SetContextARM64(arm64);
1092aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org  valid_ = true;
1102aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org}
1112aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org
11215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
11315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
11415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// MicrodumpMemoryRegion
11515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
11615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
11715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgMicrodumpMemoryRegion::MicrodumpMemoryRegion() : base_address_(0) { }
11815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
11915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgvoid MicrodumpMemoryRegion::Init(uint64_t base_address,
12015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org                                 const std::vector<uint8_t>& contents) {
12115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  base_address_ = base_address;
12215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  contents_ = contents;
12315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
12415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
12515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orguint64_t MicrodumpMemoryRegion::GetBase() const { return base_address_; }
12615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
12715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orguint32_t MicrodumpMemoryRegion::GetSize() const { return contents_.size(); }
12815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
12915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgbool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
13015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org                                               uint8_t* value) const {
13115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  return GetMemoryLittleEndian(address, value);
13215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
13315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
13415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgbool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
13515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org                                               uint16_t* value) const {
13615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  return GetMemoryLittleEndian(address, value);
13715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
13815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
13915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgbool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
14015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org                                               uint32_t* value) const {
14115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  return GetMemoryLittleEndian(address, value);
14215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
14315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
14415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgbool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
14515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org                                               uint64_t* value) const {
14615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  return GetMemoryLittleEndian(address, value);
14715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
14815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
14915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgtemplate<typename ValueType>
15015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgbool MicrodumpMemoryRegion::GetMemoryLittleEndian(uint64_t address,
15115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org                                                  ValueType* value) const {
15215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  if (address < base_address_ ||
15315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      address - base_address_ + sizeof(ValueType) > contents_.size())
15415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    return false;
15515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  ValueType v = 0;
15615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  uint64_t start = address - base_address_;
15715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  // The loop condition is odd, but it's correct for size_t.
15815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  for (size_t i = sizeof(ValueType) - 1; i < sizeof(ValueType); i--)
15915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    v = (v << 8) | static_cast<uint8_t>(contents_[start + i]);
16015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  *value = v;
16115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  return true;
16215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
16315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
16415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgvoid MicrodumpMemoryRegion::Print() const {
16515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  // Not reached, just needed to honor the base class contract.
16615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  assert(false);
16715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
16815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
16915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
17015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org// Microdump
17115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org//
17215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.orgMicrodump::Microdump(const string& contents)
17315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  : context_(new MicrodumpContext()),
17415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    stack_region_(new MicrodumpMemoryRegion()),
1752aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org    modules_(new MicrodumpModules()),
1762aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org    system_info_(new SystemInfo()) {
17715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  assert(!contents.empty());
17815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
17915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  bool in_microdump = false;
18015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  string line;
18115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  uint64_t stack_start = 0;
18215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  std::vector<uint8_t> stack_content;
18315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  string arch;
18415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
18515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  std::istringstream stream(contents);
18615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  while (std::getline(stream, line)) {
18715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    if (line.find(kGoogleBreakpadKey) == string::npos) {
18815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      continue;
18915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    }
19015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    if (line.find(kMicrodumpBegin) != string::npos) {
19115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      in_microdump = true;
19215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      continue;
19315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    }
19415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    if (line.find(kMicrodumpEnd) != string::npos) {
19515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      break;
19615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    }
19715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
19815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    if (!in_microdump) {
19915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      continue;
20015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    }
20115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
20215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    size_t pos;
20315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    if ((pos = line.find(kOsKey)) != string::npos) {
20415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      string os_str(line, pos + strlen(kOsKey));
20515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      std::istringstream os_tokens(os_str);
2062aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      string os_id;
2072aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      string num_cpus;
2082aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      string os_version;
2092aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      // This reflect the actual HW arch and might not match the arch emulated
2102aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      // for the execution (e.g., running a 32-bit binary on a 64-bit cpu).
2112aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      string hw_arch;
2122aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org
2132aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      os_tokens >> os_id;
21415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      os_tokens >> arch;
2152aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      os_tokens >> num_cpus;
2162aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      os_tokens >> hw_arch;
2172aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      std::getline(os_tokens, os_version);
2182aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      os_version.erase(0, 1);  // remove leading space.
2192aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org
2202aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      system_info_->cpu = hw_arch;
2212aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      system_info_->cpu_count = HexStrToL<uint8_t>(num_cpus);
2222aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      system_info_->os_version = os_version;
2232aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org
2242aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      if (os_id == "L") {
2252aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        system_info_->os = "Linux";
2262aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        system_info_->os_short = "linux";
2272aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      } else if (os_id == "A") {
2282aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        system_info_->os = "Android";
2292aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        system_info_->os_short = "android";
2302aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      }
2312aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org
23215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      // OS line also contains release and version for future use.
23315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    } else if ((pos = line.find(kStackKey)) != string::npos) {
23415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      if (line.find(kStackFirstLineKey) != string::npos) {
23515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        // The first line of the stack (S 0 stack header) provides the value of
23615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        // the stack pointer, the start address of the stack being dumped and
23715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        // the length of the stack. We could use it in future to double check
23815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        // that we received all the stack as expected.
23915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        continue;
24015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      }
24115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      string stack_str(line, pos + strlen(kStackKey));
24215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      std::istringstream stack_tokens(stack_str);
24315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      string start_addr_str;
24415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      string raw_content;
24515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      stack_tokens >> start_addr_str;
24615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      stack_tokens >> raw_content;
24715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      uint64_t start_addr = HexStrToL<uint64_t>(start_addr_str);
24815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
24915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      if (stack_start != 0) {
25015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        // Verify that the stack chunks in the microdump are contiguous.
25115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        assert(start_addr == stack_start + stack_content.size());
25215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      } else {
25315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        stack_start = start_addr;
25415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      }
25515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      std::vector<uint8_t> chunk = ParseHexBuf(raw_content);
25615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      stack_content.insert(stack_content.end(), chunk.begin(), chunk.end());
25715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
25815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    } else if ((pos = line.find(kCpuKey)) != string::npos) {
25915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      string cpu_state_str(line, pos + strlen(kCpuKey));
26015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      std::vector<uint8_t> cpu_state_raw = ParseHexBuf(cpu_state_str);
26115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      if (strcmp(arch.c_str(), kArmArchitecture) == 0) {
2622aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        if (cpu_state_raw.size() != sizeof(MDRawContextARM)) {
2632aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org          std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() <<
2642aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org              " bytes instead of " << sizeof(MDRawContextARM) << std::endl;
2652aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org          continue;
2662aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        }
26715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        MDRawContextARM* arm = new MDRawContextARM();
26815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
26915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        context_->SetContextARM(arm);
2702aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org      } else if (strcmp(arch.c_str(), kArm64Architecture) == 0) {
2712aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        if (cpu_state_raw.size() != sizeof(MDRawContextARM64)) {
2722aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org          std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() <<
2732aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org              " bytes instead of " << sizeof(MDRawContextARM64) << std::endl;
2742aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org          continue;
2752aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        }
2762aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        MDRawContextARM64* arm = new MDRawContextARM64();
2772aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
2782aa2e9728b4960b0c7ef6898d06a57679a3b6292primiano@chromium.org        context_->SetContextARM64(arm);
27915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      } else {
28015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org        std::cerr << "Unsupported architecture: " << arch << std::endl;
28115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      }
28215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    } else if ((pos = line.find(kMmapKey)) != string::npos) {
28315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      string mmap_line(line, pos + strlen(kMmapKey));
28415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      std::istringstream mmap_tokens(mmap_line);
28515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      string addr, offset, size, identifier, filename;
28615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      mmap_tokens >> addr;
28715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      mmap_tokens >> offset;
28815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      mmap_tokens >> size;
28915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      mmap_tokens >> identifier;
29015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      mmap_tokens >> filename;
29115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
29215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org      modules_->Add(new BasicCodeModule(
29315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org          HexStrToL<uint64_t>(addr),  // base_address
29415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org          HexStrToL<uint64_t>(size),  // size
29515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org          filename,                   // code_file
29615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org          identifier,                 // code_identifier
29715d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org          filename,                   // debug_file
29815d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org          identifier,                 // debug_identifier
29915d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org          ""));                       // version
30015d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org    }
30115d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  }
30215d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org  stack_region_->Init(stack_start, stack_content);
30315d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}
30415d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
30515d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org}  // namespace google_breakpad
30615d8ea9c36db35b474c5bd01a36ffb28dc336025mmandlis@chromium.org
307