PageRenderTime 61ms CodeModel.GetById 14ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/common/dwarf/functioninfo.cc

http://github.com/tomahawk-player/tomahawk
C++ | 229 lines | 156 code | 27 blank | 46 comment | 34 complexity | 56173f41169047002500e42a01090abe MD5 | raw file
  1// Copyright (c) 2010 Google Inc. All Rights Reserved.
  2//
  3// Redistribution and use in source and binary forms, with or without
  4// modification, are permitted provided that the following conditions are
  5// met:
  6//
  7//     * Redistributions of source code must retain the above copyright
  8// notice, this list of conditions and the following disclaimer.
  9//     * Redistributions in binary form must reproduce the above
 10// copyright notice, this list of conditions and the following disclaimer
 11// in the documentation and/or other materials provided with the
 12// distribution.
 13//     * Neither the name of Google Inc. nor the names of its
 14// contributors may be used to endorse or promote products derived from
 15// this software without specific prior written permission.
 16//
 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28
 29// This is a client for the dwarf2reader to extract function and line
 30// information from the debug info.
 31
 32#include <assert.h>
 33#include <limits.h>
 34#include <stdio.h>
 35
 36#include <map>
 37#include <queue>
 38#include <vector>
 39#include <memory>
 40
 41#include "common/dwarf/functioninfo.h"
 42
 43#include "common/dwarf/bytereader.h"
 44
 45
 46namespace dwarf2reader {
 47
 48CULineInfoHandler::CULineInfoHandler(std::vector<SourceFileInfo>* files,
 49                                     std::vector<std::string>* dirs,
 50                                     LineMap* linemap):linemap_(linemap),
 51                                                       files_(files),
 52                                                       dirs_(dirs) {
 53  // The dirs and files are 1 indexed, so just make sure we put
 54  // nothing in the 0 vector.
 55  assert(dirs->size() == 0);
 56  assert(files->size() == 0);
 57  dirs->push_back("");
 58  SourceFileInfo s;
 59  s.name = "";
 60  s.lowpc = ULLONG_MAX;
 61  files->push_back(s);
 62}
 63
 64void CULineInfoHandler::DefineDir(const std::string& name, uint32 dir_num) {
 65  // These should never come out of order, actually
 66  assert(dir_num == dirs_->size());
 67  dirs_->push_back(name);
 68}
 69
 70void CULineInfoHandler::DefineFile(const std::string& name,
 71                                   int32 file_num, uint32 dir_num,
 72                                   uint64 mod_time, uint64 length) {
 73  assert(dir_num >= 0);
 74  assert(dir_num < dirs_->size());
 75
 76  // These should never come out of order, actually.
 77  if (file_num == (int32)files_->size() || file_num == -1) {
 78    std::string dir = dirs_->at(dir_num);
 79
 80    SourceFileInfo s;
 81    s.lowpc = ULLONG_MAX;
 82
 83    if (dir == "") {
 84      s.name = name;
 85    } else {
 86      s.name = dir + "/" + name;
 87    }
 88
 89    files_->push_back(s);
 90  } else {
 91    fprintf(stderr, "error in DefineFile");
 92  }
 93}
 94
 95void CULineInfoHandler::AddLine(uint64 address, uint64 length, uint32 file_num,
 96                                uint32 line_num, uint32 column_num) {
 97  if (file_num < files_->size()) {
 98    linemap_->insert(
 99        std::make_pair(address,
100                       std::make_pair(files_->at(file_num).name.c_str(),
101                                      line_num)));
102
103    if(address < files_->at(file_num).lowpc) {
104      files_->at(file_num).lowpc = address;
105    }
106  } else {
107    fprintf(stderr,"error in AddLine");
108  }
109}
110
111bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset,
112                                                 uint8 address_size,
113                                                 uint8 offset_size,
114                                                 uint64 cu_length,
115                                                 uint8 dwarf_version) {
116  current_compilation_unit_offset_ = offset;
117  return true;
118}
119
120
121// For function info, we only care about subprograms and inlined
122// subroutines. For line info, the DW_AT_stmt_list lives in the
123// compile unit tag.
124
125bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag,
126                                     const AttributeList& attrs) {
127  switch (tag) {
128    case DW_TAG_subprogram:
129    case DW_TAG_inlined_subroutine: {
130      current_function_info_ = new FunctionInfo;
131      current_function_info_->lowpc = current_function_info_->highpc = 0;
132      current_function_info_->name = "";
133      current_function_info_->line = 0;
134      current_function_info_->file = "";
135      offset_to_funcinfo_->insert(std::make_pair(offset,
136                                                 current_function_info_));
137    };
138      // FALLTHROUGH
139    case DW_TAG_compile_unit:
140      return true;
141    default:
142      return false;
143  }
144  return false;
145}
146
147// Only care about the name attribute for functions
148
149void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset,
150                                                   enum DwarfAttribute attr,
151                                                   enum DwarfForm form,
152                                                   const std::string &data) {
153  if (current_function_info_) {
154    if (attr == DW_AT_name)
155      current_function_info_->name = data;
156    else if(attr == DW_AT_MIPS_linkage_name)
157      current_function_info_->mangled_name = data;
158  }
159}
160
161void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
162                                                     enum DwarfAttribute attr,
163                                                     enum DwarfForm form,
164                                                     uint64 data) {
165  if (attr == DW_AT_stmt_list) {
166    SectionMap::const_iterator iter = sections_.find("__debug_line");
167    assert(iter != sections_.end());
168
169    // this should be a scoped_ptr but we dont' use boost :-(
170    std::auto_ptr<LineInfo> lireader(new LineInfo(iter->second.first + data,
171                                                  iter->second.second  - data,
172                                                  reader_, linehandler_));
173    lireader->Start();
174  } else if (current_function_info_) {
175    switch (attr) {
176      case DW_AT_low_pc:
177        current_function_info_->lowpc = data;
178        break;
179      case DW_AT_high_pc:
180        current_function_info_->highpc = data;
181        break;
182      case DW_AT_decl_line:
183        current_function_info_->line = data;
184        break;
185      case DW_AT_decl_file:
186        current_function_info_->file = files_->at(data).name;
187        break;
188      default:
189        break;
190    }
191  }
192}
193
194void CUFunctionInfoHandler::ProcessAttributeReference(uint64 offset,
195                                                      enum DwarfAttribute attr,
196                                                      enum DwarfForm form,
197                                                      uint64 data) {
198  if (current_function_info_) {
199    switch (attr) {
200      case DW_AT_specification: {
201        // Some functions have a "specification" attribute
202        // which means they were defined elsewhere. The name
203        // attribute is not repeated, and must be taken from
204        // the specification DIE. Here we'll assume that
205        // any DIE referenced in this manner will already have
206        // been seen, but that's not really required by the spec.
207        FunctionMap::iterator iter = offset_to_funcinfo_->find(data);
208        if (iter != offset_to_funcinfo_->end()) {
209          current_function_info_->name = iter->second->name;
210          current_function_info_->mangled_name = iter->second->mangled_name;
211        } else {
212          // If you hit this, this code probably needs to be rewritten.
213          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);
214        }
215        break;
216      }
217      default:
218        break;
219    }
220  }
221}
222
223void CUFunctionInfoHandler::EndDIE(uint64 offset) {
224  if (current_function_info_ && current_function_info_->lowpc)
225    address_to_funcinfo_->insert(std::make_pair(current_function_info_->lowpc,
226                                                current_function_info_));
227}
228
229}  // namespace dwarf2reader