1 /* MI Command Set - catch commands. 2 Copyright (C) 2012-2023 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 "defs.h" 22 #include "arch-utils.h" 23 #include "breakpoint.h" 24 #include "ada-lang.h" 25 #include "mi-cmds.h" 26 #include "mi-getopt.h" 27 #include "mi-cmd-break.h" 28 29 /* Handler for the -catch-assert command. */ 30 31 void 32 mi_cmd_catch_assert (const char *cmd, char *argv[], int argc) 33 { 34 struct gdbarch *gdbarch = get_current_arch(); 35 std::string condition; 36 int enabled = 1; 37 int temp = 0; 38 39 int oind = 0; 40 char *oarg; 41 42 enum opt 43 { 44 OPT_CONDITION, OPT_DISABLED, OPT_TEMP, 45 }; 46 static const struct mi_opt opts[] = 47 { 48 { "c", OPT_CONDITION, 1}, 49 { "d", OPT_DISABLED, 0 }, 50 { "t", OPT_TEMP, 0 }, 51 { 0, 0, 0 } 52 }; 53 54 for (;;) 55 { 56 int opt = mi_getopt ("-catch-assert", argc, argv, opts, 57 &oind, &oarg); 58 59 if (opt < 0) 60 break; 61 62 switch ((enum opt) opt) 63 { 64 case OPT_CONDITION: 65 condition.assign (oarg); 66 break; 67 case OPT_DISABLED: 68 enabled = 0; 69 break; 70 case OPT_TEMP: 71 temp = 1; 72 break; 73 } 74 } 75 76 /* This command does not accept any argument. Make sure the user 77 did not provide any. */ 78 if (oind != argc) 79 error (_("Invalid argument: %s"), argv[oind]); 80 81 scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting (); 82 create_ada_exception_catchpoint (gdbarch, ada_catch_assert, std::string (), 83 condition, temp, enabled, 0); 84 } 85 86 /* Handler for the -catch-exception command. */ 87 88 void 89 mi_cmd_catch_exception (const char *cmd, char *argv[], int argc) 90 { 91 struct gdbarch *gdbarch = get_current_arch(); 92 std::string condition; 93 int enabled = 1; 94 std::string exception_name; 95 int temp = 0; 96 enum ada_exception_catchpoint_kind ex_kind = ada_catch_exception; 97 98 int oind = 0; 99 char *oarg; 100 101 enum opt 102 { 103 OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP, 104 OPT_UNHANDLED, 105 }; 106 static const struct mi_opt opts[] = 107 { 108 { "c", OPT_CONDITION, 1}, 109 { "d", OPT_DISABLED, 0 }, 110 { "e", OPT_EXCEPTION_NAME, 1 }, 111 { "t", OPT_TEMP, 0 }, 112 { "u", OPT_UNHANDLED, 0}, 113 { 0, 0, 0 } 114 }; 115 116 for (;;) 117 { 118 int opt = mi_getopt ("-catch-exception", argc, argv, opts, 119 &oind, &oarg); 120 121 if (opt < 0) 122 break; 123 124 switch ((enum opt) opt) 125 { 126 case OPT_CONDITION: 127 condition.assign (oarg); 128 break; 129 case OPT_DISABLED: 130 enabled = 0; 131 break; 132 case OPT_EXCEPTION_NAME: 133 exception_name = oarg; 134 break; 135 case OPT_TEMP: 136 temp = 1; 137 break; 138 case OPT_UNHANDLED: 139 ex_kind = ada_catch_exception_unhandled; 140 break; 141 } 142 } 143 144 /* This command does not accept any argument. Make sure the user 145 did not provide any. */ 146 if (oind != argc) 147 error (_("Invalid argument: %s"), argv[oind]); 148 149 /* Specifying an exception name does not make sense when requesting 150 an unhandled exception breakpoint. */ 151 if (ex_kind == ada_catch_exception_unhandled && !exception_name.empty ()) 152 error (_("\"-e\" and \"-u\" are mutually exclusive")); 153 154 scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting (); 155 create_ada_exception_catchpoint (gdbarch, ex_kind, 156 exception_name, 157 condition, temp, enabled, 0); 158 } 159 160 /* Handler for the -catch-handlers command. */ 161 162 void 163 mi_cmd_catch_handlers (const char *cmd, char *argv[], int argc) 164 { 165 struct gdbarch *gdbarch = get_current_arch (); 166 std::string condition; 167 int enabled = 1; 168 std::string exception_name; 169 int temp = 0; 170 171 int oind = 0; 172 char *oarg; 173 174 enum opt 175 { 176 OPT_CONDITION, OPT_DISABLED, OPT_EXCEPTION_NAME, OPT_TEMP 177 }; 178 static const struct mi_opt opts[] = 179 { 180 { "c", OPT_CONDITION, 1}, 181 { "d", OPT_DISABLED, 0 }, 182 { "e", OPT_EXCEPTION_NAME, 1 }, 183 { "t", OPT_TEMP, 0 }, 184 { 0, 0, 0 } 185 }; 186 187 for (;;) 188 { 189 int opt = mi_getopt ("-catch-handlers", argc, argv, opts, 190 &oind, &oarg); 191 192 if (opt < 0) 193 break; 194 195 switch ((enum opt) opt) 196 { 197 case OPT_CONDITION: 198 condition.assign (oarg); 199 break; 200 case OPT_DISABLED: 201 enabled = 0; 202 break; 203 case OPT_EXCEPTION_NAME: 204 exception_name = oarg; 205 break; 206 case OPT_TEMP: 207 temp = 1; 208 break; 209 } 210 } 211 212 /* This command does not accept any argument. Make sure the user 213 did not provide any. */ 214 if (oind != argc) 215 error (_("Invalid argument: %s"), argv[oind]); 216 217 scoped_restore restore_breakpoint_reporting 218 = setup_breakpoint_reporting (); 219 create_ada_exception_catchpoint (gdbarch, ada_catch_handlers, 220 exception_name, 221 condition, temp, enabled, 0); 222 } 223 224 /* Common path for the -catch-load and -catch-unload. */ 225 226 static void 227 mi_catch_load_unload (int load, char *argv[], int argc) 228 { 229 const char *actual_cmd = load ? "-catch-load" : "-catch-unload"; 230 int temp = 0; 231 int enabled = 1; 232 int oind = 0; 233 char *oarg; 234 enum opt 235 { 236 OPT_TEMP, 237 OPT_DISABLED, 238 }; 239 static const struct mi_opt opts[] = 240 { 241 { "t", OPT_TEMP, 0 }, 242 { "d", OPT_DISABLED, 0 }, 243 { 0, 0, 0 } 244 }; 245 246 for (;;) 247 { 248 int opt = mi_getopt (actual_cmd, argc, argv, opts, 249 &oind, &oarg); 250 251 if (opt < 0) 252 break; 253 254 switch ((enum opt) opt) 255 { 256 case OPT_TEMP: 257 temp = 1; 258 break; 259 case OPT_DISABLED: 260 enabled = 0; 261 break; 262 } 263 } 264 265 if (oind >= argc) 266 error (_("-catch-load/unload: Missing <library name>")); 267 if (oind < argc -1) 268 error (_("-catch-load/unload: Garbage following the <library name>")); 269 270 scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting (); 271 add_solib_catchpoint (argv[oind], load, temp, enabled); 272 } 273 274 /* Handler for the -catch-load. */ 275 276 void 277 mi_cmd_catch_load (const char *cmd, char *argv[], int argc) 278 { 279 mi_catch_load_unload (1, argv, argc); 280 } 281 282 283 /* Handler for the -catch-unload. */ 284 285 void 286 mi_cmd_catch_unload (const char *cmd, char *argv[], int argc) 287 { 288 mi_catch_load_unload (0, argv, argc); 289 } 290 291 /* Core handler for -catch-throw, -catch-rethrow, and -catch-catch 292 commands. The argument handling for all of these is identical, we just 293 pass KIND through to GDB's core to select the correct event type. */ 294 295 static void 296 mi_cmd_catch_exception_event (enum exception_event_kind kind, 297 const char *cmd, char *argv[], int argc) 298 { 299 char *regex = NULL; 300 bool temp = false; 301 int oind = 0; 302 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 341 mi_cmd_catch_throw (const char *cmd, char *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 349 mi_cmd_catch_rethrow (const char *cmd, char *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 357 mi_cmd_catch_catch (const char *cmd, char *argv[], int argc) 358 { 359 mi_cmd_catch_exception_event (EX_EVENT_CATCH, cmd, argv, argc); 360 } 361 362