InstructionMethodItem.java revision 7e9231a211bf00451229d88edb5c7fbd5085f73e
19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * [The "BSD licence"]
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Copyright (c) 2010 Ben Gruver (JesusFreke)
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * All rights reserved.
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Redistribution and use in source and binary forms, with or without
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * modification, are permitted provided that the following conditions
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * are met:
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1. Redistributions of source code must retain the above copyright
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *    notice, this list of conditions and the following disclaimer.
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 2. Redistributions in binary form must reproduce the above copyright
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *    notice, this list of conditions and the following disclaimer in the
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *    documentation and/or other materials provided with the distribution.
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 3. The name of the author may not be used to endorse or promote products
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *    derived from this software without specific prior written permission.
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.jf.baksmali.Adaptors.Format;
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.baksmali.Adaptors.MethodDefinition;
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.baksmali.Adaptors.MethodItem;
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.baksmali.Adaptors.ReferenceFormatter;
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.baksmali.Renderers.LongRenderer;
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.dexlib2.ReferenceType;
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.dexlib2.VerificationError;
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex;
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.dexlib2.iface.instruction.*;
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.dexlib2.iface.instruction.formats.Instruction20bc;
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.dexlib2.iface.instruction.formats.UnknownInstruction;
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.dexlib2.iface.reference.Reference;
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.jf.util.IndentingWriter;
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport javax.annotation.Nonnull;
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.IOException;
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.util.Map;
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic class InstructionMethodItem<T extends Instruction> extends MethodItem {
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    @Nonnull protected final MethodDefinition methodDef;
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    @Nonnull protected final T instruction;
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    public InstructionMethodItem(@Nonnull MethodDefinition methodDef, int codeAddress, @Nonnull T instruction) {
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        super(codeAddress);
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        this.methodDef = methodDef;
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        this.instruction = instruction;
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    public double getSortOrder() {
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        //instructions should appear after everything except an "end try" label and .catch directive
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return 100;
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    @Override
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    public boolean writeTo(IndentingWriter writer) throws IOException {
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        boolean invalidReference = false;
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (instruction instanceof ReferenceInstruction) {
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            try {
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                Reference reference = ((ReferenceInstruction)instruction).getReference();
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            } catch (InvalidItemIndex ex) {
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                invalidReference = true;
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write("#invalid ");
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(ReferenceType.toString(instruction.getOpcode().referenceType));
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(" index: ");
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.printSignedIntAsDec(ex.getInvalidIndex());
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write("\n#");
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        switch (instruction.getOpcode().format) {
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            case Format10t:
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeOpcode(writer);
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(' ');
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeTargetLabel(writer);
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return true;
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            case Format10x:
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if (instruction instanceof UnknownInstruction) {
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    writer.write("#unknown opcode: 0x");
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    writer.printUnsignedLongAsHex(((UnknownInstruction)instruction).getOriginalOpcode());
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    writer.write('\n');
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                }
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeOpcode(writer);
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return true;
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            case Format11n:
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeOpcode(writer);
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(' ');
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeFirstRegister(writer);
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(", ");
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeLiteral(writer);
1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return true;
1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            case Format11x:
1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeOpcode(writer);
1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(' ');
1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeFirstRegister(writer);
1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return true;
1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            case Format12x:
1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeOpcode(writer);
1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(' ');
1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeFirstRegister(writer);
1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(", ");
1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeSecondRegister(writer);
1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return true;
1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            case Format20bc:
1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeOpcode(writer);
1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(' ');
1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeVerificationErrorType(writer);
1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(", ");
1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeReference(writer);
1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return true;
1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            case Format20t:
1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            case Format30t:
1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeOpcode(writer);
1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writer.write(' ');
1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                writeTargetLabel(writer);
1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return true;
1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            case Format21c:
1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            case Format31c:
128                writeOpcode(writer);
129                writer.write(' ');
130                writeFirstRegister(writer);
131                writer.write(", ");
132                writeReference(writer);
133                return true;
134            case Format21ih:
135            case Format21lh:
136            case Format21s:
137            case Format31i:
138            case Format51l:
139                writeOpcode(writer);
140                writer.write(' ');
141                writeFirstRegister(writer);
142                writer.write(", ");
143                writeLiteral(writer);
144                writeResourceId(writer, ((WideLiteralInstruction)instruction).getWideLiteral());
145                return true;
146            case Format21t:
147            case Format31t:
148                writeOpcode(writer);
149                writer.write(' ');
150                writeFirstRegister(writer);
151                writer.write(", ");
152                writeTargetLabel(writer);
153                return true;
154            case Format22b:
155            case Format22s:
156                writeOpcode(writer);
157                writer.write(' ');
158                writeFirstRegister(writer);
159                writer.write(", ");
160                writeSecondRegister(writer);
161                writer.write(", ");
162                writeLiteral(writer);
163                return true;
164            case Format22c:
165                writeOpcode(writer);
166                writer.write(' ');
167                writeFirstRegister(writer);
168                writer.write(", ");
169                writeSecondRegister(writer);
170                writer.write(", ");
171                writeReference(writer);
172                return true;
173            case Format22cs:
174                writeOpcode(writer);
175                writer.write(' ');
176                writeFirstRegister(writer);
177                writer.write(", ");
178                writeSecondRegister(writer);
179                writer.write(", ");
180                writeFieldOffset(writer);
181                return true;
182            case Format22t:
183                writeOpcode(writer);
184                writer.write(' ');
185                writeFirstRegister(writer);
186                writer.write(", ");
187                writeSecondRegister(writer);
188                writer.write(", ");
189                writeTargetLabel(writer);
190                return true;
191            case Format22x:
192            case Format32x:
193                writeOpcode(writer);
194                writer.write(' ');
195                writeFirstRegister(writer);
196                writer.write(", ");
197                writeSecondRegister(writer);
198                return true;
199            case Format23x:
200                writeOpcode(writer);
201                writer.write(' ');
202                writeFirstRegister(writer);
203                writer.write(", ");
204                writeSecondRegister(writer);
205                writer.write(", ");
206                writeThirdRegister(writer);
207                return true;
208            case Format35c:
209                writeOpcode(writer);
210                writer.write(' ');
211                writeInvokeRegisters(writer);
212                writer.write(", ");
213                writeReference(writer);
214                return true;
215            case Format35mi:
216                writeOpcode(writer);
217                writer.write(' ');
218                writeInvokeRegisters(writer);
219                writer.write(", ");
220                writeInlineIndex(writer);
221                return true;
222            case Format35ms:
223                writeOpcode(writer);
224                writer.write(' ');
225                writeInvokeRegisters(writer);
226                writer.write(", ");
227                writeVtableIndex(writer);
228                return true;
229            case Format3rc:
230                writeOpcode(writer);
231                writer.write(' ');
232                writeInvokeRangeRegisters(writer);
233                writer.write(", ");
234                writeReference(writer);
235                return true;
236            case Format3rmi:
237                writeOpcode(writer);
238                writer.write(' ');
239                writeInvokeRangeRegisters(writer);
240                writer.write(", ");
241                writeInlineIndex(writer);
242                return true;
243            case Format3rms:
244                writeOpcode(writer);
245                writer.write(' ');
246                writeInvokeRangeRegisters(writer);
247                writer.write(", ");
248                writeVtableIndex(writer);
249                return true;
250        }
251        assert false;
252        return false;
253    }
254
255    protected void writeOpcode(IndentingWriter writer) throws IOException {
256        writer.write(instruction.getOpcode().name);
257    }
258
259    protected void writeTargetLabel(IndentingWriter writer) throws IOException {
260        //this method is overridden by OffsetInstructionMethodItem, and should only be called for the formats that
261        //have a target
262        throw new RuntimeException();
263    }
264
265    protected void writeRegister(IndentingWriter writer, int registerNumber) throws IOException {
266        methodDef.registerFormatter.writeTo(writer, registerNumber);
267    }
268
269    protected void writeFirstRegister(IndentingWriter writer) throws IOException {
270        writeRegister(writer, ((OneRegisterInstruction)instruction).getRegisterA());
271    }
272
273    protected void writeSecondRegister(IndentingWriter writer) throws IOException {
274        writeRegister(writer, ((TwoRegisterInstruction)instruction).getRegisterB());
275    }
276
277    protected void writeThirdRegister(IndentingWriter writer) throws IOException {
278        writeRegister(writer, ((ThreeRegisterInstruction) instruction).getRegisterC());
279    }
280
281    protected void writeInvokeRegisters(IndentingWriter writer) throws IOException {
282        FiveRegisterInstruction instruction = (FiveRegisterInstruction)this.instruction;
283        final int regCount = instruction.getRegisterCount();
284
285        writer.write('{');
286        switch (regCount) {
287            case 1:
288                writeRegister(writer, instruction.getRegisterC());
289                break;
290            case 2:
291                writeRegister(writer, instruction.getRegisterC());
292                writer.write(", ");
293                writeRegister(writer, instruction.getRegisterD());
294                break;
295            case 3:
296                writeRegister(writer, instruction.getRegisterC());
297                writer.write(", ");
298                writeRegister(writer, instruction.getRegisterD());
299                writer.write(", ");
300                writeRegister(writer, instruction.getRegisterE());
301                break;
302            case 4:
303                writeRegister(writer, instruction.getRegisterC());
304                writer.write(", ");
305                writeRegister(writer, instruction.getRegisterD());
306                writer.write(", ");
307                writeRegister(writer, instruction.getRegisterE());
308                writer.write(", ");
309                writeRegister(writer, instruction.getRegisterF());
310                break;
311            case 5:
312                writeRegister(writer, instruction.getRegisterC());
313                writer.write(", ");
314                writeRegister(writer, instruction.getRegisterD());
315                writer.write(", ");
316                writeRegister(writer, instruction.getRegisterE());
317                writer.write(", ");
318                writeRegister(writer, instruction.getRegisterF());
319                writer.write(", ");
320                writeRegister(writer, instruction.getRegisterG());
321                break;
322        }
323        writer.write('}');
324    }
325
326    protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException {
327        RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction;
328
329        int regCount = instruction.getRegisterCount();
330        if (regCount == 0) {
331            writer.write("{}");
332        } else {
333            int startRegister = instruction.getStartRegister();
334            methodDef.registerFormatter.writeRegisterRange(writer, startRegister, startRegister+regCount-1);
335        }
336    }
337
338    protected void writeLiteral(IndentingWriter writer) throws IOException {
339        LongRenderer.writeSignedIntOrLongTo(writer, ((WideLiteralInstruction)instruction).getWideLiteral());
340    }
341
342    protected void writeResourceId(IndentingWriter writer, long val) throws IOException {
343        Map<Long,String> resourceIds = methodDef.classDef.options.resourceIds;
344        if (resourceIds.containsKey(Long.valueOf(val))) {
345            writer.write("    # ");
346            writer.write(resourceIds.get(Long.valueOf(val)));
347        }
348    }
349
350    protected void writeFieldOffset(IndentingWriter writer) throws IOException {
351        writer.write("field@0x");
352        writer.printUnsignedLongAsHex(((FieldOffsetInstruction)instruction).getFieldOffset());
353    }
354
355    protected void writeInlineIndex(IndentingWriter writer) throws IOException {
356        writer.write("inline@");
357        writer.printSignedIntAsDec(((InlineIndexInstruction)instruction).getInlineIndex());
358    }
359
360    protected void writeVtableIndex(IndentingWriter writer) throws IOException {
361        writer.write("vtable@");
362        writer.printSignedIntAsDec(((VtableIndexInstruction)instruction).getVtableIndex());
363    }
364
365    protected void writeReference(IndentingWriter writer) throws IOException {
366        try {
367            ReferenceFormatter.writeReference(writer, instruction.getOpcode().referenceType,
368                    ((ReferenceInstruction)instruction).getReference());
369        } catch (InvalidItemIndex ex) {
370            writer.write(ReferenceType.toString(instruction.getOpcode().referenceType));
371            writer.write("@");
372            writer.printSignedIntAsDec(ex.getInvalidIndex());
373        }
374    }
375
376    protected void writeVerificationErrorType(IndentingWriter writer) throws IOException {
377        int verificationError = ((Instruction20bc)instruction).getVerificationError();
378        writer.write(VerificationError.getVerificationErrorName(verificationError));
379    }
380}
381