1c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// Copyright (c) 2006, Google Inc. 2c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// All rights reserved. 3c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// 4c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// Redistribution and use in source and binary forms, with or without 5c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// modification, are permitted provided that the following conditions are 6c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// met: 7c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// 8c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// * Redistributions of source code must retain the above copyright 9c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// notice, this list of conditions and the following disclaimer. 10c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// * Redistributions in binary form must reproduce the above 11c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// copyright notice, this list of conditions and the following disclaimer 12c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// in the documentation and/or other materials provided with the 13c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// distribution. 14c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// * Neither the name of Google Inc. nor the names of its 15c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// contributors may be used to endorse or promote products derived from 16c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// this software without specific prior written permission. 17c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// 18c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai 30c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// simple_symbol_supplier.cc: A simple SymbolSupplier implementation 31c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// 32c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// See simple_symbol_supplier.h for documentation. 33c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// 34c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai// Author: Mark Mentovai 35c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai 36e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include "processor/simple_symbol_supplier.h" 37e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek 38e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <assert.h> 395b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com#include <string.h> 40a14ef803d70614a01725a269acb509027fe84942mmentovai#include <sys/types.h> 41a14ef803d70614a01725a269acb509027fe84942mmentovai#include <sys/stat.h> 42a14ef803d70614a01725a269acb509027fe84942mmentovai 439fcf4db315427032a92078d1212fece2655bf049mmentovai#include <algorithm> 442ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid#include <iostream> 452ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid#include <fstream> 46f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner 474e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com#include "common/using_std_string.h" 48e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/code_module.h" 49e5dc60822e5938fea2ae892ccddb906641ba174emmentovai#include "google_breakpad/processor/system_info.h" 5065571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai#include "processor/logging.h" 51c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai#include "processor/pathname_stripper.h" 52c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai 53e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad { 54c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai 55a14ef803d70614a01725a269acb509027fe84942mmentovaistatic bool file_exists(const string &file_name) { 56a14ef803d70614a01725a269acb509027fe84942mmentovai struct stat sb; 57a14ef803d70614a01725a269acb509027fe84942mmentovai return stat(file_name.c_str(), &sb) == 0; 58a14ef803d70614a01725a269acb509027fe84942mmentovai} 59a14ef803d70614a01725a269acb509027fe84942mmentovai 60a14ef803d70614a01725a269acb509027fe84942mmentovaiSymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile( 61a14ef803d70614a01725a269acb509027fe84942mmentovai const CodeModule *module, const SystemInfo *system_info, 62a14ef803d70614a01725a269acb509027fe84942mmentovai string *symbol_file) { 6365571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai BPLOG_IF(ERROR, !symbol_file) << "SimpleSymbolSupplier::GetSymbolFile " 6465571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai "requires |symbol_file|"; 65a14ef803d70614a01725a269acb509027fe84942mmentovai assert(symbol_file); 6665571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai symbol_file->clear(); 6765571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai 68a14ef803d70614a01725a269acb509027fe84942mmentovai for (unsigned int path_index = 0; path_index < paths_.size(); ++path_index) { 69a14ef803d70614a01725a269acb509027fe84942mmentovai SymbolResult result; 700fd2f1ae2152782f2127c56fb5302002c95502d3nealsid if ((result = GetSymbolFileAtPathFromRoot(module, system_info, 710fd2f1ae2152782f2127c56fb5302002c95502d3nealsid paths_[path_index], 720fd2f1ae2152782f2127c56fb5302002c95502d3nealsid symbol_file)) != NOT_FOUND) { 73a14ef803d70614a01725a269acb509027fe84942mmentovai return result; 74a14ef803d70614a01725a269acb509027fe84942mmentovai } 75a14ef803d70614a01725a269acb509027fe84942mmentovai } 76a14ef803d70614a01725a269acb509027fe84942mmentovai return NOT_FOUND; 77a14ef803d70614a01725a269acb509027fe84942mmentovai} 78a14ef803d70614a01725a269acb509027fe84942mmentovai 792ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsidSymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile( 802ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid const CodeModule *module, 812ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid const SystemInfo *system_info, 822ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid string *symbol_file, 832ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid string *symbol_data) { 842ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid assert(symbol_data); 852ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid symbol_data->clear(); 862ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid 872d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com SymbolSupplier::SymbolResult s = GetSymbolFile(module, system_info, 882d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com symbol_file); 892ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid if (s == FOUND) { 902ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid std::ifstream in(symbol_file->c_str()); 914e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com std::getline(in, *symbol_data, string::traits_type::to_char_type( 924e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com string::traits_type::eof())); 932ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid in.close(); 942ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid } 952ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid return s; 962ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid} 972ad976ef0ba44f36842b9b7a11848f6b40fd25d5nealsid 985b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.comSymbolSupplier::SymbolResult SimpleSymbolSupplier::GetCStringSymbolData( 995b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com const CodeModule *module, 1005b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com const SystemInfo *system_info, 1015b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com string *symbol_file, 1022d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com char **symbol_data, 1032d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com size_t *symbol_data_size) { 1045b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com assert(symbol_data); 1052d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com assert(symbol_data_size); 1065b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com 1075b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com string symbol_data_string; 1085b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com SymbolSupplier::SymbolResult s = 1095b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com GetSymbolFile(module, system_info, symbol_file, &symbol_data_string); 1105b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com 1115b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com if (s == FOUND) { 1122d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com *symbol_data_size = symbol_data_string.size() + 1; 1132d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com *symbol_data = new char[*symbol_data_size]; 114a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com if (*symbol_data == NULL) { 1152d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com BPLOG(ERROR) << "Memory allocation for size " << *symbol_data_size 1162d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com << " failed"; 117a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com return INTERRUPT; 118a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com } 1192d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com memcpy(*symbol_data, symbol_data_string.c_str(), symbol_data_string.size()); 1202d460c37d16a99fd4bcdac045298e87b6b5735b0ivan.penkov@gmail.com (*symbol_data)[symbol_data_string.size()] = '\0'; 121a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com memory_buffers_.insert(make_pair(module->code_file(), *symbol_data)); 1225b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com } 1235b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com return s; 1245b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com} 1255b117cf53af46f357d28761ced3a1d94aeb5df91SiyangXie@gmail.com 126a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.comvoid SimpleSymbolSupplier::FreeSymbolData(const CodeModule *module) { 127a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com if (!module) { 128a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com BPLOG(INFO) << "Cannot free symbol data buffer for NULL module"; 129a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com return; 130a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com } 131a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com 132a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com map<string, char *>::iterator it = memory_buffers_.find(module->code_file()); 133a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com if (it == memory_buffers_.end()) { 134a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com BPLOG(INFO) << "Cannot find symbol data buffer for module " 135a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com << module->code_file(); 136a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com return; 137a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com } 138a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com delete [] it->second; 139a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com memory_buffers_.erase(it); 140a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com} 141a8c1c466a16ad4c85bfd1ca20ab8fc056d669abeSiyangXie@gmail.com 1420fd2f1ae2152782f2127c56fb5302002c95502d3nealsidSymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFileAtPathFromRoot( 14397d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai const CodeModule *module, const SystemInfo *system_info, 14497d392dc4b60f0099cd7ad8c8a5f06581a532392mmentovai const string &root_path, string *symbol_file) { 14565571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai BPLOG_IF(ERROR, !symbol_file) << "SimpleSymbolSupplier::GetSymbolFileAtPath " 14665571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai "requires |symbol_file|"; 147f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner assert(symbol_file); 14865571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai symbol_file->clear(); 14965571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai 150c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai if (!module) 151f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner return NOT_FOUND; 152c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai 153c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai // Start with the base path. 1547573d1dd4412171794f76bea833e4ae5f72929f8mmentovai string path = root_path; 155c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai 156db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai // Append the debug (pdb) file name as a directory name. 157c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai path.append("/"); 158db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai string debug_file_name = PathnameStripper::File(module->debug_file()); 15965571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai if (debug_file_name.empty()) { 16065571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai BPLOG(ERROR) << "Can't construct symbol file path without debug_file " 16165571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai "(code_file = " << 16265571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai PathnameStripper::File(module->code_file()) << ")"; 163f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner return NOT_FOUND; 16465571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai } 165db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai path.append(debug_file_name); 166c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai 167db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai // Append the identifier as a directory name. 168c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai path.append("/"); 169db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai string identifier = module->debug_identifier(); 17065571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai if (identifier.empty()) { 17165571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai BPLOG(ERROR) << "Can't construct symbol file path without debug_identifier " 17265571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai "(code_file = " << 17365571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai PathnameStripper::File(module->code_file()) << 17465571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai ", debug_file = " << debug_file_name << ")"; 175f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner return NOT_FOUND; 17665571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai } 177db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai path.append(identifier); 178c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai 179db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai // Transform the debug file name into one ending in .sym. If the existing 180c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai // name ends in .pdb, strip the .pdb. Otherwise, add .sym to the non-.pdb 181c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai // name. 182c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai path.append("/"); 1838408a209cded9d54ab1505bad6bdf49b02f0f27dted.mielczarek string debug_file_extension; 1848408a209cded9d54ab1505bad6bdf49b02f0f27dted.mielczarek if (debug_file_name.size() > 4) 1858408a209cded9d54ab1505bad6bdf49b02f0f27dted.mielczarek debug_file_extension = debug_file_name.substr(debug_file_name.size() - 4); 1860e6f5c95d7b791c2a7d2c4056d9746f3fa1ff166mmentovai std::transform(debug_file_extension.begin(), debug_file_extension.end(), 1870e6f5c95d7b791c2a7d2c4056d9746f3fa1ff166mmentovai debug_file_extension.begin(), tolower); 188db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai if (debug_file_extension == ".pdb") { 189db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai path.append(debug_file_name.substr(0, debug_file_name.size() - 4)); 190c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai } else { 191db3342a10ec30902aa9018b80e1d9a40bd01c487mmentovai path.append(debug_file_name); 192c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai } 193c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai path.append(".sym"); 194c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai 19565571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai if (!file_exists(path)) { 19665571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai BPLOG(INFO) << "No symbol file at " << path; 197a14ef803d70614a01725a269acb509027fe84942mmentovai return NOT_FOUND; 19865571f17edb82d122b5f6dc741bd7d4b9e315e1bmmentovai } 199a14ef803d70614a01725a269acb509027fe84942mmentovai 200f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner *symbol_file = path; 201f33b8d2d07a057fdd667c2e0db629ba7cbc37cc3bryner return FOUND; 202c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai} 203c34850a2023442a22fa653ab8546e72738ed2dd4mmentovai 204e5dc60822e5938fea2ae892ccddb906641ba174emmentovai} // namespace google_breakpad 205