| 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(); | 
|---|
| 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(); | 
|---|
| 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(); | 
|---|
| 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(); | 
|---|
| 133 |  | 
|---|
| 134 | /** | 
|---|
| 135 | * Table of addresses. | 
|---|
| 136 | */ | 
|---|
| 137 | static VMAddressEntry localHotSpotVMAddresses[]; | 
|---|
| 138 |  | 
|---|
| 139 | // This is used to run any checking code necessary for validation of | 
|---|
| 140 | // the data structure (debug build only) | 
|---|
| 141 | static void init(); | 
|---|
| 142 |  | 
|---|
| 143 | #ifndef PRODUCT | 
|---|
| 144 | // Execute unit tests | 
|---|
| 145 | static void test(); | 
|---|
| 146 | #endif | 
|---|
| 147 |  | 
|---|
| 148 | private: | 
|---|
| 149 | // Look up a type in localHotSpotVMTypes using strcmp() (debug build only). | 
|---|
| 150 | // Returns 1 if found, 0 if not. | 
|---|
| 151 | //  debug_only(static int findType(const char* typeName);) | 
|---|
| 152 | static int findType(const char* typeName); | 
|---|
| 153 | }; | 
|---|
| 154 |  | 
|---|
| 155 | // This utility macro quotes the passed string | 
|---|
| 156 | #define QUOTE(x) #x | 
|---|
| 157 |  | 
|---|
| 158 | //-------------------------------------------------------------------------------- | 
|---|
| 159 | // VMStructEntry macros | 
|---|
| 160 | // | 
|---|
| 161 |  | 
|---|
| 162 | // This macro generates a VMStructEntry line for a nonstatic field | 
|---|
| 163 | #define GENERATE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)              \ | 
|---|
| 164 | { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 0, offset_of(typeName, fieldName), NULL }, | 
|---|
| 165 |  | 
|---|
| 166 | // This macro generates a VMStructEntry line for a static field | 
|---|
| 167 | #define GENERATE_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)                 \ | 
|---|
| 168 | { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, &typeName::fieldName }, | 
|---|
| 169 |  | 
|---|
| 170 | // This macro generates a VMStructEntry line for a static pointer volatile field, | 
|---|
| 171 | // e.g.: "static ObjectMonitor * volatile gBlockList;" | 
|---|
| 172 | #define GENERATE_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY(typeName, fieldName, type)    \ | 
|---|
| 173 | { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, (void *)&typeName::fieldName }, | 
|---|
| 174 |  | 
|---|
| 175 | // This macro generates a VMStructEntry line for an unchecked | 
|---|
| 176 | // nonstatic field, in which the size of the type is also specified. | 
|---|
| 177 | // The type string is given as NULL, indicating an "opaque" type. | 
|---|
| 178 | #define GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, size)    \ | 
|---|
| 179 | { QUOTE(typeName), QUOTE(fieldName), NULL, 0, offset_of(typeName, fieldName), NULL }, | 
|---|
| 180 |  | 
|---|
| 181 | // This macro generates a VMStructEntry line for an unchecked | 
|---|
| 182 | // static field, in which the size of the type is also specified. | 
|---|
| 183 | // The type string is given as NULL, indicating an "opaque" type. | 
|---|
| 184 | #define GENERATE_UNCHECKED_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, size)       \ | 
|---|
| 185 | { QUOTE(typeName), QUOTE(fieldName), NULL, 1, 0, (void*) &typeName::fieldName }, | 
|---|
| 186 |  | 
|---|
| 187 | // This macro generates the sentinel value indicating the end of the list | 
|---|
| 188 | #define GENERATE_VM_STRUCT_LAST_ENTRY() \ | 
|---|
| 189 | { NULL, NULL, NULL, 0, 0, NULL } | 
|---|
| 190 |  | 
|---|
| 191 | // This macro checks the type of a VMStructEntry by comparing pointer types | 
|---|
| 192 | #define CHECK_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)                 \ | 
|---|
| 193 | {typeName *dummyObj = NULL; type* dummy = &dummyObj->fieldName;                   \ | 
|---|
| 194 | assert(offset_of(typeName, fieldName) < sizeof(typeName), "Illegal nonstatic struct entry, field offset too large"); } | 
|---|
| 195 |  | 
|---|
| 196 | // This macro checks the type of a volatile VMStructEntry by comparing pointer types | 
|---|
| 197 | #define CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)        \ | 
|---|
| 198 | {typedef type dummyvtype; typeName *dummyObj = NULL; volatile dummyvtype* dummy = &dummyObj->fieldName; } | 
|---|
| 199 |  | 
|---|
| 200 | // This macro checks the type of a static VMStructEntry by comparing pointer types | 
|---|
| 201 | #define CHECK_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)                    \ | 
|---|
| 202 | {type* dummy = &typeName::fieldName; } | 
|---|
| 203 |  | 
|---|
| 204 | // This macro checks the type of a static pointer volatile VMStructEntry by comparing pointer types, | 
|---|
| 205 | // e.g.: "static ObjectMonitor * volatile gBlockList;" | 
|---|
| 206 | #define CHECK_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY(typeName, fieldName, type)       \ | 
|---|
| 207 | {type volatile * dummy = &typeName::fieldName; } | 
|---|
| 208 |  | 
|---|
| 209 | // This macro ensures the type of a field and its containing type are | 
|---|
| 210 | // present in the type table. The assertion string is shorter than | 
|---|
| 211 | // preferable because (incredibly) of a bug in Solstice NFS client | 
|---|
| 212 | // which seems to prevent very long lines from compiling. This assertion | 
|---|
| 213 | // means that an entry in VMStructs::localHotSpotVMStructs[] was not | 
|---|
| 214 | // found in VMStructs::localHotSpotVMTypes[]. | 
|---|
| 215 | #define ENSURE_FIELD_TYPE_PRESENT(typeName, fieldName, type)                       \ | 
|---|
| 216 | { assert(findType(QUOTE(typeName)) != 0, "type \"" QUOTE(typeName) "\" not found in type table"); \ | 
|---|
| 217 | assert(findType(QUOTE(type)) != 0, "type \"" QUOTE(type) "\" not found in type table"); } | 
|---|
| 218 |  | 
|---|
| 219 | // This is a no-op macro for unchecked fields | 
|---|
| 220 | #define CHECK_NO_OP(a, b, c) | 
|---|
| 221 |  | 
|---|
| 222 |  | 
|---|
| 223 | //-------------------------------------------------------------------------------- | 
|---|
| 224 | // VMTypeEntry macros | 
|---|
| 225 | // | 
|---|
| 226 |  | 
|---|
| 227 | #define GENERATE_VM_TYPE_ENTRY(type, superclass) \ | 
|---|
| 228 | { QUOTE(type), QUOTE(superclass), 0, 0, 0, sizeof(type) }, | 
|---|
| 229 |  | 
|---|
| 230 | #define GENERATE_TOPLEVEL_VM_TYPE_ENTRY(type) \ | 
|---|
| 231 | { QUOTE(type), NULL,              0, 0, 0, sizeof(type) }, | 
|---|
| 232 |  | 
|---|
| 233 | #define GENERATE_OOP_VM_TYPE_ENTRY(type) \ | 
|---|
| 234 | { QUOTE(type), NULL,              1, 0, 0, sizeof(type) }, | 
|---|
| 235 |  | 
|---|
| 236 | #define GENERATE_INTEGER_VM_TYPE_ENTRY(type) \ | 
|---|
| 237 | { QUOTE(type), NULL,              0, 1, 0, sizeof(type) }, | 
|---|
| 238 |  | 
|---|
| 239 | #define GENERATE_UNSIGNED_INTEGER_VM_TYPE_ENTRY(type) \ | 
|---|
| 240 | { QUOTE(type), NULL,              0, 1, 1, sizeof(type) }, | 
|---|
| 241 |  | 
|---|
| 242 | #define GENERATE_VM_TYPE_LAST_ENTRY() \ | 
|---|
| 243 | { NULL, NULL, 0, 0, 0, 0 } | 
|---|
| 244 |  | 
|---|
| 245 | #define CHECK_VM_TYPE_ENTRY(type, superclass) \ | 
|---|
| 246 | { type* dummyObj = NULL; superclass* dummySuperObj = dummyObj; } | 
|---|
| 247 |  | 
|---|
| 248 | #define CHECK_VM_TYPE_NO_OP(a) | 
|---|
| 249 | #define CHECK_SINGLE_ARG_VM_TYPE_NO_OP(a) | 
|---|
| 250 |  | 
|---|
| 251 |  | 
|---|
| 252 | //-------------------------------------------------------------------------------- | 
|---|
| 253 | // VMIntConstantEntry macros | 
|---|
| 254 | // | 
|---|
| 255 |  | 
|---|
| 256 | #define GENERATE_VM_INT_CONSTANT_ENTRY(name) \ | 
|---|
| 257 | { QUOTE(name), (int32_t) name }, | 
|---|
| 258 |  | 
|---|
| 259 | #define GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY(name, value) \ | 
|---|
| 260 | { (name), (int32_t)(value) }, | 
|---|
| 261 |  | 
|---|
| 262 | #define GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY(name, value) \ | 
|---|
| 263 | { name, (int32_t) value }, | 
|---|
| 264 |  | 
|---|
| 265 | // This macro generates the sentinel value indicating the end of the list | 
|---|
| 266 | #define GENERATE_VM_INT_CONSTANT_LAST_ENTRY() \ | 
|---|
| 267 | { NULL, 0 } | 
|---|
| 268 |  | 
|---|
| 269 |  | 
|---|
| 270 | //-------------------------------------------------------------------------------- | 
|---|
| 271 | // VMLongConstantEntry macros | 
|---|
| 272 | // | 
|---|
| 273 |  | 
|---|
| 274 | #define GENERATE_VM_LONG_CONSTANT_ENTRY(name) \ | 
|---|
| 275 | { QUOTE(name), name }, | 
|---|
| 276 |  | 
|---|
| 277 | #define GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value) \ | 
|---|
| 278 | { name, value }, | 
|---|
| 279 |  | 
|---|
| 280 | // This macro generates the sentinel value indicating the end of the list | 
|---|
| 281 | #define GENERATE_VM_LONG_CONSTANT_LAST_ENTRY() \ | 
|---|
| 282 | { NULL, 0 } | 
|---|
| 283 |  | 
|---|
| 284 |  | 
|---|
| 285 | //-------------------------------------------------------------------------------- | 
|---|
| 286 | // VMAddressEntry macros | 
|---|
| 287 | // | 
|---|
| 288 |  | 
|---|
| 289 | #define GENERATE_VM_ADDRESS_ENTRY(name) \ | 
|---|
| 290 | { QUOTE(name), (void*) (name) }, | 
|---|
| 291 |  | 
|---|
| 292 | #define GENERATE_PREPROCESSOR_VM_ADDRESS_ENTRY(name, value) \ | 
|---|
| 293 | { name, (void*) (value) }, | 
|---|
| 294 |  | 
|---|
| 295 | #define GENERATE_VM_FUNCTION_ENTRY(name) \ | 
|---|
| 296 | { QUOTE(name), CAST_FROM_FN_PTR(void*, &(name)) }, | 
|---|
| 297 |  | 
|---|
| 298 | // This macro generates the sentinel value indicating the end of the list | 
|---|
| 299 | #define GENERATE_VM_ADDRESS_LAST_ENTRY() \ | 
|---|
| 300 | { NULL, NULL } | 
|---|
| 301 |  | 
|---|
| 302 | #endif // SHARE_RUNTIME_VMSTRUCTS_HPP | 
|---|
| 303 |  | 
|---|