use of org.jf.dexlib2.builder.BuilderInstruction in project atlas by alibaba.
the class PatchMethodTool method modifyMethodAndFix.
private static MethodImplementation modifyMethodAndFix(@Nonnull MethodImplementation implementation, Method method) {
MutableMethodImplementation mutableImplementation = new MutableMethodImplementation(implementation);
System.out.println(mutableImplementation.getRegisterCount());
List<BuilderInstruction> instructions = mutableImplementation.getInstructions();
mutableImplementation.addInstruction(0, new BuilderInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference("AndFix:" + method.getDefiningClass().replace("/", "."))));
mutableImplementation.addInstruction(1, new BuilderInstruction35c(Opcode.INVOKE_STATIC, 1, 0, 0, 0, 0, 0, new ImmutableMethodReference("Landroid/util/Log;", "e", Lists.newArrayList("Ljava/lang/String;", "Ljava/lang/String;"), "I")));
return mutableImplementation;
}
use of org.jf.dexlib2.builder.BuilderInstruction in project atlas by alibaba.
the class PatchMethodTool method modifyMethodTpatch.
private static MethodImplementation modifyMethodTpatch(@Nonnull MethodImplementation implementation, Method method) {
MutableMethodImplementation mutableImplementation = new MutableMethodImplementation(implementation);
System.out.println(mutableImplementation.getRegisterCount());
List<BuilderInstruction> instructions = mutableImplementation.getInstructions();
boolean isModified = false;
for (int i = 0; i < instructions.size(); i++) {
isModified = false;
if (instructions.get(i).getOpcode() == Opcode.INVOKE_DIRECT) {
if (!isModified) {
mutableImplementation.addInstruction(i++, new BuilderInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference("tpatch:" + method.getDefiningClass().replace("/", "."))));
mutableImplementation.addInstruction(i++, new BuilderInstruction35c(Opcode.INVOKE_STATIC, 1, 0, 0, 0, 0, 0, new ImmutableMethodReference("Landroid/util/Log;", "e", Lists.newArrayList("Ljava/lang/String;", "Ljava/lang/String;"), "I")));
isModified = true;
break;
}
}
// mutableImplementation.addInstruction(instructions.get(i));
}
return mutableImplementation;
}
use of org.jf.dexlib2.builder.BuilderInstruction in project soot by Sable.
the class DexPrinter method insertIntermediateJump.
/**
* Creates an intermediate jump instruction between the original jump
* instruction and its target
*
* @param targetInsPos
* The jump target index
* @param jumpInsPos
* The position of the jump instruction
* @param stmtV
* The statement visitor used for constructing the instructions
* @param instructions
* The list of Dalvik instructions
* @param labelAssigner
* The label assigner to be used for creating new labels
*/
private void insertIntermediateJump(int targetInsPos, int jumpInsPos, StmtVisitor stmtV, List<BuilderInstruction> instructions, LabelAssigner labelAssigner) {
// Get the original jump instruction
BuilderInstruction originalJumpInstruction = instructions.get(jumpInsPos);
Insn originalJumpInsn = stmtV.getInsnForInstruction(originalJumpInstruction);
if (originalJumpInsn == null)
return;
if (!(originalJumpInsn instanceof InsnWithOffset))
throw new RuntimeException("Unexpected jump instruction target");
InsnWithOffset offsetInsn = (InsnWithOffset) originalJumpInsn;
// If this is goto instruction, we can just replace it
if (originalJumpInsn instanceof Insn10t) {
if (originalJumpInsn.getOpcode() == Opcode.GOTO) {
Insn30t newJump = new Insn30t(Opcode.GOTO_32);
newJump.setTarget(((Insn10t) originalJumpInsn).getTarget());
BuilderInstruction newJumpInstruction = newJump.getRealInsn(labelAssigner);
instructions.remove(jumpInsPos);
instructions.add(jumpInsPos, newJumpInstruction);
stmtV.fakeNewInsn(stmtV.getStmtForInstruction(originalJumpInstruction), newJump, newJumpInstruction);
return;
}
}
// Find a position where we can jump to
int distance = Math.max(targetInsPos, jumpInsPos) - Math.min(targetInsPos, jumpInsPos);
if (distance == 0)
return;
int newJumpIdx = Math.min(targetInsPos, jumpInsPos) + (distance / 2);
int sign = (int) Math.signum(targetInsPos - jumpInsPos);
// label may otherwise be attached to the wrong statement
do {
Stmt newStmt = stmtV.getStmtForInstruction(instructions.get(newJumpIdx));
Stmt prevStmt = newJumpIdx > 0 ? stmtV.getStmtForInstruction(instructions.get(newJumpIdx - 1)) : null;
if (newStmt == null || newStmt == prevStmt) {
newJumpIdx -= sign;
if (newJumpIdx < 0 || newJumpIdx >= instructions.size())
throw new RuntimeException("No position for inserting intermediate " + "jump instruction found");
} else
break;
} while (true);
// Create a jump instruction from the middle to the end
NopStmt nop = Jimple.v().newNopStmt();
Insn30t newJump = new Insn30t(Opcode.GOTO_32);
newJump.setTarget(stmtV.getStmtForInstruction(instructions.get(targetInsPos)));
BuilderInstruction newJumpInstruction = newJump.getRealInsn(labelAssigner);
instructions.add(newJumpIdx, newJumpInstruction);
stmtV.fakeNewInsn(nop, newJump, newJumpInstruction);
// We have added something, so we need to fix indices
if (newJumpIdx <= jumpInsPos)
jumpInsPos++;
if (newJumpIdx <= targetInsPos)
targetInsPos++;
// Jump from the original instruction to the new one in the middle
offsetInsn.setTarget(nop);
BuilderInstruction replacementJumpInstruction = offsetInsn.getRealInsn(labelAssigner);
assert instructions.get(jumpInsPos) == originalJumpInstruction;
instructions.remove(jumpInsPos);
instructions.add(jumpInsPos, replacementJumpInstruction);
stmtV.fakeNewInsn(stmtV.getStmtForInstruction(originalJumpInstruction), originalJumpInsn, replacementJumpInstruction);
// Our indices are still fine, because we just replaced something
Stmt afterNewJump = stmtV.getStmtForInstruction(instructions.get(newJumpIdx + 1));
// Make the original control flow jump around the new artificial jump
// instruction
Insn10t jumpAround = new Insn10t(Opcode.GOTO);
jumpAround.setTarget(afterNewJump);
BuilderInstruction jumpAroundInstruction = jumpAround.getRealInsn(labelAssigner);
instructions.add(newJumpIdx, jumpAroundInstruction);
stmtV.fakeNewInsn(Jimple.v().newNopStmt(), jumpAround, jumpAroundInstruction);
}
use of org.jf.dexlib2.builder.BuilderInstruction in project soot by Sable.
the class DexPrinter method fixLongJumps.
/**
* Fixes long jumps that exceed the maximum distance for the respective jump
* type
*
* @param instructions
* The list of generated dalvik instructions
* @param labelAssigner
* The label assigner that maps statements to labels
* @param stmtV
* The statement visitor used to produce the dalvik instructions
*/
private void fixLongJumps(List<BuilderInstruction> instructions, LabelAssigner labelAssigner, StmtVisitor stmtV) {
// Only construct the maps once and update them afterwards
Map<Instruction, Integer> instructionsToIndex = new HashMap<Instruction, Integer>();
List<Integer> instructionsToOffsets = new ArrayList<Integer>();
Map<Label, Integer> labelsToOffsets = new HashMap<Label, Integer>();
Map<Label, Integer> labelsToIndex = new HashMap<Label, Integer>();
boolean hasChanged;
l0: do {
// Look for changes anew every time
hasChanged = false;
instructionsToOffsets.clear();
// Build a mapping between instructions and offsets
{
int offset = 0;
int idx = 0;
for (BuilderInstruction bi : instructions) {
instructionsToIndex.put(bi, idx);
instructionsToOffsets.add(offset);
Stmt origStmt = stmtV.getStmtForInstruction(bi);
if (origStmt != null) {
Label lbl = labelAssigner.getLabelUnsafe(origStmt);
if (lbl != null) {
labelsToOffsets.put(lbl, offset);
labelsToIndex.put(lbl, idx);
}
}
offset += (bi.getFormat().size / 2);
idx++;
}
}
// Look for references to labels
for (int j = 0; j < instructions.size(); j++) {
BuilderInstruction bj = instructions.get(j);
if (bj instanceof BuilderOffsetInstruction) {
BuilderOffsetInstruction boj = (BuilderOffsetInstruction) bj;
// Compute the distance between the instructions
Insn jumpInsn = stmtV.getInsnForInstruction(boj);
if (jumpInsn instanceof InsnWithOffset) {
InsnWithOffset offsetInsn = (InsnWithOffset) jumpInsn;
Integer targetOffset = labelsToOffsets.get(boj.getTarget());
if (targetOffset == null)
continue;
int distance = instructionsToOffsets.get(j) - targetOffset;
if (Math.abs(distance) > offsetInsn.getMaxJumpOffset()) {
// We need intermediate jumps
insertIntermediateJump(labelsToIndex.get(boj.getTarget()), j, stmtV, instructions, labelAssigner);
hasChanged = true;
continue l0;
}
}
}
}
} while (hasChanged);
}
use of org.jf.dexlib2.builder.BuilderInstruction in project tinker by Tencent.
the class BuilderMutableMethodImplementation method fixInstructions.
private void fixInstructions() {
HashSet<MethodLocation> payloadLocations = Sets.newHashSet();
for (MethodLocation location : instructionList) {
BuilderInstruction instruction = location.instruction;
if (instruction != null) {
switch(instruction.getOpcode()) {
case SPARSE_SWITCH:
case PACKED_SWITCH:
{
MethodLocation targetLocation = ((BuilderOffsetInstruction) instruction).getTarget().getLocation();
BuilderInstruction targetInstruction = targetLocation.instruction;
if (targetInstruction == null) {
throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d points to the end of the method.", location.codeAddress, location.index));
}
if (targetInstruction.getOpcode() == Opcode.NOP) {
targetInstruction = getFirstNonNop(targetLocation.index + 1);
}
if (targetInstruction == null || !(targetInstruction instanceof BuilderSwitchPayload)) {
throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d does not refer to a payload instruction.", location.codeAddress, location.index));
}
if ((instruction.opcode == Opcode.PACKED_SWITCH && targetInstruction.getOpcode() != Opcode.PACKED_SWITCH_PAYLOAD) || (instruction.opcode == Opcode.SPARSE_SWITCH && targetInstruction.getOpcode() != Opcode.SPARSE_SWITCH_PAYLOAD)) {
throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d refers to the wrong type of payload instruction.", location.codeAddress, location.index));
}
if (!payloadLocations.add(targetLocation)) {
throw new IllegalStateException("Multiple switch instructions refer to the same payload. " + "This is not currently supported. Please file a bug :)");
}
((BuilderSwitchPayload) targetInstruction).referrer = location;
break;
}
default:
{
break;
}
}
}
}
boolean madeChanges;
do {
madeChanges = false;
for (int index = 0; index < instructionList.size(); index++) {
MethodLocation location = instructionList.get(index);
BuilderInstruction instruction = location.instruction;
if (instruction != null) {
switch(instruction.getOpcode()) {
case GOTO:
{
int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
if (offset < Byte.MIN_VALUE || offset > Byte.MAX_VALUE) {
BuilderOffsetInstruction replacement;
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
} else {
replacement = new BuilderInstruction20t(Opcode.GOTO_16, ((BuilderOffsetInstruction) instruction).getTarget());
}
replaceInstruction(location.index, replacement);
madeChanges = true;
}
break;
}
case GOTO_16:
{
int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
BuilderOffsetInstruction replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
replaceInstruction(location.index, replacement);
madeChanges = true;
}
break;
}
case SPARSE_SWITCH_PAYLOAD:
case PACKED_SWITCH_PAYLOAD:
if (((BuilderSwitchPayload) instruction).referrer == null) {
// if the switch payload isn't referenced, just remove it
removeInstruction(index);
index--;
madeChanges = true;
break;
}
// intentional fall-through
case ARRAY_PAYLOAD:
{
if ((location.codeAddress & 0x01) != 0) {
int previousIndex = location.index - 1;
MethodLocation previousLocation = instructionList.get(previousIndex);
Instruction previousInstruction = previousLocation.instruction;
assert previousInstruction != null;
if (previousInstruction.getOpcode() == Opcode.NOP) {
removeInstruction(previousIndex);
index--;
} else {
addInstruction(location.index, new BuilderInstruction10x(Opcode.NOP));
index++;
}
madeChanges = true;
}
break;
}
default:
{
break;
}
}
}
}
} while (madeChanges);
fixInstructions = false;
}
Aggregations