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