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