1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 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.DalvCode; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.dex.code.DalvInsnList; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.dex.code.LocalList; 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.dex.code.PositionList; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstMethodRef; 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.AnnotatedOutput; 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.ExceptionWithContext; 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.PrintWriter; 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic class DebugInfoItem extends OffsettedItem { 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** the required alignment for instances of this class */ 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static final int ALIGNMENT = 1; 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static final boolean ENABLE_ENCODER_SELF_CHECK = false; 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} the code this item represents */ 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final DalvCode code; 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private byte[] encoded; 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final boolean isStatic; 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final CstMethodRef ref; 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public DebugInfoItem(DalvCode code, boolean isStatic, CstMethodRef ref) { 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // We don't know the write size yet. 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super (ALIGNMENT, -1); 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (code == null) { 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("code == null"); 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.code = code; 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.isStatic = isStatic; 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.ref = ref; 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public ItemType itemType() { 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ItemType.TYPE_DEBUG_INFO_ITEM; 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void addContents(DexFile file) { 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // No contents to add. 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected void place0(Section addedTo, int offset) { 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Encode the data and note the size. 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson encoded = encode(addedTo.getFile(), null, null, null, false); 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson setWriteSize(encoded.length); 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (RuntimeException ex) { 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw ExceptionWithContext.withContext(ex, 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson "...while placing debug info for " + ref.toHuman()); 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String toHuman() { 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("unsupported"); 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Writes annotations for the elements of this list, as 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * zero-length. This is meant to be used for dumping this instance 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * directly after a code dump (with the real local list actually 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * existing elsewhere in the output). 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param file {@code non-null;} the file to use for referencing other sections 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param out {@code non-null;} where to annotate to 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param prefix {@code null-ok;} prefix to attach to each line of output 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void annotateTo(DexFile file, AnnotatedOutput out, String prefix) { 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson encode(file, prefix, null, out, false); 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 encode(null, prefix, out, null, false); 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected void writeTo0(DexFile file, AnnotatedOutput out) { 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (out.annotates()) { 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Re-run the encoder to generate the annotations, 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * but write the bits from the original encode 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.annotate(offsetString() + " debug info"); 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson encode(file, null, null, out, true); 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson out.write(encoded); 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Performs debug info encoding. 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param file {@code null-ok;} file to refer to during encoding 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param prefix {@code null-ok;} prefix to attach to each line of output 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param debugPrint {@code null-ok;} if specified, an alternate output for 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * annotations 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param out {@code null-ok;} if specified, where annotations should go 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param consume whether to claim to have consumed output for 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code out} 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the encoded array 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private byte[] encode(DexFile file, String prefix, PrintWriter debugPrint, 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson AnnotatedOutput out, boolean consume) { 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson byte[] result = encode0(file, prefix, debugPrint, out, consume); 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (ENABLE_ENCODER_SELF_CHECK && (file != null)) { 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DebugInfoDecoder.validateEncode(result, file, ref, code, 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson isStatic); 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (RuntimeException ex) { 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Reconvert, annotating to System.err. 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson encode0(file, "", new PrintWriter(System.err, true), null, 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson false); 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw ex; 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return result; 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Helper for {@link #encode} to do most of the work. 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param file {@code null-ok;} file to refer to during encoding 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param prefix {@code null-ok;} prefix to attach to each line of output 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param debugPrint {@code null-ok;} if specified, an alternate output for 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * annotations 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param out {@code null-ok;} if specified, where annotations should go 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param consume whether to claim to have consumed output for 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code out} 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the encoded array 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private byte[] encode0(DexFile file, String prefix, PrintWriter debugPrint, 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson AnnotatedOutput out, boolean consume) { 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PositionList positions = code.getPositions(); 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson LocalList locals = code.getLocals(); 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DalvInsnList insns = code.getInsns(); 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int codeSize = insns.codeSize(); 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int regSize = insns.getRegistersSize(); 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DebugInfoEncoder encoder = 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new DebugInfoEncoder(positions, locals, 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson file, codeSize, regSize, isStatic, ref); 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson byte[] result; 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if ((debugPrint == null) && (out == null)) { 186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson result = encoder.convert(); 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson result = encoder.convertAndAnnotate(prefix, debugPrint, out, 189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson consume); 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return result; 193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 195