COHERENT manpages

This page displays the COHERENT manpage for db [Assembler-level symbolic debugger].

List of available manpages
Index


db -- Command

Assembler-level symbolic debugger
db [-a symfile] [-cdefort] [[mapfile] program]

db is an interactive, symbolic debugger.  It allows you to run object files
and  executable programs  under trace  control (see  the Lexicon  entry for
ptrace), run  programs with embedded breakpoints, and  dump and patch files
in a variety of forms.  You  can use it to debug assembly-language programs
that have  been assembled by as, the Mark  Williams assembler, and programs
that have been compiled with the Mark Williams C compiler cc.

What is db?

db is a symbolic debugger, which means that it works with the symbol tables
that the  compiler builds into  the object files it  generates.  Because db
works on  the level of assembly  language, you need a  working knowledge of
i80386 assembly language and microprocessor architecture.

Invoking db

To invoke  db, type its  name, plus the  options you want (if  any) and the
name of  the files with  which you will  be working.  mapfile  is an object
file that supplies a symbol table.  program is the executable program to be
debugged.  If both names are given,  the options default to -c. If only one
name is given,  it is the program; in this  case the options default to -o.
If both names are omitted, mapfile  defaults to l.out or a.out, and program
defaults to core. If possible, db accesses program with write permission.

db recognizes the following command-line options:

-a symfile
   Read symfile  for the list of symbols within  the executable, instead of
   the  executable's symbol  table.   This lets  you  copy an  executable's
   symbol table in symfile, then strip that executable.

-c program is a core file produced by a user core dump.  db checks the name
   of the command that invoked  the process that produced the core, against
   the name  of the  mapfile, if  given.  Pure segments  are read  from the
   mapfile.

-d program is a  system dump.  If the command line  names no files, mapfile
   defaults to /COHERENT and program defaults to /dev/dump.

-e The next argument  is an object file; db executes  it as a child process
   and passes it  the rest of the command line.   This permits the shell to
   expand  wildcard  characters that  you  place in  the  db command  line,
   without spoiling the syntax of the db command.

-f Map program as a straight array of bytes (file).

-k Map  program as  a kernel  process; mapfile  defaults to  /coherent, and
   program defaults to /dev/kmem.

-o program is  an object file.  If  mapfile is given, it  is another object
   file that provides the symbol table.

-p prompt
   Change the command prompt from db: to prompt.

-r Only read the file, even if  you have write permission for it.  Use this
   to give a file additional protection.

-s Do not load symbol table.

-t Perform input and output for db  via /dev/tty. This permits you to debug
   a process whose standard input or output has been redirected.

Commands and Addresses

db executes commands that you give it from the standard input.  db displays
the prompt

    db:

when it  is ready to receive  a command.  To change its  prompt, use the -p
option, described  above.  A command usually consists  of an address, which
tells db where in the program  to execute the command; and then the command
name and its options, if any.

An address is  represented by an expression, which can  be built out of one
or more of the following elements:

-> The  `.',  which represents  the  current address.   When  you enter  an
   address, db  sets the current address to that  location.  To advance the
   current address, type the <Enter> key.

-> The name of a register.  db recognizes the names of all registers on the
   80386  microprocessor  and  the  80387  numeric co-processor.   You  can
   preceed a register  name with a `%', but this  is not required.  If your
   program  contains  function eax(),  the  identifier  eax identifies  the
   function and  %eax the register.   If your program does  not define eax,
   then either eax or %eax means the register.  For example, the commands

       sin:b
       :e
       :s
       %st0?N

   sets a  breakpoint at routine  sin(), executes to it,  single steps into
   it, and  then prints the  contents of the  NDP stacktop %st0,  which one
   step into sin() contains the argument.

   Typing  the  name of  a  register displays  its  contents.  db  displays
   register contents and  stack traceback in hexadecimal values, regardless
   of the current default radix.

-> The symbols  d, i, and  u, which represent location  0 in, respectively,
   the data space, the instruction space, and the u-area.

-> The names of global symbols and  symbolic addresses can be used in place
   of  the addresses  where  they occur.   This  is useful  when setting  a
   breakpoint at the beginning of a subroutine.

-> An integer  constant, which can be  used in the same  manner as a global
   symbol.  The default is hexadecimal;  a leading 0 indicates octal and 0x
   indicates hexadecimal.

-> You can use the following binary operators:

       +   Addition
       -   Subtraction
       *   Multiplication
       /   Integer division

   All arithmetic is done in longs.

-> You can use the following unary operators:

       ~   Complementation
       -   Negation
       *   Indirection

   All operators are supported  with their normal level of precedence.  You
   can use parentheses `()' for binding.

Every  symbol  refers  to a  segment:  the  data  segment, the  instruction
segment,  or the  u-area.  This  segment, in turn,  dictates the  format in
which db  displays by default  what it finds  at that address.   The format
used by an  expression is that of its leftmost  operand.  The symbols d, i,
and u name specific segments in the absence of other symbols.

Displaying Information

To display information about program, use an expression of the form

    [address][,count]?[format]

This displays format for  count iterations, starting at address. The symbol
`.' represents  the address, which defaults to  the current display address
if omitted.  count  defaults to one.  The format string  consists of one or
more of the following characters:

    ^   Reset display address to `.'
    +   Increment display address
    -   Decrement display address
    b   Byte
    c   char; control and non-chars escaped
    C   Like `c' except `\0' not displayed
    d   Decimal
    f   float
    F   double
    i   Machine instruction, disassembled
    l   long
    n   Output `\n'
    N   NDP (80387) register
    O   octal
    p   Symbolic address
    s   String terminated by `\0', with escapes
    S   String terminated by `\0', no escapes
    u   unsigned
    w   word
    x   Hexadecimal
    Y   time (as in i-node, etc.)

The format  characters d,  o, u,  and x, specify  a numeric base.   Each of
these  can be  followed by  b,  l, or  w, which  specify a  datum  size, to
describe a single datum for display.  A format item may also be preceded by
a count  that specifies how many  times the item is  to be applied.  format
defaults to the previously set format for the segment (initially o for data
and  u-area, and  i for  instructions).  Except  where otherwise  noted, db
increments the  display address  by the size  of the datum  displayed after
each format item.

Execution Commands

In the following commands,  address defaults to the address where execution
stopped,  unless  otherwise  specified;  count  and  expr default  to  one.
commands is an arbitrary string of db commands, terminated by a newline.  A
newline may be included by preceding it with a backslash `\'.

[address]=
     Print address (offset) in hexadecimal.  address defaults to `.'.

[address]=value[,value[,value]...]
     Patch value into the  program, beginning at point address. The address
     defaults to `.'.  You can list up to ten values. The command = assigns
     values to  sequential locations in the  traced process.  db determines
     the size of the assigned value from the last display format used.  You
     can set and display the registers of the traced process, just like any
     other address in the traced process.

?    Print the last error message.

[address][,n]?[ft]
     Display formatted information.  ft indicates the format, which must be
     one of bcCdfFilnNopsSuvwxY. For details, see the command :hf, below

address?
     Print address.

!command
     Pass command to a shell for execution.

[address] :a
     Print address symbolically.  address defaults to `.'.

[address]:b[commands]
     Set a  breakpoint at address. Execute commands  when the breakpoint is
     encountered.   commands  defaults to  i+.:a\ni+.?i\n:x\n  -- that  is,
     print  the  breakpoint address,  disassemble  the  instruction at  the
     breakpoint address, and read more commands from the console.

:br [commands]
     Set breakpoint  at return from current  routine, and execute commands.
     The default commands are the same as for :b, above.

[address] :c
     Continue execution from address.

[address] :d[r][s]
     Delete the breakpoint previously set  at address. If the optional r or
     s  is specified,  delete  return or  single-step breakpoint.   address
     defaults to `.'.

[address]:e[commandline]
     Begin traced  execution of the object file  at address (default, entry
     point).  db  parses commandline and  passes it to  the traced process.
     argv[0] must be typed directly after :e if supplied.  For example,

         :eprogname foo bar baz

     sets argv[0] to progname, argv[1]  to foo, argv[2] to bar, and argv[3]
     to baz. Quotation marks, apostrophes, and redirection are parsed as by
     the  shell,  but  special  characters  `?*[]'  and  shell  punctuation
     `(){}|;' are not.  For complete  shell command line parsing use the -e
     option, above.

     Note that you  must use the :e command to  start the program execution
     prior  to  using  the  single-step,  trace-back,  or  display-register
     commands.  For example, the following COHERENT command sequence sets a
     breakpoint  at main(),  begins execution,  and single-steps  ten times
     through the program after having reached the breakpoint:

         main:b
         :e
         ,10:s

:f   Print type  of fault  that caused  a core dump  or stopped  the traced
     process.

:h   Print help information.

:hf  Print  help  information about  display  formats.   db recognizes  the
     following display formats:

     b    Byte.
     c    char; control, and non-chars printed as escape sequences.
     C    char; control and non-chars print as `.'.
     d    Decimal.
     f    float.
     F    double.
     i    Disassembled machine instruction.
     l    long.
     n    Output `\n'.
     N    NDP (80387) floating-point register (ten bytes).
     o    Octal.
     p    Symbolic address.
     s    String (NUL-terminated) with escape sequences.
     S    String (NUL-terminated).
     u    unsigned.
     v    File system l3-block address (three bytes).
     w    Word.
     x    Hexadecimal.
     Y    Time.

     Options d, o, u, and x specify numeric bases (decimal, octal, unsigned
     decimal, hexadecimal).  Each may be followed by b, w, or l to indicate
     a datum size (respectively, byte, word, or long).

:m   Display segmentation map.

:p   Display all breakpoints.

[expr] :q
     If expr is nonzero, quit the  current level of command input (see :x).
     expr defaults to one.  End-of-file is equivalent to :q.

:r   Display the contents of all registers on the microprocessor.

:rN  Display the contents of all registers on the microprocessor and on the
     numeric co-processor.   If your system does not  possess a numeric co-
     processor, it  displays the contents  of the pseudo-registers  used by
     COHERENT's emulator.

[address][,count]:s[c][commands]
     Single-step execution starting  at address, for count steps, executing
     commands at each step.  commands defaults to i+.?i.

     After a single-step  command, <Enter> is equivalent to .,1:s[c].
     The option c tells db to turn off single-stepping at a subroutine call
     and turn it on again upon return.

[depth] :t
     Print a  call traceback to depth levels.  If  depth is zero (default),
     unwind the whole stack.

[expr] :x
     If expr is nonzero, read  and execute commands from the standard input
     up to  end of file  or to receiving  the command :q.  expr defaults to
     one.

Note  that the  :c, :s,  :t, and  :r commands cannot  be executed  before a
program  is  started.  If  you  are  debugging the  program  hello, do  the
following first:

    db hello
    main:b
    :e

This invokes  the debugger for hello  and advances it to  main. Now you can
use the full set of commands.

Examples

The first  example uses  db to  examine a program  named myprog,  which has
core-dumped.  To debug it, use the command

    db myprog core

You could then issue the following commands to see where the problem lay:

:f This command displays the fault that caused the core dump.

:r This displays  the contents of registers at the  point where the program
   core dumped.

:t This command traces back the stack.   With this command, you can see how
   your program  arrived at the  point where it  core dumped.  You  can use
   this  to find  the point  in  your code  where the  program ``jumps  the
   rails''; often, this is all the information you need to fix the fault.

i1?
   This prints the value of global  variable i1 in your program at the time
   of the core dump.

:q Quit db. At  this point, you should have a  good idea of what went wrong
   with your program.

For another example, consider the following program, named segv.c:

    main()
    {
        register char *cp;

        cp = &main;
        *cp = 1000;
    }

Compile this program  with the command cc segv.c. To  run it, type segv; as
you can  see, it crashes  with a segmentation violation,  producing a core-
dump file named core. Now, you  can use db to find out why the program core
dumped.

To invoke the debugger, type:

    db segv core

Now, type the db command:

    :f

This tells  db to print the  type of fault that caused  the program to dump
core.  db replies:

    segmentation violation

Now, type:

    *%eip?

db replies:

    000000E9     movb   (%ebx), $0xE8

Here, db gives you the value  of the instruction pointer register %eip when
the  segmentation violation  occurred and  disassembles the  instruction at
that  location.  The  offending instruction is  trying to  store indirectly
through register %ebx. Type:

    :t

db prints a traceback of the call stack:

    7FFFFD24  000000E9  main(1, 0x7FFFFD38, 0x7FFFFD40)

This shows the program was in main() and not in any other function.  Type:

    :r

db prints contents of the machine registers:

    %cs =000B       %eip=000000E9   %ss =0013       %fw =00011246
    %ds =0013       %es =0013       %fs =0000       %gs =0000
    %eax=00000001   %ebx=000000D4   %ecx=00000013   %edx=7FFFFD40
    %esp=7FFFFD1C   %ebp=7FFFFD24   %edi=004090F4   %esi=00400D24

This shows  that register %ebx has  the value 0xD4 at the  time of the core
dump.  Print the contents of %ebx symbolically:

    %ebx?p

db replies:

    00000020     main

The program  is trying  to store  into the address  of main. This  causes a
segmentation violation because COHERENT does not allow programs to write on
code.  Finally, type

    :q

to exit from db.

In the  last example, suppose  you want to  print the current  address, the
instruction at  the current address, and the contents  of global variable j
when you hit function fn while running db. Type:

    db cmd
    main:b
    :e
    fn:b.:a\
    .?i\
    j?\
    :x

The backslash `\' at the end of a line ``escapes'' a newline -- that is, it
tells db  to ignore the newline,  and concatenate the contents  of the next
line  onto those  of the  present line.   Thus, the  fn command  line (four
physical lines  with escaped newlines) forms a single  db command that says
the following:

.:a
   Print the current position as an address.
.?i
   Print the contents of the current position as an instruction.
j? print the contents of j.
:x Read more db input from the console.

The :x  is necessary if you  want to keep debugging  interactively after db
executes the breakpoint command list!

See Also

commands,
coff.h,
core,
l.out.h,
od,
ptrace()