1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2008 The Android Open Source Project 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License. 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License. 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.dex.file; 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.dex.code.CatchHandlerList; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.dex.code.CatchTable; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.dex.code.DalvCode; 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.AnnotatedOutput; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.ByteArrayAnnotatedOutput; 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.Hex; 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.PrintWriter; 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.Map; 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.TreeMap; 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * List of exception handlers (tuples of covered range, catch type, 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * handler address) for a particular piece of code. Instances of this 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * class correspond to a {@code try_item[]} and a 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code catch_handler_item[]}. 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class CatchStructs { 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the size of a {@code try_item}: a {@code uint} 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * and two {@code ushort}s 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static final int TRY_ITEM_WRITE_SIZE = 4 + (2 * 2); 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} code that contains the catches */ 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final DalvCode code; 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} the underlying table; set in 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #finishProcessingIfNecessary} 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private CatchTable table; 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} the encoded handler list, if calculated; set in 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #encode} 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private byte[] encodedHandlers; 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * length of the handlers header (encoded size), if known; used for 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * annotation 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private int encodedHandlerHeaderSize; 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} map from handler lists to byte offsets, if calculated; set in 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #encode} 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private TreeMap<CatchHandlerList, Integer> handlerOffsets; 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param code {@code non-null;} code that contains the catches 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public CatchStructs(DalvCode code) { 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.code = code; 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.table = null; 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.encodedHandlers = null; 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.encodedHandlerHeaderSize = 0; 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.handlerOffsets = null; 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Finish processing the catches, if necessary. 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private void finishProcessingIfNecessary() { 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (table == null) { 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson table = code.getCatches(); 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the size of the tries list, in entries. 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code >= 0;} the tries list size 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int triesSize() { 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson finishProcessingIfNecessary(); 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return table.size(); 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Does a human-friendly dump of this instance. 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param out {@code non-null;} where to dump 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param prefix {@code non-null;} prefix to attach to each line of output 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void debugPrint(PrintWriter out, String prefix) { 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson annotateEntries(prefix, out, null); 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Encodes the handler lists. 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param file {@code non-null;} file this instance is part of 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void encode(DexFile file) { 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson finishProcessingIfNecessary(); 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson TypeIdsSection typeIds = file.getTypeIds(); 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int size = table.size(); 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson handlerOffsets = new TreeMap<CatchHandlerList, Integer>(); 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * First add a map entry for each unique list. The tree structure 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * will ensure they are sorted when we reiterate later. 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < size; i++) { 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson handlerOffsets.put(table.get(i).getHandlers(), null); 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (handlerOffsets.size() > 65535) { 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new UnsupportedOperationException( 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson "too many catch handlers"); 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(); 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Write out the handlers "header" consisting of its size in entries. 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson encodedHandlerHeaderSize = 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.writeUleb128(handlerOffsets.size()); 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Now write the lists out in order, noting the offset of each. 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (Map.Entry<CatchHandlerList, Integer> mapping : 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson handlerOffsets.entrySet()) { 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CatchHandlerList list = mapping.getKey(); 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int listSize = list.size(); 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson boolean catchesAll = list.catchesAll(); 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Set the offset before we do any writing. 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson mapping.setValue(out.getCursor()); 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (catchesAll) { 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // A size <= 0 means that the list ends with a catch-all. 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.writeSleb128(-(listSize - 1)); 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson listSize--; 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.writeSleb128(listSize); 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < listSize; i++) { 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CatchHandlerList.Entry entry = list.get(i); 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.writeUleb128( 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson typeIds.indexOf(entry.getExceptionType())); 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.writeUleb128(entry.getHandler()); 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (catchesAll) { 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.writeUleb128(list.get(listSize).getHandler()); 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson encodedHandlers = out.toByteArray(); 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the write size of this instance, in bytes. 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code >= 0;} the write size 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int writeSize() { 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (triesSize() * TRY_ITEM_WRITE_SIZE) + 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson + encodedHandlers.length; 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Writes this instance to the given stream. 189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param file {@code non-null;} file this instance is part of 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param out {@code non-null;} where to write to 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void writeTo(DexFile file, AnnotatedOutput out) { 194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson finishProcessingIfNecessary(); 195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (out.annotates()) { 197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson annotateEntries(" ", null, out); 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int tableSize = table.size(); 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < tableSize; i++) { 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CatchTable.Entry one = table.get(i); 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int start = one.getStart(); 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int end = one.getEnd(); 205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int insnCount = end - start; 206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (insnCount >= 65536) { 208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new UnsupportedOperationException( 209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson "bogus exception range: " + Hex.u4(start) + ".." + 210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Hex.u4(end)); 211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.writeInt(start); 214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.writeShort(insnCount); 215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.writeShort(handlerOffsets.get(one.getHandlers())); 216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.write(encodedHandlers); 219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Helper method to annotate or simply print the exception handlers. 223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Only one of {@code printTo} or {@code annotateTo} should 224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * be non-null. 225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param prefix {@code non-null;} prefix for each line 227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param printTo {@code null-ok;} where to print to 228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param annotateTo {@code null-ok;} where to consume bytes and annotate to 229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private void annotateEntries(String prefix, PrintWriter printTo, 231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson AnnotatedOutput annotateTo) { 232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson finishProcessingIfNecessary(); 233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson boolean consume = (annotateTo != null); 235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int amt1 = consume ? 6 : 0; 236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int amt2 = consume ? 2 : 0; 237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int size = table.size(); 238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson String subPrefix = prefix + " "; 239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (consume) { 241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson annotateTo.annotate(0, prefix + "tries:"); 242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson printTo.println(prefix + "tries:"); 244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < size; i++) { 247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CatchTable.Entry entry = table.get(i); 248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CatchHandlerList handlers = entry.getHandlers(); 249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson String s1 = subPrefix + "try " + Hex.u2or4(entry.getStart()) 250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson + ".." + Hex.u2or4(entry.getEnd()); 251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson String s2 = handlers.toHuman(subPrefix, ""); 252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (consume) { 254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson annotateTo.annotate(amt1, s1); 255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson annotateTo.annotate(amt2, s2); 256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson printTo.println(s1); 258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson printTo.println(s2); 259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (! consume) { 263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Only emit the handler lists if we are consuming bytes. 264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return; 265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson annotateTo.annotate(0, prefix + "handlers:"); 268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson annotateTo.annotate(encodedHandlerHeaderSize, 269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson subPrefix + "size: " + Hex.u2(handlerOffsets.size())); 270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int lastOffset = 0; 272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CatchHandlerList lastList = null; 273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (Map.Entry<CatchHandlerList, Integer> mapping : 275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson handlerOffsets.entrySet()) { 276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CatchHandlerList list = mapping.getKey(); 277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int offset = mapping.getValue(); 278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (lastList != null) { 280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson annotateAndConsumeHandlers(lastList, lastOffset, 281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson offset - lastOffset, subPrefix, printTo, annotateTo); 282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson lastList = list; 285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson lastOffset = offset; 286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson annotateAndConsumeHandlers(lastList, lastOffset, 289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson encodedHandlers.length - lastOffset, 290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson subPrefix, printTo, annotateTo); 291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Helper for {@link #annotateEntries} to annotate a catch handler list 295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * while consuming it. 296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param handlers {@code non-null;} handlers to annotate 298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param offset {@code >= 0;} the offset of this handler 299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param size {@code >= 1;} the number of bytes the handlers consume 300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param prefix {@code non-null;} prefix for each line 301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param printTo {@code null-ok;} where to print to 302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param annotateTo {@code non-null;} where to annotate to 303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static void annotateAndConsumeHandlers(CatchHandlerList handlers, 305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int offset, int size, String prefix, PrintWriter printTo, 306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson AnnotatedOutput annotateTo) { 307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson String s = handlers.toHuman(prefix, Hex.u2(offset) + ": "); 308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (printTo != null) { 310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson printTo.println(s); 311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson annotateTo.annotate(size, s); 314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 316