static void destroy_dyninst() { int i; for(i = 0; i < dyninst_index; i++) replace_opcode(dyninst[i].arch, dyninst[i].oldinst, dyninst[i].opcode1, dyninst[i].opcode2); }
void inline_sget(DexMethod* method, DexOpcodeField* opfield) { if (!validate_sget(method, opfield)) return; auto opcode = OPCODE_CONST; auto dest = opfield->dest(); auto field = resolve_field(opfield->field(), FieldSearch::Static); always_assert_log(field->is_concrete(), "Must be a concrete field"); auto value = field->get_static_value(); /* FIXME for sget_wide case */ uint32_t v = value != nullptr ? (uint32_t)value->value() : 0; auto newopcode = (new DexInstruction(opcode))->set_dest(dest)->set_literal(v); replace_opcode(method, opfield, newopcode); }
void inline_cheap_sget(DexMethod* method, DexOpcodeField* opfield) { if (!validate_sget(method, opfield)) return; auto dest = opfield->dest(); auto field = resolve_field(opfield->field(), FieldSearch::Static); always_assert_log(field->is_concrete(), "Must be a concrete field"); auto value = field->get_static_value(); /* FIXME for sget_wide case */ uint32_t v = value != nullptr ? (uint32_t)value->value() : 0; auto opcode = [&] { if ((v & 0xffff) == v) { return OPCODE_CONST_16; } else if ((v & 0xffff0000) == v) { return OPCODE_CONST_HIGH16; } always_assert_log(false, "Bad inline_cheap_sget queued up, can't fit to" " CONST_16 or CONST_HIGH16, bailing\n"); }(); auto newopcode = (new DexInstruction(opcode, 0))->set_dest(dest)->set_literal(v); replace_opcode(method, opfield, newopcode); }
static void update_dyninst() { int arch; char name[64]; zz_func newinst; zz_func oldinst; int opcode1; int opcode2; for(arch = 0; arch < GEN_ARCHCOUNT; arch++) { for(opcode1 = 0; opcode1 < 0x100 && dyninst_index < MAXDYNINST; opcode1++) { snprintf(name, sizeof(name), "%s%02X", prefix[arch], opcode1); newinst = HDL_FINDSYM(name); if(newinst) { oldinst = replace_opcode(arch, newinst, opcode1, -1); if(oldinst) { dyninst[dyninst_index].opcode1 = opcode1; dyninst[dyninst_index].opcode2 = -1; dyninst[dyninst_index].arch = arch; dyninst[dyninst_index].newinst = newinst; dyninst[dyninst_index].oldinst = oldinst; dyninst_index++; } } switch(opcode1) { case 0x01: case 0xa4: case 0xa6: case 0xb2: case 0xb3: case 0xb9: case 0xe4: case 0xe5: case 0xe6: case 0xa5: case 0xa7: case 0xc0: case 0xc2: case 0xc4: case 0xc6: case 0xc8: case 0xcc: case 0xe3: case 0xeb: case 0xec: case 0xed: for(opcode2 = 0; opcode2 < 0x100 && dyninst_index < MAXDYNINST; opcode2++) { snprintf(name, sizeof(name), "%s%02X%02X", prefix[arch], opcode1, opcode2); newinst = HDL_FINDSYM(name); if(newinst) { oldinst = replace_opcode(arch, newinst, opcode1, opcode2); if(oldinst) { dyninst[dyninst_index].opcode1 = opcode1; dyninst[dyninst_index].opcode2 = opcode2; dyninst[dyninst_index].arch = arch; dyninst[dyninst_index].newinst = newinst; dyninst[dyninst_index].oldinst = oldinst; dyninst_index++; } } } } } } }
void IRList::replace_opcode(IRInstruction* from, IRInstruction* to) { always_assert_log(!is_branch(to->opcode()), "You may want replace_branch instead"); replace_opcode(from, std::vector<IRInstruction*>{to}); }