use of org.jf.dexlib2.iface.ExceptionHandler 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.dexlib2.iface.ExceptionHandler 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.dexlib2.iface.ExceptionHandler in project smali by JesusFreke.
the class SmalideaMethod method getImplementation.
@Nullable
@Override
public MethodImplementation getImplementation() {
if (psiMethod instanceof SmaliMethod) {
final SmaliMethod smaliMethod = (SmaliMethod) this.psiMethod;
List<SmaliInstruction> instructions = smaliMethod.getInstructions();
if (instructions.size() == 0) {
return null;
}
// TODO: cache this?
return new MethodImplementation() {
@Override
public int getRegisterCount() {
return smaliMethod.getRegisterCount();
}
@Nonnull
@Override
public Iterable<? extends Instruction> getInstructions() {
return Lists.transform(smaliMethod.getInstructions(), new Function<SmaliInstruction, Instruction>() {
@Override
public Instruction apply(SmaliInstruction smaliInstruction) {
return SmalideaInstruction.of(smaliInstruction);
}
});
}
@Nonnull
@Override
public List<? extends TryBlock<? extends ExceptionHandler>> getTryBlocks() {
return Lists.transform(smaliMethod.getCatchStatements(), new Function<SmaliCatchStatement, TryBlock<? extends ExceptionHandler>>() {
@Override
public TryBlock<? extends ExceptionHandler> apply(SmaliCatchStatement smaliCatchStatement) {
assert smaliCatchStatement != null;
return new SmalideaTryBlock(smaliCatchStatement);
}
});
}
@Nonnull
@Override
public Iterable<? extends DebugItem> getDebugItems() {
// TODO: implement this
return ImmutableList.of();
}
};
}
return null;
}
use of org.jf.dexlib2.iface.ExceptionHandler in project smali by JesusFreke.
the class TryListBuilderTest method testOverlap_Before_Middle.
@Test
public void testOverlap_Before_Middle() {
TryListBuilder tlb = new TryListBuilder();
tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException1;", 5));
tlb.addHandler(0, 7, new ImmutableExceptionHandler("LException2;", 6));
List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks = tlb.getTryBlocks();
List<? extends TryBlock> expected = ImmutableList.of(new ImmutableTryBlock(0, 5, ImmutableList.of(new ImmutableExceptionHandler("LException2;", 6))), new ImmutableTryBlock(5, 2, ImmutableList.of(new ImmutableExceptionHandler("LException1;", 5), new ImmutableExceptionHandler("LException2;", 6))), new ImmutableTryBlock(7, 3, ImmutableList.of(new ImmutableExceptionHandler("LException1;", 5))));
Assert.assertEquals(expected, tryBlocks);
}
use of org.jf.dexlib2.iface.ExceptionHandler in project smali by JesusFreke.
the class JumboStringConversionTest method testJumboStringConversion_NonMethodBuilder.
@Test
public void testJumboStringConversion_NonMethodBuilder() throws IOException {
DexBuilder dexBuilder = new DexBuilder(Opcodes.getDefault());
final List<Instruction> instructions = Lists.newArrayList();
for (int i = 0; i < 66000; i++) {
final StringReference ref = dexBuilder.internStringReference(String.format("%08d", i));
instructions.add(new Instruction21c() {
@Override
public int getRegisterA() {
return 0;
}
@Nonnull
@Override
public Reference getReference() {
return ref;
}
@Override
public int getReferenceType() {
return ReferenceType.STRING;
}
@Override
public Opcode getOpcode() {
return Opcode.CONST_STRING;
}
@Override
public int getCodeUnits() {
return getOpcode().format.size / 2;
}
});
}
instructions.add(new ImmutableInstruction10x(Opcode.RETURN_VOID));
MethodImplementation methodImpl = new MethodImplementation() {
@Override
public int getRegisterCount() {
return 1;
}
@Nonnull
@Override
public Iterable<? extends Instruction> getInstructions() {
return instructions;
}
@Nonnull
@Override
public List<? extends TryBlock<? extends ExceptionHandler>> getTryBlocks() {
return ImmutableList.of();
}
@Nonnull
@Override
public Iterable<? extends DebugItem> getDebugItems() {
return ImmutableList.of();
}
};
dexBuilder.internClassDef("Ltest;", 0, "Ljava/lang/Object;", null, null, ImmutableSet.<Annotation>of(), null, ImmutableList.of(dexBuilder.internMethod("Ltest;", "test", null, "V", 0, ImmutableSet.<Annotation>of(), methodImpl)));
MemoryDataStore dexStore = new MemoryDataStore();
dexBuilder.writeTo(dexStore);
DexBackedDexFile dexFile = new DexBackedDexFile(Opcodes.getDefault(), dexStore.getData());
ClassDef classDef = Iterables.getFirst(dexFile.getClasses(), null);
Assert.assertNotNull(classDef);
Method method = Iterables.getFirst(classDef.getMethods(), null);
Assert.assertNotNull(method);
MethodImplementation impl = method.getImplementation();
Assert.assertNotNull(impl);
List<? extends Instruction> actualInstructions = Lists.newArrayList(impl.getInstructions());
Assert.assertEquals(66001, actualInstructions.size());
for (int i = 0; i < 65536; i++) {
Assert.assertEquals(Opcode.CONST_STRING, actualInstructions.get(i).getOpcode());
Assert.assertEquals(String.format("%08d", i), ((StringReference) ((ReferenceInstruction) actualInstructions.get(i)).getReference()).getString());
}
for (int i = 65536; i < 66000; i++) {
Assert.assertEquals(Opcode.CONST_STRING_JUMBO, actualInstructions.get(i).getOpcode());
Assert.assertEquals(String.format("%08d", i), ((StringReference) ((ReferenceInstruction) actualInstructions.get(i)).getReference()).getString());
}
Assert.assertEquals(Opcode.RETURN_VOID, actualInstructions.get(66000).getOpcode());
}
Aggregations