CACAO
stacktrace.cpp
Go to the documentation of this file.
1 /* src/vm/jit/stacktrace.cpp - machine independent stacktrace system
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5  Copyright (C) 2009 Theobroma Systems Ltd.
6 
7  This file is part of CACAO.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2, or (at
12  your option) any later version.
13 
14  This program is distributed in the hope that it will be useful, but
15  WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  02110-1301, USA.
23 
24 */
25 
26 
27 #include "config.h"
28 
29 #include <cassert>
30 #include <cstdlib>
31 #include <cstring>
32 #include <stdint.h>
33 
34 #include "vm/types.hpp"
35 
36 #include "arch.hpp"
37 #include "md.hpp"
38 
39 #include "mm/gc.hpp"
40 
41 #include "vm/jit/stacktrace.hpp"
42 
43 #include "native/llni.hpp"
44 
45 #include "threads/thread.hpp"
46 
47 #include "toolbox/logging.hpp"
48 
49 #include "vm/array.hpp"
50 #include "vm/jit/builtin.hpp"
51 #include "vm/class.hpp"
52 #include "vm/cycles-stats.hpp"
53 #include "vm/exceptions.hpp"
54 #include "vm/globals.hpp"
55 #include "vm/javaobjects.hpp"
56 #include "vm/loader.hpp"
57 #include "vm/method.hpp"
58 #include "vm/options.hpp"
59 #include "vm/string.hpp"
60 #include "vm/vm.hpp"
61 
64 #include "vm/jit/methodheader.hpp"
65 #include "vm/jit/methodtree.hpp"
66 
67 /* global variables ***********************************************************/
68 
69 CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
70 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
73 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
75 
76 
77 /* stacktrace_stackframeinfo_add ***********************************************
78 
79  Fills a stackframe info structure with the given or calculated
80  values and adds it to the chain.
81 
82 *******************************************************************************/
83 
84 void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
85 {
86  stackframeinfo_t *currentsfi;
87  codeinfo *code;
88 #if defined(ENABLE_JIT)
89  s4 framesize;
90 #endif
91 
92  /* Get current stackframe info. */
93 
95 
96  /* sometimes we don't have pv handy (e.g. in asmpart.S:
97  L_asm_call_jit_compiler_exception or in the interpreter). */
98 
99  if (pv == NULL) {
100 #if defined(ENABLE_INTRP)
101  if (opt_intrp)
102  pv = methodtree_find(ra);
103  else
104 #endif
105  {
106 #if defined(ENABLE_JIT)
107 # if defined(__SPARC_64__)
108  pv = md_get_pv_from_stackframe(sp);
109 # else
110  pv = md_codegen_get_pv_from_pc(ra);
111 # endif
112 #endif
113  }
114  }
115 
116  /* Get codeinfo pointer for the parent Java method. */
117 
118  code = code_get_codeinfo_for_pv(pv);
119 
120  /* XXX */
121  /* assert(m != NULL); */
122 
123 #if defined(ENABLE_JIT)
124 # if defined(ENABLE_INTRP)
125  /* When using the interpreter, we pass RA to the function. */
126 
127  if (!opt_intrp) {
128 # endif
129 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__)
130  /* On i386 and x86_64 we always have to get the return address
131  from the stack. */
132  /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
133  the RA from stack. */
134 
135  framesize = md_stacktrace_get_framesize(code);
136 
137  ra = md_stacktrace_get_returnaddress(sp, framesize);
138 # else
139  /* If the method is a non-leaf function, we need to get the
140  return address from the stack. For leaf functions the
141  return address is set correctly. This makes the assembler
142  and the signal handler code simpler. The code is NULL is
143  the asm_vm_call_method special case. */
144 
145  if ((code == NULL) || !code_is_leafmethod(code)) {
146  framesize = md_stacktrace_get_framesize(code);
147 
148  ra = md_stacktrace_get_returnaddress(sp, framesize);
149  }
150 # endif
151 # if defined(ENABLE_INTRP)
152  }
153 # endif
154 #endif
155 
156  /* Calculate XPC when not given. The XPC is then the return
157  address of the current method minus 1 because the RA points to
158  the instruction after the call instruction. This is required
159  e.g. for method stubs. */
160 
161  if (xpc == NULL) {
162  xpc = (void *) (((intptr_t) ra) - 1);
163  }
164 
165  /* Fill new stackframeinfo structure. */
166 
167  sfi->prev = currentsfi;
168  sfi->code = code;
169  sfi->pv = pv;
170  sfi->sp = sp;
171  sfi->ra = ra;
172  sfi->xpc = xpc;
173 
174 #if !defined(NDEBUG)
176  log_start();
177  log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
178  sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
179  method_print(sfi->code->m);
180  log_print("]");
181  log_finish();
182  }
183 #endif
184 
185  /* Store new stackframeinfo pointer. */
186 
188 
189  /* set the native world flag for the current thread */
190  /* ATTENTION: This flag tells the GC how to treat this thread in case of
191  a collection. Set this flag _after_ a valid stackframe info was set. */
192 
194 }
195 
196 
197 /* stacktrace_stackframeinfo_remove ********************************************
198 
199  Remove the given stackframeinfo from the chain in the current
200  thread.
201 
202 *******************************************************************************/
203 
205 {
206  /* Clear the native world flag for the current thread. */
207  /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
208 
210 
211 #if !defined(NDEBUG)
213  log_start();
214  log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
215  sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
216  method_print(sfi->code->m);
217  log_print("]");
218  log_finish();
219  }
220 #endif
221 
222  /* Set previous stackframe info. */
223 
225 }
226 
227 
228 /* stacktrace_stackframeinfo_fill **********************************************
229 
230  Fill the temporary stackframeinfo structure with the values given
231  in sfi.
232 
233  IN:
234  tmpsfi ... temporary stackframeinfo
235  sfi ...... stackframeinfo to be used in the next iteration
236 
237 *******************************************************************************/
238 
240 {
241  /* Sanity checks. */
242 
243  assert(tmpsfi != NULL);
244  assert(sfi != NULL);
245 
246  /* Fill the temporary stackframeinfo. */
247 
248  tmpsfi->code = sfi->code;
249  tmpsfi->pv = sfi->pv;
250  tmpsfi->sp = sfi->sp;
251  tmpsfi->ra = sfi->ra;
252  tmpsfi->xpc = sfi->xpc;
253 
254  /* Set the previous stackframe info of the temporary one to the
255  next in the chain. */
256 
257  tmpsfi->prev = sfi->prev;
258 
259 #if !defined(NDEBUG)
261  log_println("[stacktrace fill]");
262 #endif
263 }
264 
265 
266 /* stacktrace_stackframeinfo_next **********************************************
267 
268  Walk the stack (or the stackframeinfo-chain) to the next method and
269  return the new stackframe values in the temporary stackframeinfo
270  passed.
271 
272  ATTENTION: This function does NOT skip builtin methods!
273 
274  IN:
275  tmpsfi ... temporary stackframeinfo of current method
276 
277 *******************************************************************************/
278 
280 {
281  codeinfo *code;
282  void *pv;
283  void *sp;
284  void *ra;
285  //void *xpc;
286  uint32_t framesize;
287  stackframeinfo_t *prevsfi;
288 
289  /* Sanity check. */
290 
291  assert(tmpsfi != NULL);
292 
293  /* Get values from the stackframeinfo. */
294 
295  code = tmpsfi->code;
296  pv = tmpsfi->pv;
297  sp = tmpsfi->sp;
298  ra = tmpsfi->ra;
299  //xpc = tmpsfi->xpc;
300 
301  /* Get the current stack frame size. */
302 
303  framesize = md_stacktrace_get_framesize(code);
304 
305  /* Get the RA of the current stack frame (RA to the parent Java
306  method) if the current method is a non-leaf method. Otherwise
307  the value in the stackframeinfo is correct (from the signal
308  handler). */
309 
310 #if defined(ENABLE_JIT)
311 # if defined(ENABLE_INTRP)
312  if (opt_intrp)
313  ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
314  else
315 # endif
316  {
317  if (!code_is_leafmethod(code))
318  ra = md_stacktrace_get_returnaddress(sp, framesize);
319  }
320 #else
321  ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
322 #endif
323 
324  /* Get the PV for the parent Java method. */
325 
326 #if defined(ENABLE_INTRP)
327  if (opt_intrp)
328  pv = methodtree_find(ra);
329  else
330 #endif
331  {
332 #if defined(ENABLE_JIT)
333 # if defined(__SPARC_64__)
334  sp = md_get_framepointer(sp);
335  pv = md_get_pv_from_stackframe(sp);
336 # else
337  pv = md_codegen_get_pv_from_pc(ra);
338 # endif
339 #endif
340  }
341 
342  /* Get the codeinfo pointer for the parent Java method. */
343 
344  code = code_get_codeinfo_for_pv(pv);
345 
346  /* Calculate the SP for the parent Java method. */
347 
348 #if defined(ENABLE_INTRP)
349  if (opt_intrp)
350  sp = *(u1 **) (sp - framesize);
351  else
352 #endif
353  {
354 #if STACKFRAME_RA_BETWEEN_FRAMES
355  sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
356 #elif defined(__SPARC_64__)
357  /* already has the new sp */
358 #else
359  sp = (void *) (((intptr_t) sp) + framesize);
360 #endif
361  }
362 
363  /* If the new codeinfo pointer is NULL we reached a
364  asm_vm_call_method function. In this case we get the next
365  values from the previous stackframeinfo in the chain.
366  Otherwise the new values have been calculated before. */
367 
368  if (code == NULL) {
369  prevsfi = tmpsfi->prev;
370 
371  /* If the previous stackframeinfo in the chain is NULL we
372  reached the top of the stacktrace. We set code and prev to
373  NULL to mark the end, which is checked in
374  stacktrace_stackframeinfo_end_check. */
375 
376  if (prevsfi == NULL) {
377  tmpsfi->code = NULL;
378  tmpsfi->prev = NULL;
379  return;
380  }
381 
382  /* Fill the temporary stackframeinfo with the new values. */
383 
384  stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
385  }
386  else {
387  /* Store the new values in the stackframeinfo. NOTE: We
388  subtract 1 from the RA to get the XPC, because the RA
389  points to the instruction after the call instruction. */
390 
391  tmpsfi->code = code;
392  tmpsfi->pv = pv;
393  tmpsfi->sp = sp;
394  tmpsfi->ra = ra;
395  tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
396  }
397 
398 #if !defined(NDEBUG)
399  /* Print current method information. */
400 
401  if (opt_DebugStackTrace) {
402  log_start();
403  log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
404  tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
405  tmpsfi->xpc);
406  method_print(tmpsfi->code->m);
407  log_print("]");
408  log_finish();
409  }
410 #endif
411 }
412 
413 
414 /* stacktrace_stackframeinfo_end_check *****************************************
415 
416  Check if we reached the end of the stacktrace.
417 
418  IN:
419  tmpsfi ... temporary stackframeinfo of current method
420 
421  RETURN:
422  true .... the end is reached
423  false ... the end is not reached
424 
425 *******************************************************************************/
426 
428 {
429  /* Sanity check. */
430 
431  assert(tmpsfi != NULL);
432 
433  if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
434 #if !defined(NDEBUG)
436  log_println("[stacktrace stop]");
437 #endif
438 
439  return true;
440  }
441 
442  return false;
443 }
444 
445 
446 /* stacktrace_depth ************************************************************
447 
448  Calculates and returns the depth of the current stacktrace.
449 
450  IN:
451  sfi ... stackframeinfo where to start the stacktrace
452 
453  RETURN:
454  depth of the stacktrace
455 
456 *******************************************************************************/
457 
459 {
460  stackframeinfo_t tmpsfi;
461  int depth;
462  methodinfo *m;
463 
464 #if !defined(NDEBUG)
466  log_println("[stacktrace_depth]");
467 #endif
468 
469  /* XXX This is not correct, but a workaround for threads-dump for
470  now. */
471 /* assert(sfi != NULL); */
472  if (sfi == NULL)
473  return 0;
474 
475  /* Iterate over all stackframes. */
476 
477  depth = 0;
478 
479  for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
480  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
482  /* Get methodinfo. */
483 
484  m = tmpsfi.code->m;
485 
486  /* Skip builtin methods. */
487 
488  if (m->flags & ACC_METHOD_BUILTIN)
489  continue;
490 
491  depth++;
492  }
493 
494  return depth;
495 }
496 
497 
498 /* stacktrace_get **************************************************************
499 
500  Builds and returns a stacktrace starting from the given stackframe
501  info and returns the stacktrace structure wrapped in a Java
502  byte-array to not confuse the GC.
503 
504  IN:
505  sfi ... stackframe info to start stacktrace from
506 
507  RETURN:
508  stacktrace as Java byte-array
509 
510 *******************************************************************************/
511 
513 {
514  stacktrace_t *st;
515  stacktrace_entry_t *ste;
516 
518 
519 #if !defined(NDEBUG)
521  log_println("[stacktrace_get]");
522 #endif
523 
524  bool skip_fillInStackTrace = true;
525  bool skip_init = true;
526 
527  int depth = stacktrace_depth(sfi);
528 
529  if (depth == 0)
530  return NULL;
531 
532  // Allocate memory from the GC heap and copy the stacktrace buffer.
533  // ATTENTION: Use a Java byte-array for this to not confuse the GC.
534  // FIXME: We waste some memory here as we skip some entries later.
535 
536  int32_t ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
537 
538  ByteArray ba(ba_size);
539 
540  if (ba.is_null())
541  goto return_NULL;
542 
543  // Get a stacktrace entry pointer.
544  // ATTENTION: We need a critical section here because we use the
545  // byte-array data pointer directly.
546 
548 
549  st = (stacktrace_t *) ba.get_raw_data_ptr();
550  ste = st->entries;
551 
552  // Iterate over the whole stack.
553  stackframeinfo_t tmpsfi;
554 
555  for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
556  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
558  // Get the methodinfo
559 
560  methodinfo *m = tmpsfi.code->m;
561 
562  // Skip builtin methods
563 
564  if (m->flags & ACC_METHOD_BUILTIN)
565  continue;
566 
567  // This logic is taken from
568  // hotspot/src/share/vm/classfile/javaClasses.cpp
569  // (java_lang_Throwable::fill_in_stack_trace)
570 
571  // the current stack contains the following frames:
572  // * one or more fillInStackTrace frames for the exception class, we skip these
573  // * zero or more <init> frames for the exception class, we skip these
574  // * rest of the stack
575 
576  // skip Throwable.fillInStackTrace
577 
578  if (skip_fillInStackTrace) {
579  if (m->name == utf8::fillInStackTrace) {
580  continue;
581  } else {
582  // we saw all fillInStackTrace frames, stop skipping
583  skip_fillInStackTrace = false;
584  }
585  }
586 
587  // Skip <init> methods of any classes deriving from java.lang.Throwable
588 
589  if (skip_init == true) {
590  if (m->name == utf8::init && class_issubclass(m->clazz, class_java_lang_Throwable)) {
591  continue;
592  } else {
593  // we saw all <init> frames, stop skipping
594  skip_init = false;
595  }
596  }
597 
598  // Store the stacktrace entry and increment the pointer.
599 
600  ste->code = tmpsfi.code;
601  ste->pc = tmpsfi.xpc;
602 
603  ste++;
604  }
605 
606  // Store the number of entries in the stacktrace structure
607 
608  st->length = ste - st->entries;
609 
611 
612  CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
613  stacktrace_overhead)
614  return ba.get_handle();
615 
616 return_NULL:
617  CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
618  stacktrace_overhead)
619 
620  return NULL;
621 }
622 
623 
624 /* stacktrace_get_current ******************************************************
625 
626  Builds and returns a stacktrace from the current thread and returns
627  the stacktrace structure wrapped in a Java byte-array to not
628  confuse the GC.
629 
630  RETURN:
631  stacktrace as Java byte-array
632 
633 *******************************************************************************/
634 
636 {
637  stackframeinfo_t *sfi;
639 
641  ba = stacktrace_get(sfi);
642 
643  return ba;
644 }
645 
646 
647 /**
648  * Creates a java.lang.StackTraceElement for one element of the given
649  * stacktrace.
650  *
651  * @param st Given stacktrace.
652  * @param index Index of element inside stacktrace.
653  * @return The filled StackTraceElement object.
654  */
655 #if defined(ENABLE_JAVASE)
657 {
658  assert(st != NULL);
659 
660  if ((index < 0) || (index >= st->length)) {
661  /* XXX This should be an IndexOutOfBoundsException (check this
662  again). */
664  return NULL;
665  }
666 
667  // Get the stacktrace entry.
668  stacktrace_entry_t* ste = &(st->entries[index]);
669 
670  // Get the codeinfo, methodinfo and classinfo.
671  codeinfo* code = ste->code;
672  methodinfo* m = code->m;
673  classinfo* c = m->clazz;
674 
675  // Get filename.
676  java_handle_t* filename;
677 
678  if (!(m->flags & ACC_NATIVE)) {
679  if (c->sourcefile != NULL)
680  filename = JavaString::literal(c->sourcefile);
681  else
682  filename = NULL;
683  }
684  else
685  filename = NULL;
686 
687  // Get line number.
688  int32_t linenumber;
689 
690  if (m->flags & ACC_NATIVE) {
691 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
692  linenumber = -1;
693 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
694  linenumber = -2;
695 #else
696 # error unknown classpath configuration
697 #endif
698  }
699  else {
700  // FIXME linenumbertable->find could change the methodinfo
701  // pointer when hitting an inlined method.
702  linenumber = code->linenumbertable->find(&m, ste->pc);
703  linenumber = (linenumber == 0) ? -1 : linenumber;
704  }
705 
706  // Get declaring class name.
707  java_handle_t* declaringclass = JavaString(class_get_classname(c)).intern();
708 
709 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
710  // Allocate a new StackTraceElement object.
712 
713  if (h == NULL)
714  return NULL;
715 
716  java_lang_StackTraceElement jlste(h, filename, linenumber, declaringclass, JavaString::from_utf8(m->name), ((m->flags & ACC_NATIVE) ? 1 : 0));
717 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
718  // Allocate a new StackTraceElement object.
719  java_lang_StackTraceElement jlste(declaringclass, JavaString::literal(m->name), filename, linenumber);
720 
721  if (jlste.is_null())
722  return NULL;
723 #else
724 # error unknown classpath configuration
725 #endif
726 
727  return jlste.get_handle();
728 }
729 #endif
730 
731 
732 /**
733  * Creates a complete array of java.lang.StackTraceElement objects
734  * for the given stacktrace.
735  *
736  * @param st Given stacktrace.
737  * @return Array of filled StackTraceElement objects.
738  */
739 #if defined(ENABLE_JAVASE)
741 {
742  // Get length of stacktrace. If stacktrace is not available
743  // an empty array should be returned.
744  int32_t length = (st != NULL) ? st->length : 0;
745 
746  // Create the stacktrace element array.
748 
749  if (oa.is_null())
750  return NULL;
751 
752  // Iterate over all stacktrace elements.
753  for (int i = 0; i < length; i++) {
754 
755  // Get stacktrace element at current index.
757 
758  if (h == NULL)
759  return NULL;
760 
761  // Store stacktrace element in array.
762  oa.set_element(i, h);
763  }
764 
765  return oa.get_handle();
766 }
767 #endif
768 
769 
770 /* stacktrace_get_caller_class *************************************************
771 
772  Get the class on the stack at the given depth. This function skips
773  various special classes or methods.
774 
775  ARGUMENTS:
776  depth ... depth to get caller class of
777 
778  RETURN:
779  caller class
780 
781 *******************************************************************************/
782 
783 #if defined(ENABLE_JAVASE)
785 {
786  stackframeinfo_t *sfi;
787  stackframeinfo_t tmpsfi;
788  methodinfo *m;
789  classinfo *c;
790  int i;
791 
792 #if !defined(NDEBUG)
794  log_println("[stacktrace_get_caller_class]");
795 #endif
796 
797  /* Get the stackframeinfo of the current thread. */
798 
800 
801  /* Iterate over the whole stack until we reached the requested
802  depth. */
803 
804  i = 0;
805 
806  for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
807  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
809 
810  m = tmpsfi.code->m;
811  c = m->clazz;
812 
813  /* Skip builtin methods. */
814 
815  if (m->flags & ACC_METHOD_BUILTIN)
816  continue;
817 
818 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
819  /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
820  (vframeStreamCommon::security_get_caller_frame). */
821 
822  /* This is java.lang.reflect.Method.invoke(), skip it. */
823 
825  continue;
826 
827  /* This is an auxiliary frame, skip it. */
828 
829  if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
830  continue;
831 #endif
832 
833  /* We reached the requested depth. */
834 
835  if (i >= depth)
836  return c;
837 
838  i++;
839  }
840 
841  return NULL;
842 }
843 #endif
844 
845 
846 /**
847  * Returns the first non-null (user-defined) classloader on the stack.
848  *
849  * @return The first non-null classloader or NULL if none is found.
850  */
852 {
853  stackframeinfo_t *sfi;
854  stackframeinfo_t tmpsfi;
855  methodinfo *m;
856  classloader_t *cl;
857 
858 #if !defined(NDEBUG)
860  log_println("[stacktrace_first_nonnull_classloader]");
861 #endif
862 
863  /* Get the stackframeinfo of the current thread. */
864 
866 
867  /* Iterate over the whole stack. */
868 
869  for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
870  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
872 
873  m = tmpsfi.code->m;
874  cl = class_get_classloader(m->clazz);
875 
876 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
877  /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
878  (vframeStreamCommon::skip_reflection_related_frames). */
879  if (class_issubclass(m->clazz, class_sun_reflect_MethodAccessorImpl) ||
880  class_issubclass(m->clazz, class_sun_reflect_ConstructorAccessorImpl))
881  continue;
882 #endif
883 
884  if (cl != NULL)
885  return cl;
886  }
887 
888  return NULL;
889 }
890 
891 
892 /**
893  * Checks if a given classloader is equal to the the second classloader
894  * or one of its ancestors (parents).
895  *
896  * XXX: This helper method should be moved to java_lang_Classloader.
897  */
898 #if defined(ENABLE_JAVASE)
900 {
901  // Iterate over chain of possible parents.
902  while (parent != NULL) {
903 
904  // Check if given loader is parent.
905  if (loader == parent)
906  return true;
907 
908  // Jump to next parent.
909  java_lang_ClassLoader jlcl(parent);
910  parent = jlcl.get_parent();
911  }
912 
913  return false;
914 }
915 #endif /* defined(ENABLE_JAVASE) */
916 
917 
918 /**
919  * Returns the first non-system (user-defined) classloader on the stack.
920  * A non-system classloader is a non-null classloader being not equal to
921  * the system classloader (or one of its ancestors).
922  *
923  * @return The first non-system classloader or NULL if none is found.
924  */
925 #if defined(ENABLE_JAVASE)
927 {
928  stackframeinfo_t *sfi;
929  stackframeinfo_t tmpsfi;
930  methodinfo *m;
931  classloader_t *cl;
932  classloader_t *syscl;
933 
934 #if !defined(NDEBUG)
936  log_println("[stacktrace_first_nonsystem_classloader]");
937 #endif
938 
939  // Get the stackframeinfo of the current thread.
941 
942  // Get the system class class loader.
944 
945  // Iterate over the whole stack.
946  for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
947  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
949 
950  m = tmpsfi.code->m;
951  cl = class_get_classloader(m->clazz);
952 
953  if (cl == NULL)
954  continue;
955 
956  // XXX if a method in a class in a trusted loader is in a
957  // doPrivileged, return NULL (or break) here.
958 
959  if (!is_ancestor_of(cl, syscl))
960  return cl;
961  }
962 
963  return NULL;
964 }
965 #endif /* defined(ENABLE_JAVASE) */
966 
967 
968 /* stacktrace_getClassContext **************************************************
969 
970  Creates a Class context array.
971 
972  RETURN VALUE:
973  the array of java.lang.Class objects, or
974  NULL if an exception has been thrown
975 
976 *******************************************************************************/
977 
979 {
980  stackframeinfo_t *sfi;
981  stackframeinfo_t tmpsfi;
982  int depth;
983  int i;
984  methodinfo *m;
985 
987 
988 #if !defined(NDEBUG)
990  log_println("[stacktrace_getClassContext]");
991 #endif
992 
994 
995  /* Get the depth of the current stack. */
996 
997  depth = stacktrace_depth(sfi);
998 
999  /* The first stackframe corresponds to the method whose
1000  implementation calls this native function. We remove that
1001  entry. */
1002 
1003  depth--;
1004  stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1006 
1007  /* Allocate the Class array. */
1008 
1009  ClassArray ca(depth);
1010 
1011  if (ca.is_null()) {
1013 
1014  return NULL;
1015  }
1016 
1017  /* Fill the Class array from the stacktrace list. */
1018  /* Iterate over the whole stack. */
1019 
1020  i = 0;
1021 
1022  for (;
1023  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1024  stacktrace_stackframeinfo_next(&tmpsfi)) {
1025  /* Get methodinfo. */
1026 
1027  m = tmpsfi.code->m;
1028 
1029  /* Skip builtin methods. */
1030 
1031  if (m->flags & ACC_METHOD_BUILTIN)
1032  continue;
1033 
1034  /* Store the class in the array. */
1035 
1036  ca.set_element(i, m->clazz);
1037 
1038  i++;
1039  }
1040 
1042 
1044 
1045  return ca.get_handle();
1046 }
1047 
1048 
1049 /* stacktrace_getCurrentClass **************************************************
1050 
1051  Find the current class by walking the stack trace.
1052 
1053  Quote from the JNI documentation:
1054 
1055  In the Java 2 Platform, FindClass locates the class loader
1056  associated with the current native method. If the native code
1057  belongs to a system class, no class loader will be
1058  involved. Otherwise, the proper class loader will be invoked to
1059  load and link the named class. When FindClass is called through the
1060  Invocation Interface, there is no current native method or its
1061  associated class loader. In that case, the result of
1062  ClassLoader.getBaseClassLoader is used."
1063 
1064 *******************************************************************************/
1065 
1066 #if defined(ENABLE_JAVASE)
1068 {
1069  stackframeinfo_t *sfi;
1070  stackframeinfo_t tmpsfi;
1071  methodinfo *m;
1072 
1074 
1075 #if !defined(NDEBUG)
1076  if (opt_DebugStackTrace)
1077  log_println("[stacktrace_get_current_class]");
1078 #endif
1079 
1080  /* Get the stackframeinfo of the current thread. */
1081 
1083 
1084  /* If the stackframeinfo is NULL then FindClass is called through
1085  the Invocation Interface and we return NULL */
1086 
1087  if (sfi == NULL) {
1088  CYCLES_STATS_END(stacktrace_getCurrentClass);
1089 
1090  return NULL;
1091  }
1092 
1093  /* Iterate over the whole stack. */
1094 
1095  for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1096  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1097  stacktrace_stackframeinfo_next(&tmpsfi)) {
1098  /* Get the methodinfo. */
1099 
1100  m = tmpsfi.code->m;
1101 
1103  CYCLES_STATS_END(stacktrace_getCurrentClass);
1104 
1105  return NULL;
1106  }
1107 
1108  if (m->clazz != NULL) {
1109  CYCLES_STATS_END(stacktrace_getCurrentClass);
1110 
1111  return m->clazz;
1112  }
1113  }
1114 
1115  /* No Java method found on the stack. */
1116 
1117  CYCLES_STATS_END(stacktrace_getCurrentClass);
1118 
1119  return NULL;
1120 }
1121 #endif /* ENABLE_JAVASE */
1122 
1123 
1124 /* stacktrace_get_stack ********************************************************
1125 
1126  Create a 2-dimensional array for java.security.VMAccessControler.
1127 
1128  RETURN VALUE:
1129  the arrary, or
1130  NULL if an exception has been thrown
1131 
1132 *******************************************************************************/
1133 
1134 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1136 {
1137  stackframeinfo_t *sfi;
1138  stackframeinfo_t tmpsfi;
1139  int depth;
1140  methodinfo *m;
1141  java_handle_t *string;
1142  int i;
1143 
1145 
1146 #if !defined(NDEBUG)
1147  if (opt_DebugStackTrace)
1148  log_println("[stacktrace_get_stack]");
1149 #endif
1150 
1151  /* Get the stackframeinfo of the current thread. */
1152 
1154 
1155  /* Get the depth of the current stack. */
1156 
1157  depth = stacktrace_depth(sfi);
1158 
1159  if (depth == 0)
1160  return NULL;
1161 
1162  /* Allocate the required arrays. */
1163 
1165  ClassArray classes(depth);
1166  ObjectArray methodnames(depth, class_java_lang_String);
1167 
1168  if (oa.is_null())
1169  goto return_NULL;
1170 
1171  if (classes.is_null())
1172  goto return_NULL;
1173 
1174  if (methodnames.is_null())
1175  goto return_NULL;
1176 
1177  /* Set up the 2-dimensional array. */
1178 
1179  oa.set_element(0, (java_handle_t *) classes.get_handle());
1180  oa.set_element(1, (java_handle_t *) methodnames.get_handle());
1181 
1182  /* Iterate over the whole stack. */
1183  /* TODO We should use a critical section here to speed things
1184  up. */
1185 
1186  i = 0;
1187 
1188  for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1189  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1190  stacktrace_stackframeinfo_next(&tmpsfi)) {
1191  /* Get the methodinfo. */
1192 
1193  m = tmpsfi.code->m;
1194 
1195  /* Skip builtin methods. */
1196 
1197  if (m->flags & ACC_METHOD_BUILTIN)
1198  continue;
1199 
1200  /* Store the class in the array. */
1201 
1202  classes.set_element(i, m->clazz);
1203 
1204  /* Store the name in the array. */
1205 
1206  string = JavaString::from_utf8(m->name);
1207 
1208  if (string == NULL)
1209  goto return_NULL;
1210 
1211  methodnames.set_element(i, string);
1212 
1213  i++;
1214  }
1215 
1217 
1218  return oa.get_handle();
1219 
1220 return_NULL:
1222 
1223  return NULL;
1224 }
1225 #endif
1226 
1227 
1228 /* stacktrace_print_entry ****************************************************
1229 
1230  Print line for a stacktrace entry.
1231 
1232  ARGUMENTS:
1233  m ............ methodinfo of the entry
1234  linenumber ... linenumber of the entry
1235 
1236 *******************************************************************************/
1237 
1238 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1239 {
1240  /* Sanity check. */
1241 
1242  assert(m != NULL);
1243 
1244  printf("\tat ");
1245 
1246  if (m->flags & ACC_METHOD_BUILTIN)
1247  printf("NULL");
1248  else
1250 
1251  printf(".");
1254 
1255  if (m->flags & ACC_NATIVE) {
1256  puts("(Native Method)");
1257  }
1258  else {
1259  if (m->flags & ACC_METHOD_BUILTIN) {
1260  puts("(builtin)");
1261  }
1262  else {
1263  printf("(");
1265  printf(":%d)\n", linenumber);
1266  }
1267  }
1268 
1269  fflush(stdout);
1270 }
1271 
1272 
1273 /* stacktrace_print ************************************************************
1274 
1275  Print the given stacktrace with CACAO intern methods only (no Java
1276  code required).
1277 
1278  This method is used by stacktrace_dump_trace and
1279  builtin_trace_exception.
1280 
1281  IN:
1282  st ... stacktrace to print
1283 
1284 *******************************************************************************/
1285 
1287 {
1288  stacktrace_entry_t *ste;
1289  methodinfo *m;
1290  int32_t linenumber;
1291  int i;
1292 
1293  ste = &(st->entries[0]);
1294 
1295  for (i = 0; i < st->length; i++, ste++) {
1296  m = ste->code->m;
1297 
1298  /* Get the line number. */
1299 
1300  linenumber = ste->code->linenumbertable->find(&m, ste->pc);
1301 
1302  stacktrace_print_entry(m, linenumber);
1303  }
1304 }
1305 
1306 
1307 /* stacktrace_print_current ****************************************************
1308 
1309  Print the current stacktrace of the current thread.
1310 
1311  NOTE: This function prints all frames of the stacktrace and does
1312  not skip frames like stacktrace_get.
1313 
1314 *******************************************************************************/
1315 
1317 {
1318  stackframeinfo_t *sfi;
1319  stackframeinfo_t tmpsfi;
1320  codeinfo *code;
1321  methodinfo *m;
1322  int32_t linenumber;
1323 
1325 
1326  if (sfi == NULL) {
1327  puts("\t<<No stacktrace available>>");
1328  fflush(stdout);
1329  return;
1330  }
1331 
1332  for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1333  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1334  stacktrace_stackframeinfo_next(&tmpsfi)) {
1335  /* Get the methodinfo. */
1336 
1337  code = tmpsfi.code;
1338  m = code->m;
1339 
1340  // Get the line number.
1341  linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1342 
1343  stacktrace_print_entry(m, linenumber);
1344  }
1345 }
1346 
1347 
1348 /**
1349  * Creates a stacktrace for the given thread.
1350  *
1351  * @param t Given thread.
1352  * @return Current stacktrace of the given thread.
1353  *
1354  * XXX: Creation of the stacktrace starts at the most recent
1355  * stackframeinfo block. If the thread is not inside the native
1356  * world, the created stacktrace is not complete!
1357  */
1359 {
1360  stackframeinfo_t* sfi;
1362  stacktrace_t* st;
1363 
1364  sfi = t->_stackframeinfo;
1365  stba = stacktrace_get(sfi);
1366 
1367  ByteArray ba(stba);
1368 
1369  if (ba.is_null())
1370  return NULL;
1371 
1372  st = (stacktrace_t*) ba.get_raw_data_ptr();
1373 
1374  return st;
1375 }
1376 
1377 
1378 /* stacktrace_print_of_thread **************************************************
1379 
1380  Print the current stacktrace of the given thread. It will only work
1381  for suspended threads.
1382 
1383  ARGUMENTS:
1384  t ... thread
1385 
1386 *******************************************************************************/
1387 
1389 {
1390  stackframeinfo_t *sfi;
1391  stackframeinfo_t tmpsfi;
1392  codeinfo *code;
1393  methodinfo *m;
1394  int32_t linenumber;
1395 
1396  /* Build a stacktrace for the passed thread. */
1397 
1398  sfi = t->_stackframeinfo;
1399 
1400  if (!t->suspended || sfi == NULL) {
1401  puts("\t<<No stacktrace available>>");
1402  fflush(stdout);
1403  return;
1404  }
1405 
1406  for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1407  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1408  stacktrace_stackframeinfo_next(&tmpsfi)) {
1409  /* Get the methodinfo. */
1410 
1411  code = tmpsfi.code;
1412  m = code->m;
1413 
1414  // Get the line number.
1415  linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
1416 
1417  stacktrace_print_entry(m, linenumber);
1418  }
1419 }
1420 
1421 
1422 /* stacktrace_print_exception **************************************************
1423 
1424  Print the stacktrace of a given exception (more or less a wrapper
1425  to stacktrace_print).
1426 
1427  IN:
1428  h ... handle of exception to print
1429 
1430 *******************************************************************************/
1431 
1433 {
1434  if (h == NULL)
1435  return;
1436 
1437  java_lang_Throwable t(h);
1438 
1439  /* now print the stacktrace */
1440 
1441 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1442 
1444  ByteArray backtrace(vmt.get_vmdata());
1445 
1446 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1447 
1448  ByteArray backtrace(t.get_backtrace());
1449 
1450 #else
1451 # error unknown classpath configuration
1452 #endif
1453 
1454  // Sanity check.
1455 
1456  assert(backtrace.is_non_null());
1457 
1458  /* We need a critical section here as we use the byte-array data
1459  pointer directly. */
1460 
1462 
1463  stacktrace_t* st = (stacktrace_t*) backtrace.get_raw_data_ptr();
1464 
1465  stacktrace_print(st);
1466 
1468 }
1469 
1470 
1471 #if defined(ENABLE_CYCLES_STATS)
1472 void stacktrace_print_cycles_stats(FILE *file)
1473 {
1474  CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1477  CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
1479 }
1480 #endif
1481 
1482 /*
1483  * These are local overrides for various environment variables in Emacs.
1484  * Please do not remove this and leave it at the end of the file, where
1485  * Emacs will automagically detect them.
1486  * ---------------------------------------------------------------------
1487  * Local variables:
1488  * mode: c++
1489  * indent-tabs-mode: t
1490  * c-basic-offset: 4
1491  * tab-width: 4
1492  * End:
1493  * vim:noexpandtab:sw=4:ts=4:
1494  */
Utf8String name
Definition: method.hpp:71
#define methodtree_find
Definition: md-asm.hpp:101
std::size_t index
#define pv
Definition: md-asm.hpp:65
classinfo * stacktrace_get_caller_class(int depth)
Definition: stacktrace.cpp:784
codeinfo * code
Definition: stacktrace.hpp:50
virtual java_handle_t * get_handle() const
int opt_DebugStackTrace
Definition: options.cpp:174
#define ra
Definition: md-asm.hpp:62
void method_print(methodinfo *m)
Definition: method.cpp:1189
static int stacktrace_depth(stackframeinfo_t *sfi)
Definition: stacktrace.cpp:458
void stacktrace_print_current(void)
static struct stackframeinfo_t * threads_get_current_stackframeinfo(void)
Definition: thread.hpp:313
classloader_t * stacktrace_first_nonsystem_classloader(void)
Returns the first non-system (user-defined) classloader on the stack.
Definition: stacktrace.cpp:926
bool is_null() const
stacktrace_entry_t entries[1]
Definition: stacktrace.hpp:77
virtual java_handle_array_t * get_handle() const
Definition: array.hpp:103
JavaString intern() const
Definition: string.cpp:336
static bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
Definition: stacktrace.cpp:427
classloader_t * stacktrace_first_nonnull_classloader(void)
Returns the first non-null (user-defined) classloader on the stack.
Definition: stacktrace.cpp:851
static JavaString from_utf8(Utf8String)
Definition: string.cpp:184
int8_t * get_raw_data_ptr()
Definition: array.hpp:333
java_handle_t * get_vmState() const
void utf_display_printable_ascii_classname(Utf8String u)
Definition: utf8.cpp:552
#define CYCLES_STATS_PRINT(name, file)
#define THREAD_NATIVEWORLD_EXIT
Definition: thread.hpp:209
bool opt_intrp
Definition: options.cpp:55
Actual implementation of access class for Java Object arrays.
Definition: array.hpp:381
static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
u1 * intrp_md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
Definition: md.c:86
#define LLNI_CRITICAL_END
Definition: llni.hpp:141
static void * md_get_framepointer(void *sp)
Definition: md.hpp:79
uint8_t u1
Definition: types.hpp:40
void stacktrace_print_exception(java_handle_t *h)
GNU Classpath java/lang/StackTraceElement.
void set_element(int32_t index, T value)
Definition: array.hpp:255
void stacktrace_print(stacktrace_t *st)
void log_finish(void)
Definition: logging.cpp:117
void log_println(const char *text,...)
Definition: logging.cpp:193
static classloader_t * class_get_classloader(classinfo *c)
Definition: class.hpp:402
GNU Classpath java/lang/VMThrowable.
static int code_is_leafmethod(codeinfo *code)
Definition: code.hpp:151
java_handle_t * builtin_new(classinfo *c)
Definition: builtin.cpp:816
static bool is_ancestor_of(classloader_t *loader, classloader_t *parent)
Checks if a given classloader is equal to the the second classloader or one of its ancestors (parents...
Definition: stacktrace.cpp:899
#define CYCLES_STATS_PRINT_OVERHEAD(name, file)
java_handle_t * get_parent() const
methodinfo * m
Definition: code.hpp:75
java_handle_t * stacktrace_get_StackTraceElement(stacktrace_t *st, int32_t index)
Creates a java.lang.StackTraceElement for one element of the given stacktrace.
Definition: stacktrace.cpp:656
java_handle_t * class_get_classname(classinfo *c)
Returns the classname of the class, where slashes (&#39;/&#39;) are replaced by dots (&#39;.
Definition: class.cpp:86
#define xpc
Definition: md-asm.hpp:51
java_handle_objectarray_t * stacktrace_get_StackTraceElements(stacktrace_t *st)
Creates a complete array of java.lang.StackTraceElement objects for the given stacktrace.
Definition: stacktrace.cpp:740
void log_print(const char *text,...)
Definition: logging.cpp:149
classinfo * stacktrace_get_current_class(void)
jlong jlong jlong jlong jint depth
Definition: jvmti.h:497
#define CYCLES_STATS_END_WITH_OVERHEAD(name, ovname)
Utf8String descriptor
Definition: method.hpp:72
stacktrace_t * stacktrace_get_of_thread(threadobject *t)
Creates a stacktrace for the given thread.
#define CYCLES_STATS_DECLARE_AND_START
classinfo * arrayclass_java_lang_Object
Definition: globals.cpp:94
codeinfo * code
Definition: stacktrace.hpp:68
int32_t length
Definition: stacktrace.hpp:76
bool suspended
Definition: thread.hpp:123
classinfo * clazz
Definition: method.hpp:80
Utf8String name
Definition: class.hpp:91
static codeinfo * code_get_codeinfo_for_pv(void *pv)
Definition: code.hpp:201
java_handle_bytearray_t * stacktrace_get(stackframeinfo_t *sfi)
Definition: stacktrace.cpp:512
java_handle_objectarray_t * stacktrace_getClassContext(void)
Definition: stacktrace.cpp:978
void log_start(void)
Definition: logging.cpp:106
MIIterator i
int32_t s4
Definition: types.hpp:45
void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, void *pv, void *sp, void *ra, void *xpc)
Definition: stacktrace.cpp:84
static void * md_get_pv_from_stackframe(void *sp)
Definition: md.hpp:91
JNIEnv jclass jobject loader
Definition: jvmti.h:312
#define CYCLES_STATS_END(name)
GNU Classpath java/lang/Throwable.
static void * md_codegen_get_pv_from_pc(void *ra)
Definition: md.hpp:99
void stacktrace_print_of_thread(threadobject *t)
static java_handle_t * invoke_getSystemClassLoader()
Invokes the static Java method getSystemClassLoader().
Definition: javaobjects.cpp:51
Utf8String sourcefile
Definition: class.hpp:133
codeinfo * code
Definition: method.hpp:103
bool class_issubclass(classinfo *sub, classinfo *super)
Definition: class.cpp:1404
#define CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
void utf_display_printable_ascii(Utf8String u)
Definition: utf8.cpp:532
void exceptions_throw_arrayindexoutofboundsexception(void)
GNU Classpath java/lang/ClassLoader.
classinfo * class_java_lang_String
Definition: globals.cpp:39
#define sp
Definition: md-asm.hpp:81
void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
Definition: stacktrace.cpp:204
stackframeinfo_t * prev
Definition: stacktrace.hpp:49
LinenumberTable * linenumbertable
Definition: code.hpp:94
static void * md_stacktrace_get_returnaddress(void *sp, int32_t stackframesize)
Definition: md.hpp:76
#define LLNI_CRITICAL_START
Definition: llni.hpp:140
#define CYCLES_STATS_DECLARE(name, nbins, divisor)
stackframeinfo_t * _stackframeinfo
Definition: thread.hpp:129
classinfo * class_java_lang_StackTraceElement
Definition: globals.cpp:80
java_handle_objectarray_t * stacktrace_get_stack(void)
s4 flags
Definition: method.hpp:70
int32_t find(methodinfo **pm, void *pc)
Search the the line number table for the line corresponding to a given program counter.
methodinfo * method_java_lang_reflect_Method_invoke
bool is_null() const
Definition: array.hpp:203
static JavaString literal(Utf8String)
Definition: string.cpp:257
#define THREAD_NATIVEWORLD_ENTER
Definition: thread.hpp:208
static void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
Definition: stacktrace.cpp:239
Actual implementation of access class for java.lang.Class arrays.
Definition: array.hpp:391
classinfo * class_java_security_PrivilegedAction
Definition: globals.cpp:84
const char const void jint length
Definition: jvmti.h:352
#define printf(...)
Definition: ssa2.cpp:40
LoopTreeGraph * parent
classinfo * class_java_lang_Throwable
Definition: globals.cpp:43
int opt_DebugStackFrameInfo
Definition: options.cpp:173
java_handle_bytearray_t * stacktrace_get_current(void)
Definition: stacktrace.cpp:635
static void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
Definition: stacktrace.cpp:279
static void threads_set_current_stackframeinfo(struct stackframeinfo_t *sfi)
Definition: thread.hpp:318
Definition: stacktrace.hpp:67
static int32_t md_stacktrace_get_framesize(codeinfo *code)
Returns the size (in bytes) of the current stackframe, specified by the passed codeinfo structure...
Definition: md.hpp:56
void * pc
Definition: stacktrace.hpp:69