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