/thirdparty/breakpad/common/dwarf/functioninfo.cc
C++ | 229 lines | 156 code | 27 blank | 46 comment | 34 complexity | 56173f41169047002500e42a01090abe MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, GPL-3.0, GPL-2.0
- // 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.
- // This is a client for the dwarf2reader to extract function and line
- // information from the debug info.
- #include <assert.h>
- #include <limits.h>
- #include <stdio.h>
- #include <map>
- #include <queue>
- #include <vector>
- #include <memory>
- #include "common/dwarf/functioninfo.h"
- #include "common/dwarf/bytereader.h"
- namespace dwarf2reader {
- CULineInfoHandler::CULineInfoHandler(std::vector<SourceFileInfo>* files,
- std::vector<std::string>* dirs,
- LineMap* linemap):linemap_(linemap),
- files_(files),
- dirs_(dirs) {
- // The dirs and files are 1 indexed, so just make sure we put
- // nothing in the 0 vector.
- assert(dirs->size() == 0);
- assert(files->size() == 0);
- dirs->push_back("");
- SourceFileInfo s;
- s.name = "";
- s.lowpc = ULLONG_MAX;
- files->push_back(s);
- }
- void CULineInfoHandler::DefineDir(const std::string& name, uint32 dir_num) {
- // These should never come out of order, actually
- assert(dir_num == dirs_->size());
- dirs_->push_back(name);
- }
- void CULineInfoHandler::DefineFile(const std::string& name,
- int32 file_num, uint32 dir_num,
- uint64 mod_time, uint64 length) {
- assert(dir_num >= 0);
- assert(dir_num < dirs_->size());
- // These should never come out of order, actually.
- if (file_num == (int32)files_->size() || file_num == -1) {
- std::string dir = dirs_->at(dir_num);
- SourceFileInfo s;
- s.lowpc = ULLONG_MAX;
- if (dir == "") {
- s.name = name;
- } else {
- s.name = dir + "/" + name;
- }
- files_->push_back(s);
- } else {
- fprintf(stderr, "error in DefineFile");
- }
- }
- void CULineInfoHandler::AddLine(uint64 address, uint64 length, uint32 file_num,
- uint32 line_num, uint32 column_num) {
- if (file_num < files_->size()) {
- linemap_->insert(
- std::make_pair(address,
- std::make_pair(files_->at(file_num).name.c_str(),
- line_num)));
- if(address < files_->at(file_num).lowpc) {
- files_->at(file_num).lowpc = address;
- }
- } else {
- fprintf(stderr,"error in AddLine");
- }
- }
- bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset,
- uint8 address_size,
- uint8 offset_size,
- uint64 cu_length,
- uint8 dwarf_version) {
- current_compilation_unit_offset_ = offset;
- return true;
- }
- // For function info, we only care about subprograms and inlined
- // subroutines. For line info, the DW_AT_stmt_list lives in the
- // compile unit tag.
- bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag,
- const AttributeList& attrs) {
- switch (tag) {
- case DW_TAG_subprogram:
- case DW_TAG_inlined_subroutine: {
- current_function_info_ = new FunctionInfo;
- current_function_info_->lowpc = current_function_info_->highpc = 0;
- current_function_info_->name = "";
- current_function_info_->line = 0;
- current_function_info_->file = "";
- offset_to_funcinfo_->insert(std::make_pair(offset,
- current_function_info_));
- };
- // FALLTHROUGH
- case DW_TAG_compile_unit:
- return true;
- default:
- return false;
- }
- return false;
- }
- // Only care about the name attribute for functions
- void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const std::string &data) {
- if (current_function_info_) {
- if (attr == DW_AT_name)
- current_function_info_->name = data;
- else if(attr == DW_AT_MIPS_linkage_name)
- current_function_info_->mangled_name = data;
- }
- }
- void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- if (attr == DW_AT_stmt_list) {
- SectionMap::const_iterator iter = sections_.find("__debug_line");
- assert(iter != sections_.end());
- // this should be a scoped_ptr but we dont' use boost :-(
- std::auto_ptr<LineInfo> lireader(new LineInfo(iter->second.first + data,
- iter->second.second - data,
- reader_, linehandler_));
- lireader->Start();
- } else if (current_function_info_) {
- switch (attr) {
- case DW_AT_low_pc:
- current_function_info_->lowpc = data;
- break;
- case DW_AT_high_pc:
- current_function_info_->highpc = data;
- break;
- case DW_AT_decl_line:
- current_function_info_->line = data;
- break;
- case DW_AT_decl_file:
- current_function_info_->file = files_->at(data).name;
- break;
- default:
- break;
- }
- }
- }
- void CUFunctionInfoHandler::ProcessAttributeReference(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- if (current_function_info_) {
- switch (attr) {
- case DW_AT_specification: {
- // Some functions have a "specification" attribute
- // which means they were defined elsewhere. The name
- // attribute is not repeated, and must be taken from
- // the specification DIE. Here we'll assume that
- // any DIE referenced in this manner will already have
- // been seen, but that's not really required by the spec.
- FunctionMap::iterator iter = offset_to_funcinfo_->find(data);
- if (iter != offset_to_funcinfo_->end()) {
- current_function_info_->name = iter->second->name;
- current_function_info_->mangled_name = iter->second->mangled_name;
- } else {
- // If you hit this, this code probably needs to be rewritten.
- 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);
- }
- break;
- }
- default:
- break;
- }
- }
- }
- void CUFunctionInfoHandler::EndDIE(uint64 offset) {
- if (current_function_info_ && current_function_info_->lowpc)
- address_to_funcinfo_->insert(std::make_pair(current_function_info_->lowpc,
- current_function_info_));
- }
- } // namespace dwarf2reader