src/os/solaris/dtrace/libjvm_db.c

Fri, 03 Apr 2020 14:14:26 +0100

author
aph
date
Fri, 03 Apr 2020 14:14:26 +0100
changeset 9920
3a3803a0c789
parent 6948
fd94cbe7c5da
child 9931
fd44df5e3bc3
permissions
-rw-r--r--

8076475: Misuses of strncpy/strncat
Summary: Various small fixes around strncpy and strncat
Reviewed-by: andrew

duke@435 1 /*
jiangli@3826 2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 #include <stdio.h>
duke@435 26 #include <stdlib.h>
duke@435 27 #include <string.h>
duke@435 28 #include <errno.h>
duke@435 29 #include <gelf.h>
duke@435 30
duke@435 31 #include "libjvm_db.h"
duke@435 32 #include "JvmOffsets.h"
duke@435 33
duke@435 34 #define LIBJVM_SO "libjvm.so"
duke@435 35
duke@435 36 #if defined(i386) || defined(__i386) || defined(__amd64)
duke@435 37 #ifdef COMPILER2
duke@435 38 #define X86_COMPILER2
duke@435 39 #endif /* COMPILER2 */
duke@435 40 #endif /* i386 */
duke@435 41
duke@435 42 typedef struct {
duke@435 43 short vf_cnt; /* number of recognized java vframes */
duke@435 44 short bci; /* current frame method byte code index */
duke@435 45 int line; /* current frame method source line */
duke@435 46 uint64_t new_fp; /* fp for the next frame */
duke@435 47 uint64_t new_pc; /* pc for the next frame */
duke@435 48 uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */
duke@435 49 char locinf; /* indicates there is valid location info */
duke@435 50 } Jframe_t;
duke@435 51
duke@435 52 int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
duke@435 53 size_t size, Jframe_t *jframe);
duke@435 54
duke@435 55 int main(int arg) { return arg; }
duke@435 56
duke@435 57 static int debug = 0;
duke@435 58
duke@435 59 static void failed(int err, const char * file, int line) {
duke@435 60 if (debug) {
duke@435 61 fprintf(stderr, "failed %d at %s:%d\n", err, file, line);
duke@435 62 }
duke@435 63 }
duke@435 64
duke@435 65 static void warn(const char * file, int line, const char * msg) {
duke@435 66 if (debug) {
duke@435 67 fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line);
duke@435 68 }
duke@435 69 }
duke@435 70
duke@435 71 static void warn1(const char * file, int line, const char * msg, intptr_t arg1) {
duke@435 72 if (debug) {
duke@435 73 fprintf(stderr, "warning: ");
duke@435 74 fprintf(stderr, msg, arg1);
duke@435 75 fprintf(stderr, " at %s:%d\n", file, line);
duke@435 76 }
duke@435 77 }
duke@435 78
duke@435 79 #define CHECK_FAIL(err) \
duke@435 80 if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; }
duke@435 81 #define WARN(msg) warn(__FILE__, __LINE__, msg)
duke@435 82 #define WARN1(msg, arg1) warn1(__FILE__, __LINE__, msg, arg1)
duke@435 83
duke@435 84 typedef struct VMStructEntry {
duke@435 85 const char * typeName; /* The type name containing the given field (example: "Klass") */
duke@435 86 const char * fieldName; /* The field name within the type (example: "_name") */
duke@435 87 uint64_t address; /* Address of field; only used for static fields */
duke@435 88 /* ("offset" can not be reused because of apparent SparcWorks compiler bug */
duke@435 89 /* in generation of initializer data) */
duke@435 90 } VMStructEntry;
duke@435 91
duke@435 92 /* Prototyping inlined methods */
duke@435 93
duke@435 94 int sprintf(char *s, const char *format, ...);
duke@435 95
duke@435 96 #define SZ16 sizeof(int16_t)
duke@435 97 #define SZ32 sizeof(int32_t)
duke@435 98
duke@435 99 #define COMP_METHOD_SIGN '*'
duke@435 100
duke@435 101 #define MAX_VFRAMES_CNT 256
duke@435 102
duke@435 103 typedef struct vframe {
coleenp@4037 104 uint64_t method;
duke@435 105 int32_t sender_decode_offset;
duke@435 106 int32_t methodIdx;
duke@435 107 int32_t bci;
duke@435 108 int32_t line;
duke@435 109 } Vframe_t;
duke@435 110
duke@435 111 typedef struct frame {
duke@435 112 uintptr_t fp;
duke@435 113 uintptr_t pc;
duke@435 114 uintptr_t sp;
duke@435 115 uintptr_t sender_sp; // The unextended sp of the caller
duke@435 116 } Frame_t;
duke@435 117
duke@435 118 typedef struct Nmethod_t {
duke@435 119 struct jvm_agent* J;
duke@435 120 Jframe_t *jframe;
duke@435 121
duke@435 122 uint64_t nm; /* _nmethod */
duke@435 123 uint64_t pc;
duke@435 124 uint64_t pc_desc;
duke@435 125
duke@435 126 int32_t orig_pc_offset; /* _orig_pc_offset */
twisti@2103 127 int32_t instrs_beg; /* _code_offset */
duke@435 128 int32_t instrs_end;
duke@435 129 int32_t deopt_beg; /* _deoptimize_offset */
duke@435 130 int32_t scopes_data_beg; /* _scopes_data_offset */
duke@435 131 int32_t scopes_data_end;
coleenp@4037 132 int32_t metadata_beg; /* _metadata_offset */
coleenp@4037 133 int32_t metadata_end;
duke@435 134 int32_t scopes_pcs_beg; /* _scopes_pcs_offset */
duke@435 135 int32_t scopes_pcs_end;
duke@435 136
duke@435 137 int vf_cnt;
duke@435 138 Vframe_t vframes[MAX_VFRAMES_CNT];
duke@435 139 } Nmethod_t;
duke@435 140
duke@435 141 struct jvm_agent {
duke@435 142 struct ps_prochandle* P;
duke@435 143
duke@435 144 uint64_t nmethod_vtbl;
duke@435 145 uint64_t CodeBlob_vtbl;
duke@435 146 uint64_t BufferBlob_vtbl;
duke@435 147 uint64_t RuntimeStub_vtbl;
coleenp@4037 148 uint64_t Method_vtbl;
duke@435 149
kvn@1077 150 uint64_t Use_Compressed_Oops_address;
kvn@1077 151 uint64_t Universe_narrow_oop_base_address;
kvn@1077 152 uint64_t Universe_narrow_oop_shift_address;
duke@435 153 uint64_t CodeCache_heap_address;
duke@435 154
duke@435 155 /* Volatiles */
kvn@1077 156 uint8_t Use_Compressed_Oops;
kvn@1077 157 uint64_t Universe_narrow_oop_base;
kvn@1077 158 uint32_t Universe_narrow_oop_shift;
duke@435 159 uint64_t CodeCache_low;
duke@435 160 uint64_t CodeCache_high;
duke@435 161 uint64_t CodeCache_segmap_low;
duke@435 162 uint64_t CodeCache_segmap_high;
duke@435 163
duke@435 164 int32_t SIZE_CodeCache_log2_segment;
duke@435 165
coleenp@4037 166 uint64_t methodPtr;
duke@435 167 uint64_t bcx;
duke@435 168
duke@435 169 Nmethod_t *N; /*Inlined methods support */
duke@435 170 Frame_t prev_fr;
duke@435 171 Frame_t curr_fr;
duke@435 172 };
duke@435 173
duke@435 174 static int
duke@435 175 read_string(struct ps_prochandle *P,
duke@435 176 char *buf, /* caller's buffer */
duke@435 177 size_t size, /* upper limit on bytes to read */
duke@435 178 uintptr_t addr) /* address in process */
duke@435 179 {
duke@435 180 int err = PS_OK;
duke@435 181 while (size-- > 1 && err == PS_OK) {
duke@435 182 err = ps_pread(P, addr, buf, 1);
duke@435 183 if (*buf == '\0') {
duke@435 184 return PS_OK;
duke@435 185 }
duke@435 186 addr += 1;
duke@435 187 buf += 1;
duke@435 188 }
duke@435 189 return -1;
duke@435 190 }
duke@435 191
coleenp@548 192 static int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) {
coleenp@548 193 int err = -1;
coleenp@548 194 uint32_t ptr32;
coleenp@548 195 err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
coleenp@548 196 *ptr = ptr32;
coleenp@548 197 return err;
coleenp@548 198 }
coleenp@548 199
duke@435 200 static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) {
duke@435 201 int err = -1;
duke@435 202 uint32_t ptr32;
duke@435 203
duke@435 204 switch (DATA_MODEL) {
duke@435 205 case PR_MODEL_LP64:
duke@435 206 err = ps_pread(J->P, base, ptr, sizeof(uint64_t));
duke@435 207 break;
duke@435 208 case PR_MODEL_ILP32:
duke@435 209 err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
duke@435 210 *ptr = ptr32;
duke@435 211 break;
duke@435 212 }
duke@435 213
duke@435 214 return err;
duke@435 215 }
duke@435 216
duke@435 217 static int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) {
duke@435 218 uint64_t ptr;
duke@435 219 int err;
duke@435 220 char buffer[1024];
duke@435 221
duke@435 222 *stringp = NULL;
duke@435 223 err = read_pointer(J, base, &ptr);
duke@435 224 CHECK_FAIL(err);
duke@435 225 if (ptr != 0) {
duke@435 226 err = read_string(J->P, buffer, sizeof(buffer), ptr);
duke@435 227 CHECK_FAIL(err);
duke@435 228 *stringp = strdup(buffer);
duke@435 229 }
duke@435 230 return PS_OK;
duke@435 231
duke@435 232 fail:
duke@435 233 return err;
duke@435 234 }
duke@435 235
duke@435 236 static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) {
duke@435 237 uint64_t ptr;
duke@435 238 int err;
duke@435 239
duke@435 240 err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName);
duke@435 241 CHECK_FAIL(err);
duke@435 242 err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName);
duke@435 243 CHECK_FAIL(err);
duke@435 244 err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address);
duke@435 245 CHECK_FAIL(err);
duke@435 246
duke@435 247 return PS_OK;
duke@435 248
duke@435 249 fail:
duke@435 250 if (vmp->typeName != NULL) free((void*)vmp->typeName);
duke@435 251 if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
duke@435 252 return err;
duke@435 253 }
duke@435 254
duke@435 255 static int parse_vmstructs(jvm_agent_t* J) {
duke@435 256 VMStructEntry vmVar;
duke@435 257 VMStructEntry* vmp = &vmVar;
duke@435 258 uint64_t gHotSpotVMStructs;
duke@435 259 psaddr_t sym_addr;
duke@435 260 uint64_t base;
duke@435 261 int err;
duke@435 262
kevinw@6948 263 /* Clear *vmp now in case we jump to fail: */
kevinw@6948 264 memset(vmp, 0, sizeof(VMStructEntry));
kevinw@6948 265
duke@435 266 err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
duke@435 267 CHECK_FAIL(err);
duke@435 268 err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
duke@435 269 CHECK_FAIL(err);
duke@435 270 base = gHotSpotVMStructs;
duke@435 271
duke@435 272 err = PS_OK;
duke@435 273 while (err == PS_OK) {
duke@435 274 memset(vmp, 0, sizeof(VMStructEntry));
duke@435 275 err = parse_vmstruct_entry(J, base, vmp);
duke@435 276 if (err != PS_OK || vmp->typeName == NULL) {
duke@435 277 break;
duke@435 278 }
duke@435 279
duke@435 280 if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
duke@435 281 if (strcmp("_heap", vmp->fieldName) == 0) {
duke@435 282 err = read_pointer(J, vmp->address, &J->CodeCache_heap_address);
duke@435 283 }
duke@435 284 } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
kvn@1077 285 if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
kvn@1077 286 J->Universe_narrow_oop_base_address = vmp->address;
kvn@1077 287 }
kvn@1077 288 if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) {
kvn@1077 289 J->Universe_narrow_oop_shift_address = vmp->address;
coleenp@548 290 }
duke@435 291 }
duke@435 292 CHECK_FAIL(err);
duke@435 293
duke@435 294 base += SIZE_VMStructEntry;
duke@435 295 if (vmp->typeName != NULL) free((void*)vmp->typeName);
duke@435 296 if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
duke@435 297 }
duke@435 298
duke@435 299 return PS_OK;
duke@435 300
duke@435 301 fail:
duke@435 302 if (vmp->typeName != NULL) free((void*)vmp->typeName);
duke@435 303 if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
duke@435 304 return -1;
duke@435 305 }
duke@435 306
kvn@1077 307 static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) {
kvn@1077 308 psaddr_t sym_addr;
kvn@1077 309 int err;
kvn@1077 310
kvn@1077 311 err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
kvn@1077 312 if (err != PS_OK) goto fail;
kvn@1077 313 *valuep = sym_addr;
kvn@1077 314 return PS_OK;
kvn@1077 315
kvn@1077 316 fail:
kvn@1077 317 return err;
kvn@1077 318 }
kvn@1077 319
duke@435 320 static int read_volatiles(jvm_agent_t* J) {
duke@435 321 uint64_t ptr;
duke@435 322 int err;
duke@435 323
kvn@1077 324 err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address);
kvn@1077 325 if (err == PS_OK) {
kvn@1077 326 err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t));
kvn@1077 327 CHECK_FAIL(err);
kvn@1077 328 } else {
kvn@1077 329 J->Use_Compressed_Oops = 0;
kvn@1077 330 }
kvn@1077 331
kvn@1077 332 err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
coleenp@548 333 CHECK_FAIL(err);
kvn@1077 334 err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
kvn@1077 335 CHECK_FAIL(err);
kvn@1077 336
duke@435 337 err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
duke@435 338 OFFSET_VirtualSpace_low, &J->CodeCache_low);
duke@435 339 CHECK_FAIL(err);
duke@435 340 err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
duke@435 341 OFFSET_VirtualSpace_high, &J->CodeCache_high);
duke@435 342 CHECK_FAIL(err);
duke@435 343 err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
duke@435 344 OFFSET_VirtualSpace_low, &J->CodeCache_segmap_low);
duke@435 345 CHECK_FAIL(err);
duke@435 346 err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
duke@435 347 OFFSET_VirtualSpace_high, &J->CodeCache_segmap_high);
duke@435 348 CHECK_FAIL(err);
duke@435 349
duke@435 350 err = ps_pread(J->P, J->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size,
duke@435 351 &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
duke@435 352 CHECK_FAIL(err);
duke@435 353
duke@435 354 return PS_OK;
duke@435 355
duke@435 356 fail:
duke@435 357 return err;
duke@435 358 }
duke@435 359
duke@435 360
duke@435 361 static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
duke@435 362 /* make sure the code cache is up to date */
duke@435 363 return (J->CodeCache_low <= ptr && ptr < J->CodeCache_high);
duke@435 364 }
duke@435 365
duke@435 366 static uint64_t segment_for(jvm_agent_t* J, uint64_t p) {
duke@435 367 return (p - J->CodeCache_low) >> J->SIZE_CodeCache_log2_segment;
duke@435 368 }
duke@435 369
duke@435 370 static uint64_t block_at(jvm_agent_t* J, int i) {
duke@435 371 return J->CodeCache_low + (i << J->SIZE_CodeCache_log2_segment);
duke@435 372 }
duke@435 373
duke@435 374 static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
duke@435 375 int err;
duke@435 376
duke@435 377 *startp = 0;
duke@435 378 if (J->CodeCache_low <= ptr && ptr < J->CodeCache_high) {
duke@435 379 int32_t used;
duke@435 380 uint64_t segment = segment_for(J, ptr);
duke@435 381 uint64_t block = J->CodeCache_segmap_low;
duke@435 382 uint8_t tag;
duke@435 383 err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
duke@435 384 CHECK_FAIL(err);
duke@435 385 if (tag == 0xff)
duke@435 386 return PS_OK;
duke@435 387 while (tag > 0) {
duke@435 388 err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
duke@435 389 CHECK_FAIL(err);
duke@435 390 segment -= tag;
duke@435 391 }
duke@435 392 block = block_at(J, segment);
duke@435 393 err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
duke@435 394 CHECK_FAIL(err);
duke@435 395 if (used) {
duke@435 396 *startp = block + SIZE_HeapBlockHeader;
duke@435 397 }
duke@435 398 }
duke@435 399 return PS_OK;
duke@435 400
duke@435 401 fail:
duke@435 402 return -1;
duke@435 403 }
duke@435 404
duke@435 405 static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
duke@435 406 psaddr_t sym_addr;
duke@435 407 int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
duke@435 408 if (err == PS_OK) {
duke@435 409 err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t));
duke@435 410 return err;
duke@435 411 }
duke@435 412 *valuep = -1;
duke@435 413 return -1;
duke@435 414 }
duke@435 415
duke@435 416 jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) {
duke@435 417 jvm_agent_t* J;
duke@435 418 int err;
duke@435 419
duke@435 420 if (vers != JVM_DB_VERSION) {
duke@435 421 errno = ENOTSUP;
duke@435 422 return NULL;
duke@435 423 }
duke@435 424
duke@435 425 J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1);
duke@435 426
duke@435 427 debug = getenv("LIBJVMDB_DEBUG") != NULL;
duke@435 428 if (debug) debug = 3;
duke@435 429
duke@435 430 if (debug) {
duke@435 431 fprintf(stderr, "Jagent_create: debug=%d\n", debug);
duke@435 432 #ifdef X86_COMPILER2
duke@435 433 fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE);
duke@435 434 #endif /* X86_COMPILER2 */
duke@435 435 }
duke@435 436
duke@435 437 J->P = P;
duke@435 438
duke@435 439 // Initialize the initial previous frame
duke@435 440
duke@435 441 J->prev_fr.fp = 0;
duke@435 442 J->prev_fr.pc = 0;
duke@435 443 J->prev_fr.sp = 0;
duke@435 444 J->prev_fr.sender_sp = 0;
duke@435 445
duke@435 446 err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl);
duke@435 447 CHECK_FAIL(err);
duke@435 448 err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl);
duke@435 449 if (err != PS_OK) J->BufferBlob_vtbl = 0;
duke@435 450 err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl);
duke@435 451 CHECK_FAIL(err);
duke@435 452 err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl);
duke@435 453 CHECK_FAIL(err);
coleenp@4037 454 err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl);
coleenp@4037 455 CHECK_FAIL(err);
duke@435 456
duke@435 457 err = parse_vmstructs(J);
duke@435 458 CHECK_FAIL(err);
duke@435 459 err = read_volatiles(J);
duke@435 460 CHECK_FAIL(err);
duke@435 461
duke@435 462 return J;
duke@435 463
duke@435 464 fail:
duke@435 465 Jagent_destroy(J);
duke@435 466 return NULL;
duke@435 467 }
duke@435 468
duke@435 469 void Jagent_destroy(jvm_agent_t *J) {
duke@435 470 if (J != NULL) {
duke@435 471 free(J);
duke@435 472 }
duke@435 473 }
duke@435 474
coleenp@4037 475 static int is_method(jvm_agent_t* J, uint64_t methodPtr) {
duke@435 476 uint64_t klass;
coleenp@4037 477 int err = read_pointer(J, methodPtr, &klass);
duke@435 478 if (err != PS_OK) goto fail;
coleenp@4037 479 return klass == J->Method_vtbl;
duke@435 480
duke@435 481 fail:
duke@435 482 return 0;
duke@435 483 }
duke@435 484
duke@435 485 static int
coleenp@4037 486 name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size)
duke@435 487 {
duke@435 488 short nameIndex;
duke@435 489 short signatureIndex;
duke@435 490 uint64_t constantPool;
duke@435 491 uint64_t constMethod;
duke@435 492 uint64_t nameSymbol;
duke@435 493 uint64_t signatureSymbol;
duke@435 494 uint64_t klassPtr;
duke@435 495 uint64_t klassSymbol;
duke@435 496 short klassSymbolLength;
duke@435 497 short nameSymbolLength;
duke@435 498 short signatureSymbolLength;
duke@435 499 char * nameString = NULL;
duke@435 500 char * klassString = NULL;
duke@435 501 char * signatureString = NULL;
duke@435 502 int err;
duke@435 503
coleenp@4037 504 err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod);
duke@435 505 CHECK_FAIL(err);
coleenp@4037 506 err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool);
duke@435 507 CHECK_FAIL(err);
duke@435 508
duke@435 509 /* To get name string */
coleenp@4037 510 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2);
duke@435 511 CHECK_FAIL(err);
coleenp@4037 512 err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol);
duke@435 513 CHECK_FAIL(err);
coleenp@2626 514 // The symbol is a CPSlot and has lower bit set to indicate metadata
coleenp@2626 515 nameSymbol &= (~1); // remove metadata lsb
coleenp@2497 516 err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
duke@435 517 CHECK_FAIL(err);
duke@435 518 nameString = (char*)calloc(nameSymbolLength + 1, 1);
coleenp@2497 519 err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
duke@435 520 CHECK_FAIL(err);
duke@435 521
duke@435 522 /* To get signature string */
coleenp@4037 523 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2);
duke@435 524 CHECK_FAIL(err);
coleenp@4037 525 err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol);
duke@435 526 CHECK_FAIL(err);
coleenp@2626 527 signatureSymbol &= (~1); // remove metadata lsb
coleenp@2497 528 err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
duke@435 529 CHECK_FAIL(err);
duke@435 530 signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
coleenp@2497 531 err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
duke@435 532 CHECK_FAIL(err);
duke@435 533
duke@435 534 /* To get klass string */
coleenp@4037 535 err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr);
duke@435 536 CHECK_FAIL(err);
coleenp@4037 537 err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol);
duke@435 538 CHECK_FAIL(err);
coleenp@2497 539 err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
duke@435 540 CHECK_FAIL(err);
duke@435 541 klassString = (char*)calloc(klassSymbolLength + 1, 1);
coleenp@2497 542 err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
duke@435 543 CHECK_FAIL(err);
duke@435 544
duke@435 545 result[0] = '\0';
aph@9920 546 if (snprintf(result, size,
aph@9920 547 "%s.%s%s",
aph@9920 548 klassString,
aph@9920 549 nameString,
aph@9920 550 signatureString) >= size) {
aph@9920 551 // truncation
aph@9920 552 goto fail;
aph@9920 553 }
duke@435 554
duke@435 555 if (nameString != NULL) free(nameString);
duke@435 556 if (klassString != NULL) free(klassString);
duke@435 557 if (signatureString != NULL) free(signatureString);
duke@435 558
duke@435 559 return PS_OK;
duke@435 560
duke@435 561 fail:
duke@435 562 if (debug) {
coleenp@4037 563 fprintf(stderr, "name_for_methodPtr: FAIL \n\n");
duke@435 564 }
duke@435 565 if (nameString != NULL) free(nameString);
duke@435 566 if (klassString != NULL) free(klassString);
duke@435 567 if (signatureString != NULL) free(signatureString);
duke@435 568 return -1;
duke@435 569 }
duke@435 570
duke@435 571 static int nmethod_info(Nmethod_t *N)
duke@435 572 {
duke@435 573 jvm_agent_t *J = N->J;
duke@435 574 uint64_t nm = N->nm;
duke@435 575 int32_t err;
duke@435 576
duke@435 577 if (debug > 2 )
duke@435 578 fprintf(stderr, "\t nmethod_info: BEGIN \n");
duke@435 579
duke@435 580 /* Instructions */
twisti@2103 581 err = ps_pread(J->P, nm + OFFSET_CodeBlob_code_offset, &N->instrs_beg, SZ32);
duke@435 582 CHECK_FAIL(err);
duke@435 583 err = ps_pread(J->P, nm + OFFSET_CodeBlob_data_offset, &N->instrs_end, SZ32);
duke@435 584 CHECK_FAIL(err);
duke@435 585 err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32);
duke@435 586 CHECK_FAIL(err);
duke@435 587 err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32);
duke@435 588 CHECK_FAIL(err);
duke@435 589
coleenp@4037 590 /* Metadata */
coleenp@4037 591 err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32);
duke@435 592 CHECK_FAIL(err);
coleenp@4037 593 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->metadata_end, SZ32);
duke@435 594 CHECK_FAIL(err);
duke@435 595
duke@435 596 /* scopes_pcs */
duke@435 597 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32);
duke@435 598 CHECK_FAIL(err);
duke@435 599 err = ps_pread(J->P, nm + OFFSET_nmethod_handler_table_offset, &N->scopes_pcs_end, SZ32);
duke@435 600 CHECK_FAIL(err);
duke@435 601
duke@435 602 /* scopes_data */
duke@435 603 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->scopes_data_beg, SZ32);
duke@435 604 CHECK_FAIL(err);
duke@435 605
duke@435 606 if (debug > 2 ) {
duke@435 607 N->scopes_data_end = N->scopes_pcs_beg;
duke@435 608
duke@435 609 fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n",
duke@435 610 N->instrs_beg, N->instrs_end);
duke@435 611
duke@435 612 fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n",
duke@435 613 N->deopt_beg);
duke@435 614
duke@435 615 fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
duke@435 616 N->orig_pc_offset);
duke@435 617
coleenp@4037 618 fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n",
coleenp@4037 619 N->metadata_beg, N->metadata_end);
duke@435 620
duke@435 621 fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
duke@435 622 N->scopes_data_beg, N->scopes_data_end);
duke@435 623
duke@435 624 fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n",
duke@435 625 N->scopes_pcs_beg, N->scopes_pcs_end);
duke@435 626
duke@435 627 fprintf(stderr, "\t nmethod_info: END \n\n");
duke@435 628 }
duke@435 629 return PS_OK;
duke@435 630
duke@435 631 fail:
duke@435 632 return err;
duke@435 633 }
duke@435 634
duke@435 635 static int
duke@435 636 raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val)
duke@435 637 {
duke@435 638 int shift = 0;
duke@435 639 int value = 0;
duke@435 640 uint8_t ch = 0;
duke@435 641 int32_t err;
duke@435 642 int32_t sum;
duke@435 643 // Constants for UNSIGNED5 coding of Pack200
duke@435 644 // see compressedStream.hpp
duke@435 645 enum {
duke@435 646 lg_H = 6,
duke@435 647 H = 1<<lg_H,
duke@435 648 BitsPerByte = 8,
duke@435 649 L = (1<<BitsPerByte)-H,
duke@435 650 };
duke@435 651 int i;
duke@435 652
duke@435 653 err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
duke@435 654 CHECK_FAIL(err);
duke@435 655 if (debug > 2)
duke@435 656 fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch);
duke@435 657
duke@435 658 sum = ch;
duke@435 659 if ( sum >= L ) {
duke@435 660 int32_t lg_H_i = lg_H;
duke@435 661 // Read maximum of 5 total bytes (we've already read 1).
duke@435 662 // See CompressedReadStream::read_int_mb
duke@435 663 for ( i = 0; i < 4; i++) {
duke@435 664 err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
duke@435 665 CHECK_FAIL(err);
duke@435 666 sum += ch << lg_H_i;
duke@435 667 if (ch < L ) {
duke@435 668 *val = sum;
duke@435 669 return PS_OK;
duke@435 670 }
duke@435 671 lg_H_i += lg_H;
duke@435 672 }
duke@435 673 }
duke@435 674 *val = sum;
duke@435 675 return PS_OK;
duke@435 676
duke@435 677 fail:
duke@435 678 return err;
duke@435 679 }
duke@435 680
duke@435 681 static int
duke@435 682 read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line)
duke@435 683 {
duke@435 684 uint8_t next = 0;
duke@435 685 int32_t bci_delta;
duke@435 686 int32_t line_delta;
duke@435 687 int32_t err;
duke@435 688
duke@435 689 if (debug > 2)
duke@435 690 fprintf(stderr, "\t\t read_pair: BEGIN\n");
duke@435 691
duke@435 692 err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t));
duke@435 693 CHECK_FAIL(err);
duke@435 694
duke@435 695 if (next == 0) {
duke@435 696 if (debug > 2)
duke@435 697 fprintf(stderr, "\t\t read_pair: END: next == 0\n");
duke@435 698 return 1; /* stream terminated */
duke@435 699 }
duke@435 700 if (next == 0xFF) {
duke@435 701 if (debug > 2)
duke@435 702 fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n");
duke@435 703
duke@435 704 /* Escape character, regular compression used */
duke@435 705
duke@435 706 err = raw_read_int(J, buffer, &bci_delta);
duke@435 707 CHECK_FAIL(err);
duke@435 708
duke@435 709 err = raw_read_int(J, buffer, &line_delta);
duke@435 710 CHECK_FAIL(err);
duke@435 711
duke@435 712 *bci += bci_delta;
duke@435 713 *line += line_delta;
duke@435 714
duke@435 715 if (debug > 2) {
duke@435 716 fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
duke@435 717 line_delta, bci_delta);
duke@435 718 fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
duke@435 719 *line, *bci);
duke@435 720 }
duke@435 721 } else {
duke@435 722 /* Single byte compression used */
duke@435 723 *bci += next >> 3;
duke@435 724 *line += next & 0x7;
duke@435 725 if (debug > 2) {
duke@435 726 fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
duke@435 727 next & 0x7, next >> 3);
duke@435 728 fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
duke@435 729 *line, *bci);
duke@435 730 }
duke@435 731 }
duke@435 732 if (debug > 2)
duke@435 733 fprintf(stderr, "\t\t read_pair: END\n");
duke@435 734 return PS_OK;
duke@435 735
duke@435 736 fail:
duke@435 737 if (debug)
duke@435 738 fprintf(stderr, "\t\t read_pair: FAIL\n");
duke@435 739 return err;
duke@435 740 }
duke@435 741
duke@435 742 static int
duke@435 743 line_number_from_bci(jvm_agent_t* J, Vframe_t *vf)
duke@435 744 {
duke@435 745 uint64_t buffer;
duke@435 746 uint16_t code_size;
duke@435 747 uint64_t code_end_delta;
duke@435 748 uint64_t constMethod;
duke@435 749 int8_t access_flags;
duke@435 750 int32_t best_bci = 0;
duke@435 751 int32_t stream_bci = 0;
duke@435 752 int32_t stream_line = 0;
duke@435 753 int32_t err;
duke@435 754
duke@435 755 if (debug > 2) {
duke@435 756 char name[256];
coleenp@4037 757 err = name_for_methodPtr(J, vf->method, name, 256);
duke@435 758 CHECK_FAIL(err);
duke@435 759 fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n",
duke@435 760 name, vf->bci);
duke@435 761 }
duke@435 762
coleenp@4037 763 err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod);
duke@435 764 CHECK_FAIL(err);
duke@435 765
duke@435 766 vf->line = 0;
coleenp@4037 767 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t));
duke@435 768 CHECK_FAIL(err);
duke@435 769
coleenp@4037 770 if (!(access_flags & ConstMethod_has_linenumber_table)) {
duke@435 771 if (debug > 2)
duke@435 772 fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n");
duke@435 773 return PS_OK;
duke@435 774 }
duke@435 775
duke@435 776 /* The line numbers are a short array of 2-tuples [start_pc, line_number].
duke@435 777 * Not necessarily sorted and not necessarily one-to-one.
duke@435 778 */
duke@435 779
coleenp@4037 780 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16);
duke@435 781 CHECK_FAIL(err);
duke@435 782
duke@435 783 /* inlined_table_start() */
duke@435 784 code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0;
coleenp@4037 785 buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta;
duke@435 786
duke@435 787 if (debug > 2) {
coleenp@4037 788 fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n",
coleenp@4037 789 vf->method, (access_flags & AccessFlags_NATIVE));
duke@435 790 fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n",
duke@435 791 buffer, (int) code_size);
duke@435 792 }
duke@435 793
duke@435 794 while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) {
duke@435 795 if (stream_bci == vf->bci) {
duke@435 796 /* perfect match */
duke@435 797 if (debug > 2)
duke@435 798 fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line);
duke@435 799 vf->line = stream_line;
duke@435 800 return PS_OK;
duke@435 801 } else {
duke@435 802 /* update best_bci/line */
duke@435 803 if (stream_bci < vf->bci && stream_bci >= best_bci) {
duke@435 804 best_bci = stream_bci;
duke@435 805 vf->line = stream_line;
duke@435 806 if (debug > 2) {
duke@435 807 fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n",
duke@435 808 best_bci, vf->line);
duke@435 809 }
duke@435 810 }
duke@435 811 }
duke@435 812 }
duke@435 813 if (debug > 2)
duke@435 814 fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line);
duke@435 815 return PS_OK;
duke@435 816
duke@435 817 fail:
duke@435 818 if (debug)
duke@435 819 fprintf(stderr, "\t line_number_from_bci: FAIL\n");
duke@435 820 return err;
duke@435 821 }
duke@435 822
duke@435 823 static int
duke@435 824 get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc)
duke@435 825 {
duke@435 826 int32_t pc_offset;
duke@435 827 int32_t err;
duke@435 828
duke@435 829 err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32);
duke@435 830 CHECK_FAIL(err);
duke@435 831
duke@435 832 *real_pc = N->nm + N->instrs_beg + pc_offset;
duke@435 833 if (debug > 2) {
duke@435 834 fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n",
duke@435 835 pc_offset, *real_pc);
duke@435 836 }
duke@435 837 return PS_OK;
duke@435 838
duke@435 839 fail:
duke@435 840 return err;
duke@435 841 }
duke@435 842
duke@435 843 /* Finds a PcDesc with real-pc equal to N->pc */
duke@435 844 static int pc_desc_at(Nmethod_t *N)
duke@435 845 {
duke@435 846 uint64_t pc_diff;
duke@435 847 int32_t offs;
duke@435 848 int32_t err;
duke@435 849
duke@435 850 if (debug > 2)
duke@435 851 fprintf(stderr, "\t pc_desc_at: BEGIN\n");
duke@435 852
duke@435 853 N->vf_cnt = 0;
duke@435 854 N->pc_desc = 0;
duke@435 855
duke@435 856 for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) {
duke@435 857 uint64_t pd;
duke@435 858 uint64_t best_pc_diff = 16; /* some approximation */
duke@435 859 uint64_t real_pc = 0;
duke@435 860
duke@435 861 pd = N->nm + offs;
duke@435 862 err = get_real_pc(N, pd, &real_pc);
duke@435 863 CHECK_FAIL(err);
duke@435 864
duke@435 865 pc_diff = real_pc - N->pc;
duke@435 866
duke@435 867 /* In general, this fragment should work */
duke@435 868 if (pc_diff == 0) {
duke@435 869 N->pc_desc = pd;
duke@435 870 if (debug) {
duke@435 871 fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd);
duke@435 872 }
duke@435 873 return PS_OK;
duke@435 874 }
duke@435 875 /* This fragment is to be able to find out an appropriate
duke@435 876 * pc_desc entry even if pc_desc info is inaccurate.
duke@435 877 */
duke@435 878 if (best_pc_diff > pc_diff && pc_diff > 0) {
duke@435 879 best_pc_diff = pc_diff;
duke@435 880 N->pc_desc = pd;
duke@435 881 }
duke@435 882 }
duke@435 883 if (debug) {
duke@435 884 fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND");
duke@435 885 if (pc_diff < 20)
duke@435 886 fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff);
duke@435 887 else
duke@435 888 fprintf(stderr, "\n\n");
duke@435 889 }
duke@435 890 return PS_OK;
duke@435 891
duke@435 892 fail:
duke@435 893 return err;
duke@435 894 }
duke@435 895
duke@435 896 static int
duke@435 897 scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf)
duke@435 898 {
duke@435 899 uint64_t buffer;
duke@435 900 int32_t err;
duke@435 901
duke@435 902 if (debug > 2) {
duke@435 903 fprintf(stderr, "\t\t scope_desc_at: BEGIN \n");
duke@435 904 }
duke@435 905
duke@435 906 buffer = N->nm + N->scopes_data_beg + decode_offset;
duke@435 907
duke@435 908 err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset);
duke@435 909 CHECK_FAIL(err);
duke@435 910
duke@435 911 err = raw_read_int(N->J, &buffer, &vf->methodIdx);
duke@435 912 CHECK_FAIL(err);
duke@435 913
duke@435 914 err = raw_read_int(N->J, &buffer, &vf->bci);
duke@435 915 CHECK_FAIL(err);
duke@435 916
duke@435 917 if (debug > 2) {
duke@435 918 fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n",
duke@435 919 vf->sender_decode_offset);
duke@435 920 fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx);
duke@435 921 fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci);
duke@435 922
duke@435 923 fprintf(stderr, "\t\t scope_desc_at: END \n\n");
duke@435 924 }
duke@435 925 return PS_OK;
duke@435 926
duke@435 927 fail:
duke@435 928 return err;
duke@435 929 }
duke@435 930
phh@1558 931 static int scopeDesc_chain(Nmethod_t *N) {
duke@435 932 int32_t decode_offset = 0;
duke@435 933 int32_t err;
duke@435 934
phh@1558 935 if (debug > 2) {
phh@1558 936 fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
phh@1558 937 }
duke@435 938
duke@435 939 err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
duke@435 940 &decode_offset, SZ32);
duke@435 941 CHECK_FAIL(err);
duke@435 942
duke@435 943 while (decode_offset > 0) {
phh@1558 944 Vframe_t *vf = &N->vframes[N->vf_cnt];
duke@435 945
phh@1558 946 if (debug > 2) {
phh@1558 947 fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
phh@1558 948 }
duke@435 949
phh@1558 950 err = scope_desc_at(N, decode_offset, vf);
phh@1558 951 CHECK_FAIL(err);
phh@1558 952
coleenp@4037 953 if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) {
coleenp@4037 954 fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n");
phh@1558 955 return -1;
phh@1558 956 }
coleenp@4037 957 err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE,
coleenp@4037 958 &vf->method);
phh@1558 959 CHECK_FAIL(err);
phh@1558 960
coleenp@4037 961 if (vf->method) {
phh@1558 962 N->vf_cnt++;
phh@1558 963 err = line_number_from_bci(N->J, vf);
duke@435 964 CHECK_FAIL(err);
phh@1558 965 if (debug > 2) {
coleenp@4037 966 fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n",
coleenp@4037 967 vf->method, vf->line);
duke@435 968 }
phh@1558 969 }
phh@1558 970 decode_offset = vf->sender_decode_offset;
duke@435 971 }
phh@1558 972 if (debug > 2) {
phh@1558 973 fprintf(stderr, "\t scopeDesc_chain: END \n\n");
phh@1558 974 }
duke@435 975 return PS_OK;
duke@435 976
duke@435 977 fail:
phh@1558 978 if (debug) {
phh@1558 979 fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
phh@1558 980 }
duke@435 981 return err;
duke@435 982 }
duke@435 983
duke@435 984
duke@435 985 static int
duke@435 986 name_for_nmethod(jvm_agent_t* J,
duke@435 987 uint64_t nm,
duke@435 988 uint64_t pc,
coleenp@4037 989 uint64_t method,
duke@435 990 char *result,
duke@435 991 size_t size,
duke@435 992 Jframe_t *jframe
duke@435 993 ) {
duke@435 994 Nmethod_t *N;
duke@435 995 Vframe_t *vf;
duke@435 996 int32_t err;
duke@435 997 int deoptimized = 0;
duke@435 998
duke@435 999 if (debug) {
duke@435 1000 fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
duke@435 1001 }
duke@435 1002 if (J->N == NULL) {
duke@435 1003 J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
duke@435 1004 }
duke@435 1005 memset(J->N, 0, sizeof(Nmethod_t)); /* Initial stat: all values are zeros */
duke@435 1006 N = J->N;
duke@435 1007 N->J = J;
duke@435 1008 N->nm = nm;
duke@435 1009 N->pc = pc;
duke@435 1010 N->jframe = jframe;
duke@435 1011
duke@435 1012 err = nmethod_info(N);
duke@435 1013 CHECK_FAIL(err);
duke@435 1014 if (debug) {
duke@435 1015 fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc: %#llx\n",
duke@435 1016 pc, N->nm + N->deopt_beg);
duke@435 1017 }
duke@435 1018
duke@435 1019 /* check for a deoptimized frame */
duke@435 1020 if ( pc == N->nm + N->deopt_beg) {
duke@435 1021 uint64_t base;
duke@435 1022 if (debug) {
duke@435 1023 fprintf(stderr, "name_for_nmethod: found deoptimized frame\n");
duke@435 1024 }
duke@435 1025 if (J->prev_fr.sender_sp != 0) {
duke@435 1026 base = J->prev_fr.sender_sp + N->orig_pc_offset;
duke@435 1027 } else {
duke@435 1028 base = J->curr_fr.sp + N->orig_pc_offset;
duke@435 1029 }
duke@435 1030 err = read_pointer(J, base, &N->pc);
duke@435 1031 CHECK_FAIL(err);
duke@435 1032 if (debug) {
duke@435 1033 fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n",
duke@435 1034 pc, N->pc);
duke@435 1035 }
duke@435 1036 deoptimized = 1;
duke@435 1037 }
duke@435 1038
duke@435 1039 err = pc_desc_at(N);
duke@435 1040 CHECK_FAIL(err);
duke@435 1041
duke@435 1042 if (N->pc_desc > 0) {
duke@435 1043 jframe->locinf = 1;
duke@435 1044 err = scopeDesc_chain(N);
duke@435 1045 CHECK_FAIL(err);
duke@435 1046 }
duke@435 1047 result[0] = COMP_METHOD_SIGN;
duke@435 1048 vf = &N->vframes[0];
duke@435 1049 if (N->vf_cnt > 0) {
duke@435 1050 jframe->vf_cnt = N->vf_cnt;
duke@435 1051 jframe->bci = vf->bci;
duke@435 1052 jframe->line = vf->line;
coleenp@4037 1053 err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1);
duke@435 1054 CHECK_FAIL(err);
duke@435 1055 } else {
coleenp@4037 1056 err = name_for_methodPtr(J, method, result+1, size-1);
duke@435 1057 CHECK_FAIL(err);
duke@435 1058 }
duke@435 1059 if (deoptimized) {
aph@9920 1060 strncat(result, " [deoptimized frame]; ", size - strlen(result) - 1);
duke@435 1061 } else {
aph@9920 1062 strncat(result, " [compiled] ", size - strlen(result) - 1);
duke@435 1063 }
duke@435 1064 if (debug)
duke@435 1065 fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
duke@435 1066 result, N->vf_cnt);
duke@435 1067 return PS_OK;
duke@435 1068
duke@435 1069 fail:
duke@435 1070 if (debug)
duke@435 1071 fprintf(stderr, "name_for_nmethod: FAIL \n\n");
duke@435 1072 return err;
duke@435 1073 }
duke@435 1074
duke@435 1075 int is_bci(intptr_t bcx) {
duke@435 1076 switch (DATA_MODEL) {
duke@435 1077 case PR_MODEL_LP64:
duke@435 1078 return ((uintptr_t) bcx) <= ((uintptr_t) MAX_METHOD_CODE_SIZE) ;
duke@435 1079 case PR_MODEL_ILP32:
duke@435 1080 default:
duke@435 1081 return 0 <= bcx && bcx <= MAX_METHOD_CODE_SIZE;
duke@435 1082 }
duke@435 1083 }
duke@435 1084
duke@435 1085 static int
duke@435 1086 name_for_imethod(jvm_agent_t* J,
duke@435 1087 uint64_t bcx,
coleenp@4037 1088 uint64_t method,
duke@435 1089 char *result,
duke@435 1090 size_t size,
duke@435 1091 Jframe_t *jframe
duke@435 1092 ) {
duke@435 1093 uint64_t bci;
duke@435 1094 uint64_t constMethod;
duke@435 1095 Vframe_t vframe = {0};
duke@435 1096 Vframe_t *vf = &vframe;
duke@435 1097 int32_t err;
duke@435 1098
coleenp@4037 1099 err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod);
duke@435 1100 CHECK_FAIL(err);
duke@435 1101
coleenp@4037 1102 bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_ConstMethod);
duke@435 1103
duke@435 1104 if (debug)
coleenp@4037 1105 fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method);
duke@435 1106
coleenp@4037 1107 err = name_for_methodPtr(J, method, result, size);
duke@435 1108 CHECK_FAIL(err);
duke@435 1109 if (debug)
duke@435 1110 fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
duke@435 1111
duke@435 1112 if (bci > 0) {
coleenp@4037 1113 vf->method = method;
duke@435 1114 vf->bci = bci;
duke@435 1115 err = line_number_from_bci(J, vf);
duke@435 1116 CHECK_FAIL(err);
duke@435 1117 }
duke@435 1118 jframe->bci = vf->bci;
duke@435 1119 jframe->line = vf->line;
duke@435 1120 jframe->locinf = 1;
duke@435 1121
duke@435 1122 if (debug) {
duke@435 1123 fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
duke@435 1124 vf->bci, vf->line);
duke@435 1125 }
duke@435 1126 return PS_OK;
duke@435 1127
duke@435 1128 fail:
duke@435 1129 if (debug)
duke@435 1130 fprintf(stderr, "\t name_for_imethod: FAIL\n");
duke@435 1131 return err;
duke@435 1132 }
duke@435 1133
duke@435 1134 static int
duke@435 1135 name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
duke@435 1136 size_t size, Jframe_t *jframe, int* is_interpreted)
duke@435 1137 {
duke@435 1138 uint64_t start;
duke@435 1139 uint64_t vtbl;
duke@435 1140 int32_t err;
duke@435 1141 *is_interpreted = 0;
duke@435 1142
duke@435 1143 result[0] = '\0';
duke@435 1144
duke@435 1145 err = find_start(J, pc, &start);
duke@435 1146 CHECK_FAIL(err);
duke@435 1147
duke@435 1148 err = read_pointer(J, start, &vtbl);
duke@435 1149 CHECK_FAIL(err);
duke@435 1150
duke@435 1151 if (vtbl == J->nmethod_vtbl) {
coleenp@4037 1152 uint64_t method;
duke@435 1153
coleenp@4037 1154 err = read_pointer(J, start + OFFSET_nmethod_method, &method);
duke@435 1155 CHECK_FAIL(err);
duke@435 1156
duke@435 1157 if (debug) {
coleenp@4037 1158 fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n",
coleenp@4037 1159 start, pc, method);
duke@435 1160 }
coleenp@4037 1161 err = name_for_nmethod(J, start, pc, method, result, size, jframe);
duke@435 1162 CHECK_FAIL(err);
duke@435 1163 } else if (vtbl == J->BufferBlob_vtbl) {
duke@435 1164 const char * name;
duke@435 1165
duke@435 1166 err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
duke@435 1167
duke@435 1168 /*
duke@435 1169 * Temporary usage of string "Interpreter".
duke@435 1170 * We need some other way to distinguish "StubRoutines"
duke@435 1171 * and regular interpreted frames.
duke@435 1172 */
duke@435 1173 if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
duke@435 1174 *is_interpreted = 1;
coleenp@4037 1175 if (is_method(J, J->methodPtr)) {
coleenp@4037 1176 return name_for_imethod(J, J->bcx, J->methodPtr, result, size, jframe);
duke@435 1177 }
duke@435 1178 }
duke@435 1179
duke@435 1180 if (err == PS_OK) {
duke@435 1181 strncpy(result, name, size);
duke@435 1182 free((void*)name);
duke@435 1183 } else {
duke@435 1184 strncpy(result, "<unknown BufferBlob>", size);
duke@435 1185 }
duke@435 1186 /* return PS_OK; */
duke@435 1187 } else {
duke@435 1188 const char * name;
duke@435 1189
duke@435 1190 err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
duke@435 1191 if (err == PS_OK) {
duke@435 1192 strncpy(result, name, size);
duke@435 1193 free((void*)name);
duke@435 1194 } else {
duke@435 1195 strncpy(result, "<unknown CodeBlob>", size);
duke@435 1196 WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);
duke@435 1197 }
duke@435 1198 }
duke@435 1199 result[size-1] = '\0';
duke@435 1200
duke@435 1201 #ifdef X86_COMPILER2
duke@435 1202 if (vtbl != J->RuntimeStub_vtbl) {
duke@435 1203 uint64_t trial_pc;
duke@435 1204 int frame_size;
duke@435 1205 err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size,
duke@435 1206 &frame_size, SZ32);
duke@435 1207 CHECK_FAIL(err);
duke@435 1208
duke@435 1209 // frame_size is in words, we want bytes.
duke@435 1210 frame_size *= POINTER_SIZE; /* word => byte conversion */
duke@435 1211
duke@435 1212 /*
duke@435 1213 Because c2 doesn't use FP as a framepointer the value of sp/fp we receive
duke@435 1214 in the initial entry to a set of stack frames containing server frames
duke@435 1215 will pretty much be nonsense. We can detect that nonsense by looking to
duke@435 1216 see if the PC we received is correct if we look at the expected storage
duke@435 1217 location in relation to the FP (ie. POINTER_SIZE(FP) )
duke@435 1218 */
duke@435 1219
duke@435 1220 err = read_pointer(J, fp + POINTER_SIZE , &trial_pc);
duke@435 1221 if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) {
duke@435 1222 // Either we couldn't even read at the "fp" or the pc didn't match
duke@435 1223 // both are sure clues that the fp is bogus. We no search the stack
duke@435 1224 // for a reasonable number of words trying to find the bogus fp
duke@435 1225 // and the current pc in adjacent words. The we will be able to
duke@435 1226 // deduce an approximation of the frame pointer and actually get
duke@435 1227 // the correct stack pointer. Which we can then unwind for the
duke@435 1228 // next frame.
duke@435 1229 int i;
duke@435 1230 uint64_t check;
duke@435 1231 uint64_t base = J->curr_fr.sp;
duke@435 1232 uint64_t prev_fp = 0;
duke@435 1233 for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) {
duke@435 1234 err = read_pointer(J, base , &check);
duke@435 1235 CHECK_FAIL(err);
duke@435 1236 if (check == fp) {
duke@435 1237 base += POINTER_SIZE;
duke@435 1238 err = read_pointer(J, base , &check);
duke@435 1239 CHECK_FAIL(err);
duke@435 1240 if (check == pc) {
duke@435 1241 if (debug) {
duke@435 1242 fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE);
duke@435 1243 }
duke@435 1244 prev_fp = base - 2 * POINTER_SIZE;
duke@435 1245 break;
duke@435 1246 }
duke@435 1247 }
duke@435 1248 }
duke@435 1249 if ( prev_fp != 0 ) {
duke@435 1250 // real_sp is the sp we should have received for this frame
duke@435 1251 uint64_t real_sp = prev_fp + 2 * POINTER_SIZE;
duke@435 1252 // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word
duke@435 1253 jframe->new_sp = real_sp + frame_size + POINTER_SIZE;
duke@435 1254 err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc);
duke@435 1255 CHECK_FAIL(err);
duke@435 1256 err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp);
duke@435 1257 CHECK_FAIL(err);
duke@435 1258 return PS_OK;
duke@435 1259 }
duke@435 1260 }
duke@435 1261
duke@435 1262 /* A prototype to workaround FP absence */
duke@435 1263 /*
duke@435 1264 * frame_size can be 0 for StubRoutines (1) frame.
duke@435 1265 * In this case it should work with fp as usual.
duke@435 1266 */
duke@435 1267 if (frame_size > 0) {
duke@435 1268 jframe->new_fp = J->prev_fr.fp + frame_size;
duke@435 1269 jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE;
duke@435 1270 } else {
duke@435 1271 memset(&J->curr_fr, 0, sizeof(Frame_t));
duke@435 1272 err = read_pointer(J, fp, &jframe->new_fp);
duke@435 1273 CHECK_FAIL(err);
duke@435 1274
duke@435 1275 err = read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
duke@435 1276 CHECK_FAIL(err);
duke@435 1277 }
duke@435 1278 if (debug) {
duke@435 1279 fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n",
duke@435 1280 result, frame_size);
duke@435 1281 fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n",
duke@435 1282 J->prev_fr.fp, jframe->new_fp);
duke@435 1283 }
duke@435 1284 }
duke@435 1285 #endif /* X86_COMPILER2 */
duke@435 1286
duke@435 1287 return PS_OK;
duke@435 1288
duke@435 1289 fail:
duke@435 1290 return err;
duke@435 1291 }
duke@435 1292
duke@435 1293 int Jget_vframe(jvm_agent_t* J, int vframe_no,
duke@435 1294 char *name, size_t size, Jframe_t *jframe)
duke@435 1295 {
duke@435 1296 Nmethod_t *N = J->N;
duke@435 1297 Vframe_t *vf;
duke@435 1298 int32_t err;
duke@435 1299
duke@435 1300 if (vframe_no >= N->vf_cnt) {
duke@435 1301 (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
duke@435 1302 return -1;
duke@435 1303 }
duke@435 1304 vf = N->vframes + vframe_no;
duke@435 1305 name[0] = COMP_METHOD_SIGN;
coleenp@4037 1306 err = name_for_methodPtr(J, vf->method, name + 1, size);
duke@435 1307 CHECK_FAIL(err);
duke@435 1308
duke@435 1309 jframe->bci = vf->bci;
duke@435 1310 jframe->line = vf->line;
duke@435 1311 if (debug) {
duke@435 1312 fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n",
duke@435 1313 name, vf->line);
duke@435 1314 }
duke@435 1315 return PS_OK;
duke@435 1316
duke@435 1317 fail:
duke@435 1318 if (debug) {
duke@435 1319 fprintf(stderr, "\t Jget_vframe: FAIL\n");
duke@435 1320 }
duke@435 1321 return err;
duke@435 1322 }
duke@435 1323
duke@435 1324 #define MAX_SYM_SIZE 256
duke@435 1325
duke@435 1326 int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
duke@435 1327 size_t size, Jframe_t *jframe) {
duke@435 1328 uintptr_t fp;
duke@435 1329 uintptr_t pc;
duke@435 1330 /* arguments given to read_pointer need to be worst case sized */
coleenp@4037 1331 uint64_t methodPtr = 0;
duke@435 1332 uint64_t sender_sp;
duke@435 1333 uint64_t bcx = 0;
duke@435 1334 int is_interpreted = 0;
duke@435 1335 int result = PS_OK;
duke@435 1336 int err = PS_OK;
duke@435 1337
duke@435 1338 if (J == NULL) {
duke@435 1339 return -1;
duke@435 1340 }
duke@435 1341
duke@435 1342 jframe->vf_cnt = 1;
duke@435 1343 jframe->new_fp = 0;
duke@435 1344 jframe->new_pc = 0;
duke@435 1345 jframe->line = 0;
duke@435 1346 jframe->bci = 0;
duke@435 1347 jframe->locinf = 0;
duke@435 1348
duke@435 1349 read_volatiles(J);
duke@435 1350 pc = (uintptr_t) regs[R_PC];
duke@435 1351 J->curr_fr.pc = pc;
duke@435 1352 J->curr_fr.fp = regs[R_FP];
duke@435 1353 J->curr_fr.sp = regs[R_SP];
duke@435 1354
duke@435 1355 if (debug)
duke@435 1356 fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
duke@435 1357
duke@435 1358 #if defined(sparc) || defined(__sparc)
duke@435 1359 /* The following workaround is for SPARC. CALL instruction occupates 8 bytes.
duke@435 1360 * In the pcDesc structure return pc offset is recorded for CALL instructions.
duke@435 1361 * regs[R_PC] contains a CALL instruction pc offset.
duke@435 1362 */
duke@435 1363 pc += 8;
duke@435 1364 bcx = (uintptr_t) regs[R_L1];
coleenp@4037 1365 methodPtr = (uintptr_t) regs[R_L2];
duke@435 1366 sender_sp = regs[R_I5];
duke@435 1367 if (debug > 2) {
duke@435 1368 fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n",
duke@435 1369 regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]);
duke@435 1370 }
duke@435 1371 #elif defined(i386) || defined(__i386) || defined(__amd64)
duke@435 1372
duke@435 1373 fp = (uintptr_t) regs[R_FP];
duke@435 1374 if (J->prev_fr.fp == 0) {
duke@435 1375 #ifdef X86_COMPILER2
duke@435 1376 /* A workaround for top java frames */
duke@435 1377 J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
duke@435 1378 #else
duke@435 1379 J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
duke@435 1380 #endif /* COMPILER2 */
duke@435 1381 }
duke@435 1382 if (debug > 2) {
duke@435 1383 printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
duke@435 1384 }
duke@435 1385
coleenp@4037 1386 if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) {
coleenp@4037 1387 methodPtr = 0;
duke@435 1388 }
duke@435 1389 if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
duke@435 1390 sender_sp = 0;
duke@435 1391 }
duke@435 1392 if (read_pointer(J, fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) {
duke@435 1393 bcx = 0;
duke@435 1394 }
duke@435 1395 #endif /* i386 */
duke@435 1396
coleenp@4037 1397 J->methodPtr = methodPtr;
duke@435 1398 J->bcx = bcx;
duke@435 1399
duke@435 1400 /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
duke@435 1401 * For example: JVM_SuspendThread frame poins to the top interpreted frame.
coleenp@4037 1402 * If we call is_method(J, methodPtr) before codecache_contains(J, pc)
duke@435 1403 * then we go over and omit both: nmethod and I2CAdapter frames.
duke@435 1404 * Note, that regs[R_PC] is always correct if frame defined correctly.
duke@435 1405 * So it is better to call codecache_contains(J, pc) from the beginning.
duke@435 1406 */
duke@435 1407 #ifndef X86_COMPILER2
coleenp@4037 1408 if (is_method(J, J->methodPtr)) {
coleenp@4037 1409 result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe);
coleenp@4037 1410 /* If the methodPtr is a method then this is highly likely to be
duke@435 1411 an interpreter frame */
duke@435 1412 if (result >= 0) {
duke@435 1413 is_interpreted = 1;
duke@435 1414 }
duke@435 1415 } else
duke@435 1416 #endif /* ! X86_COMPILER2 */
duke@435 1417
duke@435 1418 if (codecache_contains(J, pc)) {
duke@435 1419 result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
duke@435 1420 }
duke@435 1421 #ifdef X86_COMPILER2
coleenp@4037 1422 else if (is_method(J, J->methodPtr)) {
coleenp@4037 1423 result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe);
coleenp@4037 1424 /* If the methodPtr is a method then this is highly likely to be
duke@435 1425 an interpreter frame */
duke@435 1426 if (result >= 0) {
duke@435 1427 is_interpreted = 1;
duke@435 1428 }
duke@435 1429 }
duke@435 1430 #endif /* X86_COMPILER2 */
duke@435 1431 else {
duke@435 1432 if (debug) {
duke@435 1433 fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
duke@435 1434 }
duke@435 1435 result = -1;
duke@435 1436 }
duke@435 1437 if (!is_interpreted) {
duke@435 1438 sender_sp = 0;
duke@435 1439 }
duke@435 1440 J->curr_fr.sender_sp = sender_sp;
duke@435 1441
duke@435 1442 #ifdef X86_COMPILER2
duke@435 1443 if (!J->curr_fr.fp) {
duke@435 1444 J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP];
duke@435 1445 }
duke@435 1446 if (!jframe->new_pc && jframe->new_fp) {
duke@435 1447 // This seems dubious
duke@435 1448 read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
duke@435 1449 CHECK_FAIL(err);
duke@435 1450 if (debug > 2) {
duke@435 1451 printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n",
duke@435 1452 jframe->new_fp, jframe->new_pc);
duke@435 1453 }
duke@435 1454 }
duke@435 1455
duke@435 1456 #endif /* X86_COMPILER2 */
duke@435 1457 J->prev_fr = J->curr_fr;
duke@435 1458
duke@435 1459 if (debug)
duke@435 1460 fprintf(stderr, "Jlookup_by_regs: END\n\n");
duke@435 1461
duke@435 1462 return result;
duke@435 1463
duke@435 1464 fail:
duke@435 1465 return err;
duke@435 1466 }
duke@435 1467
duke@435 1468 void update_gregs(prgregset_t gregs, Jframe_t jframe) {
duke@435 1469 #ifdef X86_COMPILER2
duke@435 1470 if (debug > 0) {
duke@435 1471 fprintf(stderr, "update_gregs: before update sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
duke@435 1472 }
duke@435 1473 /*
duke@435 1474 * A workaround for java C2 frames with unconventional FP.
duke@435 1475 * may have to modify regset with new values for FP/PC/SP when needed.
duke@435 1476 */
duke@435 1477 if (jframe.new_sp) {
duke@435 1478 *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp;
duke@435 1479 } else {
duke@435 1480 // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE;
duke@435 1481 }
duke@435 1482
duke@435 1483 if (jframe.new_fp) {
duke@435 1484 *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
duke@435 1485 }
duke@435 1486 if (jframe.new_pc) {
duke@435 1487 *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
duke@435 1488 }
duke@435 1489 if (debug > 0) {
duke@435 1490 fprintf(stderr, "update_gregs: after update sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
duke@435 1491 }
duke@435 1492 #endif /* X86_COMPILER2 */
duke@435 1493 }
duke@435 1494
duke@435 1495 /*
duke@435 1496 * Iterates over java frames at current location given by 'gregs'.
duke@435 1497 *
duke@435 1498 * Returns -1 if no java frames are present or if an error is encountered.
duke@435 1499 * Returns the result of calling 'func' if the return value is non-zero.
duke@435 1500 * Returns 0 otherwise.
duke@435 1501 */
duke@435 1502 int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) {
duke@435 1503 char buf[MAX_SYM_SIZE + 1];
duke@435 1504 Jframe_t jframe;
duke@435 1505 int i = 0, res;
duke@435 1506 #ifdef X86_COMPILER2
duke@435 1507 if (debug > 0) {
duke@435 1508 fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
duke@435 1509 }
duke@435 1510 #endif /* X86_COMPILER2 */
duke@435 1511
duke@435 1512 memset(&jframe, 0, sizeof(Jframe_t));
duke@435 1513 memset(buf, 0, sizeof(buf));
duke@435 1514 res = Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe);
duke@435 1515 if (res != PS_OK)
duke@435 1516 return (-1);
duke@435 1517
duke@435 1518
duke@435 1519 res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
duke@435 1520 jframe.line, NULL);
duke@435 1521 if (res != 0) {
duke@435 1522 update_gregs(gregs, jframe);
duke@435 1523 return (res);
duke@435 1524 }
duke@435 1525 for (i = 1; i < jframe.vf_cnt; i++) {
duke@435 1526 Jget_vframe(J, i, buf, sizeof(buf), &jframe);
duke@435 1527 res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
duke@435 1528 jframe.line, NULL);
duke@435 1529 if (res != 0) {
duke@435 1530 update_gregs(gregs, jframe);
duke@435 1531 return (res);
duke@435 1532 }
duke@435 1533 }
duke@435 1534 update_gregs(gregs, jframe);
duke@435 1535 return (0);
duke@435 1536 }

mercurial