1 /*
  2  * Copyright (c) 2000, 2023, 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), nullptr },
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 volatile field,
170 // e.g.: "static ObjectMonitor * volatile g_block_list;"
171 #define GENERATE_VOLATILE_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)    \
172   { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, (type*)&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), nullptr, 0, offset_of(typeName, fieldName), nullptr },
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), nullptr, 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  { nullptr, nullptr, nullptr, 0, 0, nullptr }
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 volatile VMStructEntry by comparing pointer types,
212 // e.g.: "static ObjectMonitor * volatile g_block_list;"
213 #define CHECK_VOLATILE_STATIC_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), nullptr,              0, 0, 0, sizeof(type) },
240 
241 #define GENERATE_OOP_VM_TYPE_ENTRY(type) \
242  { QUOTE(type), nullptr,              1, 0, 0, sizeof(type) },
243 
244 #define GENERATE_INTEGER_VM_TYPE_ENTRY(type) \
245  { QUOTE(type), nullptr,              0, 1, 0, sizeof(type) },
246 
247 #define GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY(type) \
248  { QUOTE(type), nullptr,              0, 1, 1, sizeof(type) },
249 
250 #define GENERATE_VM_TYPE_LAST_ENTRY() \
251  { nullptr, nullptr, 0, 0, 0, 0 }
252 
253 #define CHECK_VM_TYPE_ENTRY(type, superclass) \
254  { type* dummyObj = nullptr; 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  { nullptr, 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  { nullptr, 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  { nullptr, nullptr }
309 
310 #endif // SHARE_RUNTIME_VMSTRUCTS_HPP