Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/os/windows/vm/perfMemory_windows.cpp
32284 views
/*1* Copyright (c) 2001, 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/vmSymbols.hpp"26#include "memory/allocation.inline.hpp"27#include "memory/resourceArea.hpp"28#include "oops/oop.inline.hpp"29#include "os_windows.inline.hpp"30#include "runtime/handles.inline.hpp"31#include "runtime/perfMemory.hpp"32#include "services/memTracker.hpp"33#include "utilities/exceptions.hpp"3435#include <windows.h>36#include <sys/types.h>37#include <sys/stat.h>38#include <errno.h>39#include <lmcons.h>4041typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)(42IN PSECURITY_DESCRIPTOR pSecurityDescriptor,43IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,44IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet);4546// Standard Memory Implementation Details4748// create the PerfData memory region in standard memory.49//50static char* create_standard_memory(size_t size) {5152// allocate an aligned chuck of memory53char* mapAddress = os::reserve_memory(size);5455if (mapAddress == NULL) {56return NULL;57}5859// commit memory60if (!os::commit_memory(mapAddress, size, !ExecMem)) {61if (PrintMiscellaneous && Verbose) {62warning("Could not commit PerfData memory\n");63}64os::release_memory(mapAddress, size);65return NULL;66}6768return mapAddress;69}7071// delete the PerfData memory region72//73static void delete_standard_memory(char* addr, size_t size) {7475// there are no persistent external resources to cleanup for standard76// memory. since DestroyJavaVM does not support unloading of the JVM,77// cleanup of the memory resource is not performed. The memory will be78// reclaimed by the OS upon termination of the process.79//80return;8182}8384// save the specified memory region to the given file85//86static void save_memory_to_file(char* addr, size_t size) {8788const char* destfile = PerfMemory::get_perfdata_file_path();89assert(destfile[0] != '\0', "invalid Perfdata file path");9091int fd = ::_open(destfile, _O_BINARY|_O_CREAT|_O_WRONLY|_O_TRUNC,92_S_IREAD|_S_IWRITE);9394if (fd == OS_ERR) {95if (PrintMiscellaneous && Verbose) {96warning("Could not create Perfdata save file: %s: %s\n",97destfile, strerror(errno));98}99} else {100for (size_t remaining = size; remaining > 0;) {101102int nbytes = ::_write(fd, addr, (unsigned int)remaining);103if (nbytes == OS_ERR) {104if (PrintMiscellaneous && Verbose) {105warning("Could not write Perfdata save file: %s: %s\n",106destfile, strerror(errno));107}108break;109}110111remaining -= (size_t)nbytes;112addr += nbytes;113}114115int result = ::_close(fd);116if (PrintMiscellaneous && Verbose) {117if (result == OS_ERR) {118warning("Could not close %s: %s\n", destfile, strerror(errno));119}120}121}122123FREE_C_HEAP_ARRAY(char, destfile, mtInternal);124}125126// Shared Memory Implementation Details127128// Note: the win32 shared memory implementation uses two objects to represent129// the shared memory: a windows kernel based file mapping object and a backing130// store file. On windows, the name space for shared memory is a kernel131// based name space that is disjoint from other win32 name spaces. Since Java132// is unaware of this name space, a parallel file system based name space is133// maintained, which provides a common file system based shared memory name134// space across the supported platforms and one that Java apps can deal with135// through simple file apis.136//137// For performance and resource cleanup reasons, it is recommended that the138// user specific directory and the backing store file be stored in either a139// RAM based file system or a local disk based file system. Network based140// file systems are not recommended for performance reasons. In addition,141// use of SMB network based file systems may result in unsuccesful cleanup142// of the disk based resource on exit of the VM. The Windows TMP and TEMP143// environement variables, as used by the GetTempPath() Win32 API (see144// os::get_temp_directory() in os_win32.cpp), control the location of the145// user specific directory and the shared memory backing store file.146147static HANDLE sharedmem_fileMapHandle = NULL;148static HANDLE sharedmem_fileHandle = INVALID_HANDLE_VALUE;149static char* sharedmem_fileName = NULL;150151// return the user specific temporary directory name.152//153// the caller is expected to free the allocated memory.154//155static char* get_user_tmp_dir(const char* user) {156157const char* tmpdir = os::get_temp_directory();158const char* perfdir = PERFDATA_NAME;159size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3;160char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);161162// construct the path name to user specific tmp directory163_snprintf(dirname, nbytes, "%s\\%s_%s", tmpdir, perfdir, user);164165return dirname;166}167168// convert the given file name into a process id. if the file169// does not meet the file naming constraints, return 0.170//171static int filename_to_pid(const char* filename) {172173// a filename that doesn't begin with a digit is not a174// candidate for conversion.175//176if (!isdigit(*filename)) {177return 0;178}179180// check if file name can be converted to an integer without181// any leftover characters.182//183char* remainder = NULL;184errno = 0;185int pid = (int)strtol(filename, &remainder, 10);186187if (errno != 0) {188return 0;189}190191// check for left over characters. If any, then the filename is192// not a candidate for conversion.193//194if (remainder != NULL && *remainder != '\0') {195return 0;196}197198// successful conversion, return the pid199return pid;200}201202// check if the given path is considered a secure directory for203// the backing store files. Returns true if the directory exists204// and is considered a secure location. Returns false if the path205// is a symbolic link or if an error occurred.206//207static bool is_directory_secure(const char* path) {208209DWORD fa;210211fa = GetFileAttributes(path);212if (fa == 0xFFFFFFFF) {213DWORD lasterror = GetLastError();214if (lasterror == ERROR_FILE_NOT_FOUND) {215return false;216}217else {218// unexpected error, declare the path insecure219if (PrintMiscellaneous && Verbose) {220warning("could not get attributes for file %s: ",221" lasterror = %d\n", path, lasterror);222}223return false;224}225}226227if (fa & FILE_ATTRIBUTE_REPARSE_POINT) {228// we don't accept any redirection for the user specific directory229// so declare the path insecure. This may be too conservative,230// as some types of reparse points might be acceptable, but it231// is probably more secure to avoid these conditions.232//233if (PrintMiscellaneous && Verbose) {234warning("%s is a reparse point\n", path);235}236return false;237}238239if (fa & FILE_ATTRIBUTE_DIRECTORY) {240// this is the expected case. Since windows supports symbolic241// links to directories only, not to files, there is no need242// to check for open write permissions on the directory. If the243// directory has open write permissions, any files deposited that244// are not expected will be removed by the cleanup code.245//246return true;247}248else {249// this is either a regular file or some other type of file,250// any of which are unexpected and therefore insecure.251//252if (PrintMiscellaneous && Verbose) {253warning("%s is not a directory, file attributes = "254INTPTR_FORMAT "\n", path, fa);255}256return false;257}258}259260// return the user name for the owner of this process261//262// the caller is expected to free the allocated memory.263//264static char* get_user_name() {265266/* get the user name. This code is adapted from code found in267* the jdk in src/windows/native/java/lang/java_props_md.c268* java_props_md.c 1.29 02/02/06. According to the original269* source, the call to GetUserName is avoided because of a resulting270* increase in footprint of 100K.271*/272char* user = getenv("USERNAME");273char buf[UNLEN+1];274DWORD buflen = sizeof(buf);275if (user == NULL || strlen(user) == 0) {276if (GetUserName(buf, &buflen)) {277user = buf;278}279else {280return NULL;281}282}283284char* user_name = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal);285strcpy(user_name, user);286287return user_name;288}289290// return the name of the user that owns the process identified by vmid.291//292// This method uses a slow directory search algorithm to find the backing293// store file for the specified vmid and returns the user name, as determined294// by the user name suffix of the hsperfdata_<username> directory name.295//296// the caller is expected to free the allocated memory.297//298static char* get_user_name_slow(int vmid) {299300// directory search301char* latest_user = NULL;302time_t latest_ctime = 0;303304const char* tmpdirname = os::get_temp_directory();305306DIR* tmpdirp = os::opendir(tmpdirname);307308if (tmpdirp == NULL) {309return NULL;310}311312// for each entry in the directory that matches the pattern hsperfdata_*,313// open the directory and check if the file for the given vmid exists.314// The file with the expected name and the latest creation date is used315// to determine the user name for the process id.316//317struct dirent* dentry;318errno = 0;319while ((dentry = os::readdir(tmpdirp)) != NULL) {320321// check if the directory entry is a hsperfdata file322if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {323continue;324}325326char* usrdir_name = NEW_C_HEAP_ARRAY(char,327strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal);328strcpy(usrdir_name, tmpdirname);329strcat(usrdir_name, "\\");330strcat(usrdir_name, dentry->d_name);331332DIR* subdirp = os::opendir(usrdir_name);333334if (subdirp == NULL) {335FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);336continue;337}338339// Since we don't create the backing store files in directories340// pointed to by symbolic links, we also don't follow them when341// looking for the files. We check for a symbolic link after the342// call to opendir in order to eliminate a small window where the343// symlink can be exploited.344//345if (!is_directory_secure(usrdir_name)) {346FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);347os::closedir(subdirp);348continue;349}350351struct dirent* udentry;352errno = 0;353while ((udentry = os::readdir(subdirp)) != NULL) {354355if (filename_to_pid(udentry->d_name) == vmid) {356struct stat statbuf;357358char* filename = NEW_C_HEAP_ARRAY(char,359strlen(usrdir_name) + strlen(udentry->d_name) + 2, mtInternal);360361strcpy(filename, usrdir_name);362strcat(filename, "\\");363strcat(filename, udentry->d_name);364365if (::stat(filename, &statbuf) == OS_ERR) {366FREE_C_HEAP_ARRAY(char, filename, mtInternal);367continue;368}369370// skip over files that are not regular files.371if ((statbuf.st_mode & S_IFMT) != S_IFREG) {372FREE_C_HEAP_ARRAY(char, filename, mtInternal);373continue;374}375376// If we found a matching file with a newer creation time, then377// save the user name. The newer creation time indicates that378// we found a newer incarnation of the process associated with379// vmid. Due to the way that Windows recycles pids and the fact380// that we can't delete the file from the file system namespace381// until last close, it is possible for there to be more than382// one hsperfdata file with a name matching vmid (diff users).383//384// We no longer ignore hsperfdata files where (st_size == 0).385// In this function, all we're trying to do is determine the386// name of the user that owns the process associated with vmid387// so the size doesn't matter. Very rarely, we have observed388// hsperfdata files where (st_size == 0) and the st_size field389// later becomes the expected value.390//391if (statbuf.st_ctime > latest_ctime) {392char* user = strchr(dentry->d_name, '_') + 1;393394if (latest_user != NULL) FREE_C_HEAP_ARRAY(char, latest_user, mtInternal);395latest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal);396397strcpy(latest_user, user);398latest_ctime = statbuf.st_ctime;399}400401FREE_C_HEAP_ARRAY(char, filename, mtInternal);402}403}404os::closedir(subdirp);405FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);406}407os::closedir(tmpdirp);408409return(latest_user);410}411412// return the name of the user that owns the process identified by vmid.413//414// note: this method should only be used via the Perf native methods.415// There are various costs to this method and limiting its use to the416// Perf native methods limits the impact to monitoring applications only.417//418static char* get_user_name(int vmid) {419420// A fast implementation is not provided at this time. It's possible421// to provide a fast process id to user name mapping function using422// the win32 apis, but the default ACL for the process object only423// allows processes with the same owner SID to acquire the process424// handle (via OpenProcess(PROCESS_QUERY_INFORMATION)). It's possible425// to have the JVM change the ACL for the process object to allow arbitrary426// users to access the process handle and the process security token.427// The security ramifications need to be studied before providing this428// mechanism.429//430return get_user_name_slow(vmid);431}432433// return the name of the shared memory file mapping object for the434// named shared memory region for the given user name and vmid.435//436// The file mapping object's name is not the file name. It is a name437// in a separate name space.438//439// the caller is expected to free the allocated memory.440//441static char *get_sharedmem_objectname(const char* user, int vmid) {442443// construct file mapping object's name, add 3 for two '_' and a444// null terminator.445int nbytes = (int)strlen(PERFDATA_NAME) + (int)strlen(user) + 3;446447// the id is converted to an unsigned value here because win32 allows448// negative process ids. However, OpenFileMapping API complains449// about a name containing a '-' characters.450//451nbytes += UINT_CHARS;452char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);453_snprintf(name, nbytes, "%s_%s_%u", PERFDATA_NAME, user, vmid);454455return name;456}457458// return the file name of the backing store file for the named459// shared memory region for the given user name and vmid.460//461// the caller is expected to free the allocated memory.462//463static char* get_sharedmem_filename(const char* dirname, int vmid) {464465// add 2 for the file separator and a null terminator.466size_t nbytes = strlen(dirname) + UINT_CHARS + 2;467468char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);469_snprintf(name, nbytes, "%s\\%d", dirname, vmid);470471return name;472}473474// remove file475//476// this method removes the file with the given file name.477//478// Note: if the indicated file is on an SMB network file system, this479// method may be unsuccessful in removing the file.480//481static void remove_file(const char* dirname, const char* filename) {482483size_t nbytes = strlen(dirname) + strlen(filename) + 2;484char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);485486strcpy(path, dirname);487strcat(path, "\\");488strcat(path, filename);489490if (::unlink(path) == OS_ERR) {491if (PrintMiscellaneous && Verbose) {492if (errno != ENOENT) {493warning("Could not unlink shared memory backing"494" store file %s : %s\n", path, strerror(errno));495}496}497}498499FREE_C_HEAP_ARRAY(char, path, mtInternal);500}501502// returns true if the process represented by pid is alive, otherwise503// returns false. the validity of the result is only accurate if the504// target process is owned by the same principal that owns this process.505// this method should not be used if to test the status of an otherwise506// arbitrary process unless it is know that this process has the appropriate507// privileges to guarantee a result valid.508//509static bool is_alive(int pid) {510511HANDLE ph = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);512if (ph == NULL) {513// the process does not exist.514if (PrintMiscellaneous && Verbose) {515DWORD lastError = GetLastError();516if (lastError != ERROR_INVALID_PARAMETER) {517warning("OpenProcess failed: %d\n", GetLastError());518}519}520return false;521}522523DWORD exit_status;524if (!GetExitCodeProcess(ph, &exit_status)) {525if (PrintMiscellaneous && Verbose) {526warning("GetExitCodeProcess failed: %d\n", GetLastError());527}528CloseHandle(ph);529return false;530}531532CloseHandle(ph);533return (exit_status == STILL_ACTIVE) ? true : false;534}535536// check if the file system is considered secure for the backing store files537//538static bool is_filesystem_secure(const char* path) {539540char root_path[MAX_PATH];541char fs_type[MAX_PATH];542543if (PerfBypassFileSystemCheck) {544if (PrintMiscellaneous && Verbose) {545warning("bypassing file system criteria checks for %s\n", path);546}547return true;548}549550char* first_colon = strchr((char *)path, ':');551if (first_colon == NULL) {552if (PrintMiscellaneous && Verbose) {553warning("expected device specifier in path: %s\n", path);554}555return false;556}557558size_t len = (size_t)(first_colon - path);559assert(len + 2 <= MAX_PATH, "unexpected device specifier length");560strncpy(root_path, path, len + 1);561root_path[len + 1] = '\\';562root_path[len + 2] = '\0';563564// check that we have something like "C:\" or "AA:\"565assert(strlen(root_path) >= 3, "device specifier too short");566assert(strchr(root_path, ':') != NULL, "bad device specifier format");567assert(strchr(root_path, '\\') != NULL, "bad device specifier format");568569DWORD maxpath;570DWORD flags;571572if (!GetVolumeInformation(root_path, NULL, 0, NULL, &maxpath,573&flags, fs_type, MAX_PATH)) {574// we can't get information about the volume, so assume unsafe.575if (PrintMiscellaneous && Verbose) {576warning("could not get device information for %s: "577" path = %s: lasterror = %d\n",578root_path, path, GetLastError());579}580return false;581}582583if ((flags & FS_PERSISTENT_ACLS) == 0) {584// file system doesn't support ACLs, declare file system unsafe585if (PrintMiscellaneous && Verbose) {586warning("file system type %s on device %s does not support"587" ACLs\n", fs_type, root_path);588}589return false;590}591592if ((flags & FS_VOL_IS_COMPRESSED) != 0) {593// file system is compressed, declare file system unsafe594if (PrintMiscellaneous && Verbose) {595warning("file system type %s on device %s is compressed\n",596fs_type, root_path);597}598return false;599}600601return true;602}603604// cleanup stale shared memory resources605//606// This method attempts to remove all stale shared memory files in607// the named user temporary directory. It scans the named directory608// for files matching the pattern ^$[0-9]*$. For each file found, the609// process id is extracted from the file name and a test is run to610// determine if the process is alive. If the process is not alive,611// any stale file resources are removed.612//613static void cleanup_sharedmem_resources(const char* dirname) {614615// open the user temp directory616DIR* dirp = os::opendir(dirname);617618if (dirp == NULL) {619// directory doesn't exist, so there is nothing to cleanup620return;621}622623if (!is_directory_secure(dirname)) {624// the directory is not secure, don't attempt any cleanup625return;626}627628// for each entry in the directory that matches the expected file629// name pattern, determine if the file resources are stale and if630// so, remove the file resources. Note, instrumented HotSpot processes631// for this user may start and/or terminate during this search and632// remove or create new files in this directory. The behavior of this633// loop under these conditions is dependent upon the implementation of634// opendir/readdir.635//636struct dirent* entry;637errno = 0;638while ((entry = os::readdir(dirp)) != NULL) {639640int pid = filename_to_pid(entry->d_name);641642if (pid == 0) {643644if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {645646// attempt to remove all unexpected files, except "." and ".."647remove_file(dirname, entry->d_name);648}649650errno = 0;651continue;652}653654// we now have a file name that converts to a valid integer655// that could represent a process id . if this process id656// matches the current process id or the process is not running,657// then remove the stale file resources.658//659// process liveness is detected by checking the exit status660// of the process. if the process id is valid and the exit status661// indicates that it is still running, the file file resources662// are not removed. If the process id is invalid, or if we don't663// have permissions to check the process status, or if the process664// id is valid and the process has terminated, the the file resources665// are assumed to be stale and are removed.666//667if (pid == os::current_process_id() || !is_alive(pid)) {668669// we can only remove the file resources. Any mapped views670// of the file can only be unmapped by the processes that671// opened those views and the file mapping object will not672// get removed until all views are unmapped.673//674remove_file(dirname, entry->d_name);675}676errno = 0;677}678os::closedir(dirp);679}680681// create a file mapping object with the requested name, and size682// from the file represented by the given Handle object683//684static HANDLE create_file_mapping(const char* name, HANDLE fh, LPSECURITY_ATTRIBUTES fsa, size_t size) {685686DWORD lowSize = (DWORD)size;687DWORD highSize = 0;688HANDLE fmh = NULL;689690// Create a file mapping object with the given name. This function691// will grow the file to the specified size.692//693fmh = CreateFileMapping(694fh, /* HANDLE file handle for backing store */695fsa, /* LPSECURITY_ATTRIBUTES Not inheritable */696PAGE_READWRITE, /* DWORD protections */697highSize, /* DWORD High word of max size */698lowSize, /* DWORD Low word of max size */699name); /* LPCTSTR name for object */700701if (fmh == NULL) {702if (PrintMiscellaneous && Verbose) {703warning("CreateFileMapping failed, lasterror = %d\n", GetLastError());704}705return NULL;706}707708if (GetLastError() == ERROR_ALREADY_EXISTS) {709710// a stale file mapping object was encountered. This object may be711// owned by this or some other user and cannot be removed until712// the other processes either exit or close their mapping objects713// and/or mapped views of this mapping object.714//715if (PrintMiscellaneous && Verbose) {716warning("file mapping already exists, lasterror = %d\n", GetLastError());717}718719CloseHandle(fmh);720return NULL;721}722723return fmh;724}725726727// method to free the given security descriptor and the contained728// access control list.729//730static void free_security_desc(PSECURITY_DESCRIPTOR pSD) {731732BOOL success, exists, isdefault;733PACL pACL;734735if (pSD != NULL) {736737// get the access control list from the security descriptor738success = GetSecurityDescriptorDacl(pSD, &exists, &pACL, &isdefault);739740// if an ACL existed and it was not a default acl, then it must741// be an ACL we enlisted. free the resources.742//743if (success && exists && pACL != NULL && !isdefault) {744FREE_C_HEAP_ARRAY(char, pACL, mtInternal);745}746747// free the security descriptor748FREE_C_HEAP_ARRAY(char, pSD, mtInternal);749}750}751752// method to free up a security attributes structure and any753// contained security descriptors and ACL754//755static void free_security_attr(LPSECURITY_ATTRIBUTES lpSA) {756757if (lpSA != NULL) {758// free the contained security descriptor and the ACL759free_security_desc(lpSA->lpSecurityDescriptor);760lpSA->lpSecurityDescriptor = NULL;761762// free the security attributes structure763FREE_C_HEAP_ARRAY(char, lpSA, mtInternal);764}765}766767// get the user SID for the process indicated by the process handle768//769static PSID get_user_sid(HANDLE hProcess) {770771HANDLE hAccessToken;772PTOKEN_USER token_buf = NULL;773DWORD rsize = 0;774775if (hProcess == NULL) {776return NULL;777}778779// get the process token780if (!OpenProcessToken(hProcess, TOKEN_READ, &hAccessToken)) {781if (PrintMiscellaneous && Verbose) {782warning("OpenProcessToken failure: lasterror = %d \n", GetLastError());783}784return NULL;785}786787// determine the size of the token structured needed to retrieve788// the user token information from the access token.789//790if (!GetTokenInformation(hAccessToken, TokenUser, NULL, rsize, &rsize)) {791DWORD lasterror = GetLastError();792if (lasterror != ERROR_INSUFFICIENT_BUFFER) {793if (PrintMiscellaneous && Verbose) {794warning("GetTokenInformation failure: lasterror = %d,"795" rsize = %d\n", lasterror, rsize);796}797CloseHandle(hAccessToken);798return NULL;799}800}801802token_buf = (PTOKEN_USER) NEW_C_HEAP_ARRAY(char, rsize, mtInternal);803804// get the user token information805if (!GetTokenInformation(hAccessToken, TokenUser, token_buf, rsize, &rsize)) {806if (PrintMiscellaneous && Verbose) {807warning("GetTokenInformation failure: lasterror = %d,"808" rsize = %d\n", GetLastError(), rsize);809}810FREE_C_HEAP_ARRAY(char, token_buf, mtInternal);811CloseHandle(hAccessToken);812return NULL;813}814815DWORD nbytes = GetLengthSid(token_buf->User.Sid);816PSID pSID = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);817818if (!CopySid(nbytes, pSID, token_buf->User.Sid)) {819if (PrintMiscellaneous && Verbose) {820warning("GetTokenInformation failure: lasterror = %d,"821" rsize = %d\n", GetLastError(), rsize);822}823FREE_C_HEAP_ARRAY(char, token_buf, mtInternal);824FREE_C_HEAP_ARRAY(char, pSID, mtInternal);825CloseHandle(hAccessToken);826return NULL;827}828829// close the access token.830CloseHandle(hAccessToken);831FREE_C_HEAP_ARRAY(char, token_buf, mtInternal);832833return pSID;834}835836// structure used to consolidate access control entry information837//838typedef struct ace_data {839PSID pSid; // SID of the ACE840DWORD mask; // mask for the ACE841} ace_data_t;842843844// method to add an allow access control entry with the access rights845// indicated in mask for the principal indicated in SID to the given846// security descriptor. Much of the DACL handling was adapted from847// the example provided here:848// http://support.microsoft.com/kb/102102/EN-US/849//850851static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD,852ace_data_t aces[], int ace_count) {853PACL newACL = NULL;854PACL oldACL = NULL;855856if (pSD == NULL) {857return false;858}859860BOOL exists, isdefault;861862// retrieve any existing access control list.863if (!GetSecurityDescriptorDacl(pSD, &exists, &oldACL, &isdefault)) {864if (PrintMiscellaneous && Verbose) {865warning("GetSecurityDescriptor failure: lasterror = %d \n",866GetLastError());867}868return false;869}870871// get the size of the DACL872ACL_SIZE_INFORMATION aclinfo;873874// GetSecurityDescriptorDacl may return true value for exists (lpbDaclPresent)875// while oldACL is NULL for some case.876if (oldACL == NULL) {877exists = FALSE;878}879880if (exists) {881if (!GetAclInformation(oldACL, &aclinfo,882sizeof(ACL_SIZE_INFORMATION),883AclSizeInformation)) {884if (PrintMiscellaneous && Verbose) {885warning("GetAclInformation failure: lasterror = %d \n", GetLastError());886return false;887}888}889} else {890aclinfo.AceCount = 0; // assume NULL DACL891aclinfo.AclBytesFree = 0;892aclinfo.AclBytesInUse = sizeof(ACL);893}894895// compute the size needed for the new ACL896// initial size of ACL is sum of the following:897// * size of ACL structure.898// * size of each ACE structure that ACL is to contain minus the sid899// sidStart member (DWORD) of the ACE.900// * length of the SID that each ACE is to contain.901DWORD newACLsize = aclinfo.AclBytesInUse +902(sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) * ace_count;903for (int i = 0; i < ace_count; i++) {904assert(aces[i].pSid != 0, "pSid should not be 0");905newACLsize += GetLengthSid(aces[i].pSid);906}907908// create the new ACL909newACL = (PACL) NEW_C_HEAP_ARRAY(char, newACLsize, mtInternal);910911if (!InitializeAcl(newACL, newACLsize, ACL_REVISION)) {912if (PrintMiscellaneous && Verbose) {913warning("InitializeAcl failure: lasterror = %d \n", GetLastError());914}915FREE_C_HEAP_ARRAY(char, newACL, mtInternal);916return false;917}918919unsigned int ace_index = 0;920// copy any existing ACEs from the old ACL (if any) to the new ACL.921if (aclinfo.AceCount != 0) {922while (ace_index < aclinfo.AceCount) {923LPVOID ace;924if (!GetAce(oldACL, ace_index, &ace)) {925if (PrintMiscellaneous && Verbose) {926warning("InitializeAcl failure: lasterror = %d \n", GetLastError());927}928FREE_C_HEAP_ARRAY(char, newACL, mtInternal);929return false;930}931if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceFlags && INHERITED_ACE) {932// this is an inherited, allowed ACE; break from loop so we can933// add the new access allowed, non-inherited ACE in the correct934// position, immediately following all non-inherited ACEs.935break;936}937938// determine if the SID of this ACE matches any of the SIDs939// for which we plan to set ACEs.940int matches = 0;941for (int i = 0; i < ace_count; i++) {942if (EqualSid(aces[i].pSid, &(((ACCESS_ALLOWED_ACE *)ace)->SidStart))) {943matches++;944break;945}946}947948// if there are no SID matches, then add this existing ACE to the new ACL949if (matches == 0) {950if (!AddAce(newACL, ACL_REVISION, MAXDWORD, ace,951((PACE_HEADER)ace)->AceSize)) {952if (PrintMiscellaneous && Verbose) {953warning("AddAce failure: lasterror = %d \n", GetLastError());954}955FREE_C_HEAP_ARRAY(char, newACL, mtInternal);956return false;957}958}959ace_index++;960}961}962963// add the passed-in access control entries to the new ACL964for (int i = 0; i < ace_count; i++) {965if (!AddAccessAllowedAce(newACL, ACL_REVISION,966aces[i].mask, aces[i].pSid)) {967if (PrintMiscellaneous && Verbose) {968warning("AddAccessAllowedAce failure: lasterror = %d \n",969GetLastError());970}971FREE_C_HEAP_ARRAY(char, newACL, mtInternal);972return false;973}974}975976// now copy the rest of the inherited ACEs from the old ACL977if (aclinfo.AceCount != 0) {978// picking up at ace_index, where we left off in the979// previous ace_index loop980while (ace_index < aclinfo.AceCount) {981LPVOID ace;982if (!GetAce(oldACL, ace_index, &ace)) {983if (PrintMiscellaneous && Verbose) {984warning("InitializeAcl failure: lasterror = %d \n", GetLastError());985}986FREE_C_HEAP_ARRAY(char, newACL, mtInternal);987return false;988}989if (!AddAce(newACL, ACL_REVISION, MAXDWORD, ace,990((PACE_HEADER)ace)->AceSize)) {991if (PrintMiscellaneous && Verbose) {992warning("AddAce failure: lasterror = %d \n", GetLastError());993}994FREE_C_HEAP_ARRAY(char, newACL, mtInternal);995return false;996}997ace_index++;998}999}10001001// add the new ACL to the security descriptor.1002if (!SetSecurityDescriptorDacl(pSD, TRUE, newACL, FALSE)) {1003if (PrintMiscellaneous && Verbose) {1004warning("SetSecurityDescriptorDacl failure:"1005" lasterror = %d \n", GetLastError());1006}1007FREE_C_HEAP_ARRAY(char, newACL, mtInternal);1008return false;1009}10101011// if running on windows 2000 or later, set the automatic inheritance1012// control flags.1013SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl;1014_SetSecurityDescriptorControl = (SetSecurityDescriptorControlFnPtr)1015GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")),1016"SetSecurityDescriptorControl");10171018if (_SetSecurityDescriptorControl != NULL) {1019// We do not want to further propagate inherited DACLs, so making them1020// protected prevents that.1021if (!_SetSecurityDescriptorControl(pSD, SE_DACL_PROTECTED,1022SE_DACL_PROTECTED)) {1023if (PrintMiscellaneous && Verbose) {1024warning("SetSecurityDescriptorControl failure:"1025" lasterror = %d \n", GetLastError());1026}1027FREE_C_HEAP_ARRAY(char, newACL, mtInternal);1028return false;1029}1030}1031// Note, the security descriptor maintains a reference to the newACL, not1032// a copy of it. Therefore, the newACL is not freed here. It is freed when1033// the security descriptor containing its reference is freed.1034//1035return true;1036}10371038// method to create a security attributes structure, which contains a1039// security descriptor and an access control list comprised of 0 or more1040// access control entries. The method take an array of ace_data structures1041// that indicate the ACE to be added to the security descriptor.1042//1043// the caller must free the resources associated with the security1044// attributes structure created by this method by calling the1045// free_security_attr() method.1046//1047static LPSECURITY_ATTRIBUTES make_security_attr(ace_data_t aces[], int count) {10481049// allocate space for a security descriptor1050PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)1051NEW_C_HEAP_ARRAY(char, SECURITY_DESCRIPTOR_MIN_LENGTH, mtInternal);10521053// initialize the security descriptor1054if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {1055if (PrintMiscellaneous && Verbose) {1056warning("InitializeSecurityDescriptor failure: "1057"lasterror = %d \n", GetLastError());1058}1059free_security_desc(pSD);1060return NULL;1061}10621063// add the access control entries1064if (!add_allow_aces(pSD, aces, count)) {1065free_security_desc(pSD);1066return NULL;1067}10681069// allocate and initialize the security attributes structure and1070// return it to the caller.1071//1072LPSECURITY_ATTRIBUTES lpSA = (LPSECURITY_ATTRIBUTES)1073NEW_C_HEAP_ARRAY(char, sizeof(SECURITY_ATTRIBUTES), mtInternal);1074lpSA->nLength = sizeof(SECURITY_ATTRIBUTES);1075lpSA->lpSecurityDescriptor = pSD;1076lpSA->bInheritHandle = FALSE;10771078return(lpSA);1079}10801081// method to create a security attributes structure with a restrictive1082// access control list that creates a set access rights for the user/owner1083// of the securable object and a separate set access rights for everyone else.1084// also provides for full access rights for the administrator group.1085//1086// the caller must free the resources associated with the security1087// attributes structure created by this method by calling the1088// free_security_attr() method.1089//10901091static LPSECURITY_ATTRIBUTES make_user_everybody_admin_security_attr(1092DWORD umask, DWORD emask, DWORD amask) {10931094ace_data_t aces[3];10951096// initialize the user ace data1097aces[0].pSid = get_user_sid(GetCurrentProcess());1098aces[0].mask = umask;10991100if (aces[0].pSid == 0)1101return NULL;11021103// get the well known SID for BUILTIN\Administrators1104PSID administratorsSid = NULL;1105SID_IDENTIFIER_AUTHORITY SIDAuthAdministrators = SECURITY_NT_AUTHORITY;11061107if (!AllocateAndInitializeSid( &SIDAuthAdministrators, 2,1108SECURITY_BUILTIN_DOMAIN_RID,1109DOMAIN_ALIAS_RID_ADMINS,11100, 0, 0, 0, 0, 0, &administratorsSid)) {11111112if (PrintMiscellaneous && Verbose) {1113warning("AllocateAndInitializeSid failure: "1114"lasterror = %d \n", GetLastError());1115}1116return NULL;1117}11181119// initialize the ace data for administrator group1120aces[1].pSid = administratorsSid;1121aces[1].mask = amask;11221123// get the well known SID for the universal Everybody1124PSID everybodySid = NULL;1125SID_IDENTIFIER_AUTHORITY SIDAuthEverybody = SECURITY_WORLD_SID_AUTHORITY;11261127if (!AllocateAndInitializeSid( &SIDAuthEverybody, 1, SECURITY_WORLD_RID,11280, 0, 0, 0, 0, 0, 0, &everybodySid)) {11291130if (PrintMiscellaneous && Verbose) {1131warning("AllocateAndInitializeSid failure: "1132"lasterror = %d \n", GetLastError());1133}1134return NULL;1135}11361137// initialize the ace data for everybody else.1138aces[2].pSid = everybodySid;1139aces[2].mask = emask;11401141// create a security attributes structure with access control1142// entries as initialized above.1143LPSECURITY_ATTRIBUTES lpSA = make_security_attr(aces, 3);1144FREE_C_HEAP_ARRAY(char, aces[0].pSid, mtInternal);1145FreeSid(everybodySid);1146FreeSid(administratorsSid);1147return(lpSA);1148}114911501151// method to create the security attributes structure for restricting1152// access to the user temporary directory.1153//1154// the caller must free the resources associated with the security1155// attributes structure created by this method by calling the1156// free_security_attr() method.1157//1158static LPSECURITY_ATTRIBUTES make_tmpdir_security_attr() {11591160// create full access rights for the user/owner of the directory1161// and read-only access rights for everybody else. This is1162// effectively equivalent to UNIX 755 permissions on a directory.1163//1164DWORD umask = STANDARD_RIGHTS_REQUIRED | FILE_ALL_ACCESS;1165DWORD emask = GENERIC_READ | FILE_LIST_DIRECTORY | FILE_TRAVERSE;1166DWORD amask = STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS;11671168return make_user_everybody_admin_security_attr(umask, emask, amask);1169}11701171// method to create the security attributes structure for restricting1172// access to the shared memory backing store file.1173//1174// the caller must free the resources associated with the security1175// attributes structure created by this method by calling the1176// free_security_attr() method.1177//1178static LPSECURITY_ATTRIBUTES make_file_security_attr() {11791180// create extensive access rights for the user/owner of the file1181// and attribute read-only access rights for everybody else. This1182// is effectively equivalent to UNIX 600 permissions on a file.1183//1184DWORD umask = STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS;1185DWORD emask = STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES |1186FILE_READ_EA | FILE_LIST_DIRECTORY | FILE_TRAVERSE;1187DWORD amask = STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS;11881189return make_user_everybody_admin_security_attr(umask, emask, amask);1190}11911192// method to create the security attributes structure for restricting1193// access to the name shared memory file mapping object.1194//1195// the caller must free the resources associated with the security1196// attributes structure created by this method by calling the1197// free_security_attr() method.1198//1199static LPSECURITY_ATTRIBUTES make_smo_security_attr() {12001201// create extensive access rights for the user/owner of the shared1202// memory object and attribute read-only access rights for everybody1203// else. This is effectively equivalent to UNIX 600 permissions on1204// on the shared memory object.1205//1206DWORD umask = STANDARD_RIGHTS_REQUIRED | FILE_MAP_ALL_ACCESS;1207DWORD emask = STANDARD_RIGHTS_READ; // attributes only1208DWORD amask = STANDARD_RIGHTS_ALL | FILE_MAP_ALL_ACCESS;12091210return make_user_everybody_admin_security_attr(umask, emask, amask);1211}12121213// make the user specific temporary directory1214//1215static bool make_user_tmp_dir(const char* dirname) {121612171218LPSECURITY_ATTRIBUTES pDirSA = make_tmpdir_security_attr();1219if (pDirSA == NULL) {1220return false;1221}122212231224// create the directory with the given security attributes1225if (!CreateDirectory(dirname, pDirSA)) {1226DWORD lasterror = GetLastError();1227if (lasterror == ERROR_ALREADY_EXISTS) {1228// The directory already exists and was probably created by another1229// JVM instance. However, this could also be the result of a1230// deliberate symlink. Verify that the existing directory is safe.1231//1232if (!is_directory_secure(dirname)) {1233// directory is not secure1234if (PrintMiscellaneous && Verbose) {1235warning("%s directory is insecure\n", dirname);1236}1237return false;1238}1239// The administrator should be able to delete this directory.1240// But the directory created by previous version of JVM may not1241// have permission for administrators to delete this directory.1242// So add full permission to the administrator. Also setting new1243// DACLs might fix the corrupted the DACLs.1244SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;1245if (!SetFileSecurity(dirname, secInfo, pDirSA->lpSecurityDescriptor)) {1246if (PrintMiscellaneous && Verbose) {1247lasterror = GetLastError();1248warning("SetFileSecurity failed for %s directory. lasterror %d \n",1249dirname, lasterror);1250}1251}1252}1253else {1254if (PrintMiscellaneous && Verbose) {1255warning("CreateDirectory failed: %d\n", GetLastError());1256}1257return false;1258}1259}12601261// free the security attributes structure1262free_security_attr(pDirSA);12631264return true;1265}12661267// create the shared memory resources1268//1269// This function creates the shared memory resources. This includes1270// the backing store file and the file mapping shared memory object.1271//1272static HANDLE create_sharedmem_resources(const char* dirname, const char* filename, const char* objectname, size_t size) {12731274HANDLE fh = INVALID_HANDLE_VALUE;1275HANDLE fmh = NULL;127612771278// create the security attributes for the backing store file1279LPSECURITY_ATTRIBUTES lpFileSA = make_file_security_attr();1280if (lpFileSA == NULL) {1281return NULL;1282}12831284// create the security attributes for the shared memory object1285LPSECURITY_ATTRIBUTES lpSmoSA = make_smo_security_attr();1286if (lpSmoSA == NULL) {1287free_security_attr(lpFileSA);1288return NULL;1289}12901291// create the user temporary directory1292if (!make_user_tmp_dir(dirname)) {1293// could not make/find the directory or the found directory1294// was not secure1295return NULL;1296}12971298// Create the file - the FILE_FLAG_DELETE_ON_CLOSE flag allows the1299// file to be deleted by the last process that closes its handle to1300// the file. This is important as the apis do not allow a terminating1301// JVM being monitored by another process to remove the file name.1302//1303// the FILE_SHARE_DELETE share mode is valid only in winnt1304//1305fh = CreateFile(1306filename, /* LPCTSTR file name */13071308GENERIC_READ|GENERIC_WRITE, /* DWORD desired access */13091310(os::win32::is_nt() ? FILE_SHARE_DELETE : 0)|1311FILE_SHARE_READ, /* DWORD share mode, future READONLY1312* open operations allowed1313*/1314lpFileSA, /* LPSECURITY security attributes */1315CREATE_ALWAYS, /* DWORD creation disposition1316* create file, if it already1317* exists, overwrite it.1318*/1319FILE_FLAG_DELETE_ON_CLOSE, /* DWORD flags and attributes */13201321NULL); /* HANDLE template file access */13221323free_security_attr(lpFileSA);13241325if (fh == INVALID_HANDLE_VALUE) {1326DWORD lasterror = GetLastError();1327if (PrintMiscellaneous && Verbose) {1328warning("could not create file %s: %d\n", filename, lasterror);1329}1330return NULL;1331}13321333// try to create the file mapping1334fmh = create_file_mapping(objectname, fh, lpSmoSA, size);13351336free_security_attr(lpSmoSA);13371338if (fmh == NULL) {1339// closing the file handle here will decrement the reference count1340// on the file. When all processes accessing the file close their1341// handle to it, the reference count will decrement to 0 and the1342// OS will delete the file. These semantics are requested by the1343// FILE_FLAG_DELETE_ON_CLOSE flag in CreateFile call above.1344CloseHandle(fh);1345fh = NULL;1346return NULL;1347} else {1348// We created the file mapping, but rarely the size of the1349// backing store file is reported as zero (0) which can cause1350// failures when trying to use the hsperfdata file.1351struct stat statbuf;1352int ret_code = ::stat(filename, &statbuf);1353if (ret_code == OS_ERR) {1354if (PrintMiscellaneous && Verbose) {1355warning("Could not get status information from file %s: %s\n",1356filename, strerror(errno));1357}1358CloseHandle(fmh);1359CloseHandle(fh);1360fh = NULL;1361fmh = NULL;1362return NULL;1363}13641365// We could always call FlushFileBuffers() but the Microsoft1366// docs indicate that it is considered expensive so we only1367// call it when we observe the size as zero (0).1368if (statbuf.st_size == 0 && FlushFileBuffers(fh) != TRUE) {1369DWORD lasterror = GetLastError();1370if (PrintMiscellaneous && Verbose) {1371warning("could not flush file %s: %d\n", filename, lasterror);1372}1373CloseHandle(fmh);1374CloseHandle(fh);1375fh = NULL;1376fmh = NULL;1377return NULL;1378}1379}13801381// the file has been successfully created and the file mapping1382// object has been created.1383sharedmem_fileHandle = fh;1384sharedmem_fileName = strdup(filename);13851386return fmh;1387}13881389// open the shared memory object for the given vmid.1390//1391static HANDLE open_sharedmem_object(const char* objectname, DWORD ofm_access, TRAPS) {13921393HANDLE fmh;13941395// open the file mapping with the requested mode1396fmh = OpenFileMapping(1397ofm_access, /* DWORD access mode */1398FALSE, /* BOOL inherit flag - Do not allow inherit */1399objectname); /* name for object */14001401if (fmh == NULL) {1402if (PrintMiscellaneous && Verbose) {1403warning("OpenFileMapping failed for shared memory object %s:"1404" lasterror = %d\n", objectname, GetLastError());1405}1406THROW_MSG_(vmSymbols::java_lang_Exception(),1407"Could not open PerfMemory", INVALID_HANDLE_VALUE);1408}14091410return fmh;;1411}14121413// create a named shared memory region1414//1415// On Win32, a named shared memory object has a name space that1416// is independent of the file system name space. Shared memory object,1417// or more precisely, file mapping objects, provide no mechanism to1418// inquire the size of the memory region. There is also no api to1419// enumerate the memory regions for various processes.1420//1421// This implementation utilizes the shared memory name space in parallel1422// with the file system name space. This allows us to determine the1423// size of the shared memory region from the size of the file and it1424// allows us to provide a common, file system based name space for1425// shared memory across platforms.1426//1427static char* mapping_create_shared(size_t size) {14281429void *mapAddress;1430int vmid = os::current_process_id();14311432// get the name of the user associated with this process1433char* user = get_user_name();14341435if (user == NULL) {1436return NULL;1437}14381439// construct the name of the user specific temporary directory1440char* dirname = get_user_tmp_dir(user);14411442// check that the file system is secure - i.e. it supports ACLs.1443if (!is_filesystem_secure(dirname)) {1444return NULL;1445}14461447// create the names of the backing store files and for the1448// share memory object.1449//1450char* filename = get_sharedmem_filename(dirname, vmid);1451char* objectname = get_sharedmem_objectname(user, vmid);14521453// cleanup any stale shared memory resources1454cleanup_sharedmem_resources(dirname);14551456assert(((size != 0) && (size % os::vm_page_size() == 0)),1457"unexpected PerfMemry region size");14581459FREE_C_HEAP_ARRAY(char, user, mtInternal);14601461// create the shared memory resources1462sharedmem_fileMapHandle =1463create_sharedmem_resources(dirname, filename, objectname, size);14641465FREE_C_HEAP_ARRAY(char, filename, mtInternal);1466FREE_C_HEAP_ARRAY(char, objectname, mtInternal);1467FREE_C_HEAP_ARRAY(char, dirname, mtInternal);14681469if (sharedmem_fileMapHandle == NULL) {1470return NULL;1471}14721473// map the file into the address space1474mapAddress = MapViewOfFile(1475sharedmem_fileMapHandle, /* HANDLE = file mapping object */1476FILE_MAP_ALL_ACCESS, /* DWORD access flags */14770, /* DWORD High word of offset */14780, /* DWORD Low word of offset */1479(DWORD)size); /* DWORD Number of bytes to map */14801481if (mapAddress == NULL) {1482if (PrintMiscellaneous && Verbose) {1483warning("MapViewOfFile failed, lasterror = %d\n", GetLastError());1484}1485CloseHandle(sharedmem_fileMapHandle);1486sharedmem_fileMapHandle = NULL;1487return NULL;1488}14891490// clear the shared memory region1491(void)memset(mapAddress, '\0', size);14921493// it does not go through os api, the operation has to record from here1494MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress,1495size, CURRENT_PC, mtInternal);14961497return (char*) mapAddress;1498}14991500// this method deletes the file mapping object.1501//1502static void delete_file_mapping(char* addr, size_t size) {15031504// cleanup the persistent shared memory resources. since DestroyJavaVM does1505// not support unloading of the JVM, unmapping of the memory resource is not1506// performed. The memory will be reclaimed by the OS upon termination of all1507// processes mapping the resource. The file mapping handle and the file1508// handle are closed here to expedite the remove of the file by the OS. The1509// file is not removed directly because it was created with1510// FILE_FLAG_DELETE_ON_CLOSE semantics and any attempt to remove it would1511// be unsuccessful.15121513// close the fileMapHandle. the file mapping will still be retained1514// by the OS as long as any other JVM processes has an open file mapping1515// handle or a mapped view of the file.1516//1517if (sharedmem_fileMapHandle != NULL) {1518CloseHandle(sharedmem_fileMapHandle);1519sharedmem_fileMapHandle = NULL;1520}15211522// close the file handle. This will decrement the reference count on the1523// backing store file. When the reference count decrements to 0, the OS1524// will delete the file. These semantics apply because the file was1525// created with the FILE_FLAG_DELETE_ON_CLOSE flag.1526//1527if (sharedmem_fileHandle != INVALID_HANDLE_VALUE) {1528CloseHandle(sharedmem_fileHandle);1529sharedmem_fileHandle = INVALID_HANDLE_VALUE;1530}1531}15321533// this method determines the size of the shared memory file1534//1535static size_t sharedmem_filesize(const char* filename, TRAPS) {15361537struct stat statbuf;15381539// get the file size1540//1541// on win95/98/me, _stat returns a file size of 0 bytes, but on1542// winnt/2k the appropriate file size is returned. support for1543// the sharable aspects of performance counters was abandonded1544// on the non-nt win32 platforms due to this and other api1545// inconsistencies1546//1547if (::stat(filename, &statbuf) == OS_ERR) {1548if (PrintMiscellaneous && Verbose) {1549warning("stat %s failed: %s\n", filename, strerror(errno));1550}1551THROW_MSG_0(vmSymbols::java_io_IOException(),1552"Could not determine PerfMemory size");1553}15541555if ((statbuf.st_size == 0) || (statbuf.st_size % os::vm_page_size() != 0)) {1556if (PrintMiscellaneous && Verbose) {1557warning("unexpected file size: size = " SIZE_FORMAT "\n",1558statbuf.st_size);1559}1560THROW_MSG_0(vmSymbols::java_lang_Exception(),1561"Invalid PerfMemory size");1562}15631564return statbuf.st_size;1565}15661567// this method opens a file mapping object and maps the object1568// into the address space of the process1569//1570static void open_file_mapping(const char* user, int vmid,1571PerfMemory::PerfMemoryMode mode,1572char** addrp, size_t* sizep, TRAPS) {15731574ResourceMark rm;15751576void *mapAddress = 0;1577size_t size = 0;1578HANDLE fmh;1579DWORD ofm_access;1580DWORD mv_access;1581const char* luser = NULL;15821583if (mode == PerfMemory::PERF_MODE_RO) {1584ofm_access = FILE_MAP_READ;1585mv_access = FILE_MAP_READ;1586}1587else if (mode == PerfMemory::PERF_MODE_RW) {1588#ifdef LATER1589ofm_access = FILE_MAP_READ | FILE_MAP_WRITE;1590mv_access = FILE_MAP_READ | FILE_MAP_WRITE;1591#else1592THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),1593"Unsupported access mode");1594#endif1595}1596else {1597THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),1598"Illegal access mode");1599}16001601// if a user name wasn't specified, then find the user name for1602// the owner of the target vm.1603if (user == NULL || strlen(user) == 0) {1604luser = get_user_name(vmid);1605}1606else {1607luser = user;1608}16091610if (luser == NULL) {1611THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),1612"Could not map vmid to user name");1613}16141615// get the names for the resources for the target vm1616char* dirname = get_user_tmp_dir(luser);16171618// since we don't follow symbolic links when creating the backing1619// store file, we also don't following them when attaching1620//1621if (!is_directory_secure(dirname)) {1622FREE_C_HEAP_ARRAY(char, dirname, mtInternal);1623THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),1624"Process not found");1625}16261627char* filename = get_sharedmem_filename(dirname, vmid);1628char* objectname = get_sharedmem_objectname(luser, vmid);16291630// copy heap memory to resource memory. the objectname and1631// filename are passed to methods that may throw exceptions.1632// using resource arrays for these names prevents the leaks1633// that would otherwise occur.1634//1635char* rfilename = NEW_RESOURCE_ARRAY(char, strlen(filename) + 1);1636char* robjectname = NEW_RESOURCE_ARRAY(char, strlen(objectname) + 1);1637strcpy(rfilename, filename);1638strcpy(robjectname, objectname);16391640// free the c heap resources that are no longer needed1641if (luser != user) FREE_C_HEAP_ARRAY(char, luser, mtInternal);1642FREE_C_HEAP_ARRAY(char, dirname, mtInternal);1643FREE_C_HEAP_ARRAY(char, filename, mtInternal);1644FREE_C_HEAP_ARRAY(char, objectname, mtInternal);16451646if (*sizep == 0) {1647size = sharedmem_filesize(rfilename, CHECK);1648} else {1649size = *sizep;1650}16511652assert(size > 0, "unexpected size <= 0");16531654// Open the file mapping object with the given name1655fmh = open_sharedmem_object(robjectname, ofm_access, CHECK);16561657assert(fmh != INVALID_HANDLE_VALUE, "unexpected handle value");16581659// map the entire file into the address space1660mapAddress = MapViewOfFile(1661fmh, /* HANDLE Handle of file mapping object */1662mv_access, /* DWORD access flags */16630, /* DWORD High word of offset */16640, /* DWORD Low word of offset */1665size); /* DWORD Number of bytes to map */16661667if (mapAddress == NULL) {1668if (PrintMiscellaneous && Verbose) {1669warning("MapViewOfFile failed, lasterror = %d\n", GetLastError());1670}1671CloseHandle(fmh);1672THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),1673"Could not map PerfMemory");1674}16751676// it does not go through os api, the operation has to record from here1677MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size,1678CURRENT_PC, mtInternal);167916801681*addrp = (char*)mapAddress;1682*sizep = size;16831684// File mapping object can be closed at this time without1685// invalidating the mapped view of the file1686CloseHandle(fmh);16871688if (PerfTraceMemOps) {1689tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at "1690INTPTR_FORMAT "\n", size, vmid, mapAddress);1691}1692}16931694// this method unmaps the the mapped view of the the1695// file mapping object.1696//1697static void remove_file_mapping(char* addr) {16981699// the file mapping object was closed in open_file_mapping()1700// after the file map view was created. We only need to1701// unmap the file view here.1702UnmapViewOfFile(addr);1703}17041705// create the PerfData memory region in shared memory.1706static char* create_shared_memory(size_t size) {17071708return mapping_create_shared(size);1709}17101711// release a named, shared memory region1712//1713void delete_shared_memory(char* addr, size_t size) {17141715delete_file_mapping(addr, size);1716}17171718171917201721// create the PerfData memory region1722//1723// This method creates the memory region used to store performance1724// data for the JVM. The memory may be created in standard or1725// shared memory.1726//1727void PerfMemory::create_memory_region(size_t size) {17281729if (PerfDisableSharedMem || !os::win32::is_nt()) {1730// do not share the memory for the performance data.1731PerfDisableSharedMem = true;1732_start = create_standard_memory(size);1733}1734else {1735_start = create_shared_memory(size);1736if (_start == NULL) {17371738// creation of the shared memory region failed, attempt1739// to create a contiguous, non-shared memory region instead.1740//1741if (PrintMiscellaneous && Verbose) {1742warning("Reverting to non-shared PerfMemory region.\n");1743}1744PerfDisableSharedMem = true;1745_start = create_standard_memory(size);1746}1747}17481749if (_start != NULL) _capacity = size;17501751}17521753// delete the PerfData memory region1754//1755// This method deletes the memory region used to store performance1756// data for the JVM. The memory region indicated by the <address, size>1757// tuple will be inaccessible after a call to this method.1758//1759void PerfMemory::delete_memory_region() {17601761assert((start() != NULL && capacity() > 0), "verify proper state");17621763// If user specifies PerfDataSaveFile, it will save the performance data1764// to the specified file name no matter whether PerfDataSaveToFile is specified1765// or not. In other word, -XX:PerfDataSaveFile=.. overrides flag1766// -XX:+PerfDataSaveToFile.1767if (PerfDataSaveToFile || PerfDataSaveFile != NULL) {1768save_memory_to_file(start(), capacity());1769}17701771if (PerfDisableSharedMem) {1772delete_standard_memory(start(), capacity());1773}1774else {1775delete_shared_memory(start(), capacity());1776}1777}17781779// attach to the PerfData memory region for another JVM1780//1781// This method returns an <address, size> tuple that points to1782// a memory buffer that is kept reasonably synchronized with1783// the PerfData memory region for the indicated JVM. This1784// buffer may be kept in synchronization via shared memory1785// or some other mechanism that keeps the buffer updated.1786//1787// If the JVM chooses not to support the attachability feature,1788// this method should throw an UnsupportedOperation exception.1789//1790// This implementation utilizes named shared memory to map1791// the indicated process's PerfData memory region into this JVMs1792// address space.1793//1794void PerfMemory::attach(const char* user, int vmid, PerfMemoryMode mode,1795char** addrp, size_t* sizep, TRAPS) {17961797if (vmid == 0 || vmid == os::current_process_id()) {1798*addrp = start();1799*sizep = capacity();1800return;1801}18021803open_file_mapping(user, vmid, mode, addrp, sizep, CHECK);1804}18051806// detach from the PerfData memory region of another JVM1807//1808// This method detaches the PerfData memory region of another1809// JVM, specified as an <address, size> tuple of a buffer1810// in this process's address space. This method may perform1811// arbitrary actions to accomplish the detachment. The memory1812// region specified by <address, size> will be inaccessible after1813// a call to this method.1814//1815// If the JVM chooses not to support the attachability feature,1816// this method should throw an UnsupportedOperation exception.1817//1818// This implementation utilizes named shared memory to detach1819// the indicated process's PerfData memory region from this1820// process's address space.1821//1822void PerfMemory::detach(char* addr, size_t bytes, TRAPS) {18231824assert(addr != 0, "address sanity check");1825assert(bytes > 0, "capacity sanity check");18261827if (PerfMemory::contains(addr) || PerfMemory::contains(addr + bytes - 1)) {1828// prevent accidental detachment of this process's PerfMemory region1829return;1830}18311832if (MemTracker::tracking_level() > NMT_minimal) {1833// it does not go through os api, the operation has to record from here1834Tracker tkr = MemTracker::get_virtual_memory_release_tracker();1835remove_file_mapping(addr);1836tkr.record((address)addr, bytes);1837} else {1838remove_file_mapping(addr);1839}1840}18411842char* PerfMemory::backing_store_filename() {1843return sharedmem_fileName;1844}184518461847