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