xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/bt-utils.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1*6881a400Schristos /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
2*6881a400Schristos 
3*6881a400Schristos    This file is part of GDB.
4*6881a400Schristos 
5*6881a400Schristos    This program is free software; you can redistribute it and/or modify
6*6881a400Schristos    it under the terms of the GNU General Public License as published by
7*6881a400Schristos    the Free Software Foundation; either version 3 of the License, or
8*6881a400Schristos    (at your option) any later version.
9*6881a400Schristos 
10*6881a400Schristos    This program is distributed in the hope that it will be useful,
11*6881a400Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
12*6881a400Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*6881a400Schristos    GNU General Public License for more details.
14*6881a400Schristos 
15*6881a400Schristos    You should have received a copy of the GNU General Public License
16*6881a400Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17*6881a400Schristos 
18*6881a400Schristos #include "defs.h"
19*6881a400Schristos #include "bt-utils.h"
20*6881a400Schristos #include "command.h"
21*6881a400Schristos #include "gdbcmd.h"
22*6881a400Schristos #include "top.h"
23*6881a400Schristos #include "cli/cli-decode.h"
24*6881a400Schristos 
25*6881a400Schristos /* See bt-utils.h.  */
26*6881a400Schristos 
27*6881a400Schristos void
28*6881a400Schristos gdb_internal_backtrace_set_cmd (const char *args, int from_tty,
29*6881a400Schristos 				cmd_list_element *c)
30*6881a400Schristos {
31*6881a400Schristos   gdb_assert (c->type == set_cmd);
32*6881a400Schristos   gdb_assert (c->var.has_value ());
33*6881a400Schristos   gdb_assert (c->var->type () == var_boolean);
34*6881a400Schristos 
35*6881a400Schristos #ifndef GDB_PRINT_INTERNAL_BACKTRACE
36*6881a400Schristos   if (c->var->get<bool> ())
37*6881a400Schristos     {
38*6881a400Schristos       c->var->set<bool> (false);
39*6881a400Schristos       error (_("support for this feature is not compiled into GDB"));
40*6881a400Schristos     }
41*6881a400Schristos #endif
42*6881a400Schristos }
43*6881a400Schristos 
44*6881a400Schristos #ifdef GDB_PRINT_INTERNAL_BACKTRACE
45*6881a400Schristos #ifdef GDB_PRINT_INTERNAL_BACKTRACE_USING_LIBBACKTRACE
46*6881a400Schristos 
47*6881a400Schristos /* Callback used by libbacktrace if it encounters an error.  */
48*6881a400Schristos 
49*6881a400Schristos static void
50*6881a400Schristos libbacktrace_error (void *data, const char *errmsg, int errnum)
51*6881a400Schristos {
52*6881a400Schristos   /* A negative errnum indicates no debug info was available, just
53*6881a400Schristos      skip printing a backtrace in this case.  */
54*6881a400Schristos   if (errnum < 0)
55*6881a400Schristos     return;
56*6881a400Schristos 
57*6881a400Schristos   const auto sig_write = [] (const char *msg) -> void
58*6881a400Schristos   {
59*6881a400Schristos     gdb_stderr->write_async_safe (msg, strlen (msg));
60*6881a400Schristos   };
61*6881a400Schristos 
62*6881a400Schristos   sig_write ("error creating backtrace: ");
63*6881a400Schristos   sig_write (errmsg);
64*6881a400Schristos   if (errnum > 0)
65*6881a400Schristos     {
66*6881a400Schristos       char buf[20];
67*6881a400Schristos       snprintf (buf, sizeof (buf), ": %d", errnum);
68*6881a400Schristos       buf[sizeof (buf) - 1] = '\0';
69*6881a400Schristos 
70*6881a400Schristos       sig_write (buf);
71*6881a400Schristos     }
72*6881a400Schristos   sig_write ("\n");
73*6881a400Schristos }
74*6881a400Schristos 
75*6881a400Schristos /* Callback used by libbacktrace to print a single stack frame.  */
76*6881a400Schristos 
77*6881a400Schristos static int
78*6881a400Schristos libbacktrace_print (void *data, uintptr_t pc, const char *filename,
79*6881a400Schristos 		    int lineno, const char *function)
80*6881a400Schristos {
81*6881a400Schristos   const auto sig_write = [] (const char *msg) -> void
82*6881a400Schristos   {
83*6881a400Schristos     gdb_stderr->write_async_safe (msg, strlen (msg));
84*6881a400Schristos   };
85*6881a400Schristos 
86*6881a400Schristos   /* Buffer to print addresses and line numbers into.  An 8-byte address
87*6881a400Schristos      with '0x' prefix and a null terminator requires 20 characters.  This
88*6881a400Schristos      also feels like it should be enough to represent line numbers in most
89*6881a400Schristos      files.  We are also careful to ensure we don't overflow this buffer.  */
90*6881a400Schristos   char buf[20];
91*6881a400Schristos 
92*6881a400Schristos   snprintf (buf, sizeof (buf), "0x%" PRIxPTR " ", pc);
93*6881a400Schristos   buf[sizeof (buf) - 1] = '\0';
94*6881a400Schristos   sig_write (buf);
95*6881a400Schristos   sig_write (function == nullptr ? "???" : function);
96*6881a400Schristos   if (filename != nullptr)
97*6881a400Schristos     {
98*6881a400Schristos       sig_write ("\n\t");
99*6881a400Schristos       sig_write (filename);
100*6881a400Schristos       sig_write (":");
101*6881a400Schristos       snprintf (buf, sizeof (buf), "%d", lineno);
102*6881a400Schristos       buf[sizeof (buf) - 1] = '\0';
103*6881a400Schristos       sig_write (buf);
104*6881a400Schristos     }
105*6881a400Schristos   sig_write ("\n");
106*6881a400Schristos 
107*6881a400Schristos   return function != nullptr && strcmp (function, "main") == 0;
108*6881a400Schristos }
109*6881a400Schristos 
110*6881a400Schristos /* Write a backtrace to GDB's stderr in an async safe manner.  This is a
111*6881a400Schristos    backtrace of GDB, not any running inferior, and is to be used when GDB
112*6881a400Schristos    crashes or hits some other error condition.  */
113*6881a400Schristos 
114*6881a400Schristos static void
115*6881a400Schristos gdb_internal_backtrace_1 ()
116*6881a400Schristos {
117*6881a400Schristos   static struct backtrace_state *state = nullptr;
118*6881a400Schristos 
119*6881a400Schristos   if (state == nullptr)
120*6881a400Schristos     state = backtrace_create_state (nullptr, 0, libbacktrace_error, nullptr);
121*6881a400Schristos 
122*6881a400Schristos   backtrace_full (state, 0, libbacktrace_print, libbacktrace_error, nullptr);
123*6881a400Schristos }
124*6881a400Schristos 
125*6881a400Schristos #elif defined GDB_PRINT_INTERNAL_BACKTRACE_USING_EXECINFO
126*6881a400Schristos 
127*6881a400Schristos /* See the comment on previous version of this function.  */
128*6881a400Schristos 
129*6881a400Schristos static void
130*6881a400Schristos gdb_internal_backtrace_1 ()
131*6881a400Schristos {
132*6881a400Schristos   const auto sig_write = [] (const char *msg) -> void
133*6881a400Schristos   {
134*6881a400Schristos     gdb_stderr->write_async_safe (msg, strlen (msg));
135*6881a400Schristos   };
136*6881a400Schristos 
137*6881a400Schristos   /* Allow up to 25 frames of backtrace.  */
138*6881a400Schristos   void *buffer[25];
139*6881a400Schristos   int frames = backtrace (buffer, ARRAY_SIZE (buffer));
140*6881a400Schristos 
141*6881a400Schristos   backtrace_symbols_fd (buffer, frames, gdb_stderr->fd ());
142*6881a400Schristos   if (frames == ARRAY_SIZE (buffer))
143*6881a400Schristos     sig_write (_("Backtrace might be incomplete.\n"));
144*6881a400Schristos }
145*6881a400Schristos 
146*6881a400Schristos #else
147*6881a400Schristos #error "unexpected internal backtrace policy"
148*6881a400Schristos #endif
149*6881a400Schristos #endif /* GDB_PRINT_INTERNAL_BACKTRACE */
150*6881a400Schristos 
151*6881a400Schristos /* See bt-utils.h.  */
152*6881a400Schristos 
153*6881a400Schristos void
154*6881a400Schristos gdb_internal_backtrace ()
155*6881a400Schristos {
156*6881a400Schristos   if (current_ui == nullptr)
157*6881a400Schristos     return;
158*6881a400Schristos 
159*6881a400Schristos #ifdef GDB_PRINT_INTERNAL_BACKTRACE
160*6881a400Schristos   const auto sig_write = [] (const char *msg) -> void
161*6881a400Schristos   {
162*6881a400Schristos     gdb_stderr->write_async_safe (msg, strlen (msg));
163*6881a400Schristos   };
164*6881a400Schristos 
165*6881a400Schristos   sig_write (_("----- Backtrace -----\n"));
166*6881a400Schristos 
167*6881a400Schristos   if (gdb_stderr->fd () > -1)
168*6881a400Schristos     gdb_internal_backtrace_1 ();
169*6881a400Schristos   else
170*6881a400Schristos     sig_write (_("Backtrace unavailable\n"));
171*6881a400Schristos 
172*6881a400Schristos   sig_write ("---------------------\n");
173*6881a400Schristos #endif
174*6881a400Schristos }
175