1 /* CLI Definitions for GDB, the GNU debugger. 2 3 Copyright (C) 2002-2023 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 33 cli_interp_base::cli_interp_base (const char *name) 34 : interp (name) 35 {} 36 37 cli_interp_base::~cli_interp_base () 38 {} 39 40 /* The console interpreter. */ 41 42 class cli_interp final : public cli_interp_base 43 { 44 public: 45 explicit cli_interp (const char *name); 46 ~cli_interp () = default; 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 private: 55 56 /* The ui_out for the console interpreter. */ 57 std::unique_ptr<cli_ui_out> m_cli_uiout; 58 }; 59 60 cli_interp::cli_interp (const char *name) 61 : cli_interp_base (name), 62 m_cli_uiout (new cli_ui_out (gdb_stdout)) 63 { 64 } 65 66 /* Suppress notification struct. */ 67 struct cli_suppress_notification cli_suppress_notification; 68 69 /* Returns the INTERP's data cast as cli_interp_base if INTERP is a 70 console-like interpreter, and returns NULL otherwise. */ 71 72 static cli_interp_base * 73 as_cli_interp_base (interp *interp) 74 { 75 return dynamic_cast<cli_interp_base *> (interp); 76 } 77 78 /* Longjmp-safe wrapper for "execute_command". */ 79 static struct gdb_exception safe_execute_command (struct ui_out *uiout, 80 const char *command, 81 int from_tty); 82 83 /* See cli-interp.h. 84 85 Breakpoint hits should always be mirrored to a console. Deciding 86 what to mirror to a console wrt to breakpoints and random stops 87 gets messy real fast. E.g., say "s" trips on a breakpoint. We'd 88 clearly want to mirror the event to the console in this case. But 89 what about more complicated cases like "s&; thread n; s&", and one 90 of those steps spawning a new thread, and that thread hitting a 91 breakpoint? It's impossible in general to track whether the thread 92 had any relation to the commands that had been executed. So we 93 just simplify and always mirror breakpoints and random events to 94 all consoles. 95 96 OTOH, we should print the source line to the console when stepping 97 or other similar commands, iff the step was started by that console 98 (or in MI's case, by a console command), but not if it was started 99 with MI's -exec-step or similar. */ 100 101 int 102 should_print_stop_to_console (struct interp *console_interp, 103 struct thread_info *tp) 104 { 105 if ((bpstat_what (tp->control.stop_bpstat).main_action 106 == BPSTAT_WHAT_STOP_NOISY) 107 || tp->thread_fsm () == nullptr 108 || tp->thread_fsm ()->command_interp == console_interp 109 || !tp->thread_fsm ()->finished_p ()) 110 return 1; 111 return 0; 112 } 113 114 /* Observers for several run control events. If the interpreter is 115 quiet (i.e., another interpreter is being run with 116 interpreter-exec), print nothing. These are named "cli_base" as 117 they print to both CLI interpreters and TUI interpreters. */ 118 119 /* Observer for the normal_stop notification. */ 120 121 static void 122 cli_base_on_normal_stop (struct bpstat *bs, int print_frame) 123 { 124 if (!print_frame) 125 return; 126 127 /* This event is suppressed. */ 128 if (cli_suppress_notification.normal_stop) 129 return; 130 131 SWITCH_THRU_ALL_UIS () 132 { 133 struct interp *interp = top_level_interpreter (); 134 cli_interp_base *cli = as_cli_interp_base (interp); 135 if (cli == nullptr) 136 continue; 137 138 thread_info *thread = inferior_thread (); 139 if (should_print_stop_to_console (interp, thread)) 140 print_stop_event (cli->interp_ui_out ()); 141 } 142 } 143 144 /* Observer for the signal_received notification. */ 145 146 static void 147 cli_base_on_signal_received (enum gdb_signal siggnal) 148 { 149 SWITCH_THRU_ALL_UIS () 150 { 151 cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ()); 152 if (cli == nullptr) 153 continue; 154 155 print_signal_received_reason (cli->interp_ui_out (), siggnal); 156 } 157 } 158 159 /* Observer for the end_stepping_range notification. */ 160 161 static void 162 cli_base_on_end_stepping_range () 163 { 164 SWITCH_THRU_ALL_UIS () 165 { 166 cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ()); 167 if (cli == nullptr) 168 continue; 169 170 print_end_stepping_range_reason (cli->interp_ui_out ()); 171 } 172 } 173 174 /* Observer for the signalled notification. */ 175 176 static void 177 cli_base_on_signal_exited (enum gdb_signal siggnal) 178 { 179 SWITCH_THRU_ALL_UIS () 180 { 181 cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ()); 182 if (cli == nullptr) 183 continue; 184 185 print_signal_exited_reason (cli->interp_ui_out (), siggnal); 186 } 187 } 188 189 /* Observer for the exited notification. */ 190 191 static void 192 cli_base_on_exited (int exitstatus) 193 { 194 SWITCH_THRU_ALL_UIS () 195 { 196 cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ()); 197 if (cli == nullptr) 198 continue; 199 200 print_exited_reason (cli->interp_ui_out (), exitstatus); 201 } 202 } 203 204 /* Observer for the no_history notification. */ 205 206 static void 207 cli_base_on_no_history () 208 { 209 SWITCH_THRU_ALL_UIS () 210 { 211 cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ()); 212 if (cli == nullptr) 213 continue; 214 215 print_no_history_reason (cli->interp_ui_out ()); 216 } 217 } 218 219 /* Observer for the sync_execution_done notification. */ 220 221 static void 222 cli_base_on_sync_execution_done () 223 { 224 cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ()); 225 if (cli == nullptr) 226 return; 227 228 display_gdb_prompt (NULL); 229 } 230 231 /* Observer for the command_error notification. */ 232 233 static void 234 cli_base_on_command_error () 235 { 236 cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ()); 237 if (cli == nullptr) 238 return; 239 240 display_gdb_prompt (NULL); 241 } 242 243 /* Observer for the user_selected_context_changed notification. */ 244 245 static void 246 cli_base_on_user_selected_context_changed (user_selected_what selection) 247 { 248 /* This event is suppressed. */ 249 if (cli_suppress_notification.user_selected_context) 250 return; 251 252 thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : nullptr; 253 254 SWITCH_THRU_ALL_UIS () 255 { 256 cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ()); 257 if (cli == nullptr) 258 continue; 259 260 if (selection & USER_SELECTED_INFERIOR) 261 print_selected_inferior (cli->interp_ui_out ()); 262 263 if (tp != nullptr 264 && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME)))) 265 print_selected_thread_frame (cli->interp_ui_out (), selection); 266 } 267 } 268 269 /* pre_command_loop implementation. */ 270 271 void 272 cli_interp_base::pre_command_loop () 273 { 274 display_gdb_prompt (0); 275 } 276 277 /* These implement the cli out interpreter: */ 278 279 void 280 cli_interp::init (bool top_level) 281 { 282 } 283 284 void 285 cli_interp::resume () 286 { 287 struct ui *ui = current_ui; 288 struct ui_file *stream; 289 290 /*sync_execution = 1; */ 291 292 /* gdb_setup_readline will change gdb_stdout. If the CLI was 293 previously writing to gdb_stdout, then set it to the new 294 gdb_stdout afterwards. */ 295 296 stream = m_cli_uiout->set_stream (gdb_stdout); 297 if (stream != gdb_stdout) 298 { 299 m_cli_uiout->set_stream (stream); 300 stream = NULL; 301 } 302 303 gdb_setup_readline (1); 304 305 ui->input_handler = command_line_handler; 306 307 if (stream != NULL) 308 m_cli_uiout->set_stream (gdb_stdout); 309 } 310 311 void 312 cli_interp::suspend () 313 { 314 gdb_disable_readline (); 315 } 316 317 gdb_exception 318 cli_interp::exec (const char *command_str) 319 { 320 struct ui_file *old_stream; 321 struct gdb_exception result; 322 323 /* gdb_stdout could change between the time m_cli_uiout was 324 initialized and now. Since we're probably using a different 325 interpreter which has a new ui_file for gdb_stdout, use that one 326 instead of the default. 327 328 It is important that it gets reset everytime, since the user 329 could set gdb to use a different interpreter. */ 330 old_stream = m_cli_uiout->set_stream (gdb_stdout); 331 result = safe_execute_command (m_cli_uiout.get (), command_str, 1); 332 m_cli_uiout->set_stream (old_stream); 333 return result; 334 } 335 336 bool 337 cli_interp_base::supports_command_editing () 338 { 339 return true; 340 } 341 342 static struct gdb_exception 343 safe_execute_command (struct ui_out *command_uiout, const char *command, 344 int from_tty) 345 { 346 struct gdb_exception e; 347 348 /* Save and override the global ``struct ui_out'' builder. */ 349 scoped_restore saved_uiout = make_scoped_restore (¤t_uiout, 350 command_uiout); 351 352 try 353 { 354 execute_command (command, from_tty); 355 } 356 catch (gdb_exception &exception) 357 { 358 e = std::move (exception); 359 } 360 361 /* FIXME: cagney/2005-01-13: This shouldn't be needed. Instead the 362 caller should print the exception. */ 363 exception_print (gdb_stderr, e); 364 return e; 365 } 366 367 ui_out * 368 cli_interp::interp_ui_out () 369 { 370 return m_cli_uiout.get (); 371 } 372 373 /* See cli-interp.h. */ 374 375 void 376 cli_interp_base::set_logging (ui_file_up logfile, bool logging_redirect, 377 bool debug_redirect) 378 { 379 if (logfile != nullptr) 380 { 381 gdb_assert (m_saved_output == nullptr); 382 m_saved_output.reset (new saved_output_files); 383 m_saved_output->out = gdb_stdout; 384 m_saved_output->err = gdb_stderr; 385 m_saved_output->log = gdb_stdlog; 386 m_saved_output->targ = gdb_stdtarg; 387 m_saved_output->targerr = gdb_stdtargerr; 388 389 ui_file *logfile_p = logfile.get (); 390 m_saved_output->logfile_holder = std::move (logfile); 391 392 /* The new stdout and stderr only depend on whether logging 393 redirection is being done. */ 394 ui_file *new_stdout = logfile_p; 395 ui_file *new_stderr = logfile_p; 396 if (!logging_redirect) 397 { 398 m_saved_output->stdout_holder.reset 399 (new tee_file (gdb_stdout, logfile_p)); 400 new_stdout = m_saved_output->stdout_holder.get (); 401 m_saved_output->stderr_holder.reset 402 (new tee_file (gdb_stderr, logfile_p)); 403 new_stderr = m_saved_output->stderr_holder.get (); 404 } 405 406 m_saved_output->stdlog_holder.reset 407 (new timestamped_file (debug_redirect ? logfile_p : new_stderr)); 408 409 gdb_stdout = new_stdout; 410 gdb_stdlog = m_saved_output->stdlog_holder.get (); 411 gdb_stderr = new_stderr; 412 gdb_stdtarg = new_stderr; 413 gdb_stdtargerr = new_stderr; 414 } 415 else 416 { 417 gdb_stdout = m_saved_output->out; 418 gdb_stderr = m_saved_output->err; 419 gdb_stdlog = m_saved_output->log; 420 gdb_stdtarg = m_saved_output->targ; 421 gdb_stdtargerr = m_saved_output->targerr; 422 423 m_saved_output.reset (nullptr); 424 } 425 } 426 427 /* Factory for CLI interpreters. */ 428 429 static struct interp * 430 cli_interp_factory (const char *name) 431 { 432 return new cli_interp (name); 433 } 434 435 /* Standard gdb initialization hook. */ 436 437 void _initialize_cli_interp (); 438 void 439 _initialize_cli_interp () 440 { 441 interp_factory_register (INTERP_CONSOLE, cli_interp_factory); 442 443 /* Note these all work for both the CLI and TUI interpreters. */ 444 gdb::observers::normal_stop.attach (cli_base_on_normal_stop, 445 "cli-interp-base"); 446 gdb::observers::end_stepping_range.attach (cli_base_on_end_stepping_range, 447 "cli-interp-base"); 448 gdb::observers::signal_received.attach (cli_base_on_signal_received, 449 "cli-interp-base"); 450 gdb::observers::signal_exited.attach (cli_base_on_signal_exited, 451 "cli-interp-base"); 452 gdb::observers::exited.attach (cli_base_on_exited, "cli-interp-base"); 453 gdb::observers::no_history.attach (cli_base_on_no_history, "cli-interp-base"); 454 gdb::observers::sync_execution_done.attach (cli_base_on_sync_execution_done, 455 "cli-interp-base"); 456 gdb::observers::command_error.attach (cli_base_on_command_error, 457 "cli-interp-base"); 458 gdb::observers::user_selected_context_changed.attach 459 (cli_base_on_user_selected_context_changed, "cli-interp-base"); 460 } 461