GDB (xrefs)
Loading...
Searching...
No Matches
cli-interp.c
Go to the documentation of this file.
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
34 : interp (name)
35{}
36
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 () = 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
54private:
55
56 /* The ui_out for the console interpreter. */
57 std::unique_ptr<cli_ui_out> m_cli_uiout;
58};
59
62 m_cli_uiout (new cli_ui_out (gdb_stdout))
63{
64}
65
66/* Suppress notification struct. */
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
72static cli_interp_base *
74{
75 return dynamic_cast<cli_interp_base *> (interp);
76}
77
78/* Longjmp-safe wrapper for "execute_command". */
79static 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
101int
102should_print_stop_to_console (struct interp *console_interp,
103 struct thread_info *tp)
104{
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
121static void
123{
124 if (!print_frame)
125 return;
126
127 /* This event is suppressed. */
129 return;
130
132 {
135 if (cli == nullptr)
136 continue;
137
138 thread_info *thread = inferior_thread ();
141 }
142}
143
144/* Observer for the signal_received notification. */
145
146static void
147cli_base_on_signal_received (enum gdb_signal siggnal)
148{
150 {
152 if (cli == nullptr)
153 continue;
154
156 }
157}
158
159/* Observer for the end_stepping_range notification. */
160
161static void
163{
165 {
167 if (cli == nullptr)
168 continue;
169
171 }
172}
173
174/* Observer for the signalled notification. */
175
176static void
177cli_base_on_signal_exited (enum gdb_signal siggnal)
178{
180 {
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
191static void
192cli_base_on_exited (int exitstatus)
193{
195 {
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
206static void
208{
210 {
212 if (cli == nullptr)
213 continue;
214
216 }
217}
218
219/* Observer for the sync_execution_done notification. */
220
221static void
223{
225 if (cli == nullptr)
226 return;
227
228 display_gdb_prompt (NULL);
229}
230
231/* Observer for the command_error notification. */
232
233static void
235{
237 if (cli == nullptr)
238 return;
239
240 display_gdb_prompt (NULL);
241}
242
243/* Observer for the user_selected_context_changed notification. */
244
245static void
246cli_base_on_user_selected_context_changed (user_selected_what selection)
247{
248 /* This event is suppressed. */
250 return;
251
252 thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : nullptr;
253
255 {
257 if (cli == nullptr)
258 continue;
259
260 if (selection & USER_SELECTED_INFERIOR)
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
271void
273{
275}
276
277/* These implement the cli out interpreter: */
278
279void
280cli_interp::init (bool top_level)
281{
282}
283
284void
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
304
306
307 if (stream != NULL)
308 m_cli_uiout->set_stream (gdb_stdout);
309}
310
311void
313{
315}
316
317gdb_exception
318cli_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
336bool
338{
339 return true;
340}
341
342static struct gdb_exception
343safe_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 (&current_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. */
364 return e;
365}
366
367ui_out *
369{
370 return m_cli_uiout.get ();
371}
372
373/* See cli-interp.h. */
374
375void
377 bool debug_redirect)
378{
379 if (logfile != nullptr)
380 {
381 gdb_assert (m_saved_output == nullptr);
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 {
422
423 m_saved_output.reset (nullptr);
424 }
425}
426
427/* Factory for CLI interpreters. */
428
429static struct interp *
431{
432 return new cli_interp (name);
433}
434
435/* Standard gdb initialization hook. */
436
438void
440{
442
443 /* Note these all work for both the CLI and TUI interpreters. */
445 "cli-interp-base");
447 "cli-interp-base");
449 "cli-interp-base");
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");
455 "cli-interp-base");
457 "cli-interp-base");
460}
const char *const name
Definition: aarch64-tdep.c:67
@ BPSTAT_WHAT_STOP_NOISY
Definition: breakpoint.h:1165
void pre_command_loop() override
Definition: cli-interp.c:272
void set_logging(ui_file_up logfile, bool logging_redirect, bool debug_redirect) override
Definition: cli-interp.c:376
bool supports_command_editing() override
Definition: cli-interp.c:337
cli_interp_base(const char *name)
Definition: cli-interp.c:33
virtual ~cli_interp_base()=0
Definition: cli-interp.c:37
std::unique_ptr< saved_output_files > m_saved_output
Definition: cli-interp.h:55
gdb_exception exec(const char *command_str) override
Definition: cli-interp.c:318
void resume() override
Definition: cli-interp.c:285
void suspend() override
Definition: cli-interp.c:312
ui_out * interp_ui_out() override
Definition: cli-interp.c:368
~cli_interp()=default
void init(bool top_level) override
Definition: cli-interp.c:280
cli_interp(const char *name)
Definition: cli-interp.c:60
std::unique_ptr< cli_ui_out > m_cli_uiout
Definition: cli-interp.c:57
Definition: interps.h:43
virtual ui_out * interp_ui_out()=0
const char * name() const
Definition: interps.h:79
struct thread_fsm * thread_fsm() const
Definition: gdbthread.h:449
thread_control_state control
Definition: gdbthread.h:340
Definition: ui-out.h:160
void _initialize_cli_interp()
Definition: cli-interp.c:439
static void cli_base_on_end_stepping_range()
Definition: cli-interp.c:162
static struct gdb_exception safe_execute_command(struct ui_out *uiout, const char *command, int from_tty)
Definition: cli-interp.c:343
static void cli_base_on_signal_received(enum gdb_signal siggnal)
Definition: cli-interp.c:147
static void cli_base_on_exited(int exitstatus)
Definition: cli-interp.c:192
int should_print_stop_to_console(struct interp *console_interp, struct thread_info *tp)
Definition: cli-interp.c:102
static void cli_base_on_user_selected_context_changed(user_selected_what selection)
Definition: cli-interp.c:246
static cli_interp_base * as_cli_interp_base(interp *interp)
Definition: cli-interp.c:73
static void cli_base_on_command_error()
Definition: cli-interp.c:234
static struct interp * cli_interp_factory(const char *name)
Definition: cli-interp.c:430
static void cli_base_on_signal_exited(enum gdb_signal siggnal)
Definition: cli-interp.c:177
static void cli_base_on_no_history()
Definition: cli-interp.c:207
static void cli_base_on_normal_stop(struct bpstat *bs, int print_frame)
Definition: cli-interp.c:122
static void cli_base_on_sync_execution_done()
Definition: cli-interp.c:222
static bool debug_redirect
Definition: cli-logging.c:67
static bool logging_redirect
Definition: cli-logging.c:66
@ USER_SELECTED_THREAD
Definition: defs.h:644
@ USER_SELECTED_FRAME
Definition: defs.h:647
@ USER_SELECTED_INFERIOR
Definition: defs.h:641
void display_gdb_prompt(const char *new_prompt)
Definition: event-top.c:385
void gdb_setup_readline(int editing)
Definition: event-top.c:1336
void gdb_disable_readline(void)
Definition: event-top.c:1377
void command_line_handler(gdb::unique_xmalloc_ptr< char > &&rl)
Definition: event-top.c:781
struct ui * current_ui
Definition: event-top.c:483
void exception_print(struct ui_file *file, const struct gdb_exception &e)
Definition: exceptions.c:105
void execute_command(const char *, int)
Definition: top.c:574
void print_selected_thread_frame(struct ui_out *uiout, user_selected_what selection)
Definition: thread.c:1960
struct thread_info * inferior_thread(void)
Definition: thread.c:83
ptid_t inferior_ptid
Definition: infcmd.c:91
void print_selected_inferior(struct ui_out *uiout)
Definition: inferior.c:467
void print_no_history_reason(struct ui_out *uiout)
Definition: infrun.c:8407
void print_stop_event(struct ui_out *uiout, bool displays)
Definition: infrun.c:8475
void print_signal_exited_reason(struct ui_out *uiout, enum gdb_signal siggnal)
Definition: infrun.c:8309
void print_end_stepping_range_reason(struct ui_out *uiout)
Definition: infrun.c:8297
void print_exited_reason(struct ui_out *uiout, int exitstatus)
Definition: infrun.c:8330
void print_signal_received_reason(struct ui_out *uiout, enum gdb_signal siggnal)
Definition: infrun.c:8357
struct interp * top_level_interpreter(void)
Definition: interps.c:431
void interp_factory_register(const char *name, interp_factory_func func)
Definition: interps.c:112
#define INTERP_CONSOLE
Definition: interps.h:177
struct ui_file * gdb_stdtarg
Definition: main.c:79
struct ui_file * gdb_stdtargerr
Definition: main.c:80
observable sync_execution_done
observable no_history
observable< int > exited
observable end_stepping_range
observable command_error
observable< user_selected_what > user_selected_context_changed
observable< enum gdb_signal > signal_exited
observable< struct bpstat *, int > normal_stop
observable< enum gdb_signal > signal_received
static void print_frame(const frame_print_options &opts, frame_info_ptr frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal)
enum bpstat_what_main_action main_action
Definition: breakpoint.h:1193
bpstat * stop_bpstat
Definition: gdbthread.h:168
bool finished_p() const
Definition: thread-fsm.h:87
struct interp * command_interp
Definition: thread-fsm.h:98
Definition: top.h:56
void(* input_handler)(gdb::unique_xmalloc_ptr< char > &&)
Definition: top.h:83
#define SWITCH_THRU_ALL_UIS()
Definition: top.h:210
std::unique_ptr< ui_file > ui_file_up
Definition: ui-file.h:148
#define current_uiout
Definition: ui-out.h:40
#define gdb_stderr
Definition: utils.h:193
#define gdb_stdlog
Definition: utils.h:196
#define gdb_stdout
Definition: utils.h:188