1 /* 2 * Copyright (c) 2018, 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 package sun.jvm.hotspot.memory; 26 27 import java.util.*; 28 import sun.jvm.hotspot.debugger.Address; 29 import sun.jvm.hotspot.runtime.VM; 30 import sun.jvm.hotspot.runtime.VMObject; 31 import sun.jvm.hotspot.runtime.VMObjectFactory; 32 import sun.jvm.hotspot.types.*; 33 import sun.jvm.hotspot.utilities.Observable; 34 import sun.jvm.hotspot.utilities.Observer; 35 36 public class FileMapInfo { 37 private static FileMapHeader headerObj; 38 39 // Fields for handling the copied C++ vtables 40 private static Address rwRegionBaseAddress; 41 private static Address rwRegionEndAddress; 42 private static Address vtablesIndex; 43 44 // HashMap created by mapping the vTable addresses in the rw region with 45 // the corresponding metadata type. 46 private static Map<Address, Type> vTableTypeMap; 47 48 private static Type metadataTypeArray[]; 49 50 static { 51 VM.registerVMInitializedObserver(new Observer() { 52 public void update(Observable o, Object data) { 53 initialize(VM.getVM().getTypeDataBase()); 54 } 55 }); 56 } 57 58 static Address getStatic_AddressField(Type type, String fieldName) { 59 AddressField field = type.getAddressField(fieldName); 60 return field.getValue(); 61 } 62 63 static Address get_AddressField(Type type, Address instance, String fieldName) { 64 AddressField field = type.getAddressField(fieldName); 65 return field.getValue(instance); 66 } 67 68 static long get_CIntegerField(Type type, Address instance, String fieldName) { 69 CIntegerField field = type.getCIntegerField(fieldName); 70 return field.getValue(instance); 71 } 72 73 // C equivalent: return &header->_regions[index]; 74 static Address get_CDSFileMapRegion(Type FileMapHeader_type, Address header, int index) { 75 AddressField regionsField = FileMapHeader_type.getAddressField("_regions[0]"); 76 77 // size_t offset = offsetof(FileMapHeader, _regions[0]); 78 // CDSFileMapRegion* regions_0 = ((char*)header) + offset; // regions_0 = &header->_regions[index]; 79 // return ((char*)regions_0) + index * sizeof(CDSFileMapRegion); 80 long offset = regionsField.getOffset(); 81 Address regions_0 = header.addOffsetTo(offset); 82 return regions_0.addOffsetTo(index * regionsField.getSize()); 83 } 84 85 private static void initialize(TypeDataBase db) { 86 vTableTypeMap = null; // force vTableTypeMap to get re-initialized later 87 88 Type FileMapInfo_type = db.lookupType("FileMapInfo"); 89 Type FileMapHeader_type = db.lookupType("FileMapHeader"); 90 Type CDSFileMapRegion_type = db.lookupType("CDSFileMapRegion"); 91 92 // FileMapInfo * info = FileMapInfo::_current_info; 93 // FileMapHeader* header = info->_header 94 Address info = getStatic_AddressField(FileMapInfo_type, "_current_info"); 95 Address header = get_AddressField(FileMapInfo_type, info, "_header"); 96 headerObj = VMObjectFactory.newObject(FileMapHeader.class, header); 97 98 // char* mapped_base_address = header->_mapped_base_address 99 // size_t cloned_vtable_offset = header->_cloned_vtable_offset 100 // CppVtableInfo** vtablesIndex = mapped_base_address + cloned_vtable_offset; 101 Address mapped_base_address = get_AddressField(FileMapHeader_type, header, "_mapped_base_address"); 102 long cloned_vtable_offset = get_CIntegerField(FileMapHeader_type, header, "_cloned_vtables_offset"); 103 vtablesIndex = mapped_base_address.addOffsetTo(cloned_vtable_offset); 104 105 // CDSFileMapRegion* rw_region = &header->_region[rw]; 106 // char* rwRegionBaseAddress = rw_region->_mapped_base; 107 // size_t used = rw_region->_used; 108 // char* rwRegionEndAddress = rwRegionBaseAddress + used; 109 Address rw_region = get_CDSFileMapRegion(FileMapHeader_type, header, 0); 110 rwRegionBaseAddress = get_AddressField(CDSFileMapRegion_type, rw_region, "_mapped_base"); 111 long used = get_CIntegerField(CDSFileMapRegion_type, rw_region, "_used"); 112 rwRegionEndAddress = rwRegionBaseAddress.addOffsetTo(used); 113 114 populateMetadataTypeArray(db); 115 } 116 117 private static void populateMetadataTypeArray(TypeDataBase db) { 118 metadataTypeArray = new Type[11]; 119 120 metadataTypeArray[0] = db.lookupType("ConstantPool"); 121 metadataTypeArray[1] = db.lookupType("InstanceKlass"); 122 metadataTypeArray[2] = db.lookupType("InstanceClassLoaderKlass"); 123 metadataTypeArray[3] = db.lookupType("InstanceMirrorKlass"); 124 metadataTypeArray[4] = db.lookupType("InstanceRefKlass"); 125 metadataTypeArray[5] = db.lookupType("InstanceStackChunkKlass"); 126 metadataTypeArray[6] = db.lookupType("Method"); 127 metadataTypeArray[7] = db.lookupType("ObjArrayKlass"); 128 metadataTypeArray[8] = db.lookupType("TypeArrayKlass"); 129 metadataTypeArray[9] = db.lookupType("FlatArrayKlass"); 130 metadataTypeArray[10] = db.lookupType("InlineKlass"); 131 } 132 133 public FileMapHeader getHeader() { 134 return headerObj; 135 } 136 137 public boolean inCopiedVtableSpace(Address vptrAddress) { 138 FileMapHeader fmHeader = getHeader(); 139 return fmHeader.inCopiedVtableSpace(vptrAddress); 140 } 141 142 public Type getTypeForVptrAddress(Address vptrAddress) { 143 if (vTableTypeMap == null) { 144 getHeader().createVtableTypeMapping(); 145 } 146 return vTableTypeMap.get(vptrAddress); 147 } 148 149 150 //------------------------------------------------------------------------------------------ 151 152 public static class FileMapHeader extends VMObject { 153 154 public FileMapHeader(Address addr) { 155 super(addr); 156 } 157 158 public boolean inCopiedVtableSpace(Address vptrAddress) { 159 if (vptrAddress == null) { 160 return false; 161 } 162 if (vptrAddress.greaterThan(rwRegionBaseAddress) && 163 vptrAddress.lessThanOrEqual(rwRegionEndAddress)) { 164 return true; 165 } 166 return false; 167 } 168 169 public void createVtableTypeMapping() { 170 vTableTypeMap = new HashMap<Address, Type>(); 171 long addressSize = VM.getVM().getAddressSize(); 172 173 // vtablesIndex points to this: 174 // class CppVtableInfo { 175 // intptr_t _vtable_size; 176 // intptr_t _cloned_vtable[1]; 177 // ... 178 // }; 179 // CppVtableInfo** CppVtables::_index; 180 // This is the index of all the cloned vtables. E.g., for 181 // ConstantPool* cp = ....; // an archived constant pool 182 // InstanceKlass* ik = ....;// an archived class 183 // the following holds true: 184 // &_index[ConstantPool_Kind]->_cloned_vtable[0] == ((intptr_t**)cp)[0] 185 // &_index[InstanceKlass_Kind]->_cloned_vtable[0] == ((intptr_t**)ik)[0] 186 187 for (int i=0; i < metadataTypeArray.length; i++) { 188 Address vtableInfoAddress = vtablesIndex.getAddressAt(i * addressSize); // = _index[i] 189 Address vtableAddress = vtableInfoAddress.addOffsetTo(addressSize); // = &_index[i]->_cloned_vtable[0] 190 vTableTypeMap.put(vtableAddress, metadataTypeArray[i]); 191 } 192 } 193 } 194 }