Recently, I got to teach a graduate course about Computer Architecture and Assembly Language and for the homework part, I wanted students to write SPARC assembly programs.
Since actual SPARC computers are not very common these days, my choice went on using QEMU to do the job of running those programs.
In this article, I detail two solutions, both using QEMU. The first uses a full system emulation, which is when QEMU runs a fully fledged operating system (such as Debian). The second solution, much simpler, uses QEMU as an userspace emulator, thus not requiring any functional operating system running underneath.
QEMU as system emulator
My first intuition was that I would distribute QEMU images containing a Debian installation as explained in this tutorial.
After downloading the prebuilt image, I updated it, changed the keyboard layout and installed a gcc toolchain as explained in this tutorial.
Once QEMU is installed on the host computer, running a simulation is not difficult (here we start the emulation of a SPARC computer with 256 Mb of memory):
$ qemu-system-sparc -m 256 -hda debian_etch_sparc_small.qcow2
However, if we want to write the source code of our programs on the host computer and then be able to copy the source on the emulated Debian system, we have to create a ssh port redirection:
$ qemu-system-sparc -m 256 -hda debian_etch_sparc_small.qcow2 -redir tcp:2222::22
The command above means that the port 2222 of the host computer is now binded to the port 22 of the emulated system.
Now we can copy a file named source from the host computer to QEMU:
$ scp -P 2222 source user@localhost:.
After typing this command, the file source should be at the root of the user's root directory in the emulated Debian system.
As you can see, the utilization of this setup is a bit complicated. First it means distributing a +500Mb image to hundreds of students. Second it also means that the workflow is quite difficult: students have to write their code on their local computer before copying it in the QEMU image in order to compile and test it.
We can also add to the list of inconveniences the fact that for some reason, the emulated Debian system can't seem to properly shutdown. And finally, since we want to automate the correction, using such a setup would make things really complicated.
That is why the second solution seems like the best one.
QEMU as an userspace emulator
QEMU usually comes in two flavors:
qemu-system-* are system emulators (able to
run entire operating systems as seen in the previous section), while
are userspace emulators (only able to run userspace applications).
QEMU as an userspace emulator is thus able to directly execute a SPARC application, by emulating the syscalls that the application requests.
Among the greatest features of this approach are:
- The output of application is directly displayed in the terminal,
- Arguments to applications are directly given through the command line,
- QEMU returns the return code of applications, etc.
QEMU really just acts as a wrapper around the application, as
The only complicated thing you have to do in this approach is to compile a cross-toolchain for SPARC, so SPARC programs can be compiled on the host computer. Such a cross-toolchain can be generated by using the fabulous crosstool-ng.
Let's assume here that you were able to generate a SPARC cross-toolchain with
The first thing is to set the following environment variable, otherwise QEMU will not be able to find the SPARC standard libraries:
$ export QEMU_LD_PREFIX=/pathtocrosstoolchain/sparc-unknown-linux-uclibc/sparc-unknown-linux-uclibc
The detailed explanation is that the cross-compiler compiles and links SPARC
applications as if they were to be executed on a real system (i.e. with standard
libraries being in
/lib, etc.). This environment variable thus tells QEMU not
to look for the SPARC standard libraries in the regular locations since the
regular locations on the host computer contain only the libraries for the host
computer (e.g. for the x86 architecture).
Another option is to start QEMU with the
-L option and give the path to the
SPARC libraries directly on the command line.
The path to the SPARC libraries is the folder that contains the following files:
$ ll /pathtocrosstoolchain/sparc-unknown-linux-uclibc/sparc-unknown-linux-uclibc dr-xr-xr-x 2 user users 4096 2014-11-24 13:09 bin dr-xr-xr-x 3 user users 4096 2014-11-24 13:09 debug-root lrwxrwxrwx 1 user users 11 2014-11-24 12:49 lib -> sysroot/lib lrwxrwxrwx 1 user users 3 2014-11-24 12:49 lib32 -> lib lrwxrwxrwx 1 user users 3 2014-11-24 12:49 lib64 -> lib dr-xr-xr-x 4 user users 4096 2014-11-24 12:49 sysroot
Now you can easily compile and test SPARC programs:
$ sparc-unknown-linux-uclibc-gcc -o hello hello.c $ qemu-sparc ./hello joel hello joel! $
Note that it is quite likely that QEMU will display a warning, mentioning
something wrong with
/etc/ld.so.cache. It is because the dynamic loader of the
SPARC cross-toolchain (
ld-uClibc.so.0) refers to
ld.so.cache on the host computer does not correspond to what
the SPARC dynamic loader expects.
So in order to avoid having an annoying warning each time we start an
application, we have to edit the file
ld-uClibc.so.0 (located in
Locate the string
/etc/ld.so.cache in the binary (no need to use xxd or any
other hexadecimal editor, vim is perfectly adequate for the task) and just
etc by something else (e.g.
xxx). Save and that's it, you can now
rerun without any warning!