dx 生成 DEX文件流程分析

命令

dx -JXms16M -JXmx2048M --dex   --output=. /classes.dex     ./classes.jar

dalvik/dx/etc/dx

37 jarfile=dx.jar

38 libdir="$progdir"

39

40 if [ ! -r "$libdir/$jarfile" ];then

41     #set dx.jar location for the SDK case

42    libdir="$libdir/lib"

43 fi

88

 89 exec java $javaOpts-jar "$jarpath" "$@"

调用过程

dx/com/android/dx/command/Main.java

88     public static voidmain(String[] args) {

89        boolean gotCmd = false;

90        boolean showUsage = false;

91

92        try {

93            for (int i = 0; i < args.length; i++) {

94                 String arg = args[i];

95                 if (arg.equals("--")|| !arg.startsWith("--")) {

96                     gotCmd = false;

97                     showUsage = true;

98                     break;

99                 }

100

101                 gotCmd = true;

102                 if(arg.equals("--dex")) {

103                    com.android.dx.command.dexer.Main.main(without(args, i));

104                    break;

105                 } else if(arg.equals("--dump")) {

106                    com.android.dx.command.dump.Main.main(without(args, i));

107                     break;

com/android/dx/command/dexer/Main.java

195     public static voidmain(String[] argArray) throws IOException {

196        Arguments arguments = new Arguments();

197        arguments.parse(argArray);

198

 199         int result = run(arguments);

200        if (result != 0) {

201            System.exit(result);

202         }

203    }

210     public static intrun(Arguments arguments) throws IOException {

211        // Reset the error count to start fresh.

212        errors = 0;

213        // empty the list, so that  toolsthat load dx and keep it around

214        // for multiple runs don't reuse older buffers.

215        libraryDexBuffers.clear();

216

217        args = arguments;

218        args.makeOptionsObjects();

219

220        OutputStream humanOutRaw = null;

221        if (args.humanOutName != null) {

222            humanOutRaw = openOutput(args.humanOutName);

223            humanOutWriter = new OutputStreamWriter(humanOutRaw);

224        }

225

226        try {

227            if (args.multiDex) {

228                return runMultiDex();

229            } else {

 230                 return runMonoDex();

231            }

232        } finally {

233            closeOutput(humanOutRaw);

234        }

235    }

249    private static int runMonoDex()throws IOException {

250

251        File incrementalOutFile = null;

252        if (args.incremental) {

253            if (args.outName == null) {

254                 System.err.println(

255                         "error: noincremental output name specified");

256                 return -1;

257            }

258            incrementalOutFile = new File(args.outName);

259            if (incrementalOutFile.exists()) {

260                 minimumFileAge =incrementalOutFile.lastModified();

261             }

262        }

263

 264         if (!processAllFiles()) {

265            return 1;

266        }

267

268        if (args.incremental && !anyFilesProcessed) {

269            return 0; // this was a no-op incremental build

270         }

271

272        // this array is null if no classes were defined

273        byte[] outArray = null;

274

275        if (!outputDex.isEmpty()) {

 276             outArray = writeDex();

277

278            if (outArray == null) {

279                return 2;

280            }

281        }

282

283        if (args.incremental) {

284            outArray = mergeIncremental(outArray, incrementalOutFile);

285        }

286

287        outArray = mergeLibraryDexBuffers(outArray);

288

289        if (args.jarOutput) {

290            // Effectively free up the (often massive) DexFile memory.

291            outputDex = null;

292

293            if (outArray != null) {

294                outputResources.put(DexFormat.DEX_IN_JAR_NAME, outArray);

295            }

296            if (!createJar(args.outName)) {

297                 return 3;

298            }

299        } else if (outArray != null && args.outName != null) {

 300             OutputStream out =openOutput(args.outName);

 301             out.write(outArray);

302            closeOutput(out);

303        }

304

305        return 0;

306    }

748     private static byte[]writeDex() {

749        byte[] outArray = null;

750

751        try {

752            try {

753                 if (args.methodToDump != null){

754                     /*

755                      * Simply dump therequested method. Note: The call

756                      * to toDex() is requiredjust to get the underlying

757                      * structures ready.

758                      */

 759                     outputDex.toDex(null,false);

760                     dumpMethod(outputDex,args.methodToDump, humanOutWriter);

761                 } else {

762                     /*

763                      * This is the usual case:Create an output .dex file,

764                      * and write it, dump it,etc.

765                      */

 766                     outArray =outputDex.toDex(humanOutWriter, args.verboseDump);

767                 }

768

769                 if (args.statistics) {

770                    DxConsole.out.println(outputDex.getStatistics().toHuman());

771                 }

772            } finally {

773                 if (humanOutWriter != null) {

774                     humanOutWriter.flush();

775                 }

776            }

777        } catch (Exception ex) {

778            if (args.debug) {

779                DxConsole.err.println("\ntrouble writing output:");

780                ex.printStackTrace(DxConsole.err);

781            } else {

782                DxConsole.err.println("\ntrouble writing output: " +

783                                   ex.getMessage());

784            }

785            return null;

786        }

787

788        return outArray;

789    }

dx/src//com/android/dx/dex/file/DexFile.java

211     public byte[]toDex(Writer humanOut, boolean verbose)

212        throws IOException {

213        boolean annotate = (humanOut != null);

214        ByteArrayAnnotatedOutput result = toDex0(annotate, verbose);

215

216        if (annotate) {

217            result.writeAnnotationsTo(humanOut);

218        }

219

220        return result.getArray();

221    }

492     private ByteArrayAnnotatedOutputtoDex0(boolean annotate,

493             boolean verbose) {

494        /*

495         * The following is ordered so that the prepare() calls which

496         * add items happen before the calls to the sections that get

497         * added to.

498         */

499

500        classDefs.prepare();

501        classData.prepare();

502        wordData.prepare();

503        byteData.prepare();

504        methodIds.prepare();

505        fieldIds.prepare();

506        protoIds.prepare();

507        typeLists.prepare();

508        typeIds.prepare();

509        stringIds.prepare();

510        stringData.prepare();

511        header.prepare();

512

513        // Place the sections within the file.

514

515        int count = sections.length;

516        int offset = 0;

517

518        for (int i = 0; i < count; i++) {

519             Section one = sections[i];

520             int placedAt =one.setFileOffset(offset);

521             if (placedAt < offset) {

522                 throw newRuntimeException("bogus placement for section " + i);

523             }

524

525             try {

526                 if (one == map) {

527                     /*

528                      * Inform the map of allthe sections, and add it

529                      * to the file. This canonly be done after all

530                      * the other items havebeen sorted and placed.

531                      */

532                     MapItem.addMap(sections,map);

533                    map.prepare();

534                 }

535

536                 if (one instanceofMixedItemSection) {

537                     /*

538                      * Place the items of aMixedItemSection that just

539                      * got placed.

540                      */

541                     ((MixedItemSection)one).placeItems();

542                 }

543

544                 offset = placedAt +one.writeSize();

545             } catch (RuntimeException ex) {

546                 throw ExceptionWithContext.withContext(ex,

547                         "...while writingsection " + i);

548             }

549        }

550

551         // Write out all thesections.

552

553        fileSize = offset;

554        byte[] barr = new byte[fileSize];

555         ByteArrayAnnotatedOutput out = newByteArrayAnnotatedOutput(barr);

556

557        if (annotate) {

558             out.enableAnnotations(dumpWidth,verbose);

559        }

560

561        for (int i = 0; i < count; i++) {

562             try {

563                 Section one = sections[i];

564                 int zeroCount =one.getFileOffset() - out.getCursor();

565                 if (zeroCount < 0) {

566                     throw newExceptionWithContext("excess write of " +

567                             (-zeroCount));

568                 }

569                out.writeZeroes(one.getFileOffset() - out.getCursor());

570                one.writeTo(out);

571             } catch (RuntimeException ex) {

572                 ExceptionWithContext ec;

573                 if (ex instanceofExceptionWithContext) {

574                     ec =(ExceptionWithContext) ex;

575                 } else {

576                     ec = newExceptionWithContext(ex);

577                 }

578                 ec.addContext("...whilewriting section " + i);

579                 throw ec;

580             }

581        }

582

583        if (out.getCursor() != fileSize) {

584             throw newRuntimeException("foreshortened write");

585        }

586

./com/android/dx/dex/file/Section.java

 

145     public final voidwriteTo(AnnotatedOutput out) {

146        throwIfNotPrepared();

147        align(out);

148

149        int cursor = out.getCursor();

150

151        if (fileOffset < 0) {

152             fileOffset = cursor;

153        } else if (fileOffset != cursor) {

154             throw newRuntimeException("alignment mismatch: for " + this +

155                                        ",at " + cursor +

156                                        ",but expected " + fileOffset);

157        }

158

159        if (out.annotates()) {

160             if (name != null) {

161                 out.annotate(0, "\n"+ name + ":");

162             } else if (cursor != 0) {

163                 out.annotate(0,"\n");

164            }

165        }

166

167         writeTo0(out);

168    }

./com/android/dx/dex/file/UniformItemSection.java

81    protected final void writeTo0(AnnotatedOutput out) {

82        DexFile file = getFile();

83        int alignment = getAlignment();

84

 85         for (Item one : items()) {

 86             one.writeTo(file, out);

 87             out.alignTo(alignment);

88        }

89     }

com/android/dx/dex/file/HeaderItem.java

56     public voidwriteTo(DexFile file, AnnotatedOutput out) {

57        int mapOff = file.getMap().getFileOffset();

58        Section firstDataSection = file.getFirstDataSection();

59        Section lastDataSection = file.getLastDataSection();

60        int dataOff = firstDataSection.getFileOffset();

61         int dataSize =lastDataSection.getFileOffset() +

62            lastDataSection.writeSize() - dataOff;

63

64        String magic = file.getDexOptions().getMagic();

65

66        if (out.annotates()) {

67            out.annotate(8, "magic: " + new CstString(magic).toQuoted());

68            out.annotate(4, "checksum");

69            out.annotate(20, "signature");

70            out.annotate(4, "file_size:      " +

71                         Hex.u4(file.getFileSize()));

72            out.annotate(4, "header_size:    " + Hex.u4(SizeOf.HEADER_ITEM));

73            out.annotate(4, "endian_tag:     " + Hex.u4(DexFormat.ENDIAN_TAG));

74            out.annotate(4, "link_size:      0");

75            out.annotate(4, "link_off:       0");

76            out.annotate(4, "map_off:        " + Hex.u4(mapOff));

77        }

78

79        // Write the magic number.

80        for (int i = 0; i < 8; i++) {

 81             out.writeByte(magic.charAt(i));

82        }

83

84        // Leave space for the checksum and signature.

85        out.writeZeroes(24);

86

87        out.writeInt(file.getFileSize());

88        out.writeInt(SizeOf.HEADER_ITEM);

89        out.writeInt(DexFormat.ENDIAN_TAG);

90

91        /*

92         * Write zeroes for the link sizeand data, as the output

93         * isn't a staticly linked file.

94         */

95        out.writeZeroes(8);

96

97        out.writeInt(mapOff);

98

 99         // Write out each section's respectiveheader part.

100        file.getStringIds().writeHeaderPart(out);

101        file.getTypeIds().writeHeaderPart(out);

102        file.getProtoIds().writeHeaderPart(out);

103        file.getFieldIds().writeHeaderPart(out);

104        file.getMethodIds().writeHeaderPart(out);

105        file.getClassDefs().writeHeaderPart(out);

106

107        if (out.annotates()) {

108             out.annotate(4,"data_size:       " +Hex.u4(dataSize));

109             out.annotate(4,"data_off:        " +Hex.u4(dataOff));

110        }

111

112        out.writeInt(dataSize);

113        out.writeInt(dataOff);

114    }

115 }

类处理过程

Dx/src/com/android/dx/command/dexer/Main.java

processAllFiles –》 processOne –》 processFileBytes –》 run@ParallelProcessor–》 processFileBytes

 

 

606     private static booleanprocessFileBytes(String name, long lastModified, byte[] bytes) {

607        boolean isClass = name.endsWith(".class");

608        boolean isClassesDex = name.equals(DexFormat.DEX_IN_JAR_NAME);

609        boolean keepResources = (outputResources != null);

610

611        if (!isClass && !isClassesDex && !keepResources) {

612            if (args.verbose) {

613                DxConsole.out.println("ignored resource " + name);

614             }

615            return false;

616        }

617

618        if (args.verbose) {

619            DxConsole.out.println("processing " + name + "...");

620        }

621

622        String fixedName = fixPath(name);

623

624        if (isClass) {

625

626            if (keepResources && args.keepClassesInJar) {

627                 synchronized (outputResources){

628                    outputResources.put(fixedName, bytes);

629                 }

630            }

631            if (lastModified < minimumFileAge) {

632                 return true;

633            }

 634             return processClass(fixedName,bytes);

635        } else if (isClassesDex) {

636            synchronized (libraryDexBuffers) {

637                 libraryDexBuffers.add(bytes);

638            }

639            return true;

640        } else {

641            synchronized (outputResources) {

642                 outputResources.put(fixedName,bytes);

643            }

644             return true;

645        }

646    }

656     private static booleanprocessClass(String name, byte[] bytes) {

657        if (! args.coreLibrary) {

658            checkClassName(name);

659        }

660

661        DirectClassFile cf =

662            new DirectClassFile(bytes, name, args.cfOptions.strictNameCheck);

663

664        cf.setAttributeFactory(StdAttributeFactory.THE_ONE);

665        cf.getMagic();

666

667        int numMethodIds = outputDex.getMethodIds().items().size();

668        int numFieldIds = outputDex.getFieldIds().items().size();

669        int numTypeIds = outputDex.getTypeIds().items().size();

670        int constantPoolSize = cf.getConstantPool().size();

671

672         if (args.multiDex &&((numMethodIds + constantPoolSize > args.maxNumberOfIdxPerDex) ||

673            (numFieldIds + constantPoolSize > args.maxNumberOfIdxPerDex) ||

674            (numTypeIds + constantPoolSize

675                     /* annotation added by dxare not counted in numTypeIds */

676                     +AnnotationUtils.DALVIK_ANNOTATION_NUMBER

677                     >args.maxNumberOfIdxPerDex))) {

 678           createDexFile();

679        }

680

681        try {

682             ClassDefItem clazz =

683                 CfTranslator.translate(cf,bytes, args.cfOptions, args.dexOptions, outputDex);

684            synchronized (outputDex) {

 685                 outputDex.add(clazz);

686            }

687            return true;

688

689        } catch (ParseException ex) {

690            DxConsole.err.println("\ntrouble processing:");

691            if (args.debug) {

692                ex.printStackTrace(DxConsole.err);

693            } else {

694                ex.printContext(DxConsole.err);

695            }

696        }

697        errors++;

698        return false;

699    }

700

dx 生成 DEX文件流程分析相关推荐

  1. 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )

    文章目录 前言 一.DexPrepare.cpp 中 rewriteDex() 方法分析 二.DvmDex.cpp 中 dvmDexFileOpenPartial() 方法分析 ( 脱壳点 ) 三.D ...

  2. 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmContinueOptimizati() 函数分析 )

    文章目录 前言 一.DexPrepare.cpp 中 dvmContinueOptimizati() 方法分析 前言 上一篇博客 [Android 逆向]整体加固脱壳 ( DEX 优化流程分析 | D ...

  3. 【Android 安全】DEX 加密 ( Java 工具开发 | 解压 apk 文件 | 加密生成 dex 文件 | 打包未签名 apk 文件 | 文件解压缩相关代码 )

    文章目录 一.解压 apk 文件 二.加密生成 dex 文件 三.打包未签名 apk 文件 四.完整代码示例 五.文件解压缩相关代码 六.执行结果 参考博客 : [Android 安全]DEX 加密 ...

  4. 【Android 安全】DEX 加密 ( Java 工具开发 | 生成 dex 文件 | Java 命令行执行 )

    文章目录 一.生成 dex 文件 二.生成 dex 文件代码示例 三.生成 dex 结果 参考博客 : [Android 安全]DEX 加密 ( 常用 Android 反编译工具 | apktool ...

  5. .java生成dex文件

    参考:http://www.android100.org/html/201502/26/123364.html 首先第一个是 jar 文件的制作,Java 里面直接把 .class 文件打包到 .ja ...

  6. 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )

    文章目录 前言 一.DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 二./bin/dexopt 源码分析 前言 上一篇博客 [Android 逆向]整体加固脱壳 ...

  7. 如何手动生成Dump文件并分析Dump文件

    大家都知道,当服务器出现蓝屏问题时,我们需要获取系统所产生的DUMP文件进行分析,如何确保在系统问题发生时,可以正确的生成所需要的DUMP文件呢?我们需要做如下检查: 1).右键点击"我的电 ...

  8. 生成验证码的流程分析.

    浏览器解析页面, 携带uuid向服务器发送请求获取图片,  服务器生成图片验证码, 返回图片本身给浏览器,  客户端根据图片输入验证码内容, 把输入的内容发送给服务器, 服务器对比输入的验证码是否正确 ...

  9. 一步步手动实现热修复(一)-dex文件的生成与加载

    *本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 热修复技术自从QQ空间团队搞出来之后便渐渐趋于成熟. 我们这个系列主要介绍如何一步步手动实现基本的热修复功能,无需使用第三方框架. ...

最新文章

  1. PHP将死。何以为继?
  2. 非模态对话框的销毁及消息的发送顺序
  3. 如何用 Tensorflow 搭建神经网络-了解神经网络基本概念
  4. 用C语言写烟花,给心中的那个人看!
  5. cadence17.2小白eda365skill 安装教程
  6. 三容水箱液位控制系统_基于Labview软件编程的三容水箱液位控制系统
  7. 微信也能开门?微信开门解决方案来了
  8. OC桥接Swift学习记录
  9. 新媒体运营:23种免费获取流量的运营套路 ,你知道几种? 黎想
  10. HTML5+CSS大作业——三八女人节主题设计(1页)
  11. 经典的搞笑反转段子,真是笑死人不偿命
  12. 通过线性回归模型及优化实现AQI分析与预测
  13. 0x0EA772D7 (msvcr80.dll) 处有未经处理的异常: 0xC000041D: 用户回调期间遇到未经处理的异常。。
  14. C语言基础1:初识C语言(转义、注释;数组、操作符、反码、补码、static、define、指针、结构体常变量;局部变量;作用域、生命周期)
  15. 大数据培训技术使用spark对phoenix的读写
  16. typora中输入数学公式
  17. 在学习JavaScript的过程
  18. 2022-2028全球机载温度传感装置行业调研及趋势分析报告
  19. 控制器程序格式——bin/hex/SREC
  20. Android App Icon 替换

热门文章

  1. 银行卡又入账1579元,我错怪老东家了
  2. mysql分区表详解_详解MySQL分区表
  3. Idea首次提交项目到新建的git仓库
  4. 微信小程序组件样式隔离
  5. 利用MATLAB编程实现系统传递函数的构建以及它们之间进行串联、并联、反馈时的构建方法
  6. 园林绿化app开发功能
  7. 美国知名天使投资人列出愿投资的30大创意方向
  8. java根据商品编号查找商品_查询商品分类下的所有商品(分类级别不限)
  9. audio console无法连接到RPC服务
  10. Word常用快捷指令