OLD | NEW |
| (Empty) |
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 | |
46 namespace dwarf2reader { | |
47 | |
48 CULineInfoHandler::CULineInfoHandler(vector<SourceFileInfo>* files, | |
49 vector<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 | |
64 void CULineInfoHandler::DefineDir(const 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 | |
70 void CULineInfoHandler::DefineFile(const 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 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 | |
95 void 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(make_pair(address, make_pair(files_->at(file_num).name.c_st
r(), | |
99 line_num))); | |
100 | |
101 if(address < files_->at(file_num).lowpc) { | |
102 files_->at(file_num).lowpc = address; | |
103 } | |
104 } else { | |
105 fprintf(stderr,"error in AddLine"); | |
106 } | |
107 } | |
108 | |
109 bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset, | |
110 uint8 address_size, | |
111 uint8 offset_size, | |
112 uint64 cu_length, | |
113 uint8 dwarf_version) { | |
114 current_compilation_unit_offset_ = offset; | |
115 return true; | |
116 } | |
117 | |
118 | |
119 // For function info, we only care about subprograms and inlined | |
120 // subroutines. For line info, the DW_AT_stmt_list lives in the | |
121 // compile unit tag. | |
122 | |
123 bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag, | |
124 const AttributeList& attrs) { | |
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(make_pair(offset, current_function_info_)); | |
134 }; | |
135 // FALLTHROUGH | |
136 case DW_TAG_compile_unit: | |
137 return true; | |
138 default: | |
139 return false; | |
140 } | |
141 return false; | |
142 } | |
143 | |
144 // Only care about the name attribute for functions | |
145 | |
146 void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset, | |
147 enum DwarfAttribute attr, | |
148 enum DwarfForm form, | |
149 const string &data) { | |
150 if (current_function_info_) { | |
151 if (attr == DW_AT_name) | |
152 current_function_info_->name = data; | |
153 else if(attr == DW_AT_MIPS_linkage_name) | |
154 current_function_info_->mangled_name = data; | |
155 } | |
156 } | |
157 | |
158 void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset, | |
159 enum DwarfAttribute attr, | |
160 enum DwarfForm form, | |
161 uint64 data) { | |
162 if (attr == DW_AT_stmt_list) { | |
163 SectionMap::const_iterator iter = sections_.find("__debug_line"); | |
164 assert(iter != sections_.end()); | |
165 | |
166 // this should be a scoped_ptr but we dont' use boost :-( | |
167 auto_ptr<LineInfo> lireader(new LineInfo(iter->second.first + data, | |
168 iter->second.second - data, | |
169 reader_, linehandler_)); | |
170 lireader->Start(); | |
171 } else if (current_function_info_) { | |
172 switch (attr) { | |
173 case DW_AT_low_pc: | |
174 current_function_info_->lowpc = data; | |
175 break; | |
176 case DW_AT_high_pc: | |
177 current_function_info_->highpc = data; | |
178 break; | |
179 case DW_AT_decl_line: | |
180 current_function_info_->line = data; | |
181 break; | |
182 case DW_AT_decl_file: | |
183 current_function_info_->file = files_->at(data).name; | |
184 break; | |
185 default: | |
186 break; | |
187 } | |
188 } | |
189 } | |
190 | |
191 void CUFunctionInfoHandler::ProcessAttributeReference(uint64 offset, | |
192 enum DwarfAttribute attr, | |
193 enum DwarfForm form, | |
194 uint64 data) { | |
195 if (current_function_info_) { | |
196 switch (attr) { | |
197 case DW_AT_specification: { | |
198 // Some functions have a "specification" attribute | |
199 // which means they were defined elsewhere. The name | |
200 // attribute is not repeated, and must be taken from | |
201 // the specification DIE. Here we'll assume that | |
202 // any DIE referenced in this manner will already have | |
203 // been seen, but that's not really required by the spec. | |
204 FunctionMap::iterator iter = offset_to_funcinfo_->find(data); | |
205 if (iter != offset_to_funcinfo_->end()) { | |
206 current_function_info_->name = iter->second->name; | |
207 current_function_info_->mangled_name = iter->second->mangled_name; | |
208 } else { | |
209 // If you hit this, this code probably needs to be rewritten. | |
210 fprintf(stderr, "Error: DW_AT_specification was seen before the refere
nced DIE! (Looking for DIE at offset %08llx, in DIE at offset %08llx)\n", data,
offset); | |
211 } | |
212 break; | |
213 } | |
214 default: | |
215 break; | |
216 } | |
217 } | |
218 } | |
219 | |
220 void CUFunctionInfoHandler::EndDIE(uint64 offset) { | |
221 if (current_function_info_ && current_function_info_->lowpc) | |
222 address_to_funcinfo_->insert(make_pair(current_function_info_->lowpc, | |
223 current_function_info_)); | |
224 } | |
225 | |
226 } // namespace dwarf2reader | |
OLD | NEW |