<!doctype debiandoc system>

<!--
 Copyright (C) 2005 Bill Allombert
 released under the terms of the GNU
 General Public License, version 2 or (at your option) any later.
 -->

<book>

<title>Using qemu syscall emulation with Debian.
<author>Bill Allombert <email/ballombe@debian.org/
<version>version 0.0, <date>

<abstract>
</abstract>

<copyright>Copyright &copy;2005 Bill Allombert.
<p>

This manual is free software; you may redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
<p>

This is distributed in the hope that it will be useful, but
<em>without any warranty</em>; without even the implied warranty of
merchantability or fitness for a particular purpose.  See the GNU
General Public License for more details.
<p>

A copy of the GNU General Public License is available as
<tt>/usr/share/common-licenses/GPL</tt> in the Debian GNU/Linux distribution
or on the World Wide Web at
<tt>http://www.gnu.org/copyleft/gpl.html</tt>. You can also obtain it
by writing to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
<p>

<toc sect>

<chapt>Introduction
<p>

Qemu is a emulator that can be used as a virtual machine or a syscall
emulator. Here I will only be concerned with the syscall emulator
mode. I will also restrict myself to the use of the unstable 
Debian packages of qemu to run softwares provided in Debian packages. I will
also not use root priviledge even when they would make things a bit easier, for
security reason.
<p>

Syscall emulation is very different from a virtual machine: syscall are
executed by qemu without mangling. This can be sometime surprising:
if you emulate a binary that perform the syscall <prgn>exec("/bin/ls")</prgn>, 
qemu will <prgn>exec("/bin/ls")</prgn> which will cause the qemu process to be
replaced with the native ls code (and not an emulated one). Also
hard-coded path in binaries might not point where you want. On the
other access to device is not limited by the emulation, in particular
network access does not need any set up.
<p>
The Debian package include three qemu binaries for syscall emulation.
qemu-arm, qemu-ppc and qemu-sparc. After testing on a x86, it appears that
qemu-arm work the best, qemu-ppc has some issues and qemu-sparc is very
limited. Apparently there are architecture-dependent syscalls that are
difficult to emulate. Also qemu is only able to emulate a limited number of
syscalls.

<chapt> Setting up an environment <p>

To setup the environment the way I describe, you will need a directory with
around 150Mb of free space. However, once you are more experienced with the
process you can use much less disk space.

On my box, this directory is <file>/scratch/qemu</>. I install a arm
environment in <file>/scratch/qemu/ARM</> by running the command below in the
<file>/scratch/qemu</> directory.

<example>
fakeroot /usr/sbin/debootstrap --arch arm sid ARM
</example>
<p>
This will download arm debs and unpack them.
This should fail with
<example>
/usr/lib/debootstrap/functions: line 524: chroot: command not found
</example>
because you are not root. (If you are root this will fail anyway since
you cannot execute the binaries).
<p>
Now, finish to unpack the debs
<example>
for pkg in ARM/var/cache/apt/archives/*.deb; do \
echo "Extracting $pkg..."; dpkg-deb -x $pkg ARM; done
</example>
since you cannot use chroot(2), all hard-coded paths to binaries you have
installed might be a problem. In particular, edit the file
<file>
ARM/lib/ld-linux.so.2</> to replace the string <var>/etc/ld.so.cache</var> to
something that does not exists like <var>/xxx/ld.so.cache</var>.  Be careful to
not change the length of the string, else the offset will be wrong and the
ELF file will be invalid.

Now you can try qemu with
<example>
qemu-arm -L /scratch/qemu/ARM ARM/bin/ls
</example>
The <prgn>-L</> option cause qemu to use an alternative root for finding
the dynamic loader and the C library.

You can also try
<example>
qemu-arm -L /scratch/qemu/ARM ARM/bin/sh
</example>
Programs you launch from that shell will be native program unless you run
them through qemu-arm itself.
<p>
You can check network access with
<example>
qemu-arm -L /scratch/qemu/ARM ARM/usr/bin/wget www.debian.org
</example>
<chapt> Going further
<p>
<sect> Trouble-shooting
<p>
If qemu-arm fails mysteriously, try to run it under strace. It might tell
you if it look for a file in the wrong place.
<p>
Note that qemu-arm will not run scripts. This is not really a limitation
since script have a hard-coded path to the interpretor which will point
to the native version.
<p>
Current qemu really does not like symlink to directories in the directory
pointed by -L.
<sect> Installing extra packages
<p>

If you want to install more packages, you can download them with 
this variant of debget (that I will call debget-arm).
<example>
#!/bin/bash -e

for pkgspec in $*; do
  version=$(apt-get -q2 -s --reinstall install "$pkgspec" | grep ^Inst | sed -ne '$s/^.*\[\(.*\)\].*$/\1/p')
  echo "($pkgspec -> $version)"
  aptdata=$(apt-get -q2 --print-uris --reinstall install "$pkgspec" | tail -1|sed -e "s/_i386\.deb/_arm\.deb/g")
  echo $aptdata
  url=$(echo "$aptdata" | sed -e "s/^'\([^']*\)'.*$/\1/")
  file=$(echo "$aptdata" | sed -e "s/^'[^']*' \([^ ]*\).*$/\1/")
  echo $url
  echo $file
  curl "$url" > "$file"
done
</example>

This script assume your first apt source is a Debian archive that include the
arm architecture and the packages are in sync on arm.

As an example I will try to get pari-gp running:
I run
<example>
mkdir debs; cd debs;
debget-arm libpari1 libx11-6 libreadline4 pari-gp
cd ..
for pkg in debs/*; do \
echo "Extracting $pkg..."; dpkg-deb -x $pkg ARM; done
</example>

To access libraries in ARM/usr/X11R6/lib, you need to change your
<prgn>LD_LIBRARY_PATH</> variable:
<example>
export LD_LIBRARY_PATH=/scratch/qemu/ARM/usr/X11R6/lib
</example>

Now, you can try
<example>
qemu-arm -L /scratch/qemu/ARM ARM/usr/bin/gp

                  GP/PARI CALCULATOR Version 2.1.6 (released)
              arm running linux (C portable kernel) 32-bit version
</example>
As a comparaison of performance, <var>debussy.debian.org</> runs the PARI/GP
benchmark in 17246ms.  A Athlon 1800+ running qemu-arm run the benchmark
in 14730ms. The native binary run in 1340ms.

</book>
