1 /* 2 * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.openjdk.asmtools.jdis; 24 25 import org.openjdk.asmtools.jasm.TypeAnnotationTargetInfoData; 26 import org.openjdk.asmtools.jasm.TypeAnnotationTypePathData; 27 28 import java.io.DataInputStream; 29 import java.io.IOException; 30 import java.io.PrintWriter; 31 32 import static org.openjdk.asmtools.jasm.TypeAnnotationTargetInfoData.*; 33 import static org.openjdk.asmtools.jasm.TypeAnnotationTypes.*; 34 35 /** 36 * Type Annotation data is a specific kind of AnnotationData. As well as the normal data 37 * items needed to present an annotation, Type annotations require a TargetInfo 38 * descriptor. This descriptor is based on a TargetType, and it optionally may contain a 39 * location descriptor (when the Type is embedded in a collection). 40 * <p> 41 * The TypeAnnotationData class is based on JDis's AnnotationData class, and contains the 42 * (jasm) class for representing TargetInfo. 43 */ 44 public class TypeAnnotationData extends AnnotationData { 45 46 private static TTVis TT_Visitor = new TTVis(); 47 private TypeAnnotationTargetInfoData targetInfo; 48 private TypeAnnotationTypePathData typePath; 49 50 public TypeAnnotationData(boolean invisible, ClassData cls) { 51 super(invisible, cls); 52 targetInfo = null; 53 typePath = new TypeAnnotationTypePathData(); 54 visAnnotToken = "@T+"; 55 invAnnotToken = "@T-"; 56 dataName = "TypeAnnotationData"; 57 } 58 59 @Override 60 public void read(DataInputStream in) throws IOException { 61 62 int ttype = in.readUnsignedByte(); 63 ETargetType targetType = ETargetType.getTargetType(ttype); 64 65 if (targetType == null) { 66 // Throw some kind of error for bad target type index 67 throw new IOException("Bad target type: " + ttype + " in TypeAnnotationData"); 68 } 69 70 // read the target info 71 TT_Visitor.init(in); 72 TT_Visitor.visitExcept(targetType); 73 targetInfo = TT_Visitor.getTargetInfo(); 74 75 // read the target path info 76 int len = in.readUnsignedByte(); 77 TraceUtils.traceln(4,"[TypeAnnotationData.read]: Reading Location (length = " + len + ")."); 78 TraceUtils.trace(4,"[TypeAnnotationData.read]: [ "); 79 for (int i = 0; i < len; i++) { 80 int pathType = in.readUnsignedByte(); 81 String pk = (getPathKind(pathType)).parseKey(); 82 char pathArgIndex = (char) in.readUnsignedByte(); 83 typePath.addTypePathEntry(new TypePathEntry(pathType, pathArgIndex)); 84 TraceUtils.trace(" " + pk + "(" + pathType + "," + pathArgIndex + "), "); 85 } 86 TraceUtils.traceln("] "); 87 super.read(in); 88 } 89 90 @Override 91 protected void printBody(PrintWriter out, String tab) { 92 // For a type annotation, print out brackets, 93 // print out the (regular) annotation name/value pairs, 94 // then print out the target types. 95 out.print(" {"); 96 super.printBody(out, ""); 97 targetInfo.print(out, tab); 98 typePath.print(out, tab); 99 out.print(tab + "}"); 100 } 101 102 /** 103 * TTVis 104 * <p> 105 * Target Type visitor, used for constructing the target-info within a type 106 * annotation. visitExcept() is the entry point. ti is the constructed target info. 107 */ 108 private static class TTVis extends TypeAnnotationTargetVisitor { 109 110 private TypeAnnotationTargetInfoData targetInfo = null; 111 private IOException IOProb = null; 112 private DataInputStream in; 113 114 public void init(DataInputStream in) { 115 this.in = in; 116 } 117 118 public int scanByteVal() { 119 int val = 0; 120 try { 121 val = in.readUnsignedByte(); 122 } catch (IOException e) { 123 IOProb = e; 124 } 125 return val; 126 } 127 128 public int scanShortVal() { 129 int val = 0; 130 try { 131 val = in.readUnsignedShort(); 132 } catch (IOException e) { 133 IOProb = e; 134 } 135 return val; 136 } 137 138 //This is the entry point for a visitor that tunnels exceptions 139 public void visitExcept(ETargetType tt) throws IOException { 140 IOProb = null; 141 targetInfo = null; 142 143 TraceUtils.traceln(4,"Target Type: " + tt.parseKey()); 144 visit(tt); 145 146 if (IOProb != null) { 147 throw IOProb; 148 } 149 } 150 151 public TypeAnnotationTargetInfoData getTargetInfo() { 152 return targetInfo; 153 } 154 155 private boolean error() { 156 return IOProb != null; 157 } 158 159 @Override 160 public void visit_type_param_target(ETargetType tt) { 161 TraceUtils.trace(4,"Type Param Target: "); 162 int byteval = scanByteVal(); // param index 163 TraceUtils.traceln("{ param_index: " + byteval + "}"); 164 if (!error()) { 165 targetInfo = new type_parameter_target(tt, byteval); 166 } 167 } 168 169 @Override 170 public void visit_supertype_target(ETargetType tt) { 171 TraceUtils.trace(4,"SuperType Target: "); 172 int shortval = scanShortVal(); // type index 173 TraceUtils.traceln("{ type_index: " + shortval + "}"); 174 if (!error()) { 175 targetInfo = new supertype_target(tt, shortval); 176 } 177 } 178 179 @Override 180 public void visit_typeparam_bound_target(ETargetType tt) { 181 TraceUtils.trace(4,"TypeParam Bound Target: "); 182 int byteval1 = scanByteVal(); // param index 183 if (error()) { 184 return; 185 } 186 int byteval2 = scanByteVal(); // bound index 187 if (error()) { 188 return; 189 } 190 TraceUtils.traceln("{ param_index: " + byteval1 + " bound_index: " + byteval2 + "}"); 191 targetInfo = new type_parameter_bound_target(tt, byteval1, byteval2); 192 } 193 194 @Override 195 public void visit_empty_target(ETargetType tt) { 196 TraceUtils.traceln(4,"Empty Target: "); 197 if (!error()) { 198 targetInfo = new empty_target(tt); 199 } 200 } 201 202 @Override 203 public void visit_methodformalparam_target(ETargetType tt) { 204 TraceUtils.trace(4,"MethodFormalParam Target: "); 205 int byteval = scanByteVal(); // param index 206 TraceUtils.traceln("{ param_index: " + byteval + "}"); 207 if (!error()) { 208 targetInfo = new formal_parameter_target(tt, byteval); 209 } 210 } 211 212 @Override 213 public void visit_throws_target(ETargetType tt) { 214 TraceUtils.trace(4,"Throws Target: "); 215 int shortval = scanShortVal(); // exception index 216 TraceUtils.traceln("{ exception_index: " + shortval + "}"); 217 if (!error()) { 218 targetInfo = new throws_target(tt, shortval); 219 } 220 } 221 222 @Override 223 public void visit_localvar_target(ETargetType tt) { 224 TraceUtils.traceln(4,"LocalVar Target: "); 225 int tblsize = scanShortVal(); // table length (short) 226 if (error()) { 227 return; 228 } 229 localvar_target locvartab = new localvar_target(tt, tblsize); 230 targetInfo = locvartab; 231 232 for (int i = 0; i < tblsize; i++) { 233 int shortval1 = scanShortVal(); // startPC 234 if (error()) { 235 return; 236 } 237 int shortval2 = scanShortVal(); // length 238 if (error()) { 239 return; 240 } 241 int shortval3 = scanShortVal(); // CPX 242 TraceUtils.trace(4,"LocalVar[" + i + "]: "); 243 TraceUtils.traceln("{ startPC: " + shortval1 + ", length: " + shortval2 + ", CPX: " + shortval3 + "}"); 244 locvartab.addEntry(shortval1, shortval2, shortval3); 245 } 246 } 247 248 @Override 249 public void visit_catch_target(ETargetType tt) { 250 TraceUtils.trace(4,"Catch Target: "); 251 int shortval = scanShortVal(); // catch index 252 TraceUtils.traceln("{ catch_index: " + shortval + "}"); 253 if (!error()) { 254 targetInfo = new catch_target(tt, shortval); 255 } 256 } 257 258 @Override 259 public void visit_offset_target(ETargetType tt) { 260 TraceUtils.trace(4,"Offset Target: "); 261 int shortval = scanShortVal(); // offset index 262 TraceUtils.traceln("{ offset_index: " + shortval + "}"); 263 if (!error()) { 264 targetInfo = new offset_target(tt, shortval); 265 } 266 } 267 268 @Override 269 public void visit_typearg_target(ETargetType tt) { 270 TraceUtils.trace(4,"TypeArg Target: "); 271 int shortval = scanShortVal(); // offset 272 if (error()) { 273 return; 274 } 275 int byteval = scanByteVal(); // type index 276 if (error()) { 277 return; 278 } 279 TraceUtils.traceln("{ offset: " + shortval + " type_index: " + byteval + "}"); 280 targetInfo = new type_argument_target(tt, shortval, byteval); 281 } 282 } 283 }