1 /* MI Command Set - catch commands.
2    Copyright (C) 2012-2024 Free Software Foundation, Inc.
3 
4    Contributed by Intel Corporation.
5 
6    This file is part of GDB.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20 
21 #include "arch-utils.h"
22 #include "breakpoint.h"
23 #include "ada-lang.h"
24 #include "mi-cmds.h"
25 #include "mi-getopt.h"
26 #include "mi-cmd-break.h"
27 
28 /* Handler for the -catch-assert command.  */
29 
30 void
mi_cmd_catch_assert(const char * cmd,const char * const * argv,int argc)31 mi_cmd_catch_assert (const char *cmd, const char *const *argv, int argc)
32 {
33   struct gdbarch *gdbarch = get_current_arch();
34   std::string condition;
35   int enabled = 1;
36   int temp = 0;
37 
38   int oind = 0;
39   const char *oarg;
40 
41   enum opt
42     {
43       OPT_CONDITION, OPT_DISABLED, OPT_TEMP,
44     };
45   static const struct mi_opt opts[] =
46     {
47       { "c", OPT_CONDITION, 1},
48       { "d", OPT_DISABLED, 0 },
49       { "t", OPT_TEMP, 0 },
50       { 0, 0, 0 }
51     };
52 
53   for (;;)
54     {
55       int opt = mi_getopt ("-catch-assert", argc, argv, opts,
56                                  &oind, &oarg);
57 
58       if (opt < 0)
59           break;
60 
61       switch ((enum opt) opt)
62           {
63           case OPT_CONDITION:
64             condition.assign (oarg);
65             break;
66           case OPT_DISABLED:
67             enabled = 0;
68             break;
69           case OPT_TEMP:
70             temp = 1;
71             break;
72           }
73     }
74 
75   /* This command does not accept any argument.  Make sure the user
76      did not provide any.  */
77   if (oind != argc)
78     error (_("Invalid argument: %s"), argv[oind]);
79 
80   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
81   create_ada_exception_catchpoint (gdbarch, ada_catch_assert, std::string (),
82                                            condition, temp, enabled, 0);
83 }
84 
85 /* Handler for the -catch-exception command.  */
86 
87 void
mi_cmd_catch_exception(const char * cmd,const char * const * argv,int argc)88 mi_cmd_catch_exception (const char *cmd, const char *const *argv, int argc)
89 {
90   struct gdbarch *gdbarch = get_current_arch();
91   std::string condition;
92   int enabled = 1;
93   std::string exception_name;
94   int temp = 0;
95   enum ada_exception_catchpoint_kind ex_kind = ada_catch_exception;
96 
97   int oind = 0;
98   const char *oarg;
99 
100   enum opt
101     {
102       OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP,
103       OPT_UNHANDLED,
104     };
105   static const struct mi_opt opts[] =
106     {
107       { "c", OPT_CONDITION, 1},
108       { "d", OPT_DISABLED, 0 },
109       { "e", OPT_EXCEPTION_NAME, 1 },
110       { "t", OPT_TEMP, 0 },
111       { "u", OPT_UNHANDLED, 0},
112       { 0, 0, 0 }
113     };
114 
115   for (;;)
116     {
117       int opt = mi_getopt ("-catch-exception", argc, argv, opts,
118                                  &oind, &oarg);
119 
120       if (opt < 0)
121           break;
122 
123       switch ((enum opt) opt)
124           {
125           case OPT_CONDITION:
126             condition.assign (oarg);
127             break;
128           case OPT_DISABLED:
129             enabled = 0;
130             break;
131           case OPT_EXCEPTION_NAME:
132             exception_name = oarg;
133             break;
134           case OPT_TEMP:
135             temp = 1;
136             break;
137           case OPT_UNHANDLED:
138             ex_kind = ada_catch_exception_unhandled;
139             break;
140           }
141     }
142 
143   /* This command does not accept any argument.  Make sure the user
144      did not provide any.  */
145   if (oind != argc)
146     error (_("Invalid argument: %s"), argv[oind]);
147 
148   /* Specifying an exception name does not make sense when requesting
149      an unhandled exception breakpoint.  */
150   if (ex_kind == ada_catch_exception_unhandled && !exception_name.empty ())
151     error (_("\"-e\" and \"-u\" are mutually exclusive"));
152 
153   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
154   create_ada_exception_catchpoint (gdbarch, ex_kind,
155                                            std::move (exception_name),
156                                            condition, temp, enabled, 0);
157 }
158 
159 /* Handler for the -catch-handlers command.  */
160 
161 void
mi_cmd_catch_handlers(const char * cmd,const char * const * argv,int argc)162 mi_cmd_catch_handlers (const char *cmd, const char *const *argv, int argc)
163 {
164   struct gdbarch *gdbarch = get_current_arch ();
165   std::string condition;
166   int enabled = 1;
167   std::string exception_name;
168   int temp = 0;
169 
170   int oind = 0;
171   const char *oarg;
172 
173   enum opt
174     {
175       OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP
176     };
177   static const struct mi_opt opts[] =
178     {
179       { "c", OPT_CONDITION, 1},
180       { "d", OPT_DISABLED, 0 },
181       { "e", OPT_EXCEPTION_NAME, 1 },
182       { "t", OPT_TEMP, 0 },
183       { 0, 0, 0 }
184     };
185 
186   for (;;)
187     {
188       int opt = mi_getopt ("-catch-handlers", argc, argv, opts,
189                                  &oind, &oarg);
190 
191       if (opt < 0)
192           break;
193 
194       switch ((enum opt) opt)
195           {
196           case OPT_CONDITION:
197             condition.assign (oarg);
198             break;
199           case OPT_DISABLED:
200             enabled = 0;
201             break;
202           case OPT_EXCEPTION_NAME:
203             exception_name = oarg;
204             break;
205           case OPT_TEMP:
206             temp = 1;
207             break;
208           }
209     }
210 
211   /* This command does not accept any argument.  Make sure the user
212      did not provide any.  */
213   if (oind != argc)
214     error (_("Invalid argument: %s"), argv[oind]);
215 
216   scoped_restore restore_breakpoint_reporting
217     = setup_breakpoint_reporting ();
218   create_ada_exception_catchpoint (gdbarch, ada_catch_handlers,
219                                            std::move (exception_name),
220                                            condition, temp, enabled, 0);
221 }
222 
223 /* Common path for the -catch-load and -catch-unload.  */
224 
225 static void
mi_catch_load_unload(int load,const char * const * argv,int argc)226 mi_catch_load_unload (int load, const char *const *argv, int argc)
227 {
228   const char *actual_cmd = load ? "-catch-load" : "-catch-unload";
229   int temp = 0;
230   int enabled = 1;
231   int oind = 0;
232   const char *oarg;
233   enum opt
234     {
235       OPT_TEMP,
236       OPT_DISABLED,
237     };
238   static const struct mi_opt opts[] =
239     {
240       { "t", OPT_TEMP, 0 },
241       { "d", OPT_DISABLED, 0 },
242       { 0, 0, 0 }
243     };
244 
245   for (;;)
246     {
247       int opt = mi_getopt (actual_cmd, argc, argv, opts,
248                                  &oind, &oarg);
249 
250       if (opt < 0)
251           break;
252 
253       switch ((enum opt) opt)
254           {
255           case OPT_TEMP:
256             temp = 1;
257             break;
258           case OPT_DISABLED:
259             enabled = 0;
260             break;
261           }
262     }
263 
264   if (oind >= argc)
265     error (_("-catch-load/unload: Missing <library name>"));
266   if (oind < argc -1)
267     error (_("-catch-load/unload: Garbage following the <library name>"));
268 
269   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
270   add_solib_catchpoint (argv[oind], load, temp, enabled);
271 }
272 
273 /* Handler for the -catch-load.  */
274 
275 void
mi_cmd_catch_load(const char * cmd,const char * const * argv,int argc)276 mi_cmd_catch_load (const char *cmd, const char *const *argv, int argc)
277 {
278   mi_catch_load_unload (1, argv, argc);
279 }
280 
281 
282 /* Handler for the -catch-unload.  */
283 
284 void
mi_cmd_catch_unload(const char * cmd,const char * const * argv,int argc)285 mi_cmd_catch_unload (const char *cmd, const char *const *argv, int argc)
286 {
287   mi_catch_load_unload (0, argv, argc);
288 }
289 
290 /* Core handler for -catch-throw, -catch-rethrow, and -catch-catch
291    commands.  The argument handling for all of these is identical, we just
292    pass KIND through to GDB's core to select the correct event type.  */
293 
294 static void
mi_cmd_catch_exception_event(enum exception_event_kind kind,const char * cmd,const char * const * argv,int argc)295 mi_cmd_catch_exception_event (enum exception_event_kind kind,
296                                     const char *cmd, const char *const *argv,
297                                     int argc)
298 {
299   const char *regex = NULL;
300   bool temp = false;
301   int oind = 0;
302   const char *oarg;
303   enum opt
304     {
305       OPT_TEMP,
306       OPT_REGEX,
307     };
308   static const struct mi_opt opts[] =
309     {
310       { "t", OPT_TEMP, 0 },
311       { "r", OPT_REGEX, 1 },
312       { 0, 0, 0 }
313     };
314 
315   for (;;)
316     {
317       int opt = mi_getopt (cmd, argc, argv, opts,
318                                  &oind, &oarg);
319 
320       if (opt < 0)
321           break;
322 
323       switch ((enum opt) opt)
324           {
325           case OPT_TEMP:
326             temp = true;
327             break;
328           case OPT_REGEX:
329             regex = oarg;
330             break;
331           }
332     }
333 
334   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
335   catch_exception_event (kind, regex, temp, 0 /* from_tty */);
336 }
337 
338 /* Handler for -catch-throw.  */
339 
340 void
mi_cmd_catch_throw(const char * cmd,const char * const * argv,int argc)341 mi_cmd_catch_throw (const char *cmd, const char *const *argv, int argc)
342 {
343   mi_cmd_catch_exception_event (EX_EVENT_THROW, cmd, argv, argc);
344 }
345 
346 /* Handler for -catch-rethrow.  */
347 
348 void
mi_cmd_catch_rethrow(const char * cmd,const char * const * argv,int argc)349 mi_cmd_catch_rethrow (const char *cmd, const char *const *argv, int argc)
350 {
351   mi_cmd_catch_exception_event (EX_EVENT_RETHROW, cmd, argv, argc);
352 }
353 
354 /* Handler for -catch-catch.  */
355 
356 void
mi_cmd_catch_catch(const char * cmd,const char * const * argv,int argc)357 mi_cmd_catch_catch (const char *cmd, const char *const *argv, int argc)
358 {
359   mi_cmd_catch_exception_event (EX_EVENT_CATCH, cmd, argv, argc);
360 }
361 
362