]> Git Repo - binutils.git/blob - gdb/break-catch-exec.c
gdb: remove SYMBOL_CLASS macro, add getter
[binutils.git] / gdb / break-catch-exec.c
1 /* Everything about exec catchpoints, for GDB.
2
3    Copyright (C) 1986-2022 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21
22 #include "annotate.h"
23 #include "arch-utils.h"
24 #include "breakpoint.h"
25 #include "cli/cli-decode.h"
26 #include "inferior.h"
27 #include "mi/mi-common.h"
28 #include "target.h"
29 #include "valprint.h"
30
31 /* Exec catchpoints.  */
32
33 /* An instance of this type is used to represent an exec catchpoint.
34    A breakpoint is really of this type iff its ops pointer points to
35    CATCH_EXEC_BREAKPOINT_OPS.  */
36
37 struct exec_catchpoint : public breakpoint
38 {
39   /* Filename of a program whose exec triggered this catchpoint.
40      This field is only valid immediately after this catchpoint has
41      triggered.  */
42   gdb::unique_xmalloc_ptr<char> exec_pathname;
43 };
44
45 static int
46 insert_catch_exec (struct bp_location *bl)
47 {
48   return target_insert_exec_catchpoint (inferior_ptid.pid ());
49 }
50
51 static int
52 remove_catch_exec (struct bp_location *bl, enum remove_bp_reason reason)
53 {
54   return target_remove_exec_catchpoint (inferior_ptid.pid ());
55 }
56
57 static int
58 breakpoint_hit_catch_exec (const struct bp_location *bl,
59                            const address_space *aspace, CORE_ADDR bp_addr,
60                            const target_waitstatus &ws)
61 {
62   struct exec_catchpoint *c = (struct exec_catchpoint *) bl->owner;
63
64   if (ws.kind () != TARGET_WAITKIND_EXECD)
65     return 0;
66
67   c->exec_pathname = make_unique_xstrdup (ws.execd_pathname ());
68   return 1;
69 }
70
71 static enum print_stop_action
72 print_it_catch_exec (bpstat *bs)
73 {
74   struct ui_out *uiout = current_uiout;
75   struct breakpoint *b = bs->breakpoint_at;
76   struct exec_catchpoint *c = (struct exec_catchpoint *) b;
77
78   annotate_catchpoint (b->number);
79   maybe_print_thread_hit_breakpoint (uiout);
80   if (b->disposition == disp_del)
81     uiout->text ("Temporary catchpoint ");
82   else
83     uiout->text ("Catchpoint ");
84   if (uiout->is_mi_like_p ())
85     {
86       uiout->field_string ("reason", async_reason_lookup (EXEC_ASYNC_EXEC));
87       uiout->field_string ("disp", bpdisp_text (b->disposition));
88     }
89   uiout->field_signed ("bkptno", b->number);
90   uiout->text (" (exec'd ");
91   uiout->field_string ("new-exec", c->exec_pathname.get ());
92   uiout->text ("), ");
93
94   return PRINT_SRC_AND_LOC;
95 }
96
97 static void
98 print_one_catch_exec (struct breakpoint *b, struct bp_location **last_loc)
99 {
100   struct exec_catchpoint *c = (struct exec_catchpoint *) b;
101   struct value_print_options opts;
102   struct ui_out *uiout = current_uiout;
103
104   get_user_print_options (&opts);
105
106   /* Field 4, the address, is omitted (which makes the columns
107      not line up too nicely with the headers, but the effect
108      is relatively readable).  */
109   if (opts.addressprint)
110     uiout->field_skip ("addr");
111   annotate_field (5);
112   uiout->text ("exec");
113   if (c->exec_pathname != NULL)
114     {
115       uiout->text (", program \"");
116       uiout->field_string ("what", c->exec_pathname.get ());
117       uiout->text ("\" ");
118     }
119
120   if (uiout->is_mi_like_p ())
121     uiout->field_string ("catch-type", "exec");
122 }
123
124 static void
125 print_mention_catch_exec (struct breakpoint *b)
126 {
127   printf_filtered (_("Catchpoint %d (exec)"), b->number);
128 }
129
130 /* Implement the "print_recreate" breakpoint_ops method for exec
131    catchpoints.  */
132
133 static void
134 print_recreate_catch_exec (struct breakpoint *b, struct ui_file *fp)
135 {
136   fprintf_unfiltered (fp, "catch exec");
137   print_recreate_thread (b, fp);
138 }
139
140 static struct breakpoint_ops catch_exec_breakpoint_ops;
141
142 /* This function attempts to parse an optional "if <cond>" clause
143    from the arg string.  If one is not found, it returns NULL.
144
145    Else, it returns a pointer to the condition string.  (It does not
146    attempt to evaluate the string against a particular block.)  And,
147    it updates arg to point to the first character following the parsed
148    if clause in the arg string.  */
149
150 const char *
151 ep_parse_optional_if_clause (const char **arg)
152 {
153   const char *cond_string;
154
155   if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace ((*arg)[2]))
156     return NULL;
157
158   /* Skip the "if" keyword.  */
159   (*arg) += 2;
160
161   /* Skip any extra leading whitespace, and record the start of the
162      condition string.  */
163   *arg = skip_spaces (*arg);
164   cond_string = *arg;
165
166   /* Assume that the condition occupies the remainder of the arg
167      string.  */
168   (*arg) += strlen (cond_string);
169
170   return cond_string;
171 }
172
173 /* Commands to deal with catching events, such as signals, exceptions,
174    process start/exit, etc.  */
175
176 static void
177 catch_exec_command_1 (const char *arg, int from_tty,
178                       struct cmd_list_element *command)
179 {
180   struct gdbarch *gdbarch = get_current_arch ();
181   const char *cond_string = NULL;
182   bool temp = command->context () == CATCH_TEMPORARY;
183
184   if (!arg)
185     arg = "";
186   arg = skip_spaces (arg);
187
188   /* The allowed syntax is:
189      catch exec
190      catch exec if <cond>
191
192      First, check if there's an if clause.  */
193   cond_string = ep_parse_optional_if_clause (&arg);
194
195   if ((*arg != '\0') && !isspace (*arg))
196     error (_("Junk at end of arguments."));
197
198   std::unique_ptr<exec_catchpoint> c (new exec_catchpoint ());
199   init_catchpoint (c.get (), gdbarch, temp, cond_string,
200                    &catch_exec_breakpoint_ops);
201   c->exec_pathname.reset ();
202
203   install_breakpoint (0, std::move (c), 1);
204 }
205
206 static void
207 initialize_ops ()
208 {
209   struct breakpoint_ops *ops;
210
211   initialize_breakpoint_ops ();
212
213   /* Exec catchpoints.  */
214   ops = &catch_exec_breakpoint_ops;
215   *ops = base_breakpoint_ops;
216   ops->insert_location = insert_catch_exec;
217   ops->remove_location = remove_catch_exec;
218   ops->breakpoint_hit = breakpoint_hit_catch_exec;
219   ops->print_it = print_it_catch_exec;
220   ops->print_one = print_one_catch_exec;
221   ops->print_mention = print_mention_catch_exec;
222   ops->print_recreate = print_recreate_catch_exec;
223 }
224
225 void _initialize_break_catch_exec ();
226 void
227 _initialize_break_catch_exec ()
228 {
229   initialize_ops ();
230
231   add_catch_command ("exec", _("Catch calls to exec."),
232                      catch_exec_command_1,
233                      NULL,
234                      CATCH_PERMANENT,
235                      CATCH_TEMPORARY);
236 }
This page took 0.040853 seconds and 4 git commands to generate.