123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /* Everything about exec catchpoints, for GDB.
- Copyright (C) 1986-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 "annotate.h"
- #include "arch-utils.h"
- #include "breakpoint.h"
- #include "cli/cli-decode.h"
- #include "inferior.h"
- #include "mi/mi-common.h"
- #include "target.h"
- #include "valprint.h"
- /* Exec catchpoints. */
- /* An instance of this type is used to represent an exec catchpoint.
- A breakpoint is really of this type iff its ops pointer points to
- CATCH_EXEC_BREAKPOINT_OPS. */
- struct exec_catchpoint : public breakpoint
- {
- /* Filename of a program whose exec triggered this catchpoint.
- This field is only valid immediately after this catchpoint has
- triggered. */
- gdb::unique_xmalloc_ptr<char> exec_pathname;
- };
- static int
- insert_catch_exec (struct bp_location *bl)
- {
- return target_insert_exec_catchpoint (inferior_ptid.pid ());
- }
- static int
- remove_catch_exec (struct bp_location *bl, enum remove_bp_reason reason)
- {
- return target_remove_exec_catchpoint (inferior_ptid.pid ());
- }
- static int
- breakpoint_hit_catch_exec (const struct bp_location *bl,
- const address_space *aspace, CORE_ADDR bp_addr,
- const target_waitstatus &ws)
- {
- struct exec_catchpoint *c = (struct exec_catchpoint *) bl->owner;
- if (ws.kind () != TARGET_WAITKIND_EXECD)
- return 0;
- c->exec_pathname = make_unique_xstrdup (ws.execd_pathname ());
- return 1;
- }
- static enum print_stop_action
- print_it_catch_exec (bpstat *bs)
- {
- struct ui_out *uiout = current_uiout;
- struct breakpoint *b = bs->breakpoint_at;
- struct exec_catchpoint *c = (struct exec_catchpoint *) b;
- annotate_catchpoint (b->number);
- maybe_print_thread_hit_breakpoint (uiout);
- if (b->disposition == disp_del)
- uiout->text ("Temporary catchpoint ");
- else
- uiout->text ("Catchpoint ");
- if (uiout->is_mi_like_p ())
- {
- uiout->field_string ("reason", async_reason_lookup (EXEC_ASYNC_EXEC));
- uiout->field_string ("disp", bpdisp_text (b->disposition));
- }
- uiout->field_signed ("bkptno", b->number);
- uiout->text (" (exec'd ");
- uiout->field_string ("new-exec", c->exec_pathname.get ());
- uiout->text ("), ");
- return PRINT_SRC_AND_LOC;
- }
- static void
- print_one_catch_exec (struct breakpoint *b, struct bp_location **last_loc)
- {
- struct exec_catchpoint *c = (struct exec_catchpoint *) b;
- struct value_print_options opts;
- struct ui_out *uiout = current_uiout;
- get_user_print_options (&opts);
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- if (opts.addressprint)
- uiout->field_skip ("addr");
- annotate_field (5);
- uiout->text ("exec");
- if (c->exec_pathname != NULL)
- {
- uiout->text (", program \"");
- uiout->field_string ("what", c->exec_pathname.get ());
- uiout->text ("\" ");
- }
- if (uiout->is_mi_like_p ())
- uiout->field_string ("catch-type", "exec");
- }
- static void
- print_mention_catch_exec (struct breakpoint *b)
- {
- gdb_printf (_("Catchpoint %d (exec)"), b->number);
- }
- /* Implement the "print_recreate" breakpoint_ops method for exec
- catchpoints. */
- static void
- print_recreate_catch_exec (struct breakpoint *b, struct ui_file *fp)
- {
- gdb_printf (fp, "catch exec");
- print_recreate_thread (b, fp);
- }
- static struct breakpoint_ops catch_exec_breakpoint_ops;
- /* This function attempts to parse an optional "if <cond>" clause
- from the arg string. If one is not found, it returns NULL.
- Else, it returns a pointer to the condition string. (It does not
- attempt to evaluate the string against a particular block.) And,
- it updates arg to point to the first character following the parsed
- if clause in the arg string. */
- const char *
- ep_parse_optional_if_clause (const char **arg)
- {
- const char *cond_string;
- if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace ((*arg)[2]))
- return NULL;
- /* Skip the "if" keyword. */
- (*arg) += 2;
- /* Skip any extra leading whitespace, and record the start of the
- condition string. */
- *arg = skip_spaces (*arg);
- cond_string = *arg;
- /* Assume that the condition occupies the remainder of the arg
- string. */
- (*arg) += strlen (cond_string);
- return cond_string;
- }
- /* Commands to deal with catching events, such as signals, exceptions,
- process start/exit, etc. */
- static void
- catch_exec_command_1 (const char *arg, int from_tty,
- struct cmd_list_element *command)
- {
- struct gdbarch *gdbarch = get_current_arch ();
- const char *cond_string = NULL;
- bool temp = command->context () == CATCH_TEMPORARY;
- if (!arg)
- arg = "";
- arg = skip_spaces (arg);
- /* The allowed syntax is:
- catch exec
- catch exec if <cond>
- First, check if there's an if clause. */
- cond_string = ep_parse_optional_if_clause (&arg);
- if ((*arg != '\0') && !isspace (*arg))
- error (_("Junk at end of arguments."));
- std::unique_ptr<exec_catchpoint> c (new exec_catchpoint ());
- init_catchpoint (c.get (), gdbarch, temp, cond_string,
- &catch_exec_breakpoint_ops);
- c->exec_pathname.reset ();
- install_breakpoint (0, std::move (c), 1);
- }
- static void
- initialize_ops ()
- {
- struct breakpoint_ops *ops;
- initialize_breakpoint_ops ();
- /* Exec catchpoints. */
- ops = &catch_exec_breakpoint_ops;
- *ops = base_breakpoint_ops;
- ops->insert_location = insert_catch_exec;
- ops->remove_location = remove_catch_exec;
- ops->breakpoint_hit = breakpoint_hit_catch_exec;
- ops->print_it = print_it_catch_exec;
- ops->print_one = print_one_catch_exec;
- ops->print_mention = print_mention_catch_exec;
- ops->print_recreate = print_recreate_catch_exec;
- }
- void _initialize_break_catch_exec ();
- void
- _initialize_break_catch_exec ()
- {
- initialize_ops ();
- add_catch_command ("exec", _("Catch calls to exec."),
- catch_exec_command_1,
- NULL,
- CATCH_PERMANENT,
- CATCH_TEMPORARY);
- }
|