198944Sobrien/* MI Command Set - breakpoint and watchpoint commands. 298944Sobrien Copyright 2000, 2001, 2002 Free Software Foundation, Inc. 398944Sobrien Contributed by Cygnus Solutions (a Red Hat company). 498944Sobrien 598944Sobrien This file is part of GDB. 698944Sobrien 798944Sobrien This program is free software; you can redistribute it and/or modify 898944Sobrien it under the terms of the GNU General Public License as published by 998944Sobrien the Free Software Foundation; either version 2 of the License, or 1098944Sobrien (at your option) any later version. 1198944Sobrien 1298944Sobrien This program is distributed in the hope that it will be useful, 1398944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1498944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1598944Sobrien GNU General Public License for more details. 1698944Sobrien 1798944Sobrien You should have received a copy of the GNU General Public License 1898944Sobrien along with this program; if not, write to the Free Software 1998944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2098944Sobrien Boston, MA 02111-1307, USA. */ 2198944Sobrien 2298944Sobrien#include "defs.h" 2398944Sobrien#include "mi-cmds.h" 2498944Sobrien#include "ui-out.h" 2598944Sobrien#include "mi-out.h" 2698944Sobrien#include "breakpoint.h" 2798944Sobrien#include "gdb_string.h" 2898944Sobrien#include "mi-getopt.h" 2998944Sobrien#include "gdb-events.h" 3098944Sobrien#include "gdb.h" 3198944Sobrien 3298944Sobrienenum 3398944Sobrien { 3498944Sobrien FROM_TTY = 0 3598944Sobrien }; 3698944Sobrien 3798944Sobrien/* Output a single breakpoint. */ 3898944Sobrien 3998944Sobrienstatic void 4098944Sobrienbreakpoint_notify (int b) 4198944Sobrien{ 4298944Sobrien gdb_breakpoint_query (uiout, b); 4398944Sobrien} 4498944Sobrien 4598944Sobrien 4698944Sobrienstruct gdb_events breakpoint_hooks = 4798944Sobrien{ 4898944Sobrien breakpoint_notify, 4998944Sobrien breakpoint_notify, 5098944Sobrien breakpoint_notify, 5198944Sobrien}; 5298944Sobrien 5398944Sobrien 5498944Sobrienenum bp_type 5598944Sobrien { 5698944Sobrien REG_BP, 5798944Sobrien HW_BP, 5898944Sobrien REGEXP_BP 5998944Sobrien }; 6098944Sobrien 6198944Sobrien/* Insert a breakpoint. The type of breakpoint is specified by the 6298944Sobrien first argument: -break-insert <location> --> insert a regular 6398944Sobrien breakpoint. -break-insert -t <location> --> insert a temporary 6498944Sobrien breakpoint. -break-insert -h <location> --> insert an hardware 6598944Sobrien breakpoint. -break-insert -t -h <location> --> insert a temporary 6698944Sobrien hw bp. 6798944Sobrien -break-insert -r <regexp> --> insert a bp at functions matching 6898944Sobrien <regexp> */ 6998944Sobrien 7098944Sobrienenum mi_cmd_result 7198944Sobrienmi_cmd_break_insert (char *command, char **argv, int argc) 7298944Sobrien{ 7398944Sobrien char *address = NULL; 7498944Sobrien enum bp_type type = REG_BP; 7598944Sobrien int temp_p = 0; 7698944Sobrien int thread = -1; 7798944Sobrien int ignore_count = 0; 7898944Sobrien char *condition = NULL; 7998944Sobrien enum gdb_rc rc; 8098944Sobrien struct gdb_events *old_hooks; 8198944Sobrien enum opt 8298944Sobrien { 8398944Sobrien HARDWARE_OPT, TEMP_OPT /*, REGEXP_OPT */ , CONDITION_OPT, 8498944Sobrien IGNORE_COUNT_OPT, THREAD_OPT 8598944Sobrien }; 8698944Sobrien static struct mi_opt opts[] = 8798944Sobrien { 8898944Sobrien {"h", HARDWARE_OPT, 0}, 8998944Sobrien {"t", TEMP_OPT, 0}, 9098944Sobrien {"c", CONDITION_OPT, 1}, 9198944Sobrien {"i", IGNORE_COUNT_OPT, 1}, 9298944Sobrien {"p", THREAD_OPT, 1}, 9398944Sobrien 0 9498944Sobrien }; 9598944Sobrien 9698944Sobrien /* Parse arguments. It could be -r or -h or -t, <location> or ``--'' 9798944Sobrien to denote the end of the option list. */ 9898944Sobrien int optind = 0; 9998944Sobrien char *optarg; 10098944Sobrien while (1) 10198944Sobrien { 10298944Sobrien int opt = mi_getopt ("mi_cmd_break_insert", argc, argv, opts, &optind, &optarg); 10398944Sobrien if (opt < 0) 10498944Sobrien break; 10598944Sobrien switch ((enum opt) opt) 10698944Sobrien { 10798944Sobrien case TEMP_OPT: 10898944Sobrien temp_p = 1; 10998944Sobrien break; 11098944Sobrien case HARDWARE_OPT: 11198944Sobrien type = HW_BP; 11298944Sobrien break; 11398944Sobrien#if 0 11498944Sobrien case REGEXP_OPT: 11598944Sobrien type = REGEXP_BP; 11698944Sobrien break; 11798944Sobrien#endif 11898944Sobrien case CONDITION_OPT: 11998944Sobrien condition = optarg; 12098944Sobrien break; 12198944Sobrien case IGNORE_COUNT_OPT: 12298944Sobrien ignore_count = atol (optarg); 12398944Sobrien break; 12498944Sobrien case THREAD_OPT: 12598944Sobrien thread = atol (optarg); 12698944Sobrien break; 12798944Sobrien } 12898944Sobrien } 12998944Sobrien 13098944Sobrien if (optind >= argc) 13198944Sobrien error ("mi_cmd_break_insert: Missing <location>"); 13298944Sobrien if (optind < argc - 1) 13398944Sobrien error ("mi_cmd_break_insert: Garbage following <location>"); 13498944Sobrien address = argv[optind]; 13598944Sobrien 13698944Sobrien /* Now we have what we need, let's insert the breakpoint! */ 13798944Sobrien old_hooks = set_gdb_event_hooks (&breakpoint_hooks); 13898944Sobrien switch (type) 13998944Sobrien { 14098944Sobrien case REG_BP: 14198944Sobrien rc = gdb_breakpoint (address, condition, 14298944Sobrien 0 /*hardwareflag */ , temp_p, 14398944Sobrien thread, ignore_count); 14498944Sobrien break; 14598944Sobrien case HW_BP: 14698944Sobrien rc = gdb_breakpoint (address, condition, 14798944Sobrien 1 /*hardwareflag */ , temp_p, 14898944Sobrien thread, ignore_count); 14998944Sobrien break; 15098944Sobrien#if 0 15198944Sobrien case REGEXP_BP: 15298944Sobrien if (temp_p) 15398944Sobrien error ("mi_cmd_break_insert: Unsupported tempoary regexp breakpoint"); 15498944Sobrien else 15598944Sobrien rbreak_command_wrapper (address, FROM_TTY); 15698944Sobrien return MI_CMD_DONE; 15798944Sobrien break; 15898944Sobrien#endif 15998944Sobrien default: 16098944Sobrien internal_error (__FILE__, __LINE__, 16198944Sobrien "mi_cmd_break_insert: Bad switch."); 16298944Sobrien } 16398944Sobrien set_gdb_event_hooks (old_hooks); 16498944Sobrien 16598944Sobrien if (rc == GDB_RC_FAIL) 16698944Sobrien return MI_CMD_CAUGHT_ERROR; 16798944Sobrien else 16898944Sobrien return MI_CMD_DONE; 16998944Sobrien} 17098944Sobrien 17198944Sobrienenum wp_type 17298944Sobrien{ 17398944Sobrien REG_WP, 17498944Sobrien READ_WP, 17598944Sobrien ACCESS_WP 17698944Sobrien}; 17798944Sobrien 17898944Sobrien/* Insert a watchpoint. The type of watchpoint is specified by the 17998944Sobrien first argument: 18098944Sobrien -break-watch <expr> --> insert a regular wp. 18198944Sobrien -break-watch -r <expr> --> insert a read watchpoint. 18298944Sobrien -break-watch -a <expr> --> insert an access wp. */ 18398944Sobrien 18498944Sobrienenum mi_cmd_result 18598944Sobrienmi_cmd_break_watch (char *command, char **argv, int argc) 18698944Sobrien{ 18798944Sobrien char *expr = NULL; 18898944Sobrien enum wp_type type = REG_WP; 18998944Sobrien enum opt 19098944Sobrien { 19198944Sobrien READ_OPT, ACCESS_OPT 19298944Sobrien }; 19398944Sobrien static struct mi_opt opts[] = 19498944Sobrien { 19598944Sobrien {"r", READ_OPT, 0}, 19698944Sobrien {"a", ACCESS_OPT, 0}, 19798944Sobrien 0 19898944Sobrien }; 19998944Sobrien 20098944Sobrien /* Parse arguments. */ 20198944Sobrien int optind = 0; 20298944Sobrien char *optarg; 20398944Sobrien while (1) 20498944Sobrien { 20598944Sobrien int opt = mi_getopt ("mi_cmd_break_watch", argc, argv, opts, &optind, &optarg); 20698944Sobrien if (opt < 0) 20798944Sobrien break; 20898944Sobrien switch ((enum opt) opt) 20998944Sobrien { 21098944Sobrien case READ_OPT: 21198944Sobrien type = READ_WP; 21298944Sobrien break; 21398944Sobrien case ACCESS_OPT: 21498944Sobrien type = ACCESS_WP; 21598944Sobrien break; 21698944Sobrien } 21798944Sobrien } 21898944Sobrien if (optind >= argc) 21998944Sobrien error ("mi_cmd_break_watch: Missing <expression>"); 22098944Sobrien if (optind < argc - 1) 22198944Sobrien error ("mi_cmd_break_watch: Garbage following <expression>"); 22298944Sobrien expr = argv[optind]; 22398944Sobrien 22498944Sobrien /* Now we have what we need, let's insert the watchpoint! */ 22598944Sobrien switch (type) 22698944Sobrien { 22798944Sobrien case REG_WP: 22898944Sobrien watch_command_wrapper (expr, FROM_TTY); 22998944Sobrien break; 23098944Sobrien case READ_WP: 23198944Sobrien rwatch_command_wrapper (expr, FROM_TTY); 23298944Sobrien break; 23398944Sobrien case ACCESS_WP: 23498944Sobrien awatch_command_wrapper (expr, FROM_TTY); 23598944Sobrien break; 23698944Sobrien default: 23798944Sobrien error ("mi_cmd_break_watch: Unknown watchpoint type."); 23898944Sobrien } 23998944Sobrien return MI_CMD_DONE; 24098944Sobrien} 241