• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
32 package org.jf.dexlib2.dexbacked.raw.util;
33 
34 import com.google.common.collect.Maps;
35 import com.google.common.collect.Ordering;
36 import com.google.common.primitives.Ints;
37 import org.jf.dexlib2.dexbacked.raw.*;
38 import org.jf.dexlib2.util.AnnotatedBytes;
39 
40 import javax.annotation.Nonnull;
41 import javax.annotation.Nullable;
42 import java.io.IOException;
43 import java.io.Writer;
44 import java.util.Comparator;
45 import java.util.List;
46 import java.util.Map;
47 
48 public class DexAnnotator extends AnnotatedBytes {
49     @Nonnull public final RawDexFile dexFile;
50 
51     private final Map<Integer, SectionAnnotator> annotators = Maps.newHashMap();
52     private static final Map<Integer, Integer> sectionAnnotationOrder = Maps.newHashMap();
53 
54     static {
55         int[] sectionOrder = new int[] {
56                 ItemType.MAP_LIST,
57 
58                 ItemType.HEADER_ITEM,
59                 ItemType.STRING_ID_ITEM,
60                 ItemType.TYPE_ID_ITEM,
61                 ItemType.PROTO_ID_ITEM,
62                 ItemType.FIELD_ID_ITEM,
63                 ItemType.METHOD_ID_ITEM,
64 
65                 // these need to be ordered like this, so the item identities can be propagated
66                 ItemType.CLASS_DEF_ITEM,
67                 ItemType.CLASS_DATA_ITEM,
68                 ItemType.CODE_ITEM,
69                 ItemType.DEBUG_INFO_ITEM,
70 
71                 ItemType.TYPE_LIST,
72                 ItemType.ANNOTATION_SET_REF_LIST,
73                 ItemType.ANNOTATION_SET_ITEM,
74                 ItemType.STRING_DATA_ITEM,
75                 ItemType.ANNOTATION_ITEM,
76                 ItemType.ENCODED_ARRAY_ITEM,
77                 ItemType.ANNOTATION_DIRECTORY_ITEM
78         };
79 
80         for (int i=0; i<sectionOrder.length; i++) {
sectionAnnotationOrder.put(sectionOrder[i], i)81             sectionAnnotationOrder.put(sectionOrder[i], i);
82         }
83     }
84 
DexAnnotator(@onnull RawDexFile dexFile, int width)85     public DexAnnotator(@Nonnull RawDexFile dexFile, int width) {
86         super(width);
87 
88         this.dexFile = dexFile;
89 
90         for (MapItem mapItem: dexFile.getMapItems()) {
91             switch (mapItem.getType()) {
92                 case ItemType.HEADER_ITEM:
93                     annotators.put(mapItem.getType(), HeaderItem.makeAnnotator(this, mapItem));
94                     break;
95                 case ItemType.STRING_ID_ITEM:
96                     annotators.put(mapItem.getType(), StringIdItem.makeAnnotator(this, mapItem));
97                     break;
98                 case ItemType.TYPE_ID_ITEM:
99                     annotators.put(mapItem.getType(), TypeIdItem.makeAnnotator(this, mapItem));
100                     break;
101                 case ItemType.PROTO_ID_ITEM:
102                     annotators.put(mapItem.getType(), ProtoIdItem.makeAnnotator(this, mapItem));
103                     break;
104                 case ItemType.FIELD_ID_ITEM:
105                     annotators.put(mapItem.getType(), FieldIdItem.makeAnnotator(this, mapItem));
106                     break;
107                 case ItemType.METHOD_ID_ITEM:
108                     annotators.put(mapItem.getType(), MethodIdItem.makeAnnotator(this, mapItem));
109                     break;
110                 case ItemType.CLASS_DEF_ITEM:
111                     annotators.put(mapItem.getType(), ClassDefItem.makeAnnotator(this, mapItem));
112                     break;
113                 case ItemType.MAP_LIST:
114                     annotators.put(mapItem.getType(), MapItem.makeAnnotator(this, mapItem));
115                     break;
116                 case ItemType.TYPE_LIST:
117                     annotators.put(mapItem.getType(), TypeListItem.makeAnnotator(this, mapItem));
118                     break;
119                 case ItemType.ANNOTATION_SET_REF_LIST:
120                     annotators.put(mapItem.getType(), AnnotationSetRefList.makeAnnotator(this, mapItem));
121                     break;
122                 case ItemType.ANNOTATION_SET_ITEM:
123                     annotators.put(mapItem.getType(), AnnotationSetItem.makeAnnotator(this, mapItem));
124                     break;
125                 case ItemType.CLASS_DATA_ITEM:
126                     annotators.put(mapItem.getType(), ClassDataItem.makeAnnotator(this, mapItem));
127                     break;
128                 case ItemType.CODE_ITEM:
129                     annotators.put(mapItem.getType(), CodeItem.makeAnnotator(this, mapItem));
130                     break;
131                 case ItemType.STRING_DATA_ITEM:
132                     annotators.put(mapItem.getType(), StringDataItem.makeAnnotator(this, mapItem));
133                     break;
134                 case ItemType.DEBUG_INFO_ITEM:
135                     annotators.put(mapItem.getType(), DebugInfoItem.makeAnnotator(this, mapItem));
136                     break;
137                 case ItemType.ANNOTATION_ITEM:
138                     annotators.put(mapItem.getType(), AnnotationItem.makeAnnotator(this, mapItem));
139                     break;
140                 case ItemType.ENCODED_ARRAY_ITEM:
141                     annotators.put(mapItem.getType(), EncodedArrayItem.makeAnnotator(this, mapItem));
142                     break;
143                 case ItemType.ANNOTATION_DIRECTORY_ITEM:
144                     annotators.put(mapItem.getType(), AnnotationDirectoryItem.makeAnnotator(this, mapItem));
145                     break;
146                 default:
147                     throw new RuntimeException(String.format("Unrecognized item type: 0x%x", mapItem.getType()));
148             }
149         }
150     }
151 
writeAnnotations(Writer out)152     public void writeAnnotations(Writer out) throws IOException {
153         List<MapItem> mapItems = dexFile.getMapItems();
154         // sort the map items based on the order defined by sectionAnnotationOrder
155         Ordering<MapItem> ordering = Ordering.from(new Comparator<MapItem>() {
156             @Override public int compare(MapItem o1, MapItem o2) {
157                 return Ints.compare(sectionAnnotationOrder.get(o1.getType()), sectionAnnotationOrder.get(o2.getType()));
158             }
159         });
160 
161         mapItems = ordering.immutableSortedCopy(mapItems);
162 
163         try {
164             for (MapItem mapItem: mapItems) {
165                 SectionAnnotator annotator = annotators.get(mapItem.getType());
166                 annotator.annotateSection(this);
167             }
168         } finally {
169             dexFile.writeAnnotations(out, this);
170         }
171     }
172 
173     @Nullable
getAnnotator(int itemType)174     public SectionAnnotator getAnnotator(int itemType) {
175         return annotators.get(itemType);
176     }
177 }
178