1/* CLI Definitions for GDB, the GNU debugger. 2 3 Copyright (C) 2002-2020 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "defs.h" 21#include "cli-interp.h" 22#include "interps.h" 23#include "event-top.h" 24#include "ui-out.h" 25#include "cli-out.h" 26#include "top.h" /* for "execute_command" */ 27#include "infrun.h" 28#include "observable.h" 29#include "gdbthread.h" 30#include "thread-fsm.h" 31#include "inferior.h" 32 33cli_interp_base::cli_interp_base (const char *name) 34 : interp (name) 35{} 36 37cli_interp_base::~cli_interp_base () 38{} 39 40/* The console interpreter. */ 41 42class cli_interp final : public cli_interp_base 43{ 44 public: 45 explicit cli_interp (const char *name); 46 ~cli_interp (); 47 48 void init (bool top_level) override; 49 void resume () override; 50 void suspend () override; 51 gdb_exception exec (const char *command_str) override; 52 ui_out *interp_ui_out () override; 53 54 /* The ui_out for the console interpreter. */ 55 cli_ui_out *cli_uiout; 56}; 57 58cli_interp::cli_interp (const char *name) 59 : cli_interp_base (name) 60{ 61 /* Create a default uiout builder for the CLI. */ 62 this->cli_uiout = cli_out_new (gdb_stdout); 63} 64 65cli_interp::~cli_interp () 66{ 67 delete cli_uiout; 68} 69 70/* Suppress notification struct. */ 71struct cli_suppress_notification cli_suppress_notification = 72 { 73 0 /* user_selected_context_changed */ 74 }; 75 76/* Returns the INTERP's data cast as cli_interp if INTERP is a CLI, 77 and returns NULL otherwise. */ 78 79static struct cli_interp * 80as_cli_interp (struct interp *interp) 81{ 82 return dynamic_cast<cli_interp *> (interp); 83} 84 85/* Longjmp-safe wrapper for "execute_command". */ 86static struct gdb_exception safe_execute_command (struct ui_out *uiout, 87 const char *command, 88 int from_tty); 89 90/* See cli-interp.h. 91 92 Breakpoint hits should always be mirrored to a console. Deciding 93 what to mirror to a console wrt to breakpoints and random stops 94 gets messy real fast. E.g., say "s" trips on a breakpoint. We'd 95 clearly want to mirror the event to the console in this case. But 96 what about more complicated cases like "s&; thread n; s&", and one 97 of those steps spawning a new thread, and that thread hitting a 98 breakpoint? It's impossible in general to track whether the thread 99 had any relation to the commands that had been executed. So we 100 just simplify and always mirror breakpoints and random events to 101 all consoles. 102 103 OTOH, we should print the source line to the console when stepping 104 or other similar commands, iff the step was started by that console 105 (or in MI's case, by a console command), but not if it was started 106 with MI's -exec-step or similar. */ 107 108int 109should_print_stop_to_console (struct interp *console_interp, 110 struct thread_info *tp) 111{ 112 if ((bpstat_what (tp->control.stop_bpstat).main_action 113 == BPSTAT_WHAT_STOP_NOISY) 114 || tp->thread_fsm == NULL 115 || tp->thread_fsm->command_interp == console_interp 116 || !tp->thread_fsm->finished_p ()) 117 return 1; 118 return 0; 119} 120 121/* Observers for several run control events. If the interpreter is 122 quiet (i.e., another interpreter is being run with 123 interpreter-exec), print nothing. */ 124 125/* Observer for the normal_stop notification. */ 126 127static void 128cli_on_normal_stop (struct bpstats *bs, int print_frame) 129{ 130 if (!print_frame) 131 return; 132 133 SWITCH_THRU_ALL_UIS () 134 { 135 struct interp *interp = top_level_interpreter (); 136 struct cli_interp *cli = as_cli_interp (interp); 137 struct thread_info *thread; 138 139 if (cli == NULL) 140 continue; 141 142 thread = inferior_thread (); 143 if (should_print_stop_to_console (interp, thread)) 144 print_stop_event (cli->cli_uiout); 145 } 146} 147 148/* Observer for the signal_received notification. */ 149 150static void 151cli_on_signal_received (enum gdb_signal siggnal) 152{ 153 SWITCH_THRU_ALL_UIS () 154 { 155 struct cli_interp *cli = as_cli_interp (top_level_interpreter ()); 156 157 if (cli == NULL) 158 continue; 159 160 print_signal_received_reason (cli->cli_uiout, siggnal); 161 } 162} 163 164/* Observer for the end_stepping_range notification. */ 165 166static void 167cli_on_end_stepping_range (void) 168{ 169 SWITCH_THRU_ALL_UIS () 170 { 171 struct cli_interp *cli = as_cli_interp (top_level_interpreter ()); 172 173 if (cli == NULL) 174 continue; 175 176 print_end_stepping_range_reason (cli->cli_uiout); 177 } 178} 179 180/* Observer for the signalled notification. */ 181 182static void 183cli_on_signal_exited (enum gdb_signal siggnal) 184{ 185 SWITCH_THRU_ALL_UIS () 186 { 187 struct cli_interp *cli = as_cli_interp (top_level_interpreter ()); 188 189 if (cli == NULL) 190 continue; 191 192 print_signal_exited_reason (cli->cli_uiout, siggnal); 193 } 194} 195 196/* Observer for the exited notification. */ 197 198static void 199cli_on_exited (int exitstatus) 200{ 201 SWITCH_THRU_ALL_UIS () 202 { 203 struct cli_interp *cli = as_cli_interp (top_level_interpreter ()); 204 205 if (cli == NULL) 206 continue; 207 208 print_exited_reason (cli->cli_uiout, exitstatus); 209 } 210} 211 212/* Observer for the no_history notification. */ 213 214static void 215cli_on_no_history (void) 216{ 217 SWITCH_THRU_ALL_UIS () 218 { 219 struct cli_interp *cli = as_cli_interp (top_level_interpreter ()); 220 221 if (cli == NULL) 222 continue; 223 224 print_no_history_reason (cli->cli_uiout); 225 } 226} 227 228/* Observer for the sync_execution_done notification. */ 229 230static void 231cli_on_sync_execution_done (void) 232{ 233 struct cli_interp *cli = as_cli_interp (top_level_interpreter ()); 234 235 if (cli == NULL) 236 return; 237 238 display_gdb_prompt (NULL); 239} 240 241/* Observer for the command_error notification. */ 242 243static void 244cli_on_command_error (void) 245{ 246 struct cli_interp *cli = as_cli_interp (top_level_interpreter ()); 247 248 if (cli == NULL) 249 return; 250 251 display_gdb_prompt (NULL); 252} 253 254/* Observer for the user_selected_context_changed notification. */ 255 256static void 257cli_on_user_selected_context_changed (user_selected_what selection) 258{ 259 /* This event is suppressed. */ 260 if (cli_suppress_notification.user_selected_context) 261 return; 262 263 thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : NULL; 264 265 SWITCH_THRU_ALL_UIS () 266 { 267 struct cli_interp *cli = as_cli_interp (top_level_interpreter ()); 268 269 if (cli == NULL) 270 continue; 271 272 if (selection & USER_SELECTED_INFERIOR) 273 print_selected_inferior (cli->cli_uiout); 274 275 if (tp != NULL 276 && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME)))) 277 print_selected_thread_frame (cli->cli_uiout, selection); 278 } 279} 280 281/* pre_command_loop implementation. */ 282 283void 284cli_interp_base::pre_command_loop () 285{ 286 display_gdb_prompt (0); 287} 288 289/* These implement the cli out interpreter: */ 290 291void 292cli_interp::init (bool top_level) 293{ 294} 295 296void 297cli_interp::resume () 298{ 299 struct ui *ui = current_ui; 300 struct cli_interp *cli = this; 301 struct ui_file *stream; 302 303 /*sync_execution = 1; */ 304 305 /* gdb_setup_readline will change gdb_stdout. If the CLI was 306 previously writing to gdb_stdout, then set it to the new 307 gdb_stdout afterwards. */ 308 309 stream = cli->cli_uiout->set_stream (gdb_stdout); 310 if (stream != gdb_stdout) 311 { 312 cli->cli_uiout->set_stream (stream); 313 stream = NULL; 314 } 315 316 gdb_setup_readline (1); 317 318 ui->input_handler = command_line_handler; 319 320 if (stream != NULL) 321 cli->cli_uiout->set_stream (gdb_stdout); 322} 323 324void 325cli_interp::suspend () 326{ 327 gdb_disable_readline (); 328} 329 330gdb_exception 331cli_interp::exec (const char *command_str) 332{ 333 struct cli_interp *cli = this; 334 struct ui_file *old_stream; 335 struct gdb_exception result; 336 337 /* gdb_stdout could change between the time cli_uiout was 338 initialized and now. Since we're probably using a different 339 interpreter which has a new ui_file for gdb_stdout, use that one 340 instead of the default. 341 342 It is important that it gets reset everytime, since the user 343 could set gdb to use a different interpreter. */ 344 old_stream = cli->cli_uiout->set_stream (gdb_stdout); 345 result = safe_execute_command (cli->cli_uiout, command_str, 1); 346 cli->cli_uiout->set_stream (old_stream); 347 return result; 348} 349 350bool 351cli_interp_base::supports_command_editing () 352{ 353 return true; 354} 355 356static struct gdb_exception 357safe_execute_command (struct ui_out *command_uiout, const char *command, 358 int from_tty) 359{ 360 struct gdb_exception e; 361 362 /* Save and override the global ``struct ui_out'' builder. */ 363 scoped_restore saved_uiout = make_scoped_restore (¤t_uiout, 364 command_uiout); 365 366 try 367 { 368 execute_command (command, from_tty); 369 } 370 catch (gdb_exception &exception) 371 { 372 e = std::move (exception); 373 } 374 375 /* FIXME: cagney/2005-01-13: This shouldn't be needed. Instead the 376 caller should print the exception. */ 377 exception_print (gdb_stderr, e); 378 return e; 379} 380 381ui_out * 382cli_interp::interp_ui_out () 383{ 384 struct cli_interp *cli = (struct cli_interp *) this; 385 386 return cli->cli_uiout; 387} 388 389/* These hold the pushed copies of the gdb output files. 390 If NULL then nothing has yet been pushed. */ 391struct saved_output_files 392{ 393 ui_file *out; 394 ui_file *err; 395 ui_file *log; 396 ui_file *targ; 397 ui_file *targerr; 398 ui_file *file_to_delete; 399}; 400static saved_output_files saved_output; 401 402/* See cli-interp.h. */ 403 404void 405cli_interp_base::set_logging (ui_file_up logfile, bool logging_redirect, 406 bool debug_redirect) 407{ 408 if (logfile != nullptr) 409 { 410 saved_output.out = gdb_stdout; 411 saved_output.err = gdb_stderr; 412 saved_output.log = gdb_stdlog; 413 saved_output.targ = gdb_stdtarg; 414 saved_output.targerr = gdb_stdtargerr; 415 416 /* If something is being redirected, then grab logfile. */ 417 ui_file *logfile_p = nullptr; 418 if (logging_redirect || debug_redirect) 419 { 420 logfile_p = logfile.get (); 421 saved_output.file_to_delete = logfile_p; 422 } 423 424 /* If something is not being redirected, then a tee containing both the 425 logfile and stdout. */ 426 ui_file *tee = nullptr; 427 if (!logging_redirect || !debug_redirect) 428 { 429 tee = new tee_file (gdb_stdout, std::move (logfile)); 430 saved_output.file_to_delete = tee; 431 } 432 433 gdb_stdout = logging_redirect ? logfile_p : tee; 434 gdb_stdlog = debug_redirect ? logfile_p : tee; 435 gdb_stderr = logging_redirect ? logfile_p : tee; 436 gdb_stdtarg = logging_redirect ? logfile_p : tee; 437 gdb_stdtargerr = logging_redirect ? logfile_p : tee; 438 } 439 else 440 { 441 /* Delete the correct file. If it's the tee then the logfile will also 442 be deleted. */ 443 delete saved_output.file_to_delete; 444 445 gdb_stdout = saved_output.out; 446 gdb_stderr = saved_output.err; 447 gdb_stdlog = saved_output.log; 448 gdb_stdtarg = saved_output.targ; 449 gdb_stdtargerr = saved_output.targerr; 450 451 saved_output.out = nullptr; 452 saved_output.err = nullptr; 453 saved_output.log = nullptr; 454 saved_output.targ = nullptr; 455 saved_output.targerr = nullptr; 456 saved_output.file_to_delete = nullptr; 457 } 458} 459 460/* Factory for CLI interpreters. */ 461 462static struct interp * 463cli_interp_factory (const char *name) 464{ 465 return new cli_interp (name); 466} 467 468/* Standard gdb initialization hook. */ 469 470void _initialize_cli_interp (); 471void 472_initialize_cli_interp () 473{ 474 interp_factory_register (INTERP_CONSOLE, cli_interp_factory); 475 476 /* If changing this, remember to update tui-interp.c as well. */ 477 gdb::observers::normal_stop.attach (cli_on_normal_stop); 478 gdb::observers::end_stepping_range.attach (cli_on_end_stepping_range); 479 gdb::observers::signal_received.attach (cli_on_signal_received); 480 gdb::observers::signal_exited.attach (cli_on_signal_exited); 481 gdb::observers::exited.attach (cli_on_exited); 482 gdb::observers::no_history.attach (cli_on_no_history); 483 gdb::observers::sync_execution_done.attach (cli_on_sync_execution_done); 484 gdb::observers::command_error.attach (cli_on_command_error); 485 gdb::observers::user_selected_context_changed.attach 486 (cli_on_user_selected_context_changed); 487} 488