GDB (xrefs)
/tmp/gdb-8.1/gdb/break-catch-throw.c
Go to the documentation of this file.
1 /* Everything about catch/throw catchpoints, for GDB.
2 
3  Copyright (C) 1986-2018 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 #include "arch-utils.h"
22 #include <ctype.h>
23 #include "breakpoint.h"
24 #include "gdbcmd.h"
25 #include "inferior.h"
26 #include "annotate.h"
27 #include "valprint.h"
28 #include "cli/cli-utils.h"
29 #include "completer.h"
30 #include "gdb_obstack.h"
31 #include "mi/mi-common.h"
32 #include "linespec.h"
33 #include "probe.h"
34 #include "objfiles.h"
35 #include "cp-abi.h"
36 #include "gdb_regex.h"
37 #include "cp-support.h"
38 #include "location.h"
39 
40 /* Enums for exception-handling support. */
42 {
46 };
47 
48 /* Each spot where we may place an exception-related catchpoint has
49  two names: the SDT probe point and the function name. This
50  structure holds both. */
51 
53 {
54  /* The name of the probe point to try, in the form accepted by
55  'parse_probes'. */
56 
57  const char *probe;
58 
59  /* The name of the corresponding function. */
60 
61  const char *function;
62 };
63 
64 /* Names of the probe points and functions on which to break. This is
65  indexed by exception_event_kind. */
66 static const struct exception_names exception_functions[] =
67 {
68  { "-probe-stap libstdcxx:throw", "__cxa_throw" },
69  { "-probe-stap libstdcxx:rethrow", "__cxa_rethrow" },
70  { "-probe-stap libstdcxx:catch", "__cxa_begin_catch" }
71 };
72 
74 
75 /* The type of an exception catchpoint. */
76 
78 {
79  /* The kind of exception catchpoint. */
80 
82 
83  /* If not empty, a string holding the source form of the regular
84  expression to match against. */
85 
87 
88  /* If non-NULL, a compiled regular expression which is used to
89  determine which exceptions to stop on. */
90 
91  std::unique_ptr<compiled_regex> pattern;
92 };
93 
94 
95 
96 /* A helper function that fetches exception probe arguments. This
97  fills in *ARG0 (if non-NULL) and *ARG1 (which must be non-NULL).
98  It will throw an exception on any kind of failure. */
99 
100 static void
101 fetch_probe_arguments (struct value **arg0, struct value **arg1)
102 {
103  struct frame_info *frame = get_selected_frame (_("No frame selected"));
104  CORE_ADDR pc = get_frame_pc (frame);
105  struct bound_probe pc_probe;
106  unsigned n_args;
107 
108  pc_probe = find_probe_by_pc (pc);
109  if (pc_probe.prob == NULL
110  || pc_probe.prob->get_provider () != "libstdcxx"
111  || (pc_probe.prob->get_name () != "catch"
112  && pc_probe.prob->get_name () != "throw"
113  && pc_probe.prob->get_name () != "rethrow"))
114  error (_("not stopped at a C++ exception catchpoint"));
115 
116  n_args = pc_probe.prob->get_argument_count (frame);
117  if (n_args < 2)
118  error (_("C++ exception catchpoint has too few arguments"));
119 
120  if (arg0 != NULL)
121  *arg0 = pc_probe.prob->evaluate_argument (0, frame);
122  *arg1 = pc_probe.prob->evaluate_argument (1, frame);
123 
124  if ((arg0 != NULL && *arg0 == NULL) || *arg1 == NULL)
125  error (_("error computing probe argument at c++ exception catchpoint"));
126 }
127 
128 
129 
130 /* A helper function that returns a value indicating the kind of the
131  exception catchpoint B. */
132 
133 static enum exception_event_kind
135 {
136  struct exception_catchpoint *cp = (struct exception_catchpoint *) b;
137 
138  return cp->kind;
139 }
140 
141 /* Implement the 'check_status' method. */
142 
143 static void
145 {
146  struct exception_catchpoint *self
147  = (struct exception_catchpoint *) bs->breakpoint_at;
148  std::string type_name;
149 
151  if (bs->stop == 0)
152  return;
153 
154  if (self->pattern == NULL)
155  return;
156 
157  TRY
158  {
159  struct value *typeinfo_arg;
160  std::string canon;
161 
162  fetch_probe_arguments (NULL, &typeinfo_arg);
163  type_name = cplus_typename_from_type_info (typeinfo_arg);
164 
165  canon = cp_canonicalize_string (type_name.c_str ());
166  if (!canon.empty ())
167  std::swap (type_name, canon);
168  }
170  {
172  }
173  END_CATCH
174 
175  if (!type_name.empty ())
176  {
177  if (self->pattern->exec (type_name.c_str (), 0, NULL, 0) != 0)
178  bs->stop = 0;
179  }
180 }
181 
182 /* Implement the 're_set' method. */
183 
184 static void
186 {
187  std::vector<symtab_and_line> sals;
189  struct program_space *filter_pspace = current_program_space;
190 
191  /* We first try to use the probe interface. */
192  TRY
193  {
194  event_location_up location
196  sals = parse_probes (location.get (), filter_pspace, NULL);
197  }
199  {
200  /* Using the probe interface failed. Let's fallback to the normal
201  catchpoint mode. */
202  TRY
203  {
204  struct explicit_location explicit_loc;
205 
206  initialize_explicit_location (&explicit_loc);
207  explicit_loc.function_name
208  = ASTRDUP (exception_functions[kind].function);
209  event_location_up location = new_explicit_location (&explicit_loc);
210  sals = self->ops->decode_location (self, location.get (),
211  filter_pspace);
212  }
214  {
215  /* NOT_FOUND_ERROR just means the breakpoint will be
216  pending, so let it through. */
217  if (ex.error != NOT_FOUND_ERROR)
218  throw_exception (ex);
219  }
220  END_CATCH
221  }
222  END_CATCH
223 
224  update_breakpoint_locations (self, filter_pspace, sals, {});
225 }
226 
227 static enum print_stop_action
229 {
230  struct ui_out *uiout = current_uiout;
231  struct breakpoint *b = bs->breakpoint_at;
232  int bp_temp;
234 
237 
238  bp_temp = b->disposition == disp_del;
239  uiout->text (bp_temp ? "Temporary catchpoint "
240  : "Catchpoint ");
241  if (!uiout->is_mi_like_p ())
242  uiout->field_int ("bkptno", b->number);
243  uiout->text ((kind == EX_EVENT_THROW ? " (exception thrown), "
244  : (kind == EX_EVENT_CATCH ? " (exception caught), "
245  : " (exception rethrown), ")));
246  if (uiout->is_mi_like_p ())
247  {
248  uiout->field_string ("reason",
250  uiout->field_string ("disp", bpdisp_text (b->disposition));
251  uiout->field_int ("bkptno", b->number);
252  }
253  return PRINT_SRC_AND_LOC;
254 }
255 
256 static void
258  struct bp_location **last_loc)
259 {
260  struct value_print_options opts;
261  struct ui_out *uiout = current_uiout;
263 
264  get_user_print_options (&opts);
265  if (opts.addressprint)
266  {
267  annotate_field (4);
268  if (b->loc == NULL || b->loc->shlib_disabled)
269  uiout->field_string ("addr", "<PENDING>");
270  else
271  uiout->field_core_addr ("addr",
272  b->loc->gdbarch, b->loc->address);
273  }
274  annotate_field (5);
275  if (b->loc)
276  *last_loc = b->loc;
277 
278  switch (kind)
279  {
280  case EX_EVENT_THROW:
281  uiout->field_string ("what", "exception throw");
282  if (uiout->is_mi_like_p ())
283  uiout->field_string ("catch-type", "throw");
284  break;
285 
286  case EX_EVENT_RETHROW:
287  uiout->field_string ("what", "exception rethrow");
288  if (uiout->is_mi_like_p ())
289  uiout->field_string ("catch-type", "rethrow");
290  break;
291 
292  case EX_EVENT_CATCH:
293  uiout->field_string ("what", "exception catch");
294  if (uiout->is_mi_like_p ())
295  uiout->field_string ("catch-type", "catch");
296  break;
297  }
298 }
299 
300 /* Implement the 'print_one_detail' method. */
301 
302 static void
304  struct ui_out *uiout)
305 {
306  const struct exception_catchpoint *cp
307  = (const struct exception_catchpoint *) b;
308 
309  if (!cp->exception_rx.empty ())
310  {
311  uiout->text (_("\tmatching: "));
312  uiout->field_string ("regexp", cp->exception_rx.c_str ());
313  uiout->text ("\n");
314  }
315 }
316 
317 static void
319 {
320  struct ui_out *uiout = current_uiout;
321  int bp_temp;
323 
324  bp_temp = b->disposition == disp_del;
325  uiout->text (bp_temp ? _("Temporary catchpoint ")
326  : _("Catchpoint "));
327  uiout->field_int ("bkptno", b->number);
328  uiout->text ((kind == EX_EVENT_THROW ? _(" (throw)")
329  : (kind == EX_EVENT_CATCH ? _(" (catch)")
330  : _(" (rethrow)"))));
331 }
332 
333 /* Implement the "print_recreate" breakpoint_ops method for throw and
334  catch catchpoints. */
335 
336 static void
338  struct ui_file *fp)
339 {
340  int bp_temp;
342 
343  bp_temp = b->disposition == disp_del;
344  fprintf_unfiltered (fp, bp_temp ? "tcatch " : "catch ");
345  switch (kind)
346  {
347  case EX_EVENT_THROW:
348  fprintf_unfiltered (fp, "throw");
349  break;
350  case EX_EVENT_CATCH:
351  fprintf_unfiltered (fp, "catch");
352  break;
353  case EX_EVENT_RETHROW:
354  fprintf_unfiltered (fp, "rethrow");
355  break;
356  }
357  print_recreate_thread (b, fp);
358 }
359 
360 static void
361 handle_gnu_v3_exceptions (int tempflag, std::string &&except_rx,
362  const char *cond_string,
363  enum exception_event_kind ex_event, int from_tty)
364 {
365  std::unique_ptr<compiled_regex> pattern;
366 
367  if (!except_rx.empty ())
368  {
369  pattern.reset (new compiled_regex (except_rx.c_str (), REG_NOSUB,
370  _("invalid type-matching regexp")));
371  }
372 
373  std::unique_ptr<exception_catchpoint> cp (new exception_catchpoint ());
374 
375  init_catchpoint (cp.get (), get_current_arch (), tempflag, cond_string,
377  /* We need to reset 'type' in order for code in breakpoint.c to do
378  the right thing. */
379  cp->type = bp_breakpoint;
380  cp->kind = ex_event;
381  cp->exception_rx = std::move (except_rx);
382  cp->pattern = std::move (pattern);
383 
384  re_set_exception_catchpoint (cp.get ());
385 
386  install_breakpoint (0, std::move (cp), 1);
387 }
388 
389 /* Look for an "if" token in *STRING. The "if" token must be preceded
390  by whitespace.
391 
392  If there is any non-whitespace text between *STRING and the "if"
393  token, then it is returned in a newly-xmalloc'd string. Otherwise,
394  this returns NULL.
395 
396  STRING is updated to point to the "if" token, if it exists, or to
397  the end of the string. */
398 
399 static std::string
400 extract_exception_regexp (const char **string)
401 {
402  const char *start;
403  const char *last, *last_space;
404 
405  start = skip_spaces (*string);
406 
407  last = start;
408  last_space = start;
409  while (*last != '\0')
410  {
411  const char *if_token = last;
412 
413  /* Check for the "if". */
414  if (check_for_argument (&if_token, "if", 2))
415  break;
416 
417  /* No "if" token here. Skip to the next word start. */
418  last_space = skip_to_space (last);
419  last = skip_spaces (last_space);
420  }
421 
422  *string = last;
423  if (last_space > start)
424  return std::string (start, last_space - start);
425  return std::string ();
426 }
427 
428 /* Deal with "catch catch", "catch throw", and "catch rethrow"
429  commands. */
430 
431 static void
433  const char *arg,
434  int tempflag, int from_tty)
435 {
436  const char *cond_string = NULL;
437 
438  if (!arg)
439  arg = "";
440  arg = skip_spaces (arg);
441 
442  std::string except_rx = extract_exception_regexp (&arg);
443 
444  cond_string = ep_parse_optional_if_clause (&arg);
445 
446  if ((*arg != '\0') && !isspace (*arg))
447  error (_("Junk at end of arguments."));
448 
449  if (ex_event != EX_EVENT_THROW
450  && ex_event != EX_EVENT_CATCH
451  && ex_event != EX_EVENT_RETHROW)
452  error (_("Unsupported or unknown exception event; cannot catch it"));
453 
454  handle_gnu_v3_exceptions (tempflag, std::move (except_rx), cond_string,
455  ex_event, from_tty);
456 }
457 
458 /* Implementation of "catch catch" command. */
459 
460 static void
461 catch_catch_command (const char *arg, int from_tty,
462  struct cmd_list_element *command)
463 {
464  int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
465 
466  catch_exception_command_1 (EX_EVENT_CATCH, arg, tempflag, from_tty);
467 }
468 
469 /* Implementation of "catch throw" command. */
470 
471 static void
472 catch_throw_command (const char *arg, int from_tty,
473  struct cmd_list_element *command)
474 {
475  int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
476 
477  catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
478 }
479 
480 /* Implementation of "catch rethrow" command. */
481 
482 static void
483 catch_rethrow_command (const char *arg, int from_tty,
484  struct cmd_list_element *command)
485 {
486  int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
487 
488  catch_exception_command_1 (EX_EVENT_RETHROW, arg, tempflag, from_tty);
489 }
490 
491 
492 
493 /* Implement the 'make_value' method for the $_exception
494  internalvar. */
495 
496 static struct value *
497 compute_exception (struct gdbarch *argc, struct internalvar *var, void *ignore)
498 {
499  struct value *arg0, *arg1;
500  struct type *obj_type;
501 
502  fetch_probe_arguments (&arg0, &arg1);
503 
504  /* ARG0 is a pointer to the exception object. ARG1 is a pointer to
505  the std::type_info for the exception. Now we find the type from
506  the type_info and cast the result. */
507  obj_type = cplus_type_from_type_info (arg1);
508  return value_ind (value_cast (make_pointer_type (obj_type, NULL), arg0));
509 }
510 
511 /* Implementation of the '$_exception' variable. */
512 
513 static const struct internalvar_funcs exception_funcs =
514 {
516  NULL,
517  NULL
518 };
519 
520 
521 
522 static void
524 {
525  struct breakpoint_ops *ops;
526 
528 
529  /* GNU v3 exception catchpoints. */
531  *ops = bkpt_breakpoint_ops;
539 }
540 
541 void
543 {
545 
546  /* Add catch and tcatch sub-commands. */
547  add_catch_command ("catch", _("\
548 Catch an exception, when caught."),
550  NULL,
553  add_catch_command ("throw", _("\
554 Catch an exception, when thrown."),
556  NULL,
559  add_catch_command ("rethrow", _("\
560 Catch an exception, when rethrown."),
562  NULL,
565 
566  create_internalvar_type_lazy ("_exception", &exception_funcs, NULL);
567 }
const char * string
Definition: signals.c:50
Definition: probe.h:112
probe * prob
Definition: probe.h:253
bp_location * loc
Definition: breakpoint.h:702
void(* print_recreate)(struct breakpoint *, struct ui_file *fp)
Definition: breakpoint.h:593
static std::string extract_exception_regexp(const char **string)
static void print_recreate_exception_catchpoint(struct breakpoint *b, struct ui_file *fp)
struct frame_info * get_selected_frame(const char *message)
Definition: frame.c:1638
void * get_cmd_context(struct cmd_list_element *cmd)
Definition: cli-decode.c:148
virtual struct value * evaluate_argument(unsigned n, struct frame_info *frame)=0
void field_core_addr(const char *fldname, struct gdbarch *gdbarch, CORE_ADDR address)
Definition: ui-out.c:513
CORE_ADDR get_frame_pc(struct frame_info *frame)
Definition: frame.c:2376
void field_string(const char *fldname, const char *string)
Definition: ui-out.c:544
bfd_vma CORE_ADDR
Definition: common-types.h:41
static void check_status_exception_catchpoint(struct bpstats *bs)
static const struct internalvar_funcs exception_funcs
#define CATCH_TEMPORARY
Definition: breakpoint.h:1283
enum print_stop_action(* print_it)(struct bpstats *bs)
Definition: breakpoint.h:568
void install_breakpoint(int internal, std::unique_ptr< breakpoint > &&arg, int update_gll)
Definition: breakpoint.c:8256
void annotate_field(int num)
Definition: annotate.c:177
void(* print_mention)(struct breakpoint *)
Definition: breakpoint.h:590
static struct value * compute_exception(struct gdbarch *argc, struct internalvar *var, void *ignore)
struct type * make_pointer_type(struct type *type, struct type **typeptr)
Definition: gdbtypes.c:319
struct type * cplus_type_from_type_info(struct value *value)
Definition: cp-abi.c:206
struct value * value_ind(struct value *arg1)
Definition: valops.c:1542
static void print_mention_exception_catchpoint(struct breakpoint *b)
static void catch_rethrow_command(const char *arg, int from_tty, struct cmd_list_element *command)
char * skip_spaces(char *chp)
Definition: common-utils.c:337
#define _(String)
Definition: gdb_locale.h:35
#define END_CATCH
void text(const char *string)
Definition: ui-out.c:581
const std::string & get_provider() const
Definition: probe.h:203
const char * probe
void initialize_explicit_location(struct explicit_location *explicit_loc)
Definition: location.c:78
static void handle_gnu_v3_exceptions(int tempflag, std::string &&except_rx, const char *cond_string, enum exception_event_kind ex_event, int from_tty)
static void fetch_probe_arguments(struct value **arg0, struct value **arg1)
#define TRY
static enum print_stop_action print_it_exception_catchpoint(bpstat bs)
#define CATCH(EXCEPTION, MASK)
bpdisp disposition
Definition: breakpoint.h:697
static void print_one_exception_catchpoint(struct breakpoint *b, struct bp_location **last_loc)
exception_event_kind
const std::string & get_name() const
Definition: probe.h:197
void fprintf_unfiltered(struct ui_file *stream, const char *format,...)
Definition: utils.c:2018
void exception_print(struct ui_file *file, struct gdb_exception e)
Definition: exceptions.c:109
static void catch_exception_command_1(enum exception_event_kind ex_event, const char *arg, int tempflag, int from_tty)
static enum exception_event_kind classify_exception_breakpoint(struct breakpoint *b)
#define current_uiout
Definition: ui-out.h:39
#define CATCH_PERMANENT
Definition: breakpoint.h:1282
void update_breakpoint_locations(struct breakpoint *b, struct program_space *filter_pspace, gdb::array_view< const symtab_and_line > sals, gdb::array_view< const symtab_and_line > sals_end)
Definition: breakpoint.c:13646
std::vector< symtab_and_line > parse_probes(const struct event_location *location, struct program_space *search_pspace, struct linespec_result *canonical)
Definition: probe.c:119
static struct breakpoint_ops gnu_v3_exception_catchpoint_ops
Definition: gdbtypes.h:749
struct gdbarch * get_current_arch(void)
Definition: arch-utils.c:798
void _initialize_break_catch_throw(void)
struct value * value_cast(struct type *type, struct value *arg2)
Definition: valops.c:351
event_location_up new_explicit_location(const struct explicit_location *explicit_loc)
Definition: location.c:178
const char * skip_to_space(const char *chp)
Definition: common-utils.c:361
std::unique_ptr< event_location, event_location_deleter > event_location_up
Definition: location.h:140
enum exception_event_kind kind
struct breakpoint_ops bkpt_breakpoint_ops
Definition: breakpoint.c:255
virtual unsigned get_argument_count(struct frame_info *frame)=0
void(* check_status)(struct bpstats *bs)
Definition: breakpoint.h:554
static void catch_throw_command(const char *arg, int from_tty, struct cmd_list_element *command)
std::string cplus_typename_from_type_info(struct value *value)
Definition: cp-abi.c:216
Definition: value.c:169
const char * ep_parse_optional_if_clause(const char **arg)
Definition: breakpoint.c:11279
Definition: ui-out.h:77
CORE_ADDR address
Definition: breakpoint.h:427
void print_recreate_thread(struct breakpoint *b, struct ui_file *fp)
Definition: breakpoint.c:15093
event_location_up new_probe_location(const char *probe)
Definition: location.c:155
struct breakpoint * breakpoint_at
Definition: breakpoint.h:1122
char * function_name
Definition: location.h:91
print_stop_action
Definition: breakpoint.h:498
void throw_exception(struct gdb_exception exception)
static void catch_catch_command(const char *arg, int from_tty, struct cmd_list_element *command)
#define gdb_stderr
Definition: utils.h:344
const char * async_reason_lookup(enum async_reply_reason reason)
Definition: mi-common.c:49
void add_catch_command(const char *name, const char *docstring, cmd_const_sfunc_ftype *sfunc, completer_ftype *completer, void *user_data_catch, void *user_data_tcatch)
Definition: breakpoint.c:15317
void field_int(const char *fldname, int value)
Definition: ui-out.c:486
bool shlib_disabled
Definition: breakpoint.h:382
static const struct exception_names exception_functions[]
void get_user_print_options(struct value_print_options *opts)
Definition: valprint.c:120
std::string cp_canonicalize_string(const char *string)
Definition: cp-support.c:552
void(* print_one_detail)(const struct breakpoint *, struct ui_out *)
Definition: breakpoint.h:586
struct bound_probe find_probe_by_pc(CORE_ADDR pc)
Definition: probe.c:247
static void re_set_exception_catchpoint(struct breakpoint *self)
struct program_space * current_program_space
Definition: progspace.c:35
static int ignore(struct target_ops *ops, struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
Definition: corelow.c:879
void initialize_breakpoint_ops(void)
Definition: breakpoint.c:15414
char stop
Definition: breakpoint.h:1134
struct gdbarch * gdbarch
Definition: breakpoint.h:413
void annotate_catchpoint(int num)
Definition: annotate.c:87
std::unique_ptr< compiled_regex > pattern
static void initialize_throw_catchpoint_ops(void)
void(* print_one)(struct breakpoint *, struct bp_location **)
Definition: breakpoint.h:572
void maybe_print_thread_hit_breakpoint(struct ui_out *uiout)
Definition: breakpoint.c:4532
struct internalvar * create_internalvar_type_lazy(const char *name, const struct internalvar_funcs *funcs, void *data)
Definition: value.c:2177
void error(const char *fmt,...)
Definition: errors.c:38
void(* re_set)(struct breakpoint *self)
Definition: breakpoint.h:528
int check_for_argument(const char **str, const char *arg, int arg_len)
Definition: cli-utils.c:297
static void print_one_detail_exception_catchpoint(const struct breakpoint *b, struct ui_out *uiout)
bool is_mi_like_p()
Definition: ui-out.c:622
const char * bpdisp_text(enum bpdisp disp)
Definition: breakpoint.c:314
void init_catchpoint(struct breakpoint *b, struct gdbarch *gdbarch, int tempflag, const char *cond_string, const struct breakpoint_ops *ops)
Definition: breakpoint.c:8241