|
|
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.