// Copyright (c) 2010 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.

// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>

// dump_stabs.cc --- implement the StabsToModule class.

#include <assert.h>
#include <cxxabi.h>
#include <stdarg.h>
#include <stdio.h>

#include <algorithm>

#include "common/stabs_to_module.h"
#include "common/using_std_string.h"

namespace google_breakpad {

// Demangle using abi call.
// Older GCC may not support it.
static string Demangle(const string &mangled) {
  int status = 0;
  char *demangled = abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status);
  if (status == 0 && demangled != NULL) {
    string str(demangled);
    free(demangled);
    return str;
  }
  return string(mangled);
}

StabsToModule::~StabsToModule() {
  // Free any functions we've accumulated but not added to the module.
  for (vector<Module::Function *>::const_iterator func_it = functions_.begin();
       func_it != functions_.end(); func_it++)
    delete *func_it;
  // Free any function that we're currently within.
  delete current_function_;
}

bool StabsToModule::StartCompilationUnit(const char *name, uint64_t address,
                                         const char *build_directory) {
  assert(!in_compilation_unit_);
  in_compilation_unit_ = true;
  current_source_file_name_ = name;
  current_source_file_ = module_->FindFile(name);
  comp_unit_base_address_ = address;
  boundaries_.push_back(static_cast<Module::Address>(address));
  return true;
}

bool StabsToModule::EndCompilationUnit(uint64_t address) {
  assert(in_compilation_unit_);
  in_compilation_unit_ = false;
  comp_unit_base_address_ = 0;
  current_source_file_ = NULL;
  current_source_file_name_ = NULL;
  if (address)
    boundaries_.push_back(static_cast<Module::Address>(address));
  return true;
}

bool StabsToModule::StartFunction(const string &name,
                                  uint64_t address) {
  assert(!current_function_);
  Module::Function *f = new Module::Function(Demangle(name), address);
  Module::Range r(address, 0); // We compute this in StabsToModule::Finalize().
  f->ranges.push_back(r);
  f->parameter_size = 0; // We don't provide this information.
  current_function_ = f;
  boundaries_.push_back(static_cast<Module::Address>(address));
  return true;
}

bool StabsToModule::EndFunction(uint64_t address) {
  assert(current_function_);
  // Functions in this compilation unit should have address bigger
  // than the compilation unit's starting address.  There may be a lot
  // of duplicated entries for functions in the STABS data. We will
  // count on the Module to remove the duplicates.
  if (current_function_->address >= comp_unit_base_address_)
    functions_.push_back(current_function_);
  else
    delete current_function_;
  current_function_ = NULL;
  if (address)
    boundaries_.push_back(static_cast<Module::Address>(address));
  return true;
}

bool StabsToModule::Line(uint64_t address, const char *name, int number) {
  assert(current_function_);
  assert(current_source_file_);
  if (name != current_source_file_name_) {
    current_source_file_ = module_->FindFile(name);
    current_source_file_name_ = name;
  }
  Module::Line line;
  line.address = address;
  line.size = 0;  // We compute this in StabsToModule::Finalize().
  line.file = current_source_file_;
  line.number = number;
  current_function_->lines.push_back(line);
  return true;
}

bool StabsToModule::Extern(const string &name, uint64_t address) {
  Module::Extern *ext = new Module::Extern(address);
  // Older libstdc++ demangle implementations can crash on unexpected
  // input, so be careful about what gets passed in.
  if (name.compare(0, 3, "__Z") == 0) {
    ext->name = Demangle(name.substr(1));
  } else if (name[0] == '_') {
    ext->name = name.substr(1);
  } else {
    ext->name = name;
  }
  module_->AddExtern(ext);
  return true;
}

void StabsToModule::Warning(const char *format, ...) {
  va_list args;
  va_start(args, format);
  vfprintf(stderr, format, args);
  va_end(args);
}

void StabsToModule::Finalize() {
  // Sort our boundary list, so we can search it quickly.
  sort(boundaries_.begin(), boundaries_.end());
  // Sort all functions by address, just for neatness.
  sort(functions_.begin(), functions_.end(),
       Module::Function::CompareByAddress);

  for (vector<Module::Function *>::const_iterator func_it = functions_.begin();
       func_it != functions_.end();
       func_it++) {
    Module::Function *f = *func_it;
    // Compute the function f's size.
    vector<Module::Address>::const_iterator boundary
        = std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address);
    if (boundary != boundaries_.end())
      f->ranges[0].size = *boundary - f->address;
    else
      // If this is the last function in the module, and the STABS
      // reader was unable to give us its ending address, then assign
      // it a bogus, very large value.  This will happen at most once
      // per module: since we've added all functions' addresses to the
      // boundary table, only one can be the last.
      f->ranges[0].size = kFallbackSize;

    // Compute sizes for each of the function f's lines --- if it has any.
    if (!f->lines.empty()) {
      stable_sort(f->lines.begin(), f->lines.end(),
                  Module::Line::CompareByAddress);
      vector<Module::Line>::iterator last_line = f->lines.end() - 1;
      for (vector<Module::Line>::iterator line_it = f->lines.begin();
           line_it != last_line; line_it++)
        line_it[0].size = line_it[1].address - line_it[0].address;
      // Compute the size of the last line from f's end address.
      last_line->size =
        (f->ranges[0].address + f->ranges[0].size) - last_line->address;
    }
  }
  // Now that everything has a size, add our functions to the module, and
  // dispose of our private list.
  module_->AddFunctions(functions_.begin(), functions_.end());
  functions_.clear();
}

} // namespace google_breakpad
