static int get_dynamic_tag(Context * ctx, ELF_File * file, int tag, ContextAddress * addr) { unsigned i, j; for (i = 1; i < file->section_cnt; i++) { ELF_Section * sec = file->sections + i; if (sec->size == 0) continue; if (sec->name == NULL) continue; if (strcmp(sec->name, ".dynamic") == 0) { ContextAddress sec_addr = elf_map_to_run_time_address(ctx, file, sec, (ContextAddress)sec->addr); if (errno) return -1; if (elf_load(sec) < 0) return -1; if (file->elf64) { unsigned cnt = (unsigned)(sec->size / sizeof(Elf64_Dyn)); for (j = 0; j < cnt; j++) { Elf64_Dyn dyn = *((Elf64_Dyn *)sec->data + j); if (file->byte_swap) SWAP(dyn.d_tag); if (dyn.d_tag == DT_NULL) break; if (dyn.d_tag == tag) { if (context_read_mem(ctx, sec_addr + j * sizeof(dyn), &dyn, sizeof(dyn)) < 0) return -1; if (file->byte_swap) { SWAP(dyn.d_tag); SWAP(dyn.d_un.d_ptr); } if (dyn.d_tag != tag) continue; if (addr != NULL) *addr = (ContextAddress)dyn.d_un.d_ptr; return 0; } } } else { unsigned cnt = (unsigned)(sec->size / sizeof(Elf32_Dyn)); for (j = 0; j < cnt; j++) { Elf32_Dyn dyn = *((Elf32_Dyn *)sec->data + j); if (file->byte_swap) SWAP(dyn.d_tag); if (dyn.d_tag == DT_NULL) break; if (dyn.d_tag == tag) { if (context_read_mem(ctx, sec_addr + j * sizeof(dyn), &dyn, sizeof(dyn)) < 0) return -1; if (file->byte_swap) { SWAP(dyn.d_tag); SWAP(dyn.d_un.d_ptr); } if (dyn.d_tag != tag) continue; if (addr != NULL) *addr = (ContextAddress)dyn.d_un.d_ptr; return 0; } } } } } errno = ENOENT; return -1; }
static void call_client(Context * ctx, CompUnit * unit, LineNumbersState * state, LineNumbersState * code_next, LineNumbersState * text_next, ContextAddress state_addr, LineNumbersCallBack * client, void * args) { CodeArea area; FileInfo * file_info = unit->mFiles + state->mFile; LineNumbersState * text_next_stmt = get_next_statement(unit, text_next); if (code_next == NULL) return; assert(state->mSection == code_next->mSection); memset(&area, 0, sizeof(area)); area.start_line = state->mLine; area.start_column = state->mColumn; area.end_line = text_next ? text_next->mLine : state->mLine + 1; area.end_column = text_next ? text_next->mColumn : 0; area.directory = unit->mDir; if (state->mFileName != NULL) { area.file = state->mFileName; } else if (is_absolute_path(file_info->mName) || file_info->mDir == NULL) { area.file = file_info->mName; } else if (is_absolute_path(file_info->mDir)) { area.directory = file_info->mDir; area.file = file_info->mName; } else { char buf[FILE_PATH_SIZE]; snprintf(buf, sizeof(buf), "%s/%s", file_info->mDir, file_info->mName); area.file = state->mFileName = loc_strdup(buf); } area.file_mtime = file_info->mModTime; area.file_size = file_info->mSize; area.start_address = state_addr; area.end_address = code_next->mAddress - state->mAddress + state_addr; if (text_next != NULL) { if (text_next->mSection == state->mSection) { area.next_address = text_next->mAddress - state->mAddress + state_addr; } else { ELF_Section * s = NULL; if (text_next->mSection) s = unit->mFile->sections + text_next->mSection; area.next_address = elf_map_to_run_time_address(ctx, unit->mFile, s, text_next->mAddress); } } if (text_next_stmt != NULL) { if (text_next_stmt->mSection == state->mSection) { area.next_stmt_address = text_next_stmt->mAddress - state->mAddress + state_addr; } else { ELF_Section * s = NULL; if (text_next_stmt->mSection) s = unit->mFile->sections + text_next_stmt->mSection; area.next_stmt_address = elf_map_to_run_time_address(ctx, unit->mFile, s, text_next_stmt->mAddress); } } area.isa = state->mISA; area.is_statement = (state->mFlags & LINE_IsStmt) != 0; area.basic_block = (state->mFlags & LINE_BasicBlock) != 0; area.prologue_end = (state->mFlags & LINE_PrologueEnd) != 0; area.epilogue_begin = (state->mFlags & LINE_EpilogueBegin) != 0; area.op_index = state->mOpIndex; area.discriminator = state->mDiscriminator; client(&area, args); }
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 int get_global_symbol_address(Context * ctx, ELF_File * file, const char * name, ContextAddress * addr) { unsigned i, j; for (i = 1; i < file->section_cnt; i++) { ELF_Section * sec = file->sections + i; if (sec->size == 0) continue; if (sec->type == SHT_SYMTAB) { ELF_Section * str = NULL; if (sec->link == 0 || sec->link >= file->section_cnt) { errno = EINVAL; return -1; } str = file->sections + sec->link; if (elf_load(sec) < 0) return -1; if (elf_load(str) < 0) return -1; if (file->elf64) { unsigned cnt = (unsigned)(sec->size / sizeof(Elf64_Sym)); for (j = 0; j < cnt; j++) { Elf64_Sym sym = *((Elf64_Sym *)sec->data + j); if (ELF64_ST_BIND(sym.st_info) != STB_GLOBAL) continue; if (file->byte_swap) SWAP(sym.st_name); if (sym_name_cmp((char *)str->data + sym.st_name, name) != 0) continue; switch (ELF64_ST_TYPE(sym.st_info)) { case STT_NOTYPE: /* Check if the NOTYPE symbol is for a section allocated in memory */ if (file->byte_swap) SWAP(sym.st_shndx); if (sym.st_shndx <= 0 || sym.st_shndx >= file->section_cnt || ((file->sections + sym.st_shndx)->flags & SHF_ALLOC) == 0) break; /* fall through */ case STT_OBJECT: case STT_FUNC: if (file->byte_swap) SWAP(sym.st_value); *addr = elf_map_to_run_time_address(ctx, file, NULL, (ContextAddress)sym.st_value); if (errno == 0) return 0; } } } else { unsigned cnt = (unsigned)(sec->size / sizeof(Elf32_Sym)); for (j = 0; j < cnt; j++) { Elf32_Sym sym = *((Elf32_Sym *)sec->data + j); if (ELF32_ST_BIND(sym.st_info) != STB_GLOBAL) continue; if (file->byte_swap) SWAP(sym.st_name); if (sym_name_cmp((char *)str->data + sym.st_name, name) != 0) continue; switch (ELF32_ST_TYPE(sym.st_info)) { case STT_NOTYPE: /* Check if the NOTYPE symbol is for a section allocated in memory */ if (file->byte_swap) SWAP(sym.st_shndx); if (sym.st_shndx <= 0 || sym.st_shndx >= file->section_cnt || ((file->sections + sym.st_shndx)->flags & SHF_ALLOC) == 0) break; /* fall through */ case STT_OBJECT: case STT_FUNC: if (file->byte_swap) SWAP(sym.st_value); *addr = elf_map_to_run_time_address(ctx, file, NULL, (ContextAddress)sym.st_value); if (errno == 0) return 0; } } } } } errno = ENOENT; return -1; }