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