OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [mi/] [mi-interp.c] - Blame information for rev 834

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* MI Interpreter Definitions and Commands for GDB, the GNU debugger.
2
 
3
   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
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 "gdb_string.h"
23
#include "interps.h"
24
#include "event-top.h"
25
#include "event-loop.h"
26
#include "inferior.h"
27
#include "ui-out.h"
28
#include "top.h"
29
#include "exceptions.h"
30
#include "mi-main.h"
31
#include "mi-cmds.h"
32
#include "mi-out.h"
33
#include "mi-console.h"
34
#include "mi-common.h"
35
#include "observer.h"
36
#include "gdbthread.h"
37
#include "solist.h"
38
 
39
/* These are the interpreter setup, etc. functions for the MI interpreter */
40
static void mi_execute_command_wrapper (char *cmd);
41
static void mi_command_loop (int mi_version);
42
 
43
/* These are hooks that we put in place while doing interpreter_exec
44
   so we can report interesting things that happened "behind the mi's
45
   back" in this command */
46
static int mi_interp_query_hook (const char *ctlstr, va_list ap)
47
     ATTR_FORMAT (printf, 1, 0);
48
 
49
static void mi3_command_loop (void);
50
static void mi2_command_loop (void);
51
static void mi1_command_loop (void);
52
 
53
static void mi_insert_notify_hooks (void);
54
static void mi_remove_notify_hooks (void);
55
static void mi_on_normal_stop (struct bpstats *bs, int print_frame);
56
 
57
static void mi_new_thread (struct thread_info *t);
58
static void mi_thread_exit (struct thread_info *t, int silent);
59
static void mi_inferior_appeared (int pid);
60
static void mi_inferior_exit (int pid);
61
static void mi_on_resume (ptid_t ptid);
62
static void mi_solib_loaded (struct so_list *solib);
63
static void mi_solib_unloaded (struct so_list *solib);
64
static void mi_about_to_proceed (void);
65
 
66
static void *
67
mi_interpreter_init (int top_level)
68
{
69
  struct mi_interp *mi = XMALLOC (struct mi_interp);
70
 
71
  /* HACK: We need to force stdout/stderr to point at the console.  This avoids
72
     any potential side effects caused by legacy code that is still
73
     using the TUI / fputs_unfiltered_hook.  So we set up output channels for
74
     this now, and swap them in when we are run. */
75
 
76
  raw_stdout = stdio_fileopen (stdout);
77
 
78
  /* Create MI channels */
79
  mi->out = mi_console_file_new (raw_stdout, "~", '"');
80
  mi->err = mi_console_file_new (raw_stdout, "&", '"');
81
  mi->log = mi->err;
82
  mi->targ = mi_console_file_new (raw_stdout, "@", '"');
83
  mi->event_channel = mi_console_file_new (raw_stdout, "=", 0);
84
 
85
  if (top_level)
86
    {
87
      observer_attach_new_thread (mi_new_thread);
88
      observer_attach_thread_exit (mi_thread_exit);
89
      observer_attach_inferior_appeared (mi_inferior_appeared);
90
      observer_attach_inferior_exit (mi_inferior_exit);
91
      observer_attach_normal_stop (mi_on_normal_stop);
92
      observer_attach_target_resumed (mi_on_resume);
93
      observer_attach_solib_loaded (mi_solib_loaded);
94
      observer_attach_solib_unloaded (mi_solib_unloaded);
95
      observer_attach_about_to_proceed (mi_about_to_proceed);
96
    }
97
 
98
  return mi;
99
}
100
 
101
static int
102
mi_interpreter_resume (void *data)
103
{
104
  struct mi_interp *mi = data;
105
  /* As per hack note in mi_interpreter_init, swap in the output channels... */
106
 
107
  gdb_setup_readline ();
108
 
109
  /* These overwrite some of the initialization done in
110
     _intialize_event_loop.  */
111
  call_readline = gdb_readline2;
112
  input_handler = mi_execute_command_wrapper;
113
  add_file_handler (input_fd, stdin_event_handler, 0);
114
  async_command_editing_p = 0;
115
  /* FIXME: This is a total hack for now.  PB's use of the MI
116
     implicitly relies on a bug in the async support which allows
117
     asynchronous commands to leak through the commmand loop.  The bug
118
     involves (but is not limited to) the fact that sync_execution was
119
     erroneously initialized to 0.  Duplicate by initializing it thus
120
     here...  */
121
  sync_execution = 0;
122
 
123
  gdb_stdout = mi->out;
124
  /* Route error and log output through the MI */
125
  gdb_stderr = mi->err;
126
  gdb_stdlog = mi->log;
127
  /* Route target output through the MI. */
128
  gdb_stdtarg = mi->targ;
129
  /* Route target error through the MI as well. */
130
  gdb_stdtargerr = mi->targ;
131
 
132
  /* Replace all the hooks that we know about.  There really needs to
133
     be a better way of doing this... */
134
  clear_interpreter_hooks ();
135
 
136
  deprecated_show_load_progress = mi_load_progress;
137
 
138
  /* If we're _the_ interpreter, take control. */
139
  if (current_interp_named_p (INTERP_MI1))
140
    deprecated_command_loop_hook = mi1_command_loop;
141
  else if (current_interp_named_p (INTERP_MI2))
142
    deprecated_command_loop_hook = mi2_command_loop;
143
  else if (current_interp_named_p (INTERP_MI3))
144
    deprecated_command_loop_hook = mi3_command_loop;
145
  else
146
    deprecated_command_loop_hook = mi2_command_loop;
147
 
148
  return 1;
149
}
150
 
151
static int
152
mi_interpreter_suspend (void *data)
153
{
154
  gdb_disable_readline ();
155
  return 1;
156
}
157
 
158
static struct gdb_exception
159
mi_interpreter_exec (void *data, const char *command)
160
{
161
  static struct gdb_exception ok;
162
  char *tmp = alloca (strlen (command) + 1);
163
  strcpy (tmp, command);
164
  mi_execute_command_wrapper (tmp);
165
  return exception_none;
166
}
167
 
168
/* Never display the default gdb prompt in mi case.  */
169
static int
170
mi_interpreter_prompt_p (void *data)
171
{
172
  return 0;
173
}
174
 
175
void
176
mi_cmd_interpreter_exec (char *command, char **argv, int argc)
177
{
178
  struct interp *interp_to_use;
179
  int i;
180
  struct interp_procs *procs;
181
  char *mi_error_message = NULL;
182
  struct cleanup *old_chain;
183
 
184
  if (argc < 2)
185
    error ("mi_cmd_interpreter_exec: Usage: -interpreter-exec interp command");
186
 
187
  interp_to_use = interp_lookup (argv[0]);
188
  if (interp_to_use == NULL)
189
    error ("mi_cmd_interpreter_exec: could not find interpreter \"%s\"", argv[0]);
190
 
191
  if (!interp_exec_p (interp_to_use))
192
    error ("mi_cmd_interpreter_exec: interpreter \"%s\" does not support command execution",
193
              argv[0]);
194
 
195
  /* Insert the MI out hooks, making sure to also call the interpreter's hooks
196
     if it has any. */
197
  /* KRS: We shouldn't need this... Events should be installed and they should
198
     just ALWAYS fire something out down the MI channel... */
199
  mi_insert_notify_hooks ();
200
 
201
  /* Now run the code... */
202
 
203
  old_chain = make_cleanup (null_cleanup, 0);
204
  for (i = 1; i < argc; i++)
205
    {
206
      struct gdb_exception e = interp_exec (interp_to_use, argv[i]);
207
      if (e.reason < 0)
208
        {
209
          mi_error_message = xstrdup (e.message);
210
          make_cleanup (xfree, mi_error_message);
211
          break;
212
        }
213
    }
214
 
215
  mi_remove_notify_hooks ();
216
 
217
  if (mi_error_message != NULL)
218
    error ("%s", mi_error_message);
219
  do_cleanups (old_chain);
220
}
221
 
222
/*
223
 * mi_insert_notify_hooks - This inserts a number of hooks that are meant to produce
224
 * async-notify ("=") MI messages while running commands in another interpreter
225
 * using mi_interpreter_exec.  The canonical use for this is to allow access to
226
 * the gdb CLI interpreter from within the MI, while still producing MI style output
227
 * when actions in the CLI command change gdb's state.
228
*/
229
 
230
static void
231
mi_insert_notify_hooks (void)
232
{
233
  deprecated_query_hook = mi_interp_query_hook;
234
}
235
 
236
static void
237
mi_remove_notify_hooks (void)
238
{
239
  deprecated_query_hook = NULL;
240
}
241
 
242
static int
243
mi_interp_query_hook (const char *ctlstr, va_list ap)
244
{
245
  return 1;
246
}
247
 
248
static void
249
mi_execute_command_wrapper (char *cmd)
250
{
251
  mi_execute_command (cmd, stdin == instream);
252
}
253
 
254
static void
255
mi1_command_loop (void)
256
{
257
  mi_command_loop (1);
258
}
259
 
260
static void
261
mi2_command_loop (void)
262
{
263
  mi_command_loop (2);
264
}
265
 
266
static void
267
mi3_command_loop (void)
268
{
269
  mi_command_loop (3);
270
}
271
 
272
static void
273
mi_command_loop (int mi_version)
274
{
275
  /* Turn off 8 bit strings in quoted output.  Any character with the
276
     high bit set is printed using C's octal format. */
277
  sevenbit_strings = 1;
278
  /* Tell the world that we're alive */
279
  fputs_unfiltered ("(gdb) \n", raw_stdout);
280
  gdb_flush (raw_stdout);
281
  start_event_loop ();
282
}
283
 
284
static void
285
mi_new_thread (struct thread_info *t)
286
{
287
  struct mi_interp *mi = top_level_interpreter_data ();
288
 
289
  fprintf_unfiltered (mi->event_channel,
290
                      "thread-created,id=\"%d\",group-id=\"%d\"",
291
                      t->num, t->ptid.pid);
292
  gdb_flush (mi->event_channel);
293
}
294
 
295
static void
296
mi_thread_exit (struct thread_info *t, int silent)
297
{
298
  struct mi_interp *mi;
299
 
300
  if (silent)
301
    return;
302
 
303
  mi = top_level_interpreter_data ();
304
  target_terminal_ours ();
305
  fprintf_unfiltered (mi->event_channel,
306
                      "thread-exited,id=\"%d\",group-id=\"%d\"",
307
                      t->num,t->ptid.pid);
308
  gdb_flush (mi->event_channel);
309
}
310
 
311
void
312
mi_inferior_appeared (int pid)
313
{
314
  struct mi_interp *mi = top_level_interpreter_data ();
315
  target_terminal_ours ();
316
  fprintf_unfiltered (mi->event_channel, "thread-group-created,id=\"%d\"",
317
                      pid);
318
  gdb_flush (mi->event_channel);
319
}
320
 
321
static void
322
mi_inferior_exit (int pid)
323
{
324
  struct mi_interp *mi = top_level_interpreter_data ();
325
  target_terminal_ours ();
326
  fprintf_unfiltered (mi->event_channel, "thread-group-exited,id=\"%d\"",
327
                      pid);
328
  gdb_flush (mi->event_channel);
329
}
330
 
331
static void
332
mi_on_normal_stop (struct bpstats *bs, int print_frame)
333
{
334
  /* Since this can be called when CLI command is executing,
335
     using cli interpreter, be sure to use MI uiout for output,
336
     not the current one.  */
337
  struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
338
  struct mi_interp *mi = top_level_interpreter_data ();
339
 
340
  if (print_frame)
341
    {
342
      int core;
343
      if (uiout != mi_uiout)
344
        {
345
          /* The normal_stop function has printed frame information into
346
             CLI uiout, or some other non-MI uiout.  There's no way we
347
             can extract proper fields from random uiout object, so we print
348
             the frame again.  In practice, this can only happen when running
349
             a CLI command in MI.  */
350
          struct ui_out *saved_uiout = uiout;
351
          uiout = mi_uiout;
352
          print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC);
353
          uiout = saved_uiout;
354
        }
355
 
356
      ui_out_field_int (mi_uiout, "thread-id",
357
                        pid_to_thread_id (inferior_ptid));
358
      if (non_stop)
359
        {
360
          struct cleanup *back_to = make_cleanup_ui_out_list_begin_end
361
            (mi_uiout, "stopped-threads");
362
          ui_out_field_int (mi_uiout, NULL,
363
                            pid_to_thread_id (inferior_ptid));
364
          do_cleanups (back_to);
365
        }
366
      else
367
        ui_out_field_string (mi_uiout, "stopped-threads", "all");
368
 
369
      core = target_core_of_thread (inferior_ptid);
370
      if (core != -1)
371
        ui_out_field_int (mi_uiout, "core", core);
372
    }
373
 
374
  fputs_unfiltered ("*stopped", raw_stdout);
375
  mi_out_put (mi_uiout, raw_stdout);
376
  mi_out_rewind (mi_uiout);
377
  mi_print_timing_maybe ();
378
  fputs_unfiltered ("\n", raw_stdout);
379
  gdb_flush (raw_stdout);
380
}
381
 
382
static void
383
mi_about_to_proceed (void)
384
{
385
  /* Suppress output while calling an inferior function.  */
386
 
387
  if (!ptid_equal (inferior_ptid, null_ptid))
388
    {
389
      struct thread_info *tp = inferior_thread ();
390
      if (tp->in_infcall)
391
        return;
392
    }
393
 
394
  mi_proceeded = 1;
395
}
396
 
397
static int
398
mi_output_running_pid (struct thread_info *info, void *arg)
399
{
400
  ptid_t *ptid = arg;
401
 
402
  if (ptid_get_pid (*ptid) == ptid_get_pid (info->ptid))
403
    fprintf_unfiltered (raw_stdout,
404
                        "*running,thread-id=\"%d\"\n",
405
                        info->num);
406
 
407
  return 0;
408
}
409
 
410
static int
411
mi_inferior_count (struct inferior *inf, void *arg)
412
{
413
  if (inf->pid != 0)
414
    {
415
      int *count_p = arg;
416
      (*count_p)++;
417
    }
418
 
419
  return 0;
420
}
421
 
422
static void
423
mi_on_resume (ptid_t ptid)
424
{
425
  struct thread_info *tp = NULL;
426
 
427
  if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
428
    tp = inferior_thread ();
429
  else
430
    tp = find_thread_ptid (ptid);
431
 
432
  /* Suppress output while calling an inferior function.  */
433
  if (tp->in_infcall)
434
    return;
435
 
436
  /* To cater for older frontends, emit ^running, but do it only once
437
     per each command.  We do it here, since at this point we know
438
     that the target was successfully resumed, and in non-async mode,
439
     we won't return back to MI interpreter code until the target
440
     is done running, so delaying the output of "^running" until then
441
     will make it impossible for frontend to know what's going on.
442
 
443
     In future (MI3), we'll be outputting "^done" here.  */
444
  if (!running_result_record_printed && mi_proceeded)
445
    {
446
      fprintf_unfiltered (raw_stdout, "%s^running\n",
447
                          current_token ? current_token : "");
448
    }
449
 
450
  if (PIDGET (ptid) == -1)
451
    fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
452
  else if (ptid_is_pid (ptid))
453
    {
454
      int count = 0;
455
 
456
      /* Backwards compatibility.  If there's only one inferior,
457
         output "all", otherwise, output each resumed thread
458
         individually.  */
459
      iterate_over_inferiors (mi_inferior_count, &count);
460
 
461
      if (count == 1)
462
        fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
463
      else
464
        iterate_over_threads (mi_output_running_pid, &ptid);
465
    }
466
  else
467
    {
468
      struct thread_info *ti = find_thread_ptid (ptid);
469
      gdb_assert (ti);
470
      fprintf_unfiltered (raw_stdout, "*running,thread-id=\"%d\"\n", ti->num);
471
    }
472
 
473
  if (!running_result_record_printed && mi_proceeded)
474
    {
475
      running_result_record_printed = 1;
476
      /* This is what gdb used to do historically -- printing prompt even if
477
         it cannot actually accept any input.  This will be surely removed
478
         for MI3, and may be removed even earler.  */
479
      /* FIXME: review the use of target_is_async_p here -- is that
480
         what we want? */
481
      if (!target_is_async_p ())
482
        fputs_unfiltered ("(gdb) \n", raw_stdout);
483
    }
484
  gdb_flush (raw_stdout);
485
}
486
 
487
static void
488
mi_solib_loaded (struct so_list *solib)
489
{
490
  struct mi_interp *mi = top_level_interpreter_data ();
491
  target_terminal_ours ();
492
  fprintf_unfiltered (mi->event_channel,
493
                      "library-loaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded=\"%d\"",
494
                      solib->so_original_name, solib->so_original_name,
495
                      solib->so_name, solib->symbols_loaded);
496
  gdb_flush (mi->event_channel);
497
}
498
 
499
static void
500
mi_solib_unloaded (struct so_list *solib)
501
{
502
  struct mi_interp *mi = top_level_interpreter_data ();
503
  target_terminal_ours ();
504
  fprintf_unfiltered (mi->event_channel,
505
                      "library-unloaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\"",
506
                      solib->so_original_name, solib->so_original_name,
507
                      solib->so_name);
508
  gdb_flush (mi->event_channel);
509
}
510
 
511
 
512
extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
513
 
514
void
515
_initialize_mi_interp (void)
516
{
517
  static const struct interp_procs procs =
518
  {
519
    mi_interpreter_init,        /* init_proc */
520
    mi_interpreter_resume,      /* resume_proc */
521
    mi_interpreter_suspend,     /* suspend_proc */
522
    mi_interpreter_exec,        /* exec_proc */
523
    mi_interpreter_prompt_p     /* prompt_proc_p */
524
  };
525
 
526
  /* The various interpreter levels.  */
527
  interp_add (interp_new (INTERP_MI1, NULL, mi_out_new (1), &procs));
528
  interp_add (interp_new (INTERP_MI2, NULL, mi_out_new (2), &procs));
529
  interp_add (interp_new (INTERP_MI3, NULL, mi_out_new (3), &procs));
530
 
531
  /* "mi" selects the most recent released version.  "mi2" was
532
     released as part of GDB 6.0.  */
533
  interp_add (interp_new (INTERP_MI, NULL, mi_out_new (2), &procs));
534
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.