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