Tuesday, July 22, 2008

Testing qemu

The goal is to run ARM software on a Linux PC.
I download the latest qemu, which is 0.9.1 today.

There isn't much fun here, just the usual stages:

./configure --target-list=arm-linux-user
make install (as root)

Qemu requires the run-time libraries to run. The quickest way is to explode an entire package release to a root directory:

# tpkg-explode main tempdir

Warning: the postinstall scripts of the packages are not executed, which is not very important for most of the packages but the library cache file. So I manually edit etc/ld.so.conf and add the library paths there /usr/TCSL/lib.

Then I rebuild the library cache:
# ldconfig -r //tempdir

and now I can run any ARM program:

# qemu-arm -L tempdir tempdir/usr/TCSL/bin/unsls

It works great, but it does not detect memory overwrites or leaks (who told me that it could?).
It's fine, but not as a memory checker for ARM, as I intended.

Cross-compiling Valgrind

Valgrind is available for other architectures other than the i386/PC. Unfortunately it is not ported to the ARM processor family, but it still can be useful for the PPC targets I use.

First, I download the latest version of valgrind (today is 3.3.1).

Before configuring, a word of advice: the prefix option does not work as usual. The absolute prefix path gets hardwired in the valgrind code so that valgrind is able to find other tools such as memcheck, etc. So, the prefix path must be used with the target distribution in mind. As I plan to install valgrind on a network directory and mount it via NFS from the target unit, I will set 'prefix' to
the name of the mountpoint.

The reason for not installing valgrind on the target is because the size of the file is quite big (more than 50MB) as valgrind requires that his own binary files are not stripped. This is explained in the README_PACKAGERS file.

Apart from setting the usual CC variable:
/configure --host=ppc-linux --prefix=/ppc/tools/valgrind --disable-tls
make install

TLS is not provided by my kernel version, so it is disabled here.

At this point, valgrind runs but it reports an error that it is unable to do some binary code substitutions (i.e. the strlen function). It suggests that the linker may be stripped /lib/ld-·so, which is true.

Having the unstripped version of 'ld' requires compiling the entire glibc RPM. For my platform, the glibc is installed as an RPM. Then, I download and install the source RPM.

The binary files get automatically stripped by rpmbuild at the end of the %install stage. The "__os_install_post" macro contains the script that must be run at that point. This scriptlet calls the brp-strip-shared script, which lives under /opt/eldk/usr/lib/rpm, and strips all the shared libraries found in the installation directory. Unfortunately, my installation of ppc-rpm does not allow this scriptlet to be edited, so the only option is to add a condition at the top of the brp-strip-shared scripts so that if the DONT_STRIP_SHARED variable is set, then exit the script immediately. The spec file must be edited so that this variable is defined.

Then, I modify the glibc.spec file where, at the end of the %install section, there is a piece of code that strips all shared libraries but the 'libpthread' library. I just add the 'ld' library as an exception to the strip process, and then I rebuild the RPM.

export PATH=/opt/eldk/usr/ppc-linux/bin/:$PATH
ppc-rpmbuild -ba glibc.spec

Do not forget to increase or change the version of the RPM so that it is installed in the target successfully.

A simpler workaround is to copy the ld-x.y.z.so file manually, in this case, use 'cp -f' as the file is always in use.