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