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