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