@Override public void computeDataOffsets(DexBody body) { Debug.printDbg("compute data offset"); if (!(instruction instanceof Instruction31t)) throw new IllegalArgumentException( "Expected Instruction31t but got: " + instruction.getClass()); Instruction31t fillArrayInstr = (Instruction31t) instruction; int offset = fillArrayInstr.getCodeOffset(); int targetAddress = codeAddress + offset; Instruction referenceTable = body.instructionAtAddress(targetAddress).instruction; if (!(referenceTable instanceof ArrayPayload)) { throw new RuntimeException( "Address 0x" + Integer.toHexString(targetAddress) + " refers to an invalid PseudoInstruction (" + referenceTable.getClass() + ")."); } ArrayPayload arrayTable = (ArrayPayload) referenceTable; int numElements = arrayTable.getArrayElements().size(); int widthElement = arrayTable.getElementWidth(); int size = (widthElement * numElements) / 2; // addresses are on 16bits // From org.jf.dexlib.Code.Format.ArrayDataPseudoInstruction we learn // that there are 6 bytes after the magic number that we have to jump. // 6 bytes to jump = address + 3 // // out.writeByte(0x00); // magic // out.writeByte(0x03); // number // out.writeShort(elementWidth); // 2 bytes // out.writeInt(elementCount); // 4 bytes // out.write(encodedValues); // setDataFirstByte(targetAddress + 3); // address for 16 bits elements not 8 bits setDataLastByte(targetAddress + 3 + size); // - 1); setDataSize(size); // TODO: how to handle this with dexlib2 ? // ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(); // arrayTable.write(out, targetAddress); // // byte[] outa = out.getArray(); // byte[] data = new byte[outa.length-6]; // for (int i=6; i<outa.length; i++) { // data[i-6] = outa[i]; // } // setData (data); }
private NumericConstant getArrayElement(Number element, DexBody body, int arrayRegister) { List<DexlibAbstractInstruction> instructions = body.instructionsBefore(this); Set<Integer> usedRegisters = new HashSet<Integer>(); usedRegisters.add(arrayRegister); Type elementType = null; Outer: for (DexlibAbstractInstruction i : instructions) { if (usedRegisters.isEmpty()) break; for (int reg : usedRegisters) if (i instanceof NewArrayInstruction) { NewArrayInstruction newArrayInstruction = (NewArrayInstruction) i; Instruction22c instruction22c = (Instruction22c) newArrayInstruction.instruction; if (instruction22c.getRegisterA() == reg) { ArrayType arrayType = (ArrayType) DexType.toSoot((TypeReference) instruction22c.getReference()); elementType = arrayType.getElementType(); break Outer; } } // // look for obsolete registers // for (int reg : usedRegisters) { // if (i.overridesRegister(reg)) { // usedRegisters.remove(reg); // break; // there can't be more than one obsolete // } // } // look for new registers for (int reg : usedRegisters) { int newRegister = i.movesToRegister(reg); if (newRegister != -1) { usedRegisters.add(newRegister); usedRegisters.remove(reg); break; // there can't be more than one new } } } if (elementType == null) { // throw new InternalError("Unable to find array type to type array elements!"); G.v() .out .println( "Warning: Unable to find array type to type array elements! Array was not defined! (obfuscated bytecode?)"); return null; } NumericConstant value; if (elementType instanceof BooleanType) { value = IntConstant.v(element.intValue()); IntConstant ic = (IntConstant) value; if (!(ic.value == 0 || ic.value == 1)) { throw new RuntimeException("ERROR: Invalid value for boolean: " + value); } } else if (elementType instanceof ByteType) { value = IntConstant.v(element.byteValue()); } else if (elementType instanceof CharType || elementType instanceof ShortType) { value = IntConstant.v(element.shortValue()); } else if (elementType instanceof DoubleType) { value = DoubleConstant.v(Double.longBitsToDouble(element.longValue())); } else if (elementType instanceof FloatType) { value = FloatConstant.v(Float.intBitsToFloat(element.intValue())); } else if (elementType instanceof IntType) { value = IntConstant.v(element.intValue()); } else if (elementType instanceof LongType) { value = LongConstant.v(element.longValue()); } else { throw new RuntimeException( "Invalid Array Type occured in FillArrayDataInstruction: " + elementType); } Debug.printDbg("array element: ", value); return value; }