2011-10-28

Yet another GCC e500v2 bug bites the Debian powerpcspe port

I just spent probably 10 hours pouring over the libffi assembly by hand and under GDB, completely sure that a segmentation fault issue was caused by a bug in there.  I finally figured out that the stack (or the unwind data or something) was being overwritten, and that it was happening inside of the innermost function.

After literally single-stepping through about 8000 lines of ASM and not being able to find anything wrong with the libffi parts, I finally got fed up.  I ripped the testcase out and created a basic C++ function that sets up the same data-structures without using any assembly at all, and that failed too!!!

The most annoying thing I ran into while debugging was that GDB would tell me the stack was garbage, but if I actually followed the stack pointers by hand it all looked perfect.  IE: this is what GDB gave me under my stripped down testcase:

  (gdb) bt
  #0  closure_test_fn1 (cif=<value optimized out>, resp=0xbffff46c,
      args=<value optimized out>, userdata=<value optimized out>)
      at unwindtestfunc.cc:39
  #1  0x00000001 in ?? ()
  #2  0x00000001 in ?? ()
  Backtrace stopped: previous frame inner to this frame (corrupt stack?)



And yet printing by hand it looked like a valid stack:
  (gdb) print (void (*)(void))*($r1 + 4)
  $1 = (void (*)(void))
       0x10000970 <closure_test_fn1(ffi_cif*, void*, void**, void*)+320>
  (gdb) print (void (*)(void))*(*$r1 + 4)
  $2 = (void (*)(void)) 0x100006a0 <main()+324>


AAARRRGGGHHH!!!!  I hate GCC bugs!!!


The issue apparently crops up only when building with "-Os" (not with "-O2", which is almost the same), so there's probably a really stupid bug hanging around somewhere, but the stack itself looks fine and I don't understand the C++ unwind data-structures well enough to track it down.

So I filed GCC PR target/50906, which causes GCC to miscompile e500v2 floating point code using exceptions. This was causing the libffi testsuite to fail miserably with a SIGSEGV in "unwindtest.cc" when build with "-Os".

This not exactly the first major issue that mainline GCC has had with this sub-architecture port: PR44169, PR44364 PR44606. It's further worth noting that despite our pleas with FreeScale, it ended up being an IBM developer (Alan Modra from Australia) who helped us get those previous bugs solved.

I'm hopeful that this will be a relatively obvious bug and therefore very easily solved.

Cheers,
Kyle Moffett

2011-10-27

Debian PowerPC e500v2 port, part 8


This is part of the Debian PowerPC e500 porting effort, the series on my blog starts at: "How to bootstrap a new Debian port"

Sorry that it's been so long since the last post... I was able to get my board booted from NFS, but after that things got complicated.

I spent quite a while trying to re-cross-bootstrap more packages; but GCC 4.6 refused to build in a reverse-cross configuration (IE: build a compiler on amd64 that runs on powerpcspe and targets powerpcspe).

Unfortunately, there's a bit of a nasty dependency loop that prevented me from doing a native build either.  In order to build a new GCC 4.6 with multiarch support, I needed to install a new multiarch libc6... except that multiarch libc6 "Breaks" my old GCC 4.4 (which doesn't have multiarch).

I ended up doing a native build of a new multiarch libc6 on my NFS-booted system and forcibly installing that (which leaves my GCC 4.4 broken).  Thankfully libc6 creates a file in "/etc/ld.so.conf.d/" that GCC uses to help find libraries and I could work around the runtime crt*.o objects like this:

  # cd /usr/lib
  # for i in powerpc-linux-gnuspe/*; do ln -s "$i"; done

With that I was able to build a new GCC 4.6.  Unfortunately, I still had an old gcc-defaults package (depending on gcc-4.4) and the new gcc-defaults package would not build unless I could install gcc-4.6 and gcj-jdk and a half-dozen other things I don't have.

Thankfully, with a couple more quick compatibility symlinks I could just remove "gcc" and "g++" and leave "build-essential" technically broken but have a working build environment:

  # cd /usr/bin
  # for i in *g{cc,++}-4.6; do ln -s "$i" "${i%-4.6}"; done

After that, I had a new libc6 installed, along with "multiarch-support"!  Finally!  Woohoo!!!

I upgraded dpkg, apt, aptitude, and about a half-dozen other libraries and tools that all need multiarch these days...

Now I need to figure out what I need to install/build/rebuild in order to make sbuild work again, then I should be able to get a new "buildd" server going.

And of course once I have one going I have enough spare hardware to start about 18 of them.

I'll hopefully post again later today with more progress.

Cheers,
Kyle Moffett

2011-10-18

Debian PowerPC e500v2 port, part 7

This is part of the Debian PowerPC e500 porting effort, the series on my blog starts at: "How to bootstrap a new Debian port"

So last time I managed to get the old Debian archive to install onto a new NFS root filesystem, but I had not yet booted or configured that NFS root.  To do that, you need to be able to boot your board (with kernel) and get that filesystem mounted as "/" somehow; whether using busybox or some other mechanism.

At this point "/etc/inittab" doesn't exist yet, so you will need to boot with "init=/bin/bash" in the kernel arguments.  Since you're probably booting with a serial console, you also want "console=ttyS0,115200n1".  Additionally, you probably need some root filesystem options like "root=/dev/hda1 rw" or "root=192.168.1.42:/srv/nfsroot/my-board rw" or something.

Once the board boots and displays a shell, you're halfway there!  Before you can get packages to configure, though, you need to workaround a "libc6" postinst bug.  Fake the existence of an actual "init" program by running these command:
  $ mkfifo /dev/initctl
  $ cat </dev/initctl >/dev/null &


Next work around a "dash" postinst bug with these commands:
  $ dpkg-divert --package dash --divert /bin/sh.old --add /bin/sh
  $ dpkg-divert --package dash --divert /usr/share/man/man1/sh.1.gz.old \
            /usr/share/man/man1/sh.1.gz

Finally you can configure all the packages.  Run this command and reply to the interactive prompts as necessary:
  $ dpkg --configure -a


Once that finishes, you just have 2 steps remaining before you can reboot.  Set up a serial console and change root's password:
  $ echo 'T0:2345:respawn:/sbin/getty -L ttyS0 115200 xterm-color' \
            >>/etc/inittab
  $ passwd root
  Enter new UNIX password:
  Retype new UNIX password:
  passwd: password updated successfully


Ok, you're done!  Sync and reboot!  This time you don't need to pass any special options.
  $ sync && reboot -f


Unfortunately most of the last few days has been dealing with other problems like merging our HWW-1U-1A U-Boot board support upstream and dealing with other internal projects, so this is it for today.

Cheers,
Kyle Moffett

2011-10-14

Convenient remote in-system flashing with a BDI-3000

This is part of the Debian PowerPC e500 porting effort, the series on my blog starts at: "How to bootstrap a new Debian port"

The hardware I'm using is based on FreeScale's P2020 processor, with a 128MB NOR boot flash and 2GB of ECC DDR2 SDRAM.  To make it convenient to do in-system reflashing (for example, during U-Boot development), I have written a script "bditool" which does the grunt-work of generating config files and connecting to my ABATRON BDI-3000 JTAG device.  Unfortunately the BDI-3000 itself is not exactly a cheap piece of hardware (a few thousand US dollars), and the ABATRON software licenses for additional processor families are about the same.

It's released under the GPLv2 here:

It requires an existing TFTP server that can be accessed by SSH and by your BDI-3000 at the same address.  Additionally, the TFTP server is expected to be able to telnet to the BDI (since the   To customize it for your hardware and network configuration, just edit the script directly.

The first few lines contain the default command-line values, but to adjust the SDRAM configuration for your hardware you will need to edit the list of initialization values much further down in the file.

The usage is pretty simple (assuming the defaults are set up right):
  $ bditool flash ./my-uboot.bin
  $ bditool exec "help"
  $ bditool exec "info"
  $ bditool exec "config"
  $ bditool boot

Please let me know if you have questions!

Cheers,
Kyle Moffett

Debian PowerPC e500v2 port, part 6

This is part of the Debian PowerPC e500 porting effort, the series on my blog starts at: "How to bootstrap a new Debian port"

Well, after all that work building new packages I figured it was time to see how far I could get at building a chroot filesystem and upgrading it to be current.  I'll be doing all of my work in "/srv/stuff", but you can use any volume you would like with several gigs of free disk space.

The first step is building a chroot with the most recent historical snapshot of the Debian-Ports archive that actually still worked, taken on 2011-04-03, at 00:58:02 GMT.  Note that the "unstable" and "experimental" archives don't include sources (see "omitdebsrc=true" below) as those must only be binary builds of upstream Debian sources.  The "unreleased" archive does include sources, as that is intended for packages which need temporary patches to build.

NOTE: I spent a few hours trying various ways to get the multistrap to pull some packages from the current archives (including my fresh-built stuff), but so much stuff was uninstallable (especially Perl stuff) that I determined it was less work to install an old archive and try to upgrade by hand.

First I created "/srv/stuff/e500chroot.multistrap.conf":
  [General]
  arch=powerpcspe
  directory=/srv/stuff/e500chroot/
  noauth=true
  cleanup=true
  unpack=true
  aptsources=Old-Unstable Old-Experimental Old-Unreleased
  bootstrap=Old-Unstable Old-Experimental Old-Unreleased


  [Old-Unstable]
  packages=build-essential debhelper fakeroot sbuild masqmail
  source=http://snapshot.debian.org/archive/debian/ports/20110403T005802Z/
  suite=unstable
  omitdebsrc=true

  [Old-Experimental]

  packages=
  source=http://snapshot.debian.org/archive/debian/ports/20110403T005802Z/
  suite=experimental
  omitdebsrc=true

  [Old-Unreleased]

  packages=
  source=http://snapshot.debian.org/archive/debian/ports/20110403T005802Z/
  suite=unreleased

Then I wrote "/srv/stuff/setup-e500chroot.sh" to copy QEMU into the chroot before starting the multistrap process:
  #! /bin/sh


  set -e


  CHROOT=/srv/stuff/e500chroot
  MULTISTRAP_CONF=/srv/stuff/e500chroot.multistrap.conf


  install -d "${CHROOT}/usr/bin"
  install -t "${CHROOT}/usr/bin" "/usr/bin/qemu-ppc-static"
  install -d "${CHROOT}/usr/local/bin" "/usr/local/bin/qemu-e500v2-static"


  exec multistrap -f "${MULTISTRAP_CONF}"


I ran my multistrap wrapper script and waited about 5-10 minutes for the download and file extraction to complete.


WARNING: The chroot is NOT DONE YET!!!  It has been unpacked, but none of the packages have been configured yet (with "dpkg --configure -a"), because that needs to be run on the target system.


I tried to do the testing entirely on my amd64 workstation using the the QEMU procedure I described in "Using qemu-user-static to help the Debian e500 bootstrap".  Unfortunately I almost immediately started getting "Illegal instruction" exceptions out of QEMU; it looks like it might be fixed by this patch to qemu-ppc but I don't really feel like trying to rebuild all of QEMU for that.

So I need to get the files onto one of my actual HWW-1U-1A boards.  Fortunately for me, I have an old build of an initramfs (based on busybox and a few other things) which lets me do a very-basic NFS boot.  Unfortunately for anyone trying to do this over again, I don't have the original sources for that initramfs so I can't actually distribute it.  In that situation I strongly recommend formatting a plain old SATA disk with ext4 to do the multistrap onto; then just connect the disk to your hardware.

NOTE: This assumes that you already have an existing kernel you can boot on your hardware (probably from U-Boot) with everything you need built in.  Eventually you will need to switch to a Debian-standard kernel, don't worry about it for now.

Once I finish getting NFS and TFTP working I'll be back with another post.

Cheers,
Kyle Moffett

2011-10-13

Debian PowerPC e500v2 port, part 5


This is part of the Debian PowerPC e500 porting effort, the series on my blog starts at: "How to bootstrap a new Debian port"

I've been continuing working on cross-compiling a fresh base system, continuing from Part 4.  Since I got stuck on a GCC 4.6 bug I don't know how to fix at the moment, I'm working off as many other packages as I can for the moment.

Additional packages (with notes and Debian bugs) listed below:

bzip2           - 1.0.5-7               - OK
xz-utils        - 5.1.1alpha+20110809-2 - DEB_BUILD_OPTIONS=nocheck
pcre3           - 8.12-4                - OK
grep            - 2.9-2                 - OK
gdbm            - 1.8.3-10              - OK
libsepol        - 2.1.0-1               - #638018
libselinux      - 2.1.0-1.1             - #645121 (and DEB_STAGE=stage1)
hostname        - 3.06                  - OK
make-dfsg       - 3.81-8.1              - OK
debconf         - 1.5.41                - N/A (Architecture: all)
build-essential - 11.5                  - OK
findutils       - 4.5.10-1              - OK (from experimental, see #645274)
patch           - 2.6.1-2               - OK (DEB_BUILD_OPTIONS=nocheck)
gpm             - 1.20.4-4              - #645278
ncurses         - 5.9-2                 - OK
lsb             - 3.2-28                - BAD (needs python-all-dev)


I'm slowly inching closer to being able to install a new root filesystem!

Cheers,
Kyle Moffett

2011-10-12

Using "dput" and "mini-dinstall" to create a local Debian package repository


While working on bootstrapping a Debian port, I needed a place to keep a bunch of packages for later cross or native installation.  Even though I happen to have access to the debian-ports mirror for powerpcspe, I still need a place for the cross-compiled or bootstrap packages that are not appropriate for that repository.

So I created a local repository using the "mini-dinstall" command.  Configuration and setup was pretty easy, I just created a "~/.mini-dinstall.conf" file with the following contents.
  [DEFAULT]
  archivedir = /srv/stuff/local-pkgmirror
  mail_to =
  verify_sigs = false
  architectures = all, powerpcspe, amd64
  archive_style = flat
  generate_release = true
  mail_on_success = false
  release_codename = Local
  release_description = Local Packages
  release_label = kmoffett
  release_origin = kmoffett
  release_suite = local


Please note that "/srv/stuff" is just a convenient local partition with lots of free space, you can put the repository anywhere you would like.  I then created a "~/.dput.cf" file (make sure the repository location matches):
  [local]
  fqdn = localhost
  method = local
  incoming = /srv/stuff/local-pkgmirror/mini-dinstall/incoming
  run_dinstall = 0
  post_upload_command = mini-dinstall -b

To get everything created and ready, I ran "mini-dinstall -b" once first, then to "upload" packages into the repository I just run "dput -u local $PACKAGE.changes".  Note that if that command fails you may need to delete the "$PACKAGE.local.upload" file in order to try again.

Cheers,
Kyle Moffett

2011-10-11

Debian PowerPC e500v2 port, part 4


This is part of the Debian PowerPC e500 porting effort, the series on my blog starts at: "How to bootstrap a new Debian port"

So in a previous posting, I was discussing how to cross-compile packages.  For the moment, much of the existing powerpcspe archive is still perfectly usable, but several of the toolchain packages are so badly out of date it is easier to just re-cross from scratch.

Last time I built the "gzip" package as a demo, now I am trying to get the target build-dependencies for gcc-4.6 set up so I can build a new GCC for my target environment.  For the moment I have the QEMU setup disabled to prevent any accidents, but I may reenable it if I run into any stubborn packages.

As before, to satisfy build-dependencies you will need some mix of native packages (EG: "doxygen") and cross-compiled "dpkg-cross" packages (EG: "libelfg0-dev-powerpcspe-cross").  There's no really automatic way to tell which is which, although if it begins with "lib" you probably need to cross-compile it.

Since most of these so far have been pretty uneventful, I'll just list the packages I completed and any notes or Debian bugs related to the crossbuilding:

gzip        - 1.4-1              - #644785
zlib        - 1:1.2.3.4.dfsg-3   - OK
gmp         - 2:5.0.2+dfsg-1     - OK
mpfr4       - 3.1.0-2            - OK
ppl         - 0.11.2-4           - #645003 (and DEB_STAGE=stage1)
cloog-ppl   - 0.15.9-3           - OK
libelf      - 0.8.13-3           - OK
libmpc      - 0.9-4              - DEB_BUILD_OPTIONS=nocheck
base-files  - 6.5                - OK
base-passwd - 3.5.23             - OK
binutils    - 2.21.90.20111004-2 - OK
gcc-4.6     - 4.6.1-15           - #645018 #645021 STUCK HERE


After doing this now have a much larger list of "-X" options that need to be passed to dpkg-cross when installing headers and libraries for cross-building:


-X libc-bin -X libc-dev-bin -X multiarch-support -X dpkg -X install-info -X ncurses-bin -X texinfo -X make -X python


Cheers,
Kyle Moffett

2011-10-09

Using qemu-user-static to help the Debian e500 bootstrap

This is part of the Debian PowerPC e500 porting effort, the series on my blog starts at: "How to bootstrap a new Debian port"

I was trying to figure out an easy way to do basic testing without directly having access to the hardware and I discovered that QEMU supports several MPC85xx processor variants for its user-mode emulation.  The standard "qemu-user-static" package even allows you to trivially run non-native programs (either in a chroot or on your normal system) without much complexity.

Unfortunately, I could not figure out any way to convince QEMU to pick the right CPU type by default, especially since there might not be any reasonable config files in the chroot.  The solution ended up being to add a second binary alongside the normal "/usr/bin/qemu-ppc-static" file.  I wrote the following short little C program:

  #include <stdlib.h>
  #include <unistd.h>


  #define QEMU_BIN "/usr/bin/qemu-ppc-static"
  #define CPU_TYPE "MPC8548E_v21"


  int main(int argc, char **argv, char **envp)
  {
          int i;


          char **newargv = malloc(sizeof(*newargv) * (argc + 3));
          if (newargv) {
                  newargv[0] = QEMU_BIN;
                  newargv[1] = "-cpu";
                  newargv[2] = CPU_TYPE;
                  for (i = 1; i < argc; i++)
                          newargv[i + 2] = argv[i];
                  execve(QEMU_BIN, newargv, envp);
          }
          exit(255);
  }


Then I compiled it like this and put it in /usr/local/bin: (UPDATE: Fixed options for static compile)
  $ gcc -static -Wall -Wextra -Werror -ggdb3 -o qemu-e500v2-static qemu-e500v2-static.c
  $ sudo install qemu-e500v2-static /usr/local/bin/


Next I installed the Debian package "qemu-user-static" on my dev system and disabled the previously-loaded PPC support: (UPDATE: Diverted somewhere the init script won't find it)
  $ sudo aptitude install qemu-user-static binfmt-support
  $ sudo update-binfmts --package qemu-user-static \
            --remove qemu-ppc /usr/bin/qemu-ppc-static
  $ sudo dpkg-divert --divert /usr/share/binfmt.diverted.qemu-ppc \
            --local --rename --add /usr/share/binfmts/qemu-ppc


Then I needed to modify the existing PPC handler for e500v2 (and my custom C program)
  $ cp /usr/share/binfmt.diverted.qemu-ppc ~/qemu-e500v2.binfmt
  $ vim ~/qemu-e500v2.binfmt



The resulting file should look somewhat like this (the flags/offset/magic/mask are unmodified from the original):
  package <local>
  interpreter /usr/local/bin/qemu-e500v2-static
  flags: OC
  offset: 0
  magic \x7fELF......stuff....
  mask \xff\xff\xff\xff.........stuff.....

Then you just need to load your new version and off you go:
  $ sudo update-binfmts --import ~/qemu-e500v2.binfmt
  $ LD_LIBRARY_PATH=/usr/powerpc-linux-gnuspe/lib \
            /usr/powerpc-linux-gnuspe/lib/ld.so.1
  Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]
  [...]


With the rest of the multiarch support slowly going into Debian, this seems extremely promising to me for being able to avoid a lot of the classic cross-build hassle by doing pretend-native builds with a cross-compiler and a bunch of native headers and other tools.  Eventually you will also be able to have a native-architecture-only chroot with only those two binaries (the qemu-e500v2-static and the qemu-ppc-static) in it.

Unfortunately not enough of multiarch is working yet to really make it 100% feasible, but it should at least allow me to work around many of the egregious cross-compiling bugs by actually being able to run the compiled binaries locally.

On the other hand, if my goal was instead to actually identify and fix such cross-compiling bugs, then I would probably need to disable the qemu binfmt lest I get falsely successful builds.

The more likely use-case is that I will use this to perform some basic testing of my freshly built packages when I don't have direct hardware access.

Cheers,
Kyle Moffett

2011-10-08

Still waiting for Google Apps accounts to support "Google Profiles"

With all the hype about "Google+" I would love to give it a shot... but there's one teensy tiny problem:

The lack of a Google Profile makes it impossible to sign up for Google+, and it has been this way for months.  I already have waaay too many accounts to keep track of, so I refuse to create a separate Gmail account just for that one service.  Google keeps promising that it's coming, but it's been quite a while since they said:
We're actively working on making Profiles (and Google+) available for Google Apps - it should be available in the coming months  –  John Costigan @ Jun 28, 2011
Here's hoping that it will be sometime soon!

Cheers,
Kyle Moffett

Debian PowerPC e500v2 port, part 3

This is part of the Debian PowerPC e500 porting effort, the series on my blog starts at: "How to bootstrap a new Debian port"

Before we can actually start cross-compiling packages, we need to create a quick set of symlinks so that they can find our compiler.  The "gcc-4.6" packages we built in the previous steps created a set of tools named like this:
powerpc-linux-gnuspe-gcc-4.6
powerpc-linux-gnuspe-g++-4.6
Unfortunately, by default autoconf won't actually find those, and the "gcc-defaults" package does not have a cross-compiler mode (although it can be cross-"compiled", as we will need to do later).  So symlink the relevant binaries to versions without the "-4.6" at the end:
$ cd /usr/bin
$ for i in powerpc-linux-gnuspe-*-4.6; do sudo ln -s "$i" "${i%-4.6}"; done

So the next step is to make sure I have all of the Essential and Build-Essential packages up-to-date for installation into a usable root filesystem for building everything else.  That means I need to figure out a list of those packages first.

To make this easier, we can use the "grep-dctrl" tool to look through the APT package cache on our favorite Debian box.  MAKE SURE YOU USE A BOX WITH DEBIAN TESTING/UNSTABLE.  If you don't then you won't get the right package lists for your new port.

Let's first start with the "Essential: yes" packages:
$ sudo apt-get install grep-dctrl
$ grep-available -Xn -s Package -FEssential 'yes' >new-pkgs.txt

Now add "build-essential" to the list and get ready to list dependencies:
$ echo 'build-essential' >>new-pkgs.txt
$ : >all-pkgs.txt

Then we need to recursively follow dependencies.  It's all basically done with the following scriptlet:
$ while [ -s new-pkgs.txt ]; do \
      cat new-pkgs.txt >>all-pkgs.txt; \
      for i in $(cat new-pkgs.txt); do \
          grep-available -PXn -s Depends,PreDepends "$i"; \
      done | sed -e 's/([^)]\+)//g' -e 's/, /\n/g' \
          -e 's/ *|[^\n]*//g' | grep . | sort | uniq >dep-pkgs.txt; \
      cat dep-pkgs.txt all-pkgs.txt all-pkgs.txt \
          | sort | uniq -u >new-pkgs.txt; \
  done
Once that's done running (it should take ~30 seconds), you will have the complete binary package list in all-pkgs.txt.  Now we need to find all the source packages necessary to build those binary packages:
$ for i in $(cat all-pkgs.txt); do \
      grep-available -PXn -sSource:Package "$i"; \
  done | sed -e 's/ (.*//' | sort | uniq >all-srcs.txt
Go ahead and use the resulting all-srcs.txt file to make yourself a checklist, because the rest of this is going to be a painfully long and manual process.  I've included my list below, wrapped onto a single line to minimize wasted space:
base-files base-passwd bash binutils build-essential bzip2 coreutils dash db debconf debianutils diffutils dpkg e2fsprogs eglibc findutils gcc-4.6 gcc-defaults gdbm gmp grep gzip hostname insserv libselinux libsepol libtimedate-perl linux-2.6 lsb make-dfsg mpclib mpfr4 ncurses patch perl sed sensible-utils shadow sysvinit tar tzdata util-linux xz-utils zlib
Not too unreasonable, right?  What you will rapidly realize is that build-dependencies are the key, and we have not actually tried to list those out yet.  The biggest problem tends to be docs-generation tools (EG: LaTeX, Doxygen, etc) which are entirely unnecessary for bootstrap purposes but have lots of dependencies of their own (EG: xorg, qt4, etc).

So let's pick one of these and get started.  I've included the precise versions I used below, but you can just leave off the "=1.4-1" bit to get the latest unstable version assuming your APT is set up correctly.
$ mkdir gzip && cd gzip && apt-get source gzip=1.4-1
First you should check the "Build-Depends" field in the "debian/control" file, to make sure you have all of the necessary dependencies.  Note that some dependencies (automake, autoconf, texinfo, etc) should be satisfied by your build-system architecture (EG: amd64), while others (libc6, etc) should be satisfied by "-cross" packages for your target architecture.
$ grep Build-Depends: gzip-1.4/debian/rules
Build-Depends: debhelper (>= 5), texinfo, autoconf, automake, autotools-dev
 Ok, everything looks good there.  Now check the "debian/rules" file to check for the following few issues:

  1. The rules should reference DEB_HOST_GNU_TYPE to talk about the target system.  If it seems to use DEB_BUILD_GNU_TYPE for that then it's probably broken.
  2. Any testsuites should be disabled when DEB_HOST_GNU_TYPE != DEB_BUILD_GNU_TYPE, otherwise the build will likely fail.  You may be able to work around these kinds of issues by setting DEB_BUILD_OPTIONS=nocheck.
There are certainly lots of other ways that packages can fail to cross-compile correctly, but if it uses autoconf/automake and either cdbs or debhelper then it should be mostly OK.  The next step is to try a cross-compile:
$ ( cd gzip-1.4 && dpkg-buildpackage -a"${MYARCH}" -us -uc -B ) 2>&1 | tee build-gzip.log
Even if the build finishes successfully, you should use "lintian" and "dpkg-deb -c" to verify that the package files look correct.  If you have any errors or unexpected package contents then you have some serious work to do to figure out why and fix the package.  In the "gzip" case I identified a minor bug (Debian bug #644785) in the packaging which resulted in one particular setting coming from the build-system instead of from the host.

NOTE: If you have to make any changes at all, make sure you generate a nice patch and submit it back to Debian with the "reportbug" tool.

Once you have the package built, you should check to see if it resulted in any library packages (lib* and lib*-dev).  If so, you should try to get those installed with "dpkg-cross" the same way that the eglibc ones were installed previously, as you may need them to satisfy other cross-build dependencies later on.

That's it for tonight!

Cheers,
Kyle Moffett

Debian PowerPC e500v2 port, part 2

Well, I've been working again on the Debian powerpcspe port and there is a lot more progress to be had! (This series starts at: "How to bootstrap a new Debian port")

I left off last time after EGLIBC failed to build with errors about undefined references to "__stack_chk_guard".  It turns out the problem is that EGLIBC does not correctly detect the presence of support for the "-fstack-protector" GCC option, as per Debian bug #644662.  The fix is to download and apply this patch, which fixes the configure script test.

The second issue I ran into is that dpkg-gensymbols is not very good at finding all the relevant multi-arch libraries while trying to build packages, as per Debian bug #595144.  The fix there is an existing patch to the "dpkg" source package by Steve Langasek; it changes the "libdpkg-perl" binary package to fix the dpkg-gensymbols tool.

As a side note, it turns out that my previous gcc-4.6-cross-stage1-dep-fix-v2.patch broke non-bootstrap-stage builds of GCC.  As a result, I've posted a new version to Debian bug #644439; this one should handle native, cross, and cross-bootstrap builds fine although it's still undergoing compile tests here.

The final issue with the EGLIBC build is that it tries to build the "locales-all" package by executing the built binaries, which of course fails for cross-compiled EGLIBC (see Debian bug #644771).  The fix is trivial, simply don't build "locales-all" when cross-compiling, found in this patch.

So before we can retry building EGLIBC, we need to build an updated libdpkg-perl for our build host:

Step 6.1 - Building and installing a patched libdpkg-perl:
$ sudo apt-get build-dep dpkg=1.16.1
$ sudo apt-get source dpkg=1.16.1
$ curl -o 'Dpkg-Shlibs.pm-multiarch-search-paths.patch' \
  'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=595144;msg=37;att=1'
$ patch -d dpkg-1.16.1 -p1 <Dpkg-Shlibs.pm-multiarch-search-paths.patch
$ ( cd dpkg-1.16.1 && dpkg-buildpackage -b -us -uc ) 2>&1 | tee dpkg.log
$ sudo dpkg -i libdpkg-perl_1.16.1_all.deb
Going back to the EGLIBC commands I listed previously for step 6, here is an updated version:

Step 6.2 - Commands to build a stage2 EGLIBC:
$ sudo apt-get build-dep eglibc=2.13-21
$ apt-get source eglibc=2.13-21
$ curl -o 'eglibc-2.13-cross-stage1-support.patch' \
  'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=644546;msg=5;att=1'
$ curl -o 'eglibc-fix-ssp-detection.patch' \
  'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=644662;msg=5;att=1'
$ curl -o 'eglibc-disable-cross-locales-all.patch' \
  'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=644771;msg=5;att=1'
$ patch -d eglibc-2.13 -p1 <eglibc-2.13-cross-stage1-support.patch
$ patch -d eglibc-2.13 -p1 <eglibc-fix-ssp-detection.patch
$ patch -d eglibc-2.13 -p1 <eglibc-disable-cross-locales-all.patch... MAKE ANY OTHER CHANGES TO EGLIBC HERE ...
$ ( cd eglibc-2.13 && DEB_GCC_VERSION=-4.6 \
      dpkg-buildpackage -a"${MYARCH}" -B -us -uc ) 2>&1 \
      | tee eglibc-stage2.log
Once the build finishes, it will have produced a bunch of deb files, but you only actually need the libc6 and libc6-dev packages.  As before, we will eventually be able to install foreign architecture packages but for now we have to forcibly dpkg-cross them (with a few ignored dependencies).

Step 6.3 - Commands to install the stage2 EGLIBC:
$ sudo dpkg-cross -M -a "${MYARCH}" -X libc-bin -X libc-dev-bin -i \
      "libc6_2.13-21_${MYARCH}.deb" 
"libc6-dev_2.13-21_${MYARCH}.deb"
After this completes we have a fully usable C library for our target architecture, and it's time for the final GCC cross-compiler build with all features enabled.

Step 7.1 - Commands to build a final full-featured GCC:
$ sudo apt-get build-dep gcc-4.6=4.6.1-13
$ apt-get source gcc-4.6=4.6.1-13
... MAKE ANY CHANGES TO GCC HERE ...
$ ( cd gcc-4.6-4.6.1 && DEB_GCC_TARGET="${MYARCH}" DEB_STAGE=stage2 \
  dpkg-buildpackage -b -us -uc ) 2>&1 | tee gcc-4.6-stage2.log
The final GCC build leaves about 23 packages lying around in the directory, and you should probably install all of them.

Step 7.2 - Command to install the final GCC:
$ sudo dpkg -i $(dcmd --deb gcc-4.6_4.6.1-13_*.changes)

NOTE: DO NOT UPLOAD ANY OF THE PACKAGES YOU BUILT!!!  They intentionally deviate from standard in various ways due to the cross-building process and you should wait until you can rebuild them natively before uploading.

Cheers,
Kyle Moffett

2011-10-06

How to bootstrap a new Debian port

Ok... This is is kind of a funny way to start a blog, but it's the first really serious content that I felt like posting, so here goes!

I've been working on a Debian port for the e500v2 architecture "powerpcspe", which has a rather odd way of doing floating point compared to normal PowerPC systems.

Just recently I've submitted a bunch of Debian bugs for different pieces of the bootstrap process that were rather tedious, in the hope that someone doing a new architecture port in the future might benefit. To have a central place for the entire procedure (ideally one that Google can find easily), I'm posting it all here.


The first step is to figure out your architecture triplet and get that added to dpkg as a new target.  For example, the "powerpcspe" architecture uses the target triplet "powerpc-linux-gnuspe".

Temporarily you can modify the following files to get a local system to recognize a new architecture, but before you ship you should get the dpkg maintainers to add it upstream:
/usr/share/dpkg/archtable
/usr/share/dpkg/cputable
/usr/share/dpkg/triplettable
So let's set these shell variables:
$ unset MYARCH MYTRIPLET TARGET
$ MYARCH=powerpcspe
$ MYTRIPLET="$(dpkg-architecture -a"$MYARCH" -qDEB_HOST_GNU_TYPE)"
NOTE: You will see a warning that your GNU system type does not match your GCC system type.  This is OK, and part of cross-compiling.

Then you need to bootstrap a cross-compiler toolchain with that triplet:

  1. Build binutils (assembler, linker, etc)
  2. Perform a headers-only Linux Kernel build
  3. Build a minimal C-only GCC using just the target's kernel headers
  4. Build headers and run-time objects using the minimal GCC
  5. Build a secondary C-only GCC using the target's EGLIBC headers
  6. Build a full EGLIBC using the secondary C-only GCC
  7. Build a final GCC using the full EGLIBC

Later, if you need to rebuild the tools you can skip steps 3-5, as you will
already have a usable target GLIBC and target headers to start from.

Step 1 - Commands to build and install a cross-binutils:
$ sudo apt-get build-dep binutils=2.21.90.20111004-1
$ apt-get source binutils=2.21.90.20111004-1
... MAKE ANY CHANGES TO BINUTILS HERE ...
$ ( cd binutils-2.21.90.20111004 && TARGET="${MYTRIPLET}" \
          dpkg-buildpackage -b -us -uc ) 2>&1 | tee binutils-build.log
$ sudo dpkg -i "binutils-${MYTRIPLET}_2.21.90.20111004-1_amd64.deb"
Step 2 - Commands to download and modify Linux Kernel headers:
$ sudo apt-get build-dep linux-2.6=3.0.0-3
$ apt-get source linux-2.6=3.0.0-3
$ pushd linux-2.6-3.0.0
$ vim debian/config/defines ## Add "${MYARCH}" to list
$ cp -a debian/config/{powerpc,"${MYARCH}"}
$ vim debian/config/"${MYARCH}"/* ## Make it work
... MAKE ANY OTHER CHANGES TO THE LINUX KERNEL HERE ...
## THE NEXT COMMAND FAILS WITH A WARNING MESSAGE, THAT IS OK!!!
$ dpkg-buildpackage -a"${MYARCH}" -b -us -uc -T"debian/control-real"
Step 2.1 - You will need to edit the "debian/rules
" Makefile in the Debianized linux-2.6 sources and append the following text at the end:

.PHONY: FORCE
binary-%: FORCE
dh_testdir
$(MAKE) -f debian/rules.gen binary-$*_$(DEB_HOST_ARCH)
Step 2.2 - Commands to actually build Linux Kernel headers:
$ dpkg-buildpackage -a"${MYARCH}" -b -us -uc -Tsource
$ dpkg-buildpackage -a"${MYARCH}" -b -us -uc -Tbinary-libc-dev \
          --as-root -rfakeroot
$ popd
FIXME: Right now 2011/10/05 dpkg in testing/unstable does not support installing packages from foreign architectures, so we have to run the following command to forcibly convert the linux-libc-dev package with dpkg-cross.  Eventually "foreign-architecture ${MYARCH}" in your /etc/dpkg/dpkg.cfg file will be enough to make "dpkg -i" just work.

Step 2.3 - Command to install the Linux Kernel Headers:
$ sudo dpkg-cross -M -a "${MYARCH}" -i \
        "linux-libc-dev_3.0.0-3_${MYARCH}.deb"
Alternate Step 2.3 (UNTESTED) - Eventually (with full multiarch dpkg, already in some Ubuntu) you will just use this command:
$ sudo dpkg -i "linux-libc-dev_3.0.0-3_${MYARCH}.deb"
FIXME: The GCC stage1 build has a bug right now (Debian Bug #644439) which causes the gcc-4.6-powerpc-linux-gnuspe package to falsely depend on a libgcc-powerpcspe-cross package which is not part of a stage1 build.

Until that bug is fixed upstream, you will need to apply this patch to the GCC sources or it won't install (included in commands below)  (UPDATE!)  The old patch breaks native builds, use this one instead.

Step 3 - Commands to build a minimal stage1 GCC:
$ sudo apt-get build-dep gcc-4.6=4.6.1-13
$ apt-get source gcc-4.6=4.6.1-13
$ curl -o 'gcc-4.6-cross-stage1-dep-fix-v2.patch' \
  'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=644439;msg=30;att=1'
$ patch -d gcc-4.6-4.6.1 -p1 <gcc-4.6-cross-stage1-dep-fix-v3.patch
... MAKE ANY OTHER CHANGES TO GCC HERE ...
$ ( cd gcc-4.6-4.6.1 && DEB_GCC_TARGET="${MYARCH}" DEB_STAGE=stage1 \
    dpkg-buildpackage -b -us -uc ) 2>&1 | tee gcc-4.6-stage1.log
$ sudo dpkg -i "cpp-4.6-${MYTRIPLET}_4.6.1-13_amd64.deb"
$ sudo dpkg -i "gcc-4.6-${MYTRIPLET}_4.6.1-13_amd64.deb"
FIXME: The EGLIBC debian package does not actually have a way to build this as a part of a minimal package file (see Debian Bug #644546), so we need to apply this patch that lets us build stage1 packages.

Step 4 - Commands to build EGLIBC headers and run-time objects
$ sudo apt-get build-dep eglibc=2.13-21
$ apt-get source eglibc=2.13-21
$ curl -o 'eglibc-2.13-cross-stage1-support.patch' \
  'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=644546;msg=5;att=1'
$ patch -d eglibc-2.13 -p1 <eglibc-2.13-cross-stage1-support.patch
... MAKE ANY OTHER CHANGES TO GLIBC HERE ...
$ ( cd eglibc-2.13 && DEB_GCC_VERSION=-4.6 DEB_STAGE=stage1 \
    dpkg-buildpackage -a"${MYARCH}" -b -us -uc ) 2>&1 \
    | tee eglibc-stage1.log
FIXME: Right now 2011/10/05 dpkg in testing/unstable does not support installing packages from foreign architectures, so we have to run the following command to forcibly convert the libc6-dev package with dpkg-cross.  Eventually "foreign-architecture ${MYARCH}" in your /etc/dpkg/dpkg.cfg file will be enough to make "dpkg -i" just work.

FIXME2: Additionally, this package currently has excess dependencies on nonexistent libc6 and libc-dev-bin packages.  Hopefully when the Debian EGLIBC maintainers merge the stage1-support patch, they will also fix the dependencies for stage1 packages.  Until then, the dpkg-cross command includes "-X libc6 -X libc-dev-bin".

Step 4.1 - Command to install the EGLIBC headers and run-time objects:
$ sudo dpkg-cross -M -a "${MYARCH}" -X libc6 -X libc-dev-bin \
-i "libc6-dev_2.13-21_${MYARCH}.deb"
Alternate Step 4.1 (UNTESTED, BROKEN) - Eventually (with full multiarch dpkg, and the dependencies fixed) you will just use this command:
$ sudo dpkg -i "libc6-dev_2.13-21_${MYARCH}.deb"
Step 5 - Commands to build and install a stage2 GCC:
$ sudo apt-get build-dep gcc-4.6=4.6.1-13
$ apt-get source gcc-4.6=4.6.1-13
... MAKE ANY CHANGES TO GCC HERE ...
$ ( cd gcc-4.6-4.6.1 && DEB_GCC_TARGET="${MYARCH}" DEB_STAGE=stage2 \
  dpkg-buildpackage -b -us -uc ) 2>&1 | tee gcc-4.6-stage2.log
$ sudo dpkg -i "gcc-4.6-${MYTRIPLET}-base_4.6.1-13_amd64.deb"
$ sudo dpkg -i "libgcc1-${MYARCH}-cross_4.6.1-13_all.deb"
$ sudo dpkg -i "libgcc1-dbg-${MYARCH}-cross_4.6.1-13_all.deb"
$ sudo dpkg -i "gcc-4.6-${MYTRIPLET}_4.6.1-13_amd64.deb"
$ sudo dpkg -i "cpp-4.6-${MYTRIPLET}_4.6.1-13_amd64.deb"

FIXME: The same EGLIBC patch as is used above still needs to be applied or the DEB_GCC_VERSION variable will not work (see Debian Bug #644546).

Step 6 - Commands to build a final EGLIBC (UPDATE: Known to be broken):
$ sudo apt-get build-dep eglibc=2.13-21
$ apt-get source eglibc=2.13-21
$ curl -o 'eglibc-2.13-cross-stage1-support.patch' \
  'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=644546;msg=5;att=1'
$ patch -d eglibc-2.13 -p1 <eglibc-2.13-cross-stage1-support.patch
... MAKE ANY OTHER CHANGES TO GLIBC HERE ...
$ ( cd eglibc-2.13 && DEB_GCC_VERSION=-4.6 \
      dpkg-buildpackage -a"${MYARCH}" -b -us -uc ) 2>&1 \
      | tee eglibc-final.log
FIXME:  Unfortunately I'm stuck here for today...  This EGLIBC build fails with errors about undefined references to "__stack_chk_guard", presumably because it's being built with a stripped-down GCC that does not have those features enabled.  I can only assume that either the stage2 GCC needs to have some additional features turned on or there needs to be an extra round of EGLIBC build after the full GCC is working.

(UPDATE: See "Debian PowerPC e500v2 port, part 2" for further progress.)

Cheers,
Kyle Moffett