Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 #include <stdatomic.h>
     27 
     28 #include "vmDebug.h"
     29 
     30 #include "JDWP.h"
     31 #include "debugLoop.h"
     32 #include "transport.h"
     33 #include "util.h"
     34 
     35 static _Atomic(jlong) lastDebuggerActivity = ATOMIC_VAR_INIT(0LL);
     36 static _Atomic(jboolean) hasSeenDebuggerActivity = ATOMIC_VAR_INIT(JNI_FALSE);
     37 
     38 // Reset the tracking variables.
     39 void vmDebug_onDisconnect()
     40 {
     41     atomic_store(&lastDebuggerActivity, 0LL);
     42     atomic_store(&hasSeenDebuggerActivity, JNI_FALSE);
     43 }
     44 
     45 // Mark us as having seen actual debugger activity (so isDebuggerConnected can return true) and that
     46 // we are currently doing something as the debugger.
     47 void vmDebug_notifyDebuggerActivityStart()
     48 {
     49     atomic_store(&lastDebuggerActivity, 0LL);
     50     atomic_store(&hasSeenDebuggerActivity, JNI_TRUE);
     51 }
     52 
     53 // Update the timestamp for the last debugger activity.
     54 void vmDebug_notifyDebuggerActivityEnd()
     55 {
     56     atomic_store(&lastDebuggerActivity, milliTime());
     57 }
     58 
     59 // For backwards compatibility we are only considered 'connected' as far as VMDebug is concerned if
     60 // we have gotten at least one non-ddms JDWP packet.
     61 static jboolean
     62 isDebuggerConnected()
     63 {
     64     return transport_is_open() && atomic_load(&hasSeenDebuggerActivity);
     65 }
     66 
     67 static jboolean JNICALL
     68 VMDebug_isDebuggerConnected(JNIEnv* env, jclass klass)
     69 {
     70     return isDebuggerConnected();
     71 }
     72 
     73 static jboolean JNICALL
     74 VMDebug_isDebuggingEnabled(JNIEnv* env, jclass klass)
     75 {
     76     // We are running the debugger so debugging is definitely enabled.
     77     return JNI_TRUE;
     78 }
     79 
     80 static jlong JNICALL
     81 VMDebug_lastDebuggerActivity(JNIEnv* env, jclass klass)
     82 {
     83     if (!isDebuggerConnected()) {
     84         LOG_ERROR(("VMDebug.lastDebuggerActivity called without active debugger"));
     85         return -1;
     86     }
     87     jlong last_time = atomic_load(&lastDebuggerActivity);
     88     if (last_time == 0) {
     89         LOG_MISC(("debugger is performing an action"));
     90         return 0;
     91     }
     92 
     93     jlong cur_time = milliTime();
     94 
     95     if (cur_time < last_time) {
     96         LOG_ERROR(("Time seemed to go backwards: last was %lld, current is %lld",
     97                    last_time, cur_time));
     98         return 0;
     99     }
    100     jlong res = cur_time - last_time;
    101     LOG_MISC(("Debugger interval is %lld", res));
    102     return res;
    103 }
    104 
    105 void
    106 vmDebug_initalize(JNIEnv* env)
    107 {
    108     WITH_LOCAL_REFS(env, 1) {
    109         jclass vmdebug_class = JNI_FUNC_PTR(env,FindClass)(env, "dalvik/system/VMDebug");
    110         if (vmdebug_class == NULL) {
    111             // The VMDebug class isn't available. We don't need to do anything.
    112             LOG_MISC(("dalvik.system.VMDebug does not seem to be available on this runtime."));
    113             // Get rid of the ClassNotFoundException.
    114             JNI_FUNC_PTR(env,ExceptionClear)(env);
    115             goto finish;
    116         }
    117 
    118         JNINativeMethod methods[3];
    119 
    120         // Take over the implementation of these three functions.
    121         methods[0].name = "lastDebuggerActivity";
    122         methods[0].signature = "()J";
    123         methods[0].fnPtr = (void*)VMDebug_lastDebuggerActivity;
    124 
    125         methods[1].name = "isDebuggingEnabled";
    126         methods[1].signature = "()Z";
    127         methods[1].fnPtr = (void*)VMDebug_isDebuggingEnabled;
    128 
    129         methods[2].name = "isDebuggerConnected";
    130         methods[2].signature = "()Z";
    131         methods[2].fnPtr = (void*)VMDebug_isDebuggerConnected;
    132 
    133         jint res = JNI_FUNC_PTR(env,RegisterNatives)(env,
    134                                                      vmdebug_class,
    135                                                      methods,
    136                                                      sizeof(methods) / sizeof(JNINativeMethod));
    137         if (res != JNI_OK) {
    138             EXIT_ERROR(JVMTI_ERROR_INTERNAL,
    139                        "RegisterNatives returned failure for VMDebug class");
    140         }
    141 
    142         finish: ;
    143     } END_WITH_LOCAL_REFS(env);
    144 }
    145 
    146