xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/break-catch-load.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1*6881a400Schristos /* Everything about load/unload catchpoints, for GDB.
2*6881a400Schristos 
3*6881a400Schristos    Copyright (C) 1986-2023 Free Software Foundation, Inc.
4*6881a400Schristos 
5*6881a400Schristos    This file is part of GDB.
6*6881a400Schristos 
7*6881a400Schristos    This program is free software; you can redistribute it and/or modify
8*6881a400Schristos    it under the terms of the GNU General Public License as published by
9*6881a400Schristos    the Free Software Foundation; either version 3 of the License, or
10*6881a400Schristos    (at your option) any later version.
11*6881a400Schristos 
12*6881a400Schristos    This program is distributed in the hope that it will be useful,
13*6881a400Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*6881a400Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*6881a400Schristos    GNU General Public License for more details.
16*6881a400Schristos 
17*6881a400Schristos    You should have received a copy of the GNU General Public License
18*6881a400Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19*6881a400Schristos 
20*6881a400Schristos #include "defs.h"
21*6881a400Schristos 
22*6881a400Schristos #include "annotate.h"
23*6881a400Schristos #include "arch-utils.h"
24*6881a400Schristos #include "breakpoint.h"
25*6881a400Schristos #include "cli/cli-decode.h"
26*6881a400Schristos #include "mi/mi-common.h"
27*6881a400Schristos #include "progspace.h"
28*6881a400Schristos #include "solist.h"
29*6881a400Schristos #include "target.h"
30*6881a400Schristos #include "valprint.h"
31*6881a400Schristos 
32*6881a400Schristos /* An instance of this type is used to represent an solib catchpoint.
33*6881a400Schristos    A breakpoint is really of this type iff its ops pointer points to
34*6881a400Schristos    CATCH_SOLIB_BREAKPOINT_OPS.  */
35*6881a400Schristos 
36*6881a400Schristos struct solib_catchpoint : public catchpoint
37*6881a400Schristos {
38*6881a400Schristos   solib_catchpoint (struct gdbarch *gdbarch, bool temp,
39*6881a400Schristos 		    const char *cond_string,
40*6881a400Schristos 		    bool is_load_, const char *arg)
41*6881a400Schristos     : catchpoint (gdbarch, temp, cond_string),
42*6881a400Schristos       is_load (is_load_),
43*6881a400Schristos       regex (arg == nullptr ? nullptr : make_unique_xstrdup (arg)),
44*6881a400Schristos       compiled (arg == nullptr
45*6881a400Schristos 		? nullptr
46*6881a400Schristos 		: new compiled_regex (arg, REG_NOSUB, _("Invalid regexp")))
47*6881a400Schristos   {
48*6881a400Schristos   }
49*6881a400Schristos 
50*6881a400Schristos   int insert_location (struct bp_location *) override;
51*6881a400Schristos   int remove_location (struct bp_location *,
52*6881a400Schristos 		       enum remove_bp_reason reason) override;
53*6881a400Schristos   int breakpoint_hit (const struct bp_location *bl,
54*6881a400Schristos 		      const address_space *aspace,
55*6881a400Schristos 		      CORE_ADDR bp_addr,
56*6881a400Schristos 		      const target_waitstatus &ws) override;
57*6881a400Schristos   void check_status (struct bpstat *bs) override;
58*6881a400Schristos   enum print_stop_action print_it (const bpstat *bs) const override;
59*6881a400Schristos   bool print_one (bp_location **) const override;
60*6881a400Schristos   void print_mention () const override;
61*6881a400Schristos   void print_recreate (struct ui_file *fp) const override;
62*6881a400Schristos 
63*6881a400Schristos   /* True for "catch load", false for "catch unload".  */
64*6881a400Schristos   bool is_load;
65*6881a400Schristos 
66*6881a400Schristos   /* Regular expression to match, if any.  COMPILED is only valid when
67*6881a400Schristos      REGEX is non-NULL.  */
68*6881a400Schristos   gdb::unique_xmalloc_ptr<char> regex;
69*6881a400Schristos   std::unique_ptr<compiled_regex> compiled;
70*6881a400Schristos };
71*6881a400Schristos 
72*6881a400Schristos int
73*6881a400Schristos solib_catchpoint::insert_location (struct bp_location *ignore)
74*6881a400Schristos {
75*6881a400Schristos   return 0;
76*6881a400Schristos }
77*6881a400Schristos 
78*6881a400Schristos int
79*6881a400Schristos solib_catchpoint::remove_location (struct bp_location *ignore,
80*6881a400Schristos 				   enum remove_bp_reason reason)
81*6881a400Schristos {
82*6881a400Schristos   return 0;
83*6881a400Schristos }
84*6881a400Schristos 
85*6881a400Schristos int
86*6881a400Schristos solib_catchpoint::breakpoint_hit (const struct bp_location *bl,
87*6881a400Schristos 				  const address_space *aspace,
88*6881a400Schristos 				  CORE_ADDR bp_addr,
89*6881a400Schristos 				  const target_waitstatus &ws)
90*6881a400Schristos {
91*6881a400Schristos   if (ws.kind () == TARGET_WAITKIND_LOADED)
92*6881a400Schristos     return 1;
93*6881a400Schristos 
94*6881a400Schristos   for (breakpoint *other : all_breakpoints ())
95*6881a400Schristos     {
96*6881a400Schristos       if (other == bl->owner)
97*6881a400Schristos 	continue;
98*6881a400Schristos 
99*6881a400Schristos       if (other->type != bp_shlib_event)
100*6881a400Schristos 	continue;
101*6881a400Schristos 
102*6881a400Schristos       if (pspace != NULL && other->pspace != pspace)
103*6881a400Schristos 	continue;
104*6881a400Schristos 
105*6881a400Schristos       for (bp_location *other_bl : other->locations ())
106*6881a400Schristos 	{
107*6881a400Schristos 	  if (other->breakpoint_hit (other_bl, aspace, bp_addr, ws))
108*6881a400Schristos 	    return 1;
109*6881a400Schristos 	}
110*6881a400Schristos     }
111*6881a400Schristos 
112*6881a400Schristos   return 0;
113*6881a400Schristos }
114*6881a400Schristos 
115*6881a400Schristos void
116*6881a400Schristos solib_catchpoint::check_status (struct bpstat *bs)
117*6881a400Schristos {
118*6881a400Schristos   if (is_load)
119*6881a400Schristos     {
120*6881a400Schristos       for (so_list *iter : current_program_space->added_solibs)
121*6881a400Schristos 	{
122*6881a400Schristos 	  if (!regex
123*6881a400Schristos 	      || compiled->exec (iter->so_name, 0, NULL, 0) == 0)
124*6881a400Schristos 	    return;
125*6881a400Schristos 	}
126*6881a400Schristos     }
127*6881a400Schristos   else
128*6881a400Schristos     {
129*6881a400Schristos       for (const std::string &iter : current_program_space->deleted_solibs)
130*6881a400Schristos 	{
131*6881a400Schristos 	  if (!regex
132*6881a400Schristos 	      || compiled->exec (iter.c_str (), 0, NULL, 0) == 0)
133*6881a400Schristos 	    return;
134*6881a400Schristos 	}
135*6881a400Schristos     }
136*6881a400Schristos 
137*6881a400Schristos   bs->stop = 0;
138*6881a400Schristos   bs->print_it = print_it_noop;
139*6881a400Schristos }
140*6881a400Schristos 
141*6881a400Schristos enum print_stop_action
142*6881a400Schristos solib_catchpoint::print_it (const bpstat *bs) const
143*6881a400Schristos {
144*6881a400Schristos   struct breakpoint *b = bs->breakpoint_at;
145*6881a400Schristos   struct ui_out *uiout = current_uiout;
146*6881a400Schristos 
147*6881a400Schristos   annotate_catchpoint (b->number);
148*6881a400Schristos   maybe_print_thread_hit_breakpoint (uiout);
149*6881a400Schristos   if (b->disposition == disp_del)
150*6881a400Schristos     uiout->text ("Temporary catchpoint ");
151*6881a400Schristos   else
152*6881a400Schristos     uiout->text ("Catchpoint ");
153*6881a400Schristos   uiout->field_signed ("bkptno", b->number);
154*6881a400Schristos   uiout->text ("\n");
155*6881a400Schristos   if (uiout->is_mi_like_p ())
156*6881a400Schristos     uiout->field_string ("disp", bpdisp_text (b->disposition));
157*6881a400Schristos   print_solib_event (true);
158*6881a400Schristos   return PRINT_SRC_AND_LOC;
159*6881a400Schristos }
160*6881a400Schristos 
161*6881a400Schristos bool
162*6881a400Schristos solib_catchpoint::print_one (bp_location **locs) const
163*6881a400Schristos {
164*6881a400Schristos   struct value_print_options opts;
165*6881a400Schristos   struct ui_out *uiout = current_uiout;
166*6881a400Schristos 
167*6881a400Schristos   get_user_print_options (&opts);
168*6881a400Schristos   /* Field 4, the address, is omitted (which makes the columns not
169*6881a400Schristos      line up too nicely with the headers, but the effect is relatively
170*6881a400Schristos      readable).  */
171*6881a400Schristos   if (opts.addressprint)
172*6881a400Schristos     {
173*6881a400Schristos       annotate_field (4);
174*6881a400Schristos       uiout->field_skip ("addr");
175*6881a400Schristos     }
176*6881a400Schristos 
177*6881a400Schristos   std::string msg;
178*6881a400Schristos   annotate_field (5);
179*6881a400Schristos   if (is_load)
180*6881a400Schristos     {
181*6881a400Schristos       if (regex)
182*6881a400Schristos 	msg = string_printf (_("load of library matching %s"),
183*6881a400Schristos 			     regex.get ());
184*6881a400Schristos       else
185*6881a400Schristos 	msg = _("load of library");
186*6881a400Schristos     }
187*6881a400Schristos   else
188*6881a400Schristos     {
189*6881a400Schristos       if (regex)
190*6881a400Schristos 	msg = string_printf (_("unload of library matching %s"),
191*6881a400Schristos 			     regex.get ());
192*6881a400Schristos       else
193*6881a400Schristos 	msg = _("unload of library");
194*6881a400Schristos     }
195*6881a400Schristos   uiout->field_string ("what", msg);
196*6881a400Schristos 
197*6881a400Schristos   if (uiout->is_mi_like_p ())
198*6881a400Schristos     uiout->field_string ("catch-type", is_load ? "load" : "unload");
199*6881a400Schristos 
200*6881a400Schristos   return true;
201*6881a400Schristos }
202*6881a400Schristos 
203*6881a400Schristos void
204*6881a400Schristos solib_catchpoint::print_mention () const
205*6881a400Schristos {
206*6881a400Schristos   gdb_printf (_("Catchpoint %d (%s)"), number,
207*6881a400Schristos 	      is_load ? "load" : "unload");
208*6881a400Schristos }
209*6881a400Schristos 
210*6881a400Schristos void
211*6881a400Schristos solib_catchpoint::print_recreate (struct ui_file *fp) const
212*6881a400Schristos {
213*6881a400Schristos   gdb_printf (fp, "%s %s",
214*6881a400Schristos 	      disposition == disp_del ? "tcatch" : "catch",
215*6881a400Schristos 	      is_load ? "load" : "unload");
216*6881a400Schristos   if (regex)
217*6881a400Schristos     gdb_printf (fp, " %s", regex.get ());
218*6881a400Schristos   gdb_printf (fp, "\n");
219*6881a400Schristos }
220*6881a400Schristos 
221*6881a400Schristos /* See breakpoint.h.  */
222*6881a400Schristos 
223*6881a400Schristos void
224*6881a400Schristos add_solib_catchpoint (const char *arg, bool is_load, bool is_temp, bool enabled)
225*6881a400Schristos {
226*6881a400Schristos   struct gdbarch *gdbarch = get_current_arch ();
227*6881a400Schristos 
228*6881a400Schristos   if (!arg)
229*6881a400Schristos     arg = "";
230*6881a400Schristos   arg = skip_spaces (arg);
231*6881a400Schristos   if (*arg == '\0')
232*6881a400Schristos     arg = nullptr;
233*6881a400Schristos 
234*6881a400Schristos   std::unique_ptr<solib_catchpoint> c (new solib_catchpoint (gdbarch, is_temp,
235*6881a400Schristos 							     nullptr,
236*6881a400Schristos 							     is_load, arg));
237*6881a400Schristos 
238*6881a400Schristos   c->enable_state = enabled ? bp_enabled : bp_disabled;
239*6881a400Schristos 
240*6881a400Schristos   install_breakpoint (0, std::move (c), 1);
241*6881a400Schristos }
242*6881a400Schristos 
243*6881a400Schristos /* A helper function that does all the work for "catch load" and
244*6881a400Schristos    "catch unload".  */
245*6881a400Schristos 
246*6881a400Schristos static void
247*6881a400Schristos catch_load_or_unload (const char *arg, int from_tty, int is_load,
248*6881a400Schristos 		      struct cmd_list_element *command)
249*6881a400Schristos {
250*6881a400Schristos   const int enabled = 1;
251*6881a400Schristos   bool temp = command->context () == CATCH_TEMPORARY;
252*6881a400Schristos 
253*6881a400Schristos   add_solib_catchpoint (arg, is_load, temp, enabled);
254*6881a400Schristos }
255*6881a400Schristos 
256*6881a400Schristos static void
257*6881a400Schristos catch_load_command_1 (const char *arg, int from_tty,
258*6881a400Schristos 		      struct cmd_list_element *command)
259*6881a400Schristos {
260*6881a400Schristos   catch_load_or_unload (arg, from_tty, 1, command);
261*6881a400Schristos }
262*6881a400Schristos 
263*6881a400Schristos static void
264*6881a400Schristos catch_unload_command_1 (const char *arg, int from_tty,
265*6881a400Schristos 			struct cmd_list_element *command)
266*6881a400Schristos {
267*6881a400Schristos   catch_load_or_unload (arg, from_tty, 0, command);
268*6881a400Schristos }
269*6881a400Schristos 
270*6881a400Schristos void _initialize_break_catch_load ();
271*6881a400Schristos void
272*6881a400Schristos _initialize_break_catch_load ()
273*6881a400Schristos {
274*6881a400Schristos   add_catch_command ("load", _("Catch loads of shared libraries.\n\
275*6881a400Schristos Usage: catch load [REGEX]\n\
276*6881a400Schristos If REGEX is given, only stop for libraries matching the regular expression."),
277*6881a400Schristos 		     catch_load_command_1,
278*6881a400Schristos 		     NULL,
279*6881a400Schristos 		     CATCH_PERMANENT,
280*6881a400Schristos 		     CATCH_TEMPORARY);
281*6881a400Schristos   add_catch_command ("unload", _("Catch unloads of shared libraries.\n\
282*6881a400Schristos Usage: catch unload [REGEX]\n\
283*6881a400Schristos If REGEX is given, only stop for libraries matching the regular expression."),
284*6881a400Schristos 		     catch_unload_command_1,
285*6881a400Schristos 		     NULL,
286*6881a400Schristos 		     CATCH_PERMANENT,
287*6881a400Schristos 		     CATCH_TEMPORARY);
288*6881a400Schristos }
289