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.FieldModel;
31 import java.lang.classfile.MethodModel;
32 import java.lang.classfile.attribute.LocalVariableInfo;
33 import java.lang.classfile.constantpool.ClassEntry;
34 import java.lang.classfile.constantpool.ConstantPool;
35 import java.lang.classfile.constantpool.DynamicConstantPoolEntry;
36 import java.lang.classfile.constantpool.MemberRefEntry;
37 import java.lang.classfile.constantpool.NameAndTypeEntry;
38 import java.lang.constant.ClassDesc;
39 import java.lang.reflect.AccessFlag;
40 import java.util.LinkedList;
41 import java.util.List;
42 import java.util.stream.Collectors;
43
44 import jdk.internal.classfile.impl.BoundAttribute;
45 import jdk.internal.classfile.impl.CodeImpl;
46 import jdk.internal.classfile.impl.Util;
47
48 public final class VerificationWrapper {
49 final ClassModel clm;
50 private final ConstantPoolWrapper cp;
51
52 public VerificationWrapper(ClassModel clm) {
53 this.clm = clm;
54 this.cp = new ConstantPoolWrapper(clm.constantPool());
55 }
56
57 String thisClassName() {
58 return clm.thisClass().asInternalName();
59 }
60
61 int majorVersion() {
62 return clm.majorVersion();
63 }
64
65 String superclassName() {
66 return clm.superclass().map(ClassEntry::asInternalName).orElse(null);
67 }
68
69 Iterable<String> interfaceNames() {
70 return Util.mappedList(clm.interfaces(), ClassEntry::asInternalName);
71 }
72
73 Iterable<MethodWrapper> methods() {
74 return clm.methods().stream().map(m -> new MethodWrapper(m)).toList();
75 }
76
77 FieldModel findField(String name, String sig) {
78 for (var f : clm.fields())
79 if (f.fieldName().stringValue().equals(name) && f.fieldType().stringValue().equals(sig))
80 return f;
81 return null;
82 }
83
84 class MethodWrapper {
85
86 final MethodModel m;
87 private final CodeImpl c;
88 private final List<int[]> exc;
89
90 MethodWrapper(MethodModel m) {
91 this.m = m;
92 this.c = (CodeImpl)m.code().orElse(null);
93 exc = new LinkedList<>();
94 if (c != null) c.iterateExceptionHandlers((start, end, handler, catchType) -> {
95 exc.add(new int[] {start, end, handler, catchType});
96 });
97 }
98
99 ConstantPoolWrapper constantPool() {
100 return cp;
101 }
102
103 boolean isNative() {
104 return m.flags().has(AccessFlag.NATIVE);
105 }
106
107 boolean isAbstract() {
108 return m.flags().has(AccessFlag.ABSTRACT);
109 }
110
111 boolean isBridge() {
112 return m.flags().has(AccessFlag.BRIDGE);
113 }
114
115 boolean isStatic() {
116 return m.flags().has(AccessFlag.STATIC);
117 }
118
119 String name() {
120 return m.methodName().stringValue();
121 }
122
123 int maxStack() {
124 return c == null ? 0 : c.maxStack();
125 }
126
127 int maxLocals() {
128 return c == null ? 0 : c.maxLocals();
129 }
130
131 String descriptor() {
132 return m.methodType().stringValue();
133 }
134
135 String parameters() {
136 return m.methodTypeSymbol().parameterList().stream().map(ClassDesc::displayName).collect(Collectors.joining(","));
137 }
138
139 int codeLength() {
140 return c == null ? 0 : c.codeLength();
141 }
142
143 byte[] codeArray() {
144 return c == null ? null : c.codeArray();
145 }
146
147 List<int[]> exceptionTable() {
148 return exc;
149 }
150
151 List<LocalVariableInfo> localVariableTable() {
152 var attro = c.findAttribute(Attributes.localVariableTable());
153 return attro.map(lvta -> lvta.localVariables()).orElse(List.of());
154 }
155
156 byte[] stackMapTableRawData() {
157 var attro = c.findAttribute(Attributes.stackMapTable());
158 return attro.map(attr -> ((BoundAttribute) attr).contents()).orElse(null);
159 }
160
161 }
162
163 static class ConstantPoolWrapper {
164
165 final ConstantPool cp;
166
167 ConstantPoolWrapper(ConstantPool cp) {
168 this.cp = cp;
169 }
170
171 int entryCount() {
172 return cp.size();
173 }
174
175 String classNameAt(int index) {
176 return cp.entryByIndex(index, ClassEntry.class).asInternalName();
177 }
178
179 String dynamicConstantSignatureAt(int index) {
180 return cp.entryByIndex(index, DynamicConstantPoolEntry.class).type().stringValue();
181 }
182
183 int tagAt(int index) {
184 return cp.entryByIndex(index).tag();
185 }
186
187 private NameAndTypeEntry _refNameType(int index) {
188 var e = cp.entryByIndex(index);
189 return (e instanceof DynamicConstantPoolEntry de) ? de.nameAndType() :
190 e != null ? ((MemberRefEntry)e).nameAndType() : null;
191 }
192
193 String refNameAt(int index) {
194 return _refNameType(index).name().stringValue();
195 }
196
197 String refSignatureAt(int index) {
198 return _refNameType(index).type().stringValue();
199 }
200
201 int refClassIndexAt(int index) {
202 return cp.entryByIndex(index, MemberRefEntry.class).owner().index();
203 }
204
205 boolean is_within_bounds(int i) {
206 return i >= 1 && i <= cp.size();
207 }
208 }
209 }