• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dx.dex.file;
18 
19 import com.android.dx.dex.code.DalvCode;
20 import com.android.dx.dex.code.DalvInsnList;
21 import com.android.dx.dex.code.LocalList;
22 import com.android.dx.dex.code.PositionList;
23 import com.android.dx.rop.cst.CstMethodRef;
24 import com.android.dx.rop.cst.CstType;
25 import com.android.dx.rop.cst.CstUtf8;
26 import com.android.dx.util.AnnotatedOutput;
27 import com.android.dx.util.ExceptionWithContext;
28 
29 import java.io.PrintWriter;
30 
31 public class DebugInfoItem extends OffsettedItem {
32     /** the required alignment for instances of this class */
33     private static final int ALIGNMENT = 1;
34 
35     private static final boolean ENABLE_ENCODER_SELF_CHECK = false;
36 
37     /** non-null; the code this item represents */
38     private final DalvCode code;
39 
40     private byte[] encoded;
41 
42     private final boolean isStatic;
43     private final CstMethodRef ref;
44 
DebugInfoItem(DalvCode code, boolean isStatic, CstMethodRef ref)45     public DebugInfoItem(DalvCode code, boolean isStatic, CstMethodRef ref) {
46         // We don't know the write size yet.
47         super (ALIGNMENT, -1);
48 
49         if (code == null) {
50             throw new NullPointerException("code == null");
51         }
52 
53         this.code = code;
54         this.isStatic = isStatic;
55         this.ref = ref;
56     }
57 
58     /** {@inheritDoc} */
59     @Override
itemType()60     public ItemType itemType() {
61         return ItemType.TYPE_DEBUG_INFO_ITEM;
62     }
63 
64     /** {@inheritDoc} */
65     @Override
addContents(DexFile file)66     public void addContents(DexFile file) {
67         // No contents to add.
68     }
69 
70     /** {@inheritDoc} */
71     @Override
place0(Section addedTo, int offset)72     protected void place0(Section addedTo, int offset) {
73         // Encode the data and note the size.
74 
75         try {
76             encoded = encode(addedTo.getFile(), null, null, null, false);
77             setWriteSize(encoded.length);
78         } catch (RuntimeException ex) {
79             throw ExceptionWithContext.withContext(ex,
80                     "...while placing debug info for " + ref.toHuman());
81         }
82     }
83 
84     /** {@inheritDoc} */
85     @Override
toHuman()86     public String toHuman() {
87         throw new RuntimeException("unsupported");
88     }
89 
90     /**
91      * Writes annotations for the elements of this list, as
92      * zero-length. This is meant to be used for dumping this instance
93      * directly after a code dump (with the real local list actually
94      * existing elsewhere in the output).
95      *
96      * @param file non-null; the file to use for referencing other sections
97      * @param out non-null; where to annotate to
98      * @param prefix null-ok; prefix to attach to each line of output
99      */
annotateTo(DexFile file, AnnotatedOutput out, String prefix)100     public void annotateTo(DexFile file, AnnotatedOutput out, String prefix) {
101         encode(file, prefix, null, out, false);
102     }
103 
104     /**
105      * Does a human-friendly dump of this instance.
106      *
107      * @param out non-null; where to dump
108      * @param prefix non-null; prefix to attach to each line of output
109      */
debugPrint(PrintWriter out, String prefix)110     public void debugPrint(PrintWriter out, String prefix) {
111         encode(null, prefix, out, null, false);
112     }
113 
114     /** {@inheritDoc} */
115     @Override
writeTo0(DexFile file, AnnotatedOutput out)116     protected void writeTo0(DexFile file, AnnotatedOutput out) {
117         if (out.annotates()) {
118             /*
119              * Re-run the encoder to generate the annotations,
120              * but write the bits from the original encode
121              */
122 
123             out.annotate(offsetString() + " debug info");
124             encode(file, null, null, out, true);
125         }
126 
127         out.write(encoded);
128     }
129 
130     /**
131      * Performs debug info encoding.
132      *
133      * @param file null-ok; file to refer to during encoding
134      * @param prefix null-ok; prefix to attach to each line of output
135      * @param debugPrint null-ok; if specified, an alternate output for
136      * annotations
137      * @param out null-ok; if specified, where annotations should go
138      * @param consume whether to claim to have consumed output for
139      * <code>out</code>
140      * @return non-null; the encoded array
141      */
encode(DexFile file, String prefix, PrintWriter debugPrint, AnnotatedOutput out, boolean consume)142     private byte[] encode(DexFile file, String prefix, PrintWriter debugPrint,
143             AnnotatedOutput out, boolean consume) {
144         byte[] result = encode0(file, prefix, debugPrint, out, consume);
145 
146         if (ENABLE_ENCODER_SELF_CHECK && (file != null)) {
147             try {
148                 DebugInfoDecoder.validateEncode(result, file, ref, code,
149                         isStatic);
150             } catch (RuntimeException ex) {
151                 // Reconvert, annotating to System.err.
152                 encode0(file, "", new PrintWriter(System.err, true), null,
153                         false);
154                 throw ex;
155             }
156         }
157 
158         return result;
159     }
160 
161     /**
162      * Helper for {@link #encode} to do most of the work.
163      *
164      * @param file null-ok; file to refer to during encoding
165      * @param prefix null-ok; prefix to attach to each line of output
166      * @param debugPrint null-ok; if specified, an alternate output for
167      * annotations
168      * @param out null-ok; if specified, where annotations should go
169      * @param consume whether to claim to have consumed output for
170      * <code>out</code>
171      * @return non-null; the encoded array
172      */
encode0(DexFile file, String prefix, PrintWriter debugPrint, AnnotatedOutput out, boolean consume)173     private byte[] encode0(DexFile file, String prefix, PrintWriter debugPrint,
174             AnnotatedOutput out, boolean consume) {
175         PositionList positions = code.getPositions();
176         LocalList locals = code.getLocals();
177         DalvInsnList insns = code.getInsns();
178         int codeSize = insns.codeSize();
179         int regSize = insns.getRegistersSize();
180 
181         DebugInfoEncoder encoder =
182             new DebugInfoEncoder(positions, locals,
183                     file, codeSize, regSize, isStatic, ref);
184 
185         byte[] result;
186 
187         if ((debugPrint == null) && (out == null)) {
188             result = encoder.convert();
189         } else {
190             result = encoder.convertAndAnnotate(prefix, debugPrint, out,
191                     consume);
192         }
193 
194         return result;
195     }
196 }
197