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