1 /* 2 * Copyright 2013, Google LLC 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google LLC nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 package com.android.tools.smali.dexlib2.dexbacked.raw; 32 33 import com.android.tools.smali.dexlib2.dexbacked.raw.util.DexAnnotator; 34 import com.android.tools.smali.dexlib2.util.AlignmentUtils; 35 import com.android.tools.smali.dexlib2.util.AnnotatedBytes; 36 import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile; 37 38 import javax.annotation.Nonnull; 39 import javax.annotation.Nullable; 40 41 import java.util.HashMap; 42 import java.util.Map; 43 44 public abstract class SectionAnnotator { 45 @Nonnull public final DexAnnotator annotator; 46 @Nonnull public final DexBackedDexFile dexFile; 47 public final int itemType; 48 public final int sectionOffset; 49 public final int itemCount; 50 51 protected Map<Integer, String> itemIdentities = new HashMap<>(); 52 SectionAnnotator(@onnull DexAnnotator annotator, @Nonnull MapItem mapItem)53 public SectionAnnotator(@Nonnull DexAnnotator annotator, @Nonnull MapItem mapItem) { 54 this.annotator = annotator; 55 this.dexFile = annotator.dexFile; 56 this.itemType = mapItem.getType(); 57 58 if (mapItem.getType() >= ItemType.MAP_LIST) { 59 this.sectionOffset = mapItem.getOffset() + dexFile.getBaseDataOffset(); 60 } else { 61 this.sectionOffset = mapItem.getOffset(); 62 } 63 64 this.itemCount = mapItem.getItemCount(); 65 } 66 getItemName()67 @Nonnull public abstract String getItemName(); annotateItem(@onnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity)68 protected abstract void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity); 69 70 /** 71 * Write out annotations for this section 72 * 73 * @param out The AnnotatedBytes object to annotate to 74 */ annotateSection(@onnull AnnotatedBytes out)75 public void annotateSection(@Nonnull AnnotatedBytes out) { 76 out.moveTo(sectionOffset); 77 annotateSectionInner(out, itemCount); 78 } 79 getItemOffset(int itemIndex, int currentOffset)80 protected int getItemOffset(int itemIndex, int currentOffset) { 81 return AlignmentUtils.alignOffset(currentOffset, getItemAlignment()); 82 } 83 annotateSectionInner(@onnull AnnotatedBytes out, int itemCount)84 protected void annotateSectionInner(@Nonnull AnnotatedBytes out, int itemCount) { 85 String itemName = getItemName(); 86 if (itemCount > 0) { 87 out.annotate(0, ""); 88 out.annotate(0, "-----------------------------"); 89 out.annotate(0, "%s section", itemName); 90 out.annotate(0, "-----------------------------"); 91 out.annotate(0, ""); 92 93 for (int i=0; i<itemCount; i++) { 94 out.moveTo(getItemOffset(i, out.getCursor())); 95 96 String itemIdentity = getItemIdentity(out.getCursor()); 97 if (itemIdentity != null) { 98 out.annotate(0, "[%d] %s: %s", i, itemName, itemIdentity); 99 } else { 100 out.annotate(0, "[%d] %s", i, itemName); 101 } 102 out.indent(); 103 annotateItem(out, i, itemIdentity); 104 out.deindent(); 105 } 106 } 107 } 108 getItemIdentity(int itemOffset)109 @Nullable private String getItemIdentity(int itemOffset) { 110 return itemIdentities.get(itemOffset); 111 } 112 setItemIdentity(int itemOffset, String identity)113 public void setItemIdentity(int itemOffset, String identity) { 114 itemIdentities.put(itemOffset + dexFile.getBaseDataOffset(), identity); 115 } 116 getItemAlignment()117 public int getItemAlignment() { 118 return 1; 119 } 120 } 121