CSE 591: Tools

Familiarity with your environment is crucial for productive development and debugging. This page gives a brief overview of the JOS environment and useful GDB and Bochs commands. Don't take our word for it, though. Read the GDB and Bochs manuals. These are powerful tools that are worth knowing how to use.

Debugging tips: Kernel User environments
Reference: JOS makefile JOS obj/ GDB Bochs

All of the tools that you need to execute and complete the labs are installed in your course virtual machine. Details TBA.

If you wish to compile and run the tools on your own machine, the information that you need is as follows. Note that we cannot guarantee that these tools will run on your computer, and we cannot support these tools on your own computer. However, the tools should run on recent versions of Linux. The tools should also run under Windows with the help of Cygwin. Install cygwin, and be sure to install the flex and bison packages (they are under the development header).

Compiler Toolchain

Most modern Linux distributions and BSDs have an ELF toolchain compatible with the JOS labs. That is, the system-standard gcc, as, ld and objdump should just work. The lab Makefile should automatically detect this. If the makefile fails to detect your build tools, you can specify their location by adding the following line to conf/env.mk:

GCCPREFIX=

If you are using something other than standard x86 linux or BSD, you will need the GNU C compiler toolchain, configured and built as a cross-compiler for the target 'i386-jos-elf', as well as the GNU debugger, configured for the i386-jos-elf toolchain. You can download versions that are known to work with JOS via the following links, although more recent versions of gcc and binutils, and GDB should work too:

Once you've unpacked these archives, run the following commands as root:

# cd binutils-2.19
# ./configure --target=i386-jos-elf --disable-nls
# make
# make install
# cd ../gcc-4.1.2
# ./configure --target=i386-jos-elf --disable-nls --without-headers \
              --with-newlib --disable-threads --disable-shared \
              --disable-libmudflap --disable-libssp
# make
# make install
# cd ../gdb-7.2a
# ./configure --target=i386-jos-elf --program-prefix=i386-jos-elf- \
              --disable-werror
# make
# make install

Then you'll have in /usr/local/bin a bunch of binaries with names like i386-jos-elf-gcc. The lab makefile should detect this toolchain and use it in preference to your machine's default toolchain. If this doesn't work, there are instructions on how to override the toolchain inside the GNUmakefile in the labs.

Patched GDB

The standard version of gdb does not correctly handle the transition to long mode during JOS boot, yielding a "Packet too long" error. The patch below will fix this:

For the VM environment, we have pre-patched gdb packages you should install. For debugging 64-bit code on a 32-bit platform, you need both gdb and gdb-multiarch. Below we post patched Ubuntu 10.04 packages.

Download and install these packages on your course VM with the following commands

# wget http://www.cs.stonybrook.edu/~porter/courses/cse506/f12/gdb_7.2-1ubuntu11jos_i386.deb 
# wget http://www.cs.stonybrook.edu/~porter/courses/cse506/f12/gdb-multiarch_7.2-1ubuntu11jos_i386.deb
# sudo dpkg -i gdb_7.2-1ubuntu11jos_i386.deb gdb-multiarch_7.2-1ubuntu11jos_i386.deb

To build gdb against another version on Ubuntu or Debian, e.g., for home use, follow these steps:

    dpkg-source -x gdb-xxxxx.dsc   (the .dsc you installed)
    cd gdb-xxx  (a newly created directory)
    sudo apt-get build-dep gdb
    download gdb-7.2-arch-remote-change.patch
    patch -p1 < gdb-7.2-arch-remote-change.patch
    sudo debian/rules binary

Bochs Emulator

Bochs is a modern and fast PC emulator. Bochs is also the first emulator to support emulation of vmx and extended page tables.

We recommend using the most recent version (2.6.2) of bochs for this assignment. An ubuntu .deb file is available here.

Debugging tips

Kernel

GDB is your friend. Use the bochs-gdb target (or its bochs-gdb-nox variant) to make BOCHS wait for GDB to attach. See the GDB reference below for some commands that are useful when debugging kernels.

If you're getting unexpected interrupts, exceptions, or triple faults, you can ask BOCHS to generate a detailed log of interrupts using the -d argument.

To debug virtual memory issues, try the BOCHS monitor commands info mem (for a high-level overview) or info pg (for lots of detail). Note that these commands only display the current page table.

(Lab 4+) To debug multiple CPUs, use GDB's thread-related commands like thread and info threads.

User environments (lab 3+)

GDB also lets you debug user environments, but there are a few things you need to watch out for, since GDB doesn't know that there's a distinction between multiple user environments, or between user and kernel.

You can start JOS with a specific user environment using make run-name (or you can edit kern/init.c directly). To make BOCHS wait for GDB to attach, use the run-name-gdb variant.

You can symbolically debug user code, just like you can kernel code, but you have to tell GDB which symbol table to use with the symbol-file command, since it can only use one symbol table at a time. The provided .gdbinit loads the kernel symbol table, obj/kern/kernel. The symbol table for a user environment is in its ELF binary, so you can load it using symbol-file obj/user/name. Don't load symbols from any .o files, as those haven't been relocated by the linker (libraries are statically linked into JOS user binaries, so those symbols are already included in each user binary). Make sure you get the right user binary; library functions will be linked at different EIPs in different binaries and GDB won't know any better!

(Lab 4+) Since GDB is attached to the virtual machine as a whole, it sees clock interrupts as just another control transfer. This makes it basically impossible to step through user code because a clock interrupt is virtually guaranteed the moment you let the VM run again. The stepi command works because it suppresses interrupts, but it only steps one assembly instruction. Breakpoints generally work, but watch out because you can hit the same EIP in a different environment (indeed, a different binary altogether!).

Reference

JOS makefile

The JOS GNUmakefile includes a number of phony targets for running JOS in various ways. All of these targets configure BOCHS to listen for GDB connections (the *-gdb targets also wait for this connection). To start once BOCHS is running, simply run gdb from your lab directory. We provide a .gdbinit file that automatically points GDB at BOCHS, loads the kernel symbol file, and switches between 16-bit and 32-bit mode. Exiting GDB will shut down BOCHS.
make bochs
Build everything and start BOCHS with the VGA console in a new window and the serial console in your terminal. To exit, either close the VGA window or press Ctrl-c in your terminal.
make bochs-nox
Like make bochs, but run with only the serial console. To exit, send bochs a SIGHUP from another termimal (killall -HUP bochs). This is particularly useful over SSH connections to Athena dialups because the VGA window consumes a lot of bandwidth.
make bochs-gdb
Like make bochs, but rather than passively accepting GDB connections at any time, this pauses at the first machine instruction and waits for a GDB connection.
To connect from gdb, type
gdb obj/kern/kernel
target remote localhost:1234
make bochs-nox-gdb
A combination of the bochs-nox and bochs-gdb targets.
make run-name
(Lab 3+) Run user program name. For example, make run-hello runs user/hello.c.
make run-name-nox, run-name-gdb, run-name-gdb-nox,
(Lab 3+) Variants of run-name that correspond to the variants of the bochs target.
The makefile also accepts a few useful variables:
make V=1 ...
Verbose mode. Print out every command being executed, including arguments.
make V=1 grade
Stop after any failed grade test and leave the BOCHS output in jos.out for inspection.
make BOCHSEXTRA='args' ...
Specify additional arguments to pass to BOCHS.

JOS obj/

When building JOS, the makefile also produces some additional output files that may prove useful while debugging:

obj/boot/boot.asm, obj/kern/kernel.asm, obj/user/hello.asm, etc.
Assembly code listings for the bootloader, kernel, and user programs.
obj/kern/kernel.sym, obj/user/hello.sym, etc.
Symbol tables for the kernel and user programs.
obj/boot/boot.out, obj/kern/kernel, obj/user/hello, etc
Linked ELF images of the kernel and user programs. These contain symbol information that can be used by GDB.

GDB

See the GDB manual for a full guide to GDB commands. Here are some particularly useful commands for 6.828, some of which don't typically come up outside of OS development.

Ctrl-c
Halt the machine and break in to GDB at the current instruction. If BOCHS has multiple virtual CPUs, this halts all of them.
c (or continue)
Continue execution until the next breakpoint or Ctrl-c.
si (or stepi)
Execute one machine instruction.
b function or b file:line (or breakpoint)
Set a breakpoint at the given function or line.
b *addr (or breakpoint)
Set a breakpoint at the EIP addr.
set print pretty
Enable pretty-printing of arrays and structs.
info registers
Print the general purpose registers, eip, eflags, and the segment selectors. For a much more thorough dump of the machine register state, see BOCHS's own info registers command.
x/Nx addr
Display a hex dump of N words starting at virtual address addr. If N is omitted, it defaults to 1. addr can be any expression.
x/Ni addr
Display the N assembly instructions starting at addr. Using $eip as addr will display the instructions at the current instruction pointer.
symbol-file file
(Lab 3+) Switch to symbol file file. When GDB attaches to BOCHS, it has no notion of the process boundaries within the virtual machine, so we have to tell it which symbols to use. By default, we configure GDB to use the kernel symbol file, obj/kern/kernel. If the machine is running user code, say hello.c, you can switch to the hello symbol file using symbol-file obj/user/hello.

BOCHS represents each virtual CPU as a thread in GDB, so you can use all of GDB's thread-related commands to view or manipulate BOCHS's virtual CPUs.

thread n
GDB focuses on one thread (i.e., CPU) at a time. This command switches that focus to thread n, numbered from zero.
info threads
List all threads (i.e., CPUs), including their state (active or halted) and what function they're in.

BOCHS

BOCHS includes a built-in monitor that can inspect and modify the machine state in useful ways. To enter the monitor, press Ctrl-a c in the terminal running BOCHS. Press Ctrl-a c again to switch back to the serial console.

For a complete reference to the monitor commands, see the bochs manual. Here are some particularly useful commands:

xp/nuf> paddr
Display a hex dump of physical address paddr. This is the physical memory analogue of GDB's x command.
Reading register contents. These commands display the registers of the emulated CPU:
        r|reg|regs|registers         List of CPU integer registers and their contents
        sreg                         Show segment registers and their contents
        dreg                         Show debug registers and their contents
        creg                         Show control registers and their contents
        info cpu                     List of all CPU registers and their contents
        info eflags                  Show decoded EFLAGS register
        info break                   Information about current breakpoint status
        info tab                     Show paging address translation
        info device                  Show state of the specified device
page laddr
Display translation of linear to physical memory.
Other useful commands:
      show [string]
        Toggles show symbolic info (calls to begin with).
        show - shows current show mode
        show mode     - show, when processor switch mode
        show int      - show, when interrupt is happens
        show call     - show, when call is happens
        show ret      - show, when iret is happens
        show off      - toggles off symbolic info
        show dbg-all  - turn on all show flags
        show dbg-none - turn off all show flags
BOCHS also takes some useful command line arguments, which can be passed into the JOS makefile using the BOCHSEXTRA variable.

Last updated: 2014-03-30 09:33:31 -0400 [validate xhtml]