hotspot/src/os/solaris/dtrace/jvm_dtrace.c
author stefank
Tue, 23 Nov 2010 13:22:55 -0800
changeset 7397 5b173b4ca846
parent 5547 f4b087cbb361
child 18078 10417cf9967d
permissions -rw-r--r--
6989984: Use standard include model for Hospot Summary: Replaced MakeDeps and the includeDB files with more standardized solutions. Reviewed-by: coleenp, kvn, kamg
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
7397
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
     2
 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
5547
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1
diff changeset
    21
 * questions.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
#include <door.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
#include <errno.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
#include <fcntl.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
#include <limits.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
#include <poll.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
#include <signal.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
#include <stdarg.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
#include <stdio.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
#include <stdlib.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
#include <string.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
#include <sys/types.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
#include <sys/stat.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
#include <thread.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
#include <unistd.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
#include "jvm_dtrace.h"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
// NOTE: These constants are used in JVM code as well.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
// KEEP JVM CODE IN SYNC if you are going to change these...
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
#define DTRACE_ALLOC_PROBES   0x1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
#define DTRACE_METHOD_PROBES  0x2
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
#define DTRACE_MONITOR_PROBES 0x4
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
#define DTRACE_ALL_PROBES     -1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
// generic error messages
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
#define JVM_ERR_OUT_OF_MEMORY            "out of memory (native heap)"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
#define JVM_ERR_INVALID_PARAM            "invalid input parameter(s)"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
#define JVM_ERR_NULL_PARAM               "input paramater is NULL"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
// error messages for attach
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
#define JVM_ERR_CANT_OPEN_DOOR           "cannot open door file"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
#define JVM_ERR_CANT_CREATE_ATTACH_FILE  "cannot create attach file"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
#define JVM_ERR_DOOR_FILE_PERMISSION     "door file is not secure"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
#define JVM_ERR_CANT_SIGNAL              "cannot send SIGQUIT to target"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
// error messages for enable probe
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
#define JVM_ERR_DOOR_CMD_SEND            "door command send failed"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
#define JVM_ERR_DOOR_CANT_READ_STATUS    "cannot read door command status"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
#define JVM_ERR_DOOR_CMD_STATUS          "door command error status"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
// error message for detach
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
#define JVM_ERR_CANT_CLOSE_DOOR          "cannot close door file"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
#define RESTARTABLE(_cmd, _result) do { \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
    do { \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
        _result = _cmd; \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
    } while((_result == -1) && (errno == EINTR)); \
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
} while(0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
struct _jvm_t {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
    pid_t pid;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
    int door_fd;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
static int libjvm_dtrace_debug;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
static void print_debug(const char* fmt,...) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
    if (libjvm_dtrace_debug) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
        va_list alist;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
        va_start(alist, fmt);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
        fputs("libjvm_dtrace DEBUG: ", stderr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
        vfprintf(stderr, fmt, alist);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
        va_end(alist);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
/* Key for thread local error message */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
static thread_key_t jvm_error_key;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
/* init function for this library */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
static void init_jvm_dtrace() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
    /* check for env. var for debug mode */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
    libjvm_dtrace_debug = getenv("LIBJVM_DTRACE_DEBUG") != NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
    /* create key for thread local error message */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
    if (thr_keycreate(&jvm_error_key, NULL) != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
        print_debug("can't create thread_key_t for jvm error key\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
        // exit(1); ?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
#pragma init(init_jvm_dtrace)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
/* set thread local error message */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
static void set_jvm_error(const char* msg) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
    thr_setspecific(jvm_error_key, (void*)msg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
/* clear thread local error message */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
static void clear_jvm_error() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
    thr_setspecific(jvm_error_key, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
/* file handling functions that can handle interrupt */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
static int file_open(const char* path, int flag) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
    int ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
    RESTARTABLE(open(path, flag), ret);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
    return ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
static int file_close(int fd) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
    int ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
    RESTARTABLE(close(fd), ret);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
    return ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
static int file_read(int fd, char* buf, int len) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
    int ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
    RESTARTABLE(read(fd, buf, len), ret);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
    return ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
/* send SIGQUIT signal to given process */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
static int send_sigquit(pid_t pid) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
    int ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
    RESTARTABLE(kill(pid, SIGQUIT), ret);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
    return ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
/* called to check permissions on attach file */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
static int check_permission(const char* path) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
    struct stat64 sb;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
    uid_t uid, gid;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
    int res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
    /*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
     * Check that the path is owned by the effective uid/gid of this
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
     * process. Also check that group/other access is not allowed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
     */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
    uid = geteuid();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
    gid = getegid();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
    res = stat64(path, &sb);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
    if (res != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
        print_debug("stat failed for %s\n", path);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
        return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
    if ((sb.st_uid != uid) || (sb.st_gid != gid) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
        ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
        print_debug("well-known file %s is not secure\n", path);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
        return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
    return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
#define ATTACH_FILE_PATTERN "/tmp/.attach_pid%d"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
/* fill-in the name of attach file name in given buffer */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
static void fill_attach_file_name(char* path, int len, pid_t pid) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
    memset(path, 0, len);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
    sprintf(path, ATTACH_FILE_PATTERN, pid);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
#define DOOR_FILE_PATTERN "/tmp/.java_pid%d"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
/* open door file for the given JVM */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
static int open_door(pid_t pid) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
    char path[PATH_MAX + 1];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
    int fd;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
    sprintf(path, DOOR_FILE_PATTERN, pid);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
    fd = file_open(path, O_RDONLY);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
    if (fd < 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
        set_jvm_error(JVM_ERR_CANT_OPEN_DOOR);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
        print_debug("cannot open door file %s\n", path);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
        return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
    print_debug("opened door file %s\n", path);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
    if (check_permission(path) != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
        set_jvm_error(JVM_ERR_DOOR_FILE_PERMISSION);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
        print_debug("check permission failed for %s\n", path);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
        file_close(fd);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
        fd = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
    return fd;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
/* create attach file for given process */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
static int create_attach_file(pid_t pid) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
    char path[PATH_MAX + 1];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
    int fd;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
    fill_attach_file_name(path, sizeof(path), pid);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
    fd = file_open(path, O_CREAT | O_RDWR);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
    if (fd < 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
        set_jvm_error(JVM_ERR_CANT_CREATE_ATTACH_FILE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
        print_debug("cannot create file %s\n", path);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
        print_debug("created attach file %s\n", path);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
    return fd;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
/* delete attach file for given process */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
static void delete_attach_file(pid_t pid) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
    char path[PATH_MAX + 1];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
    fill_attach_file_name(path, sizeof(path), pid);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
    int res = unlink(path);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
    if (res) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
        print_debug("cannot delete attach file %s\n", path);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
        print_debug("deleted attach file %s\n", path);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
/* attach to given JVM */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
jvm_t* jvm_attach(pid_t pid) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
    jvm_t* jvm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
    int door_fd, attach_fd, i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
    jvm = (jvm_t*) calloc(1, sizeof(jvm_t));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
    if (jvm == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
        set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
        print_debug("calloc failed in %s at %d\n", __FILE__, __LINE__);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
        return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
    jvm->pid = pid;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
    attach_fd = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
    door_fd = open_door(pid);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
    if (door_fd < 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
        print_debug("trying to create attach file\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
        if ((attach_fd = create_attach_file(pid)) < 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
            goto quit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
        /* send QUIT signal to the target so that it will
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
         * check for the attach file.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
         */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
        if (send_sigquit(pid) != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
            set_jvm_error(JVM_ERR_CANT_SIGNAL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
            print_debug("sending SIGQUIT failed\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
            goto quit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
        /* give the target VM time to start the attach mechanism */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
        do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
            int res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
            RESTARTABLE(poll(0, 0, 200), res);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
            door_fd = open_door(pid);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
            i++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
        } while (i <= 50 && door_fd == -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
        if (door_fd < 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
            print_debug("Unable to open door to process %d\n", pid);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
            goto quit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
quit:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
    if (attach_fd >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
        file_close(attach_fd);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
        delete_attach_file(jvm->pid);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
    if (door_fd >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
        jvm->door_fd = door_fd;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
        clear_jvm_error();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
        free(jvm);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
        jvm = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
    return jvm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
/* return the last thread local error message */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
const char* jvm_get_last_error() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
    const char* res = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
    thr_getspecific(jvm_error_key, (void**)&res);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
    return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
/* detach the givenb JVM */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
int jvm_detach(jvm_t* jvm) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
    if (jvm) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
        int res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
        if (jvm->door_fd != -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
            if (file_close(jvm->door_fd) != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
                set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
                res = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
            } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
                clear_jvm_error();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
                res = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
        free(jvm);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
        return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
        set_jvm_error(JVM_ERR_NULL_PARAM);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
        print_debug("jvm_t* is NULL\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
        return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
 * A simple table to translate some known errors into reasonable
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
 * error messages
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
static struct {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
    int err;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
    const char* msg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
} const error_messages[] = {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
    { 100,      "Bad request" },
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
    { 101,      "Protocol mismatch" },
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
    { 102,      "Resource failure" },
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
    { 103,      "Internal error" },
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
    { 104,      "Permission denied" },
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
 * Lookup the given error code and return the appropriate
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
 * message. If not found return NULL.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
static const char* translate_error(int err) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
    int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
    int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
    for (i=0; i<table_size; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
        if (err == error_messages[i].err) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
            return error_messages[i].msg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
    return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
 * Current protocol version
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
static const char* PROTOCOL_VERSION = "1";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
#define RES_BUF_SIZE 128
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
 * Enqueue attach-on-demand command to the given JVM
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
static
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
int enqueue_command(jvm_t* jvm, const char* cstr, int arg_count, const char** args) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
    size_t size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
    door_arg_t door_args;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
    char res_buffer[RES_BUF_SIZE];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
    int rc, i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
    char* buf = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
    int result = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
    /*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
     * First we get the command string and create the start of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
     * argument string to send to the target VM:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
     * <ver>\0<cmd>\0
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
     */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
    if (cstr == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
        print_debug("command name is NULL\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
        goto quit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
    size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
    buf = (char*)malloc(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
    if (buf != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
        char* pos = buf;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
        strcpy(buf, PROTOCOL_VERSION);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
        pos += strlen(PROTOCOL_VERSION)+1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
        strcpy(pos, cstr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
        set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
        print_debug("malloc failed at %d in %s\n", __LINE__, __FILE__);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
        goto quit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
    /*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
     * Next we iterate over the arguments and extend the buffer
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
     * to include them.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
     */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
    for (i=0; i<arg_count; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
        cstr = args[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
        if (cstr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
            size_t len = strlen(cstr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
            char* newbuf = (char*)realloc(buf, size+len+1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
            if (newbuf == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
                set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
                print_debug("realloc failed in %s at %d\n", __FILE__, __LINE__);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
                goto quit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
            buf = newbuf;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
            strcpy(buf+size, cstr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
            size += len+1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
    /*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
     * The arguments to the door function are in 'buf' so we now
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
     * do the door call
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
     */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
    door_args.data_ptr = buf;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
    door_args.data_size = size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
    door_args.desc_ptr = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
    door_args.desc_num = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
    door_args.rbuf = (char*)&res_buffer;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
    door_args.rsize = sizeof(res_buffer);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
489c9b5090e2 Initial load
duke
parents:
diff changeset
   419
    RESTARTABLE(door_call(jvm->door_fd, &door_args), rc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   420
489c9b5090e2 Initial load
duke
parents:
diff changeset
   421
    /*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
     * door_call failed
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
     */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
    if (rc == -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
        print_debug("door_call failed\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
        /*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
         * door_call succeeded but the call didn't return the the expected jint.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
         */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
        if (door_args.data_size < sizeof(int)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
            print_debug("Enqueue error - reason unknown as result is truncated!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
            int* res = (int*)(door_args.data_ptr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
            if (*res != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
                const char* msg = translate_error(*res);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
                if (msg == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
                    print_debug("Unable to enqueue command to target VM: %d\n", *res);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
                } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
                    print_debug("Unable to enqueue command to target VM: %s\n", msg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
                }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
            } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
                /*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
                 * The door call should return a file descriptor to one end of
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
                 * a socket pair
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
                 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
                if ((door_args.desc_ptr != NULL) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
                    (door_args.desc_num == 1) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
                    (door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
                    result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
                } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
                    print_debug("Reply from enqueue missing descriptor!\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
                }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
quit:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
    if (buf) free(buf);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
    return result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
/* read status code for a door command */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
static int read_status(int fd) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
    char ch, buf[16];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
    int index = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
    while (1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
        if (file_read(fd, &ch, sizeof(ch)) != sizeof(ch)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   469
            set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
            print_debug("door cmd status: read status failed\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
            return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
        buf[index++] = ch;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
        if (ch == '\n') {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   475
            buf[index - 1] = '\0';
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
            return atoi(buf);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   477
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   478
        if (index == sizeof(buf)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
            set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
            print_debug("door cmd status: read status overflow\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   481
            return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   482
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
static const char* ENABLE_DPROBES_CMD = "enabledprobes";
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
/* enable one or more DTrace probes for a given JVM */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
    int fd, status = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
    char ch;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
    const char* args[1];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
    char buf[16];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
    int probe_type = 0, index;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
    int count = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
    if (jvm == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
        set_jvm_error(JVM_ERR_NULL_PARAM);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
        print_debug("jvm_t* is NULL\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
        return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
    if (num_probe_types == 0 || probe_types == NULL ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
        probe_types[0] == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
        set_jvm_error(JVM_ERR_INVALID_PARAM);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   506
        print_debug("invalid probe type argument(s)\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
        return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
    for (index = 0; index < num_probe_types; index++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   511
        const char* p = probe_types[index];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   512
        if (strcmp(p, JVM_DTPROBE_OBJECT_ALLOC) == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
            probe_type |= DTRACE_ALLOC_PROBES;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
            count++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
        } else if (strcmp(p, JVM_DTPROBE_METHOD_ENTRY) == 0 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
                   strcmp(p, JVM_DTPROBE_METHOD_RETURN) == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   517
            probe_type |= DTRACE_METHOD_PROBES;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   518
            count++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
        } else if (strcmp(p, JVM_DTPROBE_MONITOR_ENTER) == 0   ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
                   strcmp(p, JVM_DTPROBE_MONITOR_ENTERED) == 0 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
                   strcmp(p, JVM_DTPROBE_MONITOR_EXIT) == 0    ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
                   strcmp(p, JVM_DTPROBE_MONITOR_WAIT) == 0    ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
                   strcmp(p, JVM_DTPROBE_MONITOR_WAITED) == 0  ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
                   strcmp(p, JVM_DTPROBE_MONITOR_NOTIFY) == 0  ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
                   strcmp(p, JVM_DTPROBE_MONITOR_NOTIFYALL) == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
            probe_type |= DTRACE_MONITOR_PROBES;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
            count++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
        } else if (strcmp(p, JVM_DTPROBE_ALL) == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
            probe_type |= DTRACE_ALL_PROBES;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
            count++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
    if (count == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
        return count;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   537
    sprintf(buf, "%d", probe_type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
    args[0] = buf;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
    fd = enqueue_command(jvm, ENABLE_DPROBES_CMD, 1, args);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
    if (fd < 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   542
        set_jvm_error(JVM_ERR_DOOR_CMD_SEND);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
        return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
    status = read_status(fd);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
    // non-zero status is error
489c9b5090e2 Initial load
duke
parents:
diff changeset
   548
    if (status) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   549
        set_jvm_error(JVM_ERR_DOOR_CMD_STATUS);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
        print_debug("%s command failed (status: %d) in target JVM\n",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   551
                    ENABLE_DPROBES_CMD, status);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   552
        file_close(fd);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   553
        return -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   554
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   555
    // read from stream until EOF
489c9b5090e2 Initial load
duke
parents:
diff changeset
   556
    while (file_read(fd, &ch, sizeof(ch)) == sizeof(ch)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   557
        if (libjvm_dtrace_debug) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   558
            printf("%c", ch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   559
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   560
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   561
489c9b5090e2 Initial load
duke
parents:
diff changeset
   562
    file_close(fd);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   563
    clear_jvm_error();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   564
    return count;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   565
}