RawDexFile.java revision 90f8ea9f1e9175ba33933b163c4b095f578f3d5f
1/*
2 * Copyright 2013, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32package org.jf.dexlib2.dexbacked.raw;
33
34import com.google.common.collect.ImmutableMap;
35import org.jf.dexlib2.dexbacked.DexBackedDexFile;
36import org.jf.dexlib2.dexbacked.util.FixedSizeList;
37import org.jf.dexlib2.util.AnnotatedBytes;
38
39import javax.annotation.Nonnull;
40import java.io.IOException;
41import java.io.Writer;
42import java.util.List;
43import java.util.Map;
44
45public class RawDexFile {
46    @Nonnull private final byte[] buf;
47    @Nonnull public final DexBackedDexFile dexFile;
48    @Nonnull public final HeaderItem headerItem;
49
50    public RawDexFile(byte[] buf) {
51        this.buf = buf;
52        this.dexFile = new DexBackedDexFile.Impl(buf);
53        this.headerItem = new HeaderItem(dexFile);
54    }
55
56    public int getMapOffset() {
57        return headerItem.getMapOffset();
58    }
59
60    public List<MapItem> getMapItems() {
61        final int mapOffset = getMapOffset();
62        final int mapSize = dexFile.readSmallUint(mapOffset);
63
64        return new FixedSizeList<MapItem>() {
65            @Override
66            public MapItem readItem(int index) {
67                int mapItemOffset = mapOffset + 4 + index * MapItem.ITEM_SIZE;
68                return new MapItem(dexFile, mapItemOffset);
69            }
70
71            @Override public int size() {
72                return mapSize;
73            }
74        };
75    }
76
77    private static final Map<Integer, SectionAnnotator> annotators;
78    static {
79        annotators = ImmutableMap.of(
80                ItemType.TYPE_LIST, TypeListItem.getAnnotator(),
81                ItemType.ANNOTATION_SET_REF_LIST, AnnotationSetRefList.getAnnotator());
82    }
83
84    public void dumpTo(Writer out, int width) throws IOException {
85        AnnotatedBytes annotatedBytes = new AnnotatedBytes(width);
86        HeaderItem.getAnnotator().annotateSection(annotatedBytes, dexFile, 1);
87
88        int stringCount = headerItem.getStringCount();
89        if (stringCount > 0) {
90            annotatedBytes.skipTo(headerItem.getStringOffset());
91            annotatedBytes.annotate(0, " ");
92            StringIdItem.getAnnotator().annotateSection(annotatedBytes, dexFile, stringCount);
93        }
94
95        int typeCount = headerItem.getTypeCount();
96        if (typeCount > 0) {
97            annotatedBytes.skipTo(headerItem.getTypeOffset());
98            annotatedBytes.annotate(0, " ");
99            TypeIdItem.getAnnotator().annotateSection(annotatedBytes, dexFile, typeCount);
100        }
101
102        int protoCount = headerItem.getProtoCount();
103        if (protoCount > 0) {
104            annotatedBytes.skipTo(headerItem.getProtoOffset());
105            annotatedBytes.annotate(0, " ");
106            ProtoIdItem.getAnnotator().annotateSection(annotatedBytes, dexFile, protoCount);
107        }
108
109        int fieldCount = headerItem.getFieldCount();
110        if (fieldCount > 0) {
111            annotatedBytes.skipTo(headerItem.getFieldOffset());
112            annotatedBytes.annotate(0, " ");
113            FieldIdItem.getAnnotator().annotateSection(annotatedBytes, dexFile, fieldCount);
114        }
115
116        int methodCount = headerItem.getMethodCount();
117        if (methodCount > 0) {
118            annotatedBytes.skipTo(headerItem.getMethodOffset());
119            annotatedBytes.annotate(0, " ");
120            MethodIdItem.getAnnotator().annotateSection(annotatedBytes, dexFile, methodCount);
121        }
122
123        int classCount = headerItem.getClassCount();
124        if (classCount > 0) {
125            annotatedBytes.skipTo(headerItem.getClassOffset());
126            annotatedBytes.annotate(0, " ");
127            ClassDefItem.getAnnotator().annotateSection(annotatedBytes, dexFile, classCount);
128        }
129
130        for (MapItem mapItem: getMapItems()) {
131            SectionAnnotator annotator = annotators.get(mapItem.getType());
132            if (annotator != null) {
133                annotatedBytes.skipTo(mapItem.getOffset());
134                annotator.annotateSection(annotatedBytes, dexFile, mapItem.getItemCount());
135            }
136        }
137
138        annotatedBytes.writeAnnotations(out, buf);
139    }
140}
141