Mercurial > vba-clojure
comparison src/gba/elf.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 #include <cstdio> | |
2 #include <cstdlib> | |
3 #include <cstring> | |
4 | |
5 #include "../Port.h" | |
6 #include "../NLS.h" | |
7 #include "../common/System.h" // systemMessage | |
8 #include "GBAGlobals.h" | |
9 #include "elf.h" | |
10 | |
11 #define elfReadMemory(addr) \ | |
12 READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) | |
13 | |
14 #define DW_TAG_array_type 0x01 | |
15 #define DW_TAG_enumeration_type 0x04 | |
16 #define DW_TAG_formal_parameter 0x05 | |
17 #define DW_TAG_label 0x0a | |
18 #define DW_TAG_lexical_block 0x0b | |
19 #define DW_TAG_member 0x0d | |
20 #define DW_TAG_pointer_type 0x0f | |
21 #define DW_TAG_reference_type 0x10 | |
22 #define DW_TAG_compile_unit 0x11 | |
23 #define DW_TAG_structure_type 0x13 | |
24 #define DW_TAG_subroutine_type 0x15 | |
25 #define DW_TAG_typedef 0x16 | |
26 #define DW_TAG_union_type 0x17 | |
27 #define DW_TAG_unspecified_parameters 0x18 | |
28 #define DW_TAG_inheritance 0x1c | |
29 #define DW_TAG_inlined_subroutine 0x1d | |
30 #define DW_TAG_subrange_type 0x21 | |
31 #define DW_TAG_base_type 0x24 | |
32 #define DW_TAG_const_type 0x26 | |
33 #define DW_TAG_enumerator 0x28 | |
34 #define DW_TAG_subprogram 0x2e | |
35 #define DW_TAG_variable 0x34 | |
36 #define DW_TAG_volatile_type 0x35 | |
37 | |
38 #define DW_AT_sibling 0x01 | |
39 #define DW_AT_location 0x02 | |
40 #define DW_AT_name 0x03 | |
41 #define DW_AT_byte_size 0x0b | |
42 #define DW_AT_bit_offset 0x0c | |
43 #define DW_AT_bit_size 0x0d | |
44 #define DW_AT_stmt_list 0x10 | |
45 #define DW_AT_low_pc 0x11 | |
46 #define DW_AT_high_pc 0x12 | |
47 #define DW_AT_language 0x13 | |
48 #define DW_AT_compdir 0x1b | |
49 #define DW_AT_const_value 0x1c | |
50 #define DW_AT_containing_type 0x1d | |
51 #define DW_AT_inline 0x20 | |
52 #define DW_AT_producer 0x25 | |
53 #define DW_AT_prototyped 0x27 | |
54 #define DW_AT_upper_bound 0x2f | |
55 #define DW_AT_abstract_origin 0x31 | |
56 #define DW_AT_accessibility 0x32 | |
57 #define DW_AT_artificial 0x34 | |
58 #define DW_AT_data_member_location 0x38 | |
59 #define DW_AT_decl_file 0x3a | |
60 #define DW_AT_decl_line 0x3b | |
61 #define DW_AT_declaration 0x3c | |
62 #define DW_AT_encoding 0x3e | |
63 #define DW_AT_external 0x3f | |
64 #define DW_AT_frame_base 0x40 | |
65 #define DW_AT_macro_info 0x43 | |
66 #define DW_AT_specification 0x47 | |
67 #define DW_AT_type 0x49 | |
68 #define DW_AT_virtuality 0x4c | |
69 #define DW_AT_vtable_elem_location 0x4d | |
70 // DWARF 2.1/3.0 extensions | |
71 #define DW_AT_entry_pc 0x52 | |
72 #define DW_AT_ranges 0x55 | |
73 // ARM Compiler extensions | |
74 #define DW_AT_proc_body 0x2000 | |
75 #define DW_AT_save_offset 0x2001 | |
76 #define DW_AT_user_2002 0x2002 | |
77 // MIPS extensions | |
78 #define DW_AT_MIPS_linkage_name 0x2007 | |
79 | |
80 #define DW_FORM_addr 0x01 | |
81 #define DW_FORM_data2 0x05 | |
82 #define DW_FORM_data4 0x06 | |
83 #define DW_FORM_string 0x08 | |
84 #define DW_FORM_block 0x09 | |
85 #define DW_FORM_block1 0x0a | |
86 #define DW_FORM_data1 0x0b | |
87 #define DW_FORM_flag 0x0c | |
88 #define DW_FORM_sdata 0x0d | |
89 #define DW_FORM_strp 0x0e | |
90 #define DW_FORM_udata 0x0f | |
91 #define DW_FORM_ref_addr 0x10 | |
92 #define DW_FORM_ref4 0x13 | |
93 #define DW_FORM_ref_udata 0x15 | |
94 #define DW_FORM_indirect 0x16 | |
95 | |
96 #define DW_OP_addr 0x03 | |
97 #define DW_OP_plus_uconst 0x23 | |
98 #define DW_OP_reg0 0x50 | |
99 #define DW_OP_reg1 0x51 | |
100 #define DW_OP_reg2 0x52 | |
101 #define DW_OP_reg3 0x53 | |
102 #define DW_OP_reg4 0x54 | |
103 #define DW_OP_reg5 0x55 | |
104 #define DW_OP_reg6 0x56 | |
105 #define DW_OP_reg7 0x57 | |
106 #define DW_OP_reg8 0x58 | |
107 #define DW_OP_reg9 0x59 | |
108 #define DW_OP_reg10 0x5a | |
109 #define DW_OP_reg11 0x5b | |
110 #define DW_OP_reg12 0x5c | |
111 #define DW_OP_reg13 0x5d | |
112 #define DW_OP_reg14 0x5e | |
113 #define DW_OP_reg15 0x5f | |
114 #define DW_OP_fbreg 0x91 | |
115 | |
116 #define DW_LNS_extended_op 0x00 | |
117 #define DW_LNS_copy 0x01 | |
118 #define DW_LNS_advance_pc 0x02 | |
119 #define DW_LNS_advance_line 0x03 | |
120 #define DW_LNS_set_file 0x04 | |
121 #define DW_LNS_set_column 0x05 | |
122 #define DW_LNS_negate_stmt 0x06 | |
123 #define DW_LNS_set_basic_block 0x07 | |
124 #define DW_LNS_const_add_pc 0x08 | |
125 #define DW_LNS_fixed_advance_pc 0x09 | |
126 | |
127 #define DW_LNE_end_sequence 0x01 | |
128 #define DW_LNE_set_address 0x02 | |
129 #define DW_LNE_define_file 0x03 | |
130 | |
131 #define DW_CFA_advance_loc 0x01 | |
132 #define DW_CFA_offset 0x02 | |
133 #define DW_CFA_restore 0x03 | |
134 #define DW_CFA_set_loc 0x01 | |
135 #define DW_CFA_advance_loc1 0x02 | |
136 #define DW_CFA_advance_loc2 0x03 | |
137 #define DW_CFA_advance_loc4 0x04 | |
138 #define DW_CFA_offset_extended 0x05 | |
139 #define DW_CFA_restore_extended 0x06 | |
140 #define DW_CFA_undefined 0x07 | |
141 #define DW_CFA_same_value 0x08 | |
142 #define DW_CFA_register 0x09 | |
143 #define DW_CFA_remember_state 0x0a | |
144 #define DW_CFA_restore_state 0x0b | |
145 #define DW_CFA_def_cfa 0x0c | |
146 #define DW_CFA_def_cfa_register 0x0d | |
147 #define DW_CFA_def_cfa_offset 0x0e | |
148 #define DW_CFA_nop 0x00 | |
149 | |
150 #define CASE_TYPE_TAG \ | |
151 case DW_TAG_const_type: \ | |
152 case DW_TAG_volatile_type: \ | |
153 case DW_TAG_pointer_type: \ | |
154 case DW_TAG_base_type: \ | |
155 case DW_TAG_array_type: \ | |
156 case DW_TAG_structure_type: \ | |
157 case DW_TAG_union_type: \ | |
158 case DW_TAG_typedef: \ | |
159 case DW_TAG_subroutine_type: \ | |
160 case DW_TAG_enumeration_type: \ | |
161 case DW_TAG_enumerator: \ | |
162 case DW_TAG_reference_type | |
163 | |
164 struct ELFcie | |
165 { | |
166 ELFcie *next; | |
167 u32 offset; | |
168 u8 * augmentation; | |
169 u32 codeAlign; | |
170 s32 dataAlign; | |
171 int returnAddress; | |
172 u8 * data; | |
173 u32 dataLen; | |
174 }; | |
175 | |
176 struct ELFfde | |
177 { | |
178 ELFcie *cie; | |
179 u32 address; | |
180 u32 end; | |
181 u8 * data; | |
182 u32 dataLen; | |
183 }; | |
184 | |
185 enum ELFRegMode | |
186 { | |
187 REG_NOT_SET, | |
188 REG_OFFSET, | |
189 REG_REGISTER | |
190 }; | |
191 | |
192 struct ELFFrameStateRegister | |
193 { | |
194 ELFRegMode mode; | |
195 int reg; | |
196 s32 offset; | |
197 }; | |
198 | |
199 struct ELFFrameStateRegisters | |
200 { | |
201 ELFFrameStateRegister regs[16]; | |
202 ELFFrameStateRegisters *previous; | |
203 }; | |
204 | |
205 enum ELFCfaMode | |
206 { | |
207 CFA_NOT_SET, | |
208 CFA_REG_OFFSET | |
209 }; | |
210 | |
211 struct ELFFrameState | |
212 { | |
213 ELFFrameStateRegisters registers; | |
214 | |
215 ELFCfaMode cfaMode; | |
216 int cfaRegister; | |
217 s32 cfaOffset; | |
218 | |
219 u32 pc; | |
220 | |
221 int dataAlign; | |
222 int codeAlign; | |
223 int returnAddress; | |
224 }; | |
225 | |
226 extern bool8 cpuIsMultiBoot; | |
227 | |
228 Symbol *elfSymbols = NULL; | |
229 char * elfSymbolsStrTab = NULL; | |
230 int elfSymbolsCount = 0; | |
231 | |
232 ELFSectionHeader **elfSectionHeaders = NULL; | |
233 char *elfSectionHeadersStringTable = NULL; | |
234 int elfSectionHeadersCount = 0; | |
235 u8 * elfFileData = NULL; | |
236 | |
237 CompileUnit *elfCompileUnits = NULL; | |
238 DebugInfo * elfDebugInfo = NULL; | |
239 char * elfDebugStrings = NULL; | |
240 | |
241 ELFcie * elfCies = NULL; | |
242 ELFfde **elfFdes = NULL; | |
243 int elfFdeCount = 0; | |
244 | |
245 CompileUnit *elfCurrentUnit = NULL; | |
246 | |
247 u32 elfRead4Bytes(u8 *); | |
248 u16 elfRead2Bytes(u8 *); | |
249 | |
250 CompileUnit *elfGetCompileUnit(u32 addr) | |
251 { | |
252 if (elfCompileUnits) | |
253 { | |
254 CompileUnit *unit = elfCompileUnits; | |
255 while (unit) | |
256 { | |
257 if (unit->lowPC) | |
258 { | |
259 if (addr >= unit->lowPC && addr < unit->highPC) | |
260 return unit; | |
261 } | |
262 else | |
263 { | |
264 ARanges *r = unit->ranges; | |
265 if (r) | |
266 { | |
267 int count = r->count; | |
268 for (int j = 0; j < count; j++) | |
269 { | |
270 if (addr >= r->ranges[j].lowPC && addr < r->ranges[j].highPC) | |
271 return unit; | |
272 } | |
273 } | |
274 } | |
275 unit = unit->next; | |
276 } | |
277 } | |
278 return NULL; | |
279 } | |
280 | |
281 char *elfGetAddressSymbol(u32 addr) | |
282 { | |
283 static char buffer[256]; | |
284 | |
285 CompileUnit *unit = elfGetCompileUnit(addr); | |
286 // found unit, need to find function | |
287 if (unit) | |
288 { | |
289 Function *func = unit->functions; | |
290 while (func) | |
291 { | |
292 if (addr >= func->lowPC && addr < func->highPC) | |
293 { | |
294 int offset = addr - func->lowPC; | |
295 char *name = func->name; | |
296 if (!name) | |
297 name = ""; | |
298 if (offset) | |
299 sprintf(buffer, "%s+%d", name, offset); | |
300 else | |
301 strcpy(buffer, name); | |
302 return buffer; | |
303 } | |
304 func = func->next; | |
305 } | |
306 } | |
307 | |
308 if (elfSymbolsCount) | |
309 { | |
310 for (int i = 0; i < elfSymbolsCount; i++) | |
311 { | |
312 Symbol *s = &elfSymbols[i]; | |
313 if ((addr >= s->value) && addr < (s->value+s->size)) | |
314 { | |
315 int offset = addr-s->value; | |
316 char *name = s->name; | |
317 if (name == NULL) | |
318 name = ""; | |
319 if (offset) | |
320 sprintf(buffer, "%s+%d", name, addr-s->value); | |
321 else | |
322 strcpy(buffer, name); | |
323 return buffer; | |
324 } | |
325 else if (addr == s->value) | |
326 { | |
327 if (s->name) | |
328 strcpy(buffer, s->name); | |
329 else | |
330 strcpy(buffer, ""); | |
331 return buffer; | |
332 } | |
333 } | |
334 } | |
335 | |
336 return ""; | |
337 } | |
338 | |
339 bool elfFindLineInModule(u32 *addr, char *name, int line) | |
340 { | |
341 CompileUnit *unit = elfCompileUnits; | |
342 | |
343 while (unit) | |
344 { | |
345 if (unit->lineInfoTable) | |
346 { | |
347 int i; | |
348 int count = unit->lineInfoTable->fileCount; | |
349 char *found = NULL; | |
350 for (i = 0; i < count; i++) | |
351 { | |
352 if (strcmp(name, unit->lineInfoTable->files[i]) == 0) | |
353 { | |
354 found = unit->lineInfoTable->files[i]; | |
355 break; | |
356 } | |
357 } | |
358 // found a matching filename... try to find line now | |
359 if (found) | |
360 { | |
361 LineInfoItem *table = unit->lineInfoTable->lines; | |
362 count = unit->lineInfoTable->number; | |
363 for (i = 0; i < count; i++) | |
364 { | |
365 if (table[i].file == found && table[i].line == line) | |
366 { | |
367 *addr = table[i].address; | |
368 return true; | |
369 } | |
370 } | |
371 // we can only find a single match | |
372 return false; | |
373 } | |
374 } | |
375 unit = unit->next; | |
376 } | |
377 return false; | |
378 } | |
379 | |
380 int elfFindLine(CompileUnit *unit, Function * /* func */, u32 addr, char **f) | |
381 { | |
382 int currentLine = -1; | |
383 if (unit->hasLineInfo) | |
384 { | |
385 int count = unit->lineInfoTable->number; | |
386 LineInfoItem *table = unit->lineInfoTable->lines; | |
387 int i; | |
388 for (i = 0; i < count; i++) | |
389 { | |
390 if (addr <= table[i].address) | |
391 break; | |
392 } | |
393 if (i == count) | |
394 i--; | |
395 *f = table[i].file; | |
396 currentLine = table[i].line; | |
397 } | |
398 return currentLine; | |
399 } | |
400 | |
401 bool elfFindLineInUnit(u32 *addr, CompileUnit *unit, int line) | |
402 { | |
403 if (unit->hasLineInfo) | |
404 { | |
405 int count = unit->lineInfoTable->number; | |
406 LineInfoItem *table = unit->lineInfoTable->lines; | |
407 int i; | |
408 for (i = 0; i < count; i++) | |
409 { | |
410 if (line == table[i].line) | |
411 { | |
412 *addr = table[i].address; | |
413 return true; | |
414 } | |
415 } | |
416 } | |
417 return false; | |
418 } | |
419 | |
420 bool elfGetCurrentFunction(u32 addr, Function **f, CompileUnit **u) | |
421 { | |
422 CompileUnit *unit = elfGetCompileUnit(addr); | |
423 // found unit, need to find function | |
424 if (unit) | |
425 { | |
426 Function *func = unit->functions; | |
427 while (func) | |
428 { | |
429 if (addr >= func->lowPC && addr < func->highPC) | |
430 { | |
431 *f = func; | |
432 *u = unit; | |
433 return true; | |
434 } | |
435 func = func->next; | |
436 } | |
437 } | |
438 return false; | |
439 } | |
440 | |
441 bool elfGetObject(char *name, Function *f, CompileUnit *u, Object **o) | |
442 { | |
443 if (f && u) | |
444 { | |
445 Object *v = f->variables; | |
446 | |
447 while (v) | |
448 { | |
449 if (strcmp(name, v->name) == 0) | |
450 { | |
451 *o = v; | |
452 return true; | |
453 } | |
454 v = v->next; | |
455 } | |
456 v = f->parameters; | |
457 while (v) | |
458 { | |
459 if (strcmp(name, v->name) == 0) | |
460 { | |
461 *o = v; | |
462 return true; | |
463 } | |
464 v = v->next; | |
465 } | |
466 v = u->variables; | |
467 while (v) | |
468 { | |
469 if (strcmp(name, v->name) == 0) | |
470 { | |
471 *o = v; | |
472 return true; | |
473 } | |
474 v = v->next; | |
475 } | |
476 } | |
477 | |
478 CompileUnit *c = elfCompileUnits; | |
479 | |
480 while (c) | |
481 { | |
482 if (c != u) | |
483 { | |
484 Object *v = c->variables; | |
485 while (v) | |
486 { | |
487 if (strcmp(name, v->name) == 0) | |
488 { | |
489 *o = v; | |
490 return true; | |
491 } | |
492 v = v->next; | |
493 } | |
494 } | |
495 c = c->next; | |
496 } | |
497 | |
498 return false; | |
499 } | |
500 | |
501 char *elfGetSymbol(int i, u32 *value, u32 *size, int *type) | |
502 { | |
503 if (i < elfSymbolsCount) | |
504 { | |
505 Symbol *s = &elfSymbols[i]; | |
506 *value = s->value; | |
507 *size = s->size; | |
508 *type = s->type; | |
509 return s->name; | |
510 } | |
511 return NULL; | |
512 } | |
513 | |
514 bool elfGetSymbolAddress(char *sym, u32 *addr, u32 *size, int *type) | |
515 { | |
516 if (elfSymbolsCount) | |
517 { | |
518 for (int i = 0; i < elfSymbolsCount; i++) | |
519 { | |
520 Symbol *s = &elfSymbols[i]; | |
521 if (strcmp(sym, s->name) == 0) | |
522 { | |
523 *addr = s->value; | |
524 *size = s->size; | |
525 *type = s->type; | |
526 return true; | |
527 } | |
528 } | |
529 } | |
530 return false; | |
531 } | |
532 | |
533 ELFfde *elfGetFde(u32 address) | |
534 { | |
535 if (elfFdes) | |
536 { | |
537 int i; | |
538 for (i = 0; i < elfFdeCount; i++) | |
539 { | |
540 if (address >= elfFdes[i]->address && | |
541 address < elfFdes[i]->end) | |
542 { | |
543 return elfFdes[i]; | |
544 } | |
545 } | |
546 } | |
547 | |
548 return NULL; | |
549 } | |
550 | |
551 void elfExecuteCFAInstructions(ELFFrameState *state, u8 *data, u32 len, | |
552 u32 pc) | |
553 { | |
554 u8 *end = data + len; | |
555 int bytes; | |
556 int reg; | |
557 ELFFrameStateRegisters *fs; | |
558 | |
559 while (data < end && state->pc < pc) | |
560 { | |
561 u8 op = *data++; | |
562 | |
563 switch (op >> 6) | |
564 { | |
565 case DW_CFA_advance_loc: | |
566 state->pc += (op & 0x3f) * state->codeAlign; | |
567 break; | |
568 case DW_CFA_offset: | |
569 reg = op & 0x3f; | |
570 state->registers.regs[reg].mode = REG_OFFSET; | |
571 state->registers.regs[reg].offset = state->dataAlign * | |
572 (s32)elfReadLEB128(data, &bytes); | |
573 data += bytes; | |
574 break; | |
575 case DW_CFA_restore: | |
576 // we don't care much about the other possible settings, | |
577 // so just setting to unset is enough for now | |
578 state->registers.regs[op & 0x3f].mode = REG_NOT_SET; | |
579 break; | |
580 case 0: | |
581 switch (op & 0x3f) | |
582 { | |
583 case DW_CFA_nop: | |
584 break; | |
585 case DW_CFA_advance_loc1: | |
586 state->pc += state->codeAlign * (*data++); | |
587 break; | |
588 case DW_CFA_advance_loc2: | |
589 state->pc += state->codeAlign * elfRead2Bytes(data); | |
590 data += 2; | |
591 break; | |
592 case DW_CFA_advance_loc4: | |
593 state->pc += state->codeAlign * elfRead4Bytes(data); | |
594 data += 4; | |
595 break; | |
596 case DW_CFA_offset_extended: | |
597 reg = elfReadLEB128(data, &bytes); | |
598 data += bytes; | |
599 state->registers.regs[reg].mode = REG_OFFSET; | |
600 state->registers.regs[reg].offset = state->dataAlign * | |
601 (s32)elfReadLEB128(data, &bytes); | |
602 data += bytes; | |
603 break; | |
604 case DW_CFA_restore_extended: | |
605 case DW_CFA_undefined: | |
606 case DW_CFA_same_value: | |
607 reg = elfReadLEB128(data, &bytes); | |
608 data += bytes; | |
609 state->registers.regs[reg].mode = REG_NOT_SET; | |
610 break; | |
611 case DW_CFA_register: | |
612 reg = elfReadLEB128(data, &bytes); | |
613 data += bytes; | |
614 state->registers.regs[reg].mode = REG_REGISTER; | |
615 state->registers.regs[reg].reg = elfReadLEB128(data, &bytes); | |
616 data += bytes; | |
617 break; | |
618 case DW_CFA_remember_state: | |
619 fs = (ELFFrameStateRegisters *)calloc(1, | |
620 sizeof(ELFFrameStateRegisters)); | |
621 memcpy(fs, &state->registers, sizeof(ELFFrameStateRegisters)); | |
622 state->registers.previous = fs; | |
623 break; | |
624 case DW_CFA_restore_state: | |
625 if (state->registers.previous == NULL) | |
626 { | |
627 printf("Error: previous frame state is NULL.\n"); | |
628 return; | |
629 } | |
630 fs = state->registers.previous; | |
631 memcpy(&state->registers, fs, sizeof(ELFFrameStateRegisters)); | |
632 free(fs); | |
633 break; | |
634 case DW_CFA_def_cfa: | |
635 state->cfaRegister = elfReadLEB128(data, &bytes); | |
636 data += bytes; | |
637 state->cfaOffset = (s32)elfReadLEB128(data, &bytes); | |
638 data += bytes; | |
639 state->cfaMode = CFA_REG_OFFSET; | |
640 break; | |
641 case DW_CFA_def_cfa_register: | |
642 state->cfaRegister = elfReadLEB128(data, &bytes); | |
643 data += bytes; | |
644 state->cfaMode = CFA_REG_OFFSET; | |
645 break; | |
646 case DW_CFA_def_cfa_offset: | |
647 state->cfaOffset = (s32)elfReadLEB128(data, &bytes); | |
648 data += bytes; | |
649 state->cfaMode = CFA_REG_OFFSET; | |
650 break; | |
651 default: | |
652 printf("Unknown CFA opcode %08x\n", op); | |
653 return; | |
654 } | |
655 break; | |
656 default: | |
657 printf("Unknown CFA opcode %08x\n", op); | |
658 return; | |
659 } | |
660 } | |
661 } | |
662 | |
663 ELFFrameState *elfGetFrameState(ELFfde *fde, u32 address) | |
664 { | |
665 ELFFrameState *state = (ELFFrameState *)calloc(1, sizeof(ELFFrameState)); | |
666 state->pc = fde->address; | |
667 state->dataAlign = fde->cie->dataAlign; | |
668 state->codeAlign = fde->cie->codeAlign; | |
669 state->returnAddress = fde->cie->returnAddress; | |
670 | |
671 elfExecuteCFAInstructions(state, | |
672 fde->cie->data, | |
673 fde->cie->dataLen, | |
674 0xffffffff); | |
675 elfExecuteCFAInstructions(state, | |
676 fde->data, | |
677 fde->dataLen, | |
678 address); | |
679 | |
680 return state; | |
681 } | |
682 | |
683 void elfPrintCallChain(u32 address) | |
684 { | |
685 int count = 1; | |
686 | |
687 reg_pair regs[15]; | |
688 reg_pair newRegs[15]; | |
689 | |
690 memcpy(®s[0], ®[0], sizeof(reg_pair) * 15); | |
691 | |
692 while (count < 20) | |
693 { | |
694 char *addr = elfGetAddressSymbol(address); | |
695 if (*addr == 0) | |
696 addr = "???"; | |
697 | |
698 printf("%08x %s\n", address, addr); | |
699 | |
700 ELFfde *fde = elfGetFde(address); | |
701 | |
702 if (fde == NULL) | |
703 { | |
704 break; | |
705 } | |
706 | |
707 ELFFrameState *state = elfGetFrameState(fde, address); | |
708 | |
709 if (!state) | |
710 { | |
711 break; | |
712 } | |
713 | |
714 if (state->cfaMode == CFA_REG_OFFSET) | |
715 { | |
716 memcpy(&newRegs[0], ®s[0], sizeof(reg_pair) * 15); | |
717 u32 addr = 0; | |
718 for (int i = 0; i < 15; i++) | |
719 { | |
720 ELFFrameStateRegister *r = &state->registers. | |
721 regs[i]; | |
722 | |
723 switch (r->mode) | |
724 { | |
725 case REG_NOT_SET: | |
726 newRegs[i].I = regs[i].I; | |
727 break; | |
728 case REG_OFFSET: | |
729 newRegs[i].I = elfReadMemory(regs[state->cfaRegister].I + | |
730 state->cfaOffset + | |
731 r->offset); | |
732 break; | |
733 case REG_REGISTER: | |
734 newRegs[i].I = regs[r->reg].I; | |
735 break; | |
736 default: | |
737 printf("Unknown register mode: %d\n", r->mode); | |
738 break; | |
739 } | |
740 } | |
741 memcpy(regs, newRegs, sizeof(reg_pair)*15); | |
742 addr = newRegs[14].I; | |
743 addr &= 0xfffffffe; | |
744 address = addr; | |
745 count++; | |
746 } | |
747 else | |
748 { | |
749 printf("CFA not set\n"); | |
750 break; | |
751 } | |
752 if (state->registers.previous) | |
753 { | |
754 ELFFrameStateRegisters *prev = state->registers.previous; | |
755 | |
756 while (prev) | |
757 { | |
758 ELFFrameStateRegisters *p = prev->previous; | |
759 free(prev); | |
760 prev = p; | |
761 } | |
762 } | |
763 free(state); | |
764 } | |
765 } | |
766 | |
767 u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type, u32 base) | |
768 { | |
769 u32 framebase = 0; | |
770 if (f && f->frameBase) | |
771 { | |
772 ELFBlock *b = f->frameBase; | |
773 switch (*b->data) | |
774 { | |
775 case DW_OP_reg0: | |
776 case DW_OP_reg1: | |
777 case DW_OP_reg2: | |
778 case DW_OP_reg3: | |
779 case DW_OP_reg4: | |
780 case DW_OP_reg5: | |
781 case DW_OP_reg6: | |
782 case DW_OP_reg7: | |
783 case DW_OP_reg8: | |
784 case DW_OP_reg9: | |
785 case DW_OP_reg10: | |
786 case DW_OP_reg11: | |
787 case DW_OP_reg12: | |
788 case DW_OP_reg13: | |
789 case DW_OP_reg14: | |
790 case DW_OP_reg15: | |
791 framebase = reg[*b->data-0x50].I; | |
792 break; | |
793 default: | |
794 fprintf(stderr, "Unknown frameBase %02x\n", *b->data); | |
795 break; | |
796 } | |
797 } | |
798 | |
799 ELFBlock *loc = o; | |
800 u32 location = 0; | |
801 int bytes = 0; | |
802 if (loc) | |
803 { | |
804 switch (*loc->data) | |
805 { | |
806 case DW_OP_addr: | |
807 location = elfRead4Bytes(loc->data+1); | |
808 *type = LOCATION_memory; | |
809 break; | |
810 case DW_OP_plus_uconst: | |
811 location = base + elfReadLEB128(loc->data+1, &bytes); | |
812 *type = LOCATION_memory; | |
813 break; | |
814 case DW_OP_reg0: | |
815 case DW_OP_reg1: | |
816 case DW_OP_reg2: | |
817 case DW_OP_reg3: | |
818 case DW_OP_reg4: | |
819 case DW_OP_reg5: | |
820 case DW_OP_reg6: | |
821 case DW_OP_reg7: | |
822 case DW_OP_reg8: | |
823 case DW_OP_reg9: | |
824 case DW_OP_reg10: | |
825 case DW_OP_reg11: | |
826 case DW_OP_reg12: | |
827 case DW_OP_reg13: | |
828 case DW_OP_reg14: | |
829 case DW_OP_reg15: | |
830 location = *loc->data - 0x50; | |
831 *type = LOCATION_register; | |
832 break; | |
833 case DW_OP_fbreg: | |
834 { | |
835 int bytes; | |
836 s32 off = elfReadSignedLEB128(loc->data+1, &bytes); | |
837 location = framebase + off; | |
838 *type = LOCATION_memory; | |
839 break; | |
840 } | |
841 default: | |
842 fprintf(stderr, "Unknown location %02x\n", *loc->data); | |
843 break; | |
844 } | |
845 } | |
846 return location; | |
847 } | |
848 | |
849 u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type) | |
850 { | |
851 return elfDecodeLocation(f, o, type, 0); | |
852 } | |
853 | |
854 // reading function | |
855 | |
856 u32 elfRead4Bytes(u8 *data) | |
857 { | |
858 u32 value = *data++; | |
859 value |= (*data++ << 8); | |
860 value |= (*data++ << 16); | |
861 value |= (*data << 24); | |
862 return value; | |
863 } | |
864 | |
865 u16 elfRead2Bytes(u8 *data) | |
866 { | |
867 u16 value = *data++; | |
868 value |= (*data << 8); | |
869 return value; | |
870 } | |
871 | |
872 char *elfReadString(u8 *data, int *bytesRead) | |
873 { | |
874 if (*data == 0) | |
875 { | |
876 *bytesRead = 1; | |
877 return NULL; | |
878 } | |
879 *bytesRead = strlen((char *)data) + 1; | |
880 return (char *)data; | |
881 } | |
882 | |
883 s32 elfReadSignedLEB128(u8 *data, int *bytesRead) | |
884 { | |
885 s32 result = 0; | |
886 int shift = 0; | |
887 int count = 0; | |
888 | |
889 u8 byte; | |
890 do | |
891 { | |
892 byte = *data++; | |
893 count++; | |
894 result |= (byte & 0x7f) << shift; | |
895 shift += 7; | |
896 } | |
897 while (byte & 0x80); | |
898 if ((shift < 32) && (byte & 0x40)) | |
899 result |= -(1 << shift); | |
900 *bytesRead = count; | |
901 return result; | |
902 } | |
903 | |
904 u32 elfReadLEB128(u8 *data, int *bytesRead) | |
905 { | |
906 u32 result = 0; | |
907 int shift = 0; | |
908 int count = 0; | |
909 u8 byte; | |
910 do | |
911 { | |
912 byte = *data++; | |
913 count++; | |
914 result |= (byte & 0x7f) << shift; | |
915 shift += 7; | |
916 } | |
917 while (byte & 0x80); | |
918 *bytesRead = count; | |
919 return result; | |
920 } | |
921 | |
922 u8 *elfReadSection(u8 *data, ELFSectionHeader *sh) | |
923 { | |
924 return data + READ32LE(&sh->offset); | |
925 } | |
926 | |
927 ELFSectionHeader *elfGetSectionByName(char *name) | |
928 { | |
929 for (int i = 0; i < elfSectionHeadersCount; i++) | |
930 { | |
931 if (strcmp(name, | |
932 &elfSectionHeadersStringTable[READ32LE(&elfSectionHeaders[i]-> | |
933 name)]) == 0) | |
934 { | |
935 return elfSectionHeaders[i]; | |
936 } | |
937 } | |
938 return NULL; | |
939 } | |
940 | |
941 ELFSectionHeader *elfGetSectionByNumber(int number) | |
942 { | |
943 if (number < elfSectionHeadersCount) | |
944 { | |
945 return elfSectionHeaders[number]; | |
946 } | |
947 return NULL; | |
948 } | |
949 | |
950 CompileUnit *elfGetCompileUnitForData(u8 *data) | |
951 { | |
952 u8 *end = elfCurrentUnit->top + 4 + elfCurrentUnit->length; | |
953 | |
954 if (data >= elfCurrentUnit->top && data < end) | |
955 return elfCurrentUnit; | |
956 | |
957 CompileUnit *unit = elfCompileUnits; | |
958 | |
959 while (unit) | |
960 { | |
961 end = unit->top + 4 + unit->length; | |
962 | |
963 if (data >= unit->top && data < end) | |
964 return unit; | |
965 | |
966 unit = unit->next; | |
967 } | |
968 | |
969 printf("Error: cannot find reference to compile unit at offset %08x\n", | |
970 (int)(data - elfDebugInfo->infodata)); | |
971 exit(-1); | |
972 } | |
973 | |
974 u8 *elfReadAttribute(u8 *data, ELFAttr *attr) | |
975 { | |
976 int bytes; | |
977 int form = attr->form; | |
978 start: | |
979 switch (form) | |
980 { | |
981 case DW_FORM_addr: | |
982 attr->value = elfRead4Bytes(data); | |
983 data += 4; | |
984 break; | |
985 case DW_FORM_data2: | |
986 attr->value = elfRead2Bytes(data); | |
987 data += 2; | |
988 break; | |
989 case DW_FORM_data4: | |
990 attr->value = elfRead4Bytes(data); | |
991 data += 4; | |
992 break; | |
993 case DW_FORM_string: | |
994 attr->string = (char *)data; | |
995 data += strlen(attr->string)+1; | |
996 break; | |
997 case DW_FORM_strp: | |
998 attr->string = elfDebugStrings + elfRead4Bytes(data); | |
999 data += 4; | |
1000 break; | |
1001 case DW_FORM_block: | |
1002 attr->block = (ELFBlock *)malloc(sizeof(ELFBlock)); | |
1003 attr->block->length = elfReadLEB128(data, &bytes); | |
1004 data += bytes; | |
1005 attr->block->data = data; | |
1006 data += attr->block->length; | |
1007 break; | |
1008 case DW_FORM_block1: | |
1009 attr->block = (ELFBlock *)malloc(sizeof(ELFBlock)); | |
1010 attr->block->length = *data++; | |
1011 attr->block->data = data; | |
1012 data += attr->block->length; | |
1013 break; | |
1014 case DW_FORM_data1: | |
1015 attr->value = *data++; | |
1016 break; | |
1017 case DW_FORM_flag: | |
1018 attr->flag = (*data++) ? true : false; | |
1019 break; | |
1020 case DW_FORM_sdata: | |
1021 attr->value = elfReadSignedLEB128(data, &bytes); | |
1022 data += bytes; | |
1023 break; | |
1024 case DW_FORM_udata: | |
1025 attr->value = elfReadLEB128(data, &bytes); | |
1026 data += bytes; | |
1027 break; | |
1028 case DW_FORM_ref_addr: | |
1029 attr->value = (elfDebugInfo->infodata + elfRead4Bytes(data)) - | |
1030 elfGetCompileUnitForData(data)->top; | |
1031 data += 4; | |
1032 break; | |
1033 case DW_FORM_ref4: | |
1034 attr->value = elfRead4Bytes(data); | |
1035 data += 4; | |
1036 break; | |
1037 case DW_FORM_ref_udata: | |
1038 attr->value = (elfDebugInfo->infodata + | |
1039 (elfGetCompileUnitForData(data)->top - | |
1040 elfDebugInfo->infodata) + | |
1041 elfReadLEB128(data, &bytes)) - | |
1042 elfCurrentUnit->top; | |
1043 data += bytes; | |
1044 break; | |
1045 case DW_FORM_indirect: | |
1046 form = elfReadLEB128(data, &bytes); | |
1047 data += bytes; | |
1048 goto start; | |
1049 default: | |
1050 fprintf(stderr, "Unsupported FORM %02x\n", form); | |
1051 exit(-1); | |
1052 } | |
1053 return data; | |
1054 } | |
1055 | |
1056 ELFAbbrev *elfGetAbbrev(ELFAbbrev **table, u32 number) | |
1057 { | |
1058 int hash = number % 121; | |
1059 | |
1060 ELFAbbrev *abbrev = table[hash]; | |
1061 | |
1062 while (abbrev) | |
1063 { | |
1064 if (abbrev->number == number) | |
1065 return abbrev; | |
1066 abbrev = abbrev->next; | |
1067 } | |
1068 return NULL; | |
1069 } | |
1070 | |
1071 ELFAbbrev * *elfReadAbbrevs(u8 *data, u32 offset) | |
1072 { | |
1073 data += offset; | |
1074 ELFAbbrev **abbrevs = (ELFAbbrev * *)calloc(sizeof(ELFAbbrev *)*121, 1); | |
1075 int bytes = 0; | |
1076 u32 number = elfReadLEB128(data, &bytes); | |
1077 data += bytes; | |
1078 while (number) | |
1079 { | |
1080 ELFAbbrev *abbrev = (ELFAbbrev *)calloc(sizeof(ELFAbbrev), 1); | |
1081 | |
1082 // read tag information | |
1083 abbrev->number = number; | |
1084 abbrev->tag = elfReadLEB128(data, &bytes); | |
1085 data += bytes; | |
1086 abbrev->hasChildren = *data++ ? true : false; | |
1087 | |
1088 // read attributes | |
1089 int name = elfReadLEB128(data, &bytes); | |
1090 data += bytes; | |
1091 int form = elfReadLEB128(data, &bytes); | |
1092 data += bytes; | |
1093 | |
1094 while (name) | |
1095 { | |
1096 if ((abbrev->numAttrs % 4) == 0) | |
1097 { | |
1098 abbrev->attrs = (ELFAttr *)realloc(abbrev->attrs, | |
1099 (abbrev->numAttrs + 4) * | |
1100 sizeof(ELFAttr)); | |
1101 } | |
1102 abbrev->attrs[abbrev->numAttrs].name = name; | |
1103 abbrev->attrs[abbrev->numAttrs++].form = form; | |
1104 | |
1105 name = elfReadLEB128(data, &bytes); | |
1106 data += bytes; | |
1107 form = elfReadLEB128(data, &bytes); | |
1108 data += bytes; | |
1109 } | |
1110 | |
1111 int hash = number % 121; | |
1112 abbrev->next = abbrevs[hash]; | |
1113 abbrevs[hash] = abbrev; | |
1114 | |
1115 number = elfReadLEB128(data, &bytes); | |
1116 data += bytes; | |
1117 | |
1118 if (elfGetAbbrev(abbrevs, number) != NULL) | |
1119 break; | |
1120 } | |
1121 | |
1122 return abbrevs; | |
1123 } | |
1124 | |
1125 void elfParseCFA(u8 *top) | |
1126 { | |
1127 ELFSectionHeader *h = elfGetSectionByName(".debug_frame"); | |
1128 | |
1129 if (h == NULL) | |
1130 { | |
1131 return; | |
1132 } | |
1133 | |
1134 u8 *data = elfReadSection(top, h); | |
1135 | |
1136 u8 *topOffset = data; | |
1137 | |
1138 u8 *end = data + READ32LE(&h->size); | |
1139 | |
1140 ELFcie *cies = NULL; | |
1141 | |
1142 while (data < end) | |
1143 { | |
1144 u32 offset = data - topOffset; | |
1145 u32 len = elfRead4Bytes(data); | |
1146 data += 4; | |
1147 | |
1148 u8 *dataEnd = data + len; | |
1149 | |
1150 u32 id = elfRead4Bytes(data); | |
1151 data += 4; | |
1152 | |
1153 if (id == 0xffffffff) | |
1154 { | |
1155 // skip version | |
1156 *data++; | |
1157 | |
1158 ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie)); | |
1159 | |
1160 cie->next = cies; | |
1161 cies = cie; | |
1162 | |
1163 cie->offset = offset; | |
1164 | |
1165 cie->augmentation = data; | |
1166 while (*data) | |
1167 data++; | |
1168 data++; | |
1169 | |
1170 if (*cie->augmentation) | |
1171 { | |
1172 fprintf(stderr, "Error: augmentation not supported\n"); | |
1173 exit(-1); | |
1174 } | |
1175 | |
1176 int bytes; | |
1177 cie->codeAlign = elfReadLEB128(data, &bytes); | |
1178 data += bytes; | |
1179 | |
1180 cie->dataAlign = elfReadSignedLEB128(data, &bytes); | |
1181 data += bytes; | |
1182 | |
1183 cie->returnAddress = *data++; | |
1184 | |
1185 cie->data = data; | |
1186 cie->dataLen = dataEnd - data; | |
1187 } | |
1188 else | |
1189 { | |
1190 ELFfde *fde = (ELFfde *)calloc(1, sizeof(ELFfde)); | |
1191 | |
1192 ELFcie *cie = cies; | |
1193 | |
1194 while (cie != NULL) | |
1195 { | |
1196 if (cie->offset == id) | |
1197 break; | |
1198 cie = cie->next; | |
1199 } | |
1200 | |
1201 if (!cie) | |
1202 { | |
1203 fprintf(stderr, "Cannot find CIE %08x\n", id); | |
1204 exit(-1); | |
1205 } | |
1206 | |
1207 fde->cie = cie; | |
1208 | |
1209 fde->address = elfRead4Bytes(data); | |
1210 data += 4; | |
1211 | |
1212 fde->end = fde->address + elfRead4Bytes(data); | |
1213 data += 4; | |
1214 | |
1215 fde->data = data; | |
1216 fde->dataLen = dataEnd - data; | |
1217 | |
1218 if ((elfFdeCount %10) == 0) | |
1219 { | |
1220 elfFdes = (ELFfde * *)realloc(elfFdes, (elfFdeCount+10) * | |
1221 sizeof(ELFfde *)); | |
1222 } | |
1223 elfFdes[elfFdeCount++] = fde; | |
1224 } | |
1225 data = dataEnd; | |
1226 } | |
1227 | |
1228 elfCies = cies; | |
1229 } | |
1230 | |
1231 void elfAddLine(LineInfo *l, u32 a, int file, int line, int *max) | |
1232 { | |
1233 if (l->number == *max) | |
1234 { | |
1235 *max += 1000; | |
1236 l->lines = (LineInfoItem *)realloc(l->lines, *max*sizeof(LineInfoItem)); | |
1237 } | |
1238 LineInfoItem *li = &l->lines[l->number]; | |
1239 li->file = l->files[file-1]; | |
1240 li->address = a; | |
1241 li->line = line; | |
1242 l->number++; | |
1243 } | |
1244 | |
1245 void elfParseLineInfo(CompileUnit *unit, u8 *top) | |
1246 { | |
1247 ELFSectionHeader *h = elfGetSectionByName(".debug_line"); | |
1248 if (h == NULL) | |
1249 { | |
1250 fprintf(stderr, "No line information found\n"); | |
1251 return; | |
1252 } | |
1253 LineInfo *l = unit->lineInfoTable = (LineInfo *)calloc(1, sizeof(LineInfo)); | |
1254 l->number = 0; | |
1255 int max = 1000; | |
1256 l->lines = (LineInfoItem *)malloc(1000*sizeof(LineInfoItem)); | |
1257 | |
1258 u8 *data = elfReadSection(top, h); | |
1259 data += unit->lineInfo; | |
1260 u32 totalLen = elfRead4Bytes(data); | |
1261 data += 4; | |
1262 u8 *end = data + totalLen; | |
1263 // u16 version = elfRead2Bytes(data); | |
1264 data += 2; | |
1265 // u32 offset = elfRead4Bytes(data); | |
1266 data += 4; | |
1267 int minInstrSize = *data++; | |
1268 int defaultIsStmt = *data++; | |
1269 int lineBase = (s8)*data++; | |
1270 int lineRange = *data++; | |
1271 int opcodeBase = *data++; | |
1272 u8 *stdOpLen = (u8 *)malloc(opcodeBase * sizeof(u8)); | |
1273 stdOpLen[0] = 1; | |
1274 int i; | |
1275 for (i = 1; i < opcodeBase; i++) | |
1276 stdOpLen[i] = *data++; | |
1277 | |
1278 free(stdOpLen); // todo | |
1279 int bytes = 0; | |
1280 | |
1281 char *s; | |
1282 while ((s = elfReadString(data, &bytes)) != NULL) | |
1283 { | |
1284 data += bytes; | |
1285 // fprintf(stderr, "Directory is %s\n", s); | |
1286 } | |
1287 data += bytes; | |
1288 int count = 4; | |
1289 int index = 0; | |
1290 l->files = (char * *)malloc(sizeof(char *)*count); | |
1291 | |
1292 while ((s = elfReadString(data, &bytes)) != NULL) | |
1293 { | |
1294 l->files[index++] = s; | |
1295 | |
1296 data += bytes; | |
1297 // directory | |
1298 elfReadLEB128(data, &bytes); | |
1299 data += bytes; | |
1300 // time | |
1301 elfReadLEB128(data, &bytes); | |
1302 data += bytes; | |
1303 // size | |
1304 elfReadLEB128(data, &bytes); | |
1305 data += bytes; | |
1306 // fprintf(stderr, "File is %s\n", s); | |
1307 if (index == count) | |
1308 { | |
1309 count += 4; | |
1310 l->files = (char * *)realloc(l->files, sizeof(char *)*count); | |
1311 } | |
1312 } | |
1313 l->fileCount = index; | |
1314 data += bytes; | |
1315 | |
1316 while (data < end) | |
1317 { | |
1318 u32 address = 0; | |
1319 int file = 1; | |
1320 int line = 1; | |
1321 int col = 0; | |
1322 int isStmt = defaultIsStmt; | |
1323 int basicBlock = 0; | |
1324 int endSeq = 0; | |
1325 | |
1326 while (!endSeq) | |
1327 { | |
1328 int op = *data++; | |
1329 switch (op) | |
1330 { | |
1331 case DW_LNS_extended_op: | |
1332 { | |
1333 data++; | |
1334 op = *data++; | |
1335 switch (op) | |
1336 { | |
1337 case DW_LNE_end_sequence: | |
1338 endSeq = 1; | |
1339 break; | |
1340 case DW_LNE_set_address: | |
1341 address = elfRead4Bytes(data); | |
1342 data += 4; | |
1343 break; | |
1344 default: | |
1345 fprintf(stderr, "Unknown extended LINE opcode %02x\n", op); | |
1346 exit(-1); | |
1347 } | |
1348 break; | |
1349 } | |
1350 case DW_LNS_copy: | |
1351 // fprintf(stderr, "Address %08x line %d (%d)\n", address, line, file); | |
1352 elfAddLine(l, address, file, line, &max); | |
1353 basicBlock = 0; | |
1354 break; | |
1355 case DW_LNS_advance_pc: | |
1356 address += minInstrSize * elfReadLEB128(data, &bytes); | |
1357 data += bytes; | |
1358 break; | |
1359 case DW_LNS_advance_line: | |
1360 line += elfReadSignedLEB128(data, &bytes); | |
1361 data += bytes; | |
1362 break; | |
1363 case DW_LNS_set_file: | |
1364 file = elfReadLEB128(data, &bytes); | |
1365 data += bytes; | |
1366 break; | |
1367 case DW_LNS_set_column: | |
1368 col = elfReadLEB128(data, &bytes); | |
1369 data += bytes; | |
1370 break; | |
1371 case DW_LNS_negate_stmt: | |
1372 isStmt = !isStmt; | |
1373 break; | |
1374 case DW_LNS_set_basic_block: | |
1375 basicBlock = 1; | |
1376 break; | |
1377 case DW_LNS_const_add_pc: | |
1378 address += (minInstrSize *((255 - opcodeBase)/lineRange)); | |
1379 break; | |
1380 case DW_LNS_fixed_advance_pc: | |
1381 address += elfRead2Bytes(data); | |
1382 data += 2; | |
1383 break; | |
1384 default: | |
1385 op = op - opcodeBase; | |
1386 address += (op / lineRange) * minInstrSize; | |
1387 line += lineBase + (op % lineRange); | |
1388 elfAddLine(l, address, file, line, &max); | |
1389 // fprintf(stderr, "Address %08x line %d (%d)\n", address, line,file); | |
1390 basicBlock = 1; | |
1391 break; | |
1392 } | |
1393 } | |
1394 } | |
1395 l->lines = (LineInfoItem *)realloc(l->lines, l->number*sizeof(LineInfoItem)); | |
1396 } | |
1397 | |
1398 u8 *elfSkipData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs) | |
1399 { | |
1400 int i; | |
1401 int bytes; | |
1402 | |
1403 for (i = 0; i < abbrev->numAttrs; i++) | |
1404 { | |
1405 data = elfReadAttribute(data, &abbrev->attrs[i]); | |
1406 if (abbrev->attrs[i].form == DW_FORM_block1) | |
1407 free(abbrev->attrs[i].block); | |
1408 } | |
1409 | |
1410 if (abbrev->hasChildren) | |
1411 { | |
1412 int nesting = 1; | |
1413 while (nesting) | |
1414 { | |
1415 u32 abbrevNum = elfReadLEB128(data, &bytes); | |
1416 data += bytes; | |
1417 | |
1418 if (!abbrevNum) | |
1419 { | |
1420 nesting--; | |
1421 continue; | |
1422 } | |
1423 | |
1424 abbrev = elfGetAbbrev(abbrevs, abbrevNum); | |
1425 | |
1426 for (i = 0; i < abbrev->numAttrs; i++) | |
1427 { | |
1428 data = elfReadAttribute(data, &abbrev->attrs[i]); | |
1429 if (abbrev->attrs[i].form == DW_FORM_block1) | |
1430 free(abbrev->attrs[i].block); | |
1431 } | |
1432 | |
1433 if (abbrev->hasChildren) | |
1434 { | |
1435 nesting++; | |
1436 } | |
1437 } | |
1438 } | |
1439 return data; | |
1440 } | |
1441 | |
1442 Type *elfParseType(CompileUnit *unit, u32); | |
1443 u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit, | |
1444 Object **object); | |
1445 u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit, | |
1446 Function **function); | |
1447 void elfCleanUp(Function *); | |
1448 | |
1449 void elfAddType(Type *type, CompileUnit *unit, u32 offset) | |
1450 { | |
1451 if (type->next == NULL) | |
1452 { | |
1453 if (unit->types != type && type->offset == 0) | |
1454 { | |
1455 type->offset = offset; | |
1456 type->next = unit->types; | |
1457 unit->types = type; | |
1458 } | |
1459 } | |
1460 } | |
1461 | |
1462 void elfParseType(u8 *data, u32 offset, ELFAbbrev *abbrev, CompileUnit *unit, | |
1463 Type **type) | |
1464 { | |
1465 switch (abbrev->tag) | |
1466 { | |
1467 case DW_TAG_typedef: | |
1468 { | |
1469 u32 typeref = 0; | |
1470 char *name = NULL; | |
1471 for (int i = 0; i < abbrev->numAttrs; i++) | |
1472 { | |
1473 ELFAttr *attr = &abbrev->attrs[i]; | |
1474 data = elfReadAttribute(data, attr); | |
1475 switch (attr->name) | |
1476 { | |
1477 case DW_AT_name: | |
1478 name = attr->string; | |
1479 break; | |
1480 case DW_AT_type: | |
1481 typeref = attr->value; | |
1482 break; | |
1483 case DW_AT_decl_file: | |
1484 case DW_AT_decl_line: | |
1485 break; | |
1486 default: | |
1487 fprintf(stderr, "Unknown attribute for typedef %02x\n", attr->name); | |
1488 break; | |
1489 } | |
1490 } | |
1491 if (abbrev->hasChildren) | |
1492 fprintf(stderr, "Unexpected children for typedef\n"); | |
1493 *type = elfParseType(unit, typeref); | |
1494 if (name) | |
1495 (*type)->name = name; | |
1496 return; | |
1497 break; | |
1498 } | |
1499 case DW_TAG_union_type: | |
1500 case DW_TAG_structure_type: | |
1501 { | |
1502 Type *t = (Type *)calloc(sizeof(Type), 1); | |
1503 if (abbrev->tag == DW_TAG_structure_type) | |
1504 t->type = TYPE_struct; | |
1505 else | |
1506 t->type = TYPE_union; | |
1507 | |
1508 Struct *s = (Struct *)calloc(sizeof(Struct), 1); | |
1509 t->structure = s; | |
1510 elfAddType(t, unit, offset); | |
1511 | |
1512 for (int i = 0; i < abbrev->numAttrs; i++) | |
1513 { | |
1514 ELFAttr *attr = &abbrev->attrs[i]; | |
1515 data = elfReadAttribute(data, attr); | |
1516 switch (attr->name) | |
1517 { | |
1518 case DW_AT_name: | |
1519 t->name = attr->string; | |
1520 break; | |
1521 case DW_AT_byte_size: | |
1522 t->size = attr->value; | |
1523 break; | |
1524 case DW_AT_decl_file: | |
1525 case DW_AT_decl_line: | |
1526 case DW_AT_sibling: | |
1527 case DW_AT_containing_type: // todo? | |
1528 case DW_AT_declaration: | |
1529 case DW_AT_specification: // TODO: | |
1530 break; | |
1531 default: | |
1532 fprintf(stderr, "Unknown attribute for struct %02x\n", attr->name); | |
1533 break; | |
1534 } | |
1535 } | |
1536 if (abbrev->hasChildren) | |
1537 { | |
1538 int bytes; | |
1539 u32 num = elfReadLEB128(data, &bytes); | |
1540 data += bytes; | |
1541 int index = 0; | |
1542 while (num) | |
1543 { | |
1544 ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num); | |
1545 | |
1546 switch (abbr->tag) | |
1547 { | |
1548 case DW_TAG_member: | |
1549 { | |
1550 if ((index % 4) == 0) | |
1551 s->members = (Member *)realloc(s->members, | |
1552 sizeof(Member)*(index+4)); | |
1553 Member *m = &s->members[index]; | |
1554 m->location = NULL; | |
1555 m->bitOffset = 0; | |
1556 m->bitSize = 0; | |
1557 m->byteSize = 0; | |
1558 for (int i = 0; i < abbr->numAttrs; i++) | |
1559 { | |
1560 ELFAttr *attr = &abbr->attrs[i]; | |
1561 data = elfReadAttribute(data, attr); | |
1562 switch (attr->name) | |
1563 { | |
1564 case DW_AT_name: | |
1565 m->name = attr->string; | |
1566 break; | |
1567 case DW_AT_type: | |
1568 m->type = elfParseType(unit, attr->value); | |
1569 break; | |
1570 case DW_AT_data_member_location: | |
1571 m->location = attr->block; | |
1572 break; | |
1573 case DW_AT_byte_size: | |
1574 m->byteSize = attr->value; | |
1575 break; | |
1576 case DW_AT_bit_offset: | |
1577 m->bitOffset = attr->value; | |
1578 break; | |
1579 case DW_AT_bit_size: | |
1580 m->bitSize = attr->value; | |
1581 break; | |
1582 case DW_AT_decl_file: | |
1583 case DW_AT_decl_line: | |
1584 case DW_AT_accessibility: | |
1585 case DW_AT_artificial: // todo? | |
1586 break; | |
1587 default: | |
1588 fprintf(stderr, "Unknown member attribute %02x\n", | |
1589 attr->name); | |
1590 } | |
1591 } | |
1592 index++; | |
1593 break; | |
1594 } | |
1595 case DW_TAG_subprogram: | |
1596 { | |
1597 Function *fnc = NULL; | |
1598 data = elfParseFunction(data, abbr, unit, &fnc); | |
1599 if (fnc != NULL) | |
1600 { | |
1601 if (unit->lastFunction) | |
1602 unit->lastFunction->next = fnc; | |
1603 else | |
1604 unit->functions = fnc; | |
1605 unit->lastFunction = fnc; | |
1606 } | |
1607 break; | |
1608 } | |
1609 case DW_TAG_inheritance: | |
1610 // TODO: add support | |
1611 data = elfSkipData(data, abbr, unit->abbrevs); | |
1612 break; | |
1613 CASE_TYPE_TAG: | |
1614 // skip types... parsed only when used | |
1615 data = elfSkipData(data, abbr, unit->abbrevs); | |
1616 break; | |
1617 case DW_TAG_variable: | |
1618 data = elfSkipData(data, abbr, unit->abbrevs); | |
1619 break; | |
1620 default: | |
1621 fprintf(stderr, "Unknown struct tag %02x %s\n", abbr->tag, t->name); | |
1622 data = elfSkipData(data, abbr, unit->abbrevs); | |
1623 break; | |
1624 } | |
1625 num = elfReadLEB128(data, &bytes); | |
1626 data += bytes; | |
1627 } | |
1628 s->memberCount = index; | |
1629 } | |
1630 *type = t; | |
1631 return; | |
1632 break; | |
1633 } | |
1634 case DW_TAG_base_type: | |
1635 { | |
1636 Type *t = (Type *)calloc(sizeof(Type), 1); | |
1637 | |
1638 t->type = TYPE_base; | |
1639 elfAddType(t, unit, offset); | |
1640 for (int i = 0; i < abbrev->numAttrs; i++) | |
1641 { | |
1642 ELFAttr *attr = &abbrev->attrs[i]; | |
1643 data = elfReadAttribute(data, attr); | |
1644 switch (attr->name) | |
1645 { | |
1646 case DW_AT_name: | |
1647 t->name = attr->string; | |
1648 break; | |
1649 case DW_AT_encoding: | |
1650 t->encoding = attr->value; | |
1651 break; | |
1652 case DW_AT_byte_size: | |
1653 t->size = attr->value; | |
1654 break; | |
1655 case DW_AT_bit_size: | |
1656 t->bitSize = attr->value; | |
1657 break; | |
1658 default: | |
1659 fprintf(stderr, "Unknown attribute for base type %02x\n", | |
1660 attr->name); | |
1661 break; | |
1662 } | |
1663 } | |
1664 if (abbrev->hasChildren) | |
1665 fprintf(stderr, "Unexpected children for base type\n"); | |
1666 *type = t; | |
1667 return; | |
1668 break; | |
1669 } | |
1670 case DW_TAG_pointer_type: | |
1671 { | |
1672 Type *t = (Type *)calloc(sizeof(Type), 1); | |
1673 | |
1674 t->type = TYPE_pointer; | |
1675 | |
1676 elfAddType(t, unit, offset); | |
1677 | |
1678 for (int i = 0; i < abbrev->numAttrs; i++) | |
1679 { | |
1680 ELFAttr *attr = &abbrev->attrs[i]; | |
1681 data = elfReadAttribute(data, attr); | |
1682 switch (attr->name) | |
1683 { | |
1684 case DW_AT_type: | |
1685 t->pointer = elfParseType(unit, attr->value); | |
1686 break; | |
1687 case DW_AT_byte_size: | |
1688 t->size = attr->value; | |
1689 break; | |
1690 default: | |
1691 fprintf(stderr, "Unknown pointer type attribute %02x\n", attr->name); | |
1692 break; | |
1693 } | |
1694 } | |
1695 if (abbrev->hasChildren) | |
1696 fprintf(stderr, "Unexpected children for pointer type\n"); | |
1697 *type = t; | |
1698 return; | |
1699 break; | |
1700 } | |
1701 case DW_TAG_reference_type: | |
1702 { | |
1703 Type *t = (Type *)calloc(sizeof(Type), 1); | |
1704 | |
1705 t->type = TYPE_reference; | |
1706 | |
1707 elfAddType(t, unit, offset); | |
1708 | |
1709 for (int i = 0; i < abbrev->numAttrs; i++) | |
1710 { | |
1711 ELFAttr *attr = &abbrev->attrs[i]; | |
1712 data = elfReadAttribute(data, attr); | |
1713 switch (attr->name) | |
1714 { | |
1715 case DW_AT_type: | |
1716 t->pointer = elfParseType(unit, attr->value); | |
1717 break; | |
1718 case DW_AT_byte_size: | |
1719 t->size = attr->value; | |
1720 break; | |
1721 default: | |
1722 fprintf(stderr, "Unknown ref type attribute %02x\n", attr->name); | |
1723 break; | |
1724 } | |
1725 } | |
1726 if (abbrev->hasChildren) | |
1727 fprintf(stderr, "Unexpected children for ref type\n"); | |
1728 *type = t; | |
1729 return; | |
1730 break; | |
1731 } | |
1732 case DW_TAG_volatile_type: | |
1733 { | |
1734 u32 typeref = 0; | |
1735 | |
1736 for (int i = 0; i < abbrev->numAttrs; i++) | |
1737 { | |
1738 ELFAttr *attr = &abbrev->attrs[i]; | |
1739 data = elfReadAttribute(data, attr); | |
1740 switch (attr->name) | |
1741 { | |
1742 case DW_AT_type: | |
1743 typeref = attr->value; | |
1744 break; | |
1745 default: | |
1746 fprintf(stderr, "Unknown volatile attribute for type %02x\n", | |
1747 attr->name); | |
1748 break; | |
1749 } | |
1750 } | |
1751 if (abbrev->hasChildren) | |
1752 fprintf(stderr, "Unexpected children for volatile type\n"); | |
1753 *type = elfParseType(unit, typeref); | |
1754 return; | |
1755 break; | |
1756 } | |
1757 case DW_TAG_const_type: | |
1758 { | |
1759 u32 typeref = 0; | |
1760 | |
1761 for (int i = 0; i < abbrev->numAttrs; i++) | |
1762 { | |
1763 ELFAttr *attr = &abbrev->attrs[i]; | |
1764 data = elfReadAttribute(data, attr); | |
1765 switch (attr->name) | |
1766 { | |
1767 case DW_AT_type: | |
1768 typeref = attr->value; | |
1769 break; | |
1770 default: | |
1771 fprintf(stderr, "Unknown const attribute for type %02x\n", | |
1772 attr->name); | |
1773 break; | |
1774 } | |
1775 } | |
1776 if (abbrev->hasChildren) | |
1777 fprintf(stderr, "Unexpected children for const type\n"); | |
1778 *type = elfParseType(unit, typeref); | |
1779 return; | |
1780 break; | |
1781 } | |
1782 case DW_TAG_enumeration_type: | |
1783 { | |
1784 Type *t = (Type *)calloc(sizeof(Type), 1); | |
1785 t->type = TYPE_enum; | |
1786 Enum *e = (Enum *)calloc(sizeof(Enum), 1); | |
1787 t->enumeration = e; | |
1788 elfAddType(t, unit, offset); | |
1789 int count = 0; | |
1790 for (int i = 0; i < abbrev->numAttrs; i++) | |
1791 { | |
1792 ELFAttr *attr = &abbrev->attrs[i]; | |
1793 data = elfReadAttribute(data, attr); | |
1794 switch (attr->name) | |
1795 { | |
1796 case DW_AT_name: | |
1797 t->name = attr->string; | |
1798 break; | |
1799 case DW_AT_byte_size: | |
1800 t->size = attr->value; | |
1801 break; | |
1802 case DW_AT_sibling: | |
1803 case DW_AT_decl_file: | |
1804 case DW_AT_decl_line: | |
1805 break; | |
1806 default: | |
1807 fprintf(stderr, "Unknown enum attribute %02x\n", attr->name); | |
1808 } | |
1809 } | |
1810 if (abbrev->hasChildren) | |
1811 { | |
1812 int bytes; | |
1813 u32 num = elfReadLEB128(data, &bytes); | |
1814 data += bytes; | |
1815 while (num) | |
1816 { | |
1817 ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num); | |
1818 | |
1819 switch (abbr->tag) | |
1820 { | |
1821 case DW_TAG_enumerator: | |
1822 { | |
1823 count++; | |
1824 e->members = (EnumMember *)realloc(e->members, | |
1825 count*sizeof(EnumMember)); | |
1826 EnumMember *m = &e->members[count-1]; | |
1827 for (int i = 0; i < abbr->numAttrs; i++) | |
1828 { | |
1829 ELFAttr *attr = &abbr->attrs[i]; | |
1830 data = elfReadAttribute(data, attr); | |
1831 switch (attr->name) | |
1832 { | |
1833 case DW_AT_name: | |
1834 m->name = attr->string; | |
1835 break; | |
1836 case DW_AT_const_value: | |
1837 m->value = attr->value; | |
1838 break; | |
1839 default: | |
1840 fprintf(stderr, "Unknown sub param attribute %02x\n", | |
1841 attr->name); | |
1842 } | |
1843 } | |
1844 break; | |
1845 } | |
1846 default: | |
1847 fprintf(stderr, "Unknown enum tag %02x\n", abbr->tag); | |
1848 data = elfSkipData(data, abbr, unit->abbrevs); | |
1849 break; | |
1850 } | |
1851 num = elfReadLEB128(data, &bytes); | |
1852 data += bytes; | |
1853 } | |
1854 } | |
1855 e->count = count; | |
1856 *type = t; | |
1857 return; | |
1858 break; | |
1859 } | |
1860 case DW_TAG_subroutine_type: | |
1861 { | |
1862 Type *t = (Type *)calloc(sizeof(Type), 1); | |
1863 t->type = TYPE_function; | |
1864 FunctionType *f = (FunctionType *)calloc(sizeof(FunctionType), 1); | |
1865 t->function = f; | |
1866 elfAddType(t, unit, offset); | |
1867 for (int i = 0; i < abbrev->numAttrs; i++) | |
1868 { | |
1869 ELFAttr *attr = &abbrev->attrs[i]; | |
1870 data = elfReadAttribute(data, attr); | |
1871 switch (attr->name) | |
1872 { | |
1873 case DW_AT_prototyped: | |
1874 case DW_AT_sibling: | |
1875 break; | |
1876 case DW_AT_type: | |
1877 f->returnType = elfParseType(unit, attr->value); | |
1878 break; | |
1879 default: | |
1880 fprintf(stderr, "Unknown subroutine attribute %02x\n", attr->name); | |
1881 } | |
1882 } | |
1883 if (abbrev->hasChildren) | |
1884 { | |
1885 int bytes; | |
1886 u32 num = elfReadLEB128(data, &bytes); | |
1887 data += bytes; | |
1888 Object *lastVar = NULL; | |
1889 while (num) | |
1890 { | |
1891 ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num); | |
1892 | |
1893 switch (abbr->tag) | |
1894 { | |
1895 case DW_TAG_formal_parameter: | |
1896 { | |
1897 Object *o; | |
1898 data = elfParseObject(data, abbr, unit, &o); | |
1899 if (f->args) | |
1900 lastVar->next = o; | |
1901 else | |
1902 f->args = o; | |
1903 lastVar = o; | |
1904 break; | |
1905 } | |
1906 case DW_TAG_unspecified_parameters: | |
1907 // no use in the debugger yet | |
1908 data = elfSkipData(data, abbr, unit->abbrevs); | |
1909 break; | |
1910 CASE_TYPE_TAG: | |
1911 // skip types... parsed only when used | |
1912 data = elfSkipData(data, abbr, unit->abbrevs); | |
1913 break; | |
1914 default: | |
1915 fprintf(stderr, "Unknown subroutine tag %02x\n", abbr->tag); | |
1916 data = elfSkipData(data, abbr, unit->abbrevs); | |
1917 break; | |
1918 } | |
1919 num = elfReadLEB128(data, &bytes); | |
1920 data += bytes; | |
1921 } | |
1922 } | |
1923 *type = t; | |
1924 return; | |
1925 break; | |
1926 } | |
1927 case DW_TAG_array_type: | |
1928 { | |
1929 u32 typeref = 0; | |
1930 int i; | |
1931 Array *array = (Array *)calloc(sizeof(Array), 1); | |
1932 Type * t = (Type *)calloc(sizeof(Type), 1); | |
1933 t->type = TYPE_array; | |
1934 elfAddType(t, unit, offset); | |
1935 | |
1936 for (i = 0; i < abbrev->numAttrs; i++) | |
1937 { | |
1938 ELFAttr *attr = &abbrev->attrs[i]; | |
1939 data = elfReadAttribute(data, attr); | |
1940 switch (attr->name) | |
1941 { | |
1942 case DW_AT_sibling: | |
1943 break; | |
1944 case DW_AT_type: | |
1945 typeref = attr->value; | |
1946 array->type = elfParseType(unit, typeref); | |
1947 break; | |
1948 default: | |
1949 fprintf(stderr, "Unknown array attribute %02x\n", attr->name); | |
1950 } | |
1951 } | |
1952 if (abbrev->hasChildren) | |
1953 { | |
1954 int bytes; | |
1955 u32 num = elfReadLEB128(data, &bytes); | |
1956 data += bytes; | |
1957 int index = 0; | |
1958 int maxBounds = 0; | |
1959 while (num) | |
1960 { | |
1961 ELFAbbrev *abbr = elfGetAbbrev(unit->abbrevs, num); | |
1962 | |
1963 switch (abbr->tag) | |
1964 { | |
1965 case DW_TAG_subrange_type: | |
1966 { | |
1967 if (maxBounds == index) | |
1968 { | |
1969 maxBounds += 4; | |
1970 array->bounds = (int *)realloc(array->bounds, | |
1971 sizeof(int)*maxBounds); | |
1972 } | |
1973 for (int i = 0; i < abbr->numAttrs; i++) | |
1974 { | |
1975 ELFAttr *attr = &abbr->attrs[i]; | |
1976 data = elfReadAttribute(data, attr); | |
1977 switch (attr->name) | |
1978 { | |
1979 case DW_AT_upper_bound: | |
1980 array->bounds[index] = attr->value+1; | |
1981 break; | |
1982 case DW_AT_type: // ignore | |
1983 break; | |
1984 default: | |
1985 fprintf(stderr, "Unknown subrange attribute %02x\n", | |
1986 attr->name); | |
1987 } | |
1988 } | |
1989 index++; | |
1990 break; | |
1991 } | |
1992 default: | |
1993 fprintf(stderr, "Unknown array tag %02x\n", abbr->tag); | |
1994 data = elfSkipData(data, abbr, unit->abbrevs); | |
1995 break; | |
1996 } | |
1997 num = elfReadLEB128(data, &bytes); | |
1998 data += bytes; | |
1999 } | |
2000 array->maxBounds = index; | |
2001 } | |
2002 t->size = array->type->size; | |
2003 for (i = 0; i < array->maxBounds; i++) | |
2004 t->size *= array->bounds[i]; | |
2005 t->array = array; | |
2006 *type = t; | |
2007 return; | |
2008 break; | |
2009 } | |
2010 default: | |
2011 fprintf(stderr, "Unknown type TAG %02x\n", abbrev->tag); | |
2012 exit(-1); | |
2013 } | |
2014 } | |
2015 | |
2016 Type *elfParseType(CompileUnit *unit, u32 offset) | |
2017 { | |
2018 Type *t = unit->types; | |
2019 | |
2020 while (t) | |
2021 { | |
2022 if (t->offset == offset) | |
2023 return t; | |
2024 t = t->next; | |
2025 } | |
2026 if (offset == 0) | |
2027 { | |
2028 Type *t = (Type *)calloc(sizeof(Type), 1); | |
2029 t->type = TYPE_void; | |
2030 t->offset = 0; | |
2031 elfAddType(t, unit, 0); | |
2032 return t; | |
2033 } | |
2034 u8 *data = unit->top + offset; | |
2035 int bytes; | |
2036 int abbrevNum = elfReadLEB128(data, &bytes); | |
2037 data += bytes; | |
2038 Type *type = NULL; | |
2039 | |
2040 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum); | |
2041 | |
2042 elfParseType(data, offset, abbrev, unit, &type); | |
2043 return type; | |
2044 } | |
2045 | |
2046 void elfGetObjectAttributes(CompileUnit *unit, u32 offset, Object *o) | |
2047 { | |
2048 u8 *data = unit->top + offset; | |
2049 int bytes; | |
2050 u32 abbrevNum = elfReadLEB128(data, &bytes); | |
2051 data += bytes; | |
2052 | |
2053 if (!abbrevNum) | |
2054 { | |
2055 return; | |
2056 } | |
2057 | |
2058 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum); | |
2059 | |
2060 for (int i = 0; i < abbrev->numAttrs; i++) | |
2061 { | |
2062 ELFAttr *attr = &abbrev->attrs[i]; | |
2063 data = elfReadAttribute(data, attr); | |
2064 switch (attr->name) | |
2065 { | |
2066 case DW_AT_location: | |
2067 o->location = attr->block; | |
2068 break; | |
2069 case DW_AT_name: | |
2070 if (o->name == NULL) | |
2071 o->name = attr->string; | |
2072 break; | |
2073 case DW_AT_MIPS_linkage_name: | |
2074 o->name = attr->string; | |
2075 break; | |
2076 case DW_AT_decl_file: | |
2077 o->file = attr->value; | |
2078 break; | |
2079 case DW_AT_decl_line: | |
2080 o->line = attr->value; | |
2081 break; | |
2082 case DW_AT_type: | |
2083 o->type = elfParseType(unit, attr->value); | |
2084 break; | |
2085 case DW_AT_external: | |
2086 o->external = attr->flag; | |
2087 break; | |
2088 case DW_AT_const_value: | |
2089 case DW_AT_abstract_origin: | |
2090 case DW_AT_declaration: | |
2091 case DW_AT_artificial: | |
2092 // todo | |
2093 break; | |
2094 case DW_AT_specification: | |
2095 // TODO: | |
2096 break; | |
2097 default: | |
2098 fprintf(stderr, "Unknown object attribute %02x\n", attr->name); | |
2099 break; | |
2100 } | |
2101 } | |
2102 } | |
2103 | |
2104 u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit, | |
2105 Object **object) | |
2106 { | |
2107 Object *o = (Object *)calloc(sizeof(Object), 1); | |
2108 | |
2109 o->next = NULL; | |
2110 | |
2111 for (int i = 0; i < abbrev->numAttrs; i++) | |
2112 { | |
2113 ELFAttr *attr = &abbrev->attrs[i]; | |
2114 data = elfReadAttribute(data, attr); | |
2115 switch (attr->name) | |
2116 { | |
2117 case DW_AT_location: | |
2118 o->location = attr->block; | |
2119 break; | |
2120 case DW_AT_name: | |
2121 if (o->name == NULL) | |
2122 o->name = attr->string; | |
2123 break; | |
2124 case DW_AT_MIPS_linkage_name: | |
2125 o->name = attr->string; | |
2126 break; | |
2127 case DW_AT_decl_file: | |
2128 o->file = attr->value; | |
2129 break; | |
2130 case DW_AT_decl_line: | |
2131 o->line = attr->value; | |
2132 break; | |
2133 case DW_AT_type: | |
2134 o->type = elfParseType(unit, attr->value); | |
2135 break; | |
2136 case DW_AT_external: | |
2137 o->external = attr->flag; | |
2138 break; | |
2139 case DW_AT_abstract_origin: | |
2140 elfGetObjectAttributes(unit, attr->value, o); | |
2141 break; | |
2142 case DW_AT_const_value: | |
2143 case DW_AT_declaration: | |
2144 case DW_AT_artificial: | |
2145 break; | |
2146 case DW_AT_specification: | |
2147 // TODO: | |
2148 break; | |
2149 default: | |
2150 fprintf(stderr, "Unknown object attribute %02x\n", attr->name); | |
2151 break; | |
2152 } | |
2153 } | |
2154 *object = o; | |
2155 return data; | |
2156 } | |
2157 | |
2158 u8 *elfParseBlock(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit, | |
2159 Function *func, Object **lastVar) | |
2160 { | |
2161 int bytes; | |
2162 u32 start = func->lowPC; | |
2163 u32 end = func->highPC; | |
2164 | |
2165 for (int i = 0; i < abbrev->numAttrs; i++) | |
2166 { | |
2167 ELFAttr *attr = &abbrev->attrs[i]; | |
2168 data = elfReadAttribute(data, attr); | |
2169 switch (attr->name) | |
2170 { | |
2171 case DW_AT_sibling: | |
2172 break; | |
2173 case DW_AT_low_pc: | |
2174 start = attr->value; | |
2175 break; | |
2176 case DW_AT_high_pc: | |
2177 end = attr->value; | |
2178 break; | |
2179 case DW_AT_ranges: // ignore for now | |
2180 break; | |
2181 default: | |
2182 fprintf(stderr, "Unknown block attribute %02x\n", attr->name); | |
2183 break; | |
2184 } | |
2185 } | |
2186 | |
2187 if (abbrev->hasChildren) | |
2188 { | |
2189 int nesting = 1; | |
2190 | |
2191 while (nesting) | |
2192 { | |
2193 u32 abbrevNum = elfReadLEB128(data, &bytes); | |
2194 data += bytes; | |
2195 | |
2196 if (!abbrevNum) | |
2197 { | |
2198 nesting--; | |
2199 continue; | |
2200 } | |
2201 | |
2202 abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum); | |
2203 | |
2204 switch (abbrev->tag) | |
2205 { | |
2206 CASE_TYPE_TAG: // types only parsed when used | |
2207 case DW_TAG_label: // not needed | |
2208 data = elfSkipData(data, abbrev, unit->abbrevs); | |
2209 break; | |
2210 case DW_TAG_lexical_block: | |
2211 data = elfParseBlock(data, abbrev, unit, func, lastVar); | |
2212 break; | |
2213 case DW_TAG_subprogram: | |
2214 { | |
2215 Function *f = NULL; | |
2216 data = elfParseFunction(data, abbrev, unit, &f); | |
2217 if (f != NULL) | |
2218 { | |
2219 if (unit->lastFunction) | |
2220 unit->lastFunction->next = f; | |
2221 else | |
2222 unit->functions = f; | |
2223 unit->lastFunction = f; | |
2224 } | |
2225 break; | |
2226 } | |
2227 case DW_TAG_variable: | |
2228 { | |
2229 Object *o; | |
2230 data = elfParseObject(data, abbrev, unit, &o); | |
2231 if (o->startScope == 0) | |
2232 o->startScope = start; | |
2233 if (o->endScope == 0) | |
2234 o->endScope = 0; | |
2235 if (func->variables) | |
2236 (*lastVar)->next = o; | |
2237 else | |
2238 func->variables = o; | |
2239 *lastVar = o; | |
2240 break; | |
2241 } | |
2242 case DW_TAG_inlined_subroutine: | |
2243 // TODO: | |
2244 data = elfSkipData(data, abbrev, unit->abbrevs); | |
2245 break; | |
2246 default: | |
2247 { | |
2248 fprintf(stderr, "Unknown block TAG %02x\n", abbrev->tag); | |
2249 data = elfSkipData(data, abbrev, unit->abbrevs); | |
2250 break; | |
2251 } | |
2252 } | |
2253 } | |
2254 } | |
2255 return data; | |
2256 } | |
2257 | |
2258 void elfGetFunctionAttributes(CompileUnit *unit, u32 offset, Function *func) | |
2259 { | |
2260 u8 *data = unit->top + offset; | |
2261 int bytes; | |
2262 u32 abbrevNum = elfReadLEB128(data, &bytes); | |
2263 data += bytes; | |
2264 | |
2265 if (!abbrevNum) | |
2266 { | |
2267 return; | |
2268 } | |
2269 | |
2270 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum); | |
2271 | |
2272 for (int i = 0; i < abbrev->numAttrs; i++) | |
2273 { | |
2274 ELFAttr *attr = &abbrev->attrs[i]; | |
2275 data = elfReadAttribute(data, attr); | |
2276 | |
2277 switch (attr->name) | |
2278 { | |
2279 case DW_AT_sibling: | |
2280 break; | |
2281 case DW_AT_name: | |
2282 if (func->name == NULL) | |
2283 func->name = attr->string; | |
2284 break; | |
2285 case DW_AT_MIPS_linkage_name: | |
2286 func->name = attr->string; | |
2287 break; | |
2288 case DW_AT_low_pc: | |
2289 func->lowPC = attr->value; | |
2290 break; | |
2291 case DW_AT_high_pc: | |
2292 func->highPC = attr->value; | |
2293 break; | |
2294 case DW_AT_decl_file: | |
2295 func->file = attr->value; | |
2296 break; | |
2297 case DW_AT_decl_line: | |
2298 func->line = attr->value; | |
2299 break; | |
2300 case DW_AT_external: | |
2301 func->external = attr->flag; | |
2302 break; | |
2303 case DW_AT_frame_base: | |
2304 func->frameBase = attr->block; | |
2305 break; | |
2306 case DW_AT_type: | |
2307 func->returnType = elfParseType(unit, attr->value); | |
2308 break; | |
2309 case DW_AT_inline: | |
2310 case DW_AT_specification: | |
2311 case DW_AT_declaration: | |
2312 case DW_AT_artificial: | |
2313 case DW_AT_prototyped: | |
2314 case DW_AT_proc_body: | |
2315 case DW_AT_save_offset: | |
2316 case DW_AT_user_2002: | |
2317 case DW_AT_virtuality: | |
2318 case DW_AT_containing_type: | |
2319 case DW_AT_accessibility: | |
2320 // todo; | |
2321 break; | |
2322 case DW_AT_vtable_elem_location: | |
2323 free(attr->block); | |
2324 break; | |
2325 default: | |
2326 fprintf(stderr, "Unknown function attribute %02x\n", attr->name); | |
2327 break; | |
2328 } | |
2329 } | |
2330 | |
2331 return; | |
2332 } | |
2333 | |
2334 u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit, | |
2335 Function **f) | |
2336 { | |
2337 Function *func = (Function *)calloc(sizeof(Function), 1); | |
2338 *f = func; | |
2339 | |
2340 int bytes; | |
2341 bool mangled = false; | |
2342 bool declaration = false; | |
2343 for (int i = 0; i < abbrev->numAttrs; i++) | |
2344 { | |
2345 ELFAttr *attr = &abbrev->attrs[i]; | |
2346 data = elfReadAttribute(data, attr); | |
2347 switch (attr->name) | |
2348 { | |
2349 case DW_AT_sibling: | |
2350 break; | |
2351 case DW_AT_name: | |
2352 if (func->name == NULL) | |
2353 func->name = attr->string; | |
2354 break; | |
2355 case DW_AT_MIPS_linkage_name: | |
2356 func->name = attr->string; | |
2357 mangled = true; | |
2358 break; | |
2359 case DW_AT_low_pc: | |
2360 func->lowPC = attr->value; | |
2361 break; | |
2362 case DW_AT_high_pc: | |
2363 func->highPC = attr->value; | |
2364 break; | |
2365 case DW_AT_prototyped: | |
2366 break; | |
2367 case DW_AT_decl_file: | |
2368 func->file = attr->value; | |
2369 break; | |
2370 case DW_AT_decl_line: | |
2371 func->line = attr->value; | |
2372 break; | |
2373 case DW_AT_external: | |
2374 func->external = attr->flag; | |
2375 break; | |
2376 case DW_AT_frame_base: | |
2377 func->frameBase = attr->block; | |
2378 break; | |
2379 case DW_AT_type: | |
2380 func->returnType = elfParseType(unit, attr->value); | |
2381 break; | |
2382 case DW_AT_abstract_origin: | |
2383 elfGetFunctionAttributes(unit, attr->value, func); | |
2384 break; | |
2385 case DW_AT_declaration: | |
2386 declaration = attr->flag; | |
2387 break; | |
2388 case DW_AT_inline: | |
2389 case DW_AT_specification: | |
2390 case DW_AT_artificial: | |
2391 case DW_AT_proc_body: | |
2392 case DW_AT_save_offset: | |
2393 case DW_AT_user_2002: | |
2394 case DW_AT_virtuality: | |
2395 case DW_AT_containing_type: | |
2396 case DW_AT_accessibility: | |
2397 // todo; | |
2398 break; | |
2399 case DW_AT_vtable_elem_location: | |
2400 free(attr->block); | |
2401 break; | |
2402 default: | |
2403 fprintf(stderr, "Unknown function attribute %02x\n", attr->name); | |
2404 break; | |
2405 } | |
2406 } | |
2407 | |
2408 if (declaration) | |
2409 { | |
2410 elfCleanUp(func); | |
2411 free(func); | |
2412 *f = NULL; | |
2413 | |
2414 while (1) | |
2415 { | |
2416 u32 abbrevNum = elfReadLEB128(data, &bytes); | |
2417 data += bytes; | |
2418 | |
2419 if (!abbrevNum) | |
2420 { | |
2421 return data; | |
2422 } | |
2423 | |
2424 abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum); | |
2425 | |
2426 data = elfSkipData(data, abbrev, unit->abbrevs); | |
2427 } | |
2428 } | |
2429 | |
2430 if (abbrev->hasChildren) | |
2431 { | |
2432 int nesting = 1; | |
2433 Object *lastParam = NULL; | |
2434 Object *lastVar = NULL; | |
2435 | |
2436 while (nesting) | |
2437 { | |
2438 u32 abbrevNum = elfReadLEB128(data, &bytes); | |
2439 data += bytes; | |
2440 | |
2441 if (!abbrevNum) | |
2442 { | |
2443 nesting--; | |
2444 continue; | |
2445 } | |
2446 | |
2447 abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum); | |
2448 | |
2449 switch (abbrev->tag) | |
2450 { | |
2451 CASE_TYPE_TAG: // no need to parse types. only parsed when used | |
2452 case DW_TAG_label: // not needed | |
2453 data = elfSkipData(data, abbrev, unit->abbrevs); | |
2454 break; | |
2455 case DW_TAG_subprogram: | |
2456 { | |
2457 Function *fnc = NULL; | |
2458 data = elfParseFunction(data, abbrev, unit, &fnc); | |
2459 if (fnc != NULL) | |
2460 { | |
2461 if (unit->lastFunction == NULL) | |
2462 unit->functions = fnc; | |
2463 else | |
2464 unit->lastFunction->next = fnc; | |
2465 unit->lastFunction = fnc; | |
2466 } | |
2467 break; | |
2468 } | |
2469 case DW_TAG_lexical_block: | |
2470 { | |
2471 data = elfParseBlock(data, abbrev, unit, func, &lastVar); | |
2472 break; | |
2473 } | |
2474 case DW_TAG_formal_parameter: | |
2475 { | |
2476 Object *o; | |
2477 data = elfParseObject(data, abbrev, unit, &o); | |
2478 if (func->parameters) | |
2479 lastParam->next = o; | |
2480 else | |
2481 func->parameters = o; | |
2482 lastParam = o; | |
2483 break; | |
2484 } | |
2485 case DW_TAG_variable: | |
2486 { | |
2487 Object *o; | |
2488 data = elfParseObject(data, abbrev, unit, &o); | |
2489 if (func->variables) | |
2490 lastVar->next = o; | |
2491 else | |
2492 func->variables = o; | |
2493 lastVar = o; | |
2494 break; | |
2495 } | |
2496 case DW_TAG_unspecified_parameters: | |
2497 case DW_TAG_inlined_subroutine: | |
2498 { | |
2499 // todo | |
2500 for (int i = 0; i < abbrev->numAttrs; i++) | |
2501 { | |
2502 data = elfReadAttribute(data, &abbrev->attrs[i]); | |
2503 if (abbrev->attrs[i].form == DW_FORM_block1) | |
2504 free(abbrev->attrs[i].block); | |
2505 } | |
2506 | |
2507 if (abbrev->hasChildren) | |
2508 nesting++; | |
2509 break; | |
2510 } | |
2511 default: | |
2512 { | |
2513 fprintf(stderr, "Unknown function TAG %02x\n", abbrev->tag); | |
2514 data = elfSkipData(data, abbrev, unit->abbrevs); | |
2515 break; | |
2516 } | |
2517 } | |
2518 } | |
2519 } | |
2520 return data; | |
2521 } | |
2522 | |
2523 u8 *elfParseUnknownData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs) | |
2524 { | |
2525 int i; | |
2526 int bytes; | |
2527 // switch(abbrev->tag) { | |
2528 // default: | |
2529 fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag); | |
2530 | |
2531 for (i = 0; i < abbrev->numAttrs; i++) | |
2532 { | |
2533 data = elfReadAttribute(data, &abbrev->attrs[i]); | |
2534 if (abbrev->attrs[i].form == DW_FORM_block1) | |
2535 free(abbrev->attrs[i].block); | |
2536 } | |
2537 | |
2538 if (abbrev->hasChildren) | |
2539 { | |
2540 int nesting = 1; | |
2541 while (nesting) | |
2542 { | |
2543 u32 abbrevNum = elfReadLEB128(data, &bytes); | |
2544 data += bytes; | |
2545 | |
2546 if (!abbrevNum) | |
2547 { | |
2548 nesting--; | |
2549 continue; | |
2550 } | |
2551 | |
2552 abbrev = elfGetAbbrev(abbrevs, abbrevNum); | |
2553 | |
2554 fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag); | |
2555 | |
2556 for (i = 0; i < abbrev->numAttrs; i++) | |
2557 { | |
2558 data = elfReadAttribute(data, &abbrev->attrs[i]); | |
2559 if (abbrev->attrs[i].form == DW_FORM_block1) | |
2560 free(abbrev->attrs[i].block); | |
2561 } | |
2562 | |
2563 if (abbrev->hasChildren) | |
2564 { | |
2565 nesting++; | |
2566 } | |
2567 } | |
2568 } | |
2569 // } | |
2570 return data; | |
2571 } | |
2572 | |
2573 u8 *elfParseCompileUnitChildren(u8 *data, CompileUnit *unit) | |
2574 { | |
2575 int bytes; | |
2576 u32 abbrevNum = elfReadLEB128(data, &bytes); | |
2577 data += bytes; | |
2578 Object *lastObj = NULL; | |
2579 while (abbrevNum) | |
2580 { | |
2581 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum); | |
2582 switch (abbrev->tag) | |
2583 { | |
2584 case DW_TAG_subprogram: | |
2585 { | |
2586 Function *func = NULL; | |
2587 data = elfParseFunction(data, abbrev, unit, &func); | |
2588 if (func != NULL) | |
2589 { | |
2590 if (unit->lastFunction) | |
2591 unit->lastFunction->next = func; | |
2592 else | |
2593 unit->functions = func; | |
2594 unit->lastFunction = func; | |
2595 } | |
2596 break; | |
2597 } | |
2598 CASE_TYPE_TAG: | |
2599 data = elfSkipData(data, abbrev, unit->abbrevs); | |
2600 break; | |
2601 case DW_TAG_variable: | |
2602 { | |
2603 Object *var = NULL; | |
2604 data = elfParseObject(data, abbrev, unit, &var); | |
2605 if (lastObj) | |
2606 lastObj->next = var; | |
2607 else | |
2608 unit->variables = var; | |
2609 lastObj = var; | |
2610 break; | |
2611 } | |
2612 default: | |
2613 data = elfParseUnknownData(data, abbrev, unit->abbrevs); | |
2614 break; | |
2615 } | |
2616 | |
2617 abbrevNum = elfReadLEB128(data, &bytes); | |
2618 data += bytes; | |
2619 } | |
2620 return data; | |
2621 } | |
2622 | |
2623 CompileUnit *elfParseCompUnit(u8 *data, u8 *abbrevData) | |
2624 { | |
2625 int bytes; | |
2626 u8 *top = data; | |
2627 | |
2628 u32 length = elfRead4Bytes(data); | |
2629 data += 4; | |
2630 | |
2631 u16 version = elfRead2Bytes(data); | |
2632 data += 2; | |
2633 | |
2634 u32 offset = elfRead4Bytes(data); | |
2635 data += 4; | |
2636 | |
2637 u8 addrSize = *data++; | |
2638 | |
2639 if (version != 2) | |
2640 { | |
2641 fprintf(stderr, "Unsupported debugging information version %d\n", version); | |
2642 return NULL; | |
2643 } | |
2644 | |
2645 if (addrSize != 4) | |
2646 { | |
2647 fprintf(stderr, "Unsupported address size %d\n", addrSize); | |
2648 return NULL; | |
2649 } | |
2650 | |
2651 ELFAbbrev **abbrevs = elfReadAbbrevs(abbrevData, offset); | |
2652 | |
2653 u32 abbrevNum = elfReadLEB128(data, &bytes); | |
2654 data += bytes; | |
2655 | |
2656 ELFAbbrev *abbrev = elfGetAbbrev(abbrevs, abbrevNum); | |
2657 | |
2658 CompileUnit *unit = (CompileUnit *)calloc(sizeof(CompileUnit), 1); | |
2659 unit->top = top; | |
2660 unit->length = length; | |
2661 unit->abbrevs = abbrevs; | |
2662 unit->next = NULL; | |
2663 | |
2664 elfCurrentUnit = unit; | |
2665 | |
2666 int i; | |
2667 | |
2668 for (i = 0; i < abbrev->numAttrs; i++) | |
2669 { | |
2670 ELFAttr *attr = &abbrev->attrs[i]; | |
2671 data = elfReadAttribute(data, attr); | |
2672 | |
2673 switch (attr->name) | |
2674 { | |
2675 case DW_AT_name: | |
2676 unit->name = attr->string; | |
2677 break; | |
2678 case DW_AT_stmt_list: | |
2679 unit->hasLineInfo = true; | |
2680 unit->lineInfo = attr->value; | |
2681 break; | |
2682 case DW_AT_low_pc: | |
2683 unit->lowPC = attr->value; | |
2684 break; | |
2685 case DW_AT_high_pc: | |
2686 unit->highPC = attr->value; | |
2687 break; | |
2688 case DW_AT_compdir: | |
2689 unit->compdir = attr->string; | |
2690 break; | |
2691 // ignore | |
2692 case DW_AT_language: | |
2693 case DW_AT_producer: | |
2694 case DW_AT_macro_info: | |
2695 case DW_AT_entry_pc: | |
2696 break; | |
2697 default: | |
2698 fprintf(stderr, "Unknown attribute %02x\n", attr->name); | |
2699 break; | |
2700 } | |
2701 } | |
2702 | |
2703 if (abbrev->hasChildren) | |
2704 elfParseCompileUnitChildren(data, unit); | |
2705 | |
2706 return unit; | |
2707 } | |
2708 | |
2709 void elfParseAranges(u8 *data) | |
2710 { | |
2711 ELFSectionHeader *sh = elfGetSectionByName(".debug_aranges"); | |
2712 if (sh == NULL) | |
2713 { | |
2714 fprintf(stderr, "No aranges found\n"); | |
2715 return; | |
2716 } | |
2717 | |
2718 data = elfReadSection(data, sh); | |
2719 u8 *end = data + READ32LE(&sh->size); | |
2720 | |
2721 int max = 4; | |
2722 ARanges *ranges = (ARanges *)calloc(sizeof(ARanges), 4); | |
2723 | |
2724 int index = 0; | |
2725 | |
2726 while (data < end) | |
2727 { | |
2728 u32 len = elfRead4Bytes(data); | |
2729 data += 4; | |
2730 // u16 version = elfRead2Bytes(data); | |
2731 data += 2; | |
2732 u32 offset = elfRead4Bytes(data); | |
2733 data += 4; | |
2734 // u8 addrSize = *data++; | |
2735 // u8 segSize = *data++; | |
2736 data += 2; // remove if uncommenting above | |
2737 data += 4; | |
2738 ranges[index].count = (len-20)/8; | |
2739 ranges[index].offset = offset; | |
2740 ranges[index].ranges = (ARange *)calloc(sizeof(ARange), (len-20)/8); | |
2741 int i = 0; | |
2742 while (true) | |
2743 { | |
2744 u32 addr = elfRead4Bytes(data); | |
2745 data += 4; | |
2746 u32 len = elfRead4Bytes(data); | |
2747 data += 4; | |
2748 if (addr == 0 && len == 0) | |
2749 break; | |
2750 ranges[index].ranges[i].lowPC = addr; | |
2751 ranges[index].ranges[i].highPC = addr+len; | |
2752 i++; | |
2753 } | |
2754 index++; | |
2755 if (index == max) | |
2756 { | |
2757 max += 4; | |
2758 ranges = (ARanges *)realloc(ranges, max*sizeof(ARanges)); | |
2759 } | |
2760 } | |
2761 elfDebugInfo->numRanges = index; | |
2762 elfDebugInfo->ranges = ranges; | |
2763 } | |
2764 | |
2765 void elfReadSymtab(u8 *data) | |
2766 { | |
2767 ELFSectionHeader *sh = elfGetSectionByName(".symtab"); | |
2768 int table = READ32LE(&sh->link); | |
2769 | |
2770 char *strtable = (char *)elfReadSection(data, elfGetSectionByNumber(table)); | |
2771 | |
2772 ELFSymbol *symtab = (ELFSymbol *)elfReadSection(data, sh); | |
2773 | |
2774 int count = READ32LE(&sh->size) / sizeof(ELFSymbol); | |
2775 elfSymbolsCount = 0; | |
2776 | |
2777 elfSymbols = (Symbol *)malloc(sizeof(Symbol)*count); | |
2778 | |
2779 int i; | |
2780 | |
2781 for (i = 0; i < count; i++) | |
2782 { | |
2783 ELFSymbol *s = &symtab[i]; | |
2784 int type = s->info & 15; | |
2785 int binding = s->info >> 4; | |
2786 | |
2787 if (binding) | |
2788 { | |
2789 Symbol *sym = &elfSymbols[elfSymbolsCount]; | |
2790 sym->name = &strtable[READ32LE(&s->name)]; | |
2791 sym->binding = binding; | |
2792 sym->type = type; | |
2793 sym->value = READ32LE(&s->value); | |
2794 sym->size = READ32LE(&s->size); | |
2795 elfSymbolsCount++; | |
2796 } | |
2797 } | |
2798 for (i = 0; i < count; i++) | |
2799 { | |
2800 ELFSymbol *s = &symtab[i]; | |
2801 int bind = s->info>>4; | |
2802 int type = s->info & 15; | |
2803 | |
2804 if (!bind) | |
2805 { | |
2806 Symbol *sym = &elfSymbols[elfSymbolsCount]; | |
2807 sym->name = &strtable[READ32LE(&s->name)]; | |
2808 sym->binding = (s->info >> 4); | |
2809 sym->type = type; | |
2810 sym->value = READ32LE(&s->value); | |
2811 sym->size = READ32LE(&s->size); | |
2812 elfSymbolsCount++; | |
2813 } | |
2814 } | |
2815 elfSymbolsStrTab = strtable; | |
2816 // free(symtab); | |
2817 } | |
2818 | |
2819 bool elfReadProgram(ELFHeader *eh, u8 *data, int& size, bool parseDebug) | |
2820 { | |
2821 int count = READ16LE(&eh->e_phnum); | |
2822 int i; | |
2823 | |
2824 if (READ32LE(&eh->e_entry) == 0x2000000) | |
2825 cpuIsMultiBoot = true; | |
2826 | |
2827 // read program headers... should probably move this code down | |
2828 u8 *p = data + READ32LE(&eh->e_phoff); | |
2829 size = 0; | |
2830 for (i = 0; i < count; i++) | |
2831 { | |
2832 ELFProgramHeader *ph = (ELFProgramHeader *)p; | |
2833 p += sizeof(ELFProgramHeader); | |
2834 if (READ16LE(&eh->e_phentsize) != sizeof(ELFProgramHeader)) | |
2835 { | |
2836 p += READ16LE(&eh->e_phentsize) - sizeof(ELFProgramHeader); | |
2837 } | |
2838 | |
2839 // printf("PH %d %08x %08x %08x %08x %08x %08x %08x %08x\n", | |
2840 // i, ph->type, ph->offset, ph->vaddr, ph->paddr, | |
2841 // ph->filesz, ph->memsz, ph->flags, ph->align); | |
2842 if (cpuIsMultiBoot) | |
2843 { | |
2844 if (READ32LE(&ph->paddr) >= 0x2000000 && | |
2845 READ32LE(&ph->paddr) <= 0x203ffff) | |
2846 { | |
2847 memcpy(&workRAM[READ32LE(&ph->paddr) & 0x3ffff], | |
2848 data + READ32LE(&ph->offset), | |
2849 READ32LE(&ph->filesz)); | |
2850 } | |
2851 } | |
2852 else | |
2853 { | |
2854 if (READ32LE(&ph->paddr) >= 0x8000000 && | |
2855 READ32LE(&ph->paddr) <= 0x9ffffff) | |
2856 { | |
2857 memcpy(&rom[READ32LE(&ph->paddr) & 0x1ffffff], | |
2858 data + READ32LE(&ph->offset), | |
2859 READ32LE(&ph->filesz)); | |
2860 size += READ32LE(&ph->filesz); | |
2861 } | |
2862 } | |
2863 } | |
2864 | |
2865 char *stringTable = NULL; | |
2866 | |
2867 // read section headers | |
2868 p = data + READ32LE(&eh->e_shoff); | |
2869 count = READ16LE(&eh->e_shnum); | |
2870 | |
2871 ELFSectionHeader **sh = (ELFSectionHeader * *) | |
2872 malloc(sizeof(ELFSectionHeader *) * count); | |
2873 | |
2874 for (i = 0; i < count; i++) | |
2875 { | |
2876 sh[i] = (ELFSectionHeader *)p; | |
2877 p += sizeof(ELFSectionHeader); | |
2878 if (READ16LE(&eh->e_shentsize) != sizeof(ELFSectionHeader)) | |
2879 p += READ16LE(&eh->e_shentsize) - sizeof(ELFSectionHeader); | |
2880 } | |
2881 | |
2882 if (READ16LE(&eh->e_shstrndx) != 0) | |
2883 { | |
2884 stringTable = (char *)elfReadSection(data, | |
2885 sh[READ16LE(&eh->e_shstrndx)]); | |
2886 } | |
2887 | |
2888 elfSectionHeaders = sh; | |
2889 elfSectionHeadersStringTable = stringTable; | |
2890 elfSectionHeadersCount = count; | |
2891 | |
2892 for (i = 0; i < count; i++) | |
2893 { | |
2894 // printf("SH %d %-20s %08x %08x %08x %08x %08x %08x %08x %08x\n", | |
2895 // i, &stringTable[sh[i]->name], sh[i]->name, sh[i]->type, | |
2896 // sh[i]->flags, sh[i]->addr, sh[i]->offset, sh[i]->size, | |
2897 // sh[i]->link, sh[i]->info); | |
2898 if (READ32LE(&sh[i]->flags) & 2) // load section | |
2899 { | |
2900 if (cpuIsMultiBoot) | |
2901 { | |
2902 if (READ32LE(&sh[i]->addr) >= 0x2000000 && | |
2903 READ32LE(&sh[i]->addr) <= 0x203ffff) | |
2904 { | |
2905 memcpy(&workRAM[READ32LE(&sh[i]->addr) & 0x3ffff], data + | |
2906 READ32LE(&sh[i]->offset), | |
2907 READ32LE(&sh[i]->size)); | |
2908 } | |
2909 } | |
2910 else | |
2911 { | |
2912 if (READ32LE(&sh[i]->addr) >= 0x8000000 && | |
2913 READ32LE(&sh[i]->addr) <= 0x9ffffff) | |
2914 { | |
2915 memcpy(&rom[READ32LE(&sh[i]->addr) & 0x1ffffff], | |
2916 data + READ32LE(&sh[i]->offset), | |
2917 READ32LE(&sh[i]->size)); | |
2918 size += READ32LE(&sh[i]->size); | |
2919 } | |
2920 } | |
2921 } | |
2922 } | |
2923 | |
2924 if (parseDebug) | |
2925 { | |
2926 fprintf(stderr, "Parsing debug info\n"); | |
2927 | |
2928 ELFSectionHeader *dbgHeader = elfGetSectionByName(".debug_info"); | |
2929 if (dbgHeader == NULL) | |
2930 { | |
2931 fprintf(stderr, "Cannot find debug information\n"); | |
2932 goto end; | |
2933 } | |
2934 | |
2935 ELFSectionHeader *h = elfGetSectionByName(".debug_abbrev"); | |
2936 if (h == NULL) | |
2937 { | |
2938 fprintf(stderr, "Cannot find abbreviation table\n"); | |
2939 goto end; | |
2940 } | |
2941 | |
2942 elfDebugInfo = (DebugInfo *)calloc(sizeof(DebugInfo), 1); | |
2943 u8 *abbrevdata = elfReadSection(data, h); | |
2944 | |
2945 h = elfGetSectionByName(".debug_str"); | |
2946 | |
2947 if (h == NULL) | |
2948 elfDebugStrings = NULL; | |
2949 else | |
2950 elfDebugStrings = (char *)elfReadSection(data, h); | |
2951 | |
2952 u8 *debugdata = elfReadSection(data, dbgHeader); | |
2953 | |
2954 elfDebugInfo->debugdata = data; | |
2955 elfDebugInfo->infodata = debugdata; | |
2956 | |
2957 u32 total = READ32LE(&dbgHeader->size); | |
2958 u8 *end = debugdata + total; | |
2959 u8 *ddata = debugdata; | |
2960 | |
2961 CompileUnit *last = NULL; | |
2962 CompileUnit *unit = NULL; | |
2963 | |
2964 while (ddata < end) | |
2965 { | |
2966 unit = elfParseCompUnit(ddata, abbrevdata); | |
2967 unit->offset = ddata-debugdata; | |
2968 elfParseLineInfo(unit, data); | |
2969 if (last == NULL) | |
2970 elfCompileUnits = unit; | |
2971 else | |
2972 last->next = unit; | |
2973 last = unit; | |
2974 ddata += 4 + unit->length; | |
2975 } | |
2976 elfParseAranges(data); | |
2977 CompileUnit *comp = elfCompileUnits; | |
2978 while (comp) | |
2979 { | |
2980 ARanges *r = elfDebugInfo->ranges; | |
2981 for (int i = 0; i < elfDebugInfo->numRanges; i++) | |
2982 if (r[i].offset == comp->offset) | |
2983 { | |
2984 comp->ranges = &r[i]; | |
2985 break; | |
2986 } | |
2987 comp = comp->next; | |
2988 } | |
2989 elfParseCFA(data); | |
2990 elfReadSymtab(data); | |
2991 } | |
2992 end: | |
2993 if (sh) | |
2994 { | |
2995 free(sh); | |
2996 } | |
2997 | |
2998 elfSectionHeaders = NULL; | |
2999 elfSectionHeadersStringTable = NULL; | |
3000 elfSectionHeadersCount = 0; | |
3001 | |
3002 return true; | |
3003 } | |
3004 | |
3005 extern bool8 parseDebug; | |
3006 | |
3007 bool elfRead(const char *name, int& siz, FILE *f) | |
3008 { | |
3009 fseek(f, 0, SEEK_END); | |
3010 long size = ftell(f); | |
3011 elfFileData = (u8 *)malloc(size); | |
3012 fseek(f, 0, SEEK_SET); | |
3013 fread(elfFileData, 1, size, f); | |
3014 fclose(f); | |
3015 | |
3016 ELFHeader *header = (ELFHeader *)elfFileData; | |
3017 | |
3018 if (READ32LE(&header->magic) != 0x464C457F || | |
3019 READ16LE(&header->e_machine) != 40 || | |
3020 header->clazz != 1) | |
3021 { | |
3022 systemMessage(0, N_("Not a valid ELF file %s"), name); | |
3023 free(elfFileData); | |
3024 elfFileData = NULL; | |
3025 return false; | |
3026 } | |
3027 | |
3028 if (!elfReadProgram(header, elfFileData, siz, parseDebug)) | |
3029 { | |
3030 free(elfFileData); | |
3031 elfFileData = NULL; | |
3032 return false; | |
3033 } | |
3034 | |
3035 return true; | |
3036 } | |
3037 | |
3038 void elfCleanUp(Object *o) | |
3039 { | |
3040 free(o->location); | |
3041 } | |
3042 | |
3043 void elfCleanUp(Function *func) | |
3044 { | |
3045 Object *o = func->parameters; | |
3046 while (o) | |
3047 { | |
3048 elfCleanUp(o); | |
3049 Object *next = o->next; | |
3050 free(o); | |
3051 o = next; | |
3052 } | |
3053 | |
3054 o = func->variables; | |
3055 while (o) | |
3056 { | |
3057 elfCleanUp(o); | |
3058 Object *next = o->next; | |
3059 free(o); | |
3060 o = next; | |
3061 } | |
3062 free(func->frameBase); | |
3063 } | |
3064 | |
3065 void elfCleanUp(ELFAbbrev **abbrevs) | |
3066 { | |
3067 for (int i = 0; i < 121; i++) | |
3068 { | |
3069 ELFAbbrev *abbrev = abbrevs[i]; | |
3070 | |
3071 while (abbrev) | |
3072 { | |
3073 free(abbrev->attrs); | |
3074 ELFAbbrev *next = abbrev->next; | |
3075 free(abbrev); | |
3076 | |
3077 abbrev = next; | |
3078 } | |
3079 } | |
3080 } | |
3081 | |
3082 void elfCleanUp(Type *t) | |
3083 { | |
3084 switch (t->type) | |
3085 { | |
3086 case TYPE_function: | |
3087 if (t->function) | |
3088 { | |
3089 Object *o = t->function->args; | |
3090 while (o) | |
3091 { | |
3092 elfCleanUp(o); | |
3093 Object *next = o->next; | |
3094 free(o); | |
3095 o = next; | |
3096 } | |
3097 free(t->function); | |
3098 } | |
3099 break; | |
3100 case TYPE_array: | |
3101 if (t->array) | |
3102 { | |
3103 free(t->array->bounds); | |
3104 free(t->array); | |
3105 } | |
3106 break; | |
3107 case TYPE_struct: | |
3108 case TYPE_union: | |
3109 if (t->structure) | |
3110 { | |
3111 for (int i = 0; i < t->structure->memberCount; i++) | |
3112 { | |
3113 free(t->structure->members[i].location); | |
3114 } | |
3115 free(t->structure->members); | |
3116 free(t->structure); | |
3117 } | |
3118 break; | |
3119 case TYPE_enum: | |
3120 if (t->enumeration) | |
3121 { | |
3122 free(t->enumeration->members); | |
3123 free(t->enumeration); | |
3124 } | |
3125 break; | |
3126 case TYPE_base: | |
3127 case TYPE_pointer: | |
3128 case TYPE_void: | |
3129 case TYPE_reference: | |
3130 break; // nothing to do | |
3131 } | |
3132 } | |
3133 | |
3134 void elfCleanUp(CompileUnit *comp) | |
3135 { | |
3136 elfCleanUp(comp->abbrevs); | |
3137 free(comp->abbrevs); | |
3138 Function *func = comp->functions; | |
3139 while (func) | |
3140 { | |
3141 elfCleanUp(func); | |
3142 Function *next = func->next; | |
3143 free(func); | |
3144 func = next; | |
3145 } | |
3146 Type *t = comp->types; | |
3147 while (t) | |
3148 { | |
3149 elfCleanUp(t); | |
3150 Type *next = t->next; | |
3151 free(t); | |
3152 t = next; | |
3153 } | |
3154 Object *o = comp->variables; | |
3155 while (o) | |
3156 { | |
3157 elfCleanUp(o); | |
3158 Object *next = o->next; | |
3159 free(o); | |
3160 o = next; | |
3161 } | |
3162 if (comp->lineInfoTable) | |
3163 { | |
3164 free(comp->lineInfoTable->lines); | |
3165 free(comp->lineInfoTable->files); | |
3166 free(comp->lineInfoTable); | |
3167 } | |
3168 } | |
3169 | |
3170 void elfCleanUp() | |
3171 { | |
3172 CompileUnit *comp = elfCompileUnits; | |
3173 | |
3174 while (comp) | |
3175 { | |
3176 elfCleanUp(comp); | |
3177 CompileUnit *next = comp->next; | |
3178 free(comp); | |
3179 comp = next; | |
3180 } | |
3181 elfCompileUnits = NULL; | |
3182 free(elfSymbols); | |
3183 elfSymbols = NULL; | |
3184 // free(elfSymbolsStrTab); | |
3185 elfSymbolsStrTab = NULL; | |
3186 | |
3187 elfDebugStrings = NULL; | |
3188 if (elfDebugInfo) | |
3189 { | |
3190 int num = elfDebugInfo->numRanges; | |
3191 int i; | |
3192 for (i = 0; i < num; i++) | |
3193 { | |
3194 free(elfDebugInfo->ranges[i].ranges); | |
3195 } | |
3196 free(elfDebugInfo->ranges); | |
3197 free(elfDebugInfo); | |
3198 elfDebugInfo = NULL; | |
3199 } | |
3200 | |
3201 if (elfFdes) | |
3202 { | |
3203 if (elfFdeCount) | |
3204 { | |
3205 for (int i = 0; i < elfFdeCount; i++) | |
3206 free(elfFdes[i]); | |
3207 } | |
3208 free(elfFdes); | |
3209 | |
3210 elfFdes = NULL; | |
3211 elfFdeCount = 0; | |
3212 } | |
3213 | |
3214 ELFcie *cie = elfCies; | |
3215 while (cie) | |
3216 { | |
3217 ELFcie *next = cie->next; | |
3218 free(cie); | |
3219 cie = next; | |
3220 } | |
3221 elfCies = NULL; | |
3222 | |
3223 if (elfFileData) | |
3224 { | |
3225 free(elfFileData); | |
3226 elfFileData = NULL; | |
3227 } | |
3228 } | |
3229 |