private void growBufferIfNeeded(int minSize) { if (minSize > size) { if (minSize > buf.length) { int newSize = getNewBufferSize(buf.length, minSize); if (newSize < minSize) throw new IndexOutOfBoundsException(); buf = Arrays.copyOf(buf, newSize); } size = minSize; } }
private static DexDataWriter outputAt(DexDataStore dataStore, int filePosition) throws IOException { return new DexDataWriter(dataStore.outputAt(filePosition), filePosition); }
public void writeTo(@Nonnull DexDataStore dest) throws IOException { this.writeTo(dest, MemoryDeferredOutputStream.getFactory()); }
private void build() throws AndrolibException { try { DexBuilder dexBuilder; if (mApiLevel > 0) { dexBuilder = new DexBuilder(Opcodes.forApi(mApiLevel)); } else { dexBuilder = new DexBuilder(Opcodes.getDefault()); } for (String fileName : mSmaliDir.getDirectory().getFiles(true)) { buildFile(fileName, dexBuilder); } dexBuilder.writeTo(new FileDataStore( new File(mDexFile.getAbsolutePath()))); } catch (IOException | DirectoryException ex) { throw new AndrolibException(ex); } }
/** * Writes all built dex files to the given folder. * * @param folder * the output folder * @return File handles to all written dex files * @throws IOException * when failed to create {@link FileDataStore} */ public List<File> writeTo(String folder) throws IOException { final List<File> result = new ArrayList<>(dexPools.size()); for (DexPool dexPool : dexPools) { int count = result.size(); // name dex files: classes.dex, classes2.dex, classes3.dex, etc. File file = new File(folder, "classes" + (count == 0 ? "" : count + 1) + ".dex"); result.add(file); FileDataStore fds = new FileDataStore(file); dexPool.writeTo(fds); fds.close(); } return result; } }
private void updateSignature(@Nonnull DexDataStore dataStore) throws IOException { MessageDigest md; try { md = MessageDigest.getInstance("SHA-1"); } catch (NoSuchAlgorithmException ex) { throw new RuntimeException(ex); } byte[] buffer = new byte[4 * 1024]; InputStream input = dataStore.readAt(HeaderItem.SIGNATURE_DATA_START_OFFSET); int bytesRead = input.read(buffer); while (bytesRead >= 0) { md.update(buffer, 0, bytesRead); bytesRead = input.read(buffer); } byte[] signature = md.digest(); if (signature.length != HeaderItem.SIGNATURE_SIZE) { throw new RuntimeException("unexpected digest write: " + signature.length + " bytes"); } // write signature OutputStream output = dataStore.outputAt(HeaderItem.SIGNATURE_OFFSET); output.write(signature); output.close(); }
@Override public void write(byte[] bytes, int off, int len) throws IOException { output.write(bytes, off, len); writtenBytes += len; }
writeAnnotationSetRefs(offsetWriter); writeAnnotationDirectories(offsetWriter); writeDebugAndCodeItems(offsetWriter, tempFactory.makeDeferredOutputStream()); writeClasses(indexWriter, offsetWriter); updateChecksum(dest); } finally { dest.close();
@Override public DeferredOutputStream makeDeferredOutputStream() { return new MemoryDeferredOutputStream(bufferSize); } };
dexBuilder.writeTo(new FileDataStore(new File(options.outputDexFile)));
private void updateChecksum(@Nonnull DexDataStore dataStore) throws IOException { Adler32 a32 = new Adler32(); byte[] buffer = new byte[4 * 1024]; InputStream input = dataStore.readAt(HeaderItem.CHECKSUM_DATA_START_OFFSET); int bytesRead = input.read(buffer); while (bytesRead >= 0) { a32.update(buffer, 0, bytesRead); bytesRead = input.read(buffer); } // write checksum, utilizing logic in DexWriter to write the integer value properly OutputStream output = dataStore.outputAt(HeaderItem.CHECKSUM_OFFSET); DexDataWriter.writeInt(output, (int)a32.getValue()); output.close(); }
@Override public void write(int i) throws IOException { output.write(i); writtenBytes++; }
@Test public void emptyingATryBlockWithTwoHandlersWhichCreatesNullStartAndEndLocationsIsRemovedWithoutIncident() throws IOException { manipulator = OptimizerTester.getGraphManipulator(CLASS_NAME, "tryBlockWithTwoCatches()V"); assertEquals(2, manipulator.getTryBlocks().size()); manipulator.removeInstruction(0); assertEquals(0, manipulator.getTryBlocks().size()); // Exception is thrown when saving. Make sure doesn't happen. ClassManager classManager = manipulator.getVM().getClassManager(); File out = File.createTempFile("test", "simplify"); classManager.getDexBuilder().writeTo(new FileDataStore(out)); out.delete(); }
@Override public void write(byte[] bytes) throws IOException { output.write(bytes); writtenBytes += bytes.length; }
public void run(String[] args) throws IOException, UnhandledVirtualException { opts = getOptions(args); setLogLevel(opts); log.info("Options:\n{}", opts.toString()); RuntimeStats stats = new RuntimeStats(); stats.begin(); vm = vmFactory.build( opts.getInFile(), opts.getOutputAPILevel(), opts.getMaxAddressVisits(), opts.getMaxCallDepth(), opts.getMaxMethodVisits(), opts.getMaxExecutionTime() ); ClassManager classManager = vm.getClassManager(); Map<String, Collection<VirtualMethod>> targetClassNameToMethods = collectTargetClassNameToMethods(classManager, opts); stats.startClasses(targetClassNameToMethods.keySet()); for (Map.Entry<String, Collection<VirtualMethod>> entry : targetClassNameToMethods.entrySet()) { stats.incrementCurrentClassIndex(); String className = entry.getKey(); Collection<VirtualMethod> methods = entry.getValue(); System.out.println("[" + stats.getCurrentClassIndex() + " / " + stats.getTotalClasses() + "] Processing top level class " + className); executeMethods(methods, classManager, stats); } stats.end(); System.out.println("Simplification complete:\n" + stats.getStats()); System.out.println(Optimizer.getTotalOptimizationCounts()); System.out.println("Writing output to " + opts.getOutFile()); classManager.getDexBuilder().writeTo(new FileDataStore(opts.getOutDexFile())); if (opts.isZip()) { Files.copy(opts.getInFile().toPath(), opts.getOutFile().toPath(), StandardCopyOption.REPLACE_EXISTING); updateZip(opts.getOutFile(), opts.getOutDexFile(), "classes.dex"); } }
@Override public void write(int i) throws IOException { output.write(i); writtenBytes++; }
final FileDataStore fileDataStore = new FileDataStore(dest); dexBuilder.writeTo(fileDataStore); final String md5 = MD5.getMD5(dest);
@Override public void write(byte[] bytes) throws IOException { output.write(bytes); writtenBytes += bytes.length; }
@Override public void write(byte[] bytes, int off, int len) throws IOException { output.write(bytes, off, len); writtenBytes += len; }