/** * Validates an encoded debug info stream against data used to encode it, throwing an exception if * they do not match. Used to validate the encoder. * * @param info encoded debug info * @param file {@code non-null;} file to refer to during decoding * @param ref {@code non-null;} method whose info is being decoded * @param code {@code non-null;} original code object that was encoded * @param isStatic whether the method is static */ public static void validateEncode( byte[] info, DexFile file, CstMethodRef ref, DalvCode code, boolean isStatic) { PositionList pl = code.getPositions(); LocalList ll = code.getLocals(); DalvInsnList insns = code.getInsns(); int codeSize = insns.codeSize(); int countRegisters = insns.getRegistersSize(); try { validateEncode0(info, codeSize, countRegisters, isStatic, ref, file, pl, ll); } catch (RuntimeException ex) { System.err.println("instructions:"); insns.debugPrint(System.err, " ", true); System.err.println("local list:"); ll.debugPrint(System.err, " "); throw ExceptionWithContext.withContext(ex, "while processing " + ref.toHuman()); } }
/** * Helper for {@link #encode} to do most of the work. * * @param file null-ok; file to refer to during encoding * @param prefix null-ok; prefix to attach to each line of output * @param debugPrint null-ok; if specified, an alternate output for annotations * @param out null-ok; if specified, where annotations should go * @param consume whether to claim to have consumed output for <code>out</code> * @return non-null; the encoded array */ private byte[] encode0( DexFile file, String prefix, PrintWriter debugPrint, AnnotatedOutput out, boolean consume) { PositionList positions = code.getPositions(); LocalList locals = code.getLocals(); DalvInsnList insns = code.getInsns(); int codeSize = insns.codeSize(); int regSize = insns.getRegistersSize(); DebugInfoEncoder encoder = new DebugInfoEncoder(positions, locals, file, codeSize, regSize, isStatic, ref); byte[] result; if ((debugPrint == null) && (out == null)) { result = encoder.convert(); } else { result = encoder.convertAndAnnotate(prefix, debugPrint, out, consume); } return result; }
/** Helper that updates the dex statistics. */ private static void updateDexStatistics( CfOptions cfOptions, DexOptions dexOptions, RopMethod optRmeth, RopMethod nonOptRmeth, LocalVariableInfo locals, int paramSize, int originalByteCount) { /* * Run rop->dex again on optimized vs. non-optimized method to * collect statistics. We have to totally convert both ways, * since converting the "real" method getting added to the * file would corrupt it (by messing with its constant pool * indices). */ DalvCode optCode = RopTranslator.translate(optRmeth, cfOptions.positionInfo, locals, paramSize, dexOptions); DalvCode nonOptCode = RopTranslator.translate(nonOptRmeth, cfOptions.positionInfo, locals, paramSize, dexOptions); /* * Fake out the indices, so code.getInsns() can work well enough * for the current purpose. */ DalvCode.AssignIndicesCallback callback = new DalvCode.AssignIndicesCallback() { public int getIndex(Constant cst) { // Everything is at index 0! return 0; } }; optCode.assignIndices(callback); nonOptCode.assignIndices(callback); CodeStatistics.updateDexStatistics(nonOptCode, optCode); CodeStatistics.updateOriginalByteCount(originalByteCount); }