// Copyright (c) 2014 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// microdump.cc: A microdump reader.
//
// See microdump.h for documentation.

#include "google_breakpad/processor/microdump.h"

#include <stdio.h>
#include <string.h>

#include <memory>
#include <sstream>
#include <string>
#include <vector>

#include "google_breakpad/common/minidump_cpu_arm.h"
#include "google_breakpad/processor/code_module.h"
#include "processor/basic_code_module.h"
#include "processor/linked_ptr.h"
#include "processor/logging.h"
#include "processor/range_map-inl.h"

namespace {
static const char kGoogleBreakpadKey[] = "google-breakpad";
static const char kMicrodumpBegin[] = "-----BEGIN BREAKPAD MICRODUMP-----";
static const char kMicrodumpEnd[] = "-----END BREAKPAD MICRODUMP-----";
static const char kOsKey[] = ": O ";
static const char kCpuKey[] = ": C ";
static const char kGpuKey[] = ": G ";
static const char kMmapKey[] = ": M ";
static const char kStackKey[] = ": S ";
static const char kStackFirstLineKey[] = ": S 0 ";
static const char kArmArchitecture[] = "arm";
static const char kArm64Architecture[] = "arm64";
static const char kX86Architecture[] = "x86";
static const char kMipsArchitecture[] = "mips";
static const char kMips64Architecture[] = "mips64";
static const char kGpuUnknown[] = "UNKNOWN";

template<typename T>
T HexStrToL(const string& str) {
  uint64_t res = 0;
  std::istringstream ss(str);
  ss >> std::hex >> res;
  return static_cast<T>(res);
}

std::vector<uint8_t> ParseHexBuf(const string& str) {
  std::vector<uint8_t> buf;
  for (size_t i = 0; i < str.length(); i += 2) {
    buf.push_back(HexStrToL<uint8_t>(str.substr(i, 2)));
  }
  return buf;
}

bool GetLine(std::istringstream* istream, string* str) {
  if (std::getline(*istream, *str)) {
    // Trim any trailing newline from the end of the line. Allows us
    // to seamlessly handle both Windows/DOS and Unix formatted input. The
    // adb tool generally writes logcat dumps in Windows/DOS format.
    if (!str->empty() && str->at(str->size() - 1) == '\r') {
      str->erase(str->size() - 1);
    }
    return true;
  }
  return false;
}

}  // namespace

namespace google_breakpad {

//
// MicrodumpModules
//

void MicrodumpModules::Add(const CodeModule* module) {
  linked_ptr<const CodeModule> module_ptr(module);
  if (!map_.StoreRange(module->base_address(), module->size(), module_ptr)) {
    BPLOG(ERROR) << "Module " << module->code_file() <<
                    " could not be stored";
  }
}

void MicrodumpModules::SetEnableModuleShrink(bool is_enabled) {
  map_.SetEnableShrinkDown(is_enabled);
}

//
// MicrodumpContext
//

void MicrodumpContext::SetContextARM(MDRawContextARM* arm) {
  DumpContext::SetContextFlags(MD_CONTEXT_ARM);
  DumpContext::SetContextARM(arm);
  valid_ = true;
}

void MicrodumpContext::SetContextARM64(MDRawContextARM64* arm64) {
  DumpContext::SetContextFlags(MD_CONTEXT_ARM64);
  DumpContext::SetContextARM64(arm64);
  valid_ = true;
}

void MicrodumpContext::SetContextX86(MDRawContextX86* x86) {
  DumpContext::SetContextFlags(MD_CONTEXT_X86);
  DumpContext::SetContextX86(x86);
  valid_ = true;
}

void MicrodumpContext::SetContextMIPS(MDRawContextMIPS* mips32) {
  DumpContext::SetContextFlags(MD_CONTEXT_MIPS);
  DumpContext::SetContextMIPS(mips32);
  valid_ = true;
}

void MicrodumpContext::SetContextMIPS64(MDRawContextMIPS* mips64) {
  DumpContext::SetContextFlags(MD_CONTEXT_MIPS64);
  DumpContext::SetContextMIPS(mips64);
  valid_ = true;
}


//
// MicrodumpMemoryRegion
//

MicrodumpMemoryRegion::MicrodumpMemoryRegion() : base_address_(0) { }

void MicrodumpMemoryRegion::Init(uint64_t base_address,
                                 const std::vector<uint8_t>& contents) {
  base_address_ = base_address;
  contents_ = contents;
}

uint64_t MicrodumpMemoryRegion::GetBase() const { return base_address_; }

uint32_t MicrodumpMemoryRegion::GetSize() const { return contents_.size(); }

bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
                                               uint8_t* value) const {
  return GetMemoryLittleEndian(address, value);
}

bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
                                               uint16_t* value) const {
  return GetMemoryLittleEndian(address, value);
}

bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
                                               uint32_t* value) const {
  return GetMemoryLittleEndian(address, value);
}

bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
                                               uint64_t* value) const {
  return GetMemoryLittleEndian(address, value);
}

template<typename ValueType>
bool MicrodumpMemoryRegion::GetMemoryLittleEndian(uint64_t address,
                                                  ValueType* value) const {
  if (address < base_address_ ||
      address - base_address_ + sizeof(ValueType) > contents_.size())
    return false;
  ValueType v = 0;
  uint64_t start = address - base_address_;
  // The loop condition is odd, but it's correct for size_t.
  for (size_t i = sizeof(ValueType) - 1; i < sizeof(ValueType); i--)
    v = (v << 8) | static_cast<uint8_t>(contents_[start + i]);
  *value = v;
  return true;
}

void MicrodumpMemoryRegion::Print() const {
  // Not reached, just needed to honor the base class contract.
  assert(false);
}

//
// Microdump
//
Microdump::Microdump(const string& contents)
  : context_(new MicrodumpContext()),
    stack_region_(new MicrodumpMemoryRegion()),
    modules_(new MicrodumpModules()),
    system_info_(new SystemInfo()) {
  assert(!contents.empty());

  bool in_microdump = false;
  string line;
  uint64_t stack_start = 0;
  std::vector<uint8_t> stack_content;
  string arch;

  std::istringstream stream(contents);
  while (GetLine(&stream, &line)) {
    if (line.find(kGoogleBreakpadKey) == string::npos) {
      continue;
    }
    if (line.find(kMicrodumpBegin) != string::npos) {
      in_microdump = true;
      continue;
    }
    if (!in_microdump) {
      continue;
    }
    if (line.find(kMicrodumpEnd) != string::npos) {
      break;
    }

    size_t pos;
    if ((pos = line.find(kOsKey)) != string::npos) {
      string os_str(line, pos + strlen(kOsKey));
      std::istringstream os_tokens(os_str);
      string os_id;
      string num_cpus;
      string os_version;
      // This reflect the actual HW arch and might not match the arch emulated
      // for the execution (e.g., running a 32-bit binary on a 64-bit cpu).
      string hw_arch;

      os_tokens >> os_id;
      os_tokens >> arch;
      os_tokens >> num_cpus;
      os_tokens >> hw_arch;
      GetLine(&os_tokens, &os_version);
      os_version.erase(0, 1);  // remove leading space.

      system_info_->cpu = arch;
      system_info_->cpu_count = HexStrToL<uint8_t>(num_cpus);
      system_info_->os_version = os_version;

      if (os_id == "L") {
        system_info_->os = "Linux";
        system_info_->os_short = "linux";
      } else if (os_id == "A") {
        system_info_->os = "Android";
        system_info_->os_short = "android";
        modules_->SetEnableModuleShrink(true);
      }

      // OS line also contains release and version for future use.
    } else if ((pos = line.find(kStackKey)) != string::npos) {
      if (line.find(kStackFirstLineKey) != string::npos) {
        // The first line of the stack (S 0 stack header) provides the value of
        // the stack pointer, the start address of the stack being dumped and
        // the length of the stack. We could use it in future to double check
        // that we received all the stack as expected.
        continue;
      }
      string stack_str(line, pos + strlen(kStackKey));
      std::istringstream stack_tokens(stack_str);
      string start_addr_str;
      string raw_content;
      stack_tokens >> start_addr_str;
      stack_tokens >> raw_content;
      uint64_t start_addr = HexStrToL<uint64_t>(start_addr_str);

      if (stack_start != 0) {
        // Verify that the stack chunks in the microdump are contiguous.
        assert(start_addr == stack_start + stack_content.size());
      } else {
        stack_start = start_addr;
      }
      std::vector<uint8_t> chunk = ParseHexBuf(raw_content);
      stack_content.insert(stack_content.end(), chunk.begin(), chunk.end());

    } else if ((pos = line.find(kCpuKey)) != string::npos) {
      string cpu_state_str(line, pos + strlen(kCpuKey));
      std::vector<uint8_t> cpu_state_raw = ParseHexBuf(cpu_state_str);
      if (strcmp(arch.c_str(), kArmArchitecture) == 0) {
        if (cpu_state_raw.size() != sizeof(MDRawContextARM)) {
          std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
                    << " bytes instead of " << sizeof(MDRawContextARM)
                    << std::endl;
          continue;
        }
        MDRawContextARM* arm = new MDRawContextARM();
        memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
        context_->SetContextARM(arm);
      } else if (strcmp(arch.c_str(), kArm64Architecture) == 0) {
        if (cpu_state_raw.size() != sizeof(MDRawContextARM64)) {
          std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
                    << " bytes instead of " << sizeof(MDRawContextARM64)
                    << std::endl;
          continue;
        }
        MDRawContextARM64* arm = new MDRawContextARM64();
        memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
        context_->SetContextARM64(arm);
      } else if (strcmp(arch.c_str(), kX86Architecture) == 0) {
        if (cpu_state_raw.size() != sizeof(MDRawContextX86)) {
          std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
                    << " bytes instead of " << sizeof(MDRawContextX86)
                    << std::endl;
          continue;
        }
        MDRawContextX86* x86 = new MDRawContextX86();
        memcpy(x86, &cpu_state_raw[0], cpu_state_raw.size());
        context_->SetContextX86(x86);
      } else if (strcmp(arch.c_str(), kMipsArchitecture) == 0) {
        if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) {
          std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
                    << " bytes instead of " << sizeof(MDRawContextMIPS)
                    << std::endl;
          continue;
        }
        MDRawContextMIPS* mips32 = new MDRawContextMIPS();
        memcpy(mips32, &cpu_state_raw[0], cpu_state_raw.size());
        context_->SetContextMIPS(mips32);
      } else if (strcmp(arch.c_str(), kMips64Architecture) == 0) {
        if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) {
          std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
                    << " bytes instead of " << sizeof(MDRawContextMIPS)
                    << std::endl;
          continue;
        }
        MDRawContextMIPS* mips64 = new MDRawContextMIPS();
        memcpy(mips64, &cpu_state_raw[0], cpu_state_raw.size());
        context_->SetContextMIPS64(mips64);
      } else {
        std::cerr << "Unsupported architecture: " << arch << std::endl;
      }
    } else if ((pos = line.find(kGpuKey)) != string::npos) {
      string gpu_str(line, pos + strlen(kGpuKey));
      if (strcmp(gpu_str.c_str(), kGpuUnknown) != 0) {
        std::istringstream gpu_tokens(gpu_str);
        std::getline(gpu_tokens, system_info_->gl_version, '|');
        std::getline(gpu_tokens, system_info_->gl_vendor, '|');
        std::getline(gpu_tokens, system_info_->gl_renderer, '|');
      }
    } else if ((pos = line.find(kMmapKey)) != string::npos) {
      string mmap_line(line, pos + strlen(kMmapKey));
      std::istringstream mmap_tokens(mmap_line);
      string addr, offset, size, identifier, filename;
      mmap_tokens >> addr;
      mmap_tokens >> offset;
      mmap_tokens >> size;
      mmap_tokens >> identifier;
      mmap_tokens >> filename;

      modules_->Add(new BasicCodeModule(
          HexStrToL<uint64_t>(addr),  // base_address
          HexStrToL<uint64_t>(size),  // size
          filename,                   // code_file
          identifier,                 // code_identifier
          filename,                   // debug_file
          identifier,                 // debug_identifier
          ""));                       // version
    }
  }
  stack_region_->Init(stack_start, stack_content);
}

}  // namespace google_breakpad

