Cross Compiler for Projects 2 and 3

Projects 2 and 3 require a special compiler tool chain for compiling the user-level C programs in the nachos/test directory that run on the Nachos OS. Since the compiler programs are Linux x86 executables and they compile C programs into MIPS executables, we refer to the tool chain as a cross-compiler.

We have installed a MIPS cross-compiler on the instructional systems for the course. If you use a machine in the CSE basement lab, it will automatically use this installation. Similarly, if you work remotely using VSCode and ssh into ieng6 to compile and run, you will also automatically use this installation.

It is possible to get the environment working on your own system, but you will need to install the MIPS cross-compiler yourself. The cross-compiler has a couple of unusual dependencies, and the steps to get it all working are rather involved. Disclaimer: This page provides a guide, but we cannot guarantee that it will work on your system. Do not go down this path unless you are confident in your Linux system administration skills. We do not have the resources to troubleshoot installations on individual student machines (including answering posts to piazza about it), so you will need to rely upon your own skills. If you are having trouble getting it to work on your system, use the machines in the CSE basement labs or use VSCode/ssh instead.

Below are steps for installing on an Ubuntu 22.04.3 system (in my case, running in WSL 2.0 on Windows 11):

  1. Download the MIPS cross-compiler distribution and configure your environment to use it. To be concrete the steps use particular directory names, but you'll want to customize to your setup:
    $ cd /home/snoeren/cse220	
    $ wget https://cseweb.ucsd.edu/classes/wi26/cse220-a/projects/mips-x86.linux-xgcc.tar.gz
    $ tar xvfz mips-x86.linux-xgcc.tar.gz
    

    The Makefile in the nachos/test directory requires two environment variables to be properly initialized to use the cross-compiler. (You can run echo $ARCHDIR to see the value we use for the course when on ieng6.) In this example we set them as follows:

    export ARCHDIR=/home/snoeren/cse220/mips-x86.linux-xgcc
    export PATH=/home/snoeren/cse220/mips-x86.linux-xgcc:$PATH
    
  2. The cross-compiler has two legacy dependencies that we need to support. The first legacy dependency is that they are 32-bit executables, but Linux distributions (such as Ubuntu in WSL) typically support only 64-bit executables by default. If you run one of the executabls, you will likely get the following error:
    $ mips-gcc
    -bash: mips-gcc: cannot execute binary file: Exec format error
    (or)
    -bash: mips-gcc: cannot execute: required file not found
    

    The next step is to update your Linux environment to support 32-bit executables:

    $ sudo dpkg --add-architecture i386
    $ sudo apt-get update
    $ sudo apt-get install gcc-multilib g++-multilib libc6:i386
    

    At this point you might need to reboot your system. You can verify that this step worked by running an executable:

    $ mips-gcc
    mips-gcc: no input files
    

    If you see this output then your Linux now supports 32-bit executables.

  3. The second dependency is that, since they are 32-bit executables, they expect to use files in a 32-bit file system. Again, typical Linux distributions (such as WSL on Windows) use 64-bit file systems. If you compile a C program in the nachos/test directory, you will likely get the following error:
    $ cd nachos/test
    $ make    
    [...]/mips-gcc -O2 -B[...]/mips-x86.linux-xgcc/mips- -G 0 -Wa,-mips1 -nostdlib -ffreestanding -std=gnu99 -c assert.c
    cc1: assert.c: Value too large for defined data type
    

    The "Value too large" refers to file identifiers (inodes) being too large (64 bits) for the cross-compiler.

    The next step is to create a 32-bit file system in which to install and work on Nachos. We are going to create a "loopback" file system, which is a fancy term for creating a file system within a file. Specifically, we are going to perform the following steps: create a 1GB file to use as a file system; create a 32-bit file system inside that file; create an empty directory to use as a mount point; and then mount our 32-bit file system onto the mount point:

    $ cd /home/snoeren/cse220
    $ dd if=/dev/zero of=diskfile bs=1M count=1024
    $ mkfs.ext4 -O ^64bit diskfile
    $ mkdir mountdir
    $ sudo mount -o loop diskfile mountdir
    

    After mounting the file system, we can create a working directory inside of it, clone the Nachos repo, cd into the nachos/test directory, and compile:

    $ cd /home/snoeren/cse220/mountdir
    $ ls
    lost+found
    $ sudo mkdir cse220
    $ sudo chown snoeren cse220
    $ cd cse220
    $ git clone <your-repo>
    $ cd <your-repo>/nachos/test
    $ make
    

    Running make should successfully compile the Nachos C test programs.

Note that you will be working within the loopback file system that you created. When mounted, the files inside of it behave like any other file on your sysem. If you reboot your system, though, you will need to re-mount the loopback file system again. Use the same command as the first time:

$ sudo mount -o loop diskfile mountdir

Do not delete diskfile, which is the file being used to hose the file system. If you delete it, then all files inside of it will be deleted.

Compilation Steps

If you are curious about how Nachos-compatible MIPS executables are created, here are the steps (all of which are handled by the test Makefile):

  1. Source files (*.c) are compiled into object files (*.o) by mips-gcc.
  2. Some of the object files are linked into libnachos.a, the Nachos standard library.
  3. start.s is preprocessed and assembled into start.o. This file contains the assembly-language code to initialize a process. It also provides the system call "stub code" which allows system calls to be invoked. This makes use of the special MIPS instruction syscall which traps to the Nachos kernel to invoke a system call.
  4. An object file is linked with libnachos.a to produce a Nachos-compatible MIPS binary, which has the extension *.coff. (COFF stands for Common Object File Format and is an industry-standard binary format which the Nachos kernel understands.)


Last updated: 2026-02-10 09:53:23 -0800 [validate xhtml]