Debugger

You can now conditionally compile in a GDB like command line debugger, that allows you to set breakpoints, step through instructions, and other useful functions. If there isn't a command for something you believe is generally useful for the debugger, let me know and I'll implement it if possible.

To use the debugger, you must configure bochs with the '--enable-debugger' and '--enable-disasm' flags. For example:

  ./configure --enable-debugger --enable-disasm
NOTE: You must use flex version 2.5.4 or greater. I have heard that version 2.5.2 will not work.

When you first start up bochs, you will see the command line prompt

  bochs:1>
From here, you may use the following commands:

Execution Control

  c                           Continue executing
  stepi [count]               execute count instructions, default is 1
  si    [count]               execute count instructions, default is 1
  step  [count]               execute count instructions, default is 1
  s     [count]               execute count instructions, default is 1
  Ctrl-C                      stop execution, and return to command line prompt
  Ctrl-D                      if at empty line on command line, exit
  quit                        quit debugger and execution
  q                           quit debugger and execution

BreakPoints

  NOTE: The format of 'seg', 'off', and 'addr' in these descriptions,
        are as follows.  I don't have any way to set the current radix.

        hexidecimal:    0xcdef0123
        decimal:        123456789
        octal:          01234567

  vbreak seg:off              Set a virtual address instruction breakpoint
  vb     seg:off

  lbreak addr                 Set a linear address instruction breakpoint
  lb     addr

  pbreak [*] addr             Set a physical address instruction breakpoint
  pb     [*] addr             (the '*' is optional for GDB compatibility)
  break  [*] addr
  b      [*] addr

  info break                  Display state of all current breakpoints
  delete n                    Delete a breakpoint
  del    n
  d      n

Manipulating Memory

  x  /nuf addr      Examine memory at linear address addr
  xp /nuf addr      Examine memory at physical address addr
     n              Count of how many units to display
     u              Unit size; one of
                      b Individual bytes
                      h Halfwords (2 bytes)
                      w Words (4 bytes)
                      g Giant words (8 bytes)
                      NOTE: these are *not* typical Intel nomenclature sizes,
                            but they are consistent with GDB convention.
     f              Printing format.  one of
                      x Print in hexadecimal
                      d Print in decimal
                      u Print in unsigned decimal
                      o Print in octal
                      t Print in binary

    n, f, and u are optional parameters.  u and f default to the last values
    you used, or to w(words) and x(hex) if none have been supplied.
    n currently defaults to 1.  If none of these optional parameters are
    used, no slash should be typed.  addr is also optional.  If you don't
    specify it, it will be the value the next address (as if you had
    specified n+1 in the last x command).

  setpmem addr datasize val    Set physical memory location of size
                               datasize to value val.

  crc  addr1  addr2            Show CRC for physical memory range addr1..addr2
  info dirty                   Show physical pages dirtied (written to) since last display
                               Values displayed are the top 20 bits only (page addresses)

Info

  info program      Execution status of the program
  info registers    List of CPU integer registers and their contents
  info break        Information about current breakpoint status

Manipulating CPU Registers

  set $reg = val    Change a CPU register to value val.  Registers may be one of:
                      eax, ecx, edx, ebx, esp, ebp, esi, edi.
                    Currently, you may not change:
                      eflags, cs, ss, ds, es, fs, gs.

    Examples: set $eax = 0x01234567
              set $edx = 25

  info registers    See Info section
  dump_cpu          Dump complete CPU state
  set_cpu           Set  complete CPU state

    Format of "dump_cpu" and "set_cpu":
    "eax:0x%x\n"
    "ebx:0x%x\n"
    "ecx:0x%x\n"
    "edx:0x%x\n"
    "ebp:0x%x\n"
    "esi:0x%x\n"
    "edi:0x%x\n"
    "esp:0x%x\n"
    "eflags:0x%x\n"
    "eip:0x%x\n"
    "cs:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
    "ss:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
    "ds:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
    "es:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
    "fs:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
    "gs:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
    "ldtr:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
    "tr:s=0x%x, dl=0x%x, dh=0x%x, valid=%u\n"
    "gdtr:base=0x%x, limit=0x%x\n"
    "idtr:base=0x%x, limit=0x%x\n"
    "dr0:0x%x\n"
    "dr1:0x%x\n"
    "dr2:0x%x\n"
    "dr3:0x%x\n"
    "dr4:0x%x\n"
    "dr5:0x%x\n"
    "dr6:0x%x\n"
    "dr7:0x%x\n"
    "tr3:0x%x\n"
    "tr4:0x%x\n"
    "tr5:0x%x\n"
    "tr6:0x%x\n"
    "tr7:0x%x\n"
    "cr0:0x%x\n"
    "cr1:0x%x\n"
    "cr2:0x%x\n"
    "cr3:0x%x\n"
    "cr4:0x%x\n"
    "inhibit_int:%u\n"
    "done\n"

    Notes:
      - s is the selector
      - dl is the shadow descriptor low  dword (4 byte quantitiy)
      - dh is the shadow descriptor high dword (4 byte quantitiy)
      - valid denotes if the segment register holds a validated shadow descriptor
      - inhibit_int is set if the previous instruction was one which delays the
          acceptance of interrupts by one instruction (STI, MOV SS)
      - any errors encountered by the set_cpu command, are reported by
        "Error: ...".  They may be reported after any of the input lines,
        or after the "done" line, during limit checks.
      - A successful set_cpu command ends with the separate line:
        "OK".

Disassembly commands

  disassemble start end       Disassemble instructions in given linear address
                              range, inclusive of start, exclusive of end.
                              Use "set $disassemble_size =" to tell
                              debugger desired segment size.  Use a value for
                              end of less than start (or zero) if you only
                              want the first instruction disassembled.
  set $disassemble_size = n   Tell debugger what segment size to use when
                              the "disassemble" command is used.  Use values
                              of 16 or 32 for n.  Default is 32.

  set $auto_disassemble = n   Cause debugger to disassemble current instruction
                              every time execution stops if n=1.  Default is 0.
                              Segment size of current CPU context is used for
                              disassembly, so variable "$disassemble_size" is
                              ignored.

Co-emulation commands

  query pending     Query CPU for pending external events.  Response will be
                    one or more of the following:
                      "pending DMA\n"
                      "pending IRQ\n"
                      "pending none\n"

                    followed by:
                      "done\n"

  take  dma [n]     Force CPU to take current DMA event, if any, default is 1 operation
  take  irq         Force CPU to handle current IRQ event, if any

  Note: These commands are for co-emulating another CPU model against
    the bochs CPU model, and are not normally needed.

  set $synchronous_dma = n  In synchronous DMA mode, the CPU will only respond
                            to DMA requests when told to (see "take dma" command).
                            The parameter 'n' may be 0 or 1.  Default is 0, which
                            is the normal asynchronous behaviour.

  set $synchronous_irq = n  In synchronous IRQ mode, the CPU will only respond
                            to IRQ requests when told to (see "take irq" command).
                            The parameter 'n' may be 0 or 1.  Default is 0, which
                            is the normal asynchronous behaviour.

  set $event_reports = n    Set this variable to 1, to turn on reporting of events
                            necessary for co-emulation (DMA, IRQ, uncacheable
                            memory access, IO, and A20 line control operations).
                            Default is 0, events are not normally printed.

  Possible events reported (set $event_reports = 1) in response
  to various debugger commands:

  take dma [n]
    event icount=0 DMA addr=0xe240b size=1 op=read val=0xff
       -or-
    event icount=0 DMA addr=0xe240b size=1 op=read val=0xf0 0xf1 0xf2 ..
    done
 
    | Notes:
    |   The "op=" will display "read" or "write"
    |   DMA read  = from memory to IO
    |   DMA write = from IO to memory
    |   If you request more than one, up to that many operations will be
    |     processed and reported on the same line.  Operations have to be
    |     of the same time read/write, of the same size, and contiguous
    |     based on size, or separate events will be reported.
 
  take irq
    event icount=0 IRQ irq=7
    done
 
  stepi 1000 (normal execution, no UCmem or IO access)
    done
 
  stepi 1 (next instruction is known to access UCmem, possible multiple accesses {R-M-W})
    event icount=1 UCmem addr=0xa0000 size=1 op=read  val=0xaa
    event icount=1 UCmem addr=0xa0000 size=1 op=write val=0xbb
    done
 
    | Notes:
    | - UCmem is currently 0xA0000 .. 0xBFFFF
 
  stepi 1
    (next instruction is known to access IO, possible A20 action)
    event icount=1 IO  addr=0x1234 size=2 op=read val=0xffff
    event icount=1 A20 val=0
    done

Instrumentation


To use instrumentation features in bochs, you must compile in support for it.
You should build a custom instrumentation library in a separate directory in
the "instrument/" directory.  To tell configure which instrumentation library
you want to use, use the "--enable-instrumentation" option.

The default library consists of a set of stubs, and the following are
equivalent:

  ./configure [...] --enable-instrumentation
  ./configure [...] --enable-instrumentation="instrument/stubs"

You could make a separate directory with your custom library,
for example "instrument/myinstrument", copy the contents of
the "instrument/stubs" directory to it, then customize it.  Use:

  ./configure [...] --enable-instrumentation="instrument/myinstrument"

Instrumentation commands

  instrument start            calls bx_instr_start()
  instrument stop             calls bx_instr_stop()
  instrument reset            calls bx_instr_reset()
  instrument print            calls bx_instr_print()