use of org.jf.dexlib2.Opcodes in project smali by JesusFreke.
the class DebugInfoItem method makeAnnotator.
@Nonnull
public static SectionAnnotator makeAnnotator(@Nonnull DexAnnotator annotator, @Nonnull MapItem mapItem) {
return new SectionAnnotator(annotator, mapItem) {
@Nonnull
@Override
public String getItemName() {
return "debug_info_item";
}
@Override
public void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity) {
DexReader reader = dexFile.readerAt(out.getCursor());
int lineStart = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "line_start = %d", lineStart);
int parametersSize = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "parameters_size = %d", parametersSize);
if (parametersSize > 0) {
out.annotate(0, "parameters:");
out.indent();
for (int i = 0; i < parametersSize; i++) {
int paramaterIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "%s", StringIdItem.getOptionalReferenceAnnotation(dexFile, paramaterIndex, true));
}
out.deindent();
}
out.annotate(0, "debug opcodes:");
out.indent();
int codeAddress = 0;
int lineNumber = lineStart;
loop: while (true) {
int opcode = reader.readUbyte();
switch(opcode) {
case DebugItemType.END_SEQUENCE:
{
out.annotateTo(reader.getOffset(), "DBG_END_SEQUENCE");
break loop;
}
case DebugItemType.ADVANCE_PC:
{
out.annotateTo(reader.getOffset(), "DBG_ADVANCE_PC");
out.indent();
int addressDiff = reader.readSmallUleb128();
codeAddress += addressDiff;
out.annotateTo(reader.getOffset(), "addr_diff = +0x%x: 0x%x", addressDiff, codeAddress);
out.deindent();
break;
}
case DebugItemType.ADVANCE_LINE:
{
out.annotateTo(reader.getOffset(), "DBG_ADVANCE_LINE");
out.indent();
int lineDiff = reader.readSleb128();
lineNumber += lineDiff;
out.annotateTo(reader.getOffset(), "line_diff = +%d: %d", Math.abs(lineDiff), lineNumber);
out.deindent();
break;
}
case DebugItemType.START_LOCAL:
{
out.annotateTo(reader.getOffset(), "DBG_START_LOCAL");
out.indent();
int registerNum = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "register_num = v%d", registerNum);
int nameIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "name_idx = %s", StringIdItem.getOptionalReferenceAnnotation(dexFile, nameIndex, true));
int typeIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "type_idx = %s", TypeIdItem.getOptionalReferenceAnnotation(dexFile, typeIndex));
out.deindent();
break;
}
case DebugItemType.START_LOCAL_EXTENDED:
{
out.annotateTo(reader.getOffset(), "DBG_START_LOCAL_EXTENDED");
out.indent();
int registerNum = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "register_num = v%d", registerNum);
int nameIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "name_idx = %s", StringIdItem.getOptionalReferenceAnnotation(dexFile, nameIndex, true));
int typeIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "type_idx = %s", TypeIdItem.getOptionalReferenceAnnotation(dexFile, typeIndex));
int sigIndex = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "sig_idx = %s", StringIdItem.getOptionalReferenceAnnotation(dexFile, sigIndex, true));
out.deindent();
break;
}
case DebugItemType.END_LOCAL:
{
out.annotateTo(reader.getOffset(), "DBG_END_LOCAL");
out.indent();
int registerNum = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "register_num = v%d", registerNum);
out.deindent();
break;
}
case DebugItemType.RESTART_LOCAL:
{
out.annotateTo(reader.getOffset(), "DBG_RESTART_LOCAL");
out.indent();
int registerNum = reader.readSmallUleb128();
out.annotateTo(reader.getOffset(), "register_num = v%d", registerNum);
out.deindent();
break;
}
case DebugItemType.PROLOGUE_END:
{
out.annotateTo(reader.getOffset(), "DBG_SET_PROLOGUE_END");
break;
}
case DebugItemType.EPILOGUE_BEGIN:
{
out.annotateTo(reader.getOffset(), "DBG_SET_EPILOGUE_BEGIN");
break;
}
case DebugItemType.SET_SOURCE_FILE:
{
out.annotateTo(reader.getOffset(), "DBG_SET_FILE");
out.indent();
int nameIdx = reader.readSmallUleb128() - 1;
out.annotateTo(reader.getOffset(), "name_idx = %s", StringIdItem.getOptionalReferenceAnnotation(dexFile, nameIdx));
out.deindent();
break;
}
default:
int adjusted = opcode - 0x0A;
int addressDiff = adjusted / 15;
int lineDiff = (adjusted % 15) - 4;
codeAddress += addressDiff;
lineNumber += lineDiff;
out.annotateTo(reader.getOffset(), "address_diff = +0x%x:0x%x, line_diff = +%d:%d, ", addressDiff, codeAddress, lineDiff, lineNumber);
break;
}
}
out.deindent();
}
};
}
use of org.jf.dexlib2.Opcodes in project smali by JesusFreke.
the class AnalysisArguments method loadClassPathForDexFile.
@Nonnull
public ClassPath loadClassPathForDexFile(@Nonnull File dexFileDir, @Nonnull DexFile dexFile, boolean checkPackagePrivateAccess, int oatVersion) throws IOException {
ClassPathResolver resolver;
// regardless of the actual version of the oat file
if (oatVersion == NOT_ART) {
if (dexFile instanceof OatDexFile) {
checkPackagePrivateAccess = true;
oatVersion = ((OatDexFile) dexFile).getContainer().getOatVersion();
}
} else {
// this should always be true for ART
checkPackagePrivateAccess = true;
}
if (classPathDirectories == null || classPathDirectories.size() == 0) {
classPathDirectories = Lists.newArrayList(dexFileDir.getPath());
}
List<String> filteredClassPathDirectories = Lists.newArrayList();
if (classPathDirectories != null) {
for (String dir : classPathDirectories) {
File file = new File(dir);
if (!file.exists()) {
System.err.println(String.format("Warning: directory %s does not exist. Ignoring.", dir));
} else if (!file.isDirectory()) {
System.err.println(String.format("Warning: %s is not a directory. Ignoring.", dir));
} else {
filteredClassPathDirectories.add(dir);
}
}
}
if (bootClassPath == null) {
// TODO: we should be able to get the api from the Opcodes object associated with the dexFile..
// except that the oat version -> api mapping doesn't fully work yet
resolver = new ClassPathResolver(filteredClassPathDirectories, classPath, dexFile);
} else if (bootClassPath.size() == 1 && bootClassPath.get(0).length() == 0) {
// --bootclasspath "" is a special case, denoting that no bootclasspath should be used
resolver = new ClassPathResolver(ImmutableList.<String>of(), ImmutableList.<String>of(), classPath, dexFile);
} else {
resolver = new ClassPathResolver(filteredClassPathDirectories, bootClassPath, classPath, dexFile);
}
if (oatVersion == 0 && dexFile instanceof OatDexFile) {
oatVersion = ((OatDexFile) dexFile).getContainer().getOatVersion();
}
return new ClassPath(resolver.getResolvedClassProviders(), checkPackagePrivateAccess, oatVersion);
}
use of org.jf.dexlib2.Opcodes in project dex2jar by pxb1988.
the class SmaliTest method dotest.
private void dotest(File dexFile) throws IOException {
DexBackedDexFile dex = DexFileFactory.loadDexFile(dexFile, 14, false);
Map<String, DexClassNode> map = readDex(dexFile);
for (DexBackedClassDef def : dex.getClasses()) {
String type = def.getType();
System.out.println(type);
DexClassNode dexClassNode = map.get(type);
Assert.assertNotNull(dexClassNode);
// original
String smali = baksmali(def);
Smali.smaliFile2Node("fake.smali", smali);
{
byte[] data = toDex(dexClassNode);
DexBackedClassDef def2 = new DexBackedDexFile(new Opcodes(14, false), data).getClasses().iterator().next();
// original
String baksmali3 = baksmali(def2);
Assert.assertEquals(smali, baksmali3);
}
String psmali = pbaksmali(dexClassNode);
DexClassNode dexClassNode2 = Smali.smaliFile2Node("fake.smali", psmali);
Assert.assertEquals("cmp smalip", psmali, pbaksmali(dexClassNode2));
{
byte[] data = toDex(dexClassNode2);
DexBackedClassDef def2 = new DexBackedDexFile(new Opcodes(14, false), data).getClasses().iterator().next();
// original
String baksmali3 = baksmali(def2);
Assert.assertEquals(smali, baksmali3);
}
}
}
use of org.jf.dexlib2.Opcodes in project smali by JesusFreke.
the class DexFileFactory method loadDexContainer.
/**
* Loads a file containing 1 or more dex files
*
* If the given file is a dex or odex file, it will return a MultiDexContainer containing that single entry.
* Otherwise, for an oat or zip file, it will return an OatFile or ZipDexContainer respectively.
*
* @param file The file to open
* @param opcodes The set of opcodes to use
* @return A MultiDexContainer
* @throws DexFileNotFoundException If the given file does not exist
* @throws UnsupportedFileTypeException If the given file is not a valid dex/zip/odex/oat file
*/
public static MultiDexContainer<? extends DexBackedDexFile> loadDexContainer(@Nonnull File file, @Nonnull final Opcodes opcodes) throws IOException {
if (!file.exists()) {
throw new DexFileNotFoundException("%s does not exist", file.getName());
}
ZipDexContainer zipDexContainer = new ZipDexContainer(file, opcodes);
if (zipDexContainer.isZipFile()) {
return zipDexContainer;
}
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
try {
try {
DexBackedDexFile dexFile = DexBackedDexFile.fromInputStream(opcodes, inputStream);
return new SingletonMultiDexContainer(file.getPath(), dexFile);
} catch (DexBackedDexFile.NotADexFile ex) {
// just eat it
}
try {
DexBackedOdexFile odexFile = DexBackedOdexFile.fromInputStream(opcodes, inputStream);
return new SingletonMultiDexContainer(file.getPath(), odexFile);
} catch (DexBackedOdexFile.NotAnOdexFile ex) {
// just eat it
}
// Note: DexBackedDexFile.fromInputStream and DexBackedOdexFile.fromInputStream will reset inputStream
// back to the same position, if they fails
OatFile oatFile = null;
try {
oatFile = OatFile.fromInputStream(inputStream);
} catch (NotAnOatFileException ex) {
// just eat it
}
if (oatFile != null) {
// TODO: we should support loading earlier oat files, just not deodexing them
if (oatFile.isSupportedVersion() == OatFile.UNSUPPORTED) {
throw new UnsupportedOatVersionException(oatFile);
}
return oatFile;
}
} finally {
inputStream.close();
}
throw new UnsupportedFileTypeException("%s is not an apk, dex, odex or oat file.", file.getPath());
}
use of org.jf.dexlib2.Opcodes in project smali by JesusFreke.
the class DexWriter method writeCodeItem.
private int writeCodeItem(@Nonnull DexDataWriter writer, @Nonnull ByteArrayOutputStream ehBuf, @Nonnull MethodKey methodKey, @Nonnull List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks, @Nullable Iterable<? extends Instruction> instructions, int debugItemOffset) throws IOException {
if (instructions == null && debugItemOffset == NO_OFFSET) {
return -1;
}
numCodeItemItems++;
writer.align();
int codeItemOffset = writer.getPosition();
writer.writeUshort(classSection.getRegisterCount(methodKey));
boolean isStatic = AccessFlags.STATIC.isSet(classSection.getMethodAccessFlags(methodKey));
Collection<? extends TypeKey> parameters = typeListSection.getTypes(protoSection.getParameters(methodSection.getPrototype(methodKey)));
writer.writeUshort(MethodUtil.getParameterRegisterCount(parameters, isStatic));
if (instructions != null) {
tryBlocks = TryListBuilder.massageTryBlocks(tryBlocks);
int outParamCount = 0;
int codeUnitCount = 0;
for (Instruction instruction : instructions) {
codeUnitCount += instruction.getCodeUnits();
if (instruction.getOpcode().referenceType == ReferenceType.METHOD) {
ReferenceInstruction refInsn = (ReferenceInstruction) instruction;
MethodReference methodRef = (MethodReference) refInsn.getReference();
int paramCount = MethodUtil.getParameterRegisterCount(methodRef, InstructionUtil.isInvokeStatic(instruction.getOpcode()));
if (paramCount > outParamCount) {
outParamCount = paramCount;
}
}
}
writer.writeUshort(outParamCount);
writer.writeUshort(tryBlocks.size());
writer.writeInt(debugItemOffset);
InstructionWriter instructionWriter = InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection);
writer.writeInt(codeUnitCount);
int codeOffset = 0;
for (Instruction instruction : instructions) {
try {
switch(instruction.getOpcode().format) {
case Format10t:
instructionWriter.write((Instruction10t) instruction);
break;
case Format10x:
instructionWriter.write((Instruction10x) instruction);
break;
case Format11n:
instructionWriter.write((Instruction11n) instruction);
break;
case Format11x:
instructionWriter.write((Instruction11x) instruction);
break;
case Format12x:
instructionWriter.write((Instruction12x) instruction);
break;
case Format20bc:
instructionWriter.write((Instruction20bc) instruction);
break;
case Format20t:
instructionWriter.write((Instruction20t) instruction);
break;
case Format21c:
instructionWriter.write((Instruction21c) instruction);
break;
case Format21ih:
instructionWriter.write((Instruction21ih) instruction);
break;
case Format21lh:
instructionWriter.write((Instruction21lh) instruction);
break;
case Format21s:
instructionWriter.write((Instruction21s) instruction);
break;
case Format21t:
instructionWriter.write((Instruction21t) instruction);
break;
case Format22b:
instructionWriter.write((Instruction22b) instruction);
break;
case Format22c:
instructionWriter.write((Instruction22c) instruction);
break;
case Format22s:
instructionWriter.write((Instruction22s) instruction);
break;
case Format22t:
instructionWriter.write((Instruction22t) instruction);
break;
case Format22x:
instructionWriter.write((Instruction22x) instruction);
break;
case Format23x:
instructionWriter.write((Instruction23x) instruction);
break;
case Format30t:
instructionWriter.write((Instruction30t) instruction);
break;
case Format31c:
instructionWriter.write((Instruction31c) instruction);
break;
case Format31i:
instructionWriter.write((Instruction31i) instruction);
break;
case Format31t:
instructionWriter.write((Instruction31t) instruction);
break;
case Format32x:
instructionWriter.write((Instruction32x) instruction);
break;
case Format35c:
instructionWriter.write((Instruction35c) instruction);
break;
case Format3rc:
instructionWriter.write((Instruction3rc) instruction);
break;
case Format45cc:
instructionWriter.write((Instruction45cc) instruction);
break;
case Format4rcc:
instructionWriter.write((Instruction4rcc) instruction);
break;
case Format51l:
instructionWriter.write((Instruction51l) instruction);
break;
case ArrayPayload:
instructionWriter.write((ArrayPayload) instruction);
break;
case PackedSwitchPayload:
instructionWriter.write((PackedSwitchPayload) instruction);
break;
case SparseSwitchPayload:
instructionWriter.write((SparseSwitchPayload) instruction);
break;
default:
throw new ExceptionWithContext("Unsupported instruction format: %s", instruction.getOpcode().format);
}
} catch (RuntimeException ex) {
throw new ExceptionWithContext(ex, "Error while writing instruction at code offset 0x%x", codeOffset);
}
codeOffset += instruction.getCodeUnits();
}
if (tryBlocks.size() > 0) {
writer.align();
// filter out unique lists of exception handlers
Map<List<? extends ExceptionHandler>, Integer> exceptionHandlerOffsetMap = Maps.newHashMap();
for (TryBlock<? extends ExceptionHandler> tryBlock : tryBlocks) {
exceptionHandlerOffsetMap.put(tryBlock.getExceptionHandlers(), 0);
}
DexDataWriter.writeUleb128(ehBuf, exceptionHandlerOffsetMap.size());
for (TryBlock<? extends ExceptionHandler> tryBlock : tryBlocks) {
int startAddress = tryBlock.getStartCodeAddress();
int endAddress = startAddress + tryBlock.getCodeUnitCount();
int tbCodeUnitCount = endAddress - startAddress;
writer.writeInt(startAddress);
writer.writeUshort(tbCodeUnitCount);
if (tryBlock.getExceptionHandlers().size() == 0) {
throw new ExceptionWithContext("No exception handlers for the try block!");
}
Integer offset = exceptionHandlerOffsetMap.get(tryBlock.getExceptionHandlers());
if (offset != 0) {
// exception handler has already been written out, just use it
writer.writeUshort(offset);
} else {
// if offset has not been set yet, we are about to write out a new exception handler
offset = ehBuf.size();
writer.writeUshort(offset);
exceptionHandlerOffsetMap.put(tryBlock.getExceptionHandlers(), offset);
// check if the last exception handler is a catch-all and adjust the size accordingly
int ehSize = tryBlock.getExceptionHandlers().size();
ExceptionHandler ehLast = tryBlock.getExceptionHandlers().get(ehSize - 1);
if (ehLast.getExceptionType() == null) {
ehSize = ehSize * (-1) + 1;
}
// now let's layout the exception handlers, assuming that catch-all is always last
DexDataWriter.writeSleb128(ehBuf, ehSize);
for (ExceptionHandler eh : tryBlock.getExceptionHandlers()) {
TypeKey exceptionTypeKey = classSection.getExceptionType(eh);
int codeAddress = eh.getHandlerCodeAddress();
if (exceptionTypeKey != null) {
//regular exception handling
DexDataWriter.writeUleb128(ehBuf, typeSection.getItemIndex(exceptionTypeKey));
DexDataWriter.writeUleb128(ehBuf, codeAddress);
} else {
//catch-all
DexDataWriter.writeUleb128(ehBuf, codeAddress);
}
}
}
}
if (ehBuf.size() > 0) {
ehBuf.writeTo(writer);
ehBuf.reset();
}
}
} else {
// no instructions, all we have is the debug item offset
writer.writeUshort(0);
writer.writeUshort(0);
writer.writeInt(debugItemOffset);
writer.writeInt(0);
}
return codeItemOffset;
}
Aggregations