mirror of
https://github.com/revanced/smali.git
synced 2025-05-22 19:08:52 +02:00
Make CodeItem annotations more robust
This commit is contained in:
parent
d7cd52308e
commit
dc802b0660
@ -41,6 +41,7 @@ import org.jf.dexlib2.iface.instruction.*;
|
||||
import org.jf.dexlib2.iface.instruction.formats.*;
|
||||
import org.jf.dexlib2.util.AnnotatedBytes;
|
||||
import org.jf.dexlib2.util.ReferenceUtil;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
import org.jf.util.NumberUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -84,121 +85,160 @@ public class CodeItem {
|
||||
|
||||
@Override
|
||||
public void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity) {
|
||||
DexReader reader = dexFile.readerAt(out.getCursor());
|
||||
try {
|
||||
DexReader reader = dexFile.readerAt(out.getCursor());
|
||||
|
||||
int registers = reader.readUshort();
|
||||
out.annotate(2, "registers_size = %d", registers);
|
||||
int registers = reader.readUshort();
|
||||
out.annotate(2, "registers_size = %d", registers);
|
||||
|
||||
int inSize = reader.readUshort();
|
||||
out.annotate(2, "ins_size = %d", inSize);
|
||||
int inSize = reader.readUshort();
|
||||
out.annotate(2, "ins_size = %d", inSize);
|
||||
|
||||
int outSize = reader.readUshort();
|
||||
out.annotate(2, "outs_size = %d", outSize);
|
||||
int outSize = reader.readUshort();
|
||||
out.annotate(2, "outs_size = %d", outSize);
|
||||
|
||||
int triesCount = reader.readUshort();
|
||||
out.annotate(2, "tries_size = %d", triesCount);
|
||||
int triesCount = reader.readUshort();
|
||||
out.annotate(2, "tries_size = %d", triesCount);
|
||||
|
||||
int debugInfoOffset = reader.readSmallUint();
|
||||
out.annotate(4, "debug_info_off = 0x%x", debugInfoOffset);
|
||||
int debugInfoOffset = reader.readSmallUint();
|
||||
out.annotate(4, "debug_info_off = 0x%x", debugInfoOffset);
|
||||
|
||||
if (debugInfoOffset != 0) {
|
||||
addDebugInfoIdentity(debugInfoOffset, itemIdentity);
|
||||
}
|
||||
|
||||
int instructionSize = reader.readSmallUint();
|
||||
out.annotate(4, "insns_size = 0x%x", instructionSize);
|
||||
|
||||
out.annotate(0, "instructions:");
|
||||
out.indent();
|
||||
|
||||
int end = reader.getOffset() + instructionSize*2;
|
||||
while (reader.getOffset() < end) {
|
||||
Instruction instruction = DexBackedInstruction.readFrom(reader);
|
||||
|
||||
switch (instruction.getOpcode().format) {
|
||||
case Format10x:
|
||||
annotateInstruction10x(out, instruction);
|
||||
break;
|
||||
case Format35c:
|
||||
annotateInstruction35c(out, (Instruction35c)instruction);
|
||||
break;
|
||||
case Format3rc:
|
||||
annotateInstruction3rc(out, (Instruction3rc)instruction);
|
||||
break;
|
||||
case ArrayPayload:
|
||||
annotateArrayPayload(out, (ArrayPayload)instruction);
|
||||
break;
|
||||
case PackedSwitchPayload:
|
||||
annotatePackedSwitchPayload(out, (PackedSwitchPayload)instruction);
|
||||
break;
|
||||
case SparseSwitchPayload:
|
||||
annotateSparseSwitchPayload(out, (SparseSwitchPayload)instruction);
|
||||
break;
|
||||
default:
|
||||
annotateDefaultInstruction(out, instruction);
|
||||
break;
|
||||
if (debugInfoOffset != 0) {
|
||||
addDebugInfoIdentity(debugInfoOffset, itemIdentity);
|
||||
}
|
||||
|
||||
assert reader.getOffset() == out.getCursor();
|
||||
}
|
||||
out.deindent();
|
||||
int instructionSize = reader.readSmallUint();
|
||||
out.annotate(4, "insns_size = 0x%x", instructionSize);
|
||||
|
||||
if (triesCount > 0) {
|
||||
if ((reader.getOffset() % 4) != 0) {
|
||||
reader.readUshort();
|
||||
out.annotate(2, "padding");
|
||||
}
|
||||
|
||||
out.annotate(0, "try_items:");
|
||||
out.annotate(0, "instructions:");
|
||||
out.indent();
|
||||
for (int i=0; i<triesCount; i++) {
|
||||
out.annotate(0, "try_item[%d]:", i);
|
||||
out.indent();
|
||||
int startAddr = reader.readSmallUint();
|
||||
out.annotate(4, "start_addr = 0x%x", startAddr);
|
||||
|
||||
int instructionCount = reader.readUshort();
|
||||
out.annotate(2, "insn_count = 0x%x", instructionCount);
|
||||
out.setLimit(out.getCursor(), out.getCursor() + instructionSize * 2);
|
||||
|
||||
int handlerOffset = reader.readUshort();
|
||||
out.annotate(2, "handler_off = 0x%x", handlerOffset);
|
||||
int end = reader.getOffset() + instructionSize*2;
|
||||
try {
|
||||
while (reader.getOffset() < end) {
|
||||
Instruction instruction = DexBackedInstruction.readFrom(reader);
|
||||
|
||||
// if we read past the end of the instruction list
|
||||
if (reader.getOffset() > end) {
|
||||
out.annotateTo(end, "truncated instruction");
|
||||
reader.setOffset(end);
|
||||
} else {
|
||||
switch (instruction.getOpcode().format) {
|
||||
case Format10x:
|
||||
annotateInstruction10x(out, instruction);
|
||||
break;
|
||||
case Format35c:
|
||||
annotateInstruction35c(out, (Instruction35c)instruction);
|
||||
break;
|
||||
case Format3rc:
|
||||
annotateInstruction3rc(out, (Instruction3rc)instruction);
|
||||
break;
|
||||
case ArrayPayload:
|
||||
annotateArrayPayload(out, (ArrayPayload)instruction);
|
||||
break;
|
||||
case PackedSwitchPayload:
|
||||
annotatePackedSwitchPayload(out, (PackedSwitchPayload)instruction);
|
||||
break;
|
||||
case SparseSwitchPayload:
|
||||
annotateSparseSwitchPayload(out, (SparseSwitchPayload)instruction);
|
||||
break;
|
||||
default:
|
||||
annotateDefaultInstruction(out, instruction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert reader.getOffset() == out.getCursor();
|
||||
}
|
||||
} catch (ExceptionWithContext ex) {
|
||||
ex.printStackTrace(System.err);
|
||||
out.annotate(0, "annotation error: %s", ex.getMessage());
|
||||
out.moveTo(end);
|
||||
reader.setOffset(end);
|
||||
} finally {
|
||||
out.clearLimit();
|
||||
out.deindent();
|
||||
}
|
||||
out.deindent();
|
||||
|
||||
int handlerListCount = reader.readSmallUleb128();
|
||||
out.annotate(0, "encoded_catch_handler_list:");
|
||||
out.annotateTo(reader.getOffset(), "size = %d", handlerListCount);
|
||||
out.indent();
|
||||
for (int i=0; i<handlerListCount; i++) {
|
||||
out.annotate(0, "encoded_catch_handler[%d]", i);
|
||||
if (triesCount > 0) {
|
||||
if ((reader.getOffset() % 4) != 0) {
|
||||
reader.readUshort();
|
||||
out.annotate(2, "padding");
|
||||
}
|
||||
|
||||
out.annotate(0, "try_items:");
|
||||
out.indent();
|
||||
int handlerCount = reader.readSleb128();
|
||||
out.annotateTo(reader.getOffset(), "size = %d", handlerCount);
|
||||
boolean hasCatchAll = handlerCount <= 0;
|
||||
handlerCount = Math.abs(handlerCount);
|
||||
if (handlerCount != 0) {
|
||||
out.annotate(0, "handlers:");
|
||||
out.indent();
|
||||
for (int j=0; j<handlerCount; j++) {
|
||||
out.annotate(0, "encoded_type_addr_pair[%d]", i);
|
||||
try {
|
||||
for (int i=0; i<triesCount; i++) {
|
||||
out.annotate(0, "try_item[%d]:", i);
|
||||
out.indent();
|
||||
int typeIndex = reader.readSmallUleb128();
|
||||
out.annotateTo(reader.getOffset(), TypeIdItem.getReferenceAnnotation(dexFile, typeIndex));
|
||||
try {
|
||||
int startAddr = reader.readSmallUint();
|
||||
out.annotate(4, "start_addr = 0x%x", startAddr);
|
||||
|
||||
int handlerAddress = reader.readSmallUleb128();
|
||||
out.annotateTo(reader.getOffset(), "addr = 0x%x", handlerAddress);
|
||||
out.deindent();
|
||||
int instructionCount = reader.readUshort();
|
||||
out.annotate(2, "insn_count = 0x%x", instructionCount);
|
||||
|
||||
int handlerOffset = reader.readUshort();
|
||||
out.annotate(2, "handler_off = 0x%x", handlerOffset);
|
||||
} finally {
|
||||
out.deindent();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
out.deindent();
|
||||
}
|
||||
if (hasCatchAll) {
|
||||
int catchAllAddress = reader.readSmallUleb128();
|
||||
out.annotateTo(reader.getOffset(), "catch_all_addr = 0x%x", catchAllAddress);
|
||||
|
||||
int handlerListCount = reader.readSmallUleb128();
|
||||
out.annotate(0, "encoded_catch_handler_list:");
|
||||
out.annotateTo(reader.getOffset(), "size = %d", handlerListCount);
|
||||
out.indent();
|
||||
try {
|
||||
for (int i=0; i<handlerListCount; i++) {
|
||||
out.annotate(0, "encoded_catch_handler[%d]", i);
|
||||
out.indent();
|
||||
try {
|
||||
int handlerCount = reader.readSleb128();
|
||||
out.annotateTo(reader.getOffset(), "size = %d", handlerCount);
|
||||
boolean hasCatchAll = handlerCount <= 0;
|
||||
handlerCount = Math.abs(handlerCount);
|
||||
if (handlerCount != 0) {
|
||||
out.annotate(0, "handlers:");
|
||||
out.indent();
|
||||
try {
|
||||
for (int j=0; j<handlerCount; j++) {
|
||||
out.annotate(0, "encoded_type_addr_pair[%d]", i);
|
||||
out.indent();
|
||||
try {
|
||||
int typeIndex = reader.readSmallUleb128();
|
||||
out.annotateTo(reader.getOffset(), TypeIdItem.getReferenceAnnotation(dexFile, typeIndex));
|
||||
|
||||
int handlerAddress = reader.readSmallUleb128();
|
||||
out.annotateTo(reader.getOffset(), "addr = 0x%x", handlerAddress);
|
||||
} finally {
|
||||
out.deindent();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
out.deindent();
|
||||
}
|
||||
}
|
||||
if (hasCatchAll) {
|
||||
int catchAllAddress = reader.readSmallUleb128();
|
||||
out.annotateTo(reader.getOffset(), "catch_all_addr = 0x%x", catchAllAddress);
|
||||
}
|
||||
} finally {
|
||||
out.deindent();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
out.deindent();
|
||||
}
|
||||
out.deindent();
|
||||
}
|
||||
out.deindent();
|
||||
} catch (ExceptionWithContext ex) {
|
||||
out.annotate(0, "annotation error: %s", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,13 +303,17 @@ public class CodeItem {
|
||||
}
|
||||
}
|
||||
} else if (instruction instanceof VerificationErrorInstruction) {
|
||||
args.add(VerificationError.getVerificationErrorName(
|
||||
((VerificationErrorInstruction)instruction).getVerificationError()));
|
||||
String verificationError = VerificationError.getVerificationErrorName(
|
||||
((VerificationErrorInstruction) instruction).getVerificationError());
|
||||
if (verificationError != null) {
|
||||
args.add(verificationError);
|
||||
} else {
|
||||
args.add("invalid verification error type");
|
||||
}
|
||||
}
|
||||
|
||||
if (instruction instanceof ReferenceInstruction) {
|
||||
args.add(ReferenceUtil.getReferenceString(
|
||||
((ReferenceInstruction)instruction).getReference()));
|
||||
args.add(ReferenceUtil.getReferenceString(((ReferenceInstruction)instruction).getReference()));
|
||||
} else if (instruction instanceof OffsetInstruction) {
|
||||
int offset = ((OffsetInstruction)instruction).getCodeOffset();
|
||||
String sign = offset>=0?"+":"-";
|
||||
|
@ -34,6 +34,8 @@ package org.jf.dexlib2.util;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
import org.jf.util.Hex;
|
||||
import org.jf.util.TwoColumnOutput;
|
||||
|
||||
@ -78,6 +80,9 @@ public class AnnotatedBytes {
|
||||
*/
|
||||
private int hexCols = 8;
|
||||
|
||||
private int startLimit = -1;
|
||||
private int endLimit = -1;
|
||||
|
||||
public AnnotatedBytes(int width) {
|
||||
this.outputWidth = width;
|
||||
}
|
||||
@ -115,6 +120,10 @@ public class AnnotatedBytes {
|
||||
* @param formatArgs format arguments to pass to String.format
|
||||
*/
|
||||
public void annotate(int length, @Nonnull String msg, Object... formatArgs) {
|
||||
if (startLimit != -1 && endLimit != -1 && (cursor < startLimit || cursor >= endLimit)) {
|
||||
throw new ExceptionWithContext("Annotating outside the parent bounds");
|
||||
}
|
||||
|
||||
String formattedMsg = String.format(msg, formatArgs);
|
||||
int exclusiveEndOffset = cursor + length;
|
||||
|
||||
@ -129,19 +138,20 @@ public class AnnotatedBytes {
|
||||
AnnotationEndpoint previousAnnotations = previousEntry.getValue();
|
||||
AnnotationItem previousRangeAnnotation = previousAnnotations.rangeAnnotation;
|
||||
if (previousRangeAnnotation != null) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Cannot add annotation %s, due to existing annotation %s",
|
||||
throw new ExceptionWithContext(
|
||||
"Cannot add annotation %s, due to existing annotation %s",
|
||||
formatAnnotation(cursor, cursor + length, formattedMsg),
|
||||
formatAnnotation(previousEntry.getKey(), previousRangeAnnotation.annotation)));
|
||||
formatAnnotation(previousEntry.getKey(),
|
||||
previousRangeAnnotation.annotation));
|
||||
}
|
||||
}
|
||||
} else if (length > 0) {
|
||||
AnnotationItem existingRangeAnnotation = startPoint.rangeAnnotation;
|
||||
if (existingRangeAnnotation != null) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Cannot add annotation %s, due to existing annotation %s",
|
||||
throw new ExceptionWithContext(
|
||||
"Cannot add annotation %s, due to existing annotation %s",
|
||||
formatAnnotation(cursor, cursor + length, formattedMsg),
|
||||
formatAnnotation(cursor, existingRangeAnnotation.annotation)));
|
||||
formatAnnotation(cursor, existingRangeAnnotation.annotation));
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,23 +166,23 @@ public class AnnotatedBytes {
|
||||
AnnotationEndpoint nextEndpoint = nextEntry.getValue();
|
||||
AnnotationItem nextRangeAnnotation = nextEndpoint.rangeAnnotation;
|
||||
if (nextRangeAnnotation != null) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Cannot add annotation %s, due to existing annotation %s",
|
||||
throw new ExceptionWithContext(
|
||||
"Cannot add annotation %s, due to existing annotation %s",
|
||||
formatAnnotation(cursor, cursor + length, formattedMsg),
|
||||
formatAnnotation(nextKey, nextRangeAnnotation.annotation)));
|
||||
formatAnnotation(nextKey, nextRangeAnnotation.annotation));
|
||||
}
|
||||
if (nextEndpoint.pointAnnotations.size() > 0) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Cannot add annotation %s, due to existing annotation %s",
|
||||
throw new ExceptionWithContext(
|
||||
"Cannot add annotation %s, due to existing annotation %s",
|
||||
formatAnnotation(cursor, cursor + length, formattedMsg),
|
||||
formatAnnotation(nextKey, nextKey,
|
||||
nextEndpoint.pointAnnotations.get(0).annotation)));
|
||||
nextEndpoint.pointAnnotations.get(0).annotation));
|
||||
}
|
||||
// There are no annotations on this endpoint. This "shouldn't" happen. We can still throw an exception.
|
||||
throw new IllegalStateException(
|
||||
String.format("Cannot add annotation %s, due to existing annotation endpoint at %d",
|
||||
throw new ExceptionWithContext(
|
||||
"Cannot add annotation %s, due to existing annotation endpoint at %d",
|
||||
formatAnnotation(cursor, cursor + length, formattedMsg),
|
||||
nextKey));
|
||||
nextKey);
|
||||
}
|
||||
|
||||
if (nextKey == exclusiveEndOffset) {
|
||||
@ -312,4 +322,14 @@ public class AnnotatedBytes {
|
||||
twoc.write(left, "");
|
||||
}
|
||||
}
|
||||
|
||||
public void setLimit(int start, int end) {
|
||||
this.startLimit = start;
|
||||
this.endLimit = end;
|
||||
}
|
||||
|
||||
public void clearLimit() {
|
||||
this.startLimit = -1;
|
||||
this.endLimit = -1;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user