1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,227 @@ 1.4 +// Copyright (c) 2010 Google Inc. All Rights Reserved. 1.5 +// 1.6 +// Redistribution and use in source and binary forms, with or without 1.7 +// modification, are permitted provided that the following conditions are 1.8 +// met: 1.9 +// 1.10 +// * Redistributions of source code must retain the above copyright 1.11 +// notice, this list of conditions and the following disclaimer. 1.12 +// * Redistributions in binary form must reproduce the above 1.13 +// copyright notice, this list of conditions and the following disclaimer 1.14 +// in the documentation and/or other materials provided with the 1.15 +// distribution. 1.16 +// * Neither the name of Google Inc. nor the names of its 1.17 +// contributors may be used to endorse or promote products derived from 1.18 +// this software without specific prior written permission. 1.19 +// 1.20 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.21 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.22 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.23 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.24 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.25 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.26 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.27 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.28 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.29 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.30 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.31 + 1.32 +// This is a client for the dwarf2reader to extract function and line 1.33 +// information from the debug info. 1.34 + 1.35 +#include <assert.h> 1.36 +#include <limits.h> 1.37 +#include <stdio.h> 1.38 + 1.39 +#include <map> 1.40 +#include <queue> 1.41 +#include <vector> 1.42 +#include <memory> 1.43 + 1.44 +#include "common/dwarf/functioninfo.h" 1.45 +#include "common/dwarf/bytereader.h" 1.46 +#include "common/using_std_string.h" 1.47 + 1.48 +namespace dwarf2reader { 1.49 + 1.50 +CULineInfoHandler::CULineInfoHandler(std::vector<SourceFileInfo>* files, 1.51 + std::vector<string>* dirs, 1.52 + LineMap* linemap):linemap_(linemap), 1.53 + files_(files), 1.54 + dirs_(dirs) { 1.55 + // The dirs and files are 1 indexed, so just make sure we put 1.56 + // nothing in the 0 vector. 1.57 + assert(dirs->size() == 0); 1.58 + assert(files->size() == 0); 1.59 + dirs->push_back(""); 1.60 + SourceFileInfo s; 1.61 + s.name = ""; 1.62 + s.lowpc = ULLONG_MAX; 1.63 + files->push_back(s); 1.64 +} 1.65 + 1.66 +void CULineInfoHandler::DefineDir(const string& name, uint32 dir_num) { 1.67 + // These should never come out of order, actually 1.68 + assert(dir_num == dirs_->size()); 1.69 + dirs_->push_back(name); 1.70 +} 1.71 + 1.72 +void CULineInfoHandler::DefineFile(const string& name, 1.73 + int32 file_num, uint32 dir_num, 1.74 + uint64 mod_time, uint64 length) { 1.75 + assert(dir_num >= 0); 1.76 + assert(dir_num < dirs_->size()); 1.77 + 1.78 + // These should never come out of order, actually. 1.79 + if (file_num == (int32)files_->size() || file_num == -1) { 1.80 + string dir = dirs_->at(dir_num); 1.81 + 1.82 + SourceFileInfo s; 1.83 + s.lowpc = ULLONG_MAX; 1.84 + 1.85 + if (dir == "") { 1.86 + s.name = name; 1.87 + } else { 1.88 + s.name = dir + "/" + name; 1.89 + } 1.90 + 1.91 + files_->push_back(s); 1.92 + } else { 1.93 + fprintf(stderr, "error in DefineFile"); 1.94 + } 1.95 +} 1.96 + 1.97 +void CULineInfoHandler::AddLine(uint64 address, uint64 length, uint32 file_num, 1.98 + uint32 line_num, uint32 column_num) { 1.99 + if (file_num < files_->size()) { 1.100 + linemap_->insert( 1.101 + std::make_pair(address, 1.102 + std::make_pair(files_->at(file_num).name.c_str(), 1.103 + line_num))); 1.104 + 1.105 + if(address < files_->at(file_num).lowpc) { 1.106 + files_->at(file_num).lowpc = address; 1.107 + } 1.108 + } else { 1.109 + fprintf(stderr,"error in AddLine"); 1.110 + } 1.111 +} 1.112 + 1.113 +bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset, 1.114 + uint8 address_size, 1.115 + uint8 offset_size, 1.116 + uint64 cu_length, 1.117 + uint8 dwarf_version) { 1.118 + current_compilation_unit_offset_ = offset; 1.119 + return true; 1.120 +} 1.121 + 1.122 + 1.123 +// For function info, we only care about subprograms and inlined 1.124 +// subroutines. For line info, the DW_AT_stmt_list lives in the 1.125 +// compile unit tag. 1.126 + 1.127 +bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag) { 1.128 + switch (tag) { 1.129 + case DW_TAG_subprogram: 1.130 + case DW_TAG_inlined_subroutine: { 1.131 + current_function_info_ = new FunctionInfo; 1.132 + current_function_info_->lowpc = current_function_info_->highpc = 0; 1.133 + current_function_info_->name = ""; 1.134 + current_function_info_->line = 0; 1.135 + current_function_info_->file = ""; 1.136 + offset_to_funcinfo_->insert(std::make_pair(offset, 1.137 + current_function_info_)); 1.138 + }; 1.139 + // FALLTHROUGH 1.140 + case DW_TAG_compile_unit: 1.141 + return true; 1.142 + default: 1.143 + return false; 1.144 + } 1.145 + return false; 1.146 +} 1.147 + 1.148 +// Only care about the name attribute for functions 1.149 + 1.150 +void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset, 1.151 + enum DwarfAttribute attr, 1.152 + enum DwarfForm form, 1.153 + const string &data) { 1.154 + if (current_function_info_) { 1.155 + if (attr == DW_AT_name) 1.156 + current_function_info_->name = data; 1.157 + else if(attr == DW_AT_MIPS_linkage_name) 1.158 + current_function_info_->mangled_name = data; 1.159 + } 1.160 +} 1.161 + 1.162 +void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset, 1.163 + enum DwarfAttribute attr, 1.164 + enum DwarfForm form, 1.165 + uint64 data) { 1.166 + if (attr == DW_AT_stmt_list) { 1.167 + SectionMap::const_iterator iter = sections_.find("__debug_line"); 1.168 + assert(iter != sections_.end()); 1.169 + 1.170 + // this should be a scoped_ptr but we dont' use boost :-( 1.171 + std::auto_ptr<LineInfo> lireader(new LineInfo(iter->second.first + data, 1.172 + iter->second.second - data, 1.173 + reader_, linehandler_)); 1.174 + lireader->Start(); 1.175 + } else if (current_function_info_) { 1.176 + switch (attr) { 1.177 + case DW_AT_low_pc: 1.178 + current_function_info_->lowpc = data; 1.179 + break; 1.180 + case DW_AT_high_pc: 1.181 + current_function_info_->highpc = data; 1.182 + break; 1.183 + case DW_AT_decl_line: 1.184 + current_function_info_->line = data; 1.185 + break; 1.186 + case DW_AT_decl_file: 1.187 + current_function_info_->file = files_->at(data).name; 1.188 + break; 1.189 + default: 1.190 + break; 1.191 + } 1.192 + } 1.193 +} 1.194 + 1.195 +void CUFunctionInfoHandler::ProcessAttributeReference(uint64 offset, 1.196 + enum DwarfAttribute attr, 1.197 + enum DwarfForm form, 1.198 + uint64 data) { 1.199 + if (current_function_info_) { 1.200 + switch (attr) { 1.201 + case DW_AT_specification: { 1.202 + // Some functions have a "specification" attribute 1.203 + // which means they were defined elsewhere. The name 1.204 + // attribute is not repeated, and must be taken from 1.205 + // the specification DIE. Here we'll assume that 1.206 + // any DIE referenced in this manner will already have 1.207 + // been seen, but that's not really required by the spec. 1.208 + FunctionMap::iterator iter = offset_to_funcinfo_->find(data); 1.209 + if (iter != offset_to_funcinfo_->end()) { 1.210 + current_function_info_->name = iter->second->name; 1.211 + current_function_info_->mangled_name = iter->second->mangled_name; 1.212 + } else { 1.213 + // If you hit this, this code probably needs to be rewritten. 1.214 + fprintf(stderr, "Error: DW_AT_specification was seen before the referenced DIE! (Looking for DIE at offset %08llx, in DIE at offset %08llx)\n", data, offset); 1.215 + } 1.216 + break; 1.217 + } 1.218 + default: 1.219 + break; 1.220 + } 1.221 + } 1.222 +} 1.223 + 1.224 +void CUFunctionInfoHandler::EndDIE(uint64 offset) { 1.225 + if (current_function_info_ && current_function_info_->lowpc) 1.226 + address_to_funcinfo_->insert(std::make_pair(current_function_info_->lowpc, 1.227 + current_function_info_)); 1.228 +} 1.229 + 1.230 +} // namespace dwarf2reader