15b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// Copyright (c) 2010 Google Inc.
25b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// All rights reserved.
35b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com//
45b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// Redistribution and use in source and binary forms, with or without
55b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// modification, are permitted provided that the following conditions are
65b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// met:
75b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com//
85b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com//     * Redistributions of source code must retain the above copyright
95b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// notice, this list of conditions and the following disclaimer.
105b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com//     * Redistributions in binary form must reproduce the above
115b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// copyright notice, this list of conditions and the following disclaimer
125b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// in the documentation and/or other materials provided with the
135b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// distribution.
145b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com//     * Neither the name of Google Inc. nor the names of its
155b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// contributors may be used to endorse or promote products derived from
165b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// this software without specific prior written permission.
175b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com//
185b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com//
305b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// source_line_resolver_base.cc: Implementation of SourceLineResolverBase.
315b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com//
325b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// See source_line_resolver_base.h and source_line_resolver_base_types.h for
335b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// more documentation.
345b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com//
355b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com// Author: Siyang Xie (lambxsy@google.com)
365b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
375b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com#include <stdio.h>
385b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com#include <string.h>
395b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com#include <sys/stat.h>
405b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
415b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com#include <map>
425b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com#include <utility>
435b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
445b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com#include "google_breakpad/processor/source_line_resolver_base.h"
455b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com#include "processor/source_line_resolver_base_types.h"
465b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com#include "processor/module_factory.h"
475b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
485b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comusing std::map;
495b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comusing std::make_pair;
505b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
515b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comnamespace google_breakpad {
525b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
535b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comSourceLineResolverBase::SourceLineResolverBase(
545b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    ModuleFactory *module_factory)
555b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  : modules_(new ModuleMap),
562d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    corrupt_modules_(new ModuleSet),
57a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    memory_buffers_(new MemoryMap),
585b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    module_factory_(module_factory) {
595b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
605b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
615b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comSourceLineResolverBase::~SourceLineResolverBase() {
625b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  ModuleMap::iterator it;
635b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  // Iterate through ModuleMap and delete all loaded modules.
645b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  for (it = modules_->begin(); it != modules_->end(); ++it) {
655b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    // Delete individual module.
665b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    delete it->second;
675b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
685b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  // Delete the map of modules.
695b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  delete modules_;
702d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  modules_ = NULL;
712d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com
722d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  // Delete the set of corrupt modules.
732d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  delete corrupt_modules_;
742d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  corrupt_modules_ = NULL;
755b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
76a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  MemoryMap::iterator iter = memory_buffers_->begin();
77a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  for (; iter != memory_buffers_->end(); ++iter) {
78a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    delete [] iter->second;
79a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  }
80a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  // Delete the map of memory buffers.
81a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  delete memory_buffers_;
822d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  memory_buffers_ = NULL;
835b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
84a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  delete module_factory_;
852d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  module_factory_ = NULL;
86a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com}
875b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
882d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.combool SourceLineResolverBase::ReadSymbolFile(const string &map_file,
892d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                                            char **symbol_data,
902d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                                            size_t *symbol_data_size) {
912d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  if (symbol_data == NULL || symbol_data_size == NULL) {
925b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    BPLOG(ERROR) << "Could not Read file into Null memory pointer";
935b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
945b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
955b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
965b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  struct stat buf;
975b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  int error_code = stat(map_file.c_str(), &buf);
985b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (error_code == -1) {
995b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    string error_string;
1004fd4efe1c615da174abe42f3ca40662bb50763bfthestig@chromium.org    error_code = ErrnoString(&error_string);
1015b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    BPLOG(ERROR) << "Could not open " << map_file <<
1025b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com        ", error " << error_code << ": " << error_string;
1035b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
1045b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
1055b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1065b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  off_t file_size = buf.st_size;
1075b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1085b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  // Allocate memory for file contents, plus a null terminator
1095b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  // since we may use strtok() on the contents.
1102d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  *symbol_data_size = file_size + 1;
111a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  *symbol_data = new char[file_size + 1];
1125b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1135b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (*symbol_data == NULL) {
1145b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    BPLOG(ERROR) << "Could not allocate memory for " << map_file;
1155b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
1165b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
1175b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1185b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  BPLOG(INFO) << "Opening " << map_file;
1195b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1205b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  FILE *f = fopen(map_file.c_str(), "rt");
1215b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (!f) {
1225b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    string error_string;
1234fd4efe1c615da174abe42f3ca40662bb50763bfthestig@chromium.org    error_code = ErrnoString(&error_string);
1245b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    BPLOG(ERROR) << "Could not open " << map_file <<
1255b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com        ", error " << error_code << ": " << error_string;
126a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    delete [] (*symbol_data);
1275b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    *symbol_data = NULL;
1285b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
1295b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
1305b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1315b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  AutoFileCloser closer(f);
1325b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1335b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  int items_read = 0;
1345b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1355b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  items_read = fread(*symbol_data, 1, file_size, f);
1365b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1375b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (items_read != file_size) {
1385b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    string error_string;
1394fd4efe1c615da174abe42f3ca40662bb50763bfthestig@chromium.org    error_code = ErrnoString(&error_string);
1405b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    BPLOG(ERROR) << "Could not slurp " << map_file <<
1415b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com        ", error " << error_code << ": " << error_string;
142a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    delete [] (*symbol_data);
1435b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    *symbol_data = NULL;
1445b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
1455b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
1465b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1475b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  (*symbol_data)[file_size] = '\0';
1485b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  return true;
1495b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
1505b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1515b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.combool SourceLineResolverBase::LoadModule(const CodeModule *module,
1525b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com                                        const string &map_file) {
1535b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (module == NULL)
1545b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
1555b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1565b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  // Make sure we don't already have a module with the given name.
1575b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (modules_->find(module->code_file()) != modules_->end()) {
1585b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    BPLOG(INFO) << "Symbols for module " << module->code_file()
1595b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com                << " already loaded";
1605b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
1615b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
1625b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1635b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  BPLOG(INFO) << "Loading symbols for module " << module->code_file()
1645b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com              << " from " << map_file;
1655b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1665b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  char *memory_buffer;
1672d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  size_t memory_buffer_size;
1682d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  if (!ReadSymbolFile(map_file, &memory_buffer, &memory_buffer_size))
1695b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
1705b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1715b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  BPLOG(INFO) << "Read symbol file " << map_file << " succeeded";
1725b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1732d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  bool load_result = LoadModuleUsingMemoryBuffer(module, memory_buffer,
1742d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                                                 memory_buffer_size);
175a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com
176a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  if (load_result && !ShouldDeleteMemoryBufferAfterLoadModule()) {
177a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    // memory_buffer has to stay alive as long as the module.
178a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    memory_buffers_->insert(make_pair(module->code_file(), memory_buffer));
179a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  } else {
180a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    delete [] memory_buffer;
181a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  }
1825b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
183a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  return load_result;
1845b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
1855b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
1865b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.combool SourceLineResolverBase::LoadModuleUsingMapBuffer(
1875b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    const CodeModule *module, const string &map_buffer) {
188a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  if (module == NULL)
189a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    return false;
190a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com
191a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  // Make sure we don't already have a module with the given name.
192a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  if (modules_->find(module->code_file()) != modules_->end()) {
193a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    BPLOG(INFO) << "Symbols for module " << module->code_file()
194a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com                << " already loaded";
1955b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
196a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  }
197a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com
1982d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  size_t memory_buffer_size = map_buffer.size() + 1;
1992d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  char *memory_buffer = new char[memory_buffer_size];
200a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  if (memory_buffer == NULL) {
201a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    BPLOG(ERROR) << "Could not allocate memory for " << module->code_file();
202a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    return false;
203a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  }
2045b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2055b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  // Can't use strcpy, as the data may contain '\0's before the end.
2065b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  memcpy(memory_buffer, map_buffer.c_str(), map_buffer.size());
2075b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  memory_buffer[map_buffer.size()] = '\0';
2085b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2092d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  bool load_result = LoadModuleUsingMemoryBuffer(module, memory_buffer,
2102d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                                                 memory_buffer_size);
211a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com
212a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  if (load_result && !ShouldDeleteMemoryBufferAfterLoadModule()) {
213a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    // memory_buffer has to stay alive as long as the module.
214a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    memory_buffers_->insert(make_pair(module->code_file(), memory_buffer));
215a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  } else {
216a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    delete [] memory_buffer;
217a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  }
2185b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
219a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  return load_result;
2205b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
2215b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2225b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.combool SourceLineResolverBase::LoadModuleUsingMemoryBuffer(
2232d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    const CodeModule *module,
2242d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    char *memory_buffer,
2252d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    size_t memory_buffer_size) {
226a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  if (!module)
2275b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
2285b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2295b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  // Make sure we don't already have a module with the given name.
2305b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (modules_->find(module->code_file()) != modules_->end()) {
2315b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    BPLOG(INFO) << "Symbols for module " << module->code_file()
2325b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com                << " already loaded";
2335b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
2345b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
2355b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2365b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  BPLOG(INFO) << "Loading symbols for module " << module->code_file()
237a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com             << " from memory buffer";
2385b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2395b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  Module *basic_module = module_factory_->CreateModule(module->code_file());
2405b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2415b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  // Ownership of memory is NOT transfered to Module::LoadMapFromMemory().
2422d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  if (!basic_module->LoadMapFromMemory(memory_buffer, memory_buffer_size)) {
2432d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    BPLOG(ERROR) << "Too many error while parsing symbol data for module "
2442d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com                 << module->code_file();
2452d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    // Returning false from here would be an indication that the symbols for
2462d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    // this module are missing which would be wrong.  Intentionally fall through
2472d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    // and add the module to both the modules_ and the corrupt_modules_ lists.
2482d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    assert(basic_module->IsCorrupt());
2495b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
2505b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2515b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  modules_->insert(make_pair(module->code_file(), basic_module));
2522d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  if (basic_module->IsCorrupt()) {
2532d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    corrupt_modules_->insert(module->code_file());
2542d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  }
255a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  return true;
256a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com}
257a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com
258a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.combool SourceLineResolverBase::ShouldDeleteMemoryBufferAfterLoadModule() {
2595b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  return true;
2605b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
2615b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2625b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comvoid SourceLineResolverBase::UnloadModule(const CodeModule *code_module) {
2635b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (!code_module)
2645b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return;
2655b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2664fd4efe1c615da174abe42f3ca40662bb50763bfthestig@chromium.org  ModuleMap::iterator mod_iter = modules_->find(code_module->code_file());
2674fd4efe1c615da174abe42f3ca40662bb50763bfthestig@chromium.org  if (mod_iter != modules_->end()) {
2684fd4efe1c615da174abe42f3ca40662bb50763bfthestig@chromium.org    Module *symbol_module = mod_iter->second;
2695b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    delete symbol_module;
2702d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    corrupt_modules_->erase(mod_iter->first);
2714fd4efe1c615da174abe42f3ca40662bb50763bfthestig@chromium.org    modules_->erase(mod_iter);
2725b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
2735b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
274a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  if (ShouldDeleteMemoryBufferAfterLoadModule()) {
275a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    // No-op.  Because we never store any memory buffers.
276a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  } else {
277a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    // There may be a buffer stored locally, we need to find and delete it.
278a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    MemoryMap::iterator iter = memory_buffers_->find(code_module->code_file());
279a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    if (iter != memory_buffers_->end()) {
280a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com      delete [] iter->second;
281a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com      memory_buffers_->erase(iter);
282a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com    }
283a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com  }
2845b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
2855b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2865b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.combool SourceLineResolverBase::HasModule(const CodeModule *module) {
2875b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (!module)
2885b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    return false;
2895b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  return modules_->find(module->code_file()) != modules_->end();
2905b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
2915b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
2922d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.combool SourceLineResolverBase::IsModuleCorrupt(const CodeModule *module) {
2932d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  if (!module)
2942d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com    return false;
2952d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com  return corrupt_modules_->find(module->code_file()) != corrupt_modules_->end();
2962d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com}
2972d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com
2985b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comvoid SourceLineResolverBase::FillSourceLineInfo(StackFrame *frame) {
2995b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (frame->module) {
3005b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
3015b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    if (it != modules_->end()) {
3025b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com      it->second->LookupAddress(frame);
3035b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    }
3045b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
3055b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
3065b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
3075b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comWindowsFrameInfo *SourceLineResolverBase::FindWindowsFrameInfo(
3085b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    const StackFrame *frame) {
3095b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (frame->module) {
3105b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
3115b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    if (it != modules_->end()) {
3125b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com      return it->second->FindWindowsFrameInfo(frame);
3135b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    }
3145b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
3155b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  return NULL;
3165b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
3175b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
3185b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comCFIFrameInfo *SourceLineResolverBase::FindCFIFrameInfo(
3195b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    const StackFrame *frame) {
3205b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  if (frame->module) {
3215b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
3225b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    if (it != modules_->end()) {
3235b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com      return it->second->FindCFIFrameInfo(frame);
3245b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    }
3255b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  }
3265b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  return NULL;
3275b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
3285b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
3295b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.combool SourceLineResolverBase::CompareString::operator()(
3305b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    const string &s1, const string &s2) const {
3315b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  return strcmp(s1.c_str(), s2.c_str()) < 0;
3325b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
3335b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
3345b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.combool SourceLineResolverBase::Module::ParseCFIRuleSet(
3355b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com    const string &rule_set, CFIFrameInfo *frame_info) const {
3365b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  CFIFrameInfoParseHandler handler(frame_info);
3375b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  CFIRuleParser parser(&handler);
3385b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com  return parser.Parse(rule_set);
3395b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}
3405b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com
3415b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com}  // namespace google_breakpad
342