1 /*
   2  * Copyright (c) 2003, 2018, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* This test case to test the following:
  25  *      StackTrace esp. new args
  26  */
  27 
  28 #include <stdio.h>
  29 #include <string.h>
  30 #include "jvmti.h"
  31 #include "agent_common.h"
  32 
  33 #ifdef __cplusplus
  34 extern "C" {
  35 #endif
  36 
  37 #ifndef JNI_ENV_ARG
  38 
  39 #ifdef __cplusplus
  40 #define JNI_ENV_ARG(x, y) y
  41 #define JNI_ENV_ARG1(x)
  42 #define JNI_ENV_PTR(x) x
  43 #else
  44 #define JNI_ENV_ARG(x,y) x, y
  45 #define JNI_ENV_ARG1(x) x
  46 #define JNI_ENV_PTR(x) (*x)
  47 #endif
  48 
  49 #endif
  50 
  51 #define JVMTI_ENV_ARG JNI_ENV_ARG
  52 #define JVMTI_ENV_ARG1 JNI_ENV_ARG1
  53 #define JVMTI_ENV_PTR JNI_ENV_PTR
  54 
  55 #define JVMTI_ERROR_CHECK(str,res) if ( res != JVMTI_ERROR_NONE) { printf(str); printf("%d\n",res); return res;}
  56 #define JVMTI_ERROR_CHECK_EXPECTED_ERROR(str,res,err) if ( res != err) { printf(str); printf("unexpected error %d\n",res); return res;}
  57 
  58 #define JVMTI_ERROR_CHECK_VOID(str,res) if ( res != JVMTI_ERROR_NONE) { printf(str); printf("%d\n",res); iGlobalStatus = 2; }
  59 
  60 #define JVMTI_ERROR_CHECK_EXPECTED_ERROR_VOID(str,res,err) if ( res != err) { printf(str); printf("unexpected error %d\n",res); iGlobalStatus = 2; }
  61 
  62 #define THREADS_LIMIT 2000
  63 
  64 
  65 jvmtiEnv *jvmti;
  66 jint iGlobalStatus = 0;
  67 jthread susp_thrd[THREADS_LIMIT];
  68 static jvmtiEventCallbacks callbacks;
  69 static jvmtiCapabilities jvmti_caps;
  70 jrawMonitorID jraw_monitor[20];
  71 
  72 int process_once = 0;
  73 
  74 
  75 
  76 int printdump = 0;
  77 
  78 
  79 void debug_printf(const char *fmt, ...) {
  80     va_list args;
  81 
  82     va_start(args, fmt);
  83     if (printdump) {
  84         vprintf(fmt, args);
  85     }
  86     va_end(args);
  87 }
  88 
  89 
  90 #ifdef STATIC_BUILD
  91 JNIEXPORT jint JNICALL Agent_OnLoad_JvmtiTest(JavaVM *jvm, char *options, void *reserved) {
  92     return Agent_Initialize(jvm, options, reserved);
  93 }
  94 JNIEXPORT jint JNICALL Agent_OnAttach_JvmtiTest(JavaVM *jvm, char *options, void *reserved) {
  95     return Agent_Initialize(jvm, options, reserved);
  96 }
  97 JNIEXPORT jint JNI_OnLoad_JvmtiTest(JavaVM *jvm, char *options, void *reserved) {
  98     return JNI_VERSION_1_8;
  99 }
 100 #endif
 101 jint Agent_Initialize(JavaVM * jvm, char *options, void *reserved) {
 102     jint res;
 103 
 104     if (options && strlen(options) > 0) {
 105         if (strstr(options, "printdump")) {
 106             printdump = 1;
 107         }
 108     }
 109 
 110     res = JNI_ENV_PTR(jvm)->
 111         GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), JVMTI_VERSION_1_1);
 112     if (res < 0) {
 113         printf("Wrong result of a valid call to GetEnv!\n");
 114         return JNI_ERR;
 115     }
 116 
 117 
 118     /* Add capabilities */
 119     res = JVMTI_ENV_PTR(jvmti)->GetPotentialCapabilities(JVMTI_ENV_ARG(jvmti, &jvmti_caps));
 120     JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res);
 121 
 122     res = JVMTI_ENV_PTR(jvmti)->AddCapabilities(JVMTI_ENV_ARG(jvmti, &jvmti_caps));
 123     JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res);
 124 
 125     return JNI_OK;
 126 }
 127 
 128 
 129 JNIEXPORT jint JNICALL
 130 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_GetResult(JNIEnv * env, jclass cls) {
 131     return iGlobalStatus;
 132 }
 133 
 134 
 135 JNIEXPORT void JNICALL
 136 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_CreateRawMonitor(JNIEnv * env, jclass klass, jint i) {
 137     jvmtiError ret;
 138     char sz[128];
 139 
 140     sprintf(sz, "Rawmonitor-%d",i);
 141     debug_printf("jvmti create raw monitor \n");
 142     ret = JVMTI_ENV_PTR(jvmti)->CreateRawMonitor(JVMTI_ENV_ARG(jvmti, sz), &jraw_monitor[i]);
 143 
 144     if (ret != JVMTI_ERROR_NONE) {
 145         printf("Error: ForceGarbageCollection %d \n", ret);
 146         iGlobalStatus = 2;
 147     }
 148 }
 149 
 150 JNIEXPORT void JNICALL
 151 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_RawMonitorEnter(JNIEnv * env, jclass cls, jint i) {
 152     jvmtiError ret;
 153 
 154     debug_printf("jvmti Raw monitor enter \n");
 155     ret = JVMTI_ENV_PTR(jvmti)->RawMonitorEnter(JVMTI_ENV_ARG(jvmti, jraw_monitor[i]));
 156 
 157     if (ret != JVMTI_ERROR_NONE) {
 158         printf("Error: Raw monitor enter %d \n", ret);
 159         iGlobalStatus = 2;
 160     }
 161 }
 162 
 163 JNIEXPORT void JNICALL
 164 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_RawMonitorExit(JNIEnv * env, jclass cls, jint i) {
 165     jvmtiError ret;
 166 
 167     debug_printf("jvmti raw monitor exit \n");
 168     ret = JVMTI_ENV_PTR(jvmti)->RawMonitorExit(JVMTI_ENV_ARG(jvmti, jraw_monitor[i]));
 169 
 170     if (ret != JVMTI_ERROR_NONE) {
 171         printf("Error: RawMonitorExit %d \n", ret);
 172         iGlobalStatus = 2;
 173     }
 174 }
 175 
 176 JNIEXPORT void JNICALL
 177 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_RawMonitorWait(JNIEnv * env, jclass cls, jint i) {
 178     jvmtiError ret;
 179 
 180     debug_printf("jvmti RawMonitorWait \n");
 181     ret = JVMTI_ENV_PTR(jvmti)->RawMonitorWait(JVMTI_ENV_ARG(jvmti, jraw_monitor[i]), -1);
 182 
 183     if (ret != JVMTI_ERROR_NONE) {
 184         printf("Error: RawMonitorWait %d \n", ret);
 185         iGlobalStatus = 2;
 186     }
 187 }
 188 
 189 JNIEXPORT void JNICALL
 190 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_RawMonitorNotify(JNIEnv * env, jclass cls, jint i) {
 191     jvmtiError ret;
 192 
 193     debug_printf("jvmti RawMonitorNotify \n");
 194     ret = JVMTI_ENV_PTR(jvmti)->RawMonitorNotifyAll(JVMTI_ENV_ARG(jvmti, jraw_monitor[i]));
 195 
 196     if (ret != JVMTI_ERROR_NONE) {
 197         printf("Error: RawMonitorNotify %d \n", ret);
 198         iGlobalStatus = 2;
 199     }
 200 }
 201 
 202 JNIEXPORT int JNICALL
 203 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_GetFrameCount(JNIEnv * env, jclass cls, jobject thr) {
 204     jvmtiError ret;
 205     jint count;
 206 
 207     debug_printf("jvmti GetFrameCount \n");
 208     ret = JVMTI_ENV_PTR(jvmti)->GetFrameCount(JVMTI_ENV_ARG(jvmti, (jthread)thr),  &count);
 209     if (ret != JVMTI_ERROR_NONE) {
 210         printf("Error: GetFrameCount returned  %d \n", ret);
 211         iGlobalStatus = 2;
 212     }
 213     return count;
 214 }
 215 
 216 JNIEXPORT void JNICALL
 217 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_GetStackTrace(JNIEnv * env, jclass cls, jobject thr) {
 218     jvmtiError ret;
 219     jvmtiFrameInfo *stack_buffer = NULL;
 220     jvmtiFrameInfo *compare_buffer = NULL;
 221     jint max_count = 20;
 222     jint count;
 223     jclass klass;
 224     char *mname;
 225     char *signature;
 226     char *clname;
 227     int i;
 228     int j;
 229 
 230 
 231     debug_printf("jvmti GetStackTrace \n");
 232 
 233     ret = JVMTI_ENV_PTR(jvmti)->Allocate(JVMTI_ENV_ARG(jvmti, sizeof(jvmtiFrameInfo) * max_count), (unsigned char**)&stack_buffer);
 234     if (ret != JVMTI_ERROR_NONE) {
 235         printf("Error: Allocate failed with  %d \n", ret);
 236         iGlobalStatus = 2;
 237     }
 238 
 239     ret = JVMTI_ENV_PTR(jvmti)->Allocate(JVMTI_ENV_ARG(jvmti, sizeof(jvmtiFrameInfo) * max_count), (unsigned char**)&compare_buffer);
 240     if (ret != JVMTI_ERROR_NONE) {
 241         printf("Error: Allocate failed with  %d \n", ret);
 242         iGlobalStatus = 2;
 243     }
 244 
 245 
 246     ret = JVMTI_ENV_PTR(jvmti)->SuspendThread(JVMTI_ENV_ARG(jvmti, thr));
 247     if (ret != JVMTI_ERROR_NONE) {
 248         printf("Error: SuspendThread failed with  %d \n", ret);
 249         iGlobalStatus = 2;
 250     }
 251 
 252     ret = JVMTI_ENV_PTR(jvmti)->GetStackTrace(JVMTI_ENV_ARG(jvmti, thr), 0, max_count , stack_buffer, &count);
 253     if (ret != JVMTI_ERROR_NONE) {
 254         printf("Error: GetStackTrace %d \n", ret);
 255         iGlobalStatus = 2;
 256     }
 257 
 258     for (i = 1; i < count; ++i) {
 259       jint res_count = 48343;
 260       ret = JVMTI_ENV_PTR(jvmti)->GetStackTrace(JVMTI_ENV_ARG(jvmti, thr), i, max_count , compare_buffer, &res_count);
 261       if (ret != JVMTI_ERROR_NONE) {
 262         printf("Error: GetStackTrace2 %d \n", ret);
 263         iGlobalStatus = 2;
 264       }
 265       if (res_count != count - i) {
 266         printf("Error: mismatch res_count = %d, count = %d, i = %d\n", res_count, count, i);
 267         iGlobalStatus = 2;
 268       }
 269       for (j = 0; j < res_count; j++) {
 270         if (compare_buffer[j].method != stack_buffer[j+i].method) {
 271             printf("Error: wrong method\n");
 272             iGlobalStatus = 2;
 273         }
 274       }
 275     }
 276 
 277     for (i = 1; i < count; ++i) {
 278       jint res_count = 48343;
 279       ret = JVMTI_ENV_PTR(jvmti)->GetStackTrace(JVMTI_ENV_ARG(jvmti, thr), -i, max_count , compare_buffer, &res_count);
 280       if (ret != JVMTI_ERROR_NONE) {
 281         printf("Error: GetStackTrace2 %d \n", ret);
 282         iGlobalStatus = 2;
 283       }
 284       if (res_count != i) {
 285         printf("Error: mismatch res_count = %d, i = %d\n", res_count, i);
 286         iGlobalStatus = 2;
 287       }
 288       for (j = 0; j < res_count; j++) {
 289         if (compare_buffer[j].method != stack_buffer[j+count-i].method) {
 290             printf("Error: wrong neg method\n");
 291             iGlobalStatus = 2;
 292         }
 293       }
 294     }
 295 
 296     debug_printf("Count = %d\n", count);
 297 
 298 
 299     ret = JVMTI_ENV_PTR(jvmti)->ResumeThread(JVMTI_ENV_ARG(jvmti, thr));
 300     if (ret != JVMTI_ERROR_NONE) {
 301         printf("Error: ResumeThread failed with  %d \n", ret);
 302         iGlobalStatus = 2;
 303     }
 304 
 305     debug_printf(" Java Stack trace ---\n");
 306 
 307     for (i = 0; i < count; i++) {
 308         ret = JVMTI_ENV_PTR(jvmti)->GetMethodDeclaringClass(JVMTI_ENV_ARG(jvmti, stack_buffer[i].method), &klass);
 309         if (ret != JVMTI_ERROR_NONE) {
 310             printf("Error: GetMethodDeclaringClass %d  \n", ret);
 311             iGlobalStatus = 2;
 312             return;
 313         }
 314 
 315         ret = JVMTI_ENV_PTR(jvmti)->GetClassSignature(JVMTI_ENV_ARG(jvmti, klass), &clname, NULL);
 316         if (ret != JVMTI_ERROR_NONE) {
 317             printf("Error: GetClassSignature %d  \n", ret);
 318             iGlobalStatus = 2;
 319             return;
 320         }
 321 
 322         ret = JVMTI_ENV_PTR(jvmti)->GetMethodName(JVMTI_ENV_ARG(jvmti, stack_buffer[i].method), &mname, &signature, NULL);
 323         if (ret != JVMTI_ERROR_NONE) {
 324             printf("Error: GetMethodName %d  \n", ret);
 325             iGlobalStatus = 2;
 326             return;
 327         }
 328 
 329         debug_printf("[%d]  %s::%s(%s) at %lld \n",i,clname, mname, signature, stack_buffer[i].location);
 330 
 331 
 332     }
 333 
 334 
 335     ret = JVMTI_ENV_PTR(jvmti)->Deallocate(JVMTI_ENV_ARG(jvmti, (unsigned char *)stack_buffer));
 336     if (ret != JVMTI_ERROR_NONE) {
 337         printf("Error: Deallocate failed with  %d \n", ret);
 338         iGlobalStatus = 2;
 339     }
 340 
 341 
 342 }
 343 
 344 JNIEXPORT void JNICALL
 345 Java_nsk_jvmti_unit_StackTrace_JvmtiTest_SaveThreadInfo(JNIEnv * env, jclass cls, jobject oobj) {
 346 
 347 }
 348 
 349 #ifdef __cplusplus
 350 }
 351 #endif