12

I am seeing something really weird inside a chroot-ed Debian armel environment.

But first, a bit of backstory... This is long, but the question is complex and any potential help depends on knowing the full story.

I have an embedded ARM SoC that runs Linux - more specifically, a Debian armel Lenny on a 2.6.17 kernel. The Debian distro itself is easily upgradeable to later versions (sudo apt-get dist-upgrade) and can thus be brought up to speed, to the armel versions of squeeze or even wheezy.

The problem is that the kernel is a custom one... The ARM SoC in question is not part of the mainline kernel, so it is pretty much abandoned at 2.6.17.

If you know how Linux and GLIBC work, you can already see the problem - GLIBC versions are compiled with a minimum supported kernel version... Which has moved way past 2.6.17. So if we try to e.g. chroot to a Debian squeeze...

$ # From inside the little ARM machine running Debian Lenny
$ sudo debootstrap --arch armel squeeze /squeeze \
     http://ftp.whateverCountry.debian.org/debian
$ sudo -i
# mount -t proc none /squeeze/proc
# mount -t sysfs none /squeeze/sys
# mount -t devpts none /squeeze/dev/pts
# chroot /squeeze
Fatal: Kernel too old

...we see a message from the GLIBC of squeeze, telling us that it was not compiled to work with this old kernel (2.6.17).

The same problem happens with wheezy, too - since it is newer than squeeze - and will in fact happen with any Debian version from now on, since their GLIBC won't work on my 2.6.17 kernel.

At first I thought this was a deal breaker - but then I realized that I can in theory recompile GLIBC to work with the older kernel my SoC is using... But I'd need an identical environment to what was used to build the libc6 package in e.g. Debian squeeze.

I am guessing the compilation of GLIBC and the preparation of the libc6_2.11.3-4.deb file is done via automated cross-compiling machinery invented by the Gods of Debian.

I am no God... nor could I find anything in Google about how to become one - i.e. how to use my Core i5 as a host, to cross-compile GLIBC using the exact same settings that the packaged version (inside Debian squeeze) is using.

So I tricked it - I figured out how to setup the ARM version of Debian squeeze on my Core i5 (a technique that uses a static version of the qemu-arm binary).

Once I chrooted in my x86-hosted version of Debian-armel-squeeze, I was able to simply...

$ cd /var/tmp
$ apt-get source libc6
...
$ # edit this in - compile for my kernel...
$ vi eglibc-2.11.3/debian/sysdeps/linux.mk
...
MIN_KERNEL_SUPPORTED := 2.6.17
...
$ export DEB_BUILD_OPTS="nocheck parallel=1"
$ cd eglibc-2.11.3
$ dpkg-buildpackage -b -d -us -uc

...and after 3 hours (the Core i5-hosted chrooted version of Debian-armel-squeeze is much slower than a native machine...) I got my libc6 .deb package. It would probably take 3 months to do this build in my SoC, so I am not complaining.

Going back inside my real ARM SoC, I copied all the libc files (.so) of the new package over the default ones of squeeze and tried to chroot...

# chroot squeeze/
root@ttsiodras:/# 

Yes! It worked! (or so it seemed)

My custom libc reported from inside the chroot:

# /lib/libc.so.6 
GNU C Library (Debian EGLIBC 2.11.3-4) stable release version 2.11.3, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.5.
Compiled on a Linux 2.6.26 system on 2014-10-23.
Available extensions:
        crypt add-on version 2.1 by Michael Glad and others
        GNU Libidn by Simon Josefsson
        Native POSIX Threads Library by Ulrich Drepper et al
        Support for some architectures added on, not maintained in glibc core.
        BIND-8.2.3-T5B
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.

Things seemed to work - I copied a file, invoked ls...

But when I tried to use apt-get to install some apps from squeeze, I started getting... some unexpected errors:

# apt-get install indent
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  indent
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 110 kB of archives.
After this operation, 516 kB of additional disk space will be used.
Get:1 http://ftp.gr.debian.org/debian/ squeeze/main indent armel 2.2.11-1 [110 kB]
Fetched 110 kB in 0s (236 kB/s)

tar: ./control: Cannot utime: Function not implemented
tar: ./md5sums: Cannot utime: Function not implemented
tar: .: Cannot utime: Function not implemented
tar: Exiting with failure status due to previous errors

dpkg-deb: subprocess tar returned error exit status 2
dpkg: error processing /var/cache/apt/archives/indent_2.2.11-1_armel.deb (--unpack):
 subprocess dpkg-deb --control returned error exit status 2
configured to not write apport reports

rm: cannot remove `/var/lib/dpkg/tmp.ci': Function not implemented

dpkg: error while cleaning up:
 subprocess rm cleanup returned error exit status 1
Errors were encountered while processing:
 /var/cache/apt/archives/indent_2.2.11-1_armel.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)

Oh-oh... a bunch of Function not implemented. That sounds like GLIBC reporting that basic things are not working...

I managed to strace (don't ask how) and figured out that all the -at functions are failing: openat, mkdirat, renameat, etc - they are all reporting ENOSYS.

It appears that I was only partially successful - some system calls are failing in my new GLIBC.

Is it impossible to compile a squeeze or wheeze GLIBC to execute under 2.6.17?

Any ideas/pointers on what I did wrong and/or how to proceed would be much appreciated...

  • Setting up a cross-compiler isn't that difficult and there are tutorials on the web for this. It'll be significantly faster than running the compiler in Qemu. I don't know if it'll help with the resulting libc not working. – Gilles Oct 24 '14 at 16:10
  • @Gilles: Regarding "tutorials" - can you point to anything specific? I tried crosstool-ng but it doesn't go as far back as my target kernel version (2.6.17). I think this is relevant - glibc must be compiled with headers from my kernel (maybe that's what's causing my problems in my "ARM-based" build...) – ttsiodras Oct 25 '14 at 7:45
6

I made it :-)

I basically followed Gilles's advice and decided to do it properly: i.e. manage a complete cross-compilation of GLIBC. I started from crosstool-ng, and was initially disappointed - seeing that it didn't support my old kernel. I kept at it, though - manually editing the configuration file saved by crosstool-ng to do changes like these on the default arm-gnueabi build configuration:

$ ct-ng arm-unknown-linux-gnueabi
$ ct-ng menuconfig
...
$ vi .config
$ cat .config
...
CT_KERNEL_VERSION="2.6.17"
CT_KERNEL_V_2_6_17=y
CT_LIBC_VERSION="2.13"
CT_LIBC_GLIBC_V_2_13=y
CT_LIBC_GLIBC_MIN_KERNEL_VERSION="2.6.9"
CT_LIBC_GLIBC_MIN_KERNEL="2.6.9
...
$ ct-ng +libc

After numerous tests and failed attempts, the above changes did it - I got a compiled version of GLIBC that would work with my kernel, and copied the resulting files to my Debian Lenny ARM machine:

$ cd .build/arm-unknown-linux-gnueabi/build/build-libc-final/
$ tar zcpf newlibc.tgz $(find . -type f -iname \*.so)
$ scp newlibc.tgz root@mybook:.

I went all the way and moved past squeeze: I debootstrapped a /wheezy and then - very carefully - overwrote the GLIBC versions of the armel-debootstrapped /wheezy with my own:

# # In the ARM machine
# cd /wheezy/lib/arm-linux-gnueabi/
# mv /var/tmp/ohMyGod/libc.so libc-2.13.so
# mv /var/tmp/ohMyGod/rt/librt.so librt-2.13.so
...

...etc, making sure I didn't miss any shared libraries.

Finally, I copied over the ldd and ldconfig binaries (which were also part of GLIBC), and chrooted inside my /wheezy.

It worked.

I can only assume that the compilation of GLIBC from a chroot-ed 'qemu-arm' emulation inside a x86, somehow messed things up - maybe the configure process detects some stuff from the running environment - whereas the cross-compilation can't be misled.

So naturally I moved to the next step, and used a busybox-static shell to replace the {/bin,/sbin,...} folders of my old lenny with the wheezy ones - and rebooted into my brand new Wheezy :-)

I hereby claim that my WD MyBook World Edition is the only one on the planet running Debian Wheezy :-) If anyone else is interested, I can upload a tarball of the libc files someplace.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.