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 /* 25 */ 26 27 #include <stdio.h> 28 #include <string.h> 29 #include "jvmti.h" 30 #include "agent_common.h" 31 #include "JVMTITools.h" 32 33 extern "C" { 34 35 36 #define PASSED 0 37 #define STATUS_FAILED 2 38 39 static jvmtiEnv *jvmti = NULL; 40 static jvmtiCapabilities caps; 41 static jint result = PASSED; 42 static jboolean printdump = JNI_FALSE; 43 44 #ifdef STATIC_BUILD 45 JNIEXPORT jint JNICALL Agent_OnLoad_linetab004(JavaVM *jvm, char *options, void *reserved) { 46 return Agent_Initialize(jvm, options, reserved); 47 } 48 JNIEXPORT jint JNICALL Agent_OnAttach_linetab004(JavaVM *jvm, char *options, void *reserved) { 49 return Agent_Initialize(jvm, options, reserved); 50 } 51 JNIEXPORT jint JNI_OnLoad_linetab004(JavaVM *jvm, char *options, void *reserved) { 52 return JNI_VERSION_1_8; 53 } 54 #endif 55 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 56 jvmtiError err; 57 jint res; 58 59 if (options != NULL && strcmp(options, "printdump") == 0) { 60 printdump = JNI_TRUE; 61 } 62 63 res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1); 64 if (res != JNI_OK || jvmti == NULL) { 65 printf("Wrong result of a valid call to GetEnv!\n"); 66 return JNI_ERR; 67 } 68 69 err = jvmti->GetPotentialCapabilities(&caps); 70 if (err != JVMTI_ERROR_NONE) { 71 printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n", 72 TranslateError(err), err); 73 return JNI_ERR; 74 } 75 76 err = jvmti->AddCapabilities(&caps); 77 if (err != JVMTI_ERROR_NONE) { 78 printf("(AddCapabilities) unexpected error: %s (%d)\n", 79 TranslateError(err), err); 80 return JNI_ERR; 81 } 82 83 err = jvmti->GetCapabilities(&caps); 84 if (err != JVMTI_ERROR_NONE) { 85 printf("(GetCapabilities) unexpected error: %s (%d)\n", 86 TranslateError(err), err); 87 return JNI_ERR; 88 } 89 90 if (!caps.can_get_line_numbers) { 91 printf("Warning: GetLineNumberTable is not implemented\n"); 92 } 93 94 return JNI_OK; 95 } 96 97 void checkGetLineNumberTable(jmethodID mid, const char *methName, 98 int abstract, jvmtiError exp) { 99 jint entryCount = -1; 100 jvmtiLineNumberEntry *table = NULL; 101 jvmtiError err; 102 int i; 103 104 err = jvmti->GetLineNumberTable(mid, &entryCount, &table); 105 if (printdump == JNI_TRUE) { 106 printf("\n Method: %s%s\n", methName, 107 (abstract==0) ? "" : " (abstract)"); 108 } 109 if (err != exp) { 110 result = STATUS_FAILED; 111 printf(" Error expected: %s (%d),\n", TranslateError(exp), exp); 112 printf(" actual: %s (%d)\n", TranslateError(err), err); 113 if (err == JVMTI_ERROR_NONE) { 114 printf(" %s%s line number table (%d entries):%s\n", 115 methName, (abstract==0) ? "" : " (abstract)", 116 entryCount, (entryCount==0 ? " empty" : "")); 117 for (i = 0; i < entryCount; i++) { 118 printf(" start_location = 0x%x%08x,", 119 (jint)(table[i].start_location >> 32), 120 (jint)table[i].start_location); 121 printf(" line_number = %d\n", table[i].line_number); 122 } 123 } 124 } else if (printdump == JNI_TRUE) { 125 printf(" Error code: %s (%d),\n", TranslateError(err), err); 126 } 127 } 128 129 JNIEXPORT jint JNICALL 130 Java_nsk_jvmti_unit_GetLineNumberTable_linetab004_check(JNIEnv *env, jclass cls) { 131 jmethodID mid; 132 jclass abstr; 133 jclass interf; 134 135 if (jvmti == NULL) { 136 printf("JVMTI client was not properly loaded!\n"); 137 return STATUS_FAILED; 138 } 139 140 if (!caps.can_get_line_numbers) { 141 return result; 142 } 143 144 if (printdump == JNI_TRUE) { 145 printf("\n Check methods of interface:\n"); 146 } 147 interf = env->FindClass("nsk/jvmti/unit/GetLineNumberTable/Interface004"); 148 if (interf == NULL) { 149 printf("Cannot get Interface class!\n"); 150 return STATUS_FAILED; 151 } 152 153 mid = env->GetMethodID(cls, "instanceMeth0", "()I"); 154 if (mid == NULL) { 155 printf("Cannot get method ID!\n"); 156 return STATUS_FAILED; 157 } 158 checkGetLineNumberTable(mid, "instanceMeth0", 1, 159 JVMTI_ERROR_ABSENT_INFORMATION); 160 161 mid = env->GetMethodID(cls, "instanceMeth1", "()I"); 162 if (mid == NULL) { 163 printf("Cannot get method ID!\n"); 164 return STATUS_FAILED; 165 } 166 checkGetLineNumberTable(mid, "instanceMeth1", 1, 167 JVMTI_ERROR_ABSENT_INFORMATION); 168 169 if (printdump == JNI_TRUE) { 170 printf("\n Check methods of abstract class:\n"); 171 } 172 abstr = env->GetSuperclass(cls); 173 if (abstr == NULL) { 174 printf("Cannot get super class!\n"); 175 return STATUS_FAILED; 176 } 177 178 mid = env->GetMethodID(abstr, "instanceMeth0", "()I"); 179 if (mid == NULL) { 180 printf("Cannot get method ID!\n"); 181 return STATUS_FAILED; 182 } 183 checkGetLineNumberTable(mid, "instanceMeth0", 1, 184 JVMTI_ERROR_ABSENT_INFORMATION); 185 186 mid = env->GetMethodID(abstr, "instanceMeth1", "()I"); 187 if (mid == NULL) { 188 printf("Cannot get method ID!\n"); 189 return STATUS_FAILED; 190 } 191 checkGetLineNumberTable(mid, "instanceMeth1", 0, 192 JVMTI_ERROR_ABSENT_INFORMATION); 193 194 if (printdump == JNI_TRUE) { 195 printf("\n Check methods of regular class:\n"); 196 } 197 mid = env->GetMethodID(cls, "instanceMeth0", "()I"); 198 if (mid == NULL) { 199 printf("Cannot get method ID!\n"); 200 return STATUS_FAILED; 201 } 202 checkGetLineNumberTable(mid, "instanceMeth0", 0, 203 JVMTI_ERROR_ABSENT_INFORMATION); 204 205 mid = env->GetMethodID(cls, "instanceMeth1", "()I"); 206 if (mid == NULL) { 207 printf("Cannot get method ID!\n"); 208 return STATUS_FAILED; 209 } 210 checkGetLineNumberTable(mid, "instanceMeth1", 0, 211 JVMTI_ERROR_ABSENT_INFORMATION); 212 213 mid = env->GetMethodID(cls, "instanceMeth2", "()I"); 214 if (mid == NULL) { 215 printf("Cannot get method ID!\n"); 216 return STATUS_FAILED; 217 } 218 checkGetLineNumberTable(mid, "instanceMeth2", 0, 219 JVMTI_ERROR_ABSENT_INFORMATION); 220 221 if (printdump == JNI_TRUE) { 222 printf("\n Check native methods of regular class:\n"); 223 } 224 mid = env->GetMethodID(cls, "instanceNativeMeth", "()I"); 225 if (mid == NULL) { 226 printf("Cannot get method ID!\n"); 227 return STATUS_FAILED; 228 } 229 checkGetLineNumberTable(mid, "instanceNativeMeth", 1, 230 JVMTI_ERROR_NATIVE_METHOD); 231 232 mid = env->GetStaticMethodID(cls, "staticNativeMeth", "()I"); 233 if (mid == NULL) { 234 printf("Cannot get method ID!\n"); 235 return STATUS_FAILED; 236 } 237 checkGetLineNumberTable(mid, "staticNativeMeth", 1, 238 JVMTI_ERROR_NATIVE_METHOD); 239 240 if (printdump == JNI_TRUE) { 241 printf(">>> ... done\n"); 242 } 243 244 return result; 245 } 246 247 }