OLD | NEW |
| (Empty) |
1 // Copyright 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 path of Google Inc. nor the paths 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 #include <stdlib.h> | |
30 #include <stdio.h> | |
31 #include <string.h> | |
32 | |
33 #include <stack> | |
34 | |
35 #include "common/types.h" | |
36 #include "elf_reader/elf_structs.h" | |
37 #include "elf_reader/elf_object.h" | |
38 #include "elf_reader/elf_reader.h" | |
39 | |
40 #include "dwarf_reader/dwarf_reader.h" | |
41 #include "dwarf_reader/dwarf_parse.h" | |
42 #include "dwarf_reader/dwarf_vm.h" | |
43 | |
44 #include "common/dwarf/bytereader.h" | |
45 #include "common/dwarf/dwarf2reader.h" | |
46 | |
47 using namespace elf_reader; | |
48 using namespace dwarf_reader; | |
49 using namespace dwarf2reader; | |
50 | |
51 typedef pair<const char *, uint64> SectionInfo; | |
52 typedef map<string, uint64> LoadMap; | |
53 | |
54 class ElfSectionReader : public ElfReaderBase { | |
55 public: | |
56 ElfSectionReader() : byteReader_(NULL) {} | |
57 ~ElfSectionReader() { | |
58 if (byteReader_) | |
59 delete byteReader_; | |
60 } | |
61 | |
62 void Header(const char *name, void *data, uint64_t length, uint32_t classSize,
bool lsb) { | |
63 if (lsb) | |
64 byteReader_ = new ByteReader(ENDIANNESS_LITTLE); | |
65 else | |
66 byteReader_ = new ByteReader(ENDIANNESS_BIG); | |
67 } | |
68 | |
69 bool SectionHeadersStart(uint32_t count) { return true; } | |
70 void SectionHeader(const char *name, void *data, uint64_t virt, | |
71 uint32_t type, uint32_t flags, uint64_t length) { | |
72 const char *ptr = reinterpret_cast<const char *>(data); | |
73 sections_[name] = SectionInfo(ptr, length); | |
74 loads_[name] = virt; | |
75 } | |
76 | |
77 public: | |
78 ByteReader *GetByteReader() { return byteReader_; } | |
79 SectionInfo GetSectionInfo(const char *name) { return sections_[name]; } | |
80 uint64 GetSectionLoad(const char *name) { return loads_[name]; } | |
81 SectionMap& GetSectionMap() { return sections_; } | |
82 LoadMap& GetLoadMap() { return loads_; } | |
83 | |
84 private: | |
85 SectionMap sections_; | |
86 LoadMap loads_; | |
87 ByteReader *byteReader_; | |
88 }; | |
89 | |
90 struct ParseState { | |
91 public: | |
92 ParseState(IDwarfReader *reader) : reader_(reader), currCU_(NULL) {} | |
93 | |
94 public: | |
95 IDwarfReader *reader_; | |
96 void *currCU_; | |
97 stack<void*> ctxStack_; | |
98 stack<uint64> addrStack_; | |
99 }; | |
100 | |
101 class DwarfInfoParser : public Dwarf2Handler { | |
102 public: | |
103 DwarfInfoParser(ParseState *ps) : ps_(ps) {} | |
104 | |
105 | |
106 // Start to process a compilation unit at OFFSET from the beginning of the | |
107 // .debug_info section. Return false if you would like to skip this | |
108 // compilation unit. | |
109 bool StartCompilationUnit(uint64 offset, uint8 address_size, | |
110 uint8 offset_size, uint64 cu_length, | |
111 uint8 dwarf_version) { | |
112 void *ctx = ps_->reader_->StartCompilationUnit(offset, address_size, | |
113 offset_size, cu_length, | |
114 dwarf_version); | |
115 | |
116 ps_->currCU_ = ctx; | |
117 ps_->ctxStack_.push(ctx); | |
118 ps_->addrStack_.push(offset); | |
119 return true; | |
120 } | |
121 | |
122 bool StartDIE(uint64 offset, enum DwarfTag tag, const AttributeList& attrs) { | |
123 | |
124 void *ctx = ps_->reader_->StartDIE(ps_->ctxStack_.top(), | |
125 ps_->addrStack_.top(), | |
126 offset, tag); | |
127 | |
128 ps_->ctxStack_.push(ctx); | |
129 ps_->addrStack_.push(offset); | |
130 return true; | |
131 } | |
132 | |
133 void EndDIE(uint64 offset) { | |
134 | |
135 ps_->reader_->EndDIE(ps_->ctxStack_.top(), ps_->addrStack_.top()); | |
136 ps_->ctxStack_.pop(); | |
137 ps_->addrStack_.pop(); | |
138 } | |
139 | |
140 void ProcessAttributeUnsigned(uint64 offset, enum DwarfAttribute attr, | |
141 enum DwarfForm form, uint64 data) { | |
142 | |
143 ps_->reader_->ProcessAttributeUnsigned(ps_->ctxStack_.top(), | |
144 ps_->addrStack_.top(), | |
145 offset, attr, form, data); | |
146 } | |
147 | |
148 void ProcessAttributeSigned(uint64 offset, | |
149 enum DwarfAttribute attr, | |
150 enum DwarfForm form, | |
151 int64 data) { | |
152 ps_->reader_->ProcessAttributeSigned(ps_->ctxStack_.top(), | |
153 ps_->addrStack_.top(), | |
154 offset, attr, form, data); | |
155 } | |
156 | |
157 void ProcessAttributeReference(uint64 offset, | |
158 enum DwarfAttribute attr, | |
159 enum DwarfForm form, | |
160 uint64 data) { | |
161 ps_->reader_->ProcessAttributeReference(ps_->ctxStack_.top(), | |
162 ps_->addrStack_.top(), | |
163 offset, attr, form, data); | |
164 } | |
165 | |
166 void ProcessAttributeBuffer(uint64 offset, | |
167 enum DwarfAttribute attr, | |
168 enum DwarfForm form, | |
169 const char* data, | |
170 uint64 len) { | |
171 ps_->reader_->ProcessAttributeBuffer(ps_->ctxStack_.top(), | |
172 ps_->addrStack_.top(), | |
173 offset, attr, form, data, len); | |
174 } | |
175 | |
176 void ProcessAttributeString(uint64 offset, | |
177 enum DwarfAttribute attr, | |
178 enum DwarfForm form, | |
179 const string& data) { | |
180 ps_->reader_->ProcessAttributeString(ps_->ctxStack_.top(), | |
181 ps_->addrStack_.top(), | |
182 offset, attr, form, data.data()); | |
183 } | |
184 | |
185 private: | |
186 ParseState *ps_; | |
187 }; | |
188 | |
189 class DwarfLineParser : public LineInfoHandler { | |
190 public: | |
191 DwarfLineParser(ParseState *ps) : ps_(ps) {} | |
192 | |
193 void DefineDir(const string& name, uint32 dir_num) { | |
194 ps_->reader_->DefineDir(ps_->ctxStack_.top(), name.data(), dir_num); | |
195 } | |
196 | |
197 void DefineFile(const string& name, int32 file_num, uint32 dir_num, | |
198 uint64 mod_time, uint64 length) { | |
199 ps_->reader_->DefineFile(ps_->ctxStack_.top(), name.data(), file_num, | |
200 dir_num, mod_time, length); | |
201 } | |
202 | |
203 void AddLine(uint64 address, uint64 length, uint32 file_num, | |
204 uint32 line_num, uint32 column_num) { | |
205 | |
206 ps_->reader_->AddLine(ps_->ctxStack_.top(), address, length, file_num, | |
207 line_num, column_num); | |
208 } | |
209 | |
210 | |
211 private: | |
212 ParseState *ps_; | |
213 }; | |
214 | |
215 class DwarfFrameInfoReader : public CallFrameInfo::Handler { | |
216 public: | |
217 DwarfFrameInfoReader(IDwarfReader *reader) : reader_(reader){} | |
218 | |
219 virtual bool Entry(size_t offset, uint64 address, uint64 length, | |
220 uint8 version, const string &augmentation, | |
221 unsigned return_address){ | |
222 return reader_->BeginCfiEntry( | |
223 offset, | |
224 address, | |
225 length, | |
226 version, | |
227 augmentation.c_str(), | |
228 return_address); | |
229 } | |
230 | |
231 virtual bool UndefinedRule(uint64 address, int reg){ | |
232 return reader_->AddCfiRule( | |
233 address, | |
234 reg, | |
235 IDwarfReader::CFIRT_UNDEFINED, | |
236 0, | |
237 0, | |
238 NULL, | |
239 0); | |
240 } | |
241 | |
242 virtual bool SameValueRule(uint64 address, int reg){ | |
243 return reader_->AddCfiRule( | |
244 address, | |
245 reg, | |
246 IDwarfReader::CFIRT_SAMEVALUE, | |
247 0, | |
248 0, | |
249 NULL, | |
250 0); | |
251 } | |
252 | |
253 virtual bool OffsetRule(uint64 address, int reg, | |
254 int base_register, long offset){ | |
255 return reader_->AddCfiRule( | |
256 address, | |
257 reg, | |
258 IDwarfReader::CFIRT_OFFSET, | |
259 base_register, | |
260 offset, | |
261 NULL, | |
262 0); | |
263 } | |
264 | |
265 virtual bool ValOffsetRule(uint64 address, int reg, | |
266 int base_register, long offset){ | |
267 return reader_->AddCfiRule( | |
268 address, | |
269 reg, | |
270 IDwarfReader::CFIRT_VALOFFSET, | |
271 base_register, | |
272 offset, | |
273 NULL, | |
274 0); | |
275 } | |
276 | |
277 virtual bool RegisterRule(uint64 address, int reg, int base_register){ | |
278 return reader_->AddCfiRule( | |
279 address, | |
280 reg, | |
281 IDwarfReader::CFIRT_REGISTER, | |
282 base_register, | |
283 0, | |
284 NULL, | |
285 0); | |
286 } | |
287 | |
288 virtual bool ExpressionRule(uint64 address, int reg, | |
289 const string &expression){ | |
290 return reader_->AddCfiRule( | |
291 address, | |
292 reg, | |
293 IDwarfReader::CFIRT_EXPRESSION, | |
294 0, | |
295 0, | |
296 expression.c_str(), | |
297 expression.length()); | |
298 } | |
299 | |
300 virtual bool ValExpressionRule(uint64 address, int reg, | |
301 const string &expression){ | |
302 return reader_->AddCfiRule( | |
303 address, | |
304 reg, | |
305 IDwarfReader::CFIRT_VALEXPRESSION, | |
306 0, | |
307 0, | |
308 expression.c_str(), | |
309 expression.length()); | |
310 } | |
311 | |
312 virtual bool End(){ | |
313 return reader_->EndCfiEntry(); | |
314 } | |
315 | |
316 private: | |
317 IDwarfReader* reader_; | |
318 }; | |
319 | |
320 | |
321 | |
322 namespace dwarf_reader { | |
323 | |
324 void DwarfParseElf(ElfObject *elf, IDwarfReader *reader) { | |
325 ElfSectionReader *elfInfo = new ElfSectionReader(); | |
326 | |
327 ParseState parseState(reader); | |
328 | |
329 if (NULL == elf) | |
330 return; | |
331 | |
332 if (NULL == reader) | |
333 return; | |
334 | |
335 if (NULL == elfInfo) | |
336 return; | |
337 | |
338 elf->Parse(elfInfo); | |
339 SectionInfo debug_info_section = elfInfo->GetSectionInfo(".debug_info"); | |
340 SectionInfo debug_line_section = elfInfo->GetSectionInfo(".debug_line"); | |
341 SectionInfo debug_loc_section = elfInfo->GetSectionInfo(".debug_loc"); | |
342 SectionInfo debug_frame_section = elfInfo->GetSectionInfo(".eh_frame"); | |
343 SectionInfo text_section = elfInfo->GetSectionInfo(".text"); | |
344 | |
345 elfInfo->GetByteReader()->SetTextBase((uint64)text_section.first); | |
346 elfInfo->GetByteReader()->SetCFIDataBase(elfInfo->GetSectionLoad(".eh_frame"),
debug_frame_section.first); | |
347 | |
348 DwarfInfoParser info_handler(&parseState); | |
349 DwarfLineParser line_handler(&parseState); | |
350 | |
351 uint64 debug_info_length = debug_info_section.second; | |
352 uint64 debug_line_length = debug_line_section.second; | |
353 const char *debug_line_ptr = debug_line_section.first; | |
354 for (uint64 offset = 0; offset < debug_info_length;) { | |
355 dwarf2reader::CompilationUnit cureader(elfInfo->GetSectionMap(), | |
356 offset, | |
357 elfInfo->GetByteReader(), | |
358 &info_handler); | |
359 | |
360 // Process the entire compilation unit; get the offset of the next. | |
361 offset += cureader.Start(); | |
362 | |
363 // Process the matching line information; get the offset of the next. | |
364 dwarf2reader::LineInfo lineInfo(debug_line_ptr, debug_line_length, | |
365 elfInfo->GetByteReader(), &line_handler); | |
366 | |
367 debug_line_ptr += lineInfo.Start(); | |
368 | |
369 // Pop the end of the compilation unit manually | |
370 reader->EndCompilationUnit(parseState.ctxStack_.top(), parseState.addrStack_
.top()); | |
371 parseState.ctxStack_.pop(); | |
372 parseState.addrStack_.pop(); | |
373 } | |
374 | |
375 // | |
376 // Read the call frame information | |
377 // | |
378 dwarf2reader::CallFrameInfo::Reporter reporter(elf->GetPath()); | |
379 DwarfFrameInfoReader handler(reader); | |
380 dwarf2reader::CallFrameInfo cfiReader( | |
381 debug_frame_section.first, | |
382 debug_frame_section.second, | |
383 elfInfo->GetByteReader(), | |
384 &handler, | |
385 &reporter, | |
386 true); | |
387 cfiReader.Start(); | |
388 | |
389 // | |
390 // Read the location list | |
391 // TODO(ilewis): this should probably move to a different function. | |
392 // | |
393 const char* debug_loc_ptr = debug_loc_section.first; | |
394 const char* current = debug_loc_ptr; | |
395 uint64 debug_loc_length = debug_loc_section.second; | |
396 const char* debug_loc_end = debug_loc_ptr + debug_loc_length; | |
397 ByteReader* byte_reader = elfInfo->GetByteReader(); | |
398 bool is_first = true; | |
399 while (current < debug_loc_end) { | |
400 // | |
401 // Layout of the debug_loc block is: | |
402 // | |
403 // LowPc - address | |
404 // HighPc - address | |
405 // DataLength - ushort (optional) | |
406 // Data - byte[] (optional) | |
407 // | |
408 uint64 offset = current - debug_loc_ptr; | |
409 | |
410 uint64 lowPc = byte_reader->ReadAddress(current); | |
411 current += byte_reader->AddressSize(); | |
412 | |
413 uint64 highPc = byte_reader->ReadAddress(current); | |
414 current += byte_reader->AddressSize(); | |
415 | |
416 size_t dataSize = 0; | |
417 const void* data = 0; | |
418 | |
419 if (lowPc == 0 && highPc == 0) { | |
420 // if lowPc and highPc are both zero, that signals end of list. | |
421 is_first = true; | |
422 continue; | |
423 } else if (lowPc == (uint64) -1) { | |
424 // the location is an absolute address; its value is in highPc. | |
425 dataSize = 4; | |
426 data = &highPc; | |
427 } else { | |
428 dataSize = byte_reader->ReadTwoBytes(current); | |
429 current += 2; | |
430 | |
431 data = (void*)current; | |
432 current += dataSize; | |
433 } | |
434 | |
435 reader->AddLocListEntry(offset, is_first, lowPc, highPc, data, dataSize); | |
436 | |
437 is_first = false; | |
438 } | |
439 | |
440 delete elfInfo; | |
441 } | |
442 | |
443 uint32_t DwarfRun32(IDwarfVM *vm, ByteReader *reader, const char *program, int l
ength); | |
444 uint64_t DwarfRun64(IDwarfVM *vm, ByteReader *reader, const char *program, int l
ength); | |
445 | |
446 uint64_t DwarfParseVM(IDwarfVM* vm, uint8_t *data, uint32_t length) { | |
447 ByteReader *byteReader; | |
448 if (vm->IsLSB()) | |
449 byteReader = new ByteReader(ENDIANNESS_LITTLE); | |
450 else | |
451 byteReader = new ByteReader(ENDIANNESS_BIG); | |
452 | |
453 switch(vm->BitWidth()) { | |
454 case 32: | |
455 byteReader->SetAddressSize(4); | |
456 return DwarfRun32(vm, byteReader, (const char *) data, length); | |
457 break; | |
458 | |
459 case 64: | |
460 byteReader->SetAddressSize(8); | |
461 return DwarfRun32(vm, byteReader, (const char *) data, length); | |
462 break; | |
463 } | |
464 | |
465 return 0; | |
466 } | |
467 | |
468 | |
469 } // namespace dwarf_reader | |
470 | |
OLD | NEW |