* ieee.c (struct ieee_modified_type): Define.
[deliverable/binutils-gdb.git] / gdb / gdbtk.c
CommitLineData
4604b34c
SG
1/* Tcl/Tk interface routines.
2 Copyright 1994, 1995 Free Software Foundation, Inc.
3
4 Written by Stu Grossman <grossman@cygnus.com> of Cygnus Support.
754e5da2
SG
5
6This file is part of GDB.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
6c9638b4 20Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
754e5da2
SG
21
22#include "defs.h"
23#include "symtab.h"
24#include "inferior.h"
25#include "command.h"
26#include "bfd.h"
27#include "symfile.h"
28#include "objfiles.h"
29#include "target.h"
754e5da2
SG
30#include <tcl.h>
31#include <tk.h>
73d3dbd4 32#ifdef ANSI_PROTOTYPES
85c613aa
C
33#include <stdarg.h>
34#else
cd2df226 35#include <varargs.h>
85c613aa 36#endif
cd2df226
SG
37#include <signal.h>
38#include <fcntl.h>
8532893d 39#include <unistd.h>
86db943c
SG
40#include <setjmp.h>
41#include "top.h"
736a82e7 42#include <sys/ioctl.h>
2b576293 43#include "gdb_string.h"
09722039 44#include "dis-asm.h"
6131622e
SG
45#include <stdio.h>
46#include "gdbcmd.h"
736a82e7
SG
47
48#ifndef FIOASYNC
546b8ca7
SG
49#include <sys/stropts.h>
50#endif
754e5da2 51
754e5da2
SG
52/* Handle for TCL interpreter */
53static Tcl_Interp *interp = NULL;
54
55/* Handle for TK main window */
56static Tk_Window mainWindow = NULL;
57
479f0f18
SG
58static int x_fd; /* X network socket */
59
09722039
SG
60/* This variable determines where memory used for disassembly is read from.
61
62 If > 0, then disassembly comes from the exec file rather than the target
63 (which might be at the other end of a slow serial link). If == 0 then
64 disassembly comes from target. If < 0 disassembly is automatically switched
65 to the target if it's an inferior process, otherwise the exec file is
66 used.
67 */
68
69static int disassemble_from_exec = -1;
70
8c19daa1
SG
71/* Supply malloc calls for tcl/tk. */
72
73char *
74Tcl_Malloc (size)
75 unsigned int size;
76{
77 return xmalloc (size);
78}
79
80char *
81Tcl_Realloc (ptr, size)
82 char *ptr;
83 unsigned int size;
84{
85 return xrealloc (ptr, size);
86}
87
88void
89Tcl_Free(ptr)
90 char *ptr;
91{
92 free (ptr);
93}
94
754e5da2
SG
95static void
96null_routine(arg)
97 int arg;
98{
99}
100
546b8ca7
SG
101/* The following routines deal with stdout/stderr data, which is created by
102 {f}printf_{un}filtered and friends. gdbtk_fputs and gdbtk_flush are the
103 lowest level of these routines and capture all output from the rest of GDB.
104 Normally they present their data to tcl via callbacks to the following tcl
105 routines: gdbtk_tcl_fputs, gdbtk_tcl_fputs_error, and gdbtk_flush. These
106 in turn call tk routines to update the display.
86db943c 107
546b8ca7
SG
108 Under some circumstances, you may want to collect the output so that it can
109 be returned as the value of a tcl procedure. This can be done by
110 surrounding the output routines with calls to start_saving_output and
111 finish_saving_output. The saved data can then be retrieved with
112 get_saved_output (but this must be done before the call to
113 finish_saving_output). */
86db943c 114
546b8ca7 115/* Dynamic string header for stdout. */
86db943c 116
6131622e 117static Tcl_DString *result_ptr;
754e5da2 118\f
754e5da2
SG
119static void
120gdbtk_flush (stream)
121 FILE *stream;
122{
6131622e 123#if 0
86db943c
SG
124 /* Force immediate screen update */
125
754e5da2 126 Tcl_VarEval (interp, "gdbtk_tcl_flush", NULL);
6131622e 127#endif
754e5da2
SG
128}
129
8532893d 130static void
86db943c 131gdbtk_fputs (ptr, stream)
8532893d 132 const char *ptr;
86db943c 133 FILE *stream;
8532893d 134{
6131622e 135 if (result_ptr)
45f90c50 136 Tcl_DStringAppend (result_ptr, (char *)ptr, -1);
6131622e 137 else
86db943c 138 {
6131622e 139 Tcl_DString str;
86db943c 140
6131622e 141 Tcl_DStringInit (&str);
8532893d 142
6131622e 143 Tcl_DStringAppend (&str, "gdbtk_tcl_fputs", -1);
45f90c50 144 Tcl_DStringAppendElement (&str, (char *)ptr);
8532893d 145
6131622e
SG
146 Tcl_Eval (interp, Tcl_DStringValue (&str));
147 Tcl_DStringFree (&str);
148 }
8532893d
SG
149}
150
754e5da2 151static int
85c613aa
C
152gdbtk_query (query, args)
153 char *query;
754e5da2
SG
154 va_list args;
155{
4e327047
TT
156 char buf[200], *merge[2];
157 char *command;
754e5da2
SG
158 long val;
159
6131622e 160 vsprintf (buf, query, args);
4e327047
TT
161 merge[0] = "gdbtk_tcl_query";
162 merge[1] = buf;
163 command = Tcl_Merge (2, merge);
164 Tcl_Eval (interp, command);
165 free (command);
754e5da2
SG
166
167 val = atol (interp->result);
168 return val;
169}
170\f
6131622e 171static void
73d3dbd4 172#ifdef ANSI_PROTOTYPES
85c613aa
C
173dsprintf_append_element (Tcl_DString *dsp, char *format, ...)
174#else
6131622e
SG
175dsprintf_append_element (va_alist)
176 va_dcl
85c613aa 177#endif
6131622e
SG
178{
179 va_list args;
85c613aa
C
180 char buf[1024];
181
73d3dbd4 182#ifdef ANSI_PROTOTYPES
85c613aa
C
183 va_start (args, format);
184#else
6131622e
SG
185 Tcl_DString *dsp;
186 char *format;
6131622e
SG
187
188 va_start (args);
6131622e
SG
189 dsp = va_arg (args, Tcl_DString *);
190 format = va_arg (args, char *);
85c613aa 191#endif
6131622e
SG
192
193 vsprintf (buf, format, args);
194
195 Tcl_DStringAppendElement (dsp, buf);
196}
197
198static int
199gdb_get_breakpoint_list (clientData, interp, argc, argv)
200 ClientData clientData;
201 Tcl_Interp *interp;
202 int argc;
203 char *argv[];
204{
205 struct breakpoint *b;
206 extern struct breakpoint *breakpoint_chain;
207
208 if (argc != 1)
209 error ("wrong # args");
210
211 for (b = breakpoint_chain; b; b = b->next)
212 if (b->type == bp_breakpoint)
213 dsprintf_append_element (result_ptr, "%d", b->number);
214
215 return TCL_OK;
216}
217
218static int
219gdb_get_breakpoint_info (clientData, interp, argc, argv)
220 ClientData clientData;
221 Tcl_Interp *interp;
222 int argc;
223 char *argv[];
224{
225 struct symtab_and_line sal;
226 static char *bptypes[] = {"breakpoint", "hardware breakpoint", "until",
227 "finish", "watchpoint", "hardware watchpoint",
228 "read watchpoint", "access watchpoint",
229 "longjmp", "longjmp resume", "step resume",
230 "through sigtramp", "watchpoint scope",
231 "call dummy" };
232 static char *bpdisp[] = {"delete", "disable", "donttouch"};
233 struct command_line *cmd;
234 int bpnum;
235 struct breakpoint *b;
236 extern struct breakpoint *breakpoint_chain;
237
238 if (argc != 2)
239 error ("wrong # args");
240
241 bpnum = atoi (argv[1]);
242
243 for (b = breakpoint_chain; b; b = b->next)
244 if (b->number == bpnum)
245 break;
246
9468f8aa 247 if (!b || b->type != bp_breakpoint)
6131622e
SG
248 error ("Breakpoint #%d does not exist", bpnum);
249
6131622e
SG
250 sal = find_pc_line (b->address, 0);
251
252 Tcl_DStringAppendElement (result_ptr, symtab_to_filename (sal.symtab));
253 dsprintf_append_element (result_ptr, "%d", sal.line);
254 dsprintf_append_element (result_ptr, "0x%lx", b->address);
255 Tcl_DStringAppendElement (result_ptr, bptypes[b->type]);
256 Tcl_DStringAppendElement (result_ptr, b->enable == enabled ? "1" : "0");
257 Tcl_DStringAppendElement (result_ptr, bpdisp[b->disposition]);
258 dsprintf_append_element (result_ptr, "%d", b->silent);
259 dsprintf_append_element (result_ptr, "%d", b->ignore_count);
260
261 Tcl_DStringStartSublist (result_ptr);
262 for (cmd = b->commands; cmd; cmd = cmd->next)
263 Tcl_DStringAppendElement (result_ptr, cmd->line);
264 Tcl_DStringEndSublist (result_ptr);
265
266 Tcl_DStringAppendElement (result_ptr, b->cond_string);
267
268 dsprintf_append_element (result_ptr, "%d", b->thread);
269 dsprintf_append_element (result_ptr, "%d", b->hit_count);
270
271 return TCL_OK;
272}
273
754e5da2
SG
274static void
275breakpoint_notify(b, action)
276 struct breakpoint *b;
277 const char *action;
278{
6131622e 279 char buf[100];
754e5da2
SG
280 int v;
281
282 if (b->type != bp_breakpoint)
283 return;
284
4e327047
TT
285 /* We ensure that ACTION contains no special Tcl characters, so we
286 can do this. */
6131622e 287 sprintf (buf, "gdbtk_tcl_breakpoint %s %d", action, b->number);
754e5da2 288
6131622e 289 v = Tcl_Eval (interp, buf);
754e5da2
SG
290
291 if (v != TCL_OK)
292 {
546b8ca7
SG
293 gdbtk_fputs (interp->result, gdb_stdout);
294 gdbtk_fputs ("\n", gdb_stdout);
754e5da2 295 }
754e5da2
SG
296}
297
298static void
299gdbtk_create_breakpoint(b)
300 struct breakpoint *b;
301{
6131622e 302 breakpoint_notify (b, "create");
754e5da2
SG
303}
304
305static void
306gdbtk_delete_breakpoint(b)
307 struct breakpoint *b;
308{
6131622e 309 breakpoint_notify (b, "delete");
754e5da2
SG
310}
311
312static void
6131622e 313gdbtk_modify_breakpoint(b)
754e5da2
SG
314 struct breakpoint *b;
315{
6131622e 316 breakpoint_notify (b, "modify");
754e5da2
SG
317}
318\f
319/* This implements the TCL command `gdb_loc', which returns a list consisting
320 of the source and line number associated with the current pc. */
321
322static int
323gdb_loc (clientData, interp, argc, argv)
324 ClientData clientData;
325 Tcl_Interp *interp;
326 int argc;
327 char *argv[];
328{
329 char *filename;
754e5da2
SG
330 struct symtab_and_line sal;
331 char *funcname;
8532893d 332 CORE_ADDR pc;
754e5da2
SG
333
334 if (argc == 1)
335 {
1dfc8dfb 336 pc = selected_frame ? selected_frame->pc : stop_pc;
754e5da2
SG
337 sal = find_pc_line (pc, 0);
338 }
339 else if (argc == 2)
340 {
754e5da2 341 struct symtabs_and_lines sals;
8532893d 342 int nelts;
754e5da2
SG
343
344 sals = decode_line_spec (argv[1], 1);
345
8532893d
SG
346 nelts = sals.nelts;
347 sal = sals.sals[0];
348 free (sals.sals);
349
754e5da2 350 if (sals.nelts != 1)
6131622e 351 error ("Ambiguous line spec");
754e5da2 352
8532893d 353 pc = sal.pc;
754e5da2
SG
354 }
355 else
6131622e 356 error ("wrong # args");
754e5da2 357
754e5da2 358 if (sal.symtab)
6131622e 359 Tcl_DStringAppendElement (result_ptr, sal.symtab->filename);
754e5da2 360 else
6131622e 361 Tcl_DStringAppendElement (result_ptr, "");
8532893d
SG
362
363 find_pc_partial_function (pc, &funcname, NULL, NULL);
6131622e 364 Tcl_DStringAppendElement (result_ptr, funcname);
8532893d 365
637b1661 366 filename = symtab_to_filename (sal.symtab);
6131622e 367 Tcl_DStringAppendElement (result_ptr, filename);
8532893d 368
9468f8aa 369 dsprintf_append_element (result_ptr, "%d", sal.line); /* line number */
754e5da2 370
9468f8aa 371 dsprintf_append_element (result_ptr, "0x%lx", pc); /* PC */
8532893d 372
754e5da2
SG
373 return TCL_OK;
374}
375\f
09722039
SG
376/* This implements the TCL command `gdb_eval'. */
377
378static int
379gdb_eval (clientData, interp, argc, argv)
380 ClientData clientData;
381 Tcl_Interp *interp;
382 int argc;
383 char *argv[];
384{
385 struct expression *expr;
386 struct cleanup *old_chain;
387 value_ptr val;
388
389 if (argc != 2)
6131622e 390 error ("wrong # args");
09722039
SG
391
392 expr = parse_expression (argv[1]);
393
394 old_chain = make_cleanup (free_current_contents, &expr);
395
396 val = evaluate_expression (expr);
397
09722039
SG
398 val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), VALUE_ADDRESS (val),
399 gdb_stdout, 0, 0, 0, 0);
09722039
SG
400
401 do_cleanups (old_chain);
402
403 return TCL_OK;
404}
405\f
5b21fb68
SG
406/* This implements the TCL command `gdb_sourcelines', which returns a list of
407 all of the lines containing executable code for the specified source file
408 (ie: lines where you can put breakpoints). */
409
410static int
411gdb_sourcelines (clientData, interp, argc, argv)
412 ClientData clientData;
413 Tcl_Interp *interp;
414 int argc;
415 char *argv[];
416{
417 struct symtab *symtab;
418 struct linetable_entry *le;
419 int nlines;
5b21fb68
SG
420
421 if (argc != 2)
6131622e 422 error ("wrong # args");
5b21fb68
SG
423
424 symtab = lookup_symtab (argv[1]);
425
426 if (!symtab)
6131622e 427 error ("No such file");
5b21fb68
SG
428
429 /* If there's no linetable, or no entries, then we are done. */
430
431 if (!symtab->linetable
432 || symtab->linetable->nitems == 0)
433 {
6131622e 434 Tcl_DStringAppendElement (result_ptr, "");
5b21fb68
SG
435 return TCL_OK;
436 }
437
438 le = symtab->linetable->item;
439 nlines = symtab->linetable->nitems;
440
441 for (;nlines > 0; nlines--, le++)
442 {
443 /* If the pc of this line is the same as the pc of the next line, then
444 just skip it. */
445 if (nlines > 1
446 && le->pc == (le + 1)->pc)
447 continue;
448
9468f8aa 449 dsprintf_append_element (result_ptr, "%d", le->line);
5b21fb68
SG
450 }
451
452 return TCL_OK;
453}
454\f
746d1df4
SG
455static int
456map_arg_registers (argc, argv, func, argp)
457 int argc;
458 char *argv[];
6131622e 459 void (*func) PARAMS ((int regnum, void *argp));
746d1df4
SG
460 void *argp;
461{
462 int regnum;
463
464 /* Note that the test for a valid register must include checking the
465 reg_names array because NUM_REGS may be allocated for the union of the
466 register sets within a family of related processors. In this case, the
467 trailing entries of reg_names will change depending upon the particular
468 processor being debugged. */
469
470 if (argc == 0) /* No args, just do all the regs */
471 {
472 for (regnum = 0;
473 regnum < NUM_REGS
474 && reg_names[regnum] != NULL
475 && *reg_names[regnum] != '\000';
476 regnum++)
477 func (regnum, argp);
478
479 return TCL_OK;
480 }
481
482 /* Else, list of register #s, just do listed regs */
483 for (; argc > 0; argc--, argv++)
484 {
485 regnum = atoi (*argv);
486
487 if (regnum >= 0
488 && regnum < NUM_REGS
489 && reg_names[regnum] != NULL
490 && *reg_names[regnum] != '\000')
491 func (regnum, argp);
492 else
6131622e 493 error ("bad register number");
746d1df4
SG
494 }
495
496 return TCL_OK;
497}
498
6131622e 499static void
746d1df4
SG
500get_register_name (regnum, argp)
501 int regnum;
502 void *argp; /* Ignored */
503{
6131622e 504 Tcl_DStringAppendElement (result_ptr, reg_names[regnum]);
746d1df4
SG
505}
506
5b21fb68
SG
507/* This implements the TCL command `gdb_regnames', which returns a list of
508 all of the register names. */
509
510static int
511gdb_regnames (clientData, interp, argc, argv)
512 ClientData clientData;
513 Tcl_Interp *interp;
514 int argc;
515 char *argv[];
516{
746d1df4
SG
517 argc--;
518 argv++;
519
520 return map_arg_registers (argc, argv, get_register_name, 0);
521}
522
746d1df4
SG
523#ifndef REGISTER_CONVERTIBLE
524#define REGISTER_CONVERTIBLE(x) (0 != 0)
525#endif
526
527#ifndef REGISTER_CONVERT_TO_VIRTUAL
528#define REGISTER_CONVERT_TO_VIRTUAL(x, y, z, a)
529#endif
530
531#ifndef INVALID_FLOAT
532#define INVALID_FLOAT(x, y) (0 != 0)
533#endif
534
6131622e 535static void
746d1df4 536get_register (regnum, fp)
6131622e 537 int regnum;
746d1df4
SG
538 void *fp;
539{
540 char raw_buffer[MAX_REGISTER_RAW_SIZE];
541 char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
542 int format = (int)fp;
543
544 if (read_relative_register_raw_bytes (regnum, raw_buffer))
545 {
6131622e 546 Tcl_DStringAppendElement (result_ptr, "Optimized out");
746d1df4
SG
547 return;
548 }
549
746d1df4
SG
550 /* Convert raw data to virtual format if necessary. */
551
552 if (REGISTER_CONVERTIBLE (regnum))
553 {
554 REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum),
555 raw_buffer, virtual_buffer);
556 }
557 else
558 memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
559
560 val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0,
561 gdb_stdout, format, 1, 0, Val_pretty_default);
562
6131622e 563 Tcl_DStringAppend (result_ptr, " ", -1);
746d1df4
SG
564}
565
566static int
567gdb_fetch_registers (clientData, interp, argc, argv)
568 ClientData clientData;
569 Tcl_Interp *interp;
570 int argc;
571 char *argv[];
572{
573 int format;
574
575 if (argc < 2)
6131622e 576 error ("wrong # args");
5b21fb68 577
746d1df4
SG
578 argc--;
579 argv++;
5b21fb68 580
746d1df4
SG
581 argc--;
582 format = **argv++;
583
584 return map_arg_registers (argc, argv, get_register, format);
585}
586
587/* This contains the previous values of the registers, since the last call to
588 gdb_changed_register_list. */
589
590static char old_regs[REGISTER_BYTES];
591
6131622e 592static void
746d1df4 593register_changed_p (regnum, argp)
6131622e 594 int regnum;
746d1df4
SG
595 void *argp; /* Ignored */
596{
597 char raw_buffer[MAX_REGISTER_RAW_SIZE];
598 char buf[100];
599
600 if (read_relative_register_raw_bytes (regnum, raw_buffer))
601 return;
602
603 if (memcmp (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
604 REGISTER_RAW_SIZE (regnum)) == 0)
605 return;
606
607 /* Found a changed register. Save new value and return it's number. */
608
609 memcpy (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
610 REGISTER_RAW_SIZE (regnum));
611
9468f8aa 612 dsprintf_append_element (result_ptr, "%d", regnum);
746d1df4
SG
613}
614
615static int
616gdb_changed_register_list (clientData, interp, argc, argv)
617 ClientData clientData;
618 Tcl_Interp *interp;
619 int argc;
620 char *argv[];
621{
746d1df4
SG
622 argc--;
623 argv++;
624
625 return map_arg_registers (argc, argv, register_changed_p, NULL);
5b21fb68
SG
626}
627\f
754e5da2
SG
628/* This implements the TCL command `gdb_cmd', which sends it's argument into
629 the GDB command scanner. */
630
631static int
632gdb_cmd (clientData, interp, argc, argv)
633 ClientData clientData;
634 Tcl_Interp *interp;
635 int argc;
636 char *argv[];
637{
754e5da2 638 if (argc != 2)
6131622e 639 error ("wrong # args");
754e5da2 640
86db943c 641 execute_command (argv[1], 1);
479f0f18 642
754e5da2 643 bpstat_do_actions (&stop_bpstat);
754e5da2 644
754e5da2
SG
645 return TCL_OK;
646}
647
86db943c
SG
648/* This routine acts as a top-level for all GDB code called by tcl/Tk. It
649 handles cleanups, and calls to return_to_top_level (usually via error).
650 This is necessary in order to prevent a longjmp out of the bowels of Tk,
651 possibly leaving things in a bad state. Since this routine can be called
652 recursively, it needs to save and restore the contents of the jmp_buf as
653 necessary. */
654
655static int
656call_wrapper (clientData, interp, argc, argv)
657 ClientData clientData;
658 Tcl_Interp *interp;
659 int argc;
660 char *argv[];
661{
662 int val;
663 struct cleanup *saved_cleanup_chain;
664 Tcl_CmdProc *func;
665 jmp_buf saved_error_return;
6131622e
SG
666 Tcl_DString result, *old_result_ptr;
667
668 Tcl_DStringInit (&result);
669 old_result_ptr = result_ptr;
670 result_ptr = &result;
86db943c
SG
671
672 func = (Tcl_CmdProc *)clientData;
673 memcpy (saved_error_return, error_return, sizeof (jmp_buf));
674
675 saved_cleanup_chain = save_cleanups ();
676
677 if (!setjmp (error_return))
678 val = func (clientData, interp, argc, argv);
679 else
680 {
681 val = TCL_ERROR; /* Flag an error for TCL */
682
86db943c
SG
683 gdb_flush (gdb_stderr); /* Flush error output */
684
09722039
SG
685 gdb_flush (gdb_stdout); /* Sometimes error output comes here as well */
686
86db943c
SG
687/* In case of an error, we may need to force the GUI into idle mode because
688 gdbtk_call_command may have bombed out while in the command routine. */
689
4e327047 690 Tcl_Eval (interp, "gdbtk_tcl_idle");
86db943c
SG
691 }
692
693 do_cleanups (ALL_CLEANUPS);
694
695 restore_cleanups (saved_cleanup_chain);
696
697 memcpy (error_return, saved_error_return, sizeof (jmp_buf));
698
6131622e
SG
699 Tcl_DStringResult (interp, &result);
700 result_ptr = old_result_ptr;
701
86db943c
SG
702 return val;
703}
704
754e5da2
SG
705static int
706gdb_listfiles (clientData, interp, argc, argv)
707 ClientData clientData;
708 Tcl_Interp *interp;
709 int argc;
710 char *argv[];
711{
754e5da2
SG
712 struct objfile *objfile;
713 struct partial_symtab *psymtab;
546b8ca7 714 struct symtab *symtab;
754e5da2
SG
715
716 ALL_PSYMTABS (objfile, psymtab)
6131622e 717 Tcl_DStringAppendElement (result_ptr, psymtab->filename);
754e5da2 718
546b8ca7 719 ALL_SYMTABS (objfile, symtab)
6131622e 720 Tcl_DStringAppendElement (result_ptr, symtab->filename);
546b8ca7 721
754e5da2
SG
722 return TCL_OK;
723}
479f0f18
SG
724
725static int
726gdb_stop (clientData, interp, argc, argv)
727 ClientData clientData;
728 Tcl_Interp *interp;
729 int argc;
730 char *argv[];
731{
6c27841f 732 target_stop ();
546b8ca7
SG
733
734 return TCL_OK;
479f0f18 735}
09722039
SG
736\f
737/* This implements the TCL command `gdb_disassemble'. */
479f0f18 738
09722039
SG
739static int
740gdbtk_dis_asm_read_memory (memaddr, myaddr, len, info)
741 bfd_vma memaddr;
742 bfd_byte *myaddr;
743 int len;
744 disassemble_info *info;
745{
746 extern struct target_ops exec_ops;
747 int res;
748
749 errno = 0;
750 res = xfer_memory (memaddr, myaddr, len, 0, &exec_ops);
751
752 if (res == len)
753 return 0;
754 else
755 if (errno == 0)
756 return EIO;
757 else
758 return errno;
759}
760
761/* We need a different sort of line table from the normal one cuz we can't
762 depend upon implicit line-end pc's for lines. This is because of the
763 reordering we are about to do. */
764
765struct my_line_entry {
766 int line;
767 CORE_ADDR start_pc;
768 CORE_ADDR end_pc;
769};
770
771static int
772compare_lines (mle1p, mle2p)
773 const PTR mle1p;
774 const PTR mle2p;
775{
776 struct my_line_entry *mle1, *mle2;
777 int val;
778
779 mle1 = (struct my_line_entry *) mle1p;
780 mle2 = (struct my_line_entry *) mle2p;
781
782 val = mle1->line - mle2->line;
783
784 if (val != 0)
785 return val;
786
787 return mle1->start_pc - mle2->start_pc;
788}
789
790static int
791gdb_disassemble (clientData, interp, argc, argv)
792 ClientData clientData;
793 Tcl_Interp *interp;
794 int argc;
795 char *argv[];
796{
797 CORE_ADDR pc, low, high;
798 int mixed_source_and_assembly;
fc941258
DE
799 static disassemble_info di;
800 static int di_initialized;
801
802 if (! di_initialized)
803 {
810b984d
DE
804 INIT_DISASSEMBLE_INFO (di, gdb_stdout,
805 (fprintf_ftype) fprintf_unfiltered);
fc941258
DE
806 di.memory_error_func = dis_asm_memory_error;
807 di.print_address_func = dis_asm_print_address;
808 di_initialized = 1;
809 }
09722039
SG
810
811 if (argc != 3 && argc != 4)
6131622e 812 error ("wrong # args");
09722039
SG
813
814 if (strcmp (argv[1], "source") == 0)
815 mixed_source_and_assembly = 1;
816 else if (strcmp (argv[1], "nosource") == 0)
817 mixed_source_and_assembly = 0;
818 else
6131622e 819 error ("First arg must be 'source' or 'nosource'");
09722039
SG
820
821 low = parse_and_eval_address (argv[2]);
822
823 if (argc == 3)
824 {
825 if (find_pc_partial_function (low, NULL, &low, &high) == 0)
6131622e 826 error ("No function contains specified address");
09722039
SG
827 }
828 else
829 high = parse_and_eval_address (argv[3]);
830
831 /* If disassemble_from_exec == -1, then we use the following heuristic to
832 determine whether or not to do disassembly from target memory or from the
833 exec file:
834
835 If we're debugging a local process, read target memory, instead of the
836 exec file. This makes disassembly of functions in shared libs work
837 correctly.
838
839 Else, we're debugging a remote process, and should disassemble from the
840 exec file for speed. However, this is no good if the target modifies it's
841 code (for relocation, or whatever).
842 */
843
844 if (disassemble_from_exec == -1)
845 if (strcmp (target_shortname, "child") == 0
d7c4766c
SS
846 || strcmp (target_shortname, "procfs") == 0
847 || strcmp (target_shortname, "vxprocess") == 0)
09722039
SG
848 disassemble_from_exec = 0; /* It's a child process, read inferior mem */
849 else
850 disassemble_from_exec = 1; /* It's remote, read the exec file */
851
852 if (disassemble_from_exec)
a76ef70a
SG
853 di.read_memory_func = gdbtk_dis_asm_read_memory;
854 else
855 di.read_memory_func = dis_asm_read_memory;
09722039
SG
856
857 /* If just doing straight assembly, all we need to do is disassemble
858 everything between low and high. If doing mixed source/assembly, we've
859 got a totally different path to follow. */
860
861 if (mixed_source_and_assembly)
862 { /* Come here for mixed source/assembly */
863 /* The idea here is to present a source-O-centric view of a function to
864 the user. This means that things are presented in source order, with
865 (possibly) out of order assembly immediately following. */
866 struct symtab *symtab;
867 struct linetable_entry *le;
868 int nlines;
c81a3fa9 869 int newlines;
09722039
SG
870 struct my_line_entry *mle;
871 struct symtab_and_line sal;
872 int i;
873 int out_of_order;
c81a3fa9 874 int next_line;
09722039
SG
875
876 symtab = find_pc_symtab (low); /* Assume symtab is valid for whole PC range */
877
878 if (!symtab)
879 goto assembly_only;
880
881/* First, convert the linetable to a bunch of my_line_entry's. */
882
883 le = symtab->linetable->item;
884 nlines = symtab->linetable->nitems;
885
886 if (nlines <= 0)
887 goto assembly_only;
888
889 mle = (struct my_line_entry *) alloca (nlines * sizeof (struct my_line_entry));
890
891 out_of_order = 0;
892
c81a3fa9
SG
893/* Copy linetable entries for this function into our data structure, creating
894 end_pc's and setting out_of_order as appropriate. */
895
896/* First, skip all the preceding functions. */
897
898 for (i = 0; i < nlines - 1 && le[i].pc < low; i++) ;
899
900/* Now, copy all entries before the end of this function. */
901
902 newlines = 0;
903 for (; i < nlines - 1 && le[i].pc < high; i++)
09722039 904 {
c81a3fa9
SG
905 if (le[i].line == le[i + 1].line
906 && le[i].pc == le[i + 1].pc)
907 continue; /* Ignore duplicates */
908
909 mle[newlines].line = le[i].line;
09722039
SG
910 if (le[i].line > le[i + 1].line)
911 out_of_order = 1;
c81a3fa9
SG
912 mle[newlines].start_pc = le[i].pc;
913 mle[newlines].end_pc = le[i + 1].pc;
914 newlines++;
09722039
SG
915 }
916
c81a3fa9
SG
917/* If we're on the last line, and it's part of the function, then we need to
918 get the end pc in a special way. */
919
920 if (i == nlines - 1
921 && le[i].pc < high)
922 {
923 mle[newlines].line = le[i].line;
924 mle[newlines].start_pc = le[i].pc;
925 sal = find_pc_line (le[i].pc, 0);
926 mle[newlines].end_pc = sal.end;
927 newlines++;
928 }
09722039
SG
929
930/* Now, sort mle by line #s (and, then by addresses within lines). */
931
932 if (out_of_order)
c81a3fa9 933 qsort (mle, newlines, sizeof (struct my_line_entry), compare_lines);
09722039
SG
934
935/* Now, for each line entry, emit the specified lines (unless they have been
936 emitted before), followed by the assembly code for that line. */
937
c81a3fa9
SG
938 next_line = 0; /* Force out first line */
939 for (i = 0; i < newlines; i++)
09722039 940 {
c81a3fa9
SG
941/* Print out everything from next_line to the current line. */
942
943 if (mle[i].line >= next_line)
09722039 944 {
c81a3fa9
SG
945 if (next_line != 0)
946 print_source_lines (symtab, next_line, mle[i].line + 1, 0);
09722039 947 else
c81a3fa9
SG
948 print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
949
950 next_line = mle[i].line + 1;
09722039 951 }
c81a3fa9 952
09722039
SG
953 for (pc = mle[i].start_pc; pc < mle[i].end_pc; )
954 {
955 QUIT;
956 fputs_unfiltered (" ", gdb_stdout);
957 print_address (pc, gdb_stdout);
958 fputs_unfiltered (":\t ", gdb_stdout);
d039851f 959 pc += (*tm_print_insn) (pc, &di);
09722039
SG
960 fputs_unfiltered ("\n", gdb_stdout);
961 }
962 }
963 }
964 else
965 {
966assembly_only:
967 for (pc = low; pc < high; )
968 {
969 QUIT;
970 fputs_unfiltered (" ", gdb_stdout);
971 print_address (pc, gdb_stdout);
972 fputs_unfiltered (":\t ", gdb_stdout);
d039851f 973 pc += (*tm_print_insn) (pc, &di);
09722039
SG
974 fputs_unfiltered ("\n", gdb_stdout);
975 }
976 }
977
09722039
SG
978 gdb_flush (gdb_stdout);
979
980 return TCL_OK;
981}
754e5da2
SG
982\f
983static void
984tk_command (cmd, from_tty)
985 char *cmd;
986 int from_tty;
987{
546b8ca7
SG
988 int retval;
989 char *result;
990 struct cleanup *old_chain;
991
992 retval = Tcl_Eval (interp, cmd);
993
994 result = strdup (interp->result);
754e5da2 995
546b8ca7
SG
996 old_chain = make_cleanup (free, result);
997
998 if (retval != TCL_OK)
999 error (result);
1000
1001 printf_unfiltered ("%s\n", result);
1002
1003 do_cleanups (old_chain);
754e5da2
SG
1004}
1005
1006static void
1007cleanup_init (ignored)
1008 int ignored;
1009{
1010 if (mainWindow != NULL)
1011 Tk_DestroyWindow (mainWindow);
1012 mainWindow = NULL;
1013
1014 if (interp != NULL)
1015 Tcl_DeleteInterp (interp);
1016 interp = NULL;
1017}
1018
637b1661
SG
1019/* Come here during long calculations to check for GUI events. Usually invoked
1020 via the QUIT macro. */
1021
1022static void
1023gdbtk_interactive ()
1024{
1025 /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
1026}
1027
479f0f18
SG
1028/* Come here when there is activity on the X file descriptor. */
1029
1030static void
1031x_event (signo)
1032 int signo;
1033{
1034 /* Process pending events */
1035
1036 while (Tk_DoOneEvent (TK_DONT_WAIT|TK_ALL_EVENTS) != 0);
1037}
1038
1039static int
1040gdbtk_wait (pid, ourstatus)
1041 int pid;
1042 struct target_waitstatus *ourstatus;
1043{
736a82e7
SG
1044 struct sigaction action;
1045 static sigset_t nullsigmask = {0};
1046
1047#ifndef SA_RESTART
1048 /* Needed for SunOS 4.1.x */
1049#define SA_RESTART 0
546b8ca7 1050#endif
479f0f18 1051
736a82e7
SG
1052 action.sa_handler = x_event;
1053 action.sa_mask = nullsigmask;
1054 action.sa_flags = SA_RESTART;
1055 sigaction(SIGIO, &action, NULL);
1056
479f0f18
SG
1057 pid = target_wait (pid, ourstatus);
1058
736a82e7
SG
1059 action.sa_handler = SIG_IGN;
1060 sigaction(SIGIO, &action, NULL);
479f0f18
SG
1061
1062 return pid;
1063}
1064
1065/* This is called from execute_command, and provides a wrapper around
1066 various command routines in a place where both protocol messages and
1067 user input both flow through. Mostly this is used for indicating whether
1068 the target process is running or not.
1069*/
1070
1071static void
1072gdbtk_call_command (cmdblk, arg, from_tty)
1073 struct cmd_list_element *cmdblk;
1074 char *arg;
1075 int from_tty;
1076{
1077 if (cmdblk->class == class_run)
1078 {
4e327047 1079 Tcl_Eval (interp, "gdbtk_tcl_busy");
479f0f18 1080 (*cmdblk->function.cfunc)(arg, from_tty);
4e327047 1081 Tcl_Eval (interp, "gdbtk_tcl_idle");
479f0f18
SG
1082 }
1083 else
1084 (*cmdblk->function.cfunc)(arg, from_tty);
1085}
1086
754e5da2
SG
1087static void
1088gdbtk_init ()
1089{
1090 struct cleanup *old_chain;
1091 char *gdbtk_filename;
479f0f18 1092 int i;
736a82e7
SG
1093 struct sigaction action;
1094 static sigset_t nullsigmask = {0};
754e5da2
SG
1095
1096 old_chain = make_cleanup (cleanup_init, 0);
1097
1098 /* First init tcl and tk. */
1099
1100 interp = Tcl_CreateInterp ();
1101
1102 if (!interp)
1103 error ("Tcl_CreateInterp failed");
1104
1105 mainWindow = Tk_CreateMainWindow (interp, NULL, "gdb", "Gdb");
1106
1107 if (!mainWindow)
1108 return; /* DISPLAY probably not set */
1109
1110 if (Tcl_Init(interp) != TCL_OK)
1111 error ("Tcl_Init failed: %s", interp->result);
1112
1113 if (Tk_Init(interp) != TCL_OK)
1114 error ("Tk_Init failed: %s", interp->result);
1115
86db943c
SG
1116 Tcl_CreateCommand (interp, "gdb_cmd", call_wrapper, gdb_cmd, NULL);
1117 Tcl_CreateCommand (interp, "gdb_loc", call_wrapper, gdb_loc, NULL);
1118 Tcl_CreateCommand (interp, "gdb_sourcelines", call_wrapper, gdb_sourcelines,
1119 NULL);
1120 Tcl_CreateCommand (interp, "gdb_listfiles", call_wrapper, gdb_listfiles,
746d1df4 1121 NULL);
86db943c
SG
1122 Tcl_CreateCommand (interp, "gdb_stop", call_wrapper, gdb_stop, NULL);
1123 Tcl_CreateCommand (interp, "gdb_regnames", call_wrapper, gdb_regnames, NULL);
1124 Tcl_CreateCommand (interp, "gdb_fetch_registers", call_wrapper,
1125 gdb_fetch_registers, NULL);
1126 Tcl_CreateCommand (interp, "gdb_changed_register_list", call_wrapper,
1127 gdb_changed_register_list, NULL);
09722039
SG
1128 Tcl_CreateCommand (interp, "gdb_disassemble", call_wrapper,
1129 gdb_disassemble, NULL);
1130 Tcl_CreateCommand (interp, "gdb_eval", call_wrapper, gdb_eval, NULL);
6131622e
SG
1131 Tcl_CreateCommand (interp, "gdb_get_breakpoint_list", call_wrapper,
1132 gdb_get_breakpoint_list, NULL);
1133 Tcl_CreateCommand (interp, "gdb_get_breakpoint_info", call_wrapper,
1134 gdb_get_breakpoint_info, NULL);
754e5da2 1135
09722039 1136 command_loop_hook = Tk_MainLoop;
09722039
SG
1137 print_frame_info_listing_hook = null_routine;
1138 query_hook = gdbtk_query;
1139 flush_hook = gdbtk_flush;
1140 create_breakpoint_hook = gdbtk_create_breakpoint;
1141 delete_breakpoint_hook = gdbtk_delete_breakpoint;
6131622e 1142 modify_breakpoint_hook = gdbtk_modify_breakpoint;
09722039
SG
1143 interactive_hook = gdbtk_interactive;
1144 target_wait_hook = gdbtk_wait;
1145 call_command_hook = gdbtk_call_command;
754e5da2 1146
cd2df226 1147 /* Get the file descriptor for the X server */
479f0f18 1148
cd2df226 1149 x_fd = ConnectionNumber (Tk_Display (mainWindow));
479f0f18
SG
1150
1151 /* Setup for I/O interrupts */
1152
736a82e7
SG
1153 action.sa_mask = nullsigmask;
1154 action.sa_flags = 0;
1155 action.sa_handler = SIG_IGN;
1156 sigaction(SIGIO, &action, NULL);
1157
1158#ifdef FIOASYNC
1159 i = 1;
1160 if (ioctl (x_fd, FIOASYNC, &i))
1161 perror_with_name ("gdbtk_init: ioctl FIOASYNC failed");
479f0f18 1162
77a89957 1163#ifdef SIOCSPGRP
736a82e7
SG
1164 i = getpid();
1165 if (ioctl (x_fd, SIOCSPGRP, &i))
1166 perror_with_name ("gdbtk_init: ioctl SIOCSPGRP failed");
45f90c50
MM
1167
1168#else
1169#ifdef F_SETOWN
1170 i = getpid();
1171 if (fcntl (x_fd, F_SETOWN, i))
1172 perror_with_name ("gdbtk_init: fcntl F_SETOWN failed");
1173#endif /* F_SETOWN */
1174#endif /* !SIOCSPGRP */
546b8ca7
SG
1175#else
1176 if (ioctl (x_fd, I_SETSIG, S_INPUT|S_RDNORM) < 0)
736a82e7
SG
1177 perror_with_name ("gdbtk_init: ioctl I_SETSIG failed");
1178#endif /* ifndef FIOASYNC */
479f0f18 1179
754e5da2
SG
1180 add_com ("tk", class_obscure, tk_command,
1181 "Send a command directly into tk.");
09722039 1182
09722039
SG
1183 Tcl_LinkVar (interp, "disassemble-from-exec", (char *)&disassemble_from_exec,
1184 TCL_LINK_INT);
1185
1186 /* Load up gdbtk.tcl after all the environment stuff has been setup. */
1187
1188 gdbtk_filename = getenv ("GDBTK_FILENAME");
1189 if (!gdbtk_filename)
1190 if (access ("gdbtk.tcl", R_OK) == 0)
1191 gdbtk_filename = "gdbtk.tcl";
1192 else
1193 gdbtk_filename = GDBTK_FILENAME;
1194
724498fd
SG
1195/* Defer setup of fputs_unfiltered_hook to near the end so that error messages
1196 prior to this point go to stdout/stderr. */
1197
1198 fputs_unfiltered_hook = gdbtk_fputs;
1199
09722039 1200 if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK)
724498fd
SG
1201 {
1202 fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */
1203
1204 fprintf_unfiltered (stderr, "%s:%d: %s\n", gdbtk_filename,
1205 interp->errorLine, interp->result);
b66051ec
SG
1206
1207 fputs_unfiltered ("Stack trace:\n", gdb_stderr);
1208 fputs_unfiltered (Tcl_GetVar (interp, "errorInfo", 0), gdb_stderr);
1209 error ("");
724498fd 1210 }
09722039
SG
1211
1212 discard_cleanups (old_chain);
754e5da2
SG
1213}
1214
1215/* Come here during initialze_all_files () */
1216
1217void
1218_initialize_gdbtk ()
1219{
c5197511
SG
1220 if (use_windows)
1221 {
1222 /* Tell the rest of the world that Gdbtk is now set up. */
754e5da2 1223
c5197511
SG
1224 init_ui_hook = gdbtk_init;
1225 }
754e5da2 1226}
This page took 0.283186 seconds and 4 git commands to generate.