1 From beatty@unh.cs.cmu.edu Sat Jul 4 12:04:01 1987
2 Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:03:37 EDT
3 Message-Id: <8707041603.AA08600@prep.ai.mit.edu>
4 To: phr@prep.ai.mit.edu (Paul Rubin)
5 Date: Sat, 4 Jul 87 12:03:01 EDT
6 From: Derek Beatty <beatty@unh.cs.cmu.edu>
7 Subject: Re: gdb and X (msg 1 of 3)
10 This is part 1 of 3 parts. It consists of the cursor I used, and a message
11 I sent to Zalman Stern at Andrew regarding what I did, and why. The
12 code and context diffs will follow in other messages.
18 static short gdb_bits[] = {
19 0x0000, 0x0140, 0x0220, 0x0220,
20 0x23e2, 0x13e4, 0x09c8, 0x0ff8,
21 0x0220, 0x3ffe, 0x0630, 0x03e0,
22 0x0220, 0x1ffc, 0x2632, 0x01c0};
24 #define gdb_mask_width 16
25 #define gdb_mask_height 16
26 #define gdb_mask_x_hot 7
27 #define gdb_mask_y_hot 0
28 static short gdb_mask_bits[] = {
29 0x0360, 0x07f0, 0x07f0, 0x77f7,
30 0x7fff, 0x7fff, 0x1ffc, 0x1ffc,
31 0x7fff, 0x7fff, 0x7fff, 0x0ff8,
32 0x3ffe, 0x7fff, 0x7fff, 0x7fff};
35 > The X support I added is minimal; it was inspired by Suntools' dbxtool,
36 > together with the availability of the V10 implementation of the X V11
37 > toolkit specification. Design was guided by simplicity and the facilities
38 > of the toolkit. The debugger window provides a view into the code
39 > corresponding to the current stack frame, and several buttons for the
40 > breakpoint, print, step, next, continue, finish, up, and down commands.
41 > The standard gdb command interface remains available in the tty window from
42 > which gdb was started. The breakpoint and print buttons make use of the
43 > current selection, so you can do simple things like click at text in the
44 > source window, then click the "Go 'til" button to continue until that
47 > Such an interface is simple to program ( ~ 20 hours, about 700 lines),
48 > but it has some drawbacks. First, I didn't take the time to understand
49 > the longjmp's in gdb, and I'm not exactly happy with the idea of them
50 > jumping out of my callback procedures that were invoked by toolkit routines.
51 > There's one core dump bug (it shows up when gdb can't find a source
52 > file) that I haven't tracked down, and it may be related to this. Second,
53 > selection in the text window is not particularly graceful: double-clicking
54 > highlights one word of text, as the toolkit defines a word. It would
55 > be much more graceful were double-clicking to highlight a C identifier.
56 > Finally, and most seriously, most buttons operate by building textual
57 > command lines and passing them to gdb's execute_command function. This
58 > means that all selected expressions are evaluated and printed in the
59 > lexical scope corresponding to the current stack frame, although the
60 > selected text may be in a different lexical scope. This serious bug would
61 > require work to fix.
63 > I wrote the X support out of frustration at not having dbxtool available
64 > when I work on a vax. The hope of portability to V11 via the toolkit
65 > also helped motivate me to write V10 code at this late date. Finally,
66 > I'd never written any nontrivial code that ran on a windowing system
67 > (although that turns out still to be the case). Were I to make a more
68 > serious effort at this project, I would probably add a general "define-button"
69 > command akin to gdb's "define" command.
71 > Look in /usr/beatty/gnu/gdb on vlsi.cs.cmu.edu. All files I have modified
72 > are marked, and also have associated backups (.B extensions). Bennet
73 > Yee has a copy of the toolkit library; see /usr/bsy/Xtlib on f.gp.cs.cmu.edu.
80 From beatty@unh.cs.cmu.edu Sat Jul 4 12:12:47 1987
81 Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:09:20 EDT
82 Message-Id: <8707041609.AA08643@prep.ai.mit.edu>
83 To: phr@PREP.AI.MIT.EDU (Paul Rubin)
84 Date: Sat, 4 Jul 87 12:07:25 EDT
85 From: Derek Beatty <beatty@unh.cs.cmu.edu>
86 Subject: Re: gdb and X (msg 2 of 3)
87 In-Reply-To: Message from "Paul Rubin" of Jul 4, 87 at 1:22 am
90 The following is "tool.c". I hereby grant permission to do anything you
97 * gdb tool for X V10R4 (using V11-compatible toolkit).
98 * Derek Beatty 30 June 87.
101 #include <X/Xt/Xtlib.h>
107 #include "gdb.cursor"
108 #include "gdb_mask.cursor"
114 static Window createFileText();
116 * Windows manipulated by this package.
130 * Source text display.
133 static struct symtab *displayedSymtab= 0;
135 extern struct symtab *current_source_symtab;
136 extern int current_source_line;
141 static Arg labelArgs[1];
142 int linenumbers_changed= 0;
143 static int newWidget= 1;
145 struct symtab_and_line get_selected_frame_sal();
146 struct symtab_and_line sal;
148 /* we could be called before we are initialized */
151 sal= get_selected_frame_sal();
153 /* strictly this is wrong, but better than a blank display */
154 if (sal.symtab==NULL) {
155 sal.symtab= current_source_symtab;
156 /* current_source_line may be off by a small number like 4 */
157 sal.line= current_source_line;
161 * Switch to a new file if necessary.
165 linenumbers_changed= get_filename_and_charpos(sal.symtab,
168 if (!fullName) sal.symtab= NULL;
169 /* if the display may be wrong, destroy it */
170 if (linenumbers_changed || displayedSymtab != sal.symtab) {
171 XtVPanedWindowDeletePane( srcText);
172 XtSendDestroyNotify( srcText);
173 XDestroyWindow( srcText);
176 /* if there's no display, create one */
179 /* if there's no valid display, create a dummy display */
181 displayedSymtab= NULL;
182 srcText= createFileText(frame, "/dev/null");
183 XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1);
184 /* create /dev/null text widget */
185 XtSetArg(labelArgs[0], XtNlabel, "No source displayed.");
186 XtLabelSetValues(srcLabelStrip, labelArgs, XtNumber(labelArgs));
188 displayedSymtab= sal.symtab;
189 srcText= createFileText(frame, fullName);
190 XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1);
191 XtSetArg(labelArgs[0], XtNlabel, fullName);
192 XtLabelSetValues(srcLabelStrip, labelArgs, XtNumber(labelArgs));
193 /* free filename (maybe: check gdb code!) */
198 * Update display and cursor positions as necessary.
199 * Cursor should be placed on line sal.line.
203 static int prevTop= 0, highWaterMark= 0;
207 /* get positions of start of display, and caret */
208 XtSetArg(textArgs[0], XtNdisplayPosition, NULL);
209 XtTextGetValues(srcText, textArgs, XtNumber(textArgs));
210 currentTop= cvtCharToLine(displayedSymtab,
211 (int) textArgs[0].value);
213 highWaterMark += currentTop - prevTop;
215 if ( sal.line < currentTop
216 || sal.line > highWaterMark
219 /* warp the display */
223 /* yes, these magic numbers are ugly, but I don't know how
224 * to get the height of a text widget in a V11-portable way
226 currentTop= (sal.line > 15) ? sal.line - 15 : 0;
227 highWaterMark= currentTop + 35;
229 XtSetArg(textArgs[0], XtNdisplayPosition,
230 cvtLineToChar(displayedSymtab, currentTop));
231 XtTextSetValues(srcText, textArgs, XtNumber(textArgs));
233 XtSetArg(textArgs[0], XtNinsertPosition,
234 cvtLineToChar(displayedSymtab, sal.line));
235 XtTextSetValues(srcText, textArgs, XtNumber(textArgs));
241 /* return the character position of a line */
243 cvtLineToChar( s, line)
248 if (!s->line_charpos) return 0;
249 if (line < 0) line= 0;
250 if (line > s->nlines) line= s->nlines;
251 return *(s->line_charpos + line-1);
254 /* return the line position of a character */
256 cvtCharToLine( s, chr)
257 register struct symtab *s;
260 register int lineNumber= 0;
264 lnp= s->line_charpos;
265 /* files are usually short, so sequential search is Ok */
266 while ( lineNumber < s->nlines && *lnp <= chr) {
270 if (lineNumber >= s->nlines)
271 lineNumber= s->nlines;
276 * title bar at bottom
279 static char *execFileName;
285 if (execLabelStrip) {
286 static Arg labelArgs[1];
288 XtSetArg(labelArgs[0], XtNlabel, execFileName);
289 XtLabelSetValues(execLabelStrip, labelArgs, XtNumber(labelArgs));
294 * Command line into which command are placed for execution.
295 * There's some ugly interaction between this and readline in main.c.
301 * Do any necessary prompting, etc.
303 static char *gdbPrompt;
309 printf("%s", gdbPrompt);
315 * Callback procedures for control panel.
318 /* used by "print" and "print*" buttons */
319 static void printButnProc_1( starflag)
325 char *cmd= starflag ? "print * " : "print ";
326 register int cmdlen= strlen(cmd);
328 seln= XFetchBytes(&selnLen);
330 if (selnLen+cmdlen >= linesize-1) {
331 linesize= (selnLen+cmdlen > linesize*2-1) ? selnLen+cmdlen+1 : linesize*2;
332 line= (char *) xrealloc(line, linesize);
335 strncpy(line+cmdlen, seln, selnLen);
336 *(line+cmdlen+selnLen)= '\0';
337 execute_command(line, 0);
343 static void printButnProc()
348 static void printStarButnProc()
353 static void nextButnProc()
355 strcpy(line, "next");
356 execute_command(line, 0);
361 static void stepButnProc()
363 strcpy(line, "step");
364 execute_command(line, 0);
369 static void contButnProc()
371 strcpy(line, "cont");
372 execute_command(line, 0);
377 static void finButnProc()
379 strcpy(line, "finish");
380 execute_command(line, 0);
385 /* used by "stop at" and "go till" buttons */
386 static void stopAtButnProc_1( gotillFlag)
389 XtTextPosition start, finish;
390 static int lineNumber;
392 XtTextGetSelectionPos(srcText, &start, &finish);
393 if (!displayedSymtab)
394 printf("No source file displayed.\n");
396 break_command_for_tool( displayedSymtab,
397 cvtCharToLine(displayedSymtab, start),
400 strcpy(line, "cont");
401 execute_command(line, 0);
408 static void stopAtButnProc()
410 stopAtButnProc_1( 0);
413 static void untilButnProc()
415 stopAtButnProc_1( 1);
418 /* decide if a character is trash */
423 if ('a' <= c && c <= 'z') return 0;
424 if ('A' <= c && c <= 'Z') return 0;
425 if ('0' <= c && c <= '9') return 0;
426 if (c == '_') return 0;
430 static void stopInButnProc()
436 seln= XFetchBytes(&selnLen);
438 if (selnLen+6 >= linesize-1) {
439 linesize= (selnLen+6 > linesize*2-1) ? selnLen+7 : linesize*2;
440 line= (char *) xrealloc(line, linesize);
442 strcpy(line, "break ");
443 /* copy selection but not garbage */
445 sp= line+strlen(line);
446 while (garbage(*selnp) && selnLen) selnp++, selnLen--;
447 while (!garbage(*selnp) && selnLen) {
452 execute_command(line, 0);
458 static void deIconifyButnProc()
464 static void iconifyButnProc()
466 static Arg iconArgs[1];
467 XtSetArg(iconArgs[0], XtNlabel, gdbPrompt);
468 XtCommandSetValues(icon, iconArgs, XtNumber(iconArgs));
473 static void upButnProc()
476 execute_command(line, 0);
481 static void downButnProc()
483 strcpy(line, "down");
484 execute_command(line, 0);
489 #define addbutton(w) XtSetArg(buttons[buttoncount], XtNwindow, w); \
491 static Arg buttons[20];
492 static int buttoncount= 0;
495 * Create control panel buttons.
497 static createButtons(parent)
500 static Window button;
501 static Arg commandArgs[2];
503 #define crButn(label,fn) \
504 XtSetArg(commandArgs[0], XtNlabel, label);\
505 XtSetArg(commandArgs[1], XtNfunction, fn);\
506 button= XtCommandCreate(parent, commandArgs, XtNumber(commandArgs));\
509 crButn("Brk At", stopAtButnProc);
510 crButn("Brk In", stopInButnProc);
511 crButn("Go 'til", untilButnProc);
513 crButn("Print", printButnProc);
514 crButn("Print*", printStarButnProc);
516 crButn("Next", nextButnProc);
517 crButn("Step", stepButnProc);
518 crButn("Cont", contButnProc);
519 crButn("Finish", finButnProc);
521 crButn("Up", upButnProc);
522 crButn("Down", downButnProc);
524 crButn("Iconify", iconifyButnProc);
528 static Window createLabel(parent, name, label)
532 static Arg labelArgs[2];
534 XtSetArg(labelArgs[0], XtNname, name);
535 XtSetArg(labelArgs[1], XtNlabel, label);
536 return XtLabelCreate(frame, labelArgs, XtNumber(labelArgs));
539 static Window createFileText( parent, filename)
543 static Arg fileArgs[2];
545 XtSetArg(fileArgs[0], XtNfile, filename);
546 XtSetArg(fileArgs[1], XtNtextOptions, scrollVertical);
547 return XtTextDiskCreate(parent, fileArgs, XtNumber(fileArgs));
550 /***************** Externally referenced routine **************/
553 static Arg frameArgs[]= {
554 {XtNwidth, (XtArgVal) 600},
555 {XtNheight, (XtArgVal) 700},
562 * init and database stuff... this is wrong but what the heck
564 if (XOpenDisplay("") == NULL)
566 printf("Initializing tool..."); fflush(stdout);
568 /* should be checking .Xdefaults in $HOME */
569 if ((rdbFile= fopen(".Xresources", "r")) != NULL) {
570 XtGetDataBase(rdbFile, &db);
571 XtSetCurrentDataBase(db);
578 frame= XtVPanedWindowCreate(RootWindow, frameArgs, XtNumber(frameArgs));
580 /* create source label strip and add to frame */
581 srcLabelStrip= createLabel(frame, "Source File", "No source file yet.");
582 XtVPanedWindowAddPane(frame, srcLabelStrip, 0, 15, 15, 0);
584 /* create text widget and add to frame */
585 srcText= createFileText(frame, "/dev/null");
586 XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1);
588 /* create button box */
589 ctlPanel= XtButtonBoxCreate(frame, NULL, 0);
590 createButtons( ctlPanel);
591 XtButtonBoxAddButton(ctlPanel, buttons, buttoncount);
592 XtVPanedWindowAddPane(frame, ctlPanel, 2, 30, 30, 0);
594 /* create exec label strip and add */
595 execLabelStrip= createLabel(frame, "Executable",
596 execFileName ? execFileName : "No executable specified.");
597 XtVPanedWindowAddPane(frame, execLabelStrip, 3, 15, 15, 0);
602 static Arg iconArgs[2];
603 XtSetArg(iconArgs[0], XtNlabel, "(gdb)");
604 XtSetArg(iconArgs[1], XtNfunction, deIconifyButnProc);
605 icon= XtCommandCreate(RootWindow, iconArgs, XtNumber(iconArgs));
606 XMoveWindow(icon, 100, 100); /* HACK */
607 XSetIconWindow(frame, icon);
610 /* throw it onto the display */
611 curse= XCreateCursor(gdb_width, gdb_height, gdb_bits, gdb_mask_bits,
612 gdb_x_hot, gdb_y_hot,
613 BlackPixel, WhitePixel, GXcopy);
614 XDefineCursor(frame, curse);
615 XDefineCursor(icon, curse);
617 XMapSubwindows(frame);
623 /**************** Externally referenced routine. ***********/
624 /* toolDispatcher -- dispatch events until data is available on fp */
625 toolDispatcher(fp, prompt)
629 int inMask= 1 << fileno(fp);
630 int xMask= 1 << dpyno();
638 while (! (rfds & inMask)) {
641 rfds= inMask | xMask;
642 /* this isn't right for 4.3 but it works 'cuz of 4.2 compatibility */
643 nfds= select( 32, &rfds, 0, 0, (struct timeval *) 0);
645 if (pend || rfds & xMask) {
647 XtDispatchEvent(&ev);
652 From beatty@unh.cs.cmu.edu Sat Jul 4 12:17:44 1987
653 Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:15:18 EDT
654 Message-Id: <8707041615.AA08691@prep.ai.mit.edu>
655 To: phr@PREP.AI.MIT.EDU (Paul Rubin)
656 Date: Sat, 4 Jul 87 12:14:08 EDT
657 From: Derek Beatty <beatty@unh.cs.cmu.edu>
658 Subject: Re: gdb and X (msg 3 of 3)
659 In-Reply-To: Message from "Paul Rubin" of Jul 4, 87 at 1:22 am
662 Context diffs follow. The original files are from GDB 2.1 (emacs distribution
667 *** /usr/misc/.gdb/src/core.c Fri Mar 27 12:20:14 1987
668 --- core.c Sat Jul 4 11:12:16 1987
671 /* Work with core dump and executable files, for GDB.
672 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
676 + /* modified by Beatty 1 Jul 87 for gdb tool. */
678 /* Work with core dump and executable files, for GDB.
679 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
685 printf ("No exec file now.\n");
688 /* If we have both a core file and an exec file,
693 printf ("No exec file now.\n");
695 + toolSetExecFile( filename ? filename : "No executable specified.\n");
696 + #endif /* def TOOL */
699 /* If we have both a core file and an exec file,
700 *** /usr/misc/.gdb/src/breakpoint.c Fri Mar 27 12:20:11 1987
701 --- breakpoint.c Wed Jul 1 11:27:31 1987
704 /* Everything about breakpoints, for GDB.
705 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
709 + /* modified by Beatty 1 Jul 87 for gdbtool */
711 /* Everything about breakpoints, for GDB.
712 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
720 /* Set a breakpoint according to ARG (function, linenum or *address)
721 and make it temporary if TEMPFLAG is nonzero. */
729 + /* set a breakpoint from a symtab and line */
730 + void break_command_for_tool( s, line, tempflag)
735 + register struct breakpoint *b;
736 + struct symtab_and_line sal;
740 + sal.pc= find_line_pc( sal.symtab, sal.line);
742 + error("No line %d in file \"%s\".\n", sal.line, sal.symtab->filename);
744 + b= set_raw_breakpoint( sal);
745 + b->number= ++breakpoint_count;
748 + b->enable= temporary;
750 + printf ("Breakpoint %d at 0x%x", b->number, b->address);
752 + printf (": file %s, line %d.", b->symtab->filename, b->line_number);
757 + ALL_BREAKPOINTS (b)
758 + if (b->address == sal.pc && b->number != breakpoint_count)
762 + printf ("Note: breakpoint%s ", (others > 1) ? "s" : "");
763 + ALL_BREAKPOINTS (b)
764 + if (b->address == sal.pc && b->number != breakpoint_count)
769 + (b->enable == disabled) ? " (disabled)" : "",
770 + (others > 1) ? "," : ((others == 1) ? " and" : ""));
772 + printf (" also set at pc 0x%x\n", sal.pc);
777 + #endif /* def TOOL */
779 /* Set a breakpoint according to ARG (function, linenum or *address)
780 and make it temporary if TEMPFLAG is nonzero. */
781 *** /usr/misc/.gdb/src/main.c Fri Mar 27 12:20:45 1987
782 --- main.c Sat Jul 4 11:13:32 1987
785 /* Top level for GDB, the GNU debugger.
786 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
790 + /* modified by Beatty 30 june 87 for gdb tool */
792 /* Top level for GDB, the GNU debugger.
793 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
800 void free_command_lines ();
802 static void initialize_main ();
809 + /* flag indicating whether we are running in a window system */
811 + #endif /* def TOOL */
813 void free_command_lines ();
815 static void initialize_main ();
821 if (!setjmp (to_top_level))
823 clearerr (stdin); /* Don't get hung if C-d is typed. */
832 + isaTool= createTool();
833 + #endif /* def TOOL */
835 if (!setjmp (to_top_level))
837 clearerr (stdin); /* Don't get hung if C-d is typed. */
840 printf ("%s", prompt);
844 execute_command (read_line (instream == stdin), instream == stdin);
845 /* Do any commands attached to breakpoint we stopped at. */
848 printf ("%s", prompt);
852 + toolDisplaySource();
853 + if (isaTool) toolDispatcher(instream,
854 + instream==stdin ? prompt : NULL);
855 + #endif /* def TOOL */
858 execute_command (read_line (instream == stdin), instream == stdin);
859 /* Do any commands attached to breakpoint we stopped at. */
865 c = fgetc (instream);
866 if (c == -1 || c == '\n')
874 c = fgetc (instream);
875 if (c == -1 || c == '\n')
879 GDB is free software and you are welcome to distribute copies of it\n\
880 under certain conditions; type \"info copying\" to see the conditions.\n",
887 GDB is free software and you are welcome to distribute copies of it\n\
888 under certain conditions; type \"info copying\" to see the conditions.\n",
891 + printf( "(CMU X support is available in this version.)\n");
896 *** /usr/misc/.gdb/src/source.c Fri Mar 27 12:20:50 1987
897 --- source.c Wed Jul 1 17:56:58 1987
900 /* List lines of source files for GDB, the GNU debugger.
901 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
905 + /* modified 1 July 87 by Beatty for gdbtool */
907 /* List lines of source files for GDB, the GNU debugger.
908 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
913 s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
916 /* Print source lines from the file of symtab S,
917 starting with line number LINE and stopping before line number STOPLINE. */
921 s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
925 + /* Get full pathname and line number positions for a symtab
926 + * return nonzero if line numbers may have changed
927 + * set full pathname to NULL if no file found
930 + get_filename_and_charpos(s, line, fullname)
935 + register int desc, linenums_changed= 0;
937 + desc= openp(source_path, 0, s->filename, O_RDONLY, 0, fullname);
942 + if (s->line_charpos==0) linenums_changed= 1;
943 + if (linenums_changed) find_source_lines(s, desc);
945 + return linenums_changed;
947 + #endif /* def TOOL */
950 /* Print source lines from the file of symtab S,
951 starting with line number LINE and stopping before line number STOPLINE. */
952 *** /usr/misc/.gdb/src/stack.c Fri Mar 27 12:20:51 1987
953 --- stack.c Wed Jul 1 17:27:34 1987
956 /* Print and select stack frames for GDB, the GNU debugger.
957 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
961 + /* modified by Beatty 1 Jul 87 for gdbtool */
963 /* Print and select stack frames for GDB, the GNU debugger.
964 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
968 static void select_calling_frame ();
970 void print_frame_info ();
972 /* Print a stack frame briefly. FRAME should be the frame address
973 and LEVEL should be its level in the stack (or -1 for level not defined).
976 static void select_calling_frame ();
978 void print_frame_info ();
981 + /* get symtab and line of selected frame, for tool display */
982 + struct symtab_and_line
983 + get_selected_frame_sal()
985 + struct frame_info fi;
987 + fi= get_frame_info( selected_frame);
988 + return find_pc_line(fi.pc, fi.next_frame);
993 /* Print a stack frame briefly. FRAME should be the frame address
994 and LEVEL should be its level in the stack (or -1 for level not defined).
995 End of context diffs. The presence of this line verifies that this message
996 has not been truncated.