123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- /* Copyright (C) 2021-2022 Free Software Foundation, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "defs.h"
- #include "bt-utils.h"
- #include "command.h"
- #include "gdbcmd.h"
- #include "top.h"
- #include "cli/cli-decode.h"
- /* See bt-utils.h. */
- void
- gdb_internal_backtrace_set_cmd (const char *args, int from_tty,
- cmd_list_element *c)
- {
- gdb_assert (c->type == set_cmd);
- gdb_assert (c->var.has_value ());
- gdb_assert (c->var->type () == var_boolean);
- #ifndef GDB_PRINT_INTERNAL_BACKTRACE
- if (c->var->get<bool> ())
- {
- c->var->set<bool> (false);
- error (_("support for this feature is not compiled into GDB"));
- }
- #endif
- }
- #ifdef GDB_PRINT_INTERNAL_BACKTRACE
- #ifdef GDB_PRINT_INTERNAL_BACKTRACE_USING_LIBBACKTRACE
- /* Callback used by libbacktrace if it encounters an error. */
- static void
- libbacktrace_error (void *data, const char *errmsg, int errnum)
- {
- /* A negative errnum indicates no debug info was available, just
- skip printing a backtrace in this case. */
- if (errnum < 0)
- return;
- const auto sig_write = [] (const char *msg) -> void
- {
- gdb_stderr->write_async_safe (msg, strlen (msg));
- };
- sig_write ("error creating backtrace: ");
- sig_write (errmsg);
- if (errnum > 0)
- {
- char buf[20];
- snprintf (buf, sizeof (buf), ": %d", errnum);
- buf[sizeof (buf) - 1] = '\0';
- sig_write (buf);
- }
- sig_write ("\n");
- }
- /* Callback used by libbacktrace to print a single stack frame. */
- static int
- libbacktrace_print (void *data, uintptr_t pc, const char *filename,
- int lineno, const char *function)
- {
- const auto sig_write = [] (const char *msg) -> void
- {
- gdb_stderr->write_async_safe (msg, strlen (msg));
- };
- /* Buffer to print addresses and line numbers into. An 8-byte address
- with '0x' prefix and a null terminator requires 20 characters. This
- also feels like it should be enough to represent line numbers in most
- files. We are also careful to ensure we don't overflow this buffer. */
- char buf[20];
- snprintf (buf, sizeof (buf), "0x%" PRIxPTR " ", pc);
- buf[sizeof (buf) - 1] = '\0';
- sig_write (buf);
- sig_write (function == nullptr ? "???" : function);
- if (filename != nullptr)
- {
- sig_write ("\n\t");
- sig_write (filename);
- sig_write (":");
- snprintf (buf, sizeof (buf), "%d", lineno);
- buf[sizeof (buf) - 1] = '\0';
- sig_write (buf);
- }
- sig_write ("\n");
- return function != nullptr && strcmp (function, "main") == 0;
- }
- /* Write a backtrace to GDB's stderr in an async safe manner. This is a
- backtrace of GDB, not any running inferior, and is to be used when GDB
- crashes or hits some other error condition. */
- static void
- gdb_internal_backtrace_1 ()
- {
- static struct backtrace_state *state = nullptr;
- if (state == nullptr)
- state = backtrace_create_state (nullptr, 0, libbacktrace_error, nullptr);
- backtrace_full (state, 0, libbacktrace_print, libbacktrace_error, nullptr);
- }
- #elif defined GDB_PRINT_INTERNAL_BACKTRACE_USING_EXECINFO
- /* See the comment on previous version of this function. */
- static void
- gdb_internal_backtrace_1 ()
- {
- const auto sig_write = [] (const char *msg) -> void
- {
- gdb_stderr->write_async_safe (msg, strlen (msg));
- };
- /* Allow up to 25 frames of backtrace. */
- void *buffer[25];
- int frames = backtrace (buffer, ARRAY_SIZE (buffer));
- backtrace_symbols_fd (buffer, frames, gdb_stderr->fd ());
- if (frames == ARRAY_SIZE (buffer))
- sig_write (_("Backtrace might be incomplete.\n"));
- }
- #else
- #error "unexpected internal backtrace policy"
- #endif
- #endif /* GDB_PRINT_INTERNAL_BACKTRACE */
- /* See bt-utils.h. */
- void
- gdb_internal_backtrace ()
- {
- if (current_ui == nullptr)
- return;
- #ifdef GDB_PRINT_INTERNAL_BACKTRACE
- const auto sig_write = [] (const char *msg) -> void
- {
- gdb_stderr->write_async_safe (msg, strlen (msg));
- };
- sig_write (_("----- Backtrace -----\n"));
- if (gdb_stderr->fd () > -1)
- gdb_internal_backtrace_1 ();
- else
- sig_write (_("Backtrace unavailable\n"));
- sig_write ("---------------------\n");
- #endif
- }
|