static U8_T read_frame_data_pointer(U1_T encoding, ELF_Section ** sec, U8_T func_addr) { U8_T v = 0; U8_T pos; unsigned idx; ELF_File * file; if (encoding == EH_PE_omit) return 0; pos = dio_GetPos(); /* Decode the base or adjust the offset */ switch ((encoding >> 4) & 0x7) { case 0: case EH_PB_funcrel: v = func_addr; break; case EH_PB_pcrel: if (sec != NULL) { v = pos + rules.section->addr; } break; case EH_PB_datarel: if (sec != NULL) { v = rules.section->addr; } break; case EH_PB_textrel: if (sec != NULL && rules.text_section != NULL) { v = rules.text_section->addr; } break; case EH_PB_aligned: if ((pos % rules.address_size) != 0) dio_SetPos(pos + (rules.address_size - (pos % rules.address_size))); break; default: str_exception(ERR_INV_DWARF, "Unknown encoding of .eh_frame section pointers"); break; } /* Decode the value */ switch (encoding & 0xf) { case EH_PE_absptr: v += dio_ReadAddress(sec); break; case EH_PE_uleb128: v += dio_ReadU8LEB128(); break; case EH_PE_udata2: v += dio_ReadAddressX(sec, 2); break; case EH_PE_udata4: v += dio_ReadAddressX(sec, 4); break; case EH_PE_udata8: v += dio_ReadAddressX(sec, 8); break; case EH_PE_sleb128: v += dio_ReadS8LEB128(); break; case EH_PE_sdata2: v += (I2_T)dio_ReadAddressX(sec, 2); break; case EH_PE_sdata4: v += (I4_T)dio_ReadAddressX(sec, 4); break; case EH_PE_sdata8: v += (I8_T)dio_ReadAddressX(sec, 8); break; default: str_exception(ERR_INV_DWARF, "Unknown encoding of .eh_frame section pointers"); break; } if (encoding & EH_PE_indirect) { size_t size = rules.address_size; U8_T res = 0; file = rules.section->file; for (idx = 1; idx < file->section_cnt; idx++) { ELF_Section * sec = file->sections + idx; if ((sec->flags & SHF_ALLOC) == 0) continue; if (sec->addr <= v && sec->addr + sec->size >= v + size) { U1_T * p; size_t i; if (sec->data == NULL && elf_load(sec) < 0) exception(errno); p = (U1_T *)sec->data + (uintptr_t)(v - sec->addr); for (i = 0; i < size; i++) { res = (res << 8) | p[file->big_endian ? i : size - i - 1]; } break; } } v = res; } return v; }
static void add_dwarf_expression_commands(U8_T cmds_offs, U4_T cmds_size) { dio_EnterSection(NULL, rules.section, cmds_offs); while (dio_GetPos() < cmds_offs + cmds_size) { U1_T op = dio_ReadU1(); switch (op) { case OP_addr: { ELF_Section * section = NULL; U8_T lt_addr = dio_ReadAddress(§ion); ContextAddress rt_addr = elf_map_to_run_time_address( rules.ctx, rules.section->file, section, (ContextAddress)lt_addr); if (errno) str_exception(errno, "Cannot get object run-time address"); add_command(SFT_CMD_NUMBER)->args.num = rt_addr; } break; case OP_deref: { LocationExpressionCommand * cmd = add_command(SFT_CMD_RD_MEM); cmd->args.mem.size = rules.address_size; cmd->args.mem.big_endian = rules.reg_id_scope.big_endian; } break; case OP_deref_size: { LocationExpressionCommand * cmd = add_command(SFT_CMD_RD_MEM); cmd->args.mem.size = dio_ReadU1(); cmd->args.mem.big_endian = rules.reg_id_scope.big_endian; } break; case OP_const1u: add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU1(); break; case OP_const1s: add_command(SFT_CMD_NUMBER)->args.num = (I1_T)dio_ReadU1(); break; case OP_const2u: add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU2(); break; case OP_const2s: add_command(SFT_CMD_NUMBER)->args.num = (I2_T)dio_ReadU2(); break; case OP_const4u: add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU4(); break; case OP_const4s: add_command(SFT_CMD_NUMBER)->args.num = (I4_T)dio_ReadU4(); break; case OP_const8u: add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU8(); break; case OP_const8s: add_command(SFT_CMD_NUMBER)->args.num = (I8_T)dio_ReadU8(); break; case OP_constu: add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU8LEB128(); break; case OP_consts: add_command(SFT_CMD_NUMBER)->args.num = dio_ReadS8LEB128(); break; case OP_and: add_command(SFT_CMD_AND); break; case OP_minus: add_command(SFT_CMD_SUB); break; case OP_or: add_command(SFT_CMD_OR); break; case OP_plus: add_command(SFT_CMD_ADD); break; case OP_plus_uconst: add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU8LEB128(); add_command(SFT_CMD_ADD); break; case OP_ge: add_command(SFT_CMD_GE); break; case OP_gt: add_command(SFT_CMD_GT); break; case OP_le: add_command(SFT_CMD_LE); break; case OP_lt: add_command(SFT_CMD_LT); break; case OP_shl: add_command(SFT_CMD_SHL); break; case OP_lit0: case OP_lit1: case OP_lit2: case OP_lit3: case OP_lit4: case OP_lit5: case OP_lit6: case OP_lit7: case OP_lit8: case OP_lit9: case OP_lit10: case OP_lit11: case OP_lit12: case OP_lit13: case OP_lit14: case OP_lit15: case OP_lit16: case OP_lit17: case OP_lit18: case OP_lit19: case OP_lit20: case OP_lit21: case OP_lit22: case OP_lit23: case OP_lit24: case OP_lit25: case OP_lit26: case OP_lit27: case OP_lit28: case OP_lit29: case OP_lit30: case OP_lit31: add_command(SFT_CMD_NUMBER)->args.num = op - OP_lit0; break; case OP_reg0: case OP_reg1: case OP_reg2: case OP_reg3: case OP_reg4: case OP_reg5: case OP_reg6: case OP_reg7: case OP_reg8: case OP_reg9: case OP_reg10: case OP_reg11: case OP_reg12: case OP_reg13: case OP_reg14: case OP_reg15: case OP_reg16: case OP_reg17: case OP_reg18: case OP_reg19: case OP_reg20: case OP_reg21: case OP_reg22: case OP_reg23: case OP_reg24: case OP_reg25: case OP_reg26: case OP_reg27: case OP_reg28: case OP_reg29: case OP_reg30: case OP_reg31: { RegisterDefinition * def = get_reg_by_id(rules.ctx, op - OP_reg0, &rules.reg_id_scope); if (def == NULL) str_exception(errno, "Cannot read DWARF frame info"); add_command(SFT_CMD_RD_REG)->args.reg = def; } break; case OP_regx: { unsigned n = (unsigned)dio_ReadULEB128(); RegisterDefinition * def = get_reg_by_id(rules.ctx, n, &rules.reg_id_scope); if (def == NULL) str_exception(errno, "Cannot read DWARF frame info"); add_command(SFT_CMD_RD_REG)->args.reg = def; } break; case OP_breg0: case OP_breg1: case OP_breg2: case OP_breg3: case OP_breg4: case OP_breg5: case OP_breg6: case OP_breg7: case OP_breg8: case OP_breg9: case OP_breg10: case OP_breg11: case OP_breg12: case OP_breg13: case OP_breg14: case OP_breg15: case OP_breg16: case OP_breg17: case OP_breg18: case OP_breg19: case OP_breg20: case OP_breg21: case OP_breg22: case OP_breg23: case OP_breg24: case OP_breg25: case OP_breg26: case OP_breg27: case OP_breg28: case OP_breg29: case OP_breg30: case OP_breg31: { I8_T offs = dio_ReadS8LEB128(); RegisterDefinition * def = get_reg_by_id(rules.ctx, op - OP_breg0, &rules.reg_id_scope); if (def == NULL) str_exception(errno, "Cannot read DWARF frame info"); add_command(SFT_CMD_RD_REG)->args.reg = def; if (offs != 0) { add_command(SFT_CMD_NUMBER)->args.num = offs; add_command(SFT_CMD_ADD); } } break; case OP_bregx: { unsigned n = (unsigned)dio_ReadULEB128(); I8_T offs = dio_ReadS8LEB128(); RegisterDefinition * def = get_reg_by_id(rules.ctx, n, &rules.reg_id_scope); if (def == NULL) str_exception(errno, "Cannot read DWARF frame info"); add_command(SFT_CMD_RD_REG)->args.reg = def; if (offs != 0) { add_command(SFT_CMD_NUMBER)->args.num = offs; add_command(SFT_CMD_ADD); } } break; case OP_nop: break; default: trace(LOG_ALWAYS, "Unsupported DWARF expression op 0x%02x", op); str_exception(ERR_UNSUPPORTED, "Unsupported DWARF expression op"); } } }
static U8_T read_frame_data_pointer(U1_T encoding, ELF_Section ** sec) { U8_T v = 0; if (encoding != EH_PE_omit) { U8_T pos = dio_GetPos(); switch (encoding & 0xf) { case EH_PE_absptr: v = dio_ReadAddress(sec); break; case EH_PE_uleb128: v = dio_ReadU8LEB128(); break; case EH_PE_udata2: v = dio_ReadU2(); break; case EH_PE_udata4: v = dio_ReadU4(); break; case EH_PE_udata8: v = dio_ReadU8(); break; case EH_PE_sleb128: v = dio_ReadS8LEB128(); break; case EH_PE_sdata2: v = (I2_T)dio_ReadU2(); break; case EH_PE_sdata4: v = (I4_T)dio_ReadU4(); break; case EH_PE_sdata8: v = (I8_T)dio_ReadU8(); break; default: str_exception(ERR_INV_DWARF, "Unknown encoding of .eh_frame section pointers"); break; } if (v != 0 && sec != NULL) { switch ((encoding >> 4) & 0x7) { case 0: break; case EH_PB_pcrel: *sec = rules.section; v += rules.section->addr + pos; break; case EH_PB_datarel: *sec = rules.section; v += rules.section->addr; break; case EH_PB_textrel: case EH_PB_funcrel: case EH_PB_aligned: default: str_exception(ERR_INV_DWARF, "Unknown encoding of .eh_frame section pointers"); break; } if (encoding & EH_PE_indirect) { unsigned idx; ELF_File * file = rules.section->file; size_t size = rules.address_size; U8_T res = 0; for (idx = 1; idx < file->section_cnt; idx++) { ELF_Section * sec = file->sections + idx; if ((sec->flags & SHF_ALLOC) == 0) continue; if (sec->addr <= v && sec->addr + sec->size >= v + size) { U1_T * p; size_t i; if (sec->data == NULL && elf_load(sec) < 0) exception(errno); p = (U1_T *)sec->data + (uintptr_t)(v - sec->addr); for (i = 0; i < size; i++) { res = (res << 8) | p[file->big_endian ? i : size - i - 1]; } break; } } v = res; } } }