Mercurial > vba-clojure
view src/gba/elf.cpp @ 135:eb6ba88088d3
Wrote a more efficient input-number-assembly program; 91 oc -> 60 oc.
author | Dylan Holmes <ocsenave@gmail.com> |
---|---|
date | Sun, 18 Mar 2012 05:13:19 -0500 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 #include <cstdio>2 #include <cstdlib>3 #include <cstring>5 #include "../Port.h"6 #include "../NLS.h"7 #include "../common/System.h" // systemMessage8 #include "GBAGlobals.h"9 #include "elf.h"11 #define elfReadMemory(addr) \12 READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))14 #define DW_TAG_array_type 0x0115 #define DW_TAG_enumeration_type 0x0416 #define DW_TAG_formal_parameter 0x0517 #define DW_TAG_label 0x0a18 #define DW_TAG_lexical_block 0x0b19 #define DW_TAG_member 0x0d20 #define DW_TAG_pointer_type 0x0f21 #define DW_TAG_reference_type 0x1022 #define DW_TAG_compile_unit 0x1123 #define DW_TAG_structure_type 0x1324 #define DW_TAG_subroutine_type 0x1525 #define DW_TAG_typedef 0x1626 #define DW_TAG_union_type 0x1727 #define DW_TAG_unspecified_parameters 0x1828 #define DW_TAG_inheritance 0x1c29 #define DW_TAG_inlined_subroutine 0x1d30 #define DW_TAG_subrange_type 0x2131 #define DW_TAG_base_type 0x2432 #define DW_TAG_const_type 0x2633 #define DW_TAG_enumerator 0x2834 #define DW_TAG_subprogram 0x2e35 #define DW_TAG_variable 0x3436 #define DW_TAG_volatile_type 0x3538 #define DW_AT_sibling 0x0139 #define DW_AT_location 0x0240 #define DW_AT_name 0x0341 #define DW_AT_byte_size 0x0b42 #define DW_AT_bit_offset 0x0c43 #define DW_AT_bit_size 0x0d44 #define DW_AT_stmt_list 0x1045 #define DW_AT_low_pc 0x1146 #define DW_AT_high_pc 0x1247 #define DW_AT_language 0x1348 #define DW_AT_compdir 0x1b49 #define DW_AT_const_value 0x1c50 #define DW_AT_containing_type 0x1d51 #define DW_AT_inline 0x2052 #define DW_AT_producer 0x2553 #define DW_AT_prototyped 0x2754 #define DW_AT_upper_bound 0x2f55 #define DW_AT_abstract_origin 0x3156 #define DW_AT_accessibility 0x3257 #define DW_AT_artificial 0x3458 #define DW_AT_data_member_location 0x3859 #define DW_AT_decl_file 0x3a60 #define DW_AT_decl_line 0x3b61 #define DW_AT_declaration 0x3c62 #define DW_AT_encoding 0x3e63 #define DW_AT_external 0x3f64 #define DW_AT_frame_base 0x4065 #define DW_AT_macro_info 0x4366 #define DW_AT_specification 0x4767 #define DW_AT_type 0x4968 #define DW_AT_virtuality 0x4c69 #define DW_AT_vtable_elem_location 0x4d70 // DWARF 2.1/3.0 extensions71 #define DW_AT_entry_pc 0x5272 #define DW_AT_ranges 0x5573 // ARM Compiler extensions74 #define DW_AT_proc_body 0x200075 #define DW_AT_save_offset 0x200176 #define DW_AT_user_2002 0x200277 // MIPS extensions78 #define DW_AT_MIPS_linkage_name 0x200780 #define DW_FORM_addr 0x0181 #define DW_FORM_data2 0x0582 #define DW_FORM_data4 0x0683 #define DW_FORM_string 0x0884 #define DW_FORM_block 0x0985 #define DW_FORM_block1 0x0a86 #define DW_FORM_data1 0x0b87 #define DW_FORM_flag 0x0c88 #define DW_FORM_sdata 0x0d89 #define DW_FORM_strp 0x0e90 #define DW_FORM_udata 0x0f91 #define DW_FORM_ref_addr 0x1092 #define DW_FORM_ref4 0x1393 #define DW_FORM_ref_udata 0x1594 #define DW_FORM_indirect 0x1696 #define DW_OP_addr 0x0397 #define DW_OP_plus_uconst 0x2398 #define DW_OP_reg0 0x5099 #define DW_OP_reg1 0x51100 #define DW_OP_reg2 0x52101 #define DW_OP_reg3 0x53102 #define DW_OP_reg4 0x54103 #define DW_OP_reg5 0x55104 #define DW_OP_reg6 0x56105 #define DW_OP_reg7 0x57106 #define DW_OP_reg8 0x58107 #define DW_OP_reg9 0x59108 #define DW_OP_reg10 0x5a109 #define DW_OP_reg11 0x5b110 #define DW_OP_reg12 0x5c111 #define DW_OP_reg13 0x5d112 #define DW_OP_reg14 0x5e113 #define DW_OP_reg15 0x5f114 #define DW_OP_fbreg 0x91116 #define DW_LNS_extended_op 0x00117 #define DW_LNS_copy 0x01118 #define DW_LNS_advance_pc 0x02119 #define DW_LNS_advance_line 0x03120 #define DW_LNS_set_file 0x04121 #define DW_LNS_set_column 0x05122 #define DW_LNS_negate_stmt 0x06123 #define DW_LNS_set_basic_block 0x07124 #define DW_LNS_const_add_pc 0x08125 #define DW_LNS_fixed_advance_pc 0x09127 #define DW_LNE_end_sequence 0x01128 #define DW_LNE_set_address 0x02129 #define DW_LNE_define_file 0x03131 #define DW_CFA_advance_loc 0x01132 #define DW_CFA_offset 0x02133 #define DW_CFA_restore 0x03134 #define DW_CFA_set_loc 0x01135 #define DW_CFA_advance_loc1 0x02136 #define DW_CFA_advance_loc2 0x03137 #define DW_CFA_advance_loc4 0x04138 #define DW_CFA_offset_extended 0x05139 #define DW_CFA_restore_extended 0x06140 #define DW_CFA_undefined 0x07141 #define DW_CFA_same_value 0x08142 #define DW_CFA_register 0x09143 #define DW_CFA_remember_state 0x0a144 #define DW_CFA_restore_state 0x0b145 #define DW_CFA_def_cfa 0x0c146 #define DW_CFA_def_cfa_register 0x0d147 #define DW_CFA_def_cfa_offset 0x0e148 #define DW_CFA_nop 0x00150 #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_type164 struct ELFcie165 {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 };176 struct ELFfde177 {178 ELFcie *cie;179 u32 address;180 u32 end;181 u8 * data;182 u32 dataLen;183 };185 enum ELFRegMode186 {187 REG_NOT_SET,188 REG_OFFSET,189 REG_REGISTER190 };192 struct ELFFrameStateRegister193 {194 ELFRegMode mode;195 int reg;196 s32 offset;197 };199 struct ELFFrameStateRegisters200 {201 ELFFrameStateRegister regs[16];202 ELFFrameStateRegisters *previous;203 };205 enum ELFCfaMode206 {207 CFA_NOT_SET,208 CFA_REG_OFFSET209 };211 struct ELFFrameState212 {213 ELFFrameStateRegisters registers;215 ELFCfaMode cfaMode;216 int cfaRegister;217 s32 cfaOffset;219 u32 pc;221 int dataAlign;222 int codeAlign;223 int returnAddress;224 };226 extern bool8 cpuIsMultiBoot;228 Symbol *elfSymbols = NULL;229 char * elfSymbolsStrTab = NULL;230 int elfSymbolsCount = 0;232 ELFSectionHeader **elfSectionHeaders = NULL;233 char *elfSectionHeadersStringTable = NULL;234 int elfSectionHeadersCount = 0;235 u8 * elfFileData = NULL;237 CompileUnit *elfCompileUnits = NULL;238 DebugInfo * elfDebugInfo = NULL;239 char * elfDebugStrings = NULL;241 ELFcie * elfCies = NULL;242 ELFfde **elfFdes = NULL;243 int elfFdeCount = 0;245 CompileUnit *elfCurrentUnit = NULL;247 u32 elfRead4Bytes(u8 *);248 u16 elfRead2Bytes(u8 *);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 else263 {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 }281 char *elfGetAddressSymbol(u32 addr)282 {283 static char buffer[256];285 CompileUnit *unit = elfGetCompileUnit(addr);286 // found unit, need to find function287 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 else301 strcpy(buffer, name);302 return buffer;303 }304 func = func->next;305 }306 }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 else322 strcpy(buffer, name);323 return buffer;324 }325 else if (addr == s->value)326 {327 if (s->name)328 strcpy(buffer, s->name);329 else330 strcpy(buffer, "");331 return buffer;332 }333 }334 }336 return "";337 }339 bool elfFindLineInModule(u32 *addr, char *name, int line)340 {341 CompileUnit *unit = elfCompileUnits;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 now359 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 match372 return false;373 }374 }375 unit = unit->next;376 }377 return false;378 }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 }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 }420 bool elfGetCurrentFunction(u32 addr, Function **f, CompileUnit **u)421 {422 CompileUnit *unit = elfGetCompileUnit(addr);423 // found unit, need to find function424 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 }441 bool elfGetObject(char *name, Function *f, CompileUnit *u, Object **o)442 {443 if (f && u)444 {445 Object *v = f->variables;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 }478 CompileUnit *c = elfCompileUnits;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 }498 return false;499 }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 }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 }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 }548 return NULL;549 }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;559 while (data < end && state->pc < pc)560 {561 u8 op = *data++;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 now578 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 }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;671 elfExecuteCFAInstructions(state,672 fde->cie->data,673 fde->cie->dataLen,674 0xffffffff);675 elfExecuteCFAInstructions(state,676 fde->data,677 fde->dataLen,678 address);680 return state;681 }683 void elfPrintCallChain(u32 address)684 {685 int count = 1;687 reg_pair regs[15];688 reg_pair newRegs[15];690 memcpy(®s[0], ®[0], sizeof(reg_pair) * 15);692 while (count < 20)693 {694 char *addr = elfGetAddressSymbol(address);695 if (*addr == 0)696 addr = "???";698 printf("%08x %s\n", address, addr);700 ELFfde *fde = elfGetFde(address);702 if (fde == NULL)703 {704 break;705 }707 ELFFrameState *state = elfGetFrameState(fde, address);709 if (!state)710 {711 break;712 }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];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 else748 {749 printf("CFA not set\n");750 break;751 }752 if (state->registers.previous)753 {754 ELFFrameStateRegisters *prev = state->registers.previous;756 while (prev)757 {758 ELFFrameStateRegisters *p = prev->previous;759 free(prev);760 prev = p;761 }762 }763 free(state);764 }765 }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 }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 }849 u32 elfDecodeLocation(Function *f, ELFBlock *o, LocationType *type)850 {851 return elfDecodeLocation(f, o, type, 0);852 }854 // reading function856 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 }865 u16 elfRead2Bytes(u8 *data)866 {867 u16 value = *data++;868 value |= (*data << 8);869 return value;870 }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 }883 s32 elfReadSignedLEB128(u8 *data, int *bytesRead)884 {885 s32 result = 0;886 int shift = 0;887 int count = 0;889 u8 byte;890 do891 {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 }904 u32 elfReadLEB128(u8 *data, int *bytesRead)905 {906 u32 result = 0;907 int shift = 0;908 int count = 0;909 u8 byte;910 do911 {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 }922 u8 *elfReadSection(u8 *data, ELFSectionHeader *sh)923 {924 return data + READ32LE(&sh->offset);925 }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 }941 ELFSectionHeader *elfGetSectionByNumber(int number)942 {943 if (number < elfSectionHeadersCount)944 {945 return elfSectionHeaders[number];946 }947 return NULL;948 }950 CompileUnit *elfGetCompileUnitForData(u8 *data)951 {952 u8 *end = elfCurrentUnit->top + 4 + elfCurrentUnit->length;954 if (data >= elfCurrentUnit->top && data < end)955 return elfCurrentUnit;957 CompileUnit *unit = elfCompileUnits;959 while (unit)960 {961 end = unit->top + 4 + unit->length;963 if (data >= unit->top && data < end)964 return unit;966 unit = unit->next;967 }969 printf("Error: cannot find reference to compile unit at offset %08x\n",970 (int)(data - elfDebugInfo->infodata));971 exit(-1);972 }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 }1056 ELFAbbrev *elfGetAbbrev(ELFAbbrev **table, u32 number)1057 {1058 int hash = number % 121;1060 ELFAbbrev *abbrev = table[hash];1062 while (abbrev)1063 {1064 if (abbrev->number == number)1065 return abbrev;1066 abbrev = abbrev->next;1067 }1068 return NULL;1069 }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);1082 // read tag information1083 abbrev->number = number;1084 abbrev->tag = elfReadLEB128(data, &bytes);1085 data += bytes;1086 abbrev->hasChildren = *data++ ? true : false;1088 // read attributes1089 int name = elfReadLEB128(data, &bytes);1090 data += bytes;1091 int form = elfReadLEB128(data, &bytes);1092 data += bytes;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;1105 name = elfReadLEB128(data, &bytes);1106 data += bytes;1107 form = elfReadLEB128(data, &bytes);1108 data += bytes;1109 }1111 int hash = number % 121;1112 abbrev->next = abbrevs[hash];1113 abbrevs[hash] = abbrev;1115 number = elfReadLEB128(data, &bytes);1116 data += bytes;1118 if (elfGetAbbrev(abbrevs, number) != NULL)1119 break;1120 }1122 return abbrevs;1123 }1125 void elfParseCFA(u8 *top)1126 {1127 ELFSectionHeader *h = elfGetSectionByName(".debug_frame");1129 if (h == NULL)1130 {1131 return;1132 }1134 u8 *data = elfReadSection(top, h);1136 u8 *topOffset = data;1138 u8 *end = data + READ32LE(&h->size);1140 ELFcie *cies = NULL;1142 while (data < end)1143 {1144 u32 offset = data - topOffset;1145 u32 len = elfRead4Bytes(data);1146 data += 4;1148 u8 *dataEnd = data + len;1150 u32 id = elfRead4Bytes(data);1151 data += 4;1153 if (id == 0xffffffff)1154 {1155 // skip version1156 *data++;1158 ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie));1160 cie->next = cies;1161 cies = cie;1163 cie->offset = offset;1165 cie->augmentation = data;1166 while (*data)1167 data++;1168 data++;1170 if (*cie->augmentation)1171 {1172 fprintf(stderr, "Error: augmentation not supported\n");1173 exit(-1);1174 }1176 int bytes;1177 cie->codeAlign = elfReadLEB128(data, &bytes);1178 data += bytes;1180 cie->dataAlign = elfReadSignedLEB128(data, &bytes);1181 data += bytes;1183 cie->returnAddress = *data++;1185 cie->data = data;1186 cie->dataLen = dataEnd - data;1187 }1188 else1189 {1190 ELFfde *fde = (ELFfde *)calloc(1, sizeof(ELFfde));1192 ELFcie *cie = cies;1194 while (cie != NULL)1195 {1196 if (cie->offset == id)1197 break;1198 cie = cie->next;1199 }1201 if (!cie)1202 {1203 fprintf(stderr, "Cannot find CIE %08x\n", id);1204 exit(-1);1205 }1207 fde->cie = cie;1209 fde->address = elfRead4Bytes(data);1210 data += 4;1212 fde->end = fde->address + elfRead4Bytes(data);1213 data += 4;1215 fde->data = data;1216 fde->dataLen = dataEnd - data;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 }1228 elfCies = cies;1229 }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 }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));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++;1278 free(stdOpLen); // todo1279 int bytes = 0;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);1292 while ((s = elfReadString(data, &bytes)) != NULL)1293 {1294 l->files[index++] = s;1296 data += bytes;1297 // directory1298 elfReadLEB128(data, &bytes);1299 data += bytes;1300 // time1301 elfReadLEB128(data, &bytes);1302 data += bytes;1303 // size1304 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;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;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 }1398 u8 *elfSkipData(u8 *data, ELFAbbrev *abbrev, ELFAbbrev **abbrevs)1399 {1400 int i;1401 int bytes;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 }1410 if (abbrev->hasChildren)1411 {1412 int nesting = 1;1413 while (nesting)1414 {1415 u32 abbrevNum = elfReadLEB128(data, &bytes);1416 data += bytes;1418 if (!abbrevNum)1419 {1420 nesting--;1421 continue;1422 }1424 abbrev = elfGetAbbrev(abbrevs, abbrevNum);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 }1433 if (abbrev->hasChildren)1434 {1435 nesting++;1436 }1437 }1438 }1439 return data;1440 }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 *);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 }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 else1506 t->type = TYPE_union;1508 Struct *s = (Struct *)calloc(sizeof(Struct), 1);1509 t->structure = s;1510 elfAddType(t, unit, offset);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);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 else1604 unit->functions = fnc;1605 unit->lastFunction = fnc;1606 }1607 break;1608 }1609 case DW_TAG_inheritance:1610 // TODO: add support1611 data = elfSkipData(data, abbr, unit->abbrevs);1612 break;1613 CASE_TYPE_TAG:1614 // skip types... parsed only when used1615 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);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);1674 t->type = TYPE_pointer;1676 elfAddType(t, unit, offset);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);1705 t->type = TYPE_reference;1707 elfAddType(t, unit, offset);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;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;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);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);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 else1902 f->args = o;1903 lastVar = o;1904 break;1905 }1906 case DW_TAG_unspecified_parameters:1907 // no use in the debugger yet1908 data = elfSkipData(data, abbr, unit->abbrevs);1909 break;1910 CASE_TYPE_TAG:1911 // skip types... parsed only when used1912 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);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);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: // ignore1983 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 }2016 Type *elfParseType(CompileUnit *unit, u32 offset)2017 {2018 Type *t = unit->types;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;2040 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);2042 elfParseType(data, offset, abbrev, unit, &type);2043 return type;2044 }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;2053 if (!abbrevNum)2054 {2055 return;2056 }2058 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);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 // todo2093 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 }2104 u8 *elfParseObject(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,2105 Object **object)2106 {2107 Object *o = (Object *)calloc(sizeof(Object), 1);2109 o->next = NULL;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 }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;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 now2180 break;2181 default:2182 fprintf(stderr, "Unknown block attribute %02x\n", attr->name);2183 break;2184 }2185 }2187 if (abbrev->hasChildren)2188 {2189 int nesting = 1;2191 while (nesting)2192 {2193 u32 abbrevNum = elfReadLEB128(data, &bytes);2194 data += bytes;2196 if (!abbrevNum)2197 {2198 nesting--;2199 continue;2200 }2202 abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);2204 switch (abbrev->tag)2205 {2206 CASE_TYPE_TAG: // types only parsed when used2207 case DW_TAG_label: // not needed2208 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 else2222 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 else2238 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 }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;2265 if (!abbrevNum)2266 {2267 return;2268 }2270 ELFAbbrev *abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);2272 for (int i = 0; i < abbrev->numAttrs; i++)2273 {2274 ELFAttr *attr = &abbrev->attrs[i];2275 data = elfReadAttribute(data, attr);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 }2331 return;2332 }2334 u8 *elfParseFunction(u8 *data, ELFAbbrev *abbrev, CompileUnit *unit,2335 Function **f)2336 {2337 Function *func = (Function *)calloc(sizeof(Function), 1);2338 *f = func;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 }2408 if (declaration)2409 {2410 elfCleanUp(func);2411 free(func);2412 *f = NULL;2414 while (1)2415 {2416 u32 abbrevNum = elfReadLEB128(data, &bytes);2417 data += bytes;2419 if (!abbrevNum)2420 {2421 return data;2422 }2424 abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);2426 data = elfSkipData(data, abbrev, unit->abbrevs);2427 }2428 }2430 if (abbrev->hasChildren)2431 {2432 int nesting = 1;2433 Object *lastParam = NULL;2434 Object *lastVar = NULL;2436 while (nesting)2437 {2438 u32 abbrevNum = elfReadLEB128(data, &bytes);2439 data += bytes;2441 if (!abbrevNum)2442 {2443 nesting--;2444 continue;2445 }2447 abbrev = elfGetAbbrev(unit->abbrevs, abbrevNum);2449 switch (abbrev->tag)2450 {2451 CASE_TYPE_TAG: // no need to parse types. only parsed when used2452 case DW_TAG_label: // not needed2453 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 else2464 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 else2481 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 else2492 func->variables = o;2493 lastVar = o;2494 break;2495 }2496 case DW_TAG_unspecified_parameters:2497 case DW_TAG_inlined_subroutine:2498 {2499 // todo2500 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 }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 }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);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 }2538 if (abbrev->hasChildren)2539 {2540 int nesting = 1;2541 while (nesting)2542 {2543 u32 abbrevNum = elfReadLEB128(data, &bytes);2544 data += bytes;2546 if (!abbrevNum)2547 {2548 nesting--;2549 continue;2550 }2552 abbrev = elfGetAbbrev(abbrevs, abbrevNum);2554 fprintf(stderr, "Unknown TAG %02x\n", abbrev->tag);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 }2563 if (abbrev->hasChildren)2564 {2565 nesting++;2566 }2567 }2568 }2569 // }2570 return data;2571 }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 else2593 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 else2608 unit->variables = var;2609 lastObj = var;2610 break;2611 }2612 default:2613 data = elfParseUnknownData(data, abbrev, unit->abbrevs);2614 break;2615 }2617 abbrevNum = elfReadLEB128(data, &bytes);2618 data += bytes;2619 }2620 return data;2621 }2623 CompileUnit *elfParseCompUnit(u8 *data, u8 *abbrevData)2624 {2625 int bytes;2626 u8 *top = data;2628 u32 length = elfRead4Bytes(data);2629 data += 4;2631 u16 version = elfRead2Bytes(data);2632 data += 2;2634 u32 offset = elfRead4Bytes(data);2635 data += 4;2637 u8 addrSize = *data++;2639 if (version != 2)2640 {2641 fprintf(stderr, "Unsupported debugging information version %d\n", version);2642 return NULL;2643 }2645 if (addrSize != 4)2646 {2647 fprintf(stderr, "Unsupported address size %d\n", addrSize);2648 return NULL;2649 }2651 ELFAbbrev **abbrevs = elfReadAbbrevs(abbrevData, offset);2653 u32 abbrevNum = elfReadLEB128(data, &bytes);2654 data += bytes;2656 ELFAbbrev *abbrev = elfGetAbbrev(abbrevs, abbrevNum);2658 CompileUnit *unit = (CompileUnit *)calloc(sizeof(CompileUnit), 1);2659 unit->top = top;2660 unit->length = length;2661 unit->abbrevs = abbrevs;2662 unit->next = NULL;2664 elfCurrentUnit = unit;2666 int i;2668 for (i = 0; i < abbrev->numAttrs; i++)2669 {2670 ELFAttr *attr = &abbrev->attrs[i];2671 data = elfReadAttribute(data, attr);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 // ignore2692 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 }2703 if (abbrev->hasChildren)2704 elfParseCompileUnitChildren(data, unit);2706 return unit;2707 }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 }2718 data = elfReadSection(data, sh);2719 u8 *end = data + READ32LE(&sh->size);2721 int max = 4;2722 ARanges *ranges = (ARanges *)calloc(sizeof(ARanges), 4);2724 int index = 0;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 above2737 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 }2765 void elfReadSymtab(u8 *data)2766 {2767 ELFSectionHeader *sh = elfGetSectionByName(".symtab");2768 int table = READ32LE(&sh->link);2770 char *strtable = (char *)elfReadSection(data, elfGetSectionByNumber(table));2772 ELFSymbol *symtab = (ELFSymbol *)elfReadSection(data, sh);2774 int count = READ32LE(&sh->size) / sizeof(ELFSymbol);2775 elfSymbolsCount = 0;2777 elfSymbols = (Symbol *)malloc(sizeof(Symbol)*count);2779 int i;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;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;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 }2819 bool elfReadProgram(ELFHeader *eh, u8 *data, int& size, bool parseDebug)2820 {2821 int count = READ16LE(&eh->e_phnum);2822 int i;2824 if (READ32LE(&eh->e_entry) == 0x2000000)2825 cpuIsMultiBoot = true;2827 // read program headers... should probably move this code down2828 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 }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 else2853 {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 }2865 char *stringTable = NULL;2867 // read section headers2868 p = data + READ32LE(&eh->e_shoff);2869 count = READ16LE(&eh->e_shnum);2871 ELFSectionHeader **sh = (ELFSectionHeader * *)2872 malloc(sizeof(ELFSectionHeader *) * count);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 }2882 if (READ16LE(&eh->e_shstrndx) != 0)2883 {2884 stringTable = (char *)elfReadSection(data,2885 sh[READ16LE(&eh->e_shstrndx)]);2886 }2888 elfSectionHeaders = sh;2889 elfSectionHeadersStringTable = stringTable;2890 elfSectionHeadersCount = count;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 section2899 {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 else2911 {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 }2924 if (parseDebug)2925 {2926 fprintf(stderr, "Parsing debug info\n");2928 ELFSectionHeader *dbgHeader = elfGetSectionByName(".debug_info");2929 if (dbgHeader == NULL)2930 {2931 fprintf(stderr, "Cannot find debug information\n");2932 goto end;2933 }2935 ELFSectionHeader *h = elfGetSectionByName(".debug_abbrev");2936 if (h == NULL)2937 {2938 fprintf(stderr, "Cannot find abbreviation table\n");2939 goto end;2940 }2942 elfDebugInfo = (DebugInfo *)calloc(sizeof(DebugInfo), 1);2943 u8 *abbrevdata = elfReadSection(data, h);2945 h = elfGetSectionByName(".debug_str");2947 if (h == NULL)2948 elfDebugStrings = NULL;2949 else2950 elfDebugStrings = (char *)elfReadSection(data, h);2952 u8 *debugdata = elfReadSection(data, dbgHeader);2954 elfDebugInfo->debugdata = data;2955 elfDebugInfo->infodata = debugdata;2957 u32 total = READ32LE(&dbgHeader->size);2958 u8 *end = debugdata + total;2959 u8 *ddata = debugdata;2961 CompileUnit *last = NULL;2962 CompileUnit *unit = NULL;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 else2972 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 }2998 elfSectionHeaders = NULL;2999 elfSectionHeadersStringTable = NULL;3000 elfSectionHeadersCount = 0;3002 return true;3003 }3005 extern bool8 parseDebug;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);3016 ELFHeader *header = (ELFHeader *)elfFileData;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 }3028 if (!elfReadProgram(header, elfFileData, siz, parseDebug))3029 {3030 free(elfFileData);3031 elfFileData = NULL;3032 return false;3033 }3035 return true;3036 }3038 void elfCleanUp(Object *o)3039 {3040 free(o->location);3041 }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 }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 }3065 void elfCleanUp(ELFAbbrev **abbrevs)3066 {3067 for (int i = 0; i < 121; i++)3068 {3069 ELFAbbrev *abbrev = abbrevs[i];3071 while (abbrev)3072 {3073 free(abbrev->attrs);3074 ELFAbbrev *next = abbrev->next;3075 free(abbrev);3077 abbrev = next;3078 }3079 }3080 }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 do3131 }3132 }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 }3170 void elfCleanUp()3171 {3172 CompileUnit *comp = elfCompileUnits;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;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 }3201 if (elfFdes)3202 {3203 if (elfFdeCount)3204 {3205 for (int i = 0; i < elfFdeCount; i++)3206 free(elfFdes[i]);3207 }3208 free(elfFdes);3210 elfFdes = NULL;3211 elfFdeCount = 0;3212 }3214 ELFcie *cie = elfCies;3215 while (cie)3216 {3217 ELFcie *next = cie->next;3218 free(cie);3219 cie = next;3220 }3221 elfCies = NULL;3223 if (elfFileData)3224 {3225 free(elfFileData);3226 elfFileData = NULL;3227 }3228 }