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