CSCI-GA.3250-001: Lab tools


You'll use two sets of tools in this class: (1) an x86 emulator, for running your kernel; and (2) a compiler toolchain, including assembler, linker, C compiler, and debugger, for compiling and testing your kernel. This page describes these tools and provides the information that you'll need to get these tools working. This class (and this page) assumes familiarity with Unix commands throughout.

The x86 emulator that we use in this course is QEMU, a modern and fast PC emulator. Our compiler toolchain will turn C and x86 assembly into code for 32-bit Intel architectures ("x86" architectures) in the ELF binary format.

There are two options for installing these tools:

  1. (Recommended) Use the virtual devbox that we provide. This image includes both sets of tools, configured for the labs in this course.
  2. Build and install the tools directly on your own machine.
We give instructions for each of these options below.

For an overview of useful commands in the tools used in this course, see the lab tools guide.

Using the virtual machine image

A natural way to ensure that all of us are using the same development environment (short of us all using the same machine) is for us to use identically configured virtual machines. We will be studying virtual machines in depth in this course. For now, you can think of a virtual machine as a way to run a particular operating system (in our case, an Ubuntu desktop) on top of another operating system.

To get our virtual devbox running, you should do the following:

  1. Download and install on your computer (e.g., your desktop or laptop) a virtualization platform:
  2. Download to your computer the virtual devbox image that we have set up for you. Note: the file is almost 2 GB, so the initial download may take some time.
  3. Using the virtualization platform (for example, VirtualBox), import the image that you saved. This, too, may take some time.
  4. Using the virtualization platform, start up the virtual machine. You should see an Ubuntu desktop come online.
  5. Login to the machine. Username: cs3250. Password: labs.
  6. At this point, you have a machine that will act like an Ubuntu desktop, and you'll do your development on this machine.
  7. If you are using VirtualBox, you will probably want to enlarge the default "monitor size" of the virtual machine. For this to work, the scaling feature must be enabled; this may require pressing a command key plus C, depending on your platform.

Notice the potential confusion from this arrangement. VirtualBox is creating a fake machine (with a fake x86 CPU). Ubuntu desktop is running on that fake machine (though neither Ubuntu desktop nor the processes running on Ubuntu desktop are aware that they are running on a fake machine). The confusion enters because one of the pieces of software that you are going to run on Ubuntu desktop is QEMU, and what does QEMU do? It creates another fake machine on which one can run an operating system. In our case, this fake machine will run JOS. To recap: JOS will run on the fake machine that QEMU provides, QEMU is running on Ubuntu desktop, Ubuntu desktop is the operating system for the fake machine that VirtualBox provides, and VirtualBox is running on your computer's operating system (known as the "host" operating system).

All of this is to say that there are actually two levels of virtualization in play. The two levels serve different purposes. The purpose of the lower of the two is to create a uniform devbox that we all share. The purpose of the upper of the two is to create the illusion of a physical machine so that you can develop, debug, and run JOS. This is a good example of how virtualization serves multiple purposes, a point that we will return to this semester, when we study virtualization.

A potentially interesting point is that although the two levels of virtualization serve different purposes, and although they are implemented with different software (VirtualBox and qemu, respectively), they accomplish their function using similar technology. We will discuss this technology in depth, again during the virtualization unit. In the meantime, welcome to The Matrix....

Using your own machine

If you really want to, you can build and install the tools directly on your own machine. Below we give instructions for Unix and MacOS computers. It should also be possible to get the development environment running 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).

QEMU Emulator

Unfortunately, QEMU's debugging facilities, while powerful, are somewhat immature, so we highly recommend you use our (really, MIT's) patched version of QEMU instead of the stock version that may come with your distribution. The version installed on the virtual machine image is already patched. To build your own patched version of QEMU:

  1. Clone the QEMU git repository from the MIT 6.828 people:
    git clone -b 6.828-1.7.0
  2. On Linux, you may need to install the SDL development libraries to get a graphical VGA window. On Debian/Ubuntu, this is the libsdl1.2-dev package.
  3. Configure the source code
    1. Linux: ./configure --disable-kvm [--prefix=PFX] [--target-list="i386-softmmu x86_64-softmmu"]
    2. OS X: ./configure --disable-kvm --disable-sdl [--prefix=PFX] [--target-list="i386-softmmu x86_64-softmmu"] The prefix argument specifies where to install QEMU; without it QEMU will install to /usr/local by default. The target-list argument simply slims down the architectures QEMU will build support for.
  4. Run make && make install

Compiler Toolchain

First test your compiler toolchain

Modern Linux and BSD UNIX distributions already provide a toolchain suitable for this course. To test your distribution, try the following commands:

$ objdump -i

The second line should say elf32-i386.

$ gcc -m32 -print-libgcc-file-name

The command should print something like /usr/lib/gcc/i486-linux-gnu/version/libgcc.a or /usr/lib/gcc/x86_64-linux-gnu/version/32/libgcc.a

If both these commands succeed, you're all set, and don't need to compile your own toolchain.

If the gcc command fails, you may need to install a development environment. On Ubuntu Linux, try this:

$ sudo apt-get install -y build-essential gdb

On 64-bit machines, you may need to install a 32-bit support library. The symptom is that linking fails with error messages like "__udivdi3 not found" and "__muldi3 not found". On Ubuntu Linux, try this to fix the problem:

$ sudo apt-get install gcc-multilib

Building your own compiler toolchain

This will take longer to set up, but give slightly better performance than a virtual machine, and lets you work in your own familiar environment (Unix/MacOS). You can use your own tool chain by adding the following line to conf/


We assume that you are installing the toolchain into /usr/local. You will need a fair amount of disk space to compile the tools (around 1GiB). If you don't have that much space, delete each directory after its make install step.

Download the following packages:

XXX: need to check these. builds gcc4.2 on MacOS, which should solve clang problem on MacOS

(You may also use newer versions of these packages.) Unpack and build the packages. The green bold text shows you how to install into /usr/local, which is what we recommend. To install into a different directory, $PFX, click herenote the differences in lighter type (hide). If you have problems, see below.

tar xjf gmp-5.0.2.tar.bz2 cd gmp-5.0.2 ./configure --prefix=/usr/local--prefix=$PFX make make install # This step may require privilege (sudo make install) cd .. tar xjf mpfr-3.0.1.tar.bz2 cd mpfr-3.0.1 ./configure --prefix=/usr/local--prefix=$PFX --with-gmp=$PFX make make install # This step may require privilege (sudo make install) cd .. tar xzf mpc-0.9.tar.gz cd mpc-0.9 ./configure --prefix=/usr/local--prefix=$PFX --with-gmp=$PFX --with-mpfr=$PFX make make install # This step may require privilege (sudo make install) cd .. tar xjf binutils-2.21.1.tar.bz2 cd binutils-2.21.1 ./configure --prefix=/usr/local--prefix=$PFX --target=i386-jos-elf --disable-werror make make install # This step may require privilege (sudo make install) cd .. i386-jos-elf-objdump -i # Should produce output like: # BFD header file version (GNU Binutils) 2.21.1 # elf32-i386 # (header little endian, data little endian) # i386... tar xjf gcc-core-4.6.1.tar.bz2 cd gcc-4.6.1 mkdir build # GCC will not compile correctly unless you build in a separate directory cd build ../configure --prefix=/usr/local--prefix=$PFX --with-gmp=$PFX --with-mpfr=$PFX --with-mpc=$PFX \ --target=i386-jos-elf --disable-werror \ --disable-libssp --disable-libmudflap --with-newlib \ --without-headers --enable-languages=c
MAC OS X 10.7 "LION" NOTE: The default clang compiler on Mac OS X 10.7 cannot build a working version of GCC. Use the following configure line to work around the problem: ../configure --prefix=/usr/local--prefix=$PFX --with-gmp=$PFX --with-mpfr=$PFX --with-mpc=$PFX \ --target=i386-jos-elf --disable-werror \ --disable-libssp --disable-libmudflap --with-newlib \ --without-headers --enable-languages=c \ CC=/usr/bin/gcc-4.2 CPP=/usr/bin/cpp-4.2 \ make all-gcc make install-gcc # This step may require privilege (sudo make install-gcc) make all-target-libgcc make install-target-libgcc # This step may require privilege (sudo make install-target-libgcc) cd ../.. i386-jos-elf-gcc -v # Should produce output like: # Using built-in specs. # COLLECT_GCC=i386-jos-elf-gcc # COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/i386-jos-elf/4.6.1/lto-wrapper # Target: i386-jos-elf tar xjf gdb-7.3.1.tar.bz2 cd gdb-7.3.1 ./configure --prefix=/usr/local--prefix=$PFX --target=i386-jos-elf --program-prefix=i386-jos-elf- \ --disable-werror make all make install # This step may require privilege (sudo make install) cd ..


Q. I can't run make install because I don't have root permission on this machine.
A. Our instructions assume you are installing into the /usr/local directory. However, this may not be allowed in your environment. If you can only install code into your home directory, that's OK. In the instructions above, replace --prefix=/usr/local with --prefix=$HOME (and click here to update the instructions further). You will also need to change your PATH and LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (Mac OS X) environment variables, to inform your shell where to find the tools. For example:
export PATH=$HOME/bin:$PATH
Enter these lines in your ~/.bashrc file so you don't need to type them every time you log in.
Q. My build fails with an inscrutable message about "library not found".
A. You need to set your LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (Mac OS X) environment variable to include the libraries you built; see above. The environment variable must include the PREFIX/lib directory (for instance, /usr/local/lib).

(Adapted from MIT's 6.828 Tools page.)

Last updated: Tue Dec 09 19:47:59 -0500 2014 [validate xhtml]