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