static void checkMethod(String cname, String mname, ConstantPool cp, Code_attribute code) throws ConstantPool.InvalidIndex { for (Instruction i : code.getInstructions()) { String iname = i.getMnemonic(); if ("invokespecial".equals(iname) || "invokestatic".equals(iname)) { int idx = i.getByte(2); System.out.println("Verifying " + cname + ":" + mname + " instruction:" + iname + " index @" + idx); CPInfo cpinfo = cp.get(idx); if (cpinfo instanceof ConstantPool.CONSTANT_Methodref_info) { throw new RuntimeException("unexpected CP type expected " + "InterfaceMethodRef, got MethodRef, " + cname + ", " + mname); } } } }
void checkClassFile(File file) throws IOException, ConstantPoolException, InvalidDescriptor { ClassFile classFile = ClassFile.read(file); ConstantPool constantPool = classFile.constant_pool; //lets get all the methods in the class file. for (Method method : classFile.methods) { for (ElementKey elementKey: aliveRangeMap.keySet()) { String methodDesc = method.getName(constantPool) + method.descriptor.getParameterTypes(constantPool).replace(" ", ""); if (methodDesc.equals(elementKey.elem.toString())) { checkMethod(constantPool, method, aliveRangeMap.get(elementKey)); seenAliveRanges.add(elementKey); } } } }
void checkMethod(ConstantPool constantPool, Method method, AliveRanges ranges) throws InvalidIndex, UnexpectedEntry, ConstantPoolException { Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code); LocalVariableTable_attribute lvt = (LocalVariableTable_attribute) (code.attributes.get(Attribute.LocalVariableTable)); List<String> infoFromRanges = convertToStringList(ranges); List<String> infoFromLVT = convertToStringList(constantPool, lvt); // infoFromRanges most be contained in infoFromLVT int i = 0; int j = 0; while (i < infoFromRanges.size() && j < infoFromLVT.size()) { int comparison = infoFromRanges.get(i).compareTo(infoFromLVT.get(j)); if (comparison == 0) { i++; j++; } else if (comparison > 0) { j++; } else { break; } } if (i < infoFromRanges.size()) { error(infoFromLVT, infoFromRanges, method.getName(constantPool).toString()); } }
private void testExports(ModuleDescriptor moduleDescriptor, Module_attribute module, ConstantPool constantPool) throws ConstantPoolException { tr.checkEquals(module.exports_count, moduleDescriptor.exports.size(), "Wrong amount of exports."); for (Module_attribute.ExportsEntry export : module.exports) { String pkg = constantPool.getPackageInfo(export.exports_index).getName(); if (tr.checkTrue(moduleDescriptor.exports.containsKey(pkg), "Unexpected export " + pkg)) { Export expectedExport = moduleDescriptor.exports.get(pkg); tr.checkEquals(expectedExport.mask, export.exports_flags, "Wrong export flags"); List<String> expectedTo = expectedExport.to; tr.checkEquals(export.exports_to_count, expectedTo.size(), "Wrong amount of exports to"); List<String> actualTo = new ArrayList<>(); for (int toIdx : export.exports_to_index) { actualTo.add(constantPool.getModuleInfo(toIdx).getName()); } tr.checkContains(actualTo, expectedTo, "Lists of \"exports to\" don't match."); } } }
private void testOpens(ModuleDescriptor moduleDescriptor, Module_attribute module, ConstantPool constantPool) throws ConstantPoolException { tr.checkEquals(module.opens_count, moduleDescriptor.opens.size(), "Wrong amount of opens."); for (Module_attribute.OpensEntry open : module.opens) { String pkg = constantPool.getPackageInfo(open.opens_index).getName(); if (tr.checkTrue(moduleDescriptor.opens.containsKey(pkg), "Unexpected open " + pkg)) { Open expectedOpen = moduleDescriptor.opens.get(pkg); tr.checkEquals(expectedOpen.mask, open.opens_flags, "Wrong open flags"); List<String> expectedTo = expectedOpen.to; tr.checkEquals(open.opens_to_count, expectedTo.size(), "Wrong amount of opens to"); List<String> actualTo = new ArrayList<>(); for (int toIdx : open.opens_to_index) { actualTo.add(constantPool.getModuleInfo(toIdx).getName()); } tr.checkContains(actualTo, expectedTo, "Lists of \"opens to\" don't match."); } } }
private void scanConstantPool(Set<Integer> utf8Descriptors) throws Exception { for (int i = 1; i < cf.constant_pool.size(); i++) { try { ConstantPool.CPInfo info = cf.constant_pool.get(i); if (info instanceof ConstantPool.CONSTANT_NameAndType_info) { ConstantPool.CONSTANT_NameAndType_info nameAndType = (ConstantPool.CONSTANT_NameAndType_info) info; utf8Descriptors.add(nameAndType.type_index); } if (info instanceof ConstantPool.CONSTANT_MethodType_info) { ConstantPool.CONSTANT_MethodType_info mt = (ConstantPool.CONSTANT_MethodType_info) info; utf8Descriptors.add(mt.descriptor_index); } if (info instanceof ConstantPool.CONSTANT_Double_info || info instanceof ConstantPool.CONSTANT_Long_info) { i++; } } catch (ConstantPool.InvalidIndex ex) { throw new IOException(ex); } } }
void checkMethod(ConstantPool constantPool, Method method, AliveRanges ranges) throws InvalidIndex, UnexpectedEntry { Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code); LocalVariableTable_attribute lvt = (LocalVariableTable_attribute) (code.attributes.get(Attribute.LocalVariableTable)); List<String> infoFromRanges = convertToStringList(ranges); List<String> infoFromLVT = convertToStringList(constantPool, lvt); // infoFromRanges most be contained in infoFromLVT int i = 0; int j = 0; while (i < infoFromRanges.size() && j < infoFromLVT.size()) { int comparison = infoFromRanges.get(i).compareTo(infoFromLVT.get(j)); if (comparison == 0) { i++; j++; } else if (comparison > 0) { j++; } else { break; } } if (i < infoFromRanges.size()) { error(infoFromLVT, infoFromRanges); } }
void checkClassFile(File file) throws IOException, ConstantPoolException, InvalidDescriptor { ClassFile classFile = ClassFile.read(file); ConstantPool constantPool = classFile.constant_pool; //lets get all the methods in the class file. for (Method method : classFile.methods) { for (ElementKey elementKey: aliveRangeMap.keySet()) { String methodDesc = method.getName(constantPool) + method.descriptor.getParameterTypes(constantPool); if (methodDesc.equals(elementKey.elem.toString())) { checkMethod(constantPool, method, aliveRangeMap.get(elementKey)); seenAliveRanges.add(elementKey); } } } }
public void write(Object owner, Attribute attr, ConstantPool constant_pool) { if (attr != null) { // null checks owner.getClass(); constant_pool.getClass(); this.constant_pool = constant_pool; this.owner = owner; attr.accept(this, null); } }
public void write(Object owner, Attributes attrs, ConstantPool constant_pool) { if (attrs != null) { // null checks owner.getClass(); constant_pool.getClass(); this.constant_pool = constant_pool; this.owner = owner; for (Attribute attr: attrs) attr.accept(this, null); } }
String getInnerName(ConstantPool constant_pool, InnerClasses_attribute.Info info) { try { return info.getInnerName(constant_pool); } catch (ConstantPoolException e) { return report(e); } }
String stringValue(int constant_pool_index) { ClassFile classFile = classWriter.getClassFile(); try { return stringValue(classFile.constant_pool.get(constant_pool_index)); } catch (ConstantPool.InvalidIndex e) { return report(e); } }
void write(Code_attribute attr, ConstantPool constant_pool) { println("Code:"); indent(+1); writeVerboseHeader(attr, constant_pool); writeInstrs(attr); writeExceptionTable(attr); attrWriter.write(attr, attr.attributes, constant_pool); indent(-1); }
Object convertElementValue(ConstantPool cp, element_value val) throws InvalidIndex, ConstantPoolException { switch (val.tag) { case 'Z': return ((CONSTANT_Integer_info) cp.get(((Primitive_element_value) val).const_value_index)).value != 0; case 'B': return (byte) ((CONSTANT_Integer_info) cp.get(((Primitive_element_value) val).const_value_index)).value; case 'C': return (char) ((CONSTANT_Integer_info) cp.get(((Primitive_element_value) val).const_value_index)).value; case 'S': return (short) ((CONSTANT_Integer_info) cp.get(((Primitive_element_value) val).const_value_index)).value; case 'I': return ((CONSTANT_Integer_info) cp.get(((Primitive_element_value) val).const_value_index)).value; case 'J': return ((CONSTANT_Long_info) cp.get(((Primitive_element_value) val).const_value_index)).value; case 'F': return ((CONSTANT_Float_info) cp.get(((Primitive_element_value) val).const_value_index)).value; case 'D': return ((CONSTANT_Double_info) cp.get(((Primitive_element_value) val).const_value_index)).value; case 's': return ((CONSTANT_Utf8_info) cp.get(((Primitive_element_value) val).const_value_index)).value; case 'e': return new EnumConstant(cp.getUTF8Value(((Enum_element_value) val).type_name_index), cp.getUTF8Value(((Enum_element_value) val).const_name_index)); case 'c': return new ClassConstant(cp.getUTF8Value(((Class_element_value) val).class_info_index)); case '@': return annotation2Description(cp, ((Annotation_element_value) val).annotation_value); case '[': List<Object> values = new ArrayList<>(); for (element_value elem : ((Array_element_value) val).values) { values.add(convertElementValue(cp, elem)); } return values; default: throw new IllegalStateException("Currently unhandled tag: " + val.tag); } }
private List<AnnotationDescription> annotations2Description(ConstantPool cp, Attribute attr) throws ConstantPoolException { RuntimeAnnotations_attribute annotationsAttr = (RuntimeAnnotations_attribute) attr; List<AnnotationDescription> descs = new ArrayList<>(); for (Annotation a : annotationsAttr.annotations) { descs.add(annotation2Description(cp, a)); } return descs; }
private List<List<AnnotationDescription>> parameterAnnotations2Description(ConstantPool cp, Attribute attr) throws ConstantPoolException { RuntimeParameterAnnotations_attribute annotationsAttr = (RuntimeParameterAnnotations_attribute) attr; List<List<AnnotationDescription>> descs = new ArrayList<>(); for (Annotation[] attrAnnos : annotationsAttr.parameter_annotations) { List<AnnotationDescription> paramDescs = new ArrayList<>(); for (Annotation ann : attrAnnos) { paramDescs.add(annotation2Description(cp, ann)); } descs.add(paramDescs); } return descs; }
private AnnotationDescription annotation2Description(ConstantPool cp, Annotation a) throws ConstantPoolException { String annotationType = cp.getUTF8Value(a.type_index); Map<String, Object> values = new HashMap<>(); for (element_value_pair e : a.element_value_pairs) { values.put(cp.getUTF8Value(e.element_name_index), convertElementValue(cp, e.value)); } return new AnnotationDescription(annotationType, values); }
public void write(Object owner, Attribute attr, ConstantPool constant_pool) { if (attr != null) { Assert.checkNonNull(constant_pool); Assert.checkNonNull(owner); this.constant_pool = constant_pool; this.owner = owner; attr.accept(this, null); } }
public void write(Object owner, Attributes attrs, ConstantPool constant_pool) { if (attrs != null) { Assert.checkNonNull(constant_pool); Assert.checkNonNull(owner); this.constant_pool = constant_pool; this.owner = owner; for (Attribute attr: attrs) attr.accept(this, null); } }
void setStackMap(StackMapTable_attribute attr) { if (attr == null) { map = null; return; } Method m = classWriter.getMethod(); Descriptor d = m.descriptor; String[] args; try { ConstantPool cp = classWriter.getClassFile().constant_pool; String argString = d.getParameterTypes(cp); args = argString.substring(1, argString.length() - 1).split("[, ]+"); } catch (ConstantPoolException | InvalidDescriptor e) { return; } boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC); verification_type_info[] initialLocals = new verification_type_info[(isStatic ? 0 : 1) + args.length]; if (!isStatic) initialLocals[0] = new CustomVerificationTypeInfo("this"); for (int i = 0; i < args.length; i++) { initialLocals[(isStatic ? 0 : 1) + i] = new CustomVerificationTypeInfo(args[i].replace(".", "/")); } map = new HashMap<>(); StackMapBuilder builder = new StackMapBuilder(); // using -1 as the pc for the initial frame effectively compensates for // the difference in behavior for the first stack map frame (where the // pc offset is just offset_delta) compared to subsequent frames (where // the pc offset is always offset_delta+1). int pc = -1; map.put(pc, new StackMap(initialLocals, empty)); for (int i = 0; i < attr.entries.length; i++) pc = attr.entries[i].accept(builder, pc); }
private void writeDescriptor(int index, boolean resolveIndices) { if (resolveIndices) { try { ConstantPool constant_pool = classWriter.getClassFile().constant_pool; Descriptor d = new Descriptor(index); print(d.getFieldType(constant_pool)); return; } catch (ConstantPoolException | InvalidDescriptor ignore) { } } print("#" + index); }