1 /* 2 * Copyright (c) 2022, 2024, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 * 25 */ 26 package jdk.internal.classfile.impl.verifier; 27 28 import java.lang.classfile.Attributes; 29 import java.lang.classfile.ClassModel; 30 import java.lang.classfile.MethodModel; 31 import java.lang.classfile.attribute.LocalVariableInfo; 32 import java.lang.classfile.constantpool.ClassEntry; 33 import java.lang.classfile.constantpool.ConstantPool; 34 import java.lang.classfile.constantpool.DynamicConstantPoolEntry; 35 import java.lang.classfile.constantpool.MemberRefEntry; 36 import java.lang.classfile.constantpool.NameAndTypeEntry; 37 import java.lang.constant.ClassDesc; 38 import java.lang.reflect.AccessFlag; 39 import java.util.LinkedList; 40 import java.util.List; 41 import java.util.stream.Collectors; 42 43 import jdk.internal.classfile.impl.BoundAttribute; 44 import jdk.internal.classfile.impl.CodeImpl; 45 import jdk.internal.classfile.impl.Util; 46 47 public final class VerificationWrapper { 48 private final ClassModel clm; 49 private final ConstantPoolWrapper cp; 50 51 public VerificationWrapper(ClassModel clm) { 52 this.clm = clm; 53 this.cp = new ConstantPoolWrapper(clm.constantPool()); 54 } 55 56 String thisClassName() { 57 return clm.thisClass().asInternalName(); 58 } 59 60 int majorVersion() { 61 return clm.majorVersion(); 62 } 63 64 String superclassName() { 65 return clm.superclass().map(ClassEntry::asInternalName).orElse(null); 66 } 67 68 Iterable<String> interfaceNames() { 69 return Util.mappedList(clm.interfaces(), ClassEntry::asInternalName); 70 } 71 72 Iterable<MethodWrapper> methods() { 73 return clm.methods().stream().map(m -> new MethodWrapper(m)).toList(); 74 } 75 76 boolean findField(String name, String sig) { 77 for (var f : clm.fields()) 78 if (f.fieldName().stringValue().equals(name) && f.fieldType().stringValue().equals(sig)) 79 return true; 80 return false; 81 } 82 83 class MethodWrapper { 84 85 final MethodModel m; 86 private final CodeImpl c; 87 private final List<int[]> exc; 88 89 MethodWrapper(MethodModel m) { 90 this.m = m; 91 this.c = (CodeImpl)m.code().orElse(null); 92 exc = new LinkedList<>(); 93 if (c != null) c.iterateExceptionHandlers((start, end, handler, catchType) -> { 94 exc.add(new int[] {start, end, handler, catchType}); 95 }); 96 } 97 98 ConstantPoolWrapper constantPool() { 99 return cp; 100 } 101 102 boolean isNative() { 103 return m.flags().has(AccessFlag.NATIVE); 104 } 105 106 boolean isAbstract() { 107 return m.flags().has(AccessFlag.ABSTRACT); 108 } 109 110 boolean isBridge() { 111 return m.flags().has(AccessFlag.BRIDGE); 112 } 113 114 boolean isStatic() { 115 return m.flags().has(AccessFlag.STATIC); 116 } 117 118 String name() { 119 return m.methodName().stringValue(); 120 } 121 122 int maxStack() { 123 return c == null ? 0 : c.maxStack(); 124 } 125 126 int maxLocals() { 127 return c == null ? 0 : c.maxLocals(); 128 } 129 130 String descriptor() { 131 return m.methodType().stringValue(); 132 } 133 134 String parameters() { 135 return m.methodTypeSymbol().parameterList().stream().map(ClassDesc::displayName).collect(Collectors.joining(",")); 136 } 137 138 int codeLength() { 139 return c == null ? 0 : c.codeLength(); 140 } 141 142 byte[] codeArray() { 143 return c == null ? null : c.codeArray(); 144 } 145 146 List<int[]> exceptionTable() { 147 return exc; 148 } 149 150 List<LocalVariableInfo> localVariableTable() { 151 var attro = c.findAttribute(Attributes.localVariableTable()); 152 return attro.map(lvta -> lvta.localVariables()).orElse(List.of()); 153 } 154 155 byte[] stackMapTableRawData() { 156 var attro = c.findAttribute(Attributes.stackMapTable()); 157 return attro.map(attr -> ((BoundAttribute) attr).contents()).orElse(null); 158 } 159 160 } 161 162 static class ConstantPoolWrapper { 163 164 private final ConstantPool cp; 165 166 ConstantPoolWrapper(ConstantPool cp) { 167 this.cp = cp; 168 } 169 170 int entryCount() { 171 return cp.size(); 172 } 173 174 String classNameAt(int index) { 175 return cp.entryByIndex(index, ClassEntry.class).asInternalName(); 176 } 177 178 String dynamicConstantSignatureAt(int index) { 179 return cp.entryByIndex(index, DynamicConstantPoolEntry.class).type().stringValue(); 180 } 181 182 int tagAt(int index) { 183 return cp.entryByIndex(index).tag(); 184 } 185 186 private NameAndTypeEntry _refNameType(int index) { 187 var e = cp.entryByIndex(index); 188 return (e instanceof DynamicConstantPoolEntry de) ? de.nameAndType() : 189 e != null ? ((MemberRefEntry)e).nameAndType() : null; 190 } 191 192 String refNameAt(int index) { 193 return _refNameType(index).name().stringValue(); 194 } 195 196 String refSignatureAt(int index) { 197 return _refNameType(index).type().stringValue(); 198 } 199 200 int refClassIndexAt(int index) { 201 return cp.entryByIndex(index, MemberRefEntry.class).owner().index(); 202 } 203 } 204 }