toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:4d874a52acda
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 #include "common/dwarf/bytereader.h"
43 #include "common/using_std_string.h"
44
45 namespace dwarf2reader {
46
47 CULineInfoHandler::CULineInfoHandler(std::vector<SourceFileInfo>* files,
48 std::vector<string>* dirs,
49 LineMap* linemap):linemap_(linemap),
50 files_(files),
51 dirs_(dirs) {
52 // The dirs and files are 1 indexed, so just make sure we put
53 // nothing in the 0 vector.
54 assert(dirs->size() == 0);
55 assert(files->size() == 0);
56 dirs->push_back("");
57 SourceFileInfo s;
58 s.name = "";
59 s.lowpc = ULLONG_MAX;
60 files->push_back(s);
61 }
62
63 void CULineInfoHandler::DefineDir(const string& name, uint32 dir_num) {
64 // These should never come out of order, actually
65 assert(dir_num == dirs_->size());
66 dirs_->push_back(name);
67 }
68
69 void CULineInfoHandler::DefineFile(const string& name,
70 int32 file_num, uint32 dir_num,
71 uint64 mod_time, uint64 length) {
72 assert(dir_num >= 0);
73 assert(dir_num < dirs_->size());
74
75 // These should never come out of order, actually.
76 if (file_num == (int32)files_->size() || file_num == -1) {
77 string dir = dirs_->at(dir_num);
78
79 SourceFileInfo s;
80 s.lowpc = ULLONG_MAX;
81
82 if (dir == "") {
83 s.name = name;
84 } else {
85 s.name = dir + "/" + name;
86 }
87
88 files_->push_back(s);
89 } else {
90 fprintf(stderr, "error in DefineFile");
91 }
92 }
93
94 void CULineInfoHandler::AddLine(uint64 address, uint64 length, uint32 file_num,
95 uint32 line_num, uint32 column_num) {
96 if (file_num < files_->size()) {
97 linemap_->insert(
98 std::make_pair(address,
99 std::make_pair(files_->at(file_num).name.c_str(),
100 line_num)));
101
102 if(address < files_->at(file_num).lowpc) {
103 files_->at(file_num).lowpc = address;
104 }
105 } else {
106 fprintf(stderr,"error in AddLine");
107 }
108 }
109
110 bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset,
111 uint8 address_size,
112 uint8 offset_size,
113 uint64 cu_length,
114 uint8 dwarf_version) {
115 current_compilation_unit_offset_ = offset;
116 return true;
117 }
118
119
120 // For function info, we only care about subprograms and inlined
121 // subroutines. For line info, the DW_AT_stmt_list lives in the
122 // compile unit tag.
123
124 bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag) {
125 switch (tag) {
126 case DW_TAG_subprogram:
127 case DW_TAG_inlined_subroutine: {
128 current_function_info_ = new FunctionInfo;
129 current_function_info_->lowpc = current_function_info_->highpc = 0;
130 current_function_info_->name = "";
131 current_function_info_->line = 0;
132 current_function_info_->file = "";
133 offset_to_funcinfo_->insert(std::make_pair(offset,
134 current_function_info_));
135 };
136 // FALLTHROUGH
137 case DW_TAG_compile_unit:
138 return true;
139 default:
140 return false;
141 }
142 return false;
143 }
144
145 // Only care about the name attribute for functions
146
147 void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset,
148 enum DwarfAttribute attr,
149 enum DwarfForm form,
150 const string &data) {
151 if (current_function_info_) {
152 if (attr == DW_AT_name)
153 current_function_info_->name = data;
154 else if(attr == DW_AT_MIPS_linkage_name)
155 current_function_info_->mangled_name = data;
156 }
157 }
158
159 void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
160 enum DwarfAttribute attr,
161 enum DwarfForm form,
162 uint64 data) {
163 if (attr == DW_AT_stmt_list) {
164 SectionMap::const_iterator iter = sections_.find("__debug_line");
165 assert(iter != sections_.end());
166
167 // this should be a scoped_ptr but we dont' use boost :-(
168 std::auto_ptr<LineInfo> lireader(new LineInfo(iter->second.first + data,
169 iter->second.second - data,
170 reader_, linehandler_));
171 lireader->Start();
172 } else if (current_function_info_) {
173 switch (attr) {
174 case DW_AT_low_pc:
175 current_function_info_->lowpc = data;
176 break;
177 case DW_AT_high_pc:
178 current_function_info_->highpc = data;
179 break;
180 case DW_AT_decl_line:
181 current_function_info_->line = data;
182 break;
183 case DW_AT_decl_file:
184 current_function_info_->file = files_->at(data).name;
185 break;
186 default:
187 break;
188 }
189 }
190 }
191
192 void CUFunctionInfoHandler::ProcessAttributeReference(uint64 offset,
193 enum DwarfAttribute attr,
194 enum DwarfForm form,
195 uint64 data) {
196 if (current_function_info_) {
197 switch (attr) {
198 case DW_AT_specification: {
199 // Some functions have a "specification" attribute
200 // which means they were defined elsewhere. The name
201 // attribute is not repeated, and must be taken from
202 // the specification DIE. Here we'll assume that
203 // any DIE referenced in this manner will already have
204 // been seen, but that's not really required by the spec.
205 FunctionMap::iterator iter = offset_to_funcinfo_->find(data);
206 if (iter != offset_to_funcinfo_->end()) {
207 current_function_info_->name = iter->second->name;
208 current_function_info_->mangled_name = iter->second->mangled_name;
209 } else {
210 // If you hit this, this code probably needs to be rewritten.
211 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);
212 }
213 break;
214 }
215 default:
216 break;
217 }
218 }
219 }
220
221 void CUFunctionInfoHandler::EndDIE(uint64 offset) {
222 if (current_function_info_ && current_function_info_->lowpc)
223 address_to_funcinfo_->insert(std::make_pair(current_function_info_->lowpc,
224 current_function_info_));
225 }
226
227 } // namespace dwarf2reader

mercurial