MirOS Manual: 11.adb(PSD)


               A Tutorial Introduction to ADB

                      J. F. Maranzano

                        S. R. Bourne

                          ABSTRACT

          Debugging tools generally provide a wealth of
     information  about the inner workings of programs.
     These tools have been available on UNIX- to  allow
     users  to  examine ``core'' files that result from
     aborted programs. A new  debugging  program,  ADB,
     provides  enhanced  capabilities to examine "core"
     and other program files in a variety  of  formats,
     run  programs  with embedded breakpoints and patch
     files.

          ADB is an indispensable but complex tool  for
     debugging  crashed  systems  and/or programs. This
     document provides  an  introduction  to  ADB  with
     examples  of its use. It explains the various for-
     matting options, techniques for debugging  C  pro-
     grams,  examples  of printing file system informa-
     tion and patching.

1. Introduction

     ADB is a new debugging program  that  is  available  on
UNIX.  It  provides  capabilities  to look at ``core'' files
resulting from aborted programs, print output in  a  variety
of  formats,  patch  files,  and  run programs with embedded
breakpoints. This document provides  examples  of  the  more
useful  features  of ADB. The reader is expected to be fami-
liar with the basic commands on UNIX with  the  C  language,
and with References 1, 2 and 3.

2. A Quick Survey

_________________________
- UNIX is a registered trademark of AT&T  Bell  Labora-
tories in the USA and other countries.

PS1:10-2                      A Tutorial Introduction to ADB

2.1. Invocation

     ADB is invoked as:
          adb objfile corefile
where objfile is an executable UNIX file and corefile  is  a
core image file. Many times this will look like:
          adb a.out core
or more simply:
          adb
where the defaults are  a.out  and  core  respectively.  The
filename minus (-) means ignore this argument as in:
          adb - core

     ADB has requests  for  examining  locations  in  either
file.  The ? request examines the contents of objfile, the /
request examines the corefile. The  general  form  of  these
requests is:
          address ? format
or
          address / format

2.2. Current Address

     ADB maintains a current address, called dot, similar in
function  to the current pointer in the UNIX editor. When an
address is entered, the current address is set to that loca-
tion, so that:
          0126?i
sets dot to octal 126 and prints  the  instruction  at  that
address. The request:
          .,10/d
prints 10 decimal numbers  starting  at  dot.  Dot  ends  up
referring to the address of the last item printed. When used
with the ?  or  /  requests,  the  current  address  can  be
advanced  by typing newline; it can be decremented by typing
^.

     Addresses are represented by  expressions.  Expressions
are  made  up from decimal, octal, and hexadecimal integers,
and symbols from the program under test. These may  be  com-
bined  with  the  operators +, -, *, % (integer division), &
(bitwise and), | (bitwise inclusive or),  # (round up to the
next  multiple),  and ~ (not). (All arithmetic within ADB is
32 bits.) When typing a symbolic address for  a  C  program,
the  user  can  type  name or _name; ADB will recognize both
forms.

2.3. Formats

     To print data, a user specifies a collection of letters
and  characters  that  describe  the format of the printout.
Formats are "remembered" in the sense that typing a  request
without  one  will  cause  the new printout to appear in the
previous format. The following are the  most  commonly  used

A Tutorial Introduction to ADB                      PS1:10-3

format letters.
          b      one byte in octal
          c      one byte as a character
          o      one word in octal
          d      one word in decimal
          f      two words in floating point
          i      PDP 11 instruction
          s      a null terminated character string
          a      the value of dot
          u      one word as unsigned integer
          n      print a newline
          r      print a blank space
          ^      backup dot
(Format letters are also available for  "long"  values,  for
example,  `D'  for long decimal, and `F' for double floating
point.) For other formats see the ADB manual.

2.4. General Request Meanings

     The general form of a request is:
          address,count command modifier
which sets `dot' to address and executes the  command  count
times.

     The following table illustrates some general  ADB  com-
mand meanings:
          Command        Meaning
              ?  Print contents from a.out file
              /  Print contents from core file
              =  Print value of "dot"
              :  Breakpoint control
              $  Miscellaneous requests
              ;  Request separator
              !  Escape to shell

     ADB catches signals, so a user cannot use a quit signal
to  exit  from ADB. The request $q or $Q (or cntl-D) must be
used to exit from ADB.

3. Debugging C Programs

3.1. Debugging A Core Image

     Consider the C program in Figure 1. The program is used
to  illustrate  a  common  error  made by C programmers. The
object of the program is to change the  lower  case  "t"  to
upper  case in the string pointed to by charp and then write
the character string to the file indicated  by  argument  1.
The  bug  shown  is  that the character "T" is stored in the
pointer charp instead of the string  pointed  to  by  charp.
Executing the program produces a core file because of an out
of bounds memory reference.

     ADB is invoked by:

PS1:10-4                      A Tutorial Introduction to ADB

          adb a.out core
The first debugging request:
          $c
is used to  give  a  C  backtrace  through  the  subroutines
called.  As  shown  in Figure 2 only one function (main) was
called and the arguments argc and argv have octal values  02
and  0177762 respectively. Both of these values look reason-
able; 02 = two arguments, 0177762  =  address  on  stack  of
parameter vector.
The next request:
          $C
is used to give a C backtrace plus an interpretation of  all
the  local  variables  in  each function and their values in
octal. The value of the variable cc looks incorrect since cc
was declared as a character.

     The next request:
          $r
prints out the registers including the program  counter  and
an interpretation of the instruction at that location.

     The request:
          $e
prints out the values of all external variables.

     A map exists for each file handled by ADB. The map  for
the  a.out  file is referenced by ? whereas the map for core
file is referenced by /. Furthermore, a good rule  of  thumb
is  to use ? for instructions and / for data when looking at
programs. To print out information about the maps type:
          $m
This produces a report of the contents  of  the  maps.  More
about these maps later.

     In our example, it is useful to see the contents of the
string pointed to by charp. This is done by:
          *charp/s
which says use charp as a pointer in the core file and print
the information as a character string. This printout clearly
shows that the character buffer was incorrectly  overwritten
and  helps identify the error. Printing the locations around
charp shows that  the  buffer  is  unchanged  but  that  the
pointer  is  destroyed.  Using ADB similarly, we could print
information about the arguments to a function. The request:
          main.argc/d
prints the decimal core image value of the argument argc  in
the function main.
The request:
          *main.argv,3/o
prints the octal  values  of  the  three  consecutive  cells
pointed  to  by  argv  in the function main. Note that these
values are the addresses of the arguments  to  main.  There-
fore:
          0177770/s

A Tutorial Introduction to ADB                      PS1:10-5

prints the ASCII value of the first argument. Another way to
print this value would have been
          *"/s
The " means ditto which remembers the last address typed, in
this case main.argc ; the * instructs ADB to use the address
field of the core file as a pointer.

     The request:
          .=o
prints the current address (not its contents) in octal which
has  been  set  to  the  address  of the first argument. The
current address, dot, is  used  by  ADB  to  "remember"  its
current  location. It allows the user to reference locations
relative to the current address, for example:
          .-10/d

3.2. Multiple Functions

     Consider the C program illustrated in  Figure  3.  This
program  calls  functions  f,  g,  and  h until the stack is
exhausted and a core image is produced.

     Again you can enter the debugger via:
          adb
which assumes the names a.out and core  for  the  executable
file and core image file respectively. The request:
          $c
will fill a page of backtrace references to  f,  g,  and  h.
Figure  4  shows  an  abbreviated list (typing DEL will ter-
minate the output and bring you back to ADB request level).

     The request:
          ,5$C
prints the five most recent activations.

     Notice that each function (f,g,h) has a counter of  the
number of times it was called.

     The request:
          fcnt/d
prints the decimal value of the counter for the function  f.
Similarly gcnt and hcnt could be printed. To print the value
of an automatic variable, for example the decimal value of x
in the last call of the function h, type:
          h.x/d
It is currently not possible  in  the  exported  version  to
print  stack frames other than the most recent activation of
a function. Therefore, a user can print everything  with  $C
or the occurrence of a variable in the most recent call of a
function. It is possible with the $C  request,  however,  to
print the stack frame starting at some address as address$C.

PS1:10-6                      A Tutorial Introduction to ADB

3.3. Setting Breakpoints

     Consider the C program in Figure 5. This program, which
changes  tabs into blanks, is adapted from Software Tools by
Kernighan and Plauger, pp. 18-27.

     We will run this program under the control of ADB  (see
Figure 6a) by:
          adb a.out -
Breakpoints are set in the program as:
          address:b  [request]
The requests:
          settab+4:b
          fopen+4:b
          getc+4:b
          tabpos+4:b
set breakpoints at the start of these functions. C does  not
generate  statement  labels.  Therefore  it is currently not
possible to plant breakpoints at locations other than  func-
tion  entry points without a knowledge of the code generated
by the C compiler. The above addresses are entered  as  sym-
bol+4  so that they will appear in any C backtrace since the
first instruction of each function is a call to the  C  save
routine  (csv). Note that some of the functions are from the
C library.

     To print the location of breakpoints one types:
          $b
The  display  indicates  a  count  field.  A  breakpoint  is
bypassed  count  -1 times before causing a stop. The command
field indicates the ADB requests to be  executed  each  time
the  breakpoint  is  encountered.  In our example no command
fields are present.

     By displaying the original instructions at the function
settab  we  see  that the breakpoint is set after the jsr to
the C save routine. We can display  the  instructions  using
the ADB request:
          settab,5?ia
This request displays five instructions starting  at  settab
with the addresses of each location displayed. Another vari-
ation is:
          settab,5?i
which displays  the  instructions  with  only  the  starting
address.

     Notice that we accessed the addresses  from  the  a.out
file  with the ? command. In general when asking for a prin-
tout of multiple items, ADB will advance the current address
the number of bytes necessary to satisfy the request; in the
above example  five  instructions  were  displayed  and  the
current address was advanced 18 (decimal) bytes.

     To run the program one simply types:

A Tutorial Introduction to ADB                      PS1:10-7

          :r
To delete a breakpoint, for instance the entry to the  func-
tion settab, one types:
          settab+4:d
To continue execution of the  program  from  the  breakpoint
type:
          :c

     Once the program has  stopped  (in  this  case  at  the
breakpoint  for  fopen), ADB requests can be used to display
the contents of memory. For example:
          $C
to display a stack trace, or:
          tabs,3/8o
to print three lines of 8  locations  each  from  the  array
called  tabs. By this time (at location fopen) in the C pro-
gram, settab has been called and should have set  a  one  in
every eighth location of tabs.

3.4. Advanced Breakpoint Usage

     We continue execution of the program with:
          :c
See Figure 6b. Getc is called three times and  the  contents
of  the  variable  c in the function main are displayed each
time. The single character on the left hand edge is the out-
put  from the C program. On the third occurrence of getc the
program stops. We can look at the full buffer of  characters
by typing:
          ibuf+6/20c
When we continue the program with:
          :c
we hit our first breakpoint at tabpos since there is  a  tab
following the "This" word of the data.

     Several breakpoints of tabpos will occur until the pro-
gram  has  changed  the tab into equivalent blanks. Since we
feel that tabpos is working, we can remove the breakpoint at
that location by:
          tabpos+4:d
If the program is continued with:
          :c
it resumes normal execution after ADB prints the message
          a.out:running

     The UNIX quit and interrupt signals act on  ADB  itself
rather  than on the program being debugged. If such a signal
occurs then the program being debugged is stopped  and  con-
trol  is  returned to ADB. The signal is saved by ADB and is
passed on to the test program if:
          :c
is typed. This can be useful when testing interrupt handling
routines.  The  signal  is not passed on to the test program
if:

PS1:10-8                      A Tutorial Introduction to ADB

          :c  0
is typed.

     Now let us reset the breakpoint at settab  and  display
the instructions located there when we reach the breakpoint.
This is accomplished by:
          settab+4:b  settab,5?ia  *
It is also possible to execute the  ADB  requests  for  each
occurrence  of  the breakpoint but only stop after the third
occurrence by typing:
          getc+4,3:b  main.c?C  *
This request will print the local variable c in the function
main  at each occurrence of the breakpoint. The semicolon is
used to separate multiple ADB requests on a single line.

     Warning: setting a breakpoint causes the value  of  dot
to  be  changed;  executing  the  program under ADB does not
change dot. Therefore:
          settab+4:b  .,5?ia
          fopen+4:b
will print the last thing dot was set  to  (in  the  example
fopen+4)  not  the  current location (settab+4) at which the
program is executing.

     A breakpoint can be overwritten without first  deleting
the old breakpoint. For example:
          settab+4:b  settab,5?ia; ptab/o  *
could be entered after typing the above requests.

     Now the display of breakpoints:
          $b
shows the above request for the settab breakpoint. When  the
breakpoint  at  settab  is  encountered the ADB requests are
executed. Note  that  the  location  at  settab+4  has  been
changed  to  plant  the  breakpoint; all the other locations
match their original value.

     Using the functions, f, g and h shown in Figure  3,  we
can  follow  the execution of each function by planting non-
stopping breakpoints. We call ADB with the  executable  pro-
gram of Figure 3 as follows:
          adb ex3 -
Suppose we enter the following breakpoints:
          h+4:b  hcnt/d;  h.hi/;  h.hr/
_________________________
* Owing to a bug in early versions  of  ADB  (including
the version distributed in Generic 3 UNIX) these state-
ments must be written as:
          settab+4:b      settab,5?ia;0
          getc+4,3:b      main.c?C;0
          settab+4:b      settab,5?ia; ptab/o;0
Note that ;0 will set dot  to  zero  and  stop  at  the
breakpoint.

A Tutorial Introduction to ADB                      PS1:10-9

          g+4:b  gcnt/d;  g.gi/;  g.gr/
          f+4:b  fcnt/d;  f.fi/;  f.fr/
          :r
Each request line indicates that the variables  are  printed
in decimal (by the specification d). Since the format is not
changed, the d can be left off all but the first request.

     The output in Figure 7 illustrates two  points.  First,
the  ADB  requests  in  the breakpoint line are not examined
until the program under test is run. That means  any  errors
in those ADB requests is not detected until run time. At the
location of the error ADB stops running the program.

     The second point is the way ADB handles register  vari-
ables.  ADB  uses  the  symbol  table  to address variables.
Register variables, like f.fr above, have pointers to unini-
tialized  places on the stack. Therefore the message "symbol
not found".

     Another way of getting at the data in this  example  is
to print the variables used in the call as:
          f+4:b  fcnt/d;  f.a/;  f.b/;  f.fi/
          g+4:b  gcnt/d;  g.p/;  g.q/;  g.gi/
          :c
The operator / was used instead of ? to read values from the
core  file. The output for each function, as shown in Figure
7, has the same format. For the function f, for example,  it
shows  the  name and value of the external variable fcnt. It
also shows the address on the stack and value of  the  vari-
ables a, b and fi.

     Notice that the addresses on the stack will continue to
decrease  until  no address space is left for program execu-
tion at which time (after many pages of output) the  program
under test aborts. A display with names would be produced by
requests like the following:
          f+4:b  fcnt/d;  f.a/"a="d;  f.b/"b="d;  f.fi/"fi="d
In this format the quoted string is  printed  literally  and
the  d  produces  a  decimal  display  of the variables. The
results are shown in Figure 7.

3.5. Other Breakpoint Facilities

+   Arguments and change of standard input  and  output  are
    passed to a program as:
              :r  arg1  arg2 ... <infile  >outfile
    This request kills any existing program under  test  and
    starts the a.out afresh.

+   The program being debugged can be single stepped by:
              :s
    If necessary, this request will  start  up  the  program
    being  debugged  and  stop  after  executing  the  first

PS1:10-10                     A Tutorial Introduction to ADB

    instruction.

+   ADB allows a program to be entered at a specific address
    by typing:
              address:r

+   The count field can be used to skip the first  n  break-
    points as:
              ,n:r
    The request:
              ,n:c
    may also be used for skipping the  first  n  breakpoints
    when continuing a program.

+   A program can be continued at an address different  from
    the breakpoint by:
              address:c

+   The program being debugged runs as  a  separate  process
    and can be killed by:
              :k

4. Maps

     UNIX supports several executable file  formats.   These
are  used  to tell the loader how to load  the program file.
File type 407 is the most common and is  generated  by  a  C
compiler invocation such as cc pgm.c. A 410 file is produced
by a C compiler command of the form cc -n pgm.c,  whereas  a
411  file  is  produced by cc -i pgm.c. ADB interprets these
different file formats and provides access to the  different
segments  through a set of maps (see Figure 8). To print the
maps type:
          $m

     In 407 files, both text  (instructions)  and  data  are
intermixed.  This  makes  it impossible for ADB to differen-
tiate data from instructions and some of  the  printed  sym-
bolic  addresses  look incorrect; for example, printing data
addresses as offsets from routines.

     In  410  files  (shared  text),  the  instructions  are
separated  from  data  and  ?* accesses the data part of the
a.out file. The ?*  request tells ADB to use the second part
of  the  map  in  the a.out file. Accessing data in the core
file shows the data after it was modified by  the  execution
of  the  program. Notice also that the data segment may have
grown during program execution.

     In 411 files (separated I & D space), the  instructions
and  data  are  also separated. However, in this case, since
data is  mapped  through  a  separate  set  of  segmentation

A Tutorial Introduction to ADB                     PS1:10-11

registers,  the base of the data segment is also relative to
address zero. In this case since the addresses overlap it is
necessary to use the ?* operator to access the data space of
the a.out file. In both 410 and 411 files the  corresponding
core file does not contain the program text.

     Figure 9 shows the display of three maps for  the  same
program  linked  as  a 407, 410, 411 respectively. The b, e,
and f fields are used by ADB  to  map  addresses  into  file
addresses. The "f1" field is the length of the header at the
beginning of the file (020 bytes for an a.out file and 02000
bytes  for  a core file). The "f2" field is the displacement
from the beginning of the file to the data. For a  407  file
with  mixed  text and data this is the same as the length of
the header; for 410 and 411 files this is the length of  the
header plus the size of the text portion.

     The "b" and "e" fields  are  the  starting  and  ending
locations  for  a segment. Given an address, A, the location
in the file (either a.out or core) is calculated as:
          b1≤_A≤_e1 => file address = (A-b1)+f1
          b2≤_A≤_e2 => file address = (A-b2)+f2
A user can access locations by using the ADB  defined  vari-
ables.  The  $v  request prints the variables initialized by
ADB:
          b      base address of data segment
          d      length of the data segment
          s      length of the stack
          t      length of the text
          m      execution type (407,410,411)

     In Figure 9 those variables not present are  zero.  Use
can be made of these variables by expressions such as:
          <b
in the address field. Similarly the value  of  the  variable
can be changed by an assignment request such as:
          02000>b
that sets b to octal 2000. These  variables  are  useful  to
know  if the file under examination is an executable or core
image file.

     ADB reads the header of the core image file to find the
values  for  these  variables.  If the second file specified
does not seem to be a core file, or if it  is  missing  then
the header of the executable file is used instead.

5. Advanced Usage

     It is possible with ADB to combine formatting  requests
to provide elaborate displays. Below are several examples.

5.1. Formatted dump

     The line:

PS1:10-12                     A Tutorial Introduction to ADB

          <b,-1/4o4^8Cn
prints 4 octal words followed by their ASCII  interpretation
from the data space of the core image file. Broken down, the
various request pieces mean:

          <b     The base address of the data segment.

          <b,-1  Print from the base address to the  end  of
                 file.  A  negative  count  is used here and
                 elsewhere to  loop  indefinitely  or  until
                 some  error condition (like end of file) is
                 detected.

The format 4o4^8Cn is broken down as follows:

          4o     Print 4 octal locations.

          4^     Backup the current address 4 locations  (to
                 the original start of the field).

          8C     Print 8  consecutive  characters  using  an
                 escape  convention;  each  character in the
                 range 0 to 037 is printed as @ followed  by
                 the  corresponding  character  in the range
                 0140 to 0177. An @ is printed as @@.

          n      Print a newline.

     The request:
          <b,<d/4o4^8Cn
could have been used instead to allow the printing  to  stop
at the end of the data segment (<d provides the data segment
size in bytes).

     The formatting requests  can  be  combined  with  ADB's
ability  to  read  in  a script to produce a core image dump
script. ADB is invoked as:
          adb a.out core < dump
to read in a script file, dump, of requests. An  example  of
such a script is:
          120$w
          4095$s
          $v
          =3n
          $m
          =3n"C Stack Backtrace"
          $C
          =3n"C External Variables"
          $e
          =3n"Registers"
          $r
          0$s
          =3n"Data Segment"

A Tutorial Introduction to ADB                     PS1:10-13

          <b,-1/8ona

     The request 120$w sets the width of the output  to  120
characters  (normally,  the  width  is  80  characters). ADB
attempts to print addresses as:
          symbol + offset
The request 4095$s increases the maximum permissible  offset
to  the nearest symbolic address from 255 (default) to 4095.
The request = can be used to print  literal  strings.  Thus,
headings  are provided in this dump program with requests of
the form:
          =3n"C Stack Backtrace"
that spaces three lines and prints the literal  string.  The
request $v prints all non-zero ADB variables (see Figure 8).
The request 0$s sets the maximum offset for  symbol  matches
to  zero thus suppressing the printing of symbolic labels in
favor of octal values. Note that this is only done  for  the
printing of the data segment. The request:
          <b,-1/8ona
prints a dump from the base of the data segment to  the  end
of  file with an octal address field and eight octal numbers
per line.

     Figure 11 shows the results of some formatting requests
on the C program of Figure 10.

5.2. Directory Dump

     As another illustration (Figure 12) consider a  set  of
requests  to dump the contents of a directory (which is made
up of an integer inumber followed by a 14 character name):
          adb dir -
          =n8t"Inum"8t"Name"
          0,-1? u8t14cn
In this example, the u prints the  inumber  as  an  unsigned
decimal  integer,  the  8t  means that ADB will space to the
next multiple of 8 on the output line, and  the  14c  prints
the 14 character file name.

5.3. Ilist Dump

     Similarly the contents of the ilist of a  file  system,
(e.g. /dev/src, on UNIX systems distributed by the UNIX Sup-
port Group; see UNIX Programmer's Manual Section V) could be
dumped with the following set of requests:
          adb /dev/src -
          02000>b
          ?m <b
          <b,-1?"flags"8ton"links,uid,gid"8t3bn",size"8tbrdn"addr"8t8un"times"8t2Y2na
In this example the value  of  the  base  for  the  map  was
changed to 02000 (by saying ?m<b) since that is the start of
an ilist within a file system. An artifice (brd  above)  was
used  to print the 24 bit size field as a byte, a space, and
a decimal integer. The last access time and last modify time

PS1:10-14                     A Tutorial Introduction to ADB

are  printed  with the 2Y operator. Figure 12 shows portions
of these requests as applied to a directory and file system.

5.4. Converting values

     ADB may be used to convert values from one  representa-
tion to another. For example:
          072 = odx
will print
          072    58      #3a
which is the octal, decimal and hexadecimal  representations
of 072 (octal). The format is remembered so that typing sub-
sequent numbers will print them in the given formats.  Char-
acter values may be converted similarly, for example:
          'a' = co
prints
          a      0141
It may also be used to evaluate expressions  but  be  warned
that  all binary operators have the same precedence which is
lower than that for unary operators.

6. Patching

     Patching files with ADB is accomplished with the write,
w  or W, request (which is not like the ed editor write com-
mand). This is often used in conjunction with the locate,  l
or L request. In general, the request syntax for l and w are
similar as follows:
          ?l value
The request l is used to match on two bytes, L is  used  for
four  bytes.  The  request  w  is  used  to write two bytes,
whereas W writes four  bytes.  The  value  field  in  either
locate  or  write  requests  is  an  expression.  Therefore,
decimal and octal numbers, or  character  strings  are  sup-
ported.

     In order to modify a file, ADB must be called as:
          adb -w file1 file2
When called with this option, file1 and file2 are created if
necessary and opened for both reading and writing.

     For example, consider the C program shown in Figure 10.
We  can  change  the word "This" to "The " in the executable
file for this program, ex7, by using the following requests:
          adb -w ex7 -
          ?l 'Th'
          ?W 'The '
The request ?l starts at dot and stops at the first match of
"Th"  having  set  dot to the address of the location found.
Note the use of ? to write to the a.out file.  The  form  ?*
would have been used for a 411 file.

     More frequently the request will be typed as:
          ?l 'Th'; ?s

A Tutorial Introduction to ADB                     PS1:10-15

and locates the first  occurrence  of  "Th"  and  print  the
entire string. Execution of this ADB request will set dot to
the address of the "Th" characters.

     As another example  of  the  utility  of  the  patching
facility,  consider  a  C program that has an internal logic
flag. The flag could be set by the user through ADB and  the
program run. For example:
          adb a.out -
          :s arg1 arg2
          flag/w 1
          :c
The :s request is normally used to  single  step  through  a
process or start a process in single step mode. In this case
it starts a.out as a  subprocess  with  arguments  arg1  and
arg2.  If  there  is  a  subprocess running ADB writes to it
rather than to the file so the w request causes flag  to  be
changed in the memory of the subprocess.

7. Anomalies

     Below is a list  of  some  strange  things  that  users
should be aware of.

1.   Function calls and arguments are put on  the  stack  by
     the  C  save  routine. Putting breakpoints at the entry
     point to routines means that the function  appears  not
     to have been called when the breakpoint occurs.

2.   When printing addresses, ADB uses either text  or  data
     symbols  from  the  a.out  file.  This sometimes causes
     unexpected symbol names to be printed with  data  (e.g.
     savr5+022).  This does not happen if ? is used for text
     (instructions) and / for data.

3.   ADB cannot handle C  register  variables  in  the  most
     recently activated function.

8. Acknowledgements

     The authors are grateful for the thoughtful comments on
how  to organize this document from R. B. Brandt, E. N. Pin-
son and B. A. Tague. D. M. Ritchie made the  system  changes
necessary  to accommodate tracing within ADB. He also parti-
cipated in discussions during the writing of ADB.  His  ear-
lier  work with DB and CDB led to many of the features found
in ADB.

9. References

1.   D. M. Ritchie and K. Thompson, ``The UNIX  Time-Sharing
     System,'' CACM, July, 1974.

PS1:10-16                     A Tutorial Introduction to ADB

2.   B. W. Kernighan and D. M. Ritchie,  The  C  Programming
     Language, Prentice-Hall, 1978.

3.   K. Thompson and D. M. Ritchie, UNIX Programmer's Manual
     - 7th Edition, 1978.

4.   B. W. Kernighan and  P.  J.  Plauger,  Software  Tools,
     Addison-Wesley, 1976.

A Tutorial Introduction to ADB                     PS1:10-17

Figure 1:  C program with pointer bug

     struct buf {
          int fildes;
          int nleft;
          char *nextp;
          char buff[512];
          }bb;
     struct buf *obuf;

     char *charp "this is a sentence.";

     main(argc,argv)
     int argc;
     char **argv;
     {
          char cc;

          if(argc < 2) {
               printf("Input file missing\n");
               exit(8);
          }

          if((fcreat(argv[1],obuf)) < 0){
               printf("%s : not found\n", argv[1]);
               exit(8);
          }
          charp = 'T';
     printf("debug 1 %s\n",charp);
          while(cc=  *charp++)
               putc(cc,obuf);
          fflush(obuf);
     }

PS1:10-18                     A Tutorial Introduction to ADB

Figure 2:  ADB output for C program of Figure 1

     adb a.out core
     $c
     ~main(02,0177762)
     $C
     ~main(02,0177762)
          argc:         02
          argv:         0177762
          cc:      02124
     $r
     ps   0170010
     pc   0204 ~main+0152
     sp   0177740
     r5   0177752
     r4   01
     r3   0
     r2   0
     r1   0
     r0   0124
     ~main+0152:    mov  _obuf,(sp)
     $e
     savr5:        0
     _obuf:        0
     _charp:       0124
     _errno:       0
     _fout:        0
     $m
     text map    `ex1'
     b1 = 0              e1   = 02360          f1 = 020
     b2 = 0              e2   = 02360          f2 = 020
     data map    `core1'
     b1 = 0              e1   = 03500          f1 = 02000
     b2 = 0175400        e2   = 0200000        f2 = 05500
     *charp/s
     0124:          TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTLxNh@x&_
     ~
     charp/s
     _charp:        T

     _charp+02:     this is a sentence.

     _charp+026:    Input file missing
     main.argc/d
     0177756:  2
     *main.argv/3o
     0177762:  0177770   0177776   0177777
     0177770/s
     0177770:  a.out
     *main.argv/3o
     0177762:  0177770   0177776   0177777
     *"/s
     0177770:  a.out

A Tutorial Introduction to ADB                     PS1:10-19

      .=o
               0177770
      .-10/d
     0177756:  2
     $q

PS1:10-20                     A Tutorial Introduction to ADB

Figure 3:  Multiple  function  C  program  for  stack  trace
illustration

     int  fcnt,gcnt,hcnt;
     h(x,y)
     {
          int hi; register int hr;
          hi = x+1;
          hr = x-y+1;
          hcnt++ ;
          hj:
          f(hr,hi);
     }

     g(p,q)
     {
          int gi; register int gr;
          gi = q-p;
          gr = q-p+1;
          gcnt++ ;
          gj:
          h(gr,gi);
     }

     f(a,b)
     {
          int fi; register int fr;
          fi = a+2*b;
          fr = a+b;
          fcnt++ ;
          fj:
          g(fr,fi);
     }

     main()
     {
          f(1,1);
     }

A Tutorial Introduction to ADB                     PS1:10-21

Figure 4:  ADB output for C program of Figure 3

     adb
     $c
     ~h(04452,04451)
     ~g(04453,011124)
     ~f(02,04451)
     ~h(04450,04447)
     ~g(04451,011120)
     ~f(02,04447)
     ~h(04446,04445)
     ~g(04447,011114)
     ~f(02,04445)
     ~h(04444,04443)
     HIT DEL KEY
     adb
     ,5$C
     ~h(04452,04451)
          x:       04452
          y:       04451
          hi:      ?
     ~g(04453,011124)
          p:       04453
          q:       011124
          gi:      04451
          gr:      ?
     ~f(02,04451)
          a:       02
          b:       04451
          fi:      011124
          fr:      04453
     ~h(04450,04447)
          x:       04450
          y:       04447
          hi:      04451
          hr:      02
     ~g(04451,011120)
          p:       04451
          q:       011120
          gi:      04447
          gr:      04450
     fcnt/d
     _fcnt:         1173
     gcnt/d
     _gcnt:         1173
     hcnt/d
     _hcnt:         1172
     h.x/d
     022004:        2346
     $q

PS1:10-22                     A Tutorial Introduction to ADB

Figure 5:  C program to decode tabs

     #define MAXLINE     80
     #define YES         1
     #define NO          0
     #define TABSP       8
     char input[] "data";
     char ibuf[518];
     int  tabs[MAXLINE];
     main()
     {
          int col, *ptab;
          char c;
          ptab = tabs;
          settab(ptab);  /*Set initial tab stops */
          col = 1;
          if(fopen(input,ibuf) < 0) {
               printf("%s : not found\n",input);
               exit(8);
          }
          while((c = getc(ibuf)) != -1) {
               switch(c) {
                    case '\t':     /* TAB */
                         while(tabpos(col) != YES) {
                              putchar(' ');  /* put BLANK */
                              col++ ;
                         }
                         break;
                    case '\n':     /*NEWLINE */
                         putchar('\n');
                         col = 1;
                         break;
                    default:
                         putchar(c);
                         col++ ;
               }
          }
     }
     /* Tabpos return YES if col is a tab stop */
     tabpos(col)
     int col;
     {
          if(col > MAXLINE)
               return(YES);
          else
               return(tabs[col]);
     }
     /* Settab - Set initial tab stops */
     settab(tabp)
     int *tabp;
     {
          int i;
          for(i = 0; i<= MAXLINE; i++)

A Tutorial Introduction to ADB                     PS1:10-23

               (i%TABSP) ? (tabs[i] = NO) : (tabs[i] = YES);
     }

PS1:10-24                     A Tutorial Introduction to ADB

Figure 6a:  ADB output for C program of Figure 5

     adb a.out -
     settab+4:b
     fopen+4:b
     getc+4:b
     tabpos+4:b
     $b
     breakpoints
     count     bkpt      command
     1    ~tabpos+04
     1    _getc+04
     1    _fopen+04
     1    ~settab+04
     settab,5?ia
     ~settab:       jsr  r5,csv
     ~settab+04:    tst  -(sp)
     ~settab+06:    clr  0177770(r5)
     ~settab+012:   cmp  $0120,0177770(r5)
     ~settab+020:   blt  ~settab+076
     ~settab+022:
     settab,5?i
     ~settab:       jsr  r5,csv
               tst  -(sp)
               clr  0177770(r5)
               cmp  $0120,0177770(r5)
               blt  ~settab+076
     :r
     a.out: running
     breakpoint     ~settab+04:    tst  -(sp)
     settab+4:d
     :c
     a.out: running
     breakpoint     _fopen+04:     mov  04(r5),nulstr+012
     $C
     _fopen(02302,02472)
     ~main(01,0177770)
          col:     01
          c:       0
          ptab:         03500
     tabs,3/8o
     03500:         01   0    0    0    0    0    0    0
               01   0    0    0    0    0    0    0
               01   0    0    0    0    0    0    0

A Tutorial Introduction to ADB                     PS1:10-25

Figure 6b:  ADB output for C program of Figure 5

     :c
     a.out: running
     breakpoint     _getc+04: mov  04(r5),r1
     ibuf+6/20c
     __cleanu+0202:      This is   a test    of
     :c
     a.out: running
     breakpoint     ~tabpos+04:    cmp  $0120,04(r5)
     tabpos+4:d
     settab+4:b  settab,5?ia
     settab+4:b  settab,5?ia;  0
     getc+4,3:b  main.c?C;  0
     settab+4:b  settab,5?ia;  ptab/o;  0
     $b
     breakpoints
     count     bkpt      command
     1    ~tabpos+04
     3    _getc+04  main.c?C;0
     1    _fopen+04
     1    ~settab+04     settab,5?ia;ptab?o;0
     ~settab:       jsr  r5,csv
     ~settab+04:    bpt
     ~settab+06:    clr  0177770(r5)
     ~settab+012:   cmp  $0120,0177770(r5)
     ~settab+020:   blt  ~settab+076
     ~settab+022:
     0177766:  0177770
     0177744:  @`
     T0177744: T
     h0177744: h
     i0177744: i
     s0177744: s

PS1:10-26                     A Tutorial Introduction to ADB

Figure 7:  ADB output for C program with breakpoints

     adb ex3 -
     h+4:b hcnt/d; h.hi/; h.hr/
     g+4:b gcnt/d; g.gi/; g.gr/
     f+4:b fcnt/d; f.fi/; f.fr/
     :r
     ex3: running
     _fcnt:          0
     0177732:        214
     symbol not found
     f+4:b fcnt/d; f.a/; f.b/; f.fi/
     g+4:b gcnt/d; g.p/; g.q/; g.gi/
     h+4:b hcnt/d; h.x/; h.y/; h.hi/
     :c
     ex3: running
     _fcnt:          0
     0177746:        1
     0177750:        1
     0177732:        214
     _gcnt:          0
     0177726:        2
     0177730:        3
     0177712:        214
     _hcnt:          0
     0177706:        2
     0177710:        1
     0177672:        214
     _fcnt:          1
     0177666:        2
     0177670:        3
     0177652:        214
     _gcnt:          1
     0177646:        5
     0177650:        8
     0177632:        214
     HIT DEL
     f+4:b fcnt/d; f.a/"a = "d; f.b/"b = "d; f.fi/"fi = "d
     g+4:b gcnt/d; g.p/"p = "d; g.q/"q = "d; g.gi/"gi = "d
     h+4:b hcnt/d; h.x/"x = "d; h.y/"h = "d; h.hi/"hi = "d
     :r
     ex3: running
     _fcnt:          0
     0177746:        a = 1
     0177750:        b = 1
     0177732:        fi = 214
     _gcnt:          0
     0177726:        p = 2
     0177730:        q = 3
     0177712:        gi = 214
     _hcnt:          0
     0177706:        x = 2
     0177710:        y = 1
     0177672:        hi = 214

A Tutorial Introduction to ADB                     PS1:10-27

     _fcnt:          1
     0177666:        a = 2
     0177670:        b = 3
     0177652:        fi = 214
     HIT DEL
     $q

PS1:10-28                     A Tutorial Introduction to ADB

Figure 8:  ADB address maps

407 files

a.out       hdr             text+data
          |____|_____________________________|
                0                           D

core        hdr             text+data                stack
          |______|_____________________________......|________|
                  0                           D   S          E

410 files (shared text)

a.out       hdr              text                    data
          |____|_____________________________|________________|
                0                           T B              D

core        hdr         data             stack
          |______|________________......|________|
                  B               D  S          E

411 files (separated I and D space)

a.out       hdr             text                     data
          |____|_____________________________|________________|
                0                           T 0              D

core        hdr         data             stack
          |______|________________......|________|
                  0               D  S          E

The following adb variables are set.

                                   407       410       411

       b       base of data        0         B         0
       d       length of data      D         D-B       D
       s       length of stack     S         S         S
       t       length of text      0         T         T

A Tutorial Introduction to ADB                     PS1:10-29

Figure 9:  ADB output for maps

     adb map407 core407
     $m
     text map    `map407'
     b1 = 0               e1 = 0256            f1 = 020
     b2 = 0               e2 = 0256            f2 = 020
     data map    `core407'
     b1 = 0               e1 = 0300            f1 = 02000
     b2 = 0175400         e2 = 0200000         f2 = 02300
     $v
     variables
     d = 0300
     m = 0407
     s = 02400
     $q

     adb map410 core410
     $m
     text map    `map410'
     b1 = 0               e1 = 0200            f1 = 020
     b2 = 020000          e2 = 020116          f2 = 0220
     data map    `core410'
     b1 = 020000          e1 = 020200          f1 = 02000
     b2 = 0175400         e2 = 0200000         f2 = 02200
     $v
     variables
     b = 020000
     d = 0200
     m = 0410
     s = 02400
     t = 0200
     $q

     adb map411 core411
     $m
     text map    `map411'
     b1 = 0               e1 = 0200            f1 = 020
     b2 = 0               e2 = 0116            f2 = 0220
     data map    `core411'
     b1 = 0               e1 = 0200            f1 = 02000
     b2 = 0175400         e2 = 0200000         f2 = 02200
     $v
     variables
     d = 0200
     m = 0411
     s = 02400
     t = 0200
     $q

PS1:10-30                     A Tutorial Introduction to ADB

Figure 10:  Simple C program for illustrating formatting and
patching

     char str1[]    "This is a character string";
     int  one  1;
     int  number    456;
     long lnum 1234;
     float     fpt  1.25;
     char str2[]    "This is the second character string";
     main()
     {
          one = 2;
     }

A Tutorial Introduction to ADB                     PS1:10-31

Figure 11:  ADB output illustrating fancy formats

adb map410 core410
<b,-1/8ona
020000:         0       064124  071551  064440  020163  020141  064143  071141
_str1+016:      061541  062564  020162  072163  064562  063556  0       02
_number:
_number:        0710    0       02322   040240  0       064124  071551  064440
_str2+06:       020163  064164  020145  062563  067543  062156  061440  060550
_str2+026:      060562  072143  071145  071440  071164  067151  0147    0
savr5+02:       0       0       0       0       0       0       0       0
<b,20/4o4^8Cn
020000:         0       064124  071551  064440  @`@`This i
                020163  020141  064143  071141  s a char
                061541  062564  020162  072163  acter st
                064562  063556  0       02      ring@`@`@b@`
_number:        0710    0       02322   040240  H@a@`@`R@d @@
                0       064124  071551  064440  @`@`This i
                020163  064164  020145  062563  s the se
                067543  062156  061440  060550  cond cha
                060562  072143  071145  071440  racter s
                071164  067151  0147    0       tring@`@`@`
                0       0       0       0       @`@`@`@`@`@`@`@`
                0       0       0       0       @`@`@`@`@`@`@`@`
data address not found
<b,20/4o4^8t8cna
020000:         0       064124  071551  064440          This i
_str1+06:       020163  020141  064143  071141          s a char
_str1+016:      061541  062564  020162  072163          acter st
_str1+026:      064562  063556  0       02              ring
_number:
_number:        0710    0       02322   040240          HR
_fpt+02:        0       064124  071551  064440          This i
_str2+06:       020163  064164  020145  062563          s the se
_str2+016:      067543  062156  061440  060550          cond cha
_str2+026:      060562  072143  071145  071440          racter  s
_str2+036:      071164  067151  0147    0               tring
savr5+02:       0       0       0       0
savr5+012:      0       0       0       0
data address not found
<b,10/2b8t^2cn
020000:         0       0
_str1:          0124    0150            Th
                0151    0163            is
                040     0151             i
                0163    040             s
                0141    040             a
                0143    0150            ch
                0141    0162            ar
                0141    0143            ac
                0164    0145            te
$Q

PS1:10-32                     A Tutorial Introduction to ADB

Figure 12:  Directory and inode dumps

adb dir -
=nt"Inode"t"Name"
0,-1?ut14cn

                Inode   Name
0:              652     .
                82      ..
                5971    cap.c
                5323    cap
                0       pp

adb /dev/src -
02000>b
?m<b
new map     `/dev/src'
b1 = 02000           e1 = 0100000000      f1 = 0
b2 = 0               e2 = 0               f2 = 0
$v
variables
b = 02000
<b,-1?"flags"8ton"links,uid,gid"8t3bn"size"8tbrdn"addr"8t8un"times"8t2Y2na
02000:          flags   073145
                links,uid,gid   0163    0164    0141
                size    0162    10356
                addr    28770   8236    25956   27766   25455   8236    25956   25206
                times   1976 Feb 5 08:34:56     1975 Dec 28 10:55:15

02040:          flags   024555
                links,uid,gid   012     0163    0164
                size    0162    25461
                addr    8308    30050   8294    25130   15216   26890   29806   10784
                times   1976 Aug 17 12:16:51    1976 Aug 17 12:16:51

02100:          flags   05173
                links,uid,gid   011     0162    0145
                size    0147    29545
                addr    25972   8306    28265   8308    25642   15216   2314    25970
                times   1977 Apr 2 08:58:01     1977 Feb 5 10:21:44

A Tutorial Introduction to ADB                     PS1:10-33

                        ADB Summary

Command Summary

a)   formatted printing

? formatprint from a.out file according to format

/ formatprint from core file according to format

= formatprint the value of dot

?w exprwrite expression into a.out file

/w exprwrite expression into core file

?l exprlocate expression in a.out file

b)   breakpoint and program control

:b     set breakpoint at dot
:c     continue running program
:d     delete breakpoint
:k     kill the program being debugged
:r     run a.out file under ADB control
:s     single step

c)   miscellaneous printing

$b     print current breakpoints
$c     C stack trace
$e     external variables
$f     floating registers
$m     print ADB segment maps
$q     exit from ADB
$r     general registers
$s     set offset for symbol match
$v     print ADB variables
$w     set output line width

d)   calling the shell

!      call shell to read rest of line

e)   assignment to variables

>name  assign dot to variable or register name

PS1:10-34                     A Tutorial Introduction to ADB

Format Summary

a      the value of dot
b      one byte in octal
c      one byte as a character
d      one word in decimal
f      two words in floating point
i      PDP 11 instruction
o      one word in octal
n      print a newline
r      print a blank space
s      a null terminated character string
nt     move to next n space tab
u      one word as unsigned integer
x      hexadecimal
Y      date
^      backup dot
"..."  print string

Expression Summary

a) expression components

decimal integere.g. 256
octal integere.g. 0277
hexadecimale.g. #ff
symbols    e.g. flag  _main  main.argc
variables  e.g. <b
registers  e.g. <pc <r0
(expression)expression grouping

b) dyadic operators

+      add
-      subtract
*      multiply
%      integer division
&      bitwise and
|      bitwise or
#      round up to the next multiple

c) monadic operators

~      not
*      contents of location
-      integer negate

Generated on 2014-07-04 21:17:45 by $MirOS: src/scripts/roff2htm,v 1.79 2014/02/10 00:36:11 tg Exp $

These manual pages and other documentation are copyrighted by their respective writers; their source is available at our CVSweb, AnonCVS, and other mirrors. The rest is Copyright © 2002‒2014 The MirOS Project, Germany.
This product includes material provided by Thorsten Glaser.

This manual page’s HTML representation is supposed to be valid XHTML/1.1; if not, please send a bug report – diffs preferred.