OLD | NEW |
| (Empty) |
1 // -*- mode: c++ -*- | |
2 | |
3 // Copyright (c) 2010 Google Inc. All Rights Reserved. | |
4 // | |
5 // Redistribution and use in source and binary forms, with or without | |
6 // modification, are permitted provided that the following conditions are | |
7 // met: | |
8 // | |
9 // * Redistributions of source code must retain the above copyright | |
10 // notice, this list of conditions and the following disclaimer. | |
11 // * Redistributions in binary form must reproduce the above | |
12 // copyright notice, this list of conditions and the following disclaimer | |
13 // in the documentation and/or other materials provided with the | |
14 // distribution. | |
15 // * Neither the name of Google Inc. nor the names of its | |
16 // contributors may be used to endorse or promote products derived from | |
17 // this software without specific prior written permission. | |
18 // | |
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | |
31 | |
32 #include <sys/types.h> | |
33 #include <sys/stat.h> | |
34 #include <fcntl.h> | |
35 #include <stdio.h> | |
36 #include <stdlib.h> | |
37 #include <string.h> | |
38 #include <io.h> | |
39 | |
40 #include <algorithm> | |
41 #include <map> | |
42 #include <stack> | |
43 #include <iostream> | |
44 #include <sstream> | |
45 | |
46 #include "common\dwarf\dwarf2enums.h" | |
47 | |
48 #include "elf_reader\elf_object.h" | |
49 #include "dwarf_reader\dwarf_parse.h" | |
50 #include "dwarf_reader\dwarf_reader.h" | |
51 #include "dwarf_reader\dwarf_strings.h" | |
52 #include "dwarf_reader\dwarf_vm.h" | |
53 | |
54 using namespace std; | |
55 using namespace dwarf2reader; | |
56 using namespace dwarf_reader; | |
57 using namespace elf_reader; | |
58 | |
59 void StreamTabs(uint32_t depth) { | |
60 cout.width(0); | |
61 | |
62 for (int64 a = 0; a < depth; a++) | |
63 cout << " "; | |
64 } | |
65 | |
66 void StreamStartTag(const char *name) { | |
67 cout.width(0); | |
68 cout << "<" << name << ">"; | |
69 } | |
70 | |
71 void StreamEndTag(const char *name) { | |
72 cout.width(0); | |
73 cout << "</" << name << ">" << endl; | |
74 } | |
75 | |
76 template<typename T> | |
77 void StreamValue(const T& val) { | |
78 cout << val; | |
79 } | |
80 | |
81 void StreamValue(const uint64& val) { | |
82 cout << hex << val << dec; | |
83 } | |
84 | |
85 template<typename T> | |
86 void StreamTag(int tabs, const char* name, const T& val) { | |
87 StreamTabs(tabs); | |
88 StreamStartTag(name); | |
89 StreamValue(val); | |
90 StreamEndTag(name); | |
91 } | |
92 | |
93 template<typename T> | |
94 void StreamTag(const char* name, const T& val, int tabs = 0) { | |
95 StreamTag(0, name, val); | |
96 } | |
97 | |
98 | |
99 class DwarfInfo : public IDwarfReader { | |
100 public: | |
101 void *StartCompilationUnit(uint64 offset, uint8 address_size, | |
102 uint8 offset_size, uint64 cu_length, | |
103 uint8 dwarf_version) { | |
104 | |
105 cout.fill('0'); | |
106 cout.setf(std::ios_base::showbase); | |
107 | |
108 StreamStartTag("compile_block"); | |
109 cout << endl; | |
110 return (void *) 1; | |
111 } | |
112 | |
113 void EndCompilationUnit(void *ctx, uint64 offset) { | |
114 StreamEndTag("compile_block"); | |
115 } | |
116 | |
117 void *StartDIE(void *ctx, uint64 parent, uint64 offset, enum DwarfTag tag) { | |
118 const char *tagName = DwarfTagName(tag); | |
119 | |
120 StreamTabs((int) ctx); | |
121 StreamStartTag(tagName); | |
122 cout << endl; | |
123 | |
124 tags_.push(tagName); | |
125 | |
126 StreamTabs((int) ctx + 1); | |
127 StreamStartTag("ID"); | |
128 cout.width(1); | |
129 cout.setf(ios_base::hex , ios_base::basefield); | |
130 cout << offset; | |
131 StreamEndTag("ID"); | |
132 return (void *) (((int) ctx) + 1); | |
133 } | |
134 | |
135 void EndDIE(void *ctx, uint64 offset) { | |
136 const char *name = tags_.top(); | |
137 tags_.pop(); | |
138 | |
139 StreamTabs((int) ctx - 1); | |
140 StreamStartTag(name); | |
141 cout << endl; | |
142 } | |
143 | |
144 void ProcessAttributeUnsigned(void *ctx, | |
145 uint64 offset, | |
146 uint64 parent, | |
147 enum DwarfAttribute attr, | |
148 enum DwarfForm form, | |
149 uint64 data) { | |
150 const char *attrName = DwarfAttributeName(attr); | |
151 | |
152 switch(form) { | |
153 case DW_FORM_data8: | |
154 cout.width(16); | |
155 cout.setf(ios_base::hex , ios_base::basefield); | |
156 break; | |
157 | |
158 case DW_FORM_data4: | |
159 case DW_FORM_data2: | |
160 cout.width(8); | |
161 cout.setf(ios_base::hex , ios_base::basefield); | |
162 break; | |
163 | |
164 case DW_FORM_addr: | |
165 cout.width(1); | |
166 cout.setf(ios_base::hex , ios_base::basefield); | |
167 break; | |
168 | |
169 case DW_FORM_data1: | |
170 case DW_FORM_flag: | |
171 cout.width(1); | |
172 cout.setf(ios_base::dec , ios_base::basefield); | |
173 break; | |
174 | |
175 default: | |
176 break; | |
177 } | |
178 | |
179 StreamTabs((int) ctx); | |
180 StreamStartTag(attrName); | |
181 cout << data; | |
182 StreamEndTag(attrName); | |
183 } | |
184 | |
185 void ProcessAttributeSigned(void *ctx, | |
186 uint64 offset, | |
187 uint64 parent, | |
188 enum DwarfAttribute attr, | |
189 enum DwarfForm form, | |
190 int64 data) { | |
191 const char *attrName = DwarfAttributeName(attr); | |
192 switch(form) { | |
193 case DW_FORM_data4: | |
194 case DW_FORM_data2: | |
195 cout.width(8); | |
196 cout.setf(ios_base::hex , ios_base::basefield); | |
197 break; | |
198 | |
199 case DW_FORM_data1: | |
200 case DW_FORM_sdata: | |
201 cout.width(1); | |
202 cout.setf(ios_base::dec , ios_base::basefield); | |
203 break; | |
204 | |
205 default: | |
206 break; | |
207 } | |
208 | |
209 StreamTabs((int) ctx); | |
210 StreamStartTag(attrName); | |
211 cout << data; | |
212 StreamEndTag(attrName); | |
213 } | |
214 | |
215 void ProcessAttributeReference(void *ctx, | |
216 uint64 offset, | |
217 uint64 parent, | |
218 enum DwarfAttribute attr, | |
219 enum DwarfForm form, | |
220 uint64 data) { | |
221 const char *attrName = DwarfAttributeName(attr); | |
222 switch(form) { | |
223 case DW_FORM_ref_addr: | |
224 case DW_FORM_ref1: | |
225 case DW_FORM_ref2: | |
226 case DW_FORM_ref4: | |
227 case DW_FORM_ref8: | |
228 cout.width(1); | |
229 cout.setf(ios_base::hex , ios_base::basefield); | |
230 break; | |
231 | |
232 default: | |
233 break; | |
234 } | |
235 | |
236 StreamTabs((int) ctx); | |
237 StreamStartTag(attrName); | |
238 cout << data; | |
239 StreamEndTag(attrName); | |
240 } | |
241 | |
242 void ProcessAttributeBuffer(void *ctx, | |
243 uint64 offset, | |
244 uint64 parent, | |
245 enum DwarfAttribute attr, | |
246 enum DwarfForm form, | |
247 const char* data, | |
248 uint64 len) { | |
249 const char *attrName = DwarfAttributeName(attr); | |
250 | |
251 StreamTabs((int) ctx); | |
252 StreamStartTag(attrName); | |
253 | |
254 cout.width(0); | |
255 cout.setf(ios_base::hex , ios_base::basefield); | |
256 | |
257 if (form != DW_FORM_block1) { | |
258 printf("ATTR=%s FORM=%s\n", DwarfAttributeName(attr), DwarfFormName(form))
; | |
259 cout.unsetf(std::ios_base::showbase); | |
260 cout << "0x"; | |
261 for (uint64 a = 0; a < len; a++) { | |
262 uint32 l = ((unsigned char) data[a]) >> 4; | |
263 uint32 r = ((unsigned char) data[a]) & 0xF; | |
264 | |
265 cout << l; | |
266 cout << r; | |
267 } | |
268 } | |
269 else { | |
270 DwarfStaticVM64 vm; | |
271 // vm.Push(0); | |
272 // vm.Run(data, len); | |
273 // int64 addr = *(vm.StackTop()); | |
274 | |
275 int64 addr = DwarfParseVM(&vm, (uint8_t *) data, len); | |
276 cout.setf(std::ios_base::showbase); | |
277 if (addr < 0) | |
278 cout.setf(ios_base::dec , ios_base::basefield); | |
279 | |
280 cout << addr; | |
281 } | |
282 cout.setf(std::ios_base::showbase); | |
283 StreamEndTag(attrName); | |
284 } | |
285 | |
286 void ProcessAttributeString(void *ctx, | |
287 uint64 offset, | |
288 uint64 parent, | |
289 enum DwarfAttribute attr, | |
290 enum DwarfForm form, | |
291 const char* data) { | |
292 const char *attrName = DwarfAttributeName(attr); | |
293 switch(form) { | |
294 case DW_FORM_strp: | |
295 case DW_FORM_string: | |
296 break; | |
297 | |
298 default: | |
299 break; | |
300 } | |
301 | |
302 StreamTabs((int) ctx); | |
303 StreamStartTag(attrName); | |
304 cout << data; | |
305 StreamEndTag(attrName); | |
306 } | |
307 | |
308 void DefineDir(void *ctx, const char *name, uint32 dir_num) { | |
309 StreamTabs((int) ctx); | |
310 StreamStartTag("dir"); | |
311 cout << endl; | |
312 | |
313 StreamTabs((int) ctx + 1); | |
314 StreamStartTag("name"); | |
315 cout << name; | |
316 StreamEndTag("name"); | |
317 | |
318 StreamTabs((int) ctx + 1); | |
319 StreamStartTag("number"); | |
320 cout << dir_num; | |
321 StreamEndTag("number"); | |
322 | |
323 StreamTabs((int) ctx); | |
324 StreamEndTag("dir"); | |
325 } | |
326 | |
327 void DefineFile(void *ctx, const char *name, int32 file_num, | |
328 uint32 dir_num, uint64 mod_time, uint64 length) { | |
329 | |
330 StreamTabs((int) ctx); | |
331 StreamStartTag("file"); | |
332 cout << endl; | |
333 | |
334 StreamTabs((int) ctx + 1); | |
335 StreamStartTag("name"); | |
336 cout << name; | |
337 StreamEndTag("name"); | |
338 | |
339 StreamTabs((int) ctx + 1); | |
340 StreamStartTag("number"); | |
341 cout << file_num; | |
342 StreamEndTag("number"); | |
343 | |
344 StreamTabs((int) ctx + 1); | |
345 StreamStartTag("dir"); | |
346 cout << dir_num; | |
347 StreamEndTag("dir"); | |
348 | |
349 StreamTabs((int) ctx); | |
350 StreamEndTag("file"); | |
351 } | |
352 | |
353 void AddLine(void *ctx, uint64 address, uint64 length, uint32 file_num, | |
354 uint32 line_num, uint32 column_num) { | |
355 | |
356 StreamTabs((int) ctx); | |
357 StreamStartTag("line"); | |
358 cout << endl; | |
359 | |
360 StreamTabs((int) ctx + 1); | |
361 StreamStartTag("address"); | |
362 cout.setf(ios_base::hex , ios_base::basefield); | |
363 cout << address; | |
364 StreamEndTag("address"); | |
365 | |
366 StreamTabs((int) ctx + 1); | |
367 StreamStartTag("length"); | |
368 cout.setf(ios_base::dec , ios_base::basefield); | |
369 cout << length; | |
370 StreamEndTag("length"); | |
371 | |
372 StreamTabs((int) ctx + 1); | |
373 StreamStartTag("file"); | |
374 cout << file_num; | |
375 StreamEndTag("file"); | |
376 | |
377 StreamTabs((int) ctx + 1); | |
378 StreamStartTag("line_number"); | |
379 cout << line_num; | |
380 StreamEndTag("line_number"); | |
381 | |
382 StreamTabs((int) ctx); | |
383 StreamEndTag("line"); | |
384 } | |
385 | |
386 virtual void AddLocListEntry( | |
387 uint64 offset, | |
388 bool is_first_entry, | |
389 uint64 lowPc, | |
390 uint64 highPc, | |
391 const void* data, | |
392 size_t dataSize) { | |
393 // do nothing | |
394 } | |
395 | |
396 virtual bool BeginCfiEntry ( | |
397 size_t offset, | |
398 uint64 address, | |
399 uint64 length, | |
400 uint8 version, | |
401 const char* augmentation, | |
402 unsigned return_address){ | |
403 StreamStartTag("cfi-entry"); | |
404 cout << endl; | |
405 StreamTag(1, "offset", offset); | |
406 StreamTag(1, "address", address); | |
407 StreamTag(1, "version", (uint32)version); | |
408 StreamTag(1, "augmentation", augmentation); | |
409 StreamTag(1, "return-address", return_address); | |
410 StreamTabs(1); | |
411 StreamStartTag("rules"); | |
412 cout << endl; | |
413 return true; | |
414 } | |
415 | |
416 virtual bool AddCfiRule( | |
417 uint64 address, | |
418 int reg, | |
419 CFI_RuleType ruleType, | |
420 int base_register, | |
421 int32 offset, | |
422 const void* expression, | |
423 uint32 expressionLength) { | |
424 StreamTabs(2); | |
425 StreamStartTag("cfi-rule"); | |
426 cout << endl; | |
427 | |
428 StreamTag(3, "address", address); | |
429 StreamTag(3, "register", reg); | |
430 StreamTag(3, "rule-type", ruleType); | |
431 StreamTag(3, "base-register", base_register); | |
432 StreamTag(3, "offset", offset); | |
433 StreamTag(3, "expression", expression); | |
434 | |
435 StreamTabs(2); | |
436 StreamEndTag("cfi-rule"); | |
437 return true; | |
438 } | |
439 | |
440 virtual bool EndCfiEntry() { | |
441 StreamTabs(1); | |
442 StreamEndTag("rules"); | |
443 StreamEndTag("cfi-entry"); | |
444 return true; | |
445 } | |
446 public: | |
447 stack<const char *> tags_; | |
448 }; | |
449 | |
450 | |
451 | |
452 int main(int argc, const char *argv[]) { | |
453 const char *file = "..\\..\\..\\..\\src\\loop\\loop.nexe"; | |
454 ElfObject elf; | |
455 DwarfInfo dwarf; | |
456 | |
457 if (argc == 2) | |
458 file = argv[1]; | |
459 else { | |
460 printf("Expecting: dwarf_xml <file.nexe>\n"); | |
461 return -1; | |
462 } | |
463 | |
464 if (0 == file) | |
465 return -1; | |
466 | |
467 if (elf.Load(file)) | |
468 DwarfParseElf(&elf, &dwarf); | |
469 else | |
470 printf("Could not load '%s'\n", file); | |
471 | |
472 return 0; | |
473 } | |
OLD | NEW |