Today I was messing around with Raspberry Pi Zero and initramfs, as a side effect of my latest article (Das U-Boot on Raspberry). My goal was to have a minimal working init in intramfs that would just print “Hello”, but instead I've been receiving kernel panics. Unfortunately this was only the first step to the hell.
The problem was not initramfs as I thought on the beginning, but incompatible ABI of the cross compiled init. I was kinda surprised as I used exactly the same cross toolchain (crossbuild-essential-armhf) as I did when compiling the kernel (which works super cool btw). Actually, any binary crossed compiled for RPiZ was giving me “Segmentation fault” error when run on the Pi.
It took me 3/4 of the day to find out what's going on. The architecture of RPiZ is armv6, while the cross toolchain was compiled for armv7. This can be easily checked by invoking the below command:
$ arm-linux-gnueabihf-gcc -v
Even when I used proper flags during compilation (like -march, -mcpu, -mfpu etc.), the problem was not in gcc itself, but in linker. Take a look at the readelf output of the compiled but not linked binary:
File Attributes Tag_CPU_name: "6" Tag_CPU_arch: v6 Tag_ARM_ISA_use: Yes Tag_THUMB_ISA_use: Thumb-1 Tag_FP_arch: VFPv2 Tag_ABI_PCS_wchar_t: 4 Tag_ABI_FP_denormal: Needed Tag_ABI_FP_exceptions: Needed Tag_ABI_FP_number_model: IEEE 754 Tag_ABI_align_needed: 8-byte Tag_ABI_align_preserved: 8-byte, except leaf SP Tag_ABI_enum_size: int Tag_ABI_VFP_args: VFP registers Tag_ABI_optimization_goals: Aggressive Debug Tag_CPU_unaligned_access: v6
As you see, everything says that this is an armv6 binary. And now let's see what will happen if we compile it with linking:
File Attributes Tag_CPU_name: "7-A" Tag_CPU_arch: v7 Tag_CPU_arch_profile: Application Tag_ARM_ISA_use: Yes Tag_THUMB_ISA_use: Thumb-2 Tag_FP_arch: VFPv3-D16 Tag_ABI_PCS_wchar_t: 4 Tag_ABI_FP_rounding: Needed Tag_ABI_FP_denormal: Needed Tag_ABI_FP_exceptions: Needed Tag_ABI_FP_number_model: IEEE 754 Tag_ABI_align_needed: 8-byte Tag_ABI_align_preserved: 8-byte, except leaf SP Tag_ABI_enum_size: int Tag_ABI_VFP_args: VFP registers Tag_CPU_unaligned_access: v6
The best solution for this, if you have to target older Pies or Zero, is to simply compile your own ARM GCC toolchain, and configure it for armv6.