/* If has_instr_jmp_targets is true, this routine trashes the note field * of each instr_t to store the offset in order to properly encode * the relative pc for an instr_t jump target */ byte * instrlist_encode_to_copy(dcontext_t *dcontext, instrlist_t *ilist, byte *copy_pc, byte *final_pc, byte *max_pc, bool has_instr_jmp_targets) { instr_t *inst; int len = 0; #ifdef ARM /* XXX i#1734: reset encode state to avoid any stale encode state * or dangling pointer. */ if (instr_get_isa_mode(instrlist_first(ilist)) == DR_ISA_ARM_THUMB) encode_reset_it_block(dcontext); #endif /* Do an extra pass over the instrlist so we can determine if an instr opnd * was erroneously used with has_instr_jmp_targets = false. */ DOCHECK(2, { if (!has_instr_jmp_targets) { for (inst = instrlist_first(ilist); inst; inst = instr_get_next(inst)) { if (TEST(INSTR_OPERANDS_VALID, (inst)->flags)) { int i; for (i = 0; i < instr_num_srcs(inst); ++i) { CLIENT_ASSERT(!opnd_is_instr(instr_get_src(inst, i)), "has_instr_jmp_targets was unset " "but an instr opnd was found"); } } } } });
instrlist_t* instrlist_clone(dcontext_t *dcontext, instrlist_t *old) { instr_t *inst, *copy; instrlist_t *newlist = instrlist_create(dcontext); inst = instrlist_first(old); while (inst != NULL) { copy = instr_clone(dcontext, inst); /* to copy instr targets we temporarily clobber note field */ instr_set_note(inst, (void *)copy); instrlist_append(newlist, copy); inst = instr_get_next(inst); } /* Fix up instr src if it is an instr and restore note field */ /* Note: we do not allows instruction update code cache, * which is very dangerous. * So we do not support instr as dst opnd and won't fix up here if any. */ for (inst = instrlist_first(old), copy = instrlist_first(newlist); inst != NULL && copy != NULL; inst = instr_get_next(inst), copy = instr_get_next(copy)) { int i; for (i = 0; i < inst->num_srcs; i++) { instr_t *tgt; opnd_t op = instr_get_src(copy, i); if (!opnd_is_instr(op)) continue; CLIENT_ASSERT(opnd_get_instr(op) != NULL, "instrlist_clone: NULL instr operand"); tgt = (instr_t *) instr_get_note(opnd_get_instr(op)); CLIENT_ASSERT(tgt != NULL, "instrlist_clone: operand instr not in instrlist"); if (opnd_is_far_instr(op)) { instr_set_src(copy, i, opnd_create_far_instr (opnd_get_segment_selector(op), tgt)); } else instr_set_src(copy, i, opnd_create_instr(tgt)); } } for (inst = instrlist_first(old), copy = instrlist_first(newlist); inst != NULL && copy != NULL; inst = instr_get_next(inst), copy = instr_get_next(copy)) { /* restore note field */ instr_set_note(inst, instr_get_note(copy)); } #ifdef CLIENT_INTERFACE newlist->fall_through_bb = old->fall_through_bb; #endif return newlist; }
/* To support multiple non-meta ctis in app2app phase, we mark them meta * before handing to DR to satisfy its bb constraints */ static void drmgr_fix_app_ctis(void *drcontext, instrlist_t *bb) { instr_t *inst; for (inst = instrlist_first(bb); inst != NULL; inst = instr_get_next(inst)) { /* Any CTI with an instr target must have an intra-bb target and thus * we assume it should not be mangled. We mark it meta. */ if (instr_ok_to_mangle(inst) && instr_is_cti(inst) && opnd_is_instr(instr_get_target(inst))) { instr_set_ok_to_mangle(inst, false); /* instrumentation passes should set the translation field * so other passes can see what app pc these app instrs * correspond to: but DR complains if there's a meta instr * w/ a translation but no restore_state event */ instr_set_translation(inst, NULL); } } }