break-catch-exec.c 6.4 KB

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