use of org.jf.util.ExceptionWithContext in project atlas by alibaba.
the class MethodDefinition method addTries.
private void addTries(List<MethodItem> methodItems) {
List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks = methodImpl.getTryBlocks();
if (tryBlocks.size() == 0) {
return;
}
int lastInstructionAddress = instructionOffsetMap.getInstructionCodeOffset(instructions.size() - 1);
int codeSize = lastInstructionAddress + instructions.get(instructions.size() - 1).getCodeUnits();
for (TryBlock<? extends ExceptionHandler> tryBlock : tryBlocks) {
int startAddress = tryBlock.getStartCodeAddress();
int endAddress = startAddress + tryBlock.getCodeUnitCount();
if (startAddress >= codeSize) {
throw new RuntimeException(String.format("Try start offset %d is past the end of the code block.", startAddress));
}
// Note: not >=. endAddress == codeSize is valid, when the try covers the last instruction
if (endAddress > codeSize) {
throw new RuntimeException(String.format("Try end offset %d is past the end of the code block.", endAddress));
}
/**
* The end address points to the address immediately after the end of the last
* instruction that the try block covers. We want the .catch directive and end_try
* label to be associated with the last covered instruction, so we need to get
* the address for that instruction
*/
int lastCoveredIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(endAddress - 1, false);
int lastCoveredAddress = instructionOffsetMap.getInstructionCodeOffset(lastCoveredIndex);
for (ExceptionHandler handler : tryBlock.getExceptionHandlers()) {
int handlerAddress = handler.getHandlerCodeAddress();
if (handlerAddress >= codeSize) {
throw new ExceptionWithContext("Exception handler offset %d is past the end of the code block.", handlerAddress);
}
//use the address from the last covered instruction
CatchMethodItem catchMethodItem = new CatchMethodItem(classDef.options, labelCache, lastCoveredAddress, handler.getExceptionType(), startAddress, endAddress, handlerAddress);
methodItems.add(catchMethodItem);
}
}
}
use of org.jf.util.ExceptionWithContext in project smali by JesusFreke.
the class AnnotatedBytes method annotate.
/**
* Add an annotation of the given length at the current location.
*
* The location
*
*
* @param length the length of data being annotated
* @param msg the annotation message
* @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;
if (formatArgs != null && formatArgs.length > 0) {
formattedMsg = String.format(msg, formatArgs);
} else {
formattedMsg = msg;
}
int exclusiveEndOffset = cursor + length;
AnnotationEndpoint endPoint = null;
// Do we have an endpoint at the beginning of this annotation already?
AnnotationEndpoint startPoint = annotatations.get(cursor);
if (startPoint == null) {
// Nope. We need to check that we're not in the middle of an existing range annotation.
Map.Entry<Integer, AnnotationEndpoint> previousEntry = annotatations.lowerEntry(cursor);
if (previousEntry != null) {
AnnotationEndpoint previousAnnotations = previousEntry.getValue();
AnnotationItem previousRangeAnnotation = previousAnnotations.rangeAnnotation;
if (previousRangeAnnotation != null) {
throw new ExceptionWithContext("Cannot add annotation %s, due to existing annotation %s", formatAnnotation(cursor, cursor + length, formattedMsg), formatAnnotation(previousEntry.getKey(), previousRangeAnnotation.annotation));
}
}
} else if (length > 0) {
AnnotationItem existingRangeAnnotation = startPoint.rangeAnnotation;
if (existingRangeAnnotation != null) {
throw new ExceptionWithContext("Cannot add annotation %s, due to existing annotation %s", formatAnnotation(cursor, cursor + length, formattedMsg), formatAnnotation(cursor, existingRangeAnnotation.annotation));
}
}
if (length > 0) {
// Ensure that there is no later annotation that would intersect with this one
Map.Entry<Integer, AnnotationEndpoint> nextEntry = annotatations.higherEntry(cursor);
if (nextEntry != null) {
int nextKey = nextEntry.getKey();
if (nextKey < exclusiveEndOffset) {
// there is an endpoint that would intersect with this annotation. Find one of the annotations
// associated with the endpoint, to print in the error message
AnnotationEndpoint nextEndpoint = nextEntry.getValue();
AnnotationItem nextRangeAnnotation = nextEndpoint.rangeAnnotation;
if (nextRangeAnnotation != null) {
throw new ExceptionWithContext("Cannot add annotation %s, due to existing annotation %s", formatAnnotation(cursor, cursor + length, formattedMsg), formatAnnotation(nextKey, nextRangeAnnotation.annotation));
}
if (nextEndpoint.pointAnnotations.size() > 0) {
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));
}
// There are no annotations on this endpoint. This "shouldn't" happen. We can still throw an exception.
throw new ExceptionWithContext("Cannot add annotation %s, due to existing annotation endpoint at %d", formatAnnotation(cursor, cursor + length, formattedMsg), nextKey);
}
if (nextKey == exclusiveEndOffset) {
// the next endpoint matches the end of the annotation we are adding
endPoint = nextEntry.getValue();
}
}
}
// the range annotation
if (startPoint == null) {
startPoint = new AnnotationEndpoint();
annotatations.put(cursor, startPoint);
}
if (length == 0) {
startPoint.pointAnnotations.add(new AnnotationItem(indentLevel, formattedMsg));
} else {
startPoint.rangeAnnotation = new AnnotationItem(indentLevel, formattedMsg);
// If endPoint is null, we need to create a new, empty one and add it to annotations
if (endPoint == null) {
endPoint = new AnnotationEndpoint();
annotatations.put(exclusiveEndOffset, endPoint);
}
}
cursor += length;
}
use of org.jf.util.ExceptionWithContext in project smali by JesusFreke.
the class DexWriter method writeDebugAndCodeItems.
private void writeDebugAndCodeItems(@Nonnull DexDataWriter offsetWriter, @Nonnull DeferredOutputStream temp) throws IOException {
ByteArrayOutputStream ehBuf = new ByteArrayOutputStream();
debugSectionOffset = offsetWriter.getPosition();
DebugWriter<StringKey, TypeKey> debugWriter = new DebugWriter<StringKey, TypeKey>(stringSection, typeSection, offsetWriter);
DexDataWriter codeWriter = new DexDataWriter(temp, 0);
List<CodeItemOffset<MethodKey>> codeOffsets = Lists.newArrayList();
for (ClassKey classKey : classSection.getSortedClasses()) {
Collection<? extends MethodKey> directMethods = classSection.getSortedDirectMethods(classKey);
Collection<? extends MethodKey> virtualMethods = classSection.getSortedVirtualMethods(classKey);
Iterable<MethodKey> methods = Iterables.concat(directMethods, virtualMethods);
for (MethodKey methodKey : methods) {
List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks = classSection.getTryBlocks(methodKey);
Iterable<? extends Instruction> instructions = classSection.getInstructions(methodKey);
Iterable<? extends DebugItem> debugItems = classSection.getDebugItems(methodKey);
if (instructions != null && stringSection.hasJumboIndexes()) {
boolean needsFix = false;
for (Instruction instruction : instructions) {
if (instruction.getOpcode() == Opcode.CONST_STRING) {
if (stringSection.getItemIndex((StringRef) ((ReferenceInstruction) instruction).getReference()) >= 65536) {
needsFix = true;
break;
}
}
}
if (needsFix) {
MutableMethodImplementation mutableMethodImplementation = classSection.makeMutableMethodImplementation(methodKey);
fixInstructions(mutableMethodImplementation);
instructions = mutableMethodImplementation.getInstructions();
tryBlocks = mutableMethodImplementation.getTryBlocks();
debugItems = mutableMethodImplementation.getDebugItems();
}
}
int debugItemOffset = writeDebugItem(offsetWriter, debugWriter, classSection.getParameterNames(methodKey), debugItems);
int codeItemOffset;
try {
codeItemOffset = writeCodeItem(codeWriter, ehBuf, methodKey, tryBlocks, instructions, debugItemOffset);
} catch (RuntimeException ex) {
throw new ExceptionWithContext(ex, "Exception occurred while writing code_item for method %s", methodSection.getMethodReference(methodKey));
}
if (codeItemOffset != -1) {
codeOffsets.add(new CodeItemOffset<MethodKey>(methodKey, codeItemOffset));
}
}
}
offsetWriter.align();
codeSectionOffset = offsetWriter.getPosition();
codeWriter.close();
temp.writeTo(offsetWriter);
temp.close();
for (CodeItemOffset<MethodKey> codeOffset : codeOffsets) {
classSection.setCodeItemOffset(codeOffset.method, codeSectionOffset + codeOffset.codeOffset);
}
}
use of org.jf.util.ExceptionWithContext in project smali by JesusFreke.
the class InstructionOffsetMapTest method testInstructionOffsetMap.
@Test
public void testInstructionOffsetMap() {
ImmutableList<ImmutableInstruction> instructions = ImmutableList.of(/*00: 0x00*/
new ImmutableInstruction10t(Opcode.GOTO, 1), /*01: 0x01*/
new ImmutableInstruction10x(Opcode.NOP), /*02: 0x02*/
new ImmutableInstruction11n(Opcode.CONST_4, 2, 3), /*03: 0x03*/
new ImmutableInstruction11x(Opcode.RETURN, 4), /*04: 0x04*/
new ImmutableInstruction12x(Opcode.ARRAY_LENGTH, 5, 6), /*05: 0x05*/
new ImmutableInstruction20t(Opcode.GOTO_16, 7), /*06: 0x07*/
new ImmutableInstruction21c(Opcode.CONST_STRING, 8, new ImmutableStringReference("blah")), /*07: 0x09*/
new ImmutableInstruction21ih(Opcode.CONST_HIGH16, 9, 0x10000), /*08: 0x0b*/
new ImmutableInstruction21lh(Opcode.CONST_WIDE_HIGH16, 10, 0x1000000000000L), /*09: 0x0d*/
new ImmutableInstruction21s(Opcode.CONST_16, 11, 12), /*10: 0x0f*/
new ImmutableInstruction21t(Opcode.IF_EQZ, 12, 13), /*11: 0x11*/
new ImmutableInstruction22b(Opcode.ADD_INT_LIT8, 14, 15, 16), /*12: 0x13*/
new ImmutableInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Ltype;")), /*13: 0x15*/
new ImmutableInstruction22s(Opcode.ADD_INT_LIT16, 2, 3, 17), /*14: 0x17*/
new ImmutableInstruction22t(Opcode.IF_EQ, 4, 5, 18), /*15: 0x19*/
new ImmutableInstruction22x(Opcode.MOVE_FROM16, 19, 20), /*16: 0x1b*/
new ImmutableInstruction23x(Opcode.AGET, 21, 22, 23), /*17: 0x1d*/
new ImmutableInstruction30t(Opcode.GOTO_32, 24), /*18: 0x20*/
new ImmutableInstruction31c(Opcode.CONST_STRING_JUMBO, 25, new ImmutableStringReference("this is a string")), /*19: 0x23*/
new ImmutableInstruction31i(Opcode.CONST, 26, 27), /*20: 0x26*/
new ImmutableInstruction31t(Opcode.FILL_ARRAY_DATA, 28, 29), /*21: 0x29*/
new ImmutableInstruction32x(Opcode.MOVE_16, 30, 31), /*22: 0x2c*/
new ImmutableInstruction35c(Opcode.FILLED_NEW_ARRAY, 0, 0, 0, 0, 0, 0, new ImmutableTypeReference("Ltype;")), /*23: 0x2f*/
new ImmutableInstruction3rc(Opcode.FILLED_NEW_ARRAY_RANGE, 0, 0, new ImmutableTypeReference("Ltype;")), /*24: 0x32*/
new ImmutableInstruction51l(Opcode.CONST_WIDE, 32, 33), /*25: 0x37*/
new ImmutableInstruction10t(Opcode.GOTO, 1));
ImmutableMethodImplementation impl = new ImmutableMethodImplementation(33, instructions, null, null);
InstructionOffsetMap instructionOffsetMap = new InstructionOffsetMap(instructions);
int[] expectedOffsets = new int[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x37 };
for (int i = 0; i < instructions.size(); i++) {
Assert.assertEquals(expectedOffsets[i], instructionOffsetMap.getInstructionCodeOffset(i));
Assert.assertEquals(i, instructionOffsetMap.getInstructionIndexAtCodeOffset(expectedOffsets[i], true));
Assert.assertEquals(i, instructionOffsetMap.getInstructionIndexAtCodeOffset(expectedOffsets[i], false));
}
int instructionIndex = -1;
for (int codeOffset = 0; codeOffset <= expectedOffsets[expectedOffsets.length - 1]; codeOffset++) {
if (codeOffset == expectedOffsets[instructionIndex + 1]) {
// this offset is at the beginning of an instruction
instructionIndex++;
} else {
// this offset is in the middle of an instruction
Assert.assertEquals(instructionIndex, instructionOffsetMap.getInstructionIndexAtCodeOffset(codeOffset, false));
try {
instructionOffsetMap.getInstructionIndexAtCodeOffset(codeOffset, true);
Assert.fail(String.format("Exception exception didn't occur for code offset 0x%x", codeOffset));
} catch (ExceptionWithContext ex) {
// expected exception
}
}
}
Assert.assertEquals(expectedOffsets.length - 1, instructionOffsetMap.getInstructionIndexAtCodeOffset(expectedOffsets[expectedOffsets.length - 1] + 1, false));
Assert.assertEquals(expectedOffsets.length - 1, instructionOffsetMap.getInstructionIndexAtCodeOffset(expectedOffsets[expectedOffsets.length - 1] + 10, false));
}
use of org.jf.util.ExceptionWithContext in project smali by JesusFreke.
the class ClassPool method intern.
public void intern(@Nonnull ClassDef classDef) {
PoolClassDef poolClassDef = new PoolClassDef(classDef);
PoolClassDef prev = internedItems.put(poolClassDef.getType(), poolClassDef);
if (prev != null) {
throw new ExceptionWithContext("Class %s has already been interned", poolClassDef.getType());
}
dexPool.typeSection.intern(poolClassDef.getType());
dexPool.typeSection.internNullable(poolClassDef.getSuperclass());
dexPool.typeListSection.intern(poolClassDef.getInterfaces());
dexPool.stringSection.internNullable(poolClassDef.getSourceFile());
HashSet<String> fields = new HashSet<String>();
for (Field field : poolClassDef.getFields()) {
String fieldDescriptor = ReferenceUtil.getShortFieldDescriptor(field);
if (!fields.add(fieldDescriptor)) {
throw new ExceptionWithContext("Multiple definitions for field %s->%s", poolClassDef.getType(), fieldDescriptor);
}
dexPool.fieldSection.intern(field);
EncodedValue initialValue = field.getInitialValue();
if (initialValue != null) {
dexPool.internEncodedValue(initialValue);
}
dexPool.annotationSetSection.intern(field.getAnnotations());
}
HashSet<String> methods = new HashSet<String>();
for (PoolMethod method : poolClassDef.getMethods()) {
String methodDescriptor = ReferenceUtil.getMethodDescriptor(method, true);
if (!methods.add(methodDescriptor)) {
throw new ExceptionWithContext("Multiple definitions for method %s->%s", poolClassDef.getType(), methodDescriptor);
}
dexPool.methodSection.intern(method);
internCode(method);
internDebug(method);
dexPool.annotationSetSection.intern(method.getAnnotations());
for (MethodParameter parameter : method.getParameters()) {
dexPool.annotationSetSection.intern(parameter.getAnnotations());
}
}
dexPool.annotationSetSection.intern(poolClassDef.getAnnotations());
}
Aggregations