Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/memory/filemap.cpp
32285 views
/*1* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/classLoader.hpp"26#include "classfile/sharedClassUtil.hpp"27#include "classfile/symbolTable.hpp"28#include "classfile/systemDictionaryShared.hpp"29#include "classfile/altHashing.hpp"30#include "memory/filemap.hpp"31#include "memory/metadataFactory.hpp"32#include "memory/oopFactory.hpp"33#include "oops/objArrayOop.hpp"34#include "runtime/arguments.hpp"35#include "runtime/java.hpp"36#include "runtime/os.hpp"37#include "services/memTracker.hpp"38#include "utilities/defaultStream.hpp"3940# include <sys/stat.h>41# include <errno.h>4243#ifndef O_BINARY // if defined (Win32) use binary files.44#define O_BINARY 0 // otherwise do nothing.45#endif4647PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC48extern address JVM_FunctionAtStart();49extern address JVM_FunctionAtEnd();5051// Complain and stop. All error conditions occurring during the writing of52// an archive file should stop the process. Unrecoverable errors during53// the reading of the archive file should stop the process.5455static void fail(const char *msg, va_list ap) {56// This occurs very early during initialization: tty is not initialized.57jio_fprintf(defaultStream::error_stream(),58"An error has occurred while processing the"59" shared archive file.\n");60jio_vfprintf(defaultStream::error_stream(), msg, ap);61jio_fprintf(defaultStream::error_stream(), "\n");62// Do not change the text of the below message because some tests check for it.63vm_exit_during_initialization("Unable to use shared archive.", NULL);64}656667void FileMapInfo::fail_stop(const char *msg, ...) {68va_list ap;69va_start(ap, msg);70fail(msg, ap); // Never returns.71va_end(ap); // for completeness.72}737475// Complain and continue. Recoverable errors during the reading of the76// archive file may continue (with sharing disabled).77//78// If we continue, then disable shared spaces and close the file.7980void FileMapInfo::fail_continue(const char *msg, ...) {81va_list ap;82va_start(ap, msg);83MetaspaceShared::set_archive_loading_failed();84if (PrintSharedArchiveAndExit && _validating_classpath_entry_table) {85// If we are doing PrintSharedArchiveAndExit and some of the classpath entries86// do not validate, we can still continue "limping" to validate the remaining87// entries. No need to quit.88tty->print("[");89tty->vprint(msg, ap);90tty->print_cr("]");91} else {92if (RequireSharedSpaces) {93fail(msg, ap);94} else {95if (PrintSharedSpaces) {96tty->print_cr("UseSharedSpaces: %s", msg);97}98}99UseSharedSpaces = false;100assert(current_info() != NULL, "singleton must be registered");101current_info()->close();102}103va_end(ap);104}105106// Fill in the fileMapInfo structure with data about this VM instance.107108// This method copies the vm version info into header_version. If the version is too109// long then a truncated version, which has a hash code appended to it, is copied.110//111// Using a template enables this method to verify that header_version is an array of112// length JVM_IDENT_MAX. This ensures that the code that writes to the CDS file and113// the code that reads the CDS file will both use the same size buffer. Hence, will114// use identical truncation. This is necessary for matching of truncated versions.115template <int N> static void get_header_version(char (&header_version) [N]) {116assert(N == JVM_IDENT_MAX, "Bad header_version size");117118const char *vm_version = VM_Version::internal_vm_info_string();119const int version_len = (int)strlen(vm_version);120121if (version_len < (JVM_IDENT_MAX-1)) {122strcpy(header_version, vm_version);123124} else {125// Get the hash value. Use a static seed because the hash needs to return the same126// value over multiple jvm invocations.127uint32_t hash = AltHashing::halfsiphash_32(8191, (const uint8_t*)vm_version, version_len);128129// Truncate the ident, saving room for the 8 hex character hash value.130strncpy(header_version, vm_version, JVM_IDENT_MAX-9);131132// Append the hash code as eight hex digits.133sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash);134header_version[JVM_IDENT_MAX-1] = 0; // Null terminate.135}136}137138FileMapInfo::FileMapInfo() {139assert(_current_info == NULL, "must be singleton"); // not thread safe140_current_info = this;141memset(this, 0, sizeof(FileMapInfo));142_file_offset = 0;143_file_open = false;144_header = SharedClassUtil::allocate_file_map_header();145_header->_version = _invalid_version;146}147148FileMapInfo::~FileMapInfo() {149assert(_current_info == this, "must be singleton"); // not thread safe150_current_info = NULL;151}152153void FileMapInfo::populate_header(size_t alignment) {154_header->populate(this, alignment);155}156157size_t FileMapInfo::FileMapHeader::data_size() {158return SharedClassUtil::file_map_header_size() - sizeof(FileMapInfo::FileMapHeaderBase);159}160161void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {162_magic = 0xf00baba2;163_version = _current_version;164_alignment = alignment;165_obj_alignment = ObjectAlignmentInBytes;166_classpath_entry_table_size = mapinfo->_classpath_entry_table_size;167_classpath_entry_table = mapinfo->_classpath_entry_table;168_classpath_entry_size = mapinfo->_classpath_entry_size;169170// The following fields are for sanity checks for whether this archive171// will function correctly with this JVM and the bootclasspath it's172// invoked with.173174// JVM version string ... changes on each build.175get_header_version(_jvm_ident);176}177178void FileMapInfo::allocate_classpath_entry_table() {179int bytes = 0;180int count = 0;181char* strptr = NULL;182char* strptr_max = NULL;183Thread* THREAD = Thread::current();184185ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();186size_t entry_size = SharedClassUtil::shared_class_path_entry_size();187188for (int pass=0; pass<2; pass++) {189ClassPathEntry *cpe = ClassLoader::classpath_entry(0);190191for (int cur_entry = 0 ; cpe != NULL; cpe = cpe->next(), cur_entry++) {192const char *name = cpe->name();193int name_bytes = (int)(strlen(name) + 1);194195if (pass == 0) {196count ++;197bytes += (int)entry_size;198bytes += name_bytes;199if (TraceClassPaths || (TraceClassLoading && Verbose)) {200tty->print_cr("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name);201}202} else {203SharedClassPathEntry* ent = shared_classpath(cur_entry);204if (cpe->is_jar_file()) {205struct stat st;206if (os::stat(name, &st) != 0) {207// The file/dir must exist, or it would not have been added208// into ClassLoader::classpath_entry().209//210// If we can't access a jar file in the boot path, then we can't211// make assumptions about where classes get loaded from.212FileMapInfo::fail_stop("Unable to open jar file %s.", name);213}214215EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.216SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);217} else {218ent->_filesize = -1;219if (!os::dir_is_empty(name)) {220ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name);221}222}223ent->_name = strptr;224if (strptr + name_bytes <= strptr_max) {225strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0.226strptr += name_bytes;227} else {228assert(0, "miscalculated buffer size");229}230}231}232233if (pass == 0) {234EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.235Array<u8>* arr = MetadataFactory::new_array<u8>(loader_data, (bytes + 7)/8, THREAD);236strptr = (char*)(arr->data());237strptr_max = strptr + bytes;238SharedClassPathEntry* table = (SharedClassPathEntry*)strptr;239strptr += entry_size * count;240241_classpath_entry_table_size = count;242_classpath_entry_table = table;243_classpath_entry_size = entry_size;244}245}246}247248bool FileMapInfo::validate_classpath_entry_table() {249_validating_classpath_entry_table = true;250251int count = _header->_classpath_entry_table_size;252253_classpath_entry_table = _header->_classpath_entry_table;254_classpath_entry_size = _header->_classpath_entry_size;255256for (int i=0; i<count; i++) {257SharedClassPathEntry* ent = shared_classpath(i);258struct stat st;259const char* name = ent->_name;260bool ok = true;261if (TraceClassPaths || (TraceClassLoading && Verbose)) {262tty->print_cr("[Checking shared classpath entry: %s]", name);263}264if (os::stat(name, &st) != 0) {265fail_continue("Required classpath entry does not exist: %s", name);266ok = false;267} else if (ent->is_dir()) {268if (!os::dir_is_empty(name)) {269fail_continue("directory is not empty: %s", name);270ok = false;271}272} else {273if (ent->_timestamp != st.st_mtime ||274ent->_filesize != st.st_size) {275ok = false;276if (PrintSharedArchiveAndExit) {277fail_continue(ent->_timestamp != st.st_mtime ?278"Timestamp mismatch" :279"File size mismatch");280} else {281fail_continue("A jar file is not the one used while building"282" the shared archive file: %s", name);283}284}285}286if (ok) {287if (TraceClassPaths || (TraceClassLoading && Verbose)) {288tty->print_cr("[ok]");289}290} else if (!PrintSharedArchiveAndExit) {291_validating_classpath_entry_table = false;292return false;293}294}295296_classpath_entry_table_size = _header->_classpath_entry_table_size;297_validating_classpath_entry_table = false;298return true;299}300301302// Read the FileMapInfo information from the file.303304bool FileMapInfo::init_from_file(int fd) {305size_t sz = _header->data_size();306char* addr = _header->data();307size_t n = os::read(fd, addr, (unsigned int)sz);308if (n != sz) {309fail_continue("Unable to read the file header.");310return false;311}312if (_header->_version != current_version()) {313fail_continue("The shared archive file has the wrong version.");314return false;315}316317size_t info_size = _header->_paths_misc_info_size;318_paths_misc_info = NEW_C_HEAP_ARRAY_RETURN_NULL(char, info_size, mtClass);319if (_paths_misc_info == NULL) {320fail_continue("Unable to read the file header.");321return false;322}323n = os::read(fd, _paths_misc_info, (unsigned int)info_size);324if (n != info_size) {325fail_continue("Unable to read the shared path info header.");326FREE_C_HEAP_ARRAY(char, _paths_misc_info, mtClass);327_paths_misc_info = NULL;328return false;329}330331size_t len = lseek(fd, 0, SEEK_END);332struct FileMapInfo::FileMapHeader::space_info* si =333&_header->_space[MetaspaceShared::mc];334if (si->_file_offset >= len || len - si->_file_offset < si->_used) {335fail_continue("The shared archive file has been truncated.");336return false;337}338339_file_offset += (long)n;340return true;341}342343344// Read the FileMapInfo information from the file.345bool FileMapInfo::open_for_read() {346_full_path = Arguments::GetSharedArchivePath();347int fd = open(_full_path, O_RDONLY | O_BINARY, 0);348if (fd < 0) {349if (errno == ENOENT) {350// Not locating the shared archive is ok.351fail_continue("Specified shared archive not found.");352} else {353fail_continue("Failed to open shared archive file (%s).",354strerror(errno));355}356return false;357}358359_fd = fd;360_file_open = true;361return true;362}363364365// Write the FileMapInfo information to the file.366367void FileMapInfo::open_for_write() {368_full_path = Arguments::GetSharedArchivePath();369if (PrintSharedSpaces) {370tty->print_cr("Dumping shared data to file: ");371tty->print_cr(" %s", _full_path);372}373374#ifdef _WINDOWS // On Windows, need WRITE permission to remove the file.375chmod(_full_path, _S_IREAD | _S_IWRITE);376#endif377378// Use remove() to delete the existing file because, on Unix, this will379// allow processes that have it open continued access to the file.380remove(_full_path);381int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444);382if (fd < 0) {383fail_stop("Unable to create shared archive file %s.", _full_path);384}385_fd = fd;386_file_offset = 0;387_file_open = true;388}389390391// Write the header to the file, seek to the next allocation boundary.392393void FileMapInfo::write_header() {394int info_size = ClassLoader::get_shared_paths_misc_info_size();395396_header->_paths_misc_info_size = info_size;397398align_file_position();399size_t sz = _header->data_size();400char* addr = _header->data();401write_bytes(addr, (int)sz); // skip the C++ vtable402write_bytes(ClassLoader::get_shared_paths_misc_info(), info_size);403align_file_position();404}405406407// Dump shared spaces to file.408409void FileMapInfo::write_space(int i, Metaspace* space, bool read_only) {410align_file_position();411size_t used = space->used_bytes_slow(Metaspace::NonClassType);412size_t capacity = space->capacity_bytes_slow(Metaspace::NonClassType);413struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];414write_region(i, (char*)space->bottom(), used, capacity, read_only, false);415}416417418// Dump region to file.419420void FileMapInfo::write_region(int region, char* base, size_t size,421size_t capacity, bool read_only,422bool allow_exec) {423struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[region];424425if (_file_open) {426guarantee(si->_file_offset == _file_offset, "file offset mismatch.");427if (PrintSharedSpaces) {428tty->print_cr("Shared file region %d: 0x%6x bytes, addr " INTPTR_FORMAT429" file offset 0x%6x", region, size, base, _file_offset);430}431} else {432si->_file_offset = _file_offset;433}434si->_base = base;435si->_used = size;436si->_capacity = capacity;437si->_read_only = read_only;438si->_allow_exec = allow_exec;439si->_crc = ClassLoader::crc32(0, base, (jint)size);440write_bytes_aligned(base, (int)size);441}442443444// Dump bytes to file -- at the current file position.445446void FileMapInfo::write_bytes(const void* buffer, int nbytes) {447if (_file_open) {448int n = ::write(_fd, buffer, nbytes);449if (n != nbytes) {450// It is dangerous to leave the corrupted shared archive file around,451// close and remove the file. See bug 6372906.452close();453remove(_full_path);454fail_stop("Unable to write to shared archive file.");455}456}457_file_offset += nbytes;458}459460461// Align file position to an allocation unit boundary.462463void FileMapInfo::align_file_position() {464size_t new_file_offset = align_size_up(_file_offset,465os::vm_allocation_granularity());466if (new_file_offset != _file_offset) {467_file_offset = new_file_offset;468if (_file_open) {469// Seek one byte back from the target and write a byte to insure470// that the written file is the correct length.471_file_offset -= 1;472if (lseek(_fd, (long)_file_offset, SEEK_SET) < 0) {473fail_stop("Unable to seek.");474}475char zero = 0;476write_bytes(&zero, 1);477}478}479}480481482// Dump bytes to file -- at the current file position.483484void FileMapInfo::write_bytes_aligned(const void* buffer, int nbytes) {485align_file_position();486write_bytes(buffer, nbytes);487align_file_position();488}489490491// Close the shared archive file. This does NOT unmap mapped regions.492493void FileMapInfo::close() {494if (_file_open) {495if (::close(_fd) < 0) {496fail_stop("Unable to close the shared archive file.");497}498_file_open = false;499_fd = -1;500}501}502503504// JVM/TI RedefineClasses() support:505// Remap the shared readonly space to shared readwrite, private.506bool FileMapInfo::remap_shared_readonly_as_readwrite() {507struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[0];508if (!si->_read_only) {509// the space is already readwrite so we are done510return true;511}512size_t used = si->_used;513size_t size = align_size_up(used, os::vm_allocation_granularity());514if (!open_for_read()) {515return false;516}517char *base = os::remap_memory(_fd, _full_path, si->_file_offset,518si->_base, size, false /* !read_only */,519si->_allow_exec);520close();521if (base == NULL) {522fail_continue("Unable to remap shared readonly space (errno=%d).", errno);523return false;524}525if (base != si->_base) {526fail_continue("Unable to remap shared readonly space at required address.");527return false;528}529si->_read_only = false;530return true;531}532533// Map the whole region at once, assumed to be allocated contiguously.534ReservedSpace FileMapInfo::reserve_shared_memory() {535struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[0];536char* requested_addr = si->_base;537538size_t size = FileMapInfo::shared_spaces_size();539540// Reserve the space first, then map otherwise map will go right over some541// other reserved memory (like the code cache).542ReservedSpace rs(size, os::vm_allocation_granularity(), false, requested_addr);543if (!rs.is_reserved()) {544fail_continue("Unable to reserve shared space at required address " INTPTR_FORMAT, requested_addr);545return rs;546}547// the reserved virtual memory is for mapping class data sharing archive548MemTracker::record_virtual_memory_type((address)rs.base(), mtClassShared);549550return rs;551}552553// Memory map a region in the address space.554static const char* shared_region_name[] = { "ReadOnly", "ReadWrite", "MiscData", "MiscCode"};555556char* FileMapInfo::map_region(int i) {557struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];558size_t used = si->_used;559size_t alignment = os::vm_allocation_granularity();560size_t size = align_size_up(used, alignment);561char *requested_addr = si->_base;562563// map the contents of the CDS archive in this memory564char *base = os::map_memory(_fd, _full_path, si->_file_offset,565requested_addr, size, si->_read_only,566si->_allow_exec);567if (base == NULL || base != si->_base) {568fail_continue("Unable to map %s shared space at required address.", shared_region_name[i]);569return NULL;570}571#ifdef _WINDOWS572// This call is Windows-only because the memory_type gets recorded for the other platforms573// in method FileMapInfo::reserve_shared_memory(), which is not called on Windows.574MemTracker::record_virtual_memory_type((address)base, mtClassShared);575#endif576return base;577}578579bool FileMapInfo::verify_region_checksum(int i) {580if (!VerifySharedSpaces) {581return true;582}583const char* buf = _header->_space[i]._base;584size_t sz = _header->_space[i]._used;585int crc = ClassLoader::crc32(0, buf, (jint)sz);586if (crc != _header->_space[i]._crc) {587fail_continue("Checksum verification failed.");588return false;589}590return true;591}592593// Unmap a memory region in the address space.594595void FileMapInfo::unmap_region(int i) {596struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];597size_t used = si->_used;598size_t size = align_size_up(used, os::vm_allocation_granularity());599if (!os::unmap_memory(si->_base, size)) {600fail_stop("Unable to unmap shared space.");601}602}603604605void FileMapInfo::assert_mark(bool check) {606if (!check) {607fail_stop("Mark mismatch while restoring from shared file.");608}609}610611612FileMapInfo* FileMapInfo::_current_info = NULL;613SharedClassPathEntry* FileMapInfo::_classpath_entry_table = NULL;614int FileMapInfo::_classpath_entry_table_size = 0;615size_t FileMapInfo::_classpath_entry_size = 0x1234baad;616bool FileMapInfo::_validating_classpath_entry_table = false;617618// Open the shared archive file, read and validate the header619// information (version, boot classpath, etc.). If initialization620// fails, shared spaces are disabled and the file is closed. [See621// fail_continue.]622//623// Validation of the archive is done in two steps:624//625// [1] validate_header() - done here. This checks the header, including _paths_misc_info.626// [2] validate_classpath_entry_table - this is done later, because the table is in the RW627// region of the archive, which is not mapped yet.628bool FileMapInfo::initialize() {629assert(UseSharedSpaces, "UseSharedSpaces expected.");630631if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) {632fail_continue("Tool agent requires sharing to be disabled.");633return false;634}635636if (!open_for_read()) {637return false;638}639640init_from_file(_fd);641if (!validate_header()) {642return false;643}644645SharedReadOnlySize = _header->_space[0]._capacity;646SharedReadWriteSize = _header->_space[1]._capacity;647SharedMiscDataSize = _header->_space[2]._capacity;648SharedMiscCodeSize = _header->_space[3]._capacity;649return true;650}651652int FileMapInfo::FileMapHeader::compute_crc() {653char* header = data();654// start computing from the field after _crc655char* buf = (char*)&_crc + sizeof(int);656size_t sz = data_size() - (buf - header);657int crc = ClassLoader::crc32(0, buf, (jint)sz);658return crc;659}660661int FileMapInfo::compute_header_crc() {662return _header->compute_crc();663}664665bool FileMapInfo::FileMapHeader::validate() {666if (_magic != (int)0xf00baba2) {667FileMapInfo::fail_continue("The shared archive file has a bad magic number.");668return false;669}670if (VerifySharedSpaces && compute_crc() != _crc) {671fail_continue("Header checksum verification failed.");672return false;673}674if (_version != current_version()) {675FileMapInfo::fail_continue("The shared archive file is the wrong version.");676677return false;678}679char header_version[JVM_IDENT_MAX];680get_header_version(header_version);681if (strncmp(_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) {682if (TraceClassPaths) {683tty->print_cr("Expected: %s", header_version);684tty->print_cr("Actual: %s", _jvm_ident);685}686FileMapInfo::fail_continue("The shared archive file was created by a different"687" version or build of HotSpot");688return false;689}690if (_obj_alignment != ObjectAlignmentInBytes) {691FileMapInfo::fail_continue("The shared archive file's ObjectAlignmentInBytes of %d"692" does not equal the current ObjectAlignmentInBytes of %d.",693_obj_alignment, ObjectAlignmentInBytes);694return false;695}696697return true;698}699700bool FileMapInfo::validate_header() {701bool status = _header->validate();702703if (status) {704if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size)) {705if (!PrintSharedArchiveAndExit) {706fail_continue("shared class paths mismatch (hint: enable -XX:+TraceClassPaths to diagnose the failure)");707status = false;708}709}710}711712if (_paths_misc_info != NULL) {713FREE_C_HEAP_ARRAY(char, _paths_misc_info, mtClass);714_paths_misc_info = NULL;715}716return status;717}718719// The following method is provided to see whether a given pointer720// falls in the mapped shared space.721// Param:722// p, The given pointer723// Return:724// True if the p is within the mapped shared space, otherwise, false.725bool FileMapInfo::is_in_shared_space(const void* p) {726for (int i = 0; i < MetaspaceShared::n_regions; i++) {727if (p >= _header->_space[i]._base &&728p < _header->_space[i]._base + _header->_space[i]._used) {729return true;730}731}732733return false;734}735736void FileMapInfo::print_shared_spaces() {737gclog_or_tty->print_cr("Shared Spaces:");738for (int i = 0; i < MetaspaceShared::n_regions; i++) {739struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];740gclog_or_tty->print(" %s " INTPTR_FORMAT "-" INTPTR_FORMAT,741shared_region_name[i],742si->_base, si->_base + si->_used);743}744}745746// Unmap mapped regions of shared space.747void FileMapInfo::stop_sharing_and_unmap(const char* msg) {748FileMapInfo *map_info = FileMapInfo::current_info();749if (map_info) {750map_info->fail_continue("%s", msg);751for (int i = 0; i < MetaspaceShared::n_regions; i++) {752if (map_info->_header->_space[i]._base != NULL) {753map_info->unmap_region(i);754map_info->_header->_space[i]._base = NULL;755}756}757} else if (DumpSharedSpaces) {758fail_stop("%s", msg);759}760}761762763