1 /*
 2  * Copyright (c) 2003, 2025, 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 "runtime/frame.inline.hpp"
26 #include "runtime/os.inline.hpp"
27 #include "utilities/decoder.hpp"
28 #include "utilities/globalDefinitions.hpp"
29 #include "utilities/nativeStackPrinter.hpp"
30 #include "utilities/ostream.hpp"
31 
32 bool NativeStackPrinter::print_stack(outputStream* st, char* buf, int buf_size,
33                                      address& lastpc, bool print_source_info,
34                                      int max_frames) {
35   if (os::platform_print_native_stack(st, _context, buf, buf_size, lastpc)) {
36     return true;
37   } else {
38     print_stack_from_frame(st, buf, buf_size, print_source_info, max_frames);
39     return false;
40   }
41 }
42 
43 void NativeStackPrinter::print_stack_from_frame(outputStream* st, frame fr,
44                                                 char* buf, int buf_size,
45                                                 bool print_source_info, int max_frames) {
46   // see if it's a valid frame
47   if (fr.pc()) {
48     st->print_cr("Native frames: (J=compiled Java code, A=AOT compiled, P=AOT preloaded, j=interpreted, Vv=VM code, C=native code)");
49     const int limit = max_frames == -1 ? StackPrintLimit
50                                        : MIN2(max_frames, StackPrintLimit);
51     int count = 0;
52     while (count++ < limit) {
53       fr.print_on_error(st, buf, buf_size);
54       if (fr.pc()) { // print source file and line, if available
55         char filename[128];
56         int line_no;
57         if (count == 1 && _lineno != 0) {
58           // We have source information for the first frame for internal errors,
59           // there is no need to parse it from the symbols.
60           st->print("  (%s:%d)", _filename, _lineno);
61         } else if (print_source_info &&
62                    Decoder::get_source_info(fr.pc(), filename, sizeof(filename), &line_no, count != 1)) {
63           st->print("  (%s:%d)", filename, line_no);
64         }
65       }
66       st->cr();
67       fr = frame::next_frame(fr, _current);
68       if (fr.pc() == nullptr) {
69         break;
70       }
71     }
72 
73     if (count > limit) {
74       st->print_cr("...<more frames>...");
75     }
76 
77   } else {
78     st->print_cr("Native frames: <unavailable>");
79   }
80 }