src/os/bsd/dtrace/libjvm_db.c
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File 8004128_2 Sdiff src/os/bsd/dtrace

src/os/bsd/dtrace/libjvm_db.c

Print this page




 147   uint64_t RuntimeStub_vtbl;
 148   uint64_t Method_vtbl;
 149 
 150   uint64_t Use_Compressed_Oops_address;
 151   uint64_t Universe_narrow_oop_base_address;
 152   uint64_t Universe_narrow_oop_shift_address;
 153   uint64_t CodeCache_heap_address;
 154 
 155   /* Volatiles */
 156   uint8_t  Use_Compressed_Oops;
 157   uint64_t Universe_narrow_oop_base;
 158   uint32_t Universe_narrow_oop_shift;
 159   uint64_t CodeCache_low;
 160   uint64_t CodeCache_high;
 161   uint64_t CodeCache_segmap_low;
 162   uint64_t CodeCache_segmap_high;
 163 
 164   int32_t  SIZE_CodeCache_log2_segment;
 165 
 166   uint64_t methodPtr;
 167   uint64_t bcx;
 168 
 169   Nmethod_t *N;                 /*Inlined methods support */
 170   Frame_t   prev_fr;
 171   Frame_t   curr_fr;
 172 };
 173 
 174 static int
 175 read_string(struct ps_prochandle *P,
 176         char *buf,              /* caller's buffer */
 177         size_t size,            /* upper limit on bytes to read */
 178         uintptr_t addr)         /* address in process */
 179 {
 180   int err = PS_OK;
 181   while (size-- > 1 && err == PS_OK) {
 182     err = ps_pread(P, addr, buf, 1);
 183     if (*buf == '\0') {
 184       return PS_OK;
 185     }
 186     addr += 1;
 187     buf += 1;


1051   } else {
1052       err = name_for_methodPtr(J, method, result+1, size-1);
1053       CHECK_FAIL(err);
1054   }
1055   if (deoptimized) {
1056     strncat(result + 1, " [deoptimized frame]; ", size-1);
1057   } else {
1058     strncat(result + 1, " [compiled] ", size-1);
1059   }
1060   if (debug)
1061       fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
1062                       result, N->vf_cnt);
1063   return PS_OK;
1064 
1065  fail:
1066   if (debug)
1067       fprintf(stderr, "name_for_nmethod: FAIL \n\n");
1068   return err;
1069 }
1070 
1071 int is_bci(intptr_t bcx) {
1072   switch (DATA_MODEL) {
1073   case PR_MODEL_LP64:
1074     return ((uintptr_t) bcx) <= ((uintptr_t) MAX_METHOD_CODE_SIZE) ;
1075   case PR_MODEL_ILP32:
1076   default:
1077     return 0 <= bcx && bcx <= MAX_METHOD_CODE_SIZE;
1078   }
1079 }
1080 
1081 static int
1082 name_for_imethod(jvm_agent_t* J,
1083                  uint64_t bcx,
1084                  uint64_t method,
1085                  char *result,
1086                  size_t size,
1087                  Jframe_t *jframe
1088 ) {
1089   uint64_t bci;
1090   uint64_t constMethod;
1091   Vframe_t vframe = {0};
1092   Vframe_t *vf = &vframe;
1093   int32_t   err;
1094 
1095   err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod);
1096   CHECK_FAIL(err);
1097 
1098   bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_ConstMethod);
1099 
1100   if (debug)
1101       fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method);
1102 
1103   err = name_for_methodPtr(J, method, result, size);
1104   CHECK_FAIL(err);
1105   if (debug)
1106       fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
1107 
1108   if (bci > 0) {
1109       vf->method = method;
1110       vf->bci       = bci;
1111       err = line_number_from_bci(J, vf);
1112       CHECK_FAIL(err);
1113   }
1114   jframe->bci  = vf->bci;
1115   jframe->line = vf->line;
1116   jframe->locinf = 1;
1117 
1118   if (debug) {


1152 
1153     if (debug) {
1154         fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n",
1155                         start, pc, method);
1156     }
1157     err = name_for_nmethod(J, start, pc, method, result, size, jframe);
1158     CHECK_FAIL(err);
1159   } else if (vtbl == J->BufferBlob_vtbl) {
1160     const char * name;
1161 
1162     err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
1163 
1164     /*
1165      * Temporary usage of string "Interpreter".
1166      * We need some other way to distinguish "StubRoutines"
1167      * and regular interpreted frames.
1168      */
1169     if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
1170       *is_interpreted = 1;
1171       if (is_method(J, J->methodPtr)) {
1172         return name_for_imethod(J, J->bcx, J->methodPtr, result, size, jframe);
1173       }
1174     }
1175 
1176     if (err == PS_OK) {
1177       strncpy(result, name, size);
1178       free((void*)name);
1179     } else {
1180       strncpy(result, "<unknown BufferBlob>", size);
1181     }
1182     /* return PS_OK; */
1183   } else {
1184     const char * name;
1185 
1186     err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
1187     if (err == PS_OK) {
1188       strncpy(result, name, size);
1189       free((void*)name);
1190     } else {
1191       strncpy(result, "<unknown CodeBlob>", size);
1192       WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);


1309                        name, vf->line);
1310   }
1311   return PS_OK;
1312 
1313  fail:
1314   if (debug) {
1315       fprintf(stderr, "\t Jget_vframe: FAIL\n");
1316   }
1317   return err;
1318 }
1319 
1320 #define MAX_SYM_SIZE 256
1321 
1322 int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
1323                     size_t size, Jframe_t *jframe) {
1324   uintptr_t fp;
1325   uintptr_t pc;
1326   /* arguments given to read_pointer need to be worst case sized */
1327   uint64_t methodPtr = 0;
1328   uint64_t sender_sp;
1329   uint64_t bcx = 0;
1330   int is_interpreted = 0;
1331   int result = PS_OK;
1332   int err = PS_OK;
1333 
1334   if (J == NULL) {
1335     return -1;
1336   }
1337 
1338   jframe->vf_cnt = 1;
1339   jframe->new_fp = 0;
1340   jframe->new_pc = 0;
1341   jframe->line   = 0;
1342   jframe->bci    = 0;
1343   jframe->locinf = 0;
1344 
1345   read_volatiles(J);
1346   pc = (uintptr_t) regs[R_PC];
1347   J->curr_fr.pc = pc;
1348   J->curr_fr.fp = regs[R_FP];
1349   J->curr_fr.sp = regs[R_SP];
1350 
1351   if (debug)
1352       fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
1353 
1354 #if defined(sparc) || defined(__sparc)
1355     /* The following workaround is for SPARC. CALL instruction occupates 8 bytes.
1356      * In the pcDesc structure return pc offset is recorded for CALL instructions.
1357      * regs[R_PC] contains a CALL instruction pc offset.
1358      */
1359     pc += 8;
1360     bcx          = (uintptr_t) regs[R_L1];
1361     methodPtr = (uintptr_t) regs[R_L2];
1362     sender_sp = regs[R_I5];
1363     if (debug > 2) {
1364         fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n",
1365                          regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]);
1366     }
1367 #elif defined(i386) || defined(__i386) || defined(__amd64)
1368 
1369     fp = (uintptr_t) regs[R_FP];
1370     if (J->prev_fr.fp == 0) {
1371 #ifdef X86_COMPILER2
1372         /* A workaround for top java frames */
1373         J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
1374 #else
1375         J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
1376 #endif /* COMPILER2 */
1377     }
1378     if (debug > 2) {
1379         printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
1380     }
1381 
1382     if (read_pointer(J,  fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) {
1383       methodPtr = 0;
1384     }
1385     if (read_pointer(J,  fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
1386       sender_sp = 0;
1387     }
1388     if (read_pointer(J,  fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) {
1389       bcx = 0;
1390     }
1391 #endif /* i386 */
1392 
1393   J->methodPtr = methodPtr;
1394   J->bcx = bcx;
1395 
1396   /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
1397    * For example: JVM_SuspendThread frame poins to the top interpreted frame.
1398    * If we call is_method(J, methodPtr) before codecache_contains(J, pc)
1399    * then we go over and omit both: nmethod and I2CAdapter frames.
1400    * Note, that regs[R_PC] is always correct if frame defined correctly.
1401    * So it is better to call codecache_contains(J, pc) from the beginning.
1402    */
1403 #ifndef X86_COMPILER2
1404   if (is_method(J, J->methodPtr)) {
1405     result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe);
1406     /* If the methodPtr is a method then this is highly likely to be
1407        an interpreter frame */
1408     if (result >= 0) {
1409       is_interpreted = 1;
1410     }
1411   } else
1412 #endif /* ! X86_COMPILER2 */
1413 
1414   if (codecache_contains(J, pc)) {
1415     result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
1416   }
1417 #ifdef X86_COMPILER2
1418   else if (is_method(J, J->methodPtr)) {
1419     result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe);
1420     /* If the methodPtr is a method then this is highly likely to be
1421        an interpreter frame */
1422     if (result >= 0) {
1423       is_interpreted = 1;
1424     }
1425   }
1426 #endif /* X86_COMPILER2 */
1427   else {
1428     if (debug) {
1429         fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
1430     }
1431     result = -1;
1432   }
1433   if (!is_interpreted) {
1434     sender_sp = 0;
1435   }
1436   J->curr_fr.sender_sp = sender_sp;
1437 
1438 #ifdef X86_COMPILER2
1439   if (!J->curr_fr.fp) {




 147   uint64_t RuntimeStub_vtbl;
 148   uint64_t Method_vtbl;
 149 
 150   uint64_t Use_Compressed_Oops_address;
 151   uint64_t Universe_narrow_oop_base_address;
 152   uint64_t Universe_narrow_oop_shift_address;
 153   uint64_t CodeCache_heap_address;
 154 
 155   /* Volatiles */
 156   uint8_t  Use_Compressed_Oops;
 157   uint64_t Universe_narrow_oop_base;
 158   uint32_t Universe_narrow_oop_shift;
 159   uint64_t CodeCache_low;
 160   uint64_t CodeCache_high;
 161   uint64_t CodeCache_segmap_low;
 162   uint64_t CodeCache_segmap_high;
 163 
 164   int32_t  SIZE_CodeCache_log2_segment;
 165 
 166   uint64_t methodPtr;
 167   uint64_t bcp;
 168 
 169   Nmethod_t *N;                 /*Inlined methods support */
 170   Frame_t   prev_fr;
 171   Frame_t   curr_fr;
 172 };
 173 
 174 static int
 175 read_string(struct ps_prochandle *P,
 176         char *buf,              /* caller's buffer */
 177         size_t size,            /* upper limit on bytes to read */
 178         uintptr_t addr)         /* address in process */
 179 {
 180   int err = PS_OK;
 181   while (size-- > 1 && err == PS_OK) {
 182     err = ps_pread(P, addr, buf, 1);
 183     if (*buf == '\0') {
 184       return PS_OK;
 185     }
 186     addr += 1;
 187     buf += 1;


1051   } else {
1052       err = name_for_methodPtr(J, method, result+1, size-1);
1053       CHECK_FAIL(err);
1054   }
1055   if (deoptimized) {
1056     strncat(result + 1, " [deoptimized frame]; ", size-1);
1057   } else {
1058     strncat(result + 1, " [compiled] ", size-1);
1059   }
1060   if (debug)
1061       fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
1062                       result, N->vf_cnt);
1063   return PS_OK;
1064 
1065  fail:
1066   if (debug)
1067       fprintf(stderr, "name_for_nmethod: FAIL \n\n");
1068   return err;
1069 }
1070 










1071 static int
1072 name_for_imethod(jvm_agent_t* J,
1073                  uint64_t bcp,
1074                  uint64_t method,
1075                  char *result,
1076                  size_t size,
1077                  Jframe_t *jframe
1078 ) {
1079   uint64_t bci;
1080   uint64_t constMethod;
1081   Vframe_t vframe = {0};
1082   Vframe_t *vf = &vframe;
1083   int32_t   err;
1084 
1085   err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod);
1086   CHECK_FAIL(err);
1087 
1088   bci = bcp - (constMethod + (uint64_t) SIZE_ConstMethod);
1089 
1090   if (debug)
1091       fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method);
1092 
1093   err = name_for_methodPtr(J, method, result, size);
1094   CHECK_FAIL(err);
1095   if (debug)
1096       fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
1097 
1098   if (bci > 0) {
1099       vf->method = method;
1100       vf->bci       = bci;
1101       err = line_number_from_bci(J, vf);
1102       CHECK_FAIL(err);
1103   }
1104   jframe->bci  = vf->bci;
1105   jframe->line = vf->line;
1106   jframe->locinf = 1;
1107 
1108   if (debug) {


1142 
1143     if (debug) {
1144         fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n",
1145                         start, pc, method);
1146     }
1147     err = name_for_nmethod(J, start, pc, method, result, size, jframe);
1148     CHECK_FAIL(err);
1149   } else if (vtbl == J->BufferBlob_vtbl) {
1150     const char * name;
1151 
1152     err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
1153 
1154     /*
1155      * Temporary usage of string "Interpreter".
1156      * We need some other way to distinguish "StubRoutines"
1157      * and regular interpreted frames.
1158      */
1159     if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
1160       *is_interpreted = 1;
1161       if (is_method(J, J->methodPtr)) {
1162         return name_for_imethod(J, J->bcp, J->methodPtr, result, size, jframe);
1163       }
1164     }
1165 
1166     if (err == PS_OK) {
1167       strncpy(result, name, size);
1168       free((void*)name);
1169     } else {
1170       strncpy(result, "<unknown BufferBlob>", size);
1171     }
1172     /* return PS_OK; */
1173   } else {
1174     const char * name;
1175 
1176     err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
1177     if (err == PS_OK) {
1178       strncpy(result, name, size);
1179       free((void*)name);
1180     } else {
1181       strncpy(result, "<unknown CodeBlob>", size);
1182       WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);


1299                        name, vf->line);
1300   }
1301   return PS_OK;
1302 
1303  fail:
1304   if (debug) {
1305       fprintf(stderr, "\t Jget_vframe: FAIL\n");
1306   }
1307   return err;
1308 }
1309 
1310 #define MAX_SYM_SIZE 256
1311 
1312 int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
1313                     size_t size, Jframe_t *jframe) {
1314   uintptr_t fp;
1315   uintptr_t pc;
1316   /* arguments given to read_pointer need to be worst case sized */
1317   uint64_t methodPtr = 0;
1318   uint64_t sender_sp;
1319   uint64_t bcp = 0;
1320   int is_interpreted = 0;
1321   int result = PS_OK;
1322   int err = PS_OK;
1323 
1324   if (J == NULL) {
1325     return -1;
1326   }
1327 
1328   jframe->vf_cnt = 1;
1329   jframe->new_fp = 0;
1330   jframe->new_pc = 0;
1331   jframe->line   = 0;
1332   jframe->bci    = 0;
1333   jframe->locinf = 0;
1334 
1335   read_volatiles(J);
1336   pc = (uintptr_t) regs[R_PC];
1337   J->curr_fr.pc = pc;
1338   J->curr_fr.fp = regs[R_FP];
1339   J->curr_fr.sp = regs[R_SP];
1340 
1341   if (debug)
1342       fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
1343 
1344 #if defined(sparc) || defined(__sparc)
1345     /* The following workaround is for SPARC. CALL instruction occupates 8 bytes.
1346      * In the pcDesc structure return pc offset is recorded for CALL instructions.
1347      * regs[R_PC] contains a CALL instruction pc offset.
1348      */
1349     pc += 8;
1350     bcp          = (uintptr_t) regs[R_L1];
1351     methodPtr = (uintptr_t) regs[R_L2];
1352     sender_sp = regs[R_I5];
1353     if (debug > 2) {
1354         fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n",
1355                          regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]);
1356     }
1357 #elif defined(i386) || defined(__i386) || defined(__amd64)
1358 
1359     fp = (uintptr_t) regs[R_FP];
1360     if (J->prev_fr.fp == 0) {
1361 #ifdef X86_COMPILER2
1362         /* A workaround for top java frames */
1363         J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
1364 #else
1365         J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
1366 #endif /* COMPILER2 */
1367     }
1368     if (debug > 2) {
1369         printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
1370     }
1371 
1372     if (read_pointer(J,  fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) {
1373       methodPtr = 0;
1374     }
1375     if (read_pointer(J,  fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
1376       sender_sp = 0;
1377     }
1378     if (read_pointer(J,  fp + OFFSET_interpreter_frame_bcp_offset, &bcp) != PS_OK) {
1379       bcp = 0;
1380     }
1381 #endif /* i386 */
1382 
1383   J->methodPtr = methodPtr;
1384   J->bcp = bcp;
1385 
1386   /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
1387    * For example: JVM_SuspendThread frame poins to the top interpreted frame.
1388    * If we call is_method(J, methodPtr) before codecache_contains(J, pc)
1389    * then we go over and omit both: nmethod and I2CAdapter frames.
1390    * Note, that regs[R_PC] is always correct if frame defined correctly.
1391    * So it is better to call codecache_contains(J, pc) from the beginning.
1392    */
1393 #ifndef X86_COMPILER2
1394   if (is_method(J, J->methodPtr)) {
1395     result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe);
1396     /* If the methodPtr is a method then this is highly likely to be
1397        an interpreter frame */
1398     if (result >= 0) {
1399       is_interpreted = 1;
1400     }
1401   } else
1402 #endif /* ! X86_COMPILER2 */
1403 
1404   if (codecache_contains(J, pc)) {
1405     result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
1406   }
1407 #ifdef X86_COMPILER2
1408   else if (is_method(J, J->methodPtr)) {
1409     result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe);
1410     /* If the methodPtr is a method then this is highly likely to be
1411        an interpreter frame */
1412     if (result >= 0) {
1413       is_interpreted = 1;
1414     }
1415   }
1416 #endif /* X86_COMPILER2 */
1417   else {
1418     if (debug) {
1419         fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
1420     }
1421     result = -1;
1422   }
1423   if (!is_interpreted) {
1424     sender_sp = 0;
1425   }
1426   J->curr_fr.sender_sp = sender_sp;
1427 
1428 #ifdef X86_COMPILER2
1429   if (!J->curr_fr.fp) {


src/os/bsd/dtrace/libjvm_db.c
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File