|
|
1.1 root 1: .\" @(#)adb.ms 6.1 (Berkeley) 5/7/86
2: .\"
3: .EH 'PS1:10-%''A Tutorial Introduction to ADB'
4: .OH 'A Tutorial Introduction to ADB''PS1:10-%'
5: .de P1
6: .sp .5
7: .if \\n(.$>0 .ta \\$1 \\$2 \\$3 \\$4 \\$5 \\$6
8: .if \\n(.$=0 .ta 1i 1.7i 2.5i
9: .ft 3
10: .nf
11: ..
12: .de P2
13: .sp .5
14: .ft 1
15: .fi
16: ..
17: .\".RP
18: .....TM "77-8234-11 77-1273-10" "49170-220 39199" "40952-1 39199-11"
19: .ND May 5, 1977
20: .TL
21: A Tutorial Introduction to ADB
22: .AU "MH2F-207" "3816"
23: J. F. Maranzano
24: .AU "MH2C-512" 7419
25: S. R. Bourne
26: .AI
27: .MH
28: .OK
29: .\"UNIX
30: .\"Debugging
31: .\"C Programming
32: .AB
33: .PP
34: Debugging tools generally provide a wealth of information
35: about the inner workings of programs.
36: These tools have been available on
37: .UX
38: to allow users to
39: examine ``core'' files
40: that result from aborted programs.
41: A new debugging program, ADB, provides enhanced capabilities
42: to examine "core" and other program files in a
43: variety of formats, run programs with embedded breakpoints and patch files.
44: .PP
45: ADB is an indispensable but complex tool for debugging crashed systems and/or
46: programs.
47: This document provides an introduction to ADB with examples of its use.
48: It explains the various formatting options,
49: techniques for debugging C programs, examples of printing
50: file system information and patching.
51: .AE
52: .CS 12 15 27 13 0 5
53: .NH
54: Introduction
55: .PP
56: ADB is a new debugging program that is
57: available on UNIX.
58: It provides capabilities to look at
59: ``core'' files resulting from aborted programs, print output in a
60: variety of formats, patch files, and run programs
61: with embedded breakpoints.
62: This document provides examples of
63: the more useful features of ADB.
64: The reader is expected to be
65: familiar with the basic commands on
66: .UX
67: with the C
68: language, and with References 1, 2 and 3.
69: .NH
70: A Quick Survey
71: .NH 2
72: Invocation
73: .PP
74: ADB is invoked as:
75: .P1
76: adb objfile corefile
77: .P2
78: where
79: .ul
80: objfile
81: is an executable UNIX file and
82: .ul
83: corefile
84: is a core image file.
85: Many times this will look like:
86: .P1
87: adb a.out core
88: .P2
89: or more simply:
90: .P1
91: adb
92: .P2
93: where the defaults are
94: .ul
95: a.out
96: and
97: .ul
98: core
99: respectively.
100: The filename minus (\-) means ignore this argument as in:
101: .P1
102: adb \- core
103: .P2
104: .PP
105: ADB has requests for examining locations in either file.
106: The
107: \fB?\fP
108: request examines the contents of
109: .ul
110: objfile,
111: the
112: \fB/\fP
113: request examines the
114: .ul
115: corefile.
116: The general form of these requests is:
117: .P1
118: address ? format
119: .P2
120: or
121: .P1
122: address / format
123: .P2
124: .NH 2
125: Current Address
126: .PP
127: ADB maintains a current address, called dot,
128: similar in function to the current pointer in the UNIX editor.
129: When an address is entered, the current address is set to that location,
130: so that:
131: .P1
132: 0126?i
133: .P2
134: sets dot to octal 126 and prints the instruction
135: at that address.
136: The request:
137: .P1
138: .,10/d
139: .P2
140: prints 10 decimal numbers starting at dot.
141: Dot ends up referring to the address of the last item printed.
142: When used with the \fB?\fP or \fB/\fP requests,
143: the current address can be advanced by typing newline; it can be decremented
144: by typing \fB^\fP.
145: .PP
146: Addresses are represented by
147: expressions.
148: Expressions are made up from decimal, octal, and hexadecimal integers,
149: and symbols from the program under test.
150: These may be combined with the operators +, \-, *, % (integer division),
151: & (bitwise and), | (bitwise inclusive or), # (round up
152: to the next multiple), and ~ (not).
153: (All arithmetic within ADB is 32 bits.)
154: When typing a symbolic address for a C program,
155: the user can type
156: .ul
157: name
158: or
159: .ul
160: _name;
161: ADB will recognize both forms.
162: .NH 2
163: Formats
164: .PP
165: To print data, a user specifies a collection of letters and characters
166: that describe the format of the printout.
167: Formats are "remembered" in the sense that typing a request without one
168: will cause the new printout to appear in the previous format.
169: The following are the most commonly used format letters.
170: .P1
171: \fB b \fPone byte in octal
172: \fB c \fPone byte as a character
173: \fB o \fPone word in octal
174: \fB d \fPone word in decimal
175: \fB f \fPtwo words in floating point
176: \fB i \fPPDP 11 instruction
177: \fB s \fPa null terminated character string
178: \fB a \fPthe value of dot
179: \fB u \fPone word as unsigned integer
180: \fB n \fPprint a newline
181: \fB r \fPprint a blank space
182: \fB ^ \fPbackup dot
183: .P2
184: (Format letters are also available for "long" values,
185: for example, `\fBD\fR' for long decimal, and `\fBF\fP' for double floating point.)
186: For other formats see the ADB manual.
187: .NH 2
188: General Request Meanings
189: .PP
190: The general form of a request is:
191: .P1
192: address,count command modifier
193: .P2
194: which sets `dot' to \fIaddress\fP
195: and executes the command
196: \fIcount\fR times.
197: .PP
198: The following table illustrates some general ADB command meanings:
199: .P1
200: Command Meaning
201: \fB ? \fPPrint contents from \fIa.out\fP file
202: \fB / \fPPrint contents from \fIcore\fP file
203: \fB = \fPPrint value of "dot"
204: \fB : \fPBreakpoint control
205: \fB $ \fPMiscellaneous requests
206: \fB ; \fPRequest separator
207: \fB ! \fPEscape to shell
208: .P2
209: .PP
210: ADB catches signals, so a user cannot use a quit signal to exit from ADB.
211: The request $q or $Q (or cntl-D) must be used
212: to exit from ADB.
213: .NH
214: Debugging C Programs
215: .NH 2
216: Debugging A Core Image
217: .PP
218: Consider the C program in Figure 1.
219: The program is used to illustrate a common error made by
220: C programmers.
221: The object of the program is to change the
222: lower case "t" to upper case in the string pointed to by
223: .ul
224: charp
225: and then write the character string to the file indicated by
226: argument 1.
227: The bug shown is that the character "T"
228: is stored in the pointer
229: .ul
230: charp
231: instead of the string pointed to by
232: .ul
233: charp.
234: Executing the program produces a core file because of an out of bounds memory reference.
235: .PP
236: ADB is invoked by:
237: .P1
238: adb a.out core
239: .P2
240: The first debugging request:
241: .P1
242: $c
243: .P2
244: is used to give a C backtrace through the
245: subroutines called.
246: As shown in Figure 2
247: only one function (\fImain\fR) was called and the
248: arguments
249: .ul
250: argc
251: and
252: .ul
253: argv
254: have octal values 02 and
255: 0177762 respectively.
256: Both of these values look
257: reasonable; 02 = two arguments, 0177762 = address on stack
258: of parameter vector.
259: .br
260: The next request:
261: .P1
262: $C
263: .P2
264: is used to give a C backtrace plus an interpretation
265: of all the local variables in each function and their
266: values in octal.
267: The value of the variable
268: .ul
269: cc
270: looks incorrect
271: since
272: .ul
273: cc
274: was declared as a character.
275: .PP
276: The next request:
277: .P1
278: $r
279: .P2
280: prints out the registers including the program
281: counter and an interpretation of the instruction at that
282: location.
283: .PP
284: The request:
285: .P1
286: $e
287: .P2
288: prints out the values of all external variables.
289: .PP
290: A map exists for each file
291: handled by
292: ADB.
293: The map for the
294: .ul
295: a.out
296: file is referenced by \fB?\fP whereas the map for
297: .ul
298: core
299: file is referenced by \fB/\fP.
300: Furthermore, a good rule of thumb is to use \fB?\fP for
301: instructions and \fB/\fP for data when looking at programs.
302: To print out information about the maps type:
303: .P1
304: $m
305: .P2
306: This produces a report of the contents of the maps.
307: More about these maps later.
308: .PP
309: In our example, it is useful to see the
310: contents of the string pointed to by
311: .ul
312: charp.
313: This is done by:
314: .P1
315: *charp/s
316: .P2
317: which says use
318: .ul
319: charp
320: as a pointer in the
321: .ul
322: core
323: file
324: and print the information as a character string.
325: This printout clearly shows that the character buffer
326: was incorrectly overwritten and helps identify the error.
327: Printing the locations around
328: .ul
329: charp
330: shows that the buffer is unchanged
331: but that the pointer is destroyed.
332: Using ADB similarly, we could print information about the
333: arguments to a function.
334: The request:
335: .P1
336: main.argc/d
337: .P2
338: prints the decimal
339: .ul
340: core
341: image value of the argument
342: .ul
343: argc
344: in the function
345: .ul
346: main.
347: .br
348: The request:
349: .P1
350: *main.argv,3/o
351: .P2
352: prints the octal values of the three consecutive
353: cells pointed to by
354: .ul
355: argv
356: in the function
357: .ul
358: main.
359: Note that these values are the addresses of the arguments
360: to main.
361: Therefore:
362: .P1
363: 0177770/s
364: .P2
365: prints the ASCII value of the first argument.
366: Another way to print this value would have been
367: .P1
368: *"/s
369: .P2
370: The " means ditto which remembers the last address
371: typed, in this case \fImain.argc\fP ; the \fB*\fP instructs ADB to use the address field of the
372: .ul
373: core
374: file as a pointer.
375: .PP
376: The request:
377: .P1
378: .=o
379: .P2
380: prints the current address (not its contents) in octal which has been set to the address of the first argument.
381: The current address, dot, is used by ADB to
382: "remember" its current location.
383: It allows the user
384: to reference locations relative to the current
385: address, for example:
386: .P1
387: .\-10/d
388: .P2
389: .NH 2
390: Multiple Functions
391: .PP
392: Consider the C program illustrated in
393: Figure 3.
394: This program calls functions
395: .ul
396: f, g,
397: and
398: .ul
399: h
400: until the stack is exhausted and a core image is produced.
401: .PP
402: Again you can enter the debugger via:
403: .P1
404: adb
405: .P2
406: which assumes the names
407: .ul
408: a.out
409: and
410: .ul
411: core
412: for the executable
413: file and core image file respectively.
414: The request:
415: .P1
416: $c
417: .P2
418: will fill a page of backtrace references to
419: .ul
420: f, g,
421: and
422: .ul
423: h.
424: Figure 4 shows an abbreviated list (typing
425: .ul
426: DEL
427: will terminate the output and bring you back to ADB request level).
428: .PP
429: The request:
430: .P1
431: ,5$C
432: .P2
433: prints the five most recent activations.
434: .PP
435: Notice that each function
436: (\fIf,g,h\fP) has a counter
437: of the number of times it was called.
438: .PP
439: The request:
440: .P1
441: fcnt/d
442: .P2
443: prints the decimal value of the counter for the function
444: .ul
445: f.
446: Similarly
447: .ul
448: gcnt
449: and
450: .ul
451: hcnt
452: could be printed.
453: To print the value of an automatic variable,
454: for example the decimal value of
455: .ul
456: x
457: in the last call of the function
458: .ul
459: h,
460: type:
461: .P1
462: h.x/d
463: .P2
464: It is currently not possible in the exported version to print stack frames other than the most recent activation of a function.
465: Therefore, a user can print everything with
466: \fB$C\fR or the occurrence of a variable in the most recent call of a function.
467: It is possible with the \fB$C\fR request, however, to print the stack frame
468: starting at some address as \fBaddress$C.\fR
469: .NH 2
470: Setting Breakpoints
471: .PP
472: Consider the C program in Figure 5.
473: This program, which changes tabs into blanks, is adapted from
474: .ul
475: Software Tools
476: by Kernighan and Plauger, pp. 18-27.
477: .PP
478: We will run this program under the control of ADB (see Figure 6a) by:
479: .P1
480: adb a.out \-
481: .P2
482: Breakpoints are set in the program as:
483: .ul
484: .P1
485: address:b [request]
486: .P2
487: The requests:
488: .P1
489: settab+4:b
490: fopen+4:b
491: getc+4:b
492: tabpos+4:b
493: .P2
494: set breakpoints at the start of these functions.
495: C does not generate statement labels.
496: Therefore it is currently not possible to plant breakpoints at locations
497: other than function entry points without a knowledge of the code
498: generated by the C compiler.
499: The above addresses are entered as
500: .ft B
501: symbol+4
502: .ft R
503: so that they will appear in any
504: C backtrace since the first instruction of each function is a call
505: to the C save routine
506: (\fIcsv\fR).
507: Note that some of the functions are from the C library.
508: .PP
509: To print the location of breakpoints one types:
510: .P1
511: $b
512: .P2
513: The display indicates a
514: .ul
515: count
516: field.
517: A breakpoint is bypassed
518: .ul
519: count \-1
520: times before causing a stop.
521: The
522: .ul
523: command
524: field indicates the ADB requests to be executed each time the breakpoint is encountered.
525: In our example no
526: .ul
527: command
528: fields are present.
529: .PP
530: By displaying the original instructions at the function
531: .ul
532: settab
533: we see that
534: the breakpoint is set after the jsr to the C save routine.
535: We can display the instructions using the ADB request:
536: .P1
537: settab,5?ia
538: .P2
539: This request displays five instructions starting at
540: .ul
541: settab
542: with the addresses of each location displayed.
543: Another variation is:
544: .P1
545: settab,5?i
546: .P2
547: which displays the instructions with only the starting address.
548: .PP
549: Notice that we accessed the addresses from the
550: .ul
551: a.out
552: file with the \fB?\fP command.
553: In general when asking for a printout of multiple items,
554: ADB will advance the current address the number of
555: bytes necessary to satisfy the request; in the above
556: example five instructions were displayed and the current address was
557: advanced 18 (decimal) bytes.
558: .PP
559: To run the program one simply types:
560: .P1
561: :r
562: .P2
563: To delete a breakpoint, for instance the entry to the function
564: .ul
565: settab,
566: one types:
567: .P1
568: settab+4:d
569: .P2
570: To continue execution of the program from the breakpoint type:
571: .P1
572: :c
573: .PP
574: Once the program has stopped (in this case at the breakpoint for
575: .ul
576: fopen),
577: ADB requests can be used to display the contents of memory.
578: For example:
579: .P1
580: $C
581: .P2
582: to display a stack trace, or:
583: .P1
584: tabs,3/8o
585: .P2
586: to print three lines of 8 locations each from the array called
587: .ul
588: tabs.
589: By this time (at location
590: .ul
591: fopen)
592: in the C program,
593: .ul
594: settab
595: has been called and should have set a one in every eighth location of
596: .ul
597: tabs.
598: .NH 2
599: Advanced Breakpoint Usage
600: .PP
601: We continue execution of the program with:
602: .P1
603: :c
604: .P2
605: See Figure 6b.
606: .ul
607: Getc
608: is called three times and the contents of the variable
609: .ul
610: c
611: in the function
612: .ul
613: main
614: are displayed
615: each time.
616: The single character on the left hand edge is the output from the C program.
617: On the third occurrence of
618: .ul
619: getc
620: the program stops.
621: We can look at the full buffer of characters by typing:
622: .P1
623: ibuf+6/20c
624: .P2
625: When we continue the program with:
626: .P1
627: :c
628: .P2
629: we hit our first breakpoint at
630: .ul
631: tabpos
632: since there is a tab following the
633: "This" word of the data.
634: .PP
635: Several breakpoints of
636: .ul
637: tabpos
638: will occur until the program has changed the tab into equivalent blanks.
639: Since we feel that
640: .ul
641: tabpos
642: is working,
643: we can remove the breakpoint at that location by:
644: .P1
645: tabpos+4:d
646: .P2
647: If the program is continued with:
648: .P1
649: :c
650: .P2
651: it resumes normal execution after ADB prints
652: the message
653: .P1
654: a.out:running
655: .P2
656: .PP
657: The UNIX quit and interrupt signals
658: act on ADB itself rather than on the program being debugged.
659: If such a signal occurs then the program being debugged is stopped and control is returned to ADB.
660: The signal is saved by ADB and is passed on to the test program if:
661: .P1
662: :c
663: .P2
664: is typed.
665: This can be useful when testing interrupt
666: handling routines.
667: The signal is not passed on to the test program if:
668: .P1
669: :c 0
670: .P2
671: is typed.
672: .PP
673: Now let us reset the breakpoint at
674: .ul
675: settab
676: and display the instructions located there when we reach the breakpoint.
677: This is accomplished by:
678: .P1
679: settab+4:b settab,5?ia \fR*
680: .P2
681: .FS
682: * Owing to a bug in early versions of ADB (including the
683: version distributed in Generic 3 UNIX) these statements
684: must be written as:
685: .br
686: .in 1i
687: \fBsettab+4:b settab,5?ia;0\fR
688: .ft B
689: .br
690: getc+4,3:b main.c?C;0
691: .br
692: settab+4:b settab,5?ia; ptab/o;0
693: .br
694: .ft R
695: .in -1i
696: Note that \fB;0\fR will set dot to zero and stop at the breakpoint.
697: .FE
698: It is also possible to execute the ADB requests for each occurrence of the breakpoint but
699: only stop after the third occurrence by typing:
700: .P1
701: getc+4,3:b main.c?C \fR*
702: .P2
703: This request will print the local variable
704: .ul
705: c
706: in the function
707: .ul
708: main
709: at each occurrence of the breakpoint.
710: The semicolon is used to separate multiple ADB requests on a single line.
711: .PP
712: Warning:
713: setting a breakpoint causes the value of dot to be changed;
714: executing the program under ADB does not change dot.
715: Therefore:
716: .P1
717: settab+4:b .,5?ia
718: fopen+4:b
719: .P2
720: will print the last thing dot was set to
721: (in the example \fIfopen+4\fP)
722: .ul
723: not
724: the current location (\fIsettab+4\fP)
725: at which the program is executing.
726: .PP
727: A breakpoint can be overwritten without first deleting the old breakpoint.
728: For example:
729: .P1
730: settab+4:b settab,5?ia; ptab/o \fR*
731: .P2
732: could be entered after typing the above requests.
733: .PP
734: Now the display of breakpoints:
735: .P1
736: $b
737: .P2
738: shows the above request for the
739: .ul
740: settab
741: breakpoint.
742: When the breakpoint at
743: .ul
744: settab
745: is encountered the ADB requests are executed.
746: Note that the location at
747: .ul
748: settab+4
749: has been changed to plant the breakpoint;
750: all the other locations match their original value.
751: .PP
752: Using the functions,
753: .ul
754: f, g
755: and
756: .ul
757: h
758: shown in Figure 3,
759: we can follow the execution of each function by planting non-stopping
760: breakpoints.
761: We call ADB with the executable program of Figure 3 as follows:
762: .P1
763: adb ex3 \-
764: .P2
765: Suppose we enter the following breakpoints:
766: .P1
767: h+4:b hcnt/d; h.hi/; h.hr/
768: g+4:b gcnt/d; g.gi/; g.gr/
769: f+4:b fcnt/d; f.fi/; f.fr/
770: :r
771: .P2
772: Each request line indicates that the variables are printed in decimal
773: (by the specification \fBd\fR).
774: Since the format is not changed, the \fBd\fR can be left off all but
775: the first request.
776: .PP
777: The output in Figure 7 illustrates two points.
778: First, the ADB requests in the breakpoint line are not
779: examined until the program under
780: test is run.
781: That means any errors in those ADB requests is not detected until run time.
782: At the location of the error ADB stops running the program.
783: .PP
784: The second point is the way ADB handles register variables.
785: ADB uses the symbol table to address variables.
786: Register variables, like \fIf.fr\fR above, have pointers to uninitialized
787: places on the stack.
788: Therefore the message "symbol not found".
789: .PP
790: Another way of getting at the data in this example is to print
791: the variables used in the call as:
792: .P1
793: f+4:b fcnt/d; f.a/; f.b/; f.fi/
794: g+4:b gcnt/d; g.p/; g.q/; g.gi/
795: :c
796: .P2
797: The operator / was used instead of ?
798: to read values from the \fIcore\fP file.
799: The output for each function, as shown in Figure 7, has the same format.
800: For the function \fIf\fP, for example, it shows the name and value of the
801: .ul
802: external
803: variable
804: .ul
805: fcnt.
806: It also shows the address on the stack and value of the
807: variables
808: .ul
809: a, b
810: and
811: .ul
812: fi.
813: .PP
814: Notice that the addresses on the stack will continue to decrease
815: until no address space is left for program execution
816: at which time (after many pages of output)
817: the program under test aborts.
818: A display with names would be produced by requests like the following:
819: .P1
820: f+4:b fcnt/d; f.a/"a="d; f.b/"b="d; f.fi/"fi="d
821: .P2
822: In this format the quoted string is printed literally and the \fBd\fP
823: produces a decimal display of the variables.
824: The results are shown in Figure 7.
825: .NH 2
826: Other Breakpoint Facilities
827: .LP
828: .IP \(bu 4
829: Arguments and change of standard input and output are passed to a program as:
830: .P1
831: :r arg1 arg2 ... <infile >outfile
832: .P2
833: This request
834: kills any existing program under test and
835: starts the
836: .ul
837: a.out
838: afresh.
839: .IP \(bu
840: The program being debugged can be single stepped
841: by:
842: .P1
843: :s
844: .P2
845: If necessary, this request will start up the program being
846: debugged and stop after executing
847: the first instruction.
848: .IP \(bu
849: ADB allows a program to be entered at a specific address
850: by typing:
851: .P1
852: address:r
853: .P2
854: .IP \(bu
855: The count field can be used to skip the first \fIn\fR breakpoints as:
856: .P1
857: ,n:r
858: .P2
859: The request:
860: .P1
861: ,n:c
862: .P2
863: may also be used for skipping the first \fIn\fR breakpoints
864: when continuing a program.
865: .sp
866: .IP \(bu
867: A program can be continued at an address different from the breakpoint by:
868: .P1
869: address:c
870: .P2
871: .IP \(bu
872: The program being debugged runs as a separate process and can be killed by:
873: .P1
874: :k
875: .P2
876: .LP
877: .NH
878: Maps
879: .PP
880: UNIX supports several executable file formats. These are used to tell
881: the loader how to load the program file. File type 407
882: is the most common and is generated by a C compiler invocation such as
883: \fBcc pgm.c\fP.
884: A 410 file is produced by a C compiler command of the form \fBcc -n pgm.c\fP,
885: whereas a 411 file is produced by \fBcc -i pgm.c\fP.
886: ADB interprets these different file formats and
887: provides access to the different segments through a set of maps (see Figure 8).
888: To print the maps type:
889: .P1
890: $m
891: .P2
892: .PP
893: In 407 files, both text (instructions) and data are intermixed.
894: This makes it impossible for ADB to differentiate data from
895: instructions and some of the printed symbolic addresses look incorrect;
896: for example, printing data addresses as offsets from routines.
897: .PP
898: In 410 files (shared text), the instructions are separated from data and
899: \fB?*\fR accesses the data part of the \fIa.out\fP file.
900: The \fB?* \fP request tells ADB to use the second part of the
901: map in the
902: .ul
903: a.out
904: file.
905: Accessing data in the \fIcore\fP file shows
906: the data after it was modified by the execution of the program.
907: Notice also that the data segment may have grown during
908: program execution.
909: .PP
910: In 411 files (separated I & D space), the
911: instructions and data are also separated.
912: However, in this
913: case, since data is mapped through a separate set of segmentation
914: registers, the base of the data segment is also relative to address zero.
915: In this case since the addresses overlap it is necessary to use
916: the \fB?*\fR operator to access the data space of the \fIa.out\fP file.
917: In both 410 and 411 files the corresponding
918: core file does not contain the program text.
919: .PP
920: Figure 9 shows the display of three maps
921: for the same program linked as a 407, 410, 411 respectively.
922: The b, e, and f fields are used by ADB to map
923: addresses into file addresses.
924: The "f1" field is the
925: length of the header at the beginning of the file (020 bytes
926: for an \fIa.out\fP file and 02000 bytes for a \fIcore\fP file).
927: The "f2" field is the displacement from the beginning of the file to the data.
928: For a 407 file with mixed text and data this is the
929: same as the length of the header; for 410 and 411 files this
930: is the length of the header plus the size of the text portion.
931: .PP
932: The "b" and "e" fields are the starting and ending locations
933: for a segment.
934: Given an address, A, the location in
935: the file (either \fIa.out\fP or \fIcore\fP) is calculated as:
936: .P1
937: b1\(<=A\(<=e1 =\h'-.5m'> file address = (A\-b1)+f1
938: b2\(<=A\(<=e2 =\h'-.5m'> file address = (A\-b2)+f2
939: .P2
940: A user can access locations by using the ADB defined variables.
941: The \fB$v\fR request prints the variables initialized by ADB:
942: .P1
943: b base address of data segment
944: d length of the data segment
945: s length of the stack
946: t length of the text
947: m execution type (407,410,411)
948: .P2
949: .PP
950: In Figure 9 those variables not present are zero.
951: Use can be made of these variables by expressions such as:
952: .P1
953: <b
954: .P2
955: in the address field.
956: Similarly the value of the variable can be changed by an assignment request
957: such as:
958: .P1
959: 02000>b
960: .P2
961: that sets \fBb\fP to octal 2000.
962: These variables are useful to know if the file under examination
963: is an executable or \fIcore\fP image file.
964: .PP
965: ADB reads the header of the \fIcore\fP image file to find the
966: values for these variables.
967: If the second file specified does not
968: seem to be a \fIcore\fP file, or if it is missing then the header of
969: the executable file is used instead.
970: .NH
971: Advanced Usage
972: .PP
973: It is possible with ADB to combine formatting requests
974: to provide elaborate displays.
975: Below are several examples.
976: .NH 2
977: Formatted dump
978: .PP
979: The line:
980: .P1
981: <b,\-1/4o4^8Cn
982: .P2
983: prints 4 octal words followed by their ASCII interpretation
984: from the data space of the core image file.
985: Broken down, the various request pieces mean:
986: .sp
987: .in 1.7i
988: .ta .7i
989: .ti -.7i
990: <b The base address of the data segment.
991: .sp
992: .ti -.7i
993: <b,\-1 Print from the base address to the end of file.
994: A negative count is used here and elsewhere to loop indefinitely
995: or until some error condition (like end of file) is detected.
996: .sp
997: .ti -1.7i
998: The format \fB4o4^8Cn\fR is broken down as follows:
999: .sp
1000: .ti -.7i
1001: 4o Print 4 octal locations.
1002: .sp
1003: .ti -.7i
1004: 4^ Backup the current address 4 locations (to the original start of the field).
1005: .sp
1006: .ti -.7i
1007: 8C Print 8 consecutive characters using an escape convention;
1008: each character in the range 0 to 037 is printed as @ followed by the corresponding character in the range 0140 to 0177.
1009: An @ is printed as @@.
1010: .sp
1011: .ti -.7i
1012: n Print a newline.
1013: .in -1.7i
1014: .fi
1015: .sp
1016: .PP
1017: The request:
1018: .P1
1019: <b,<d/4o4^8Cn
1020: .P2
1021: could have been used instead to allow the printing to stop
1022: at the end of the data segment (<d provides the data segment size in bytes).
1023: .PP
1024: The formatting requests can be combined with ADB's ability
1025: to read in a script to produce a core image dump script.
1026: ADB is invoked as:
1027: .P1
1028: adb a.out core < dump
1029: .P2
1030: to read in a script file,
1031: .ul
1032: dump,
1033: of requests.
1034: An example of such a script is:
1035: .P1
1036: 120$w
1037: 4095$s
1038: $v
1039: =3n
1040: $m
1041: =3n"C Stack Backtrace"
1042: $C
1043: =3n"C External Variables"
1044: $e
1045: =3n"Registers"
1046: $r
1047: 0$s
1048: =3n"Data Segment"
1049: <b,\-1/8ona
1050: .P2
1051: .PP
1052: The request \fB120$w\fP sets the width of the output to
1053: 120 characters
1054: (normally, the width is 80 characters).
1055: ADB attempts to print addresses as:
1056: .P1
1057: symbol + offset
1058: .P2
1059: The request \fB4095$s\fP increases the maximum permissible offset
1060: to the nearest symbolic address from 255 (default) to 4095.
1061: The request \fB=\fP can be used to print literal strings.
1062: Thus,
1063: headings are provided in this
1064: .ul
1065: dump
1066: program
1067: with requests of the form:
1068: .P1
1069: =3n"C Stack Backtrace"
1070: .P2
1071: that spaces three lines and prints the literal
1072: string.
1073: The request \fB$v\fP prints all non-zero ADB variables (see Figure 8).
1074: The request
1075: \fB0$s\fP
1076: sets the maximum offset for symbol matches to zero thus
1077: suppressing the printing of symbolic labels in favor
1078: of octal values.
1079: Note that this is only done for the printing of the data segment.
1080: The request:
1081: .P1
1082: <b,\-1/8ona
1083: .P2
1084: prints a dump from the base of the data segment to the end of file
1085: with an octal address field and eight octal numbers per line.
1086: .PP
1087: Figure 11 shows the results of some formatting requests
1088: on the C program of Figure 10.
1089: .NH 2
1090: Directory Dump
1091: .PP
1092: As another illustration (Figure 12) consider a set of requests to dump
1093: the contents of a directory (which is made up
1094: of an integer \fIinumber\fP followed by a 14 character name):
1095: .P1
1096: adb dir \-
1097: =n8t"Inum"8t"Name"
1098: 0,\-1? u8t14cn
1099: .P2
1100: In this example, the \fBu\fP prints the \fIinumber\fP as an unsigned decimal integer,
1101: the \fB8t\fP means that ADB will space to the next
1102: multiple of 8 on the output line, and the \fB14c\fP prints the 14 character file name.
1103: .NH 2
1104: Ilist Dump
1105: .PP
1106: Similarly the contents of the \fIilist\fP of a file system, (e.g. /dev/src,
1107: on UNIX systems distributed by the UNIX Support Group;
1108: see UNIX Programmer's
1109: Manual Section V) could be dumped with the following set of
1110: requests:
1111: .P1
1112: adb /dev/src \-
1113: 02000>b
1114: ?m <b
1115: <b,\-1?"flags"8ton"links,uid,gid"8t3bn",size"8tbrdn"addr"8t8un"times"8t2Y2na
1116: .P2
1117: In this example the value of the base for the map was changed
1118: to 02000 (by saying \fB?m<b\fR) since that is the start of an \fIilist\fP within a file system.
1119: An artifice (\fBbrd\fP above) was used to print the 24 bit size field
1120: as a byte, a space, and a decimal integer.
1121: The last access time and last modify time are printed with the
1122: \fB2Y\fR
1123: operator.
1124: Figure 12 shows portions of these requests as applied to a directory
1125: and file system.
1126: .NH 2
1127: Converting values
1128: .PP
1129: ADB may be used to convert values from one representation to
1130: another.
1131: For example:
1132: .P1
1133: 072 = odx
1134: .P2
1135: will print
1136: .P1
1137: 072 58 #3a
1138: .P2
1139: which is the octal, decimal and hexadecimal representations
1140: of 072 (octal).
1141: The format is remembered so that typing
1142: subsequent numbers will print them in the given formats.
1143: Character values may be converted similarly, for example:
1144: .P1
1145: 'a' = co
1146: .P2
1147: prints
1148: .P1
1149: a 0141
1150: .P2
1151: It may also be used to evaluate expressions but be
1152: warned that all binary operators have
1153: the same precedence which is lower than that for unary operators.
1154: .NH
1155: Patching
1156: .PP
1157: Patching files with ADB is accomplished with the
1158: .ul
1159: write,
1160: \fBw\fP or \fBW\fP, request (which is not like the \fIed\fP editor write command).
1161: This is often used in conjunction with the
1162: .ul
1163: locate,
1164: \fBl\fP or \fBL\fP
1165: request.
1166: In general, the request syntax for \fBl\fP and \fBw\fP are similar as follows:
1167: .P1
1168: ?l value
1169: .P2
1170: The request \fBl\fP is used to match on two bytes, \fBL\fP is used for
1171: four bytes.
1172: The request \fBw\fP is used to write two bytes, whereas
1173: \fBW\fP writes four bytes.
1174: The \fBvalue\fP field in either
1175: .ul
1176: locate
1177: or
1178: .ul
1179: write
1180: requests
1181: is an expression.
1182: Therefore, decimal and octal numbers, or character strings are supported.
1183: .PP
1184: In order to modify a file, ADB must be called as:
1185: .P1
1186: adb \-w file1 file2
1187: .P2
1188: When called with this option,
1189: .ul
1190: file1
1191: and
1192: .ul
1193: file2
1194: are created if necessary and opened for both reading and writing.
1195: .PP
1196: For example, consider the C program shown in Figure 10.
1197: We can change the word "This" to "The " in the executable file
1198: for this program, \fIex7\fP, by using the following requests:
1199: .P1
1200: adb \-w ex7 \-
1201: ?l 'Th'
1202: ?W 'The '
1203: .P2
1204: The request \fB?l\fP starts at dot and stops at the first match of "Th"
1205: having set dot to the address of the location found.
1206: Note the use of \fB?\fP to write to the
1207: .ul
1208: a.out
1209: file.
1210: The form \fB?*\fP would have been used for a 411 file.
1211: .PP
1212: More frequently the
1213: request will be typed as:
1214: .P1
1215: ?l 'Th'; ?s
1216: .P2
1217: and locates the first occurrence of "Th" and print the entire string.
1218: Execution of this ADB request will set dot to the address of the
1219: "Th" characters.
1220: .PP
1221: As another example of the utility of the patching facility,
1222: consider a C program that has an internal logic flag.
1223: The flag could be set by the user through ADB and the program run.
1224: For example:
1225: .P1
1226: adb a.out \-
1227: :s arg1 arg2
1228: flag/w 1
1229: :c
1230: .P2
1231: The \fB:s\fR request is normally used to single step through a process
1232: or start a process in single step mode.
1233: In this case it starts
1234: .ul
1235: a.out
1236: as a subprocess
1237: with arguments \fBarg1\fP and \fBarg2\fP.
1238: If there is a subprocess running ADB writes to it rather than to the file
1239: so the \fBw\fP request causes \fIflag\fP to be changed in the memory of the subprocess.
1240: .NH
1241: Anomalies
1242: .PP
1243: Below is a list of some strange things that users
1244: should be aware of.
1245: .IP 1.
1246: Function calls and arguments are put on the stack by the C
1247: save routine.
1248: Putting breakpoints at the entry point to routines
1249: means that the function appears not to have been called
1250: when the
1251: breakpoint occurs.
1252: .IP 2.
1253: When printing addresses, ADB uses
1254: either text or data symbols from the \fIa.out\fP file.
1255: This sometimes causes unexpected symbol names to be printed
1256: with data (e.g. \fIsavr5+022\fP).
1257: This does not happen if
1258: \fB?\fR is used for text (instructions)
1259: and \fB/\fP for data.
1260: .IP 3.
1261: ADB cannot handle C register variables
1262: in the most recently activated function.
1263: .LP
1264: .NH
1265: Acknowledgements
1266: .PP
1267: The authors are grateful for the thoughtful comments
1268: on how to organize this document
1269: from R. B. Brandt, E. N. Pinson and B. A. Tague.
1270: D. M. Ritchie made the system changes necessary to accommodate
1271: tracing within ADB. He also participated in discussions
1272: during the writing of ADB.
1273: His earlier work with DB and CDB led to many of the
1274: features found in ADB.
1275: .SG MH-8234-JFM/1273-SRB-unix
1276: .NH
1277: References
1278: .LP
1279: .IP 1.
1280: D. M. Ritchie and K. Thompson,
1281: ``The UNIX Time-Sharing System,''
1282: CACM, July, 1974.
1283: .IP 2.
1284: B. W. Kernighan and D. M. Ritchie,
1285: .ul
1286: The C Programming Language,
1287: Prentice-Hall, 1978.
1288: .IP 3.
1289: K. Thompson and D. M. Ritchie,
1290: UNIX Programmer's Manual - 7th Edition,
1291: 1978.
1292: .IP 4.
1293: B. W. Kernighan and P. J. Plauger,
1294: .ul
1295: Software Tools,
1296: Addison-Wesley, 1976.
1297: .sp 100
1298: .nr PS 9
1299: .nr VS 11
1300: . \" START OF Figures
1301: .de P1
1302: .nf
1303: .in +.5i
1304: .ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i
1305: .sp
1306: .ps 9
1307: .vs 11p
1308: ..
1309: .de P2
1310: .sp
1311: .fi
1312: .ps \\n(PS
1313: .vs \\n(VS
1314: .in -.5i
1315: ..
1316: .SH
1317: Figure 1: C program with pointer bug
1318: .LP
1319: .P1
1320: struct buf {
1321: int fildes;
1322: int nleft;
1323: char *nextp;
1324: char buff[512];
1325: }bb;
1326: struct buf *obuf;
1327:
1328: char *charp "this is a sentence.";
1329:
1330: main(argc,argv)
1331: int argc;
1332: char **argv;
1333: {
1334: char cc;
1335:
1336: if(argc < 2) {
1337: printf("Input file missing\\n");
1338: exit(8);
1339: }
1340:
1341: if((fcreat(argv[1],obuf)) < 0){
1342: printf("%s : not found\\n", argv[1]);
1343: exit(8);
1344: }
1345: charp = \'T\';
1346: printf("debug 1 %s\\n",charp);
1347: while(cc= *charp++)
1348: putc(cc,obuf);
1349: fflush(obuf);
1350: }
1351: .P2
1352: .sp 100
1353: .SH
1354: Figure 2: ADB output for C program of Figure 1
1355: .LP
1356: .P1
1357: .ft B
1358: adb a.out core
1359: $c
1360: .ft R
1361: ~main(02,0177762)
1362: .ft B
1363: $C
1364: .ft R
1365: ~main(02,0177762)
1366: argc: 02
1367: argv: 0177762
1368: cc: 02124
1369: .ft B
1370: $r
1371: .ft R
1372: ps 0170010
1373: pc 0204 ~main+0152
1374: sp 0177740
1375: r5 0177752
1376: r4 01
1377: r3 0
1378: r2 0
1379: r1 0
1380: r0 0124
1381: ~main+0152: mov _obuf,(sp)
1382: .ft B
1383: $e
1384: .ft R
1385: savr5: 0
1386: _obuf: 0
1387: _charp: 0124
1388: _errno: 0
1389: _fout: 0
1390: .ft B
1391: $m
1392: .ft R
1393: text map \`ex1\'
1394: b1 = 0 e1 = 02360 f1 = 020
1395: b2 = 0 e2 = 02360 f2 = 020
1396: data map \`core1\'
1397: b1 = 0 e1 = 03500 f1 = 02000
1398: b2 = 0175400 e2 = 0200000 f2 = 05500
1399: .ft B
1400: *charp/s
1401: .ft R
1402: 0124: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTLx Nh@x&_
1403: ~
1404: .ft B
1405: charp/s
1406: .ft R
1407: _charp: T
1408:
1409: _charp+02: this is a sentence.
1410:
1411: _charp+026: Input file missing
1412: .ft B
1413: main.argc/d
1414: .ft R
1415: 0177756: 2
1416: .ft B
1417: *main.argv/3o
1418: .ft R
1419: 0177762: 0177770 0177776 0177777
1420: .ft B
1421: 0177770/s
1422: .ft R
1423: 0177770: a.out
1424: .ft B
1425: *main.argv/3o
1426: .ft R
1427: 0177762: 0177770 0177776 0177777
1428: .ft B
1429: *"/s
1430: .ft R
1431: 0177770: a.out
1432: .ft B
1433: .=o
1434: .ft R
1435: 0177770
1436: .ft B
1437: .\(mi10/d
1438: .ft R
1439: 0177756: 2
1440: .ft B
1441: $q
1442: .P2
1443: .sp 100
1444: .SH
1445: Figure 3: Multiple function C program for stack trace illustration
1446: .LP
1447: .P1
1448: int fcnt,gcnt,hcnt;
1449: h(x,y)
1450: {
1451: int hi; register int hr;
1452: hi = x+1;
1453: hr = x\(miy+1;
1454: hcnt++ ;
1455: hj:
1456: f(hr,hi);
1457: }
1458:
1459: g(p,q)
1460: {
1461: int gi; register int gr;
1462: gi = q\(mip;
1463: gr = q\(mip+1;
1464: gcnt++ ;
1465: gj:
1466: h(gr,gi);
1467: }
1468:
1469: f(a,b)
1470: {
1471: int fi; register int fr;
1472: fi = a+2*b;
1473: fr = a+b;
1474: fcnt++ ;
1475: fj:
1476: g(fr,fi);
1477: }
1478:
1479: main()
1480: {
1481: f(1,1);
1482: }
1483: .P2
1484: .sp 100
1485: .SH
1486: Figure 4: ADB output for C program of Figure 3
1487: .LP
1488: .P1
1489: .ft B
1490: adb
1491: $c
1492: .ft R
1493: ~h(04452,04451)
1494: ~g(04453,011124)
1495: ~f(02,04451)
1496: ~h(04450,04447)
1497: ~g(04451,011120)
1498: ~f(02,04447)
1499: ~h(04446,04445)
1500: ~g(04447,011114)
1501: ~f(02,04445)
1502: ~h(04444,04443)
1503: .ft B
1504: HIT DEL KEY
1505: .ft R
1506: adb
1507: .ft B
1508: ,5$C
1509: .ft R
1510: ~h(04452,04451)
1511: x: 04452
1512: y: 04451
1513: hi: ?
1514: ~g(04453,011124)
1515: p: 04453
1516: q: 011124
1517: gi: 04451
1518: gr: ?
1519: ~f(02,04451)
1520: a: 02
1521: b: 04451
1522: fi: 011124
1523: fr: 04453
1524: ~h(04450,04447)
1525: x: 04450
1526: y: 04447
1527: hi: 04451
1528: hr: 02
1529: ~g(04451,011120)
1530: p: 04451
1531: q: 011120
1532: gi: 04447
1533: gr: 04450
1534: .ft B
1535: fcnt/d
1536: .ft R
1537: _fcnt: 1173
1538: .ft B
1539: gcnt/d
1540: .ft R
1541: _gcnt: 1173
1542: .ft B
1543: hcnt/d
1544: .ft R
1545: _hcnt: 1172
1546: .ft B
1547: h.x/d
1548: .ft R
1549: 022004: 2346
1550: .ft B
1551: $q
1552: .P2
1553: .sp 100
1554: .SH
1555: Figure 5: C program to decode tabs
1556: .LP
1557: .P1
1558: #define MAXLINE 80
1559: #define YES 1
1560: #define NO 0
1561: #define TABSP 8
1562: .sp .5
1563: char input[] "data";
1564: char ibuf[518];
1565: int tabs[MAXLINE];
1566: .sp .5
1567: main()
1568: {
1569: int col, *ptab;
1570: char c;
1571: .sp .5
1572: ptab = tabs;
1573: settab(ptab); /*Set initial tab stops */
1574: col = 1;
1575: if(fopen(input,ibuf) < 0) {
1576: printf("%s : not found\\n",input);
1577: exit(8);
1578: }
1579: while((c = getc(ibuf)) != \(mi1) {
1580: switch(c) {
1581: case \(fm\\t\(fm: /* TAB */
1582: while(tabpos(col) != YES) {
1583: putchar(\(fm \(fm); /* put BLANK */
1584: col++ ;
1585: }
1586: break;
1587: case \(fm\\n\(fm: /*NEWLINE */
1588: putchar(\(fm\\n\(fm);
1589: col = 1;
1590: break;
1591: default:
1592: putchar(c);
1593: col++ ;
1594: }
1595: }
1596: }
1597: .sp .5
1598: /* Tabpos return YES if col is a tab stop */
1599: tabpos(col)
1600: int col;
1601: {
1602: if(col > MAXLINE)
1603: return(YES);
1604: else
1605: return(tabs[col]);
1606: }
1607: .sp .5
1608: /* Settab - Set initial tab stops */
1609: settab(tabp)
1610: int *tabp;
1611: {
1612: int i;
1613: .sp .5
1614: for(i = 0; i<= MAXLINE; i++)
1615: (i%TABSP) ? (tabs[i] = NO) : (tabs[i] = YES);
1616: }
1617: .P2
1618: .sp 100
1619: .SH
1620: Figure 6a: ADB output for C program of Figure 5
1621: .LP
1622: .P1
1623: .ft B
1624: adb a.out \(mi
1625: settab+4:b
1626: fopen+4:b
1627: getc+4:b
1628: tabpos+4:b
1629: $b
1630: .ft R
1631: breakpoints
1632: count bkpt command
1633: 1 ~tabpos+04
1634: 1 _getc+04
1635: 1 _fopen+04
1636: 1 ~settab+04
1637: .ft B
1638: settab,5?ia
1639: .ft R
1640: ~settab: jsr r5,csv
1641: ~settab+04: tst \(mi(sp)
1642: ~settab+06: clr 0177770(r5)
1643: ~settab+012: cmp $0120,0177770(r5)
1644: ~settab+020: blt ~settab+076
1645: ~settab+022:
1646: .ft B
1647: settab,5?i
1648: .ft R
1649: ~settab: jsr r5,csv
1650: tst \(mi(sp)
1651: clr 0177770(r5)
1652: cmp $0120,0177770(r5)
1653: blt ~settab+076
1654: .ft B
1655: :r
1656: .ft R
1657: a.out: running
1658: breakpoint ~settab+04: tst \(mi(sp)
1659: .ft B
1660: settab+4:d
1661: :c
1662: .ft R
1663: a.out: running
1664: breakpoint _fopen+04: mov 04(r5),nulstr+012
1665: .ft B
1666: $C
1667: .ft R
1668: _fopen(02302,02472)
1669: ~main(01,0177770)
1670: col: 01
1671: c: 0
1672: ptab: 03500
1673: .ft B
1674: tabs,3/8o
1675: .ft R
1676: 03500: 01 0 0 0 0 0 0 0
1677: 01 0 0 0 0 0 0 0
1678: 01 0 0 0 0 0 0 0
1679: .P2
1680: .sp 100
1681: .SH
1682: Figure 6b: ADB output for C program of Figure 5
1683: .LP
1684: .P1
1685: .ft B
1686: :c
1687: .ft R
1688: a.out: running
1689: breakpoint _getc+04: mov 04(r5),r1
1690: .ft B
1691: ibuf+6/20c
1692: .ft R
1693: __cleanu+0202: This is a test of
1694: .ft B
1695: :c
1696: .ft R
1697: a.out: running
1698: breakpoint ~tabpos+04: cmp $0120,04(r5)
1699: .ft B
1700: tabpos+4:d
1701: settab+4:b settab,5?ia
1702: settab+4:b settab,5?ia; 0
1703: getc+4,3:b main.c?C; 0
1704: settab+4:b settab,5?ia; ptab/o; 0
1705: $b
1706: .ft R
1707: breakpoints
1708: count bkpt command
1709: 1 ~tabpos+04
1710: 3 _getc+04 main.c?C;0
1711: 1 _fopen+04
1712: 1 ~settab+04 settab,5?ia;ptab?o;0
1713: ~settab: jsr r5,csv
1714: ~settab+04: bpt
1715: ~settab+06: clr 0177770(r5)
1716: ~settab+012: cmp $0120,0177770(r5)
1717: ~settab+020: blt ~settab+076
1718: ~settab+022:
1719: 0177766: 0177770
1720: 0177744: @\`
1721: T0177744: T
1722: h0177744: h
1723: i0177744: i
1724: s0177744: s
1725: .P2
1726: .sp 100
1727: .SH
1728: Figure 7: ADB output for C program with breakpoints
1729: .LP
1730: .in +.5i
1731: .nf
1732: .ps 8
1733: .vs 9
1734: .ft B
1735: adb ex3 \(mi
1736: h+4:b hcnt/d; h.hi/; h.hr/
1737: g+4:b gcnt/d; g.gi/; g.gr/
1738: f+4:b fcnt/d; f.fi/; f.fr/
1739: :r
1740: .ft R
1741: ex3: running
1742: _fcnt: 0
1743: 0177732: 214
1744: symbol not found
1745: .ft B
1746: f+4:b fcnt/d; f.a/; f.b/; f.fi/
1747: g+4:b gcnt/d; g.p/; g.q/; g.gi/
1748: h+4:b hcnt/d; h.x/; h.y/; h.hi/
1749: :c
1750: .ft R
1751: ex3: running
1752: _fcnt: 0
1753: 0177746: 1
1754: 0177750: 1
1755: 0177732: 214
1756: _gcnt: 0
1757: 0177726: 2
1758: 0177730: 3
1759: 0177712: 214
1760: _hcnt: 0
1761: 0177706: 2
1762: 0177710: 1
1763: 0177672: 214
1764: _fcnt: 1
1765: 0177666: 2
1766: 0177670: 3
1767: 0177652: 214
1768: _gcnt: 1
1769: 0177646: 5
1770: 0177650: 8
1771: 0177632: 214
1772: .ft B
1773: HIT DEL
1774: f+4:b fcnt/d; f.a/"a = "d; f.b/"b = "d; f.fi/"fi = "d
1775: g+4:b gcnt/d; g.p/"p = "d; g.q/"q = "d; g.gi/"gi = "d
1776: h+4:b hcnt/d; h.x/"x = "d; h.y/"h = "d; h.hi/"hi = "d
1777: :r
1778: .ft R
1779: ex3: running
1780: _fcnt: 0
1781: 0177746: a = 1
1782: 0177750: b = 1
1783: 0177732: fi = 214
1784: _gcnt: 0
1785: 0177726: p = 2
1786: 0177730: q = 3
1787: 0177712: gi = 214
1788: _hcnt: 0
1789: 0177706: x = 2
1790: 0177710: y = 1
1791: 0177672: hi = 214
1792: _fcnt: 1
1793: 0177666: a = 2
1794: 0177670: b = 3
1795: 0177652: fi = 214
1796: .ft B
1797: HIT DEL
1798: $q
1799: .in -.5i
1800: .sp 100
1801: .SH
1802: Figure 8: ADB address maps
1803: .LP
1804: .de l1
1805: .tc
1806: .ta 1.20i +1.6i +2.5i
1807: ..
1808: .de l3
1809: .tc
1810: .ta 1.6i +2.80i +.2i +1.55i
1811: ..
1812: .de l2
1813: .tc
1814: .ti 1.0i
1815: .ta +0.5i +3.0i +1.75i
1816: .tc _
1817: ..
1818: .de l5
1819: .tc
1820: .ti 1.0i
1821: .ta +0.75i +3.0i +1.5i
1822: .tc _
1823: ..
1824: .de l6
1825: .tc
1826: .ti 1.0i
1827: .ta +.8i +2.85i +0.4i +1.1i
1828: ..
1829: .de l8
1830: .tc
1831: .ti 1.0i
1832: .ta +0.5i +3.0i +1.75i
1833: .tc _
1834: ..
1835: .de la
1836: .tc
1837: .ta 1.20i +1.25i +1.7i
1838: ..
1839: .de lc
1840: .tc
1841: .ti 1.0i
1842: .ta +.85i +1.6i +.35i +1.1i
1843: ..
1844: .de lb
1845: .tc
1846: .ti 1.0i
1847: .ta +0.75i +1.75i +1.5i
1848: .tc _
1849: ..
1850: .ul
1851: 407 files
1852: .sp
1853: .l1
1854: a.out hdr text+data
1855: .l2
1856: | | |
1857: .l3
1858: 0 D
1859: .sp
1860: .l1
1861: core hdr text+data stack
1862: .l5
1863: | | ......| |
1864: .l6
1865: 0 D S E
1866: .sp 2
1867: .ul
1868: 410 files (shared text)
1869: .sp
1870: .l1
1871: a.out hdr text data
1872: .l2
1873: | | | |
1874: .l3
1875: 0 T B D
1876: .sp
1877: .la
1878: core hdr data stack
1879: .lb
1880: | | ......| |
1881: .lc
1882: B D S E
1883: .sp 2
1884: .ul
1885: 411 files (separated I and D space)
1886: .sp
1887: .l1
1888: a.out hdr text data
1889: .l2
1890: | | | |
1891: .l3
1892: 0 T 0 D
1893: .sp
1894: .la
1895: core hdr data stack
1896: .lb
1897: | | ......| |
1898: .lc
1899: 0 D S E
1900: .sp 2
1901: The following
1902: .ul
1903: adb
1904: variables are set.
1905: .nf
1906: .ta .75i 1.5i 3.5i 4.5i 5.5i
1907: .sp
1908: 407 410 411
1909: .sp
1910: b base of data 0 B 0
1911: d length of data D D\(miB D
1912: s length of stack S S S
1913: t length of text 0 T T
1914: .sp 100
1915: .SH
1916: Figure 9: ADB output for maps
1917: .LP
1918: .nf
1919: .in +.5i
1920: .ft B
1921: adb map407 core407
1922: $m
1923: .ft R
1924: text map \`map407\'
1925: b1 = 0 e1 = 0256 f1 = 020
1926: b2 = 0 e2 = 0256 f2 = 020
1927: data map \`core407\'
1928: b1 = 0 e1 = 0300 f1 = 02000
1929: b2 = 0175400 e2 = 0200000 f2 = 02300
1930: .ft B
1931: $v
1932: .ft R
1933: variables
1934: d = 0300
1935: m = 0407
1936: s = 02400
1937: .ft B
1938: $q
1939: .sp 2
1940: adb map410 core410
1941: $m
1942: .ft R
1943: text map \`map410\'
1944: b1 = 0 e1 = 0200 f1 = 020
1945: b2 = 020000 e2 = 020116 f2 = 0220
1946: data map \`core410\'
1947: b1 = 020000 e1 = 020200 f1 = 02000
1948: b2 = 0175400 e2 = 0200000 f2 = 02200
1949: .ft B
1950: $v
1951: .ft R
1952: variables
1953: b = 020000
1954: d = 0200
1955: m = 0410
1956: s = 02400
1957: t = 0200
1958: .ft B
1959: $q
1960: .sp 2
1961: adb map411 core411
1962: $m
1963: .ft R
1964: text map \`map411\'
1965: b1 = 0 e1 = 0200 f1 = 020
1966: b2 = 0 e2 = 0116 f2 = 0220
1967: data map \`core411\'
1968: b1 = 0 e1 = 0200 f1 = 02000
1969: b2 = 0175400 e2 = 0200000 f2 = 02200
1970: .ft B
1971: $v
1972: .ft R
1973: variables
1974: d = 0200
1975: m = 0411
1976: s = 02400
1977: t = 0200
1978: .ft B
1979: $q
1980: .in -.5i
1981: .sp 100
1982: .SH
1983: Figure 10: Simple C program for illustrating formatting and patching
1984: .LP
1985: .P1
1986: char str1[] "This is a character string";
1987: int one 1;
1988: int number 456;
1989: long lnum 1234;
1990: float fpt 1.25;
1991: char str2[] "This is the second character string";
1992: main()
1993: {
1994: one = 2;
1995: }
1996: .P2
1997: .sp 100
1998: .SH
1999: Figure 11: ADB output illustrating fancy formats
2000: .LP
2001: .nf
2002: .ps 9
2003: .vs 11p
2004: .ft B
2005: adb map410 core410
2006: <b,\(mi1/8ona
2007: .ft R
2008: 020000: 0 064124 071551 064440 020163 020141 064143 071141
2009: .sp .5
2010: _str1+016: 061541 062564 020162 072163 064562 063556 0 02
2011: .sp .5
2012: _number:
2013: _number: 0710 0 02322 040240 0 064124 071551 064440
2014: .sp .5
2015: _str2+06: 020163 064164 020145 062563 067543 062156 061440 060550
2016: .sp .5
2017: _str2+026: 060562 072143 071145 071440 071164 067151 0147 0
2018: .sp .5
2019: savr5+02: 0 0 0 0 0 0 0 0
2020: .sp .5
2021: .ft B
2022: <b,20/4o4^8Cn
2023: .ft R
2024: 020000: 0 064124 071551 064440 @\`@\`This i
2025: 020163 020141 064143 071141 s a char
2026: 061541 062564 020162 072163 acter st
2027: 064562 063556 0 02 ring@\`@\`@b@\`
2028: .sp .5
2029: _number: 0710 0 02322 040240 H@a@\`@\`R@d @@
2030: 0 064124 071551 064440 @\`@\`This i
2031: 020163 064164 020145 062563 s the se
2032: 067543 062156 061440 060550 cond cha
2033: 060562 072143 071145 071440 racter s
2034: 071164 067151 0147 0 tring@\`@\`@\`
2035: 0 0 0 0 @\`@\`@\`@\`@\`@\`@\`@\`
2036: 0 0 0 0 @\`@\`@\`@\`@\`@\`@\`@\`
2037: data address not found
2038: .ft B
2039: <b,20/4o4^8t8cna
2040: .ft R
2041: 020000: 0 064124 071551 064440 This i
2042: _str1+06: 020163 020141 064143 071141 s a char
2043: _str1+016: 061541 062564 020162 072163 acter st
2044: _str1+026: 064562 063556 0 02 ring
2045: _number:
2046: _number: 0710 0 02322 040240 HR
2047: _fpt+02: 0 064124 071551 064440 This i
2048: _str2+06: 020163 064164 020145 062563 s the se
2049: _str2+016: 067543 062156 061440 060550 cond cha
2050: _str2+026: 060562 072143 071145 071440 racter s
2051: _str2+036: 071164 067151 0147 0 tring
2052: savr5+02: 0 0 0 0
2053: savr5+012: 0 0 0 0
2054: data address not found
2055: .ft B
2056: <b,10/2b8t^2cn
2057: .ft R
2058: 020000: 0 0
2059: .sp .5
2060: _str1: 0124 0150 Th
2061: 0151 0163 is
2062: 040 0151 i
2063: 0163 040 s
2064: 0141 040 a
2065: 0143 0150 ch
2066: 0141 0162 ar
2067: 0141 0143 ac
2068: 0164 0145 te
2069: .ft B
2070: $Q
2071: .sp 100
2072: .SH
2073: Figure 12: Directory and inode dumps
2074: .LP
2075: .nf
2076: .ft B
2077: adb dir \(mi
2078: =nt"Inode"t"Name"
2079: 0,\(mi1?ut14cn
2080: .ft R
2081:
2082: Inode Name
2083: 0: 652 .
2084: 82 ..
2085: 5971 cap.c
2086: 5323 cap
2087: 0 pp
2088: .sp 4
2089: .ft B
2090: adb /dev/src \(mi
2091: .ft B
2092: 02000>b
2093: ?m<b
2094: .ft R
2095: new map \`/dev/src\'
2096: b1 = 02000 e1 = 0100000000 f1 = 0
2097: b2 = 0 e2 = 0 f2 = 0
2098: .ft B
2099: $v
2100: .ft R
2101: variables
2102: b = 02000
2103: .ft B
2104: <b,\(mi1?"flags"8ton"links,uid,gid"8t3bn"size"8tbrdn"addr"8t8un"times"8t2Y2na
2105: .ft R
2106: 02000: flags 073145
2107: links,uid,gid 0163 0164 0141
2108: size 0162 10356
2109: addr 28770 8236 25956 27766 25455 8236 25956 25206
2110: times 1976 Feb 5 08:34:56 1975 Dec 28 10:55:15
2111:
2112: 02040: flags 024555
2113: links,uid,gid 012 0163 0164
2114: size 0162 25461
2115: addr 8308 30050 8294 25130 15216 26890 29806 10784
2116: times 1976 Aug 17 12:16:51 1976 Aug 17 12:16:51
2117:
2118: 02100: flags 05173
2119: links,uid,gid 011 0162 0145
2120: size 0147 29545
2121: addr 25972 8306 28265 8308 25642 15216 2314 25970
2122: times 1977 Apr 2 08:58:01 1977 Feb 5 10:21:44
2123: .\"
2124: .\" Start of Summary
2125: .sp 100
2126: .TL
2127: ADB Summary
2128: .LP
2129: .LP
2130: .if t .2C
2131: .nr VS 9
2132: .nr VS 11
2133: .SH
2134: Command Summary
2135: .LP
2136: .ta .7i
2137: a) formatted printing
2138: .sp .5
2139: .IP "\fB? \fIformat\fR" .7i
2140: print from \fIa.out\fR file according to \fIformat\fR
2141: .IP "\fB/ \fIformat\fR" .7i
2142: print from \fIcore\fR file according to \fIformat\fR
2143: .IP "\fB= \fIformat\fR" .7i
2144: print the value of \fIdot\fR
2145: .sp .5
2146: .IP "\fB?w\fR expr" .7i
2147: write expression into \fIa.out\fR file
2148: .IP "\fB/w\fR expr" .7i
2149: write expression into \fIcore\fR file
2150: .sp .5
2151: .IP "\fB?l\fR expr" .7i
2152: locate expression in \fIa.out\fR file
2153: .LP
2154: .ta .7i
2155: b) breakpoint and program control
2156: .LP
2157: .ta .7i
2158: .nf
2159: .ta .7i
2160: \fB:b\fR set breakpoint at \fIdot\fR
2161: \fB:c\fR continue running program
2162: \fB:d\fR delete breakpoint
2163: \fB:k\fR kill the program being debugged
2164: \fB:r\fR run \fIa.out\fR file under ADB control
2165: \fB:s\fR single step
2166: .LP
2167: .ta .7i
2168: c) miscellaneous printing
2169: .LP
2170: .ta .7i
2171: .nf
2172: \fB$b\fR print current breakpoints
2173: \fB$c\fR C stack trace
2174: \fB$e\fR external variables
2175: \fB$f\fR floating registers
2176: \fB$m\fR print ADB segment maps
2177: \fB$q\fR exit from ADB
2178: \fB$r\fR general registers
2179: \fB$s\fR set offset for symbol match
2180: \fB$v\fR print ADB variables
2181: \fB$w\fR set output line width
2182: .LP
2183: .ta .7i
2184: d) calling the shell
2185: .LP
2186: .ta .7i
2187: .nf
2188: \fB!\fR call \fIshell\fP to read rest of line
2189: .LP
2190: .ta .7i
2191: e) assignment to variables
2192: .LP
2193: .ta .7i
2194: .nf
2195: \fB>\fIname\fR assign dot to variable or register \fIname\fR
2196: .sp 100
2197: .SH
2198: Format Summary
2199: .LP
2200: .ta .7i
2201: .nf
2202: \fBa \fRthe value of dot
2203: \fBb \fRone byte in octal
2204: \fBc \fRone byte as a character
2205: \fBd \fRone word in decimal
2206: \fBf \fRtwo words in floating point
2207: \fBi \fRPDP 11 instruction
2208: \fBo \fRone word in octal
2209: \fBn \fRprint a newline
2210: \fBr \fRprint a blank space
2211: \fBs \fRa null terminated character string
2212: \fIn\fBt \fRmove to next \fIn\fR space tab
2213: \fBu \fRone word as unsigned integer
2214: \fBx \fRhexadecimal
2215: \fBY \fRdate
2216: \fB^ \fRbackup dot
2217: \fB"..."\fR print string
2218: .LP
2219: .ta .7i
2220: .SH
2221: Expression Summary
2222: .LP
2223: .ta .7i
2224: a) expression components
2225: .LP
2226: .ta .1.1i
2227: .nf
2228: \fBdecimal integer \fRe.g. 256
2229: \fBoctal integer \fRe.g. 0277
2230: \fBhexadecimal \fRe.g. #ff
2231: \fBsymbols \fRe.g. flag _main main.argc
2232: \fBvariables \fRe.g. <b
2233: \fBregisters \fRe.g. <pc <r0
2234: \fB(expression) \fRexpression grouping
2235: .LP
2236: .ta .7i
2237: b) dyadic operators
2238: .LP
2239: .ta .7i
2240: .nf
2241: \fB+\fP add
2242: \fB\(mi\fP subtract
2243: \fB*\fP multiply
2244: \fB%\fP integer division
2245: \fB&\fP bitwise and
2246: \fB|\fP bitwise or
2247: \fB#\fP round up to the next multiple
2248: .LP
2249: .ta .7i
2250: c) monadic operators
2251: .LP
2252: .ta .7i
2253: .nf
2254: \v'.25m'\s+2\fB~\fP\s0\v'-.25m' not
2255: \fB*\fR contents of location
2256: \fB\(mi\fR integer negate
2257: .fi
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.