comparison src/os/solaris/dtrace/libjvm_db.c @ 0:a61af66fc99e jdk7-b24

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