use of org.jf.dexlib2.iface.reference.Reference in project smali by JesusFreke.
the class InstructionMethodItemTest method testInvalidReference.
@Test
public void testInvalidReference() throws IOException {
Instruction21c instruction = new Instruction21c() {
@Override
public int getRegisterA() {
return 0;
}
@Nonnull
@Override
public Reference getReference() {
return new BaseStringReference() {
@Override
public void validateReference() throws InvalidReferenceException {
throw new InvalidReferenceException("blahblahblah");
}
@Nonnull
@Override
public String getString() {
throw new RuntimeException("invalid reference");
}
};
}
@Override
public int getReferenceType() {
return ReferenceType.STRING;
}
@Override
public Opcode getOpcode() {
return Opcode.CONST_STRING;
}
@Override
public int getCodeUnits() {
return Format.Format21c.size / 2;
}
};
MethodImplementation methodImplementation = new MethodImplementation() {
@Override
public int getRegisterCount() {
return 1;
}
@Nonnull
@Override
public Iterable<? extends Instruction> getInstructions() {
return ImmutableList.of(instruction);
}
@Nonnull
@Override
public List<? extends TryBlock<? extends ExceptionHandler>> getTryBlocks() {
return ImmutableList.of();
}
@Nonnull
@Override
public Iterable<? extends DebugItem> getDebugItems() {
return ImmutableList.of();
}
};
Method method = new TestMethod(methodImplementation);
ClassDefinition classDefinition = new ClassDefinition(new BaksmaliOptions(), new TestClassDef());
MethodDefinition methodDefinition = new MethodDefinition(classDefinition, method, methodImplementation);
methodDefinition.registerFormatter = new RegisterFormatter(new BaksmaliOptions(), 1, 0);
InstructionMethodItem methodItem = new InstructionMethodItem<Instruction21c>(methodDefinition, 0, instruction);
StringWriter stringWriter = new StringWriter();
BaksmaliWriter writer = new BaksmaliWriter(stringWriter);
methodItem.writeTo(writer);
Assert.assertEquals("#Invalid reference\n#const-string v0, blahblahblah\nnop", stringWriter.toString());
}
use of org.jf.dexlib2.iface.reference.Reference in project smali by JesusFreke.
the class ListReferencesCommand method run.
@Override
public void run() {
if (help || inputList == null || inputList.isEmpty()) {
usage();
return;
}
if (inputList.size() > 1) {
System.err.println("Too many files specified");
usage();
return;
}
String input = inputList.get(0);
loadDexFile(input);
BaksmaliFormatter formatter = new BaksmaliFormatter();
for (Reference reference : dexFile.getReferences(referenceType)) {
System.out.println(formatter.getReference(reference));
}
}
use of org.jf.dexlib2.iface.reference.Reference in project smali by JesusFreke.
the class AnalyzedInstruction method setsRegister.
/**
* Determines if this instruction sets the given register, or alters its type
*
* @param registerNumber The register to check
* @return true if this instruction sets the given register or alters its type
*/
public boolean setsRegister(int registerNumber) {
if (isInvokeInit()) {
// When constructing a new object, the register type will be an uninitialized reference after the
// new-instance instruction, but becomes an initialized reference once the <init> method is called. So even
// though invoke instructions don't normally change any registers, calling an <init> method will change the
// type of its object register. If the uninitialized reference has been copied to other registers, they will
// be initialized as well, so we need to check for that too
int destinationRegister;
if (instruction instanceof FiveRegisterInstruction) {
assert ((FiveRegisterInstruction) instruction).getRegisterCount() > 0;
destinationRegister = ((FiveRegisterInstruction) instruction).getRegisterC();
} else {
assert instruction instanceof RegisterRangeInstruction;
RegisterRangeInstruction rangeInstruction = (RegisterRangeInstruction) instruction;
assert rangeInstruction.getRegisterCount() > 0;
destinationRegister = rangeInstruction.getStartRegister();
}
RegisterType preInstructionDestRegisterType = getPreInstructionRegisterType(destinationRegister);
if (preInstructionDestRegisterType.category == RegisterType.UNKNOWN) {
// We never let an uninitialized reference propagate past an invoke-init if the object register type is
// unknown This is because the uninitialized reference may be an alias to the reference being
// initialized, but we can't know that until the object register's type is known
RegisterType preInstructionRegisterType = getPreInstructionRegisterType(registerNumber);
if (preInstructionRegisterType.category == RegisterType.UNINIT_REF || preInstructionRegisterType.category == RegisterType.UNINIT_THIS) {
return true;
}
}
if (preInstructionDestRegisterType.category != RegisterType.UNINIT_REF && preInstructionDestRegisterType.category != RegisterType.UNINIT_THIS) {
return false;
}
if (registerNumber == destinationRegister) {
return true;
}
// check if the uninit ref has been copied to another register
return preInstructionDestRegisterType.equals(getPreInstructionRegisterType(registerNumber));
}
// branch of the following if-eqz/if-nez
if (instructionIndex > 0 && methodAnalyzer.getClassPath().isArt() && getPredecessorCount() == 1 && (instruction.getOpcode() == Opcode.IF_EQZ || instruction.getOpcode() == Opcode.IF_NEZ)) {
AnalyzedInstruction prevInstruction = predecessors.first();
if (prevInstruction.instruction.getOpcode() == Opcode.INSTANCE_OF && MethodAnalyzer.canPropagateTypeAfterInstanceOf(prevInstruction, this, methodAnalyzer.getClassPath())) {
Instruction22c instanceOfInstruction = (Instruction22c) prevInstruction.instruction;
if (registerNumber == instanceOfInstruction.getRegisterB()) {
return true;
}
// TODO: do we need to do some sort of additional check that these multiple move-object predecessors actually refer to the same value?
if (instructionIndex > 1) {
int originalSourceRegister = -1;
RegisterType newType = null;
for (AnalyzedInstruction prevPrevAnalyzedInstruction : prevInstruction.predecessors) {
Opcode opcode = prevPrevAnalyzedInstruction.instruction.getOpcode();
if (opcode == Opcode.MOVE_OBJECT || opcode == Opcode.MOVE_OBJECT_16 || opcode == Opcode.MOVE_OBJECT_FROM16) {
TwoRegisterInstruction moveInstruction = ((TwoRegisterInstruction) prevPrevAnalyzedInstruction.instruction);
RegisterType originalType = prevPrevAnalyzedInstruction.getPostInstructionRegisterType(moveInstruction.getRegisterB());
if (moveInstruction.getRegisterA() != instanceOfInstruction.getRegisterB()) {
originalSourceRegister = -1;
break;
}
if (originalType.type == null) {
originalSourceRegister = -1;
break;
}
if (newType == null) {
newType = RegisterType.getRegisterType(methodAnalyzer.getClassPath(), (TypeReference) instanceOfInstruction.getReference());
}
if (MethodAnalyzer.isNotWideningConversion(originalType, newType)) {
if (originalSourceRegister != -1) {
if (originalSourceRegister != moveInstruction.getRegisterB()) {
originalSourceRegister = -1;
break;
}
} else {
originalSourceRegister = moveInstruction.getRegisterB();
}
}
} else {
originalSourceRegister = -1;
break;
}
}
if (originalSourceRegister != -1 && registerNumber == originalSourceRegister) {
return true;
}
}
}
}
if (!instruction.getOpcode().setsRegister()) {
return false;
}
int destinationRegister = getDestinationRegister();
if (registerNumber == destinationRegister) {
return true;
}
if (instruction.getOpcode().setsWideRegister() && registerNumber == (destinationRegister + 1)) {
return true;
}
return false;
}
use of org.jf.dexlib2.iface.reference.Reference in project smali by JesusFreke.
the class DexBackedMethod method getSize.
/**
* Calculate and return the private size of a method definition.
*
* Calculated as: method_idx_diff + access_flags + code_off +
* implementation size + reference size
*
* @return size in bytes
*/
public int getSize() {
int size = 0;
DexReader reader = dexFile.getDataBuffer().readerAt(startOffset);
// method_idx_diff
reader.readLargeUleb128();
// access_flags
reader.readSmallUleb128();
// code_off
reader.readSmallUleb128();
size += reader.getOffset() - startOffset;
DexBackedMethodImplementation impl = getImplementation();
if (impl != null) {
size += impl.getSize();
}
DexBackedMethodReference methodRef = new DexBackedMethodReference(dexFile, methodIndex);
size += methodRef.getSize();
return size;
}
use of org.jf.dexlib2.iface.reference.Reference in project smali by JesusFreke.
the class DexBackedField method getSize.
/**
* Calculate and return the private size of a field definition.
*
* Calculated as: field_idx_diff + access_flags + annotations overhead +
* initial value size + field reference size
*
* @return size in bytes
*/
public int getSize() {
int size = 0;
DexReader reader = dexFile.getBuffer().readerAt(startOffset);
// field_idx_diff
reader.readLargeUleb128();
// access_flags
reader.readSmallUleb128();
size += reader.getOffset() - startOffset;
Set<? extends DexBackedAnnotation> annotations = getAnnotations();
if (!annotations.isEmpty()) {
// 2 * uint overhead from field_annotation
size += 2 * 4;
}
if (initialValueOffset > 0) {
reader.setOffset(initialValueOffset);
if (initialValue != null) {
DexBackedEncodedValue.skipFrom(reader);
size += reader.getOffset() - initialValueOffset;
}
}
DexBackedFieldReference fieldRef = new DexBackedFieldReference(dexFile, fieldIndex);
size += fieldRef.getSize();
return size;
}
Aggregations