1 /* 2 * Copyright (c) 2018, 2021, 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->_space[index]; 74 static Address get_CDSFileMapRegion(Type FileMapHeader_type, Address header, int index) { 75 AddressField spaceField = FileMapHeader_type.getAddressField("_space[0]"); 76 77 // size_t offset = offsetof(FileMapHeader, _space[0]); 78 // CDSFileMapRegion* space_0 = ((char*)header) + offset; // space_0 = &header->_space[index]; 79 // return ((char*)space_0) + index * sizeof(CDSFileMapRegion); 80 long offset = spaceField.getOffset(); 81 Address space_0 = header.addOffsetTo(offset); 82 return space_0.addOffsetTo(index * spaceField.getSize()); 83 } 84 85 private static void initialize(TypeDataBase db) { 86 Type FileMapInfo_type = db.lookupType("FileMapInfo"); 87 Type FileMapHeader_type = db.lookupType("FileMapHeader"); 88 Type CDSFileMapRegion_type = db.lookupType("CDSFileMapRegion"); 89 90 // FileMapInfo * info = FileMapInfo::_current_info; 91 // FileMapHeader* header = info->_header 92 Address info = getStatic_AddressField(FileMapInfo_type, "_current_info"); 93 Address header = get_AddressField(FileMapInfo_type, info, "_header"); 94 headerObj = (FileMapHeader) VMObjectFactory.newObject(FileMapInfo.FileMapHeader.class, header); 95 96 // char* mapped_base_address = header->_mapped_base_address 97 // size_t cloned_vtable_offset = header->_cloned_vtable_offset 98 // CppVtableInfo** vtablesIndex = mapped_base_address + cloned_vtable_offset; 99 Address mapped_base_address = get_AddressField(FileMapHeader_type, header, "_mapped_base_address"); 100 long cloned_vtable_offset = get_CIntegerField(FileMapHeader_type, header, "_cloned_vtables_offset"); 101 vtablesIndex = mapped_base_address.addOffsetTo(cloned_vtable_offset); 102 103 // CDSFileMapRegion* rw_space = &header->_space[rw]; 104 // char* rwRegionBaseAddress = rw_space->_mapped_base; 105 // size_t used = rw_space->_used; 106 // char* rwRegionEndAddress = rwRegionBaseAddress + used; 107 Address rw_space = get_CDSFileMapRegion(FileMapHeader_type, header, 0); 108 rwRegionBaseAddress = get_AddressField(CDSFileMapRegion_type, rw_space, "_mapped_base"); 109 long used = get_CIntegerField(CDSFileMapRegion_type, rw_space, "_used"); 110 rwRegionEndAddress = rwRegionBaseAddress.addOffsetTo(used); 111 112 populateMetadataTypeArray(db); 113 } 114 115 private static void populateMetadataTypeArray(TypeDataBase db) { 116 metadataTypeArray = new Type[10]; 117 118 metadataTypeArray[0] = db.lookupType("ConstantPool"); 119 metadataTypeArray[1] = db.lookupType("InstanceKlass"); 120 metadataTypeArray[2] = db.lookupType("InstanceClassLoaderKlass"); 121 metadataTypeArray[3] = db.lookupType("InstanceMirrorKlass"); 122 metadataTypeArray[4] = db.lookupType("InstanceRefKlass"); 123 metadataTypeArray[5] = db.lookupType("Method"); 124 metadataTypeArray[6] = db.lookupType("ObjArrayKlass"); 125 metadataTypeArray[7] = db.lookupType("TypeArrayKlass"); 126 metadataTypeArray[8] = db.lookupType("FlatArrayKlass"); 127 metadataTypeArray[9] = db.lookupType("InlineKlass"); 128 } 129 130 public FileMapHeader getHeader() { 131 return headerObj; 132 } 133 134 public boolean inCopiedVtableSpace(Address vptrAddress) { 135 FileMapHeader fmHeader = getHeader(); 136 return fmHeader.inCopiedVtableSpace(vptrAddress); 137 } 138 139 public Type getTypeForVptrAddress(Address vptrAddress) { 140 if (vTableTypeMap == null) { 141 getHeader().createVtableTypeMapping(); 142 } 143 return vTableTypeMap.get(vptrAddress); 144 } 145 146 147 //------------------------------------------------------------------------------------------ 148 149 public static class FileMapHeader extends VMObject { 150 151 public FileMapHeader(Address addr) { 152 super(addr); 153 } 154 155 public boolean inCopiedVtableSpace(Address vptrAddress) { 156 if (vptrAddress == null) { 157 return false; 158 } 159 if (vptrAddress.greaterThan(rwRegionBaseAddress) && 160 vptrAddress.lessThanOrEqual(rwRegionEndAddress)) { 161 return true; 162 } 163 return false; 164 } 165 166 public void createVtableTypeMapping() { 167 vTableTypeMap = new HashMap<Address, Type>(); 168 long addressSize = VM.getVM().getAddressSize(); 169 170 // vtablesIndex points to this: 171 // class CppVtableInfo { 172 // intptr_t _vtable_size; 173 // intptr_t _cloned_vtable[1]; 174 // ... 175 // }; 176 // CppVtableInfo** CppVtables::_index; 177 // This is the index of all the cloned vtables. E.g., for 178 // ConstantPool* cp = ....; // an archived constant pool 179 // InstanceKlass* ik = ....;// an archived class 180 // the following holds true: 181 // &_index[ConstantPool_Kind]->_cloned_vtable[0] == ((intptr_t**)cp)[0] 182 // &_index[InstanceKlass_Kind]->_cloned_vtable[0] == ((intptr_t**)ik)[0] 183 184 for (int i=0; i < metadataTypeArray.length; i++) { 185 Address vtableInfoAddress = vtablesIndex.getAddressAt(i * addressSize); // = _index[i] 186 Address vtableAddress = vtableInfoAddress.addOffsetTo(addressSize); // = &_index[i]->_cloned_vtable[0] 187 vTableTypeMap.put(vtableAddress, metadataTypeArray[i]); 188 } 189 } 190 } 191 }