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