1 /*
2 * Copyright (c) 2000, 2019, 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 */
24
25 #ifndef SHARE_RUNTIME_VMSTRUCTS_HPP
26 #define SHARE_RUNTIME_VMSTRUCTS_HPP
27
28 #include "utilities/debug.hpp"
29 #include "utilities/globalDefinitions.hpp"
30 #ifdef COMPILER1
31 #include "c1/c1_Runtime1.hpp"
32 #endif
33
34 // This table encapsulates the debugging information required by the
35 // serviceability agent in order to run. Specifically, we need to
36 // understand the layout of certain C data structures (offsets, in
37 // bytes, of their fields.)
38 //
39 // There are alternatives for the design of this mechanism, including
40 // parsing platform-specific debugging symbols from a debug build into
41 // a program database. While this current mechanism can be considered
42 // to be a workaround for the inability to debug arbitrary C and C++
43 // programs at the present time, it does have certain advantages.
44 // First, it is platform-independent, which will vastly simplify the
45 // initial bringup of the system both now and on future platforms.
46 // Second, it is embedded within the VM, as opposed to being in a
47 // separate program database; experience has shown that whenever
48 // portions of a system are decoupled, version skew is problematic.
49 // Third, generating a program database, for example for a product
50 // build, would probably require two builds to be done: the desired
51 // product build as well as an intermediary build with the PRODUCT
52 // flag turned on but also compiled with -g, leading to a doubling of
53 // the time required to get a serviceability agent-debuggable product
54 // build. Fourth, and very significantly, this table probably
55 // preserves more information about field types than stabs do; for
56 // example, it preserves the fact that a field is a "jlong" rather
57 // than transforming the type according to the typedef in jni_md.h,
58 // which allows the Java-side code to identify "Java-sized" fields in
59 // C++ data structures. If the symbol parsing mechanism was redone
60 // using stabs, it might still be necessary to have a table somewhere
61 // containing this information.
62 //
63 // Do not change the sizes or signedness of the integer values in
64 // these data structures; they are fixed over in the serviceability
65 // agent's Java code (for bootstrapping).
66
67 typedef struct {
68 const char* typeName; // The type name containing the given field (example: "Klass")
69 const char* fieldName; // The field name within the type (example: "_name")
70 const char* typeString; // Quoted name of the type of this field (example: "Symbol*";
71 // parsed in Java to ensure type correctness
72 int32_t isStatic; // Indicates whether following field is an offset or an address
73 uint64_t offset; // Offset of field within structure; only used for nonstatic fields
74 void* address; // Address of field; only used for static fields
75 // ("offset" can not be reused because of apparent solstudio compiler bug
76 // in generation of initializer data)
77 } VMStructEntry;
78
79 typedef struct {
80 const char* typeName; // Type name (example: "Method")
81 const char* superclassName; // Superclass name, or null if none (example: "oopDesc")
82 int32_t isOopType; // Does this type represent an oop typedef? (i.e., "Method*" or
83 // "Klass*", but NOT "Method")
84 int32_t isIntegerType; // Does this type represent an integer type (of arbitrary size)?
85 int32_t isUnsigned; // If so, is it unsigned?
86 uint64_t size; // Size, in bytes, of the type
87 } VMTypeEntry;
88
89 typedef struct {
90 const char* name; // Name of constant (example: "_thread_in_native")
91 int32_t value; // Value of constant
92 } VMIntConstantEntry;
93
94 typedef struct {
95 const char* name; // Name of constant (example: "_thread_in_native")
96 uint64_t value; // Value of constant
97 } VMLongConstantEntry;
98
99 typedef struct {
100 const char* name; // Name of address (example: "SharedRuntime::register_finalizer")
101 void* value; // Value of address
102 } VMAddressEntry;
103
104 // This class is a friend of most classes, to be able to access
105 // private fields
106 class VMStructs {
107 public:
108 // The last entry is identified over in the serviceability agent by
109 // the fact that it has a NULL fieldName
110 static VMStructEntry localHotSpotVMStructs[];
111 // The function to get localHotSpotVMStructs length
112 static size_t localHotSpotVMStructsLength() NOT_VM_STRUCTS_RETURN_(0);
113
114 // The last entry is identified over in the serviceability agent by
115 // the fact that it has a NULL typeName
116 static VMTypeEntry localHotSpotVMTypes[];
117 // The function to get localHotSpotVMTypes length
118 static size_t localHotSpotVMTypesLength() NOT_VM_STRUCTS_RETURN_(0);
119
120 // Table of integer constants required by the serviceability agent.
121 // The last entry is identified over in the serviceability agent by
122 // the fact that it has a NULL typeName
123 static VMIntConstantEntry localHotSpotVMIntConstants[];
124 // The function to get localHotSpotVMIntConstants length
125 static size_t localHotSpotVMIntConstantsLength() NOT_VM_STRUCTS_RETURN_(0);
126
127 // Table of long constants required by the serviceability agent.
128 // The last entry is identified over in the serviceability agent by
129 // the fact that it has a NULL typeName
130 static VMLongConstantEntry localHotSpotVMLongConstants[];
131 // The function to get localHotSpotVMIntConstants length
132 static size_t localHotSpotVMLongConstantsLength() NOT_VM_STRUCTS_RETURN_(0);
133
134 /**
135 * Table of addresses.
136 */
137 static VMAddressEntry localHotSpotVMAddresses[];
138
139 #ifdef ASSERT
140 // This is used to run any checking code necessary for validation of
141 // the data structure (debug build only)
142 static void init() NOT_VM_STRUCTS_RETURN;
143
144 private:
145 // Look up a type in localHotSpotVMTypes using strcmp() (debug build only).
146 // Returns 1 if found, 0 if not.
147 static int findType(const char* typeName) NOT_VM_STRUCTS_RETURN_(0);
148 #endif // ASSERT
149
150 public:
151 static void compact_headers_overrides() NOT_VM_STRUCTS_RETURN;
152 };
153
154 // This utility macro quotes the passed string
155 #define QUOTE(x) #x
156
157 //--------------------------------------------------------------------------------
158 // VMStructEntry macros
159 //
160
161 // This macro generates a VMStructEntry line for a nonstatic field
162 #define GENERATE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \
163 { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 0, offset_of(typeName, fieldName), NULL },
164
165 // This macro generates a VMStructEntry line for a static field
166 #define GENERATE_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \
167 { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, &typeName::fieldName },
168
169 // This macro generates a VMStructEntry line for a static pointer volatile field,
170 // e.g.: "static ObjectMonitor * volatile g_block_list;"
171 #define GENERATE_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY(typeName, fieldName, type) \
172 { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, (void *)&typeName::fieldName },
173
174 // This macro generates a VMStructEntry line for an unchecked
175 // nonstatic field, in which the size of the type is also specified.
176 // The type string is given as NULL, indicating an "opaque" type.
177 #define GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, size) \
178 { QUOTE(typeName), QUOTE(fieldName), NULL, 0, offset_of(typeName, fieldName), NULL },
179
180 // This macro generates a VMStructEntry line for an unchecked
181 // static field, in which the size of the type is also specified.
182 // The type string is given as NULL, indicating an "opaque" type.
183 #define GENERATE_UNCHECKED_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, size) \
184 { QUOTE(typeName), QUOTE(fieldName), NULL, 1, 0, (void*) &typeName::fieldName },
185
186 // This macro generates the sentinel value indicating the end of the list
187 #define GENERATE_VM_STRUCT_LAST_ENTRY() \
188 { NULL, NULL, NULL, 0, 0, NULL }
189
190
191 #ifdef ASSERT
192
193 // This macro checks the type of a VMStructEntry by comparing pointer types
194 #define CHECK_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) { \
195 static_assert( \
196 std::is_convertible< \
197 std::add_pointer_t<decltype(declval<typeName>().fieldName)>, \
198 std::add_pointer_t<type>>::value, \
199 "type mismatch for " XSTR(fieldName) " member of " XSTR(typeName)); \
200 assert(offset_of(typeName, fieldName) < sizeof(typeName), "..."); \
201 }
202
203 // This macro checks the type of a volatile VMStructEntry by comparing pointer types
204 #define CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \
205 CHECK_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, std::add_volatile_t<type>)
206
207 // This macro checks the type of a static VMStructEntry by comparing pointer types
208 #define CHECK_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \
209 {type* dummy = &typeName::fieldName; }
210
211 // This macro checks the type of a static pointer volatile VMStructEntry by comparing pointer types,
212 // e.g.: "static ObjectMonitor * volatile g_block_list;"
213 #define CHECK_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY(typeName, fieldName, type) \
214 {type volatile * dummy = &typeName::fieldName; }
215
216 // This macro ensures the type of a field and its containing type are
217 // present in the type table. The assertion string is shorter than
218 // preferable because (incredibly) of a bug in Solstice NFS client
219 // which seems to prevent very long lines from compiling. This assertion
220 // means that an entry in VMStructs::localHotSpotVMStructs[] was not
221 // found in VMStructs::localHotSpotVMTypes[].
222 #define ENSURE_FIELD_TYPE_PRESENT(typeName, fieldName, type) \
223 { assert(findType(QUOTE(typeName)) != 0, "type \"" QUOTE(typeName) "\" not found in type table"); \
224 assert(findType(QUOTE(type)) != 0, "type \"" QUOTE(type) "\" not found in type table"); }
225
226 // This is a no-op macro for unchecked fields
227 #define CHECK_NO_OP(a, b, c)
228
229 #endif // ASSERT
230
231 //--------------------------------------------------------------------------------
232 // VMTypeEntry macros
233 //
234
235 #define GENERATE_VM_TYPE_ENTRY(type, superclass) \
236 { QUOTE(type), QUOTE(superclass), 0, 0, 0, sizeof(type) },
237
238 #define GENERATE_TOPLEVEL_VM_TYPE_ENTRY(type) \
239 { QUOTE(type), NULL, 0, 0, 0, sizeof(type) },
240
241 #define GENERATE_OOP_VM_TYPE_ENTRY(type) \
242 { QUOTE(type), NULL, 1, 0, 0, sizeof(type) },
243
244 #define GENERATE_INTEGER_VM_TYPE_ENTRY(type) \
245 { QUOTE(type), NULL, 0, 1, 0, sizeof(type) },
246
247 #define GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY(type) \
248 { QUOTE(type), NULL, 0, 1, 1, sizeof(type) },
249
250 #define GENERATE_VM_TYPE_LAST_ENTRY() \
251 { NULL, NULL, 0, 0, 0, 0 }
252
253 #define CHECK_VM_TYPE_ENTRY(type, superclass) \
254 { type* dummyObj = NULL; superclass* dummySuperObj = dummyObj; }
255
256 #define CHECK_VM_TYPE_NO_OP(a)
257 #define CHECK_SINGLE_ARG_VM_TYPE_NO_OP(a)
258
259
260 //--------------------------------------------------------------------------------
261 // VMIntConstantEntry macros
262 //
263
264 #define GENERATE_VM_INT_CONSTANT_ENTRY(name) \
265 { QUOTE(name), (int32_t) name },
266
267 #define GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY(name, value) \
268 { (name), (int32_t)(value) },
269
270 #define GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY(name, value) \
271 { name, (int32_t) value },
272
273 // This macro generates the sentinel value indicating the end of the list
274 #define GENERATE_VM_INT_CONSTANT_LAST_ENTRY() \
275 { NULL, 0 }
276
277
278 //--------------------------------------------------------------------------------
279 // VMLongConstantEntry macros
280 //
281
282 #define GENERATE_VM_LONG_CONSTANT_ENTRY(name) \
283 { QUOTE(name), name },
284
285 #define GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value) \
286 { name, value },
287
288 // This macro generates the sentinel value indicating the end of the list
289 #define GENERATE_VM_LONG_CONSTANT_LAST_ENTRY() \
290 { NULL, 0 }
291
292
293 //--------------------------------------------------------------------------------
294 // VMAddressEntry macros
295 //
296
297 #define GENERATE_VM_ADDRESS_ENTRY(name) \
298 { QUOTE(name), (void*) (name) },
299
300 #define GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY(name, value) \
301 { name, (void*) (value) },
302
303 #define GENERATE_VM_FUNCTION_ENTRY(name) \
304 { QUOTE(name), CAST_FROM_FN_PTR(void*, &(name)) },
305
306 // This macro generates the sentinel value indicating the end of the list
307 #define GENERATE_VM_ADDRESS_LAST_ENTRY() \
308 { NULL, NULL }
309
310 #endif // SHARE_RUNTIME_VMSTRUCTS_HPP