changeset 50407:ec2dd30adbc1

8174994: SA: clhsdb printmdo throws WrongTypeException when attached to a process with CDS Summary: Read in the md region of the CDS archive in SA and map the vtable addresses to the corresponding metadata type. Reviewed-by: iklam, coleenp, ysuenaga, dholmes
author jgeorge
date Thu, 26 Apr 2018 12:25:36 +0530
parents 661ef62a6618
children 117501815bed
files src/hotspot/share/memory/filemap.hpp src/hotspot/share/runtime/vmStructs.cpp src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java test/hotspot/jtreg/serviceability/sa/ClhsdbCDSJstackPrintAll.java test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java
diffstat 11 files changed, 719 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/memory/filemap.hpp	Wed Apr 25 22:12:06 2018 -0700
+++ b/src/hotspot/share/memory/filemap.hpp	Thu Apr 26 12:25:36 2018 +0530
@@ -75,6 +75,7 @@
 class FileMapInfo : public CHeapObj<mtInternal> {
 private:
   friend class ManifestStream;
+  friend class VMStructs;
   enum {
     _invalid_version = -1,
     _current_version = 3
--- a/src/hotspot/share/runtime/vmStructs.cpp	Wed Apr 25 22:12:06 2018 -0700
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Thu Apr 26 12:25:36 2018 +0530
@@ -56,6 +56,7 @@
 #include "memory/referenceType.hpp"
 #include "memory/universe.hpp"
 #include "memory/virtualspace.hpp"
+#include "memory/filemap.hpp"
 #include "oops/array.hpp"
 #include "oops/arrayKlass.hpp"
 #include "oops/arrayOop.hpp"
@@ -1120,6 +1121,16 @@
      static_field(java_lang_Class,             _oop_size_offset,                              int)                                   \
      static_field(java_lang_Class,             _static_oop_field_count_offset,                int)                                   \
                                                                                                                                      \
+  /********************************************/                                                                                     \
+  /* FileMapInfo fields (CDS archive related) */                                                                                     \
+  /********************************************/                                                                                     \
+                                                                                                                                     \
+  nonstatic_field(FileMapInfo,                 _header,                                       FileMapInfo::FileMapHeader*)           \
+     static_field(FileMapInfo,                 _current_info,                                 FileMapInfo*)                          \
+  nonstatic_field(FileMapInfo::FileMapHeader,  _space[0],                                     FileMapInfo::FileMapHeader::space_info)\
+  nonstatic_field(FileMapInfo::FileMapHeader::space_info, _addr._base,                        char*)                                 \
+  nonstatic_field(FileMapInfo::FileMapHeader::space_info, _used,                              size_t)                                \
+                                                                                                                                     \
   /******************/                                                                                                               \
   /* VMError fields */                                                                                                               \
   /******************/                                                                                                               \
@@ -1444,7 +1455,7 @@
   declare_type(SafepointBlob,            SingletonBlob)                   \
   declare_type(DeoptimizationBlob,       SingletonBlob)                   \
   declare_c2_type(ExceptionBlob,         SingletonBlob)                   \
-  declare_c2_type(UncommonTrapBlob,      RuntimeBlob)                        \
+  declare_c2_type(UncommonTrapBlob,      RuntimeBlob)                     \
                                                                           \
   /***************************************/                               \
   /* PcDesc and other compiled code info */                               \
@@ -2000,6 +2011,10 @@
   declare_toplevel_type(vframeArrayElement)                               \
   declare_toplevel_type(Annotations*)                                     \
   declare_type(OopMapValue, StackObj)                                     \
+  declare_type(FileMapInfo, CHeapObj<mtInternal>)                         \
+  declare_type(FileMapInfo::FileMapHeaderBase, CHeapObj<mtClass>)         \
+  declare_type(FileMapInfo::FileMapHeader, FileMapInfo::FileMapHeaderBase)\
+  declare_toplevel_type(FileMapInfo::FileMapHeader::space_info)           \
                                                                           \
   /************/                                                          \
   /* GC types */                                                          \
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c	Wed Apr 25 22:12:06 2018 -0700
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c	Thu Apr 26 12:25:36 2018 +0530
@@ -212,29 +212,51 @@
 // mapped.  This structure gets written to a file.  It is not a class,
 // so that the compilers don't add any compiler-private data to it.
 
-#define NUM_SHARED_MAPS 4
+#define NUM_SHARED_MAPS 9
 
 // Refer to FileMapInfo::_current_version in filemap.hpp
-#define CURRENT_ARCHIVE_VERSION 1
+#define CURRENT_ARCHIVE_VERSION 3
+
+typedef unsigned char* address;
+typedef uintptr_t      uintx;
+typedef intptr_t       intx;
 
 struct FileMapHeader {
-  int   _magic;              // identify file type.
-  int   _version;            // (from enum, above.)
-  size_t _alignment;         // how shared archive should be aligned
+  int     _magic;                   // identify file type.
+  int     _crc;                     // header crc checksum.
+  int     _version;                 // (from enum, above.)
+  size_t  _alignment;               // how shared archive should be aligned
+  int     _obj_alignment;           // value of ObjectAlignmentInBytes
+  address _narrow_oop_base;         // compressed oop encoding base
+  int     _narrow_oop_shift;        // compressed oop encoding shift
+  bool    _compact_strings;         // value of CompactStrings
+  uintx   _max_heap_size;           // java max heap size during dumping
+  int     _narrow_oop_mode;         // compressed oop encoding mode
+  int     _narrow_klass_shift;      // save narrow klass base and shift
+  address _narrow_klass_base;
+  char*   _misc_data_patching_start;
+  char*   _read_only_tables_start;
+  address _cds_i2i_entry_code_buffers;
+  size_t  _cds_i2i_entry_code_buffers_size;
+  size_t  _core_spaces_size;        // number of bytes allocated by the core spaces
+                                    // (mc, md, ro, rw and od).
+
 
   struct space_info {
-    int    _file_offset;     // sizeof(this) rounded to vm page size
-    char*  _base;            // copy-on-write base address
-    size_t _capacity;        // for validity checking
-    size_t _used;            // for setting space top on read
-
+    int     _crc;          // crc checksum of the current space
+    size_t  _file_offset;  // sizeof(this) rounded to vm page size
+    union {
+      char*  _base;        // copy-on-write base address
+      intx   _offset;      // offset from the compressed oop encoding base, only used
+                           // by archive heap space
+    } _addr;
+    size_t _used;          // for setting space top on read
     // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
     // the C type matching the C++ bool type on any given platform.
     // We assume the corresponding C type is char but licensees
     // may need to adjust the type of these fields.
-    char   _read_only;       // read only space?
-    char   _allow_exec;      // executable code in space?
-
+    char   _read_only;     // read only space?
+    char   _allow_exec;    // executable code in space?
   } _space[NUM_SHARED_MAPS];
 
   // Ignore the rest of the FileMapHeader. We don't need those fields here.
@@ -381,7 +403,7 @@
       // add read-only maps from classes.jsa to the list of maps
       for (m = 0; m < NUM_SHARED_MAPS; m++) {
         if (header._space[m]._read_only) {
-          base = (uintptr_t) header._space[m]._base;
+          base = (uintptr_t) header._space[m]._addr._base;
           // no need to worry about the fractional pages at-the-end.
           // possible fractional pages are handled by core_read_data.
           add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
--- a/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c	Wed Apr 25 22:12:06 2018 -0700
+++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c	Thu Apr 26 12:25:36 2018 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -213,29 +213,52 @@
 // mapped.  This structure gets written to a file.  It is not a class,
 // so that the compilers don't add any compiler-private data to it.
 
-#define NUM_SHARED_MAPS 4
+#define NUM_SHARED_MAPS 9
 
 // Refer to FileMapInfo::_current_version in filemap.hpp
-#define CURRENT_ARCHIVE_VERSION 1
+#define CURRENT_ARCHIVE_VERSION 3
+
+typedef unsigned char* address;
+typedef uintptr_t      uintx;
+typedef intptr_t       intx;
+
 
 struct FileMapHeader {
-  int   _magic;              // identify file type.
-  int   _version;            // (from enum, above.)
-  size_t _alignment;         // how shared archive should be aligned
+  int     _magic;                   // identify file type.
+  int     _crc;                     // header crc checksum.
+  int     _version;                 // (from enum, above.)
+  size_t  _alignment;               // how shared archive should be aligned
+  int     _obj_alignment;           // value of ObjectAlignmentInBytes
+  address _narrow_oop_base;         // compressed oop encoding base
+  int     _narrow_oop_shift;        // compressed oop encoding shift
+  bool    _compact_strings;         // value of CompactStrings
+  uintx   _max_heap_size;           // java max heap size during dumping
+  int     _narrow_oop_mode;         // compressed oop encoding mode
+  int     _narrow_klass_shift;      // save narrow klass base and shift
+  address _narrow_klass_base;
+  char*   _misc_data_patching_start;
+  char*   _read_only_tables_start;
+  address _cds_i2i_entry_code_buffers;
+  size_t  _cds_i2i_entry_code_buffers_size;
+  size_t  _core_spaces_size;        // number of bytes allocated by the core spaces
+                                    // (mc, md, ro, rw and od).
+
 
   struct space_info {
-    int    _file_offset;     // sizeof(this) rounded to vm page size
-    char*  _base;            // copy-on-write base address
-    size_t _capacity;        // for validity checking
-    size_t _used;            // for setting space top on read
-
+    int     _crc;          // crc checksum of the current space
+    size_t  _file_offset;  // sizeof(this) rounded to vm page size
+    union {
+      char*  _base;        // copy-on-write base address
+      intx   _offset;      // offset from the compressed oop encoding base, only used
+                           // by archive heap space
+    } _addr;
+    size_t _used;          // for setting space top on read
     // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
     // the C type matching the C++ bool type on any given platform.
     // We assume the corresponding C type is char but licensees
     // may need to adjust the type of these fields.
-    char   _read_only;       // read only space?
-    char   _allow_exec;      // executable code in space?
-
+    char   _read_only;     // read only space?
+    char   _allow_exec;    // executable code in space?
   } _space[NUM_SHARED_MAPS];
 
   // Ignore the rest of the FileMapHeader. We don't need those fields here.
@@ -282,15 +305,14 @@
   return true;
 }
 
+// mangled name of Arguments::SharedArchivePath
+#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
+
 #ifdef __APPLE__
 #define USE_SHARED_SPACES_SYM "_UseSharedSpaces"
-// mangled name of Arguments::SharedArchivePath
-#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
 #define LIBJVM_NAME "/libjvm.dylib"
 #else
 #define USE_SHARED_SPACES_SYM "UseSharedSpaces"
-// mangled name of Arguments::SharedArchivePath
-#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
 #define LIBJVM_NAME "/libjvm.so"
 #endif // __APPLE_
 
@@ -387,7 +409,7 @@
       // add read-only maps from classes.jsa to the list of maps
       for (m = 0; m < NUM_SHARED_MAPS; m++) {
         if (header._space[m]._read_only) {
-          base = (uintptr_t) header._space[m]._base;
+          base = (uintptr_t) header._space[m]._addr._base;
           // no need to worry about the fractional pages at-the-end.
           // possible fractional pages are handled by core_read_data.
           add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java	Thu Apr 26 12:25:36 2018 +0530
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.memory;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.runtime.VMObject;
+import sun.jvm.hotspot.runtime.VMObjectFactory;
+import sun.jvm.hotspot.types.*;
+
+public class FileMapInfo {
+  private static FileMapHeader header;
+  private static Address headerValue;
+
+  // Fields for class FileMapHeader
+  private static Address mdSpaceValue;
+  private static Address mdRegionBaseAddress;
+  private static Address mdRegionEndAddress;
+
+  // HashMap created by mapping the vTable addresses in the md region with
+  // the corresponding metadata type.
+  private static Map<Address, Type> vTableTypeMap;
+
+  private static Type metadataTypeArray[];
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static void initialize(TypeDataBase db) {
+    // FileMapInfo
+    Type type = db.lookupType("FileMapInfo");
+    AddressField currentInfoField = type.getAddressField("_current_info");
+    long headerFieldOffset = type.getField("_header").getOffset();
+    Address headerAddress = currentInfoField.getValue().addOffsetTo(headerFieldOffset);
+    headerValue = headerAddress.getAddressAt(0);
+
+    // FileMapHeader
+    type = db.lookupType("FileMapInfo::FileMapHeader");
+    AddressField spaceField = type.getAddressField("_space[0]");
+    Address spaceValue = headerValue.addOffsetTo(type.getField("_space[0]").getOffset());
+    mdSpaceValue = spaceValue.addOffsetTo(3 * spaceField.getSize());
+
+    // SpaceInfo
+    type = db.lookupType("FileMapInfo::FileMapHeader::space_info");
+    long mdRegionBaseAddressOffset = type.getField("_addr._base").getOffset();
+    mdRegionBaseAddress = (mdSpaceValue.addOffsetTo(mdRegionBaseAddressOffset)).getAddressAt(0);
+    long mdRegionSizeOffset = type.getField("_used").getOffset();
+    long mdRegionSize = (mdSpaceValue.addOffsetTo(mdRegionSizeOffset)).getAddressAt(0).asLongValue();
+    mdRegionEndAddress = mdRegionBaseAddress.addOffsetTo(mdRegionSize);
+
+    populateMetadataTypeArray(db);
+  }
+
+  private static void populateMetadataTypeArray(TypeDataBase db) {
+    metadataTypeArray = new Type[8];
+
+    metadataTypeArray[0] = db.lookupType("ConstantPool");
+    metadataTypeArray[1] = db.lookupType("InstanceKlass");
+    metadataTypeArray[2] = db.lookupType("InstanceClassLoaderKlass");
+    metadataTypeArray[3] = db.lookupType("InstanceMirrorKlass");
+    metadataTypeArray[4] = db.lookupType("InstanceRefKlass");
+    metadataTypeArray[5] = db.lookupType("Method");
+    metadataTypeArray[6] = db.lookupType("ObjArrayKlass");
+    metadataTypeArray[7] = db.lookupType("TypeArrayKlass");
+  }
+
+  public FileMapHeader getHeader() {
+    if (header == null) {
+      header = (FileMapHeader) VMObjectFactory.newObject(FileMapInfo.FileMapHeader.class, headerValue);
+    }
+    return header;
+  }
+
+  public boolean inCopiedVtableSpace(Address vptrAddress) {
+    FileMapHeader fmHeader = getHeader();
+    return fmHeader.inCopiedVtableSpace(vptrAddress);
+  }
+
+  public Type getTypeForVptrAddress(Address vptrAddress) {
+    if (vTableTypeMap == null) {
+      getHeader().createVtableTypeMapping();
+    }
+    return vTableTypeMap.get(vptrAddress);
+  }
+
+
+  //------------------------------------------------------------------------------------------
+
+  public static class FileMapHeader extends VMObject {
+
+    public FileMapHeader(Address addr) {
+      super(addr);
+    }
+
+    public boolean inCopiedVtableSpace(Address vptrAddress) {
+      if (vptrAddress.greaterThan(mdRegionBaseAddress) &&
+          vptrAddress.lessThanOrEqual(mdRegionEndAddress)) {
+        return true;
+      }
+      return false;
+    }
+
+    public void createVtableTypeMapping() {
+      vTableTypeMap = new HashMap<Address, Type>();
+      long metadataVTableSize = 0;
+      long addressSize = VM.getVM().getAddressSize();
+
+      Address copiedVtableAddress = mdRegionBaseAddress;
+      for (int i=0; i < metadataTypeArray.length; i++) {
+        // The first entry denotes the vtable size.
+        metadataVTableSize = copiedVtableAddress.getAddressAt(0).asLongValue();
+        vTableTypeMap.put(copiedVtableAddress.addOffsetTo(addressSize), metadataTypeArray[i]);
+
+        // The '+ 1' below is to skip the entry containing the size of this metadata's vtable.
+        copiedVtableAddress =
+          copiedVtableAddress.addOffsetTo((metadataVTableSize + 1) * addressSize);
+      }
+    }
+  }
+}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java	Wed Apr 25 22:12:06 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java	Thu Apr 26 12:25:36 2018 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,7 @@
   private JNIHandles   handles;
   private Interpreter  interpreter;
   private StubRoutines stubRoutines;
+  private FileMapInfo  fileMapInfo;
   private Bytes        bytes;
 
   /** Flag indicating if JVMTI support is included in the build */
@@ -717,6 +718,16 @@
     return vmregImpl;
   }
 
+  public FileMapInfo getFileMapInfo() {
+    if (!isSharingEnabled()) {
+      return null;
+    }
+    if (fileMapInfo == null) {
+      fileMapInfo = new FileMapInfo();
+    }
+    return fileMapInfo;
+  }
+
   public Bytes getBytes() {
     if (bytes == null) {
       bytes = new Bytes(debugger.getMachineDescription());
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java	Wed Apr 25 22:12:06 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java	Thu Apr 26 12:25:36 2018 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 import sun.jvm.hotspot.runtime.VM;
 import sun.jvm.hotspot.types.Type;
 import sun.jvm.hotspot.types.TypeDataBase;
+import sun.jvm.hotspot.memory.FileMapInfo;
 
 /** <P> This is a basic implementation of the TypeDataBase interface.
     It allows an external type database builder to add types to be
@@ -294,6 +295,15 @@
     // the locations searched.
 
     Address loc1 = addr.getAddressAt(0);
+
+    if (VM.getVM().isSharingEnabled()) {
+      // Check if the value falls in the _md_region
+      FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo();
+      if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) {
+         return cdsFileMapInfo.getTypeForVptrAddress(loc1);
+      }
+    }
+
     Address loc2 = null;
     Address loc3 = null;
     long offset2 = baseType.getSize();
--- a/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp	Wed Apr 25 22:12:06 2018 -0700
+++ b/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp	Thu Apr 26 12:25:36 2018 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -496,29 +496,54 @@
 // mapped.  This structure gets written to a file.  It is not a class, so
 // that the compilers don't add any compiler-private data to it.
 
-const int NUM_SHARED_MAPS = 4;
+const int NUM_SHARED_MAPS = 9;
 
 // Refer to FileMapInfo::_current_version in filemap.hpp
-const int CURRENT_ARCHIVE_VERSION = 1;
+const int CURRENT_ARCHIVE_VERSION = 3;
+
+typedef unsigned char* address;
+typedef uintptr_t      uintx;
+typedef intptr_t       intx;
 
 struct FileMapHeader {
- int   _magic;              // identify file type.
- int   _version;            // (from enum, above.)
- size_t _alignment;         // how shared archive should be aligned
+  int     _magic;                   // identify file type.
+  int     _crc;                     // header crc checksum.
+  int     _version;                 // (from enum, above.)
+  size_t  _alignment;               // how shared archive should be aligned
+  int     _obj_alignment;           // value of ObjectAlignmentInBytes
+  address _narrow_oop_base;         // compressed oop encoding base
+  int     _narrow_oop_shift;        // compressed oop encoding shift
+  bool    _compact_strings;         // value of CompactStrings
+  uintx   _max_heap_size;           // java max heap size during dumping
+  int     _narrow_oop_mode;         // compressed oop encoding mode
+  int     _narrow_klass_shift;      // save narrow klass base and shift
+  address _narrow_klass_base;
+  char*   _misc_data_patching_start;
+  char*   _read_only_tables_start;
+  address _cds_i2i_entry_code_buffers;
+  size_t  _cds_i2i_entry_code_buffers_size;
+  size_t  _core_spaces_size;        // number of bytes allocated by the core spaces
+                                    // (mc, md, ro, rw and od).
 
 
- struct space_info {
-   int    _file_offset;     // sizeof(this) rounded to vm page size
-   char*  _base;            // copy-on-write base address
-   size_t _capacity;        // for validity checking
-   size_t _used;            // for setting space top on read
+  struct space_info {
+    int     _crc;          // crc checksum of the current space
+    size_t  _file_offset;  // sizeof(this) rounded to vm page size
+    union {
+      char*  _base;        // copy-on-write base address
+      intx   _offset;      // offset from the compressed oop encoding base, only used
+                           // by archive heap space
+    } _addr;
+    size_t _used;          // for setting space top on read
+    // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
+    // the C type matching the C++ bool type on any given platform.
+    // We assume the corresponding C type is char but licensees
+    // may need to adjust the type of these fields.
+    char   _read_only;     // read only space?
+    char   _allow_exec;    // executable code in space?
+  } _space[NUM_SHARED_MAPS];
 
-   bool   _read_only;       // read only space?
-   bool   _allow_exec;      // executable code in space?
-
- } _space[NUM_SHARED_MAPS];
-
- // Ignore the rest of the FileMapHeader. We don't need those fields here.
+// Ignore the rest of the FileMapHeader. We don't need those fields here.
 };
 
 static bool
@@ -677,7 +702,7 @@
   if (_libsaproc_debug) {
     for (int m = 0; m < NUM_SHARED_MAPS; m++) {
        print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n",
-          pheader->_space[m]._file_offset, pheader->_space[m]._base,
+          pheader->_space[m]._file_offset, pheader->_space[m]._addr._base,
           pheader->_space[m]._used, pheader->_space[m]._read_only);
     }
   }
@@ -1058,7 +1083,7 @@
       print_debug("read failed at 0x%lx, attempting shared heap area\n", (long) address);
 
       struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID);
-      // walk through the shared mappings -- we just have 4 of them.
+      // walk through the shared mappings -- we just have 9 of them.
       // so, linear walking is okay.
       for (int m = 0; m < NUM_SHARED_MAPS; m++) {
 
@@ -1066,7 +1091,7 @@
         // and hence will be read by libproc. Besides, the file copy may be
         // stale because the process might have modified those pages.
         if (pheader->_space[m]._read_only) {
-          jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._base;
+          jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._addr._base;
           size_t usedSize = pheader->_space[m]._used;
           if (address >= baseAddress && address < (baseAddress + usedSize)) {
             // the given address falls in this shared heap area
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java	Thu Apr 26 12:25:36 2018 +0530
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8174994
+ * @summary Test the clhsdb commands 'printmdo', 'printall' on a CDS enabled corefile.
+ * @requires vm.cds
+ * @requires os.family != "windows"
+ * @requires vm.flavor == "server"
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @run main/othervm/timeout=2400 -Xmx1g ClhsdbCDSCore
+ */
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.HashMap;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.cds.CDSTestUtils;
+import jdk.test.lib.cds.CDSOptions;
+import java.io.IOException;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import jdk.test.lib.Asserts;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import jdk.internal.misc.Unsafe;
+import java.util.Scanner;
+
+class CrashApp {
+    public static void main(String[] args) {
+        Unsafe.getUnsafe().putInt(0L, 0);
+    }
+}
+
+public class ClhsdbCDSCore {
+
+    private static final String TEST_CDS_CORE_FILE_NAME = "cds_core_file";
+    private static final String LOCATIONS_STRING = "location: ";
+    private static final String RUN_SHELL_NO_LIMIT = "ulimit -c unlimited && ";
+    private static final String SHARED_ARCHIVE_NAME = "ArchiveForClhsdbCDSCore.jsa";
+    private static final String CORE_PATTERN_FILE_NAME = "/proc/sys/kernel/core_pattern";
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Starting ClhsdbCDSCore test");
+        cleanup();
+
+        try {
+            CDSOptions opts = (new CDSOptions()).setArchiveName(SHARED_ARCHIVE_NAME);
+            CDSTestUtils.createArchiveAndCheck(opts);
+
+            String[] jArgs = {
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:SharedArchiveFile=" + SHARED_ARCHIVE_NAME,
+                "-XX:+CreateCoredumpOnCrash",
+                "-Xshare:auto",
+                "-XX:+ProfileInterpreter",
+                "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
+                CrashApp.class.getName()
+            };
+
+            OutputAnalyzer crashOut;
+            try {
+               List<String> options = new ArrayList<>();
+               options.addAll(Arrays.asList(jArgs));
+               crashOut =
+                   ProcessTools.executeProcess(getTestJavaCommandlineWithPrefix(
+                   RUN_SHELL_NO_LIMIT, options.toArray(new String[0])));
+            } catch (Throwable t) {
+               throw new Error("Can't execute the java cds process.", t);
+            }
+
+            System.out.println(crashOut.getOutput());
+            String crashOutputString = crashOut.getOutput();
+            String coreFileLocation = getCoreFileLocation(crashOutputString);
+            if (coreFileLocation == null) {
+                if (Platform.isOSX()) {
+                    File coresDir = new File("/cores");
+                    if (!coresDir.isDirectory() || !coresDir.canWrite()) {
+                        throw new Error("cores is not a directory or does not have write permissions");
+                    }
+                } else if (Platform.isLinux()) {
+                    // Check if a crash report tool is installed.
+                    File corePatternFile = new File(CORE_PATTERN_FILE_NAME);
+                    Scanner scanner = new Scanner(corePatternFile);
+                    while (scanner.hasNextLine()) {
+                        String line = scanner.nextLine();
+                        line = line.trim();
+                        System.out.println(line);
+                        if (line.startsWith("|")) {
+                            System.out.println(
+                                "\nThis system uses a crash report tool ($cat /proc/sys/kernel/core_pattern).\n" +
+                                "Core files might not be generated. Please reset /proc/sys/kernel/core_pattern\n" +
+                                "to enable core generation. Skipping this test.");
+                            cleanup();
+                            return;
+                        }
+                    }
+                }
+                throw new Error("Couldn't find core file location in: '" + crashOutputString + "'");
+            }
+            try {
+                Asserts.assertGT(new File(coreFileLocation).length(), 0L, "Unexpected core size");
+                Files.move(Paths.get(coreFileLocation), Paths.get(TEST_CDS_CORE_FILE_NAME));
+            } catch (IOException ioe) {
+                throw new Error("Can't move core file: " + ioe, ioe);
+            }
+
+            ClhsdbLauncher test = new ClhsdbLauncher();
+
+            // Ensure that UseSharedSpaces is turned on.
+            List<String> cmds = List.of("flags UseSharedSpaces");
+
+            String useSharedSpacesOutput = test.runOnCore(TEST_CDS_CORE_FILE_NAME, cmds,
+                                                          null, null);
+
+            if (useSharedSpacesOutput == null) {
+                // Output could be null due to attach permission issues.
+                System.out.println("Could not determine the UseSharedSpaces value - test skipped.");
+                cleanup();
+                return;
+            }
+
+            if (!useSharedSpacesOutput.contains("true")) {
+                // CDS archive is not mapped. Skip the rest of the test.
+                System.out.println("The CDS archive is not mapped - test skipped.");
+                cleanup();
+                return;
+            }
+
+            cmds = List.of("printmdo -a", "printall");
+
+            Map<String, List<String>> expStrMap = new HashMap<>();
+            Map<String, List<String>> unExpStrMap = new HashMap<>();
+            expStrMap.put("printmdo -a", List.of(
+                "CounterData",
+                "BranchData"));
+            unExpStrMap.put("printmdo -a", List.of(
+                "No suitable match for type of address"));
+            expStrMap.put("printall", List.of(
+                "aload_0",
+                "Constant Pool of",
+                "public static void main(java.lang.String[])",
+                "Bytecode",
+                "invokevirtual",
+                "checkcast",
+                "Exception Table",
+                "invokedynamic"));
+            unExpStrMap.put("printall", List.of(
+                "sun.jvm.hotspot.types.WrongTypeException",
+                "No suitable match for type of address"));
+            test.runOnCore(TEST_CDS_CORE_FILE_NAME, cmds, expStrMap, unExpStrMap);
+        } catch (Exception ex) {
+            throw new RuntimeException("Test ERROR " + ex, ex);
+        }
+        cleanup();
+        System.out.println("Test PASSED");
+    }
+
+    // lets search for a few possible locations using process output and return existing location
+    private static String getCoreFileLocation(String crashOutputString) {
+        Asserts.assertTrue(crashOutputString.contains(LOCATIONS_STRING),
+            "Output doesn't contain the location of core file.");
+        String stringWithLocation = Arrays.stream(crashOutputString.split("\\r?\\n"))
+            .filter(str -> str.contains(LOCATIONS_STRING))
+            .findFirst()
+            .get();
+        stringWithLocation = stringWithLocation.substring(stringWithLocation
+            .indexOf(LOCATIONS_STRING) + LOCATIONS_STRING.length());
+        String coreWithPid;
+        if (stringWithLocation.contains("or ")) {
+            Matcher m = Pattern.compile("or.* ([^ ]+[^\\)])\\)?").matcher(stringWithLocation);
+            if (!m.find()) {
+                throw new Error("Couldn't find path to core inside location string");
+            }
+            coreWithPid = m.group(1);
+        } else {
+            coreWithPid = stringWithLocation.trim();
+        }
+        if (new File(coreWithPid).exists()) {
+            return coreWithPid;
+        }
+        String justCore = Paths.get("core").toString();
+        if (new File(justCore).exists()) {
+            return justCore;
+        }
+        Path coreWithPidPath = Paths.get(coreWithPid);
+        String justFile = coreWithPidPath.getFileName().toString();
+        if (new File(justFile).exists()) {
+            return justFile;
+        }
+        Path parent = coreWithPidPath.getParent();
+        if (parent != null) {
+            String coreWithoutPid = parent.resolve("core").toString();
+            if (new File(coreWithoutPid).exists()) {
+                return coreWithoutPid;
+            }
+        }
+        return null;
+    }
+
+    private static String[] getTestJavaCommandlineWithPrefix(String prefix, String... args) {
+        try {
+            String cmd = ProcessTools.getCommandLine(ProcessTools.createJavaProcessBuilder(true, args));
+            return new String[]{"sh", "-c", prefix + cmd};
+        } catch (Throwable t) {
+            throw new Error("Can't create process builder: " + t, t);
+        }
+    }
+
+    private static void cleanup() {
+        remove(TEST_CDS_CORE_FILE_NAME);
+        remove(SHARED_ARCHIVE_NAME);
+    }
+
+    private static void remove(String item) {
+        File toDelete = new File(item);
+        toDelete.delete();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSJstackPrintAll.java	Thu Apr 26 12:25:36 2018 +0530
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8174994
+ * @summary Test the clhsdb commands 'jstack', 'printall' with CDS enabled
+ * @requires vm.cds
+ * @library /test/lib
+ * @run main/othervm/timeout=2400 -Xmx1g ClhsdbCDSJstackPrintAll
+ */
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.HashMap;
+import jdk.test.lib.cds.CDSTestUtils;
+import jdk.test.lib.cds.CDSOptions;
+import jdk.test.lib.apps.LingeredApp;
+
+public class ClhsdbCDSJstackPrintAll {
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Starting ClhsdbCDSJstackPrintAll test");
+        String sharedArchiveName = "ArchiveForClhsdbJstackPrintAll.jsa";
+        LingeredApp theApp = null;
+
+        try {
+            CDSOptions opts = (new CDSOptions()).setArchiveName(sharedArchiveName);
+            CDSTestUtils.createArchiveAndCheck(opts);
+
+            ClhsdbLauncher test = new ClhsdbLauncher();
+            List<String> vmArgs = Arrays.asList(
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:SharedArchiveFile=" + sharedArchiveName,
+                "-Xshare:auto");
+            theApp = LingeredApp.startApp(vmArgs);
+            System.out.println("Started LingeredApp with pid " + theApp.getPid());
+
+            // Ensure that UseSharedSpaces is turned on.
+            List<String> cmds = List.of("flags UseSharedSpaces");
+
+            String useSharedSpacesOutput = test.run(theApp.getPid(), cmds,
+                                                    null, null);
+
+            if (useSharedSpacesOutput == null) {
+                // Attach permission issues.
+                System.out.println("Could not determine the UseSharedSpaces value - test skipped.");
+                LingeredApp.stopApp(theApp);
+                return;
+            }
+
+            if (!useSharedSpacesOutput.contains("true")) {
+                // CDS archive is not mapped. Skip the rest of the test.
+                System.out.println("The CDS archive is not mapped - test skipped.");
+                LingeredApp.stopApp(theApp);
+                return;
+            }
+
+            cmds = List.of("jstack -v", "printall");
+
+            Map<String, List<String>> expStrMap = new HashMap<>();
+            Map<String, List<String>> unExpStrMap = new HashMap<>();
+            expStrMap.put("jstack -v", List.of(
+                "No deadlocks found",
+                "Common-Cleaner",
+                "Signal Dispatcher",
+                "Method*",
+                "LingeredApp.main"));
+            unExpStrMap.put("jstack -v", List.of(
+                "sun.jvm.hotspot.types.WrongTypeException",
+                "No suitable match for type of address"));
+            expStrMap.put("printall", List.of(
+                "aload_0",
+                "Constant Pool of",
+                "public static void main(java.lang.String[])",
+                "Bytecode",
+                "invokevirtual",
+                "checkcast",
+                "Exception Table",
+                "invokedynamic"));
+            unExpStrMap.put("printall", List.of(
+                "No suitable match for type of address"));
+            test.run(theApp.getPid(), cmds, expStrMap, unExpStrMap);
+        } catch (Exception ex) {
+            throw new RuntimeException("Test ERROR " + ex, ex);
+        } finally {
+            LingeredApp.stopApp(theApp);
+        }
+        System.out.println("Test PASSED");
+    }
+}
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java	Wed Apr 25 22:12:06 2018 -0700
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java	Thu Apr 26 12:25:36 2018 +0530
@@ -29,6 +29,7 @@
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.Platform;
 import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.process.OutputAnalyzer;
 
 /**
@@ -68,6 +69,27 @@
 
     /**
      *
+     * Launches 'jhsdb clhsdb' and loads a core file.
+     * @param coreFileName - Name of the corefile to be loaded.
+     */
+    private void loadCore(String coreFileName)
+        throws IOException {
+
+        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
+        launcher.addToolArg("clhsdb");
+        launcher.addToolArg("--core=" + coreFileName);
+        launcher.addToolArg("--exe=" + JDKToolFinder.getTestJDKTool("java"));
+        System.out.println("Starting clhsdb against corefile " + coreFileName +
+                           " and exe " + JDKToolFinder.getTestJDKTool("java"));
+
+        ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+        processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
+
+        toolProcess = processBuilder.start();
+    }
+
+    /**
+     *
      * Runs 'jhsdb clhsdb' commands and checks for expected and unexpected strings.
      * @param commands  - clhsdb commands to execute.
      * @param expectedStrMap - Map of expected strings per command which need to
@@ -159,4 +181,32 @@
         attach(lingeredAppPid);
         return runCmd(commands, expectedStrMap, unExpectedStrMap);
     }
+
+    /**
+     *
+     * Launches 'jhsdb clhsdb', loads a core file, executes the commands,
+     * checks for expected and unexpected strings.
+     * @param coreFileName - Name of the core file to be debugged.
+     * @param commands  - clhsdb commands to execute.
+     * @param expectedStrMap - Map of expected strings per command which need to
+     *                         be checked in the output of the command.
+     * @param unExpectedStrMap - Map of unexpected strings per command which should
+     *                           not be present in the output of the command.
+     * @return Output of the commands as a String.
+     */
+    public String runOnCore(String coreFileName,
+                            List<String> commands,
+                            Map<String, List<String>> expectedStrMap,
+                            Map<String, List<String>> unExpectedStrMap)
+        throws IOException, InterruptedException {
+
+        if (!Platform.shouldSAAttach()) {
+            // Silently skip the test if we don't have enough permissions to attach
+            System.out.println("SA attach not expected to work - test skipped.");
+            return null;
+        }
+
+        loadCore(coreFileName);
+        return runCmd(commands, expectedStrMap, unExpectedStrMap);
+    }
 }