183e085b7a331c96237cf8e814f97b3ef4c36a70fjimblandy// Copyright (c) 2010 Google Inc. 25a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// All rights reserved. 35a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// 45a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// Redistribution and use in source and binary forms, with or without 55a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// modification, are permitted provided that the following conditions are 65a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// met: 75a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// 85a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// * Redistributions of source code must retain the above copyright 95a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// notice, this list of conditions and the following disclaimer. 105a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// * Redistributions in binary form must reproduce the above 115a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// copyright notice, this list of conditions and the following disclaimer 125a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// in the documentation and/or other materials provided with the 135a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// distribution. 145a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// * Neither the name of Google Inc. nor the names of its 155a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// contributors may be used to endorse or promote products derived from 165a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// this software without specific prior written permission. 175a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// 185a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 30c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 31c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy 32b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandy// dump_stabs.cc --- implement the StabsToModule class. 335a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 34b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandy#include <assert.h> 355a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy#include <cxxabi.h> 36b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandy#include <stdarg.h> 373ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek#include <stdio.h> 385a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 395a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy#include <algorithm> 405a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 41b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandy#include "common/stabs_to_module.h" 424e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com#include "common/using_std_string.h" 435a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 445a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandynamespace google_breakpad { 455a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 465a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// Demangle using abi call. 475a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy// Older GCC may not support it. 485a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandystatic string Demangle(const string &mangled) { 495a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy int status = 0; 505a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy char *demangled = abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status); 515a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy if (status == 0 && demangled != NULL) { 525a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy string str(demangled); 535a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy free(demangled); 545a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy return str; 555a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy } 565a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy return string(mangled); 575a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy} 585a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 59b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandyStabsToModule::~StabsToModule() { 6056e7a3c65df2a89cd35ee13800284dc29fb90aadjimblandy // Free any functions we've accumulated but not added to the module. 610dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org for (vector<Module::Function *>::const_iterator func_it = functions_.begin(); 6256e7a3c65df2a89cd35ee13800284dc29fb90aadjimblandy func_it != functions_.end(); func_it++) 6356e7a3c65df2a89cd35ee13800284dc29fb90aadjimblandy delete *func_it; 6456e7a3c65df2a89cd35ee13800284dc29fb90aadjimblandy // Free any function that we're currently within. 6556e7a3c65df2a89cd35ee13800284dc29fb90aadjimblandy delete current_function_; 6656e7a3c65df2a89cd35ee13800284dc29fb90aadjimblandy} 6756e7a3c65df2a89cd35ee13800284dc29fb90aadjimblandy 68b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandybool StabsToModule::StartCompilationUnit(const char *name, uint64_t address, 69b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandy const char *build_directory) { 7081aadb99a6acf7f1175e8c6f538a609c96b3a961jimblandy assert(!in_compilation_unit_); 7181aadb99a6acf7f1175e8c6f538a609c96b3a961jimblandy in_compilation_unit_ = true; 725a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy current_source_file_name_ = name; 735a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy current_source_file_ = module_->FindFile(name); 745a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy comp_unit_base_address_ = address; 755a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy boundaries_.push_back(static_cast<Module::Address>(address)); 765a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy return true; 775a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy} 785a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 79b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandybool StabsToModule::EndCompilationUnit(uint64_t address) { 8081aadb99a6acf7f1175e8c6f538a609c96b3a961jimblandy assert(in_compilation_unit_); 8181aadb99a6acf7f1175e8c6f538a609c96b3a961jimblandy in_compilation_unit_ = false; 825a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy comp_unit_base_address_ = 0; 835a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy current_source_file_ = NULL; 845a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy current_source_file_name_ = NULL; 855a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy if (address) 865a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy boundaries_.push_back(static_cast<Module::Address>(address)); 875a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy return true; 885a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy} 895a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 90b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandybool StabsToModule::StartFunction(const string &name, 91b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandy uint64_t address) { 925a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy assert(!current_function_); 936105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org Module::Function *f = new Module::Function(Demangle(name), address); 94b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandy f->size = 0; // We compute this in StabsToModule::Finalize(). 953e60d65111607f401461ff15981a463cde8f744ajimblandy f->parameter_size = 0; // We don't provide this information. 965a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy current_function_ = f; 975a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy boundaries_.push_back(static_cast<Module::Address>(address)); 985a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy return true; 995a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy} 1005a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 101b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandybool StabsToModule::EndFunction(uint64_t address) { 1025a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy assert(current_function_); 1035a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // Functions in this compilation unit should have address bigger 1045a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // than the compilation unit's starting address. There may be a lot 1050dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org // of duplicated entries for functions in the STABS data. We will 1060dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org // count on the Module to remove the duplicates. 1073e60d65111607f401461ff15981a463cde8f744ajimblandy if (current_function_->address >= comp_unit_base_address_) 1085a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy functions_.push_back(current_function_); 1095a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy else 1105a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy delete current_function_; 1115a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy current_function_ = NULL; 1125a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy if (address) 1135a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy boundaries_.push_back(static_cast<Module::Address>(address)); 1145a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy return true; 1155a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy} 1165a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 117b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandybool StabsToModule::Line(uint64_t address, const char *name, int number) { 1185a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy assert(current_function_); 1195a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy assert(current_source_file_); 1205a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy if (name != current_source_file_name_) { 1215a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy current_source_file_ = module_->FindFile(name); 1225a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy current_source_file_name_ = name; 1235a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy } 1245a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy Module::Line line; 1253e60d65111607f401461ff15981a463cde8f744ajimblandy line.address = address; 126b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandy line.size = 0; // We compute this in StabsToModule::Finalize(). 1273e60d65111607f401461ff15981a463cde8f744ajimblandy line.file = current_source_file_; 1283e60d65111607f401461ff15981a463cde8f744ajimblandy line.number = number; 1293e60d65111607f401461ff15981a463cde8f744ajimblandy current_function_->lines.push_back(line); 1305a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy return true; 1315a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy} 1325a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 133bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarekbool StabsToModule::Extern(const string &name, uint64_t address) { 1346105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org Module::Extern *ext = new Module::Extern(address); 135bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek // Older libstdc++ demangle implementations can crash on unexpected 136bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek // input, so be careful about what gets passed in. 137bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek if (name.compare(0, 3, "__Z") == 0) { 138bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek ext->name = Demangle(name.substr(1)); 139bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek } else if (name[0] == '_') { 140bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek ext->name = name.substr(1); 141bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek } else { 142bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek ext->name = name; 143bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek } 144bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek module_->AddExtern(ext); 145bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek return true; 146bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek} 147bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek 148b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandyvoid StabsToModule::Warning(const char *format, ...) { 1495a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy va_list args; 1505a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy va_start(args, format); 1515a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy vfprintf(stderr, format, args); 1525a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy va_end(args); 1535a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy} 1545a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 155b28be1254c0698cfd42a9abb910da3c94cf35a7fjimblandyvoid StabsToModule::Finalize() { 1565a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // Sort our boundary list, so we can search it quickly. 1575a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy sort(boundaries_.begin(), boundaries_.end()); 1585a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // Sort all functions by address, just for neatness. 1595a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy sort(functions_.begin(), functions_.end(), 1605a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy Module::Function::CompareByAddress); 1610dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org 1620dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org for (vector<Module::Function *>::const_iterator func_it = functions_.begin(); 1635a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy func_it != functions_.end(); 1645a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy func_it++) { 1655a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy Module::Function *f = *func_it; 1665a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // Compute the function f's size. 1670dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org vector<Module::Address>::const_iterator boundary 1683e60d65111607f401461ff15981a463cde8f744ajimblandy = std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address); 1695a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy if (boundary != boundaries_.end()) 1703e60d65111607f401461ff15981a463cde8f744ajimblandy f->size = *boundary - f->address; 1715a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy else 1725a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // If this is the last function in the module, and the STABS 1735a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // reader was unable to give us its ending address, then assign 1745a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // it a bogus, very large value. This will happen at most once 1755a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // per module: since we've added all functions' addresses to the 1765a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // boundary table, only one can be the last. 1773e60d65111607f401461ff15981a463cde8f744ajimblandy f->size = kFallbackSize; 1785a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 1795a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // Compute sizes for each of the function f's lines --- if it has any. 1803e60d65111607f401461ff15981a463cde8f744ajimblandy if (!f->lines.empty()) { 1813e60d65111607f401461ff15981a463cde8f744ajimblandy stable_sort(f->lines.begin(), f->lines.end(), 1825a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy Module::Line::CompareByAddress); 1833e60d65111607f401461ff15981a463cde8f744ajimblandy vector<Module::Line>::iterator last_line = f->lines.end() - 1; 1843e60d65111607f401461ff15981a463cde8f744ajimblandy for (vector<Module::Line>::iterator line_it = f->lines.begin(); 1855a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy line_it != last_line; line_it++) 1863e60d65111607f401461ff15981a463cde8f744ajimblandy line_it[0].size = line_it[1].address - line_it[0].address; 1875a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // Compute the size of the last line from f's end address. 1883e60d65111607f401461ff15981a463cde8f744ajimblandy last_line->size = (f->address + f->size) - last_line->address; 1895a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy } 1905a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy } 1915a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // Now that everything has a size, add our functions to the module, and 1925a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy // dispose of our private list. 1935a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy module_->AddFunctions(functions_.begin(), functions_.end()); 1945a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy functions_.clear(); 1955a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy} 1965a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy 1975a6e1d3f03ec2c8ccbb63edaccf00ecd02e148bcjimblandy} // namespace google_breakpad 198