~vitty/armagetronad/trunk-armagetronad-breakpad

« back to all changes in this revision

Viewing changes to src/thirdparty/breakpad/common/stabs_to_module.cc

  • Committer: Vitty
  • Date: 2011-07-22 18:33:21 UTC
  • Revision ID: vitty4@gmail.com-20110722183321-mtj3mny5mfm7ytm2
Add dump_syms program for linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2010 Google Inc.
 
2
// All rights reserved.
 
3
//
 
4
// Redistribution and use in source and binary forms, with or without
 
5
// modification, are permitted provided that the following conditions are
 
6
// met:
 
7
//
 
8
//     * Redistributions of source code must retain the above copyright
 
9
// notice, this list of conditions and the following disclaimer.
 
10
//     * Redistributions in binary form must reproduce the above
 
11
// copyright notice, this list of conditions and the following disclaimer
 
12
// in the documentation and/or other materials provided with the
 
13
// distribution.
 
14
//     * Neither the name of Google Inc. nor the names of its
 
15
// contributors may be used to endorse or promote products derived from
 
16
// this software without specific prior written permission.
 
17
//
 
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
19
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
20
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
21
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
22
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
23
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
24
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
25
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
26
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
27
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
28
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 
 
30
// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
 
31
 
 
32
// dump_stabs.cc --- implement the StabsToModule class.
 
33
 
 
34
#include <assert.h>
 
35
#include <cxxabi.h>
 
36
#include <stdarg.h>
 
37
#include <stdio.h>
 
38
 
 
39
#include <algorithm>
 
40
 
 
41
#include "common/stabs_to_module.h"
 
42
 
 
43
namespace google_breakpad {
 
44
 
 
45
using std::string;
 
46
 
 
47
// Demangle using abi call.
 
48
// Older GCC may not support it.
 
49
static string Demangle(const string &mangled) {
 
50
  int status = 0;
 
51
  char *demangled = abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status);
 
52
  if (status == 0 && demangled != NULL) {
 
53
    string str(demangled);
 
54
    free(demangled);
 
55
    return str;
 
56
  }
 
57
  return string(mangled);
 
58
}
 
59
 
 
60
StabsToModule::~StabsToModule() {
 
61
  // Free any functions we've accumulated but not added to the module.
 
62
  for (vector<Module::Function *>::const_iterator func_it = functions_.begin();
 
63
       func_it != functions_.end(); func_it++)
 
64
    delete *func_it;
 
65
  // Free any function that we're currently within.
 
66
  delete current_function_;
 
67
}
 
68
 
 
69
bool StabsToModule::StartCompilationUnit(const char *name, uint64_t address,
 
70
                                         const char *build_directory) {
 
71
  assert(!in_compilation_unit_);
 
72
  in_compilation_unit_ = true;
 
73
  current_source_file_name_ = name;
 
74
  current_source_file_ = module_->FindFile(name);
 
75
  comp_unit_base_address_ = address;
 
76
  boundaries_.push_back(static_cast<Module::Address>(address));
 
77
  return true;
 
78
}
 
79
 
 
80
bool StabsToModule::EndCompilationUnit(uint64_t address) {
 
81
  assert(in_compilation_unit_);
 
82
  in_compilation_unit_ = false;
 
83
  comp_unit_base_address_ = 0;
 
84
  current_source_file_ = NULL;
 
85
  current_source_file_name_ = NULL;
 
86
  if (address)
 
87
    boundaries_.push_back(static_cast<Module::Address>(address));
 
88
  return true;
 
89
}
 
90
 
 
91
bool StabsToModule::StartFunction(const string &name,
 
92
                                  uint64_t address) {
 
93
  assert(!current_function_);
 
94
  Module::Function *f = new Module::Function;
 
95
  f->name = Demangle(name);
 
96
  f->address = address;
 
97
  f->size = 0;           // We compute this in StabsToModule::Finalize().
 
98
  f->parameter_size = 0; // We don't provide this information.
 
99
  current_function_ = f;
 
100
  boundaries_.push_back(static_cast<Module::Address>(address));
 
101
  return true;
 
102
}
 
103
 
 
104
bool StabsToModule::EndFunction(uint64_t address) {
 
105
  assert(current_function_);
 
106
  // Functions in this compilation unit should have address bigger
 
107
  // than the compilation unit's starting address.  There may be a lot
 
108
  // of duplicated entries for functions in the STABS data. We will
 
109
  // count on the Module to remove the duplicates.
 
110
  if (current_function_->address >= comp_unit_base_address_)
 
111
    functions_.push_back(current_function_);
 
112
  else
 
113
    delete current_function_;
 
114
  current_function_ = NULL;
 
115
  if (address)
 
116
    boundaries_.push_back(static_cast<Module::Address>(address));
 
117
  return true;
 
118
}
 
119
 
 
120
bool StabsToModule::Line(uint64_t address, const char *name, int number) {
 
121
  assert(current_function_);
 
122
  assert(current_source_file_);
 
123
  if (name != current_source_file_name_) {
 
124
    current_source_file_ = module_->FindFile(name);
 
125
    current_source_file_name_ = name;
 
126
  }
 
127
  Module::Line line;
 
128
  line.address = address;
 
129
  line.size = 0;  // We compute this in StabsToModule::Finalize().
 
130
  line.file = current_source_file_;
 
131
  line.number = number;
 
132
  current_function_->lines.push_back(line);
 
133
  return true;
 
134
}
 
135
 
 
136
bool StabsToModule::Extern(const string &name, uint64_t address) {
 
137
  Module::Extern *ext = new Module::Extern;
 
138
  // Older libstdc++ demangle implementations can crash on unexpected
 
139
  // input, so be careful about what gets passed in.
 
140
  if (name.compare(0, 3, "__Z") == 0) {
 
141
    ext->name = Demangle(name.substr(1));
 
142
  } else if (name[0] == '_') {
 
143
    ext->name = name.substr(1);
 
144
  } else {
 
145
    ext->name = name;
 
146
  }
 
147
  ext->address = address;
 
148
  module_->AddExtern(ext);
 
149
  return true;
 
150
}
 
151
 
 
152
void StabsToModule::Warning(const char *format, ...) {
 
153
  va_list args;
 
154
  va_start(args, format);
 
155
  vfprintf(stderr, format, args);
 
156
  va_end(args);
 
157
}
 
158
 
 
159
void StabsToModule::Finalize() {
 
160
  // Sort our boundary list, so we can search it quickly.
 
161
  sort(boundaries_.begin(), boundaries_.end());
 
162
  // Sort all functions by address, just for neatness.
 
163
  sort(functions_.begin(), functions_.end(),
 
164
       Module::Function::CompareByAddress);
 
165
 
 
166
  for (vector<Module::Function *>::const_iterator func_it = functions_.begin();
 
167
       func_it != functions_.end();
 
168
       func_it++) {
 
169
    Module::Function *f = *func_it;
 
170
    // Compute the function f's size.
 
171
    vector<Module::Address>::const_iterator boundary
 
172
        = std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address);
 
173
    if (boundary != boundaries_.end())
 
174
      f->size = *boundary - f->address;
 
175
    else
 
176
      // If this is the last function in the module, and the STABS
 
177
      // reader was unable to give us its ending address, then assign
 
178
      // it a bogus, very large value.  This will happen at most once
 
179
      // per module: since we've added all functions' addresses to the
 
180
      // boundary table, only one can be the last.
 
181
      f->size = kFallbackSize;
 
182
 
 
183
    // Compute sizes for each of the function f's lines --- if it has any.
 
184
    if (!f->lines.empty()) {
 
185
      stable_sort(f->lines.begin(), f->lines.end(),
 
186
                  Module::Line::CompareByAddress);
 
187
      vector<Module::Line>::iterator last_line = f->lines.end() - 1;
 
188
      for (vector<Module::Line>::iterator line_it = f->lines.begin();
 
189
           line_it != last_line; line_it++)
 
190
        line_it[0].size = line_it[1].address - line_it[0].address;
 
191
      // Compute the size of the last line from f's end address.
 
192
      last_line->size = (f->address + f->size) - last_line->address;
 
193
    }
 
194
  }
 
195
  // Now that everything has a size, add our functions to the module, and
 
196
  // dispose of our private list.
 
197
  module_->AddFunctions(functions_.begin(), functions_.end());
 
198
  functions_.clear();
 
199
}
 
200
 
 
201
} // namespace google_breakpad