/* iterate basic block to find a dead register */ static reg_id_t bb_find_dead_reg(instrlist_t *ilist) { instr_t *instr; int i; bool reg_is_read[DR_NUM_GPR_REGS] = { false,}; for (instr = instrlist_first(ilist); instr != NULL; instr = instr_get_next(instr)) { if (instr_is_syscall(instr) || instr_is_interrupt(instr)) return DR_REG_NULL; for (i = 0; i < DR_NUM_GPR_REGS; i++) { if (!reg_is_read[i] && instr_reads_from_reg(instr, (reg_id_t)(DR_REG_START_GPR + i))) { reg_is_read[i] = true; } if (!reg_is_read[i] && instr_writes_to_exact_reg(instr, (reg_id_t)(DR_REG_START_GPR + i))) { return (reg_id_t)(DR_REG_START_GPR + i); } #ifdef X64 /* in x64, update on 32-bit register kills the whole register */ if (!reg_is_read[i] && instr_writes_to_exact_reg(instr, reg_64_to_32 ((reg_id_t)(DR_REG_START_GPR + i)))) { return (reg_id_t)(DR_REG_START_GPR + i); } #endif } } return DR_REG_NULL; }
DR_EXPORT bool drx_aflags_are_dead(instr_t *where) { instr_t *instr; uint flags; for (instr = where; instr != NULL; instr = instr_get_next(instr)) { /* we treat syscall/interrupt as aflags read */ if (instr_is_syscall(instr) || instr_is_interrupt(instr)) return false; flags = instr_get_arith_flags(instr, DR_QUERY_DEFAULT); if (TESTANY(EFLAGS_READ_ARITH, flags)) return false; if (TESTALL(EFLAGS_WRITE_ARITH, flags)) return true; if (instr_is_cti(instr)) { if (instr_is_app(instr) && (instr_is_ubr(instr) || instr_is_call_direct(instr))) { instr_t *next = instr_get_next(instr); opnd_t tgt = instr_get_target(instr); /* continue on elision */ if (next != NULL && instr_is_app(next) && opnd_is_pc(tgt) && opnd_get_pc(tgt) == instr_get_app_pc(next)) continue; } /* unknown target, assume aflags is live */ return false; } } return false; }