1 /*
2  * Copyright (c) 2018, 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 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 
34 public class FileMapInfo {
35   private static FileMapHeader header;
36   private static Address headerValue;
37 
38   // Fields for class FileMapHeader
39   private static Address mdSpaceValue;
40   private static Address mdRegionBaseAddress;
41   private static Address mdRegionEndAddress;
42 
43   // HashMap created by mapping the vTable addresses in the md region with
44   // the corresponding metadata type.
45   private static Map<Address, Type> vTableTypeMap;
46 
47   private static Type metadataTypeArray[];
48 
49   static {
VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { initialize(VM.getVM().getTypeDataBase()); } })50     VM.registerVMInitializedObserver(new Observer() {
51         public void update(Observable o, Object data) {
52           initialize(VM.getVM().getTypeDataBase());
53         }
54       });
55   }
56 
initialize(TypeDataBase db)57   private static void initialize(TypeDataBase db) {
58     // FileMapInfo
59     Type type = db.lookupType("FileMapInfo");
60     AddressField currentInfoField = type.getAddressField("_current_info");
61     long headerFieldOffset = type.getField("_header").getOffset();
62     Address headerAddress = currentInfoField.getValue().addOffsetTo(headerFieldOffset);
63     headerValue = headerAddress.getAddressAt(0);
64 
65     // FileMapHeader
66     type = db.lookupType("FileMapHeader");
67     AddressField spaceField = type.getAddressField("_space[0]");
68     Address spaceValue = headerValue.addOffsetTo(type.getField("_space[0]").getOffset());
69     mdSpaceValue = spaceValue.addOffsetTo(3 * spaceField.getSize());
70 
71     // SpaceInfo
72     type = db.lookupType("CDSFileMapRegion");
73     long mdRegionBaseAddressOffset = type.getField("_mapped_base").getOffset();
74     mdRegionBaseAddress = (mdSpaceValue.addOffsetTo(mdRegionBaseAddressOffset)).getAddressAt(0);
75     long mdRegionSizeOffset = type.getField("_used").getOffset();
76     long mdRegionSize = (mdSpaceValue.addOffsetTo(mdRegionSizeOffset)).getAddressAt(0).asLongValue();
77     mdRegionEndAddress = mdRegionBaseAddress.addOffsetTo(mdRegionSize);
78 
79     populateMetadataTypeArray(db);
80   }
81 
populateMetadataTypeArray(TypeDataBase db)82   private static void populateMetadataTypeArray(TypeDataBase db) {
83     metadataTypeArray = new Type[8];
84 
85     metadataTypeArray[0] = db.lookupType("ConstantPool");
86     metadataTypeArray[1] = db.lookupType("InstanceKlass");
87     metadataTypeArray[2] = db.lookupType("InstanceClassLoaderKlass");
88     metadataTypeArray[3] = db.lookupType("InstanceMirrorKlass");
89     metadataTypeArray[4] = db.lookupType("InstanceRefKlass");
90     metadataTypeArray[5] = db.lookupType("Method");
91     metadataTypeArray[6] = db.lookupType("ObjArrayKlass");
92     metadataTypeArray[7] = db.lookupType("TypeArrayKlass");
93   }
94 
getHeader()95   public FileMapHeader getHeader() {
96     if (header == null) {
97       header = (FileMapHeader) VMObjectFactory.newObject(FileMapInfo.FileMapHeader.class, headerValue);
98     }
99     return header;
100   }
101 
inCopiedVtableSpace(Address vptrAddress)102   public boolean inCopiedVtableSpace(Address vptrAddress) {
103     FileMapHeader fmHeader = getHeader();
104     return fmHeader.inCopiedVtableSpace(vptrAddress);
105   }
106 
getTypeForVptrAddress(Address vptrAddress)107   public Type getTypeForVptrAddress(Address vptrAddress) {
108     if (vTableTypeMap == null) {
109       getHeader().createVtableTypeMapping();
110     }
111     return vTableTypeMap.get(vptrAddress);
112   }
113 
114 
115   //------------------------------------------------------------------------------------------
116 
117   public static class FileMapHeader extends VMObject {
118 
FileMapHeader(Address addr)119     public FileMapHeader(Address addr) {
120       super(addr);
121     }
122 
inCopiedVtableSpace(Address vptrAddress)123     public boolean inCopiedVtableSpace(Address vptrAddress) {
124       if (vptrAddress.greaterThan(mdRegionBaseAddress) &&
125           vptrAddress.lessThanOrEqual(mdRegionEndAddress)) {
126         return true;
127       }
128       return false;
129     }
130 
createVtableTypeMapping()131     public void createVtableTypeMapping() {
132       vTableTypeMap = new HashMap<Address, Type>();
133       long metadataVTableSize = 0;
134       long addressSize = VM.getVM().getAddressSize();
135 
136       Address copiedVtableAddress = mdRegionBaseAddress;
137       for (int i=0; i < metadataTypeArray.length; i++) {
138         // The first entry denotes the vtable size.
139         metadataVTableSize = copiedVtableAddress.getAddressAt(0).asLongValue();
140         vTableTypeMap.put(copiedVtableAddress.addOffsetTo(addressSize), metadataTypeArray[i]);
141 
142         // The '+ 1' below is to skip the entry containing the size of this metadata's vtable.
143         copiedVtableAddress =
144           copiedVtableAddress.addOffsetTo((metadataVTableSize + 1) * addressSize);
145       }
146     }
147   }
148 }
149