Notes on cross compiling for ARM PowerPMAC#

Linker Flags#

To make sure the binary will run when copied across to the ppmac, the ARM libs are copied as well, but they will not be used by default. Linker flags are provided to embed the dynamic linker and the library paths within the binary. These are:

  • -Wl,--disable-new-dtags,-rpath | Set search paths for libraries

  • -Wl,-dynamic-linker | Set dynamic linker

The --disable-new-dtags flag is used to set RPATH rather than RUNPATH, which seems to be necessary to acheive the desired behaviour when running on the ppmac. The binary can be inspected with readelf to confirm the RPATH is set:

root@172.23.107.175:/opt/ppmac# readelf -d /root/prefix/bin/pmacFilterControl

Dynamic section at offset 0x8fbc8 contains 36 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libzmq.so.5]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libppmac.so]
 0x00000001 (NEEDED)                     Shared library: [libpthread_rt.so.1]
 0x00000001 (NEEDED)                     Shared library: [libxenomai.so.0]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x00000001 (NEEDED)                     Shared library: [ld-linux-armhf.so.3]
 0x0000000f (RPATH)                      Library rpath: [/root/prefix/lib/:/root/libzmq/prefix/lib/:/root/lib]
...

ldd is also useful to see what the flags change:

  • With the correct flags (and the application runs without setting LD_LIBRARY_PATH):

root@172.23.107.175:/opt/ppmac# ldd /root/prefix/bin/pmacFilterControl
    libzmq.so.5 => /root/libzmq/prefix/lib/libzmq.so.5 (0x76e4a000)
    libpthread.so.0 => /root/lib/libpthread.so.0 (0x76e24000)
    libppmac.so => /root/prefix/lib/libppmac.so (0x76ab9000)
    libpthread_rt.so.1 => /root/prefix/lib/libpthread_rt.so.1 (0x76a9f000)
    libxenomai.so.0 => /root/prefix/lib/libxenomai.so.0 (0x76a89000)
    libstdc++.so.6 => /root/lib/libstdc++.so.6 (0x7693f000)
    libgcc_s.so.1 => /root/lib/libgcc_s.so.1 (0x76916000)
    libc.so.6 => /root/lib/libc.so.6 (0x76817000)
    /root/lib/ld-linux-armhf.so.3 => /lib/ld-linux-armhf.so.3 (0x54b12000)
    libdl.so.2 => /root/lib/libdl.so.2 (0x76804000)
    libmath.so => /opt/ppmac/libmath/libmath.so (0x767e5000)
    librt.so.1 => /root/lib/librt.so.1 (0x767ce000)
    libm.so.6 => /root/lib/libm.so.6 (0x76765000)
root@172.23.107.175:/opt/ppmac# /root/prefix/bin/pmacFilterControl
Must pass control_port and data_endpoint - e.g. '10000 127.0.0.1:10000'
  • Without --disable-new-dtags:

root@172.23.107.175:/opt/ppmac# ldd /root/prefix/bin/pmacFilterControl
/root/prefix/bin/pmacFilterControl: /lib/arm-linux-gnueabihf/libm.so.6: version GLIBC_2.29 not found (required by /root/lib/libstdc++.so.6)
    libzmq.so.5 => /root/libzmq/prefix/lib/libzmq.so.5 (0x76e1e000)
    libpthread.so.0 => /root/lib/libpthread.so.0 (0x76df8000)
    libppmac.so => /root/prefix/lib/libppmac.so (0x76a8d000)
    libpthread_rt.so.1 => /root/prefix/lib/libpthread_rt.so.1 (0x76a73000)
    libxenomai.so.0 => /root/prefix/lib/libxenomai.so.0 (0x76a5d000)
    libstdc++.so.6 => /root/lib/libstdc++.so.6 (0x76913000)
    libgcc_s.so.1 => /root/lib/libgcc_s.so.1 (0x768ea000)
    libc.so.6 => /root/lib/libc.so.6 (0x767eb000)
    /root/lib/ld-linux-armhf.so.3 => /lib/ld-linux-armhf.so.3 (0x54b36000)
    libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0x767d2000)
    libmath.so => /opt/ppmac/libmath/libmath.so (0x767b3000)
    librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0x7679c000)
    libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76728000)
  • Without rpath or dynamic linker set:

root@172.23.107.175:/opt/ppmac# ldd /root/prefix/bin/pmacFilterControl
/root/prefix/bin/pmacFilterControl: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version GLIBCXX_3.4.22 not found (required by /root/prefix/bin/pmacFilterControl)
/root/prefix/bin/pmacFilterControl: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version GLIBCXX_3.4.21 not found (required by /root/prefix/bin/pmacFilterControl)
	libzmq.so.5 => not found
	libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0x76e95000)
	libppmac.so => not found
	libpthread_rt.so.1 => /usr/xenomai/lib/libpthread_rt.so.1 (0x76e7b000)
	libxenomai.so.0 => /usr/xenomai/lib/libxenomai.so.0 (0x76e65000)
	libstdc++.so.6 => /usr/lib/arm-linux-gnueabihf/libstdc++.so.6 (0x76dae000)
	libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0x76d84000)
	libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76c94000)
	/lib/ld-linux-armhf.so.3 (0x54b3c000)
	librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0x76c7e000)
	libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76c0a000)

Wrapped symbols#

The ppmac libraries are linked using the flags -Wl,--wrap,<function>, which invoke some linker magic to allow the linker to ignore resolving the given symbol and it can then be provided by another library when linking the final binary. This seems to be used to patch kernel functions with real-time code using xenomai. Client applications must be linked against these xenomai libs - without it gcc will give link errors such as, e.g., libppmac.so: undefined reference to __wrap_listen.

Example build through Power PMAC IDE#

The following snippet from the build log in the PowerPMAC IDE shows these flags being used and linking against xenomai.

arm-omron49-linux-gnueabihf-gcc -mhard-float -funsigned-char --sysroot=/opt/armv71-4.1.18-ipipe -I/usr/local/dtlibs/rtpmac -I/usr/local/dtlibs/libppmac -I/usr/local/dtlibs/libopener -I/opt/armv71-4.1.18-ipipe/usr/xenomai/include -I/opt/armv71-4.1.18-ipipe/usr/xenomai/include/posix  -I/usr/local/dtlibs/libmath -D_GNU_SOURCE -D_REENTRANT -D__XENO__  -DOPENER_SUPPORT_64BIT_DATATYPES  -g3 -c capp1.c -o capp1.o
arm-omron49-linux-gnueabihf-gcc -o "../../../Bin/Debug/capp1.out" capp1.o -ldl -lppmac -lpthread_rt -lxenomai -lpthread -lgcc_s -lmath -lm -L/usr/local/dtlibs/libmath --sysroot=/opt/armv71-4.1.18-ipipe -L../../../Bin/Debug/ -L/opt/armv71-4.1.18-ipipe/usr/xenomai/lib -L/usr/local/dtlibs/libppmac -L/usr/local/dtlibs/rtpmac -Wl,-rpath,/var/ftp/usrflash/Project/C\ Language/Libraries -Wl,-rpath,/var/ftp/usrflash/Project/Bin/Debug -Wl,-rpath,/opt/ppmac/libppmac -Wl,-rpath,/opt/ppmac/libmath -Wl,-rpath-link,/opt/armv71-4.1.18-ipipe/lib/arm-linux-gnueabihf -Wl,--wrap,shm_open -Wl,--wrap,pthread_create -Wl,--wrap,pthread_create -Wl,--wrap,pthread_setschedparam -Wl,--wrap,pthread_getschedparam -Wl,--wrap,pthread_yield -Wl,--wrap,sched_yield -Wl,--wrap,pthread_kill -Wl,--wrap,sem_init -Wl,--wrap,sem_destroy -Wl,--wrap,sem_post -Wl,--wrap,sem_timedwait -Wl,--wrap,sem_wait -Wl,--wrap,sem_trywait -Wl,--wrap,sem_getvalue -Wl,--wrap,sem_open -Wl,--wrap,sem_close -Wl,--wrap,sem_unlink -Wl,--wrap,clock_getres -Wl,--wrap,clock_gettime -Wl,--wrap,clock_settime -Wl,--wrap,clock_nanosleep -Wl,--wrap,nanosleep -Wl,--wrap,pthread_mutexattr_init -Wl,--wrap,pthread_mutexattr_destroy -Wl,--wrap,pthread_mutexattr_gettype -Wl,--wrap,pthread_mutexattr_settype -Wl,--wrap,pthread_mutexattr_getprotocol -Wl,--wrap,pthread_mutexattr_setprotocol -Wl,--wrap,pthread_mutexattr_getpshared -Wl,--wrap,pthread_mutexattr_setpshared -Wl,--wrap,pthread_mutex_init -Wl,--wrap,pthread_mutex_destroy -Wl,--wrap,pthread_mutex_lock -Wl,--wrap,pthread_mutex_trylock -Wl,--wrap,pthread_mutex_timedlock -Wl,--wrap,pthread_mutex_unlock -Wl,--wrap,pthread_condattr_init -Wl,--wrap,pthread_condattr_destroy -Wl,--wrap,pthread_condattr_getclock -Wl,--wrap,pthread_condattr_setclock -Wl,--wrap,pthread_condattr_getpshared -Wl,--wrap,pthread_condattr_setpshared -Wl,--wrap,pthread_cond_init -Wl,--wrap,pthread_cond_destroy -Wl,--wrap,pthread_cond_wait -Wl,--wrap,pthread_cond_timedwait -Wl,--wrap,pthread_cond_signal -Wl,--wrap,pthread_cond_broadcast -Wl,--wrap,mq_open -Wl,--wrap,mq_close -Wl,--wrap,mq_unlink -Wl,--wrap,mq_getattr -Wl,--wrap,mq_setattr -Wl,--wrap,mq_send -Wl,--wrap,mq_timedsend -Wl,--wrap,mq_receive -Wl,--wrap,mq_timedreceive -Wl,--wrap,mq_notify -Wl,--wrap,open -Wl,--wrap,socket -Wl,--wrap,close -Wl,--wrap,ioctl -Wl,--wrap,read -Wl,--wrap,write -Wl,--wrap,recvmsg -Wl,--wrap,sendmsg -Wl,--wrap,recvfrom -Wl,--wrap,sendto -Wl,--wrap,recv -Wl,--wrap,send -Wl,--wrap,getsockopt -Wl,--wrap,setsockopt -Wl,--wrap,bind -Wl,--wrap,connect -Wl,--wrap,listen -Wl,--wrap,accept -Wl,--wrap,getsockname -Wl,--wrap,getpeername -Wl,--wrap,shutdown -Wl,--wrap,timer_create -Wl,--wrap,timer_delete -Wl,--wrap,timer_settime -Wl,--wrap,timer_getoverrun -Wl,--wrap,timer_gettime -Wl,--wrap,ftruncate -Wl,--wrap,ftruncate64 -Wl,--wrap,close -Wl,--wrap,shm_open -Wl,--wrap,shm_unlink -Wl,--wrap,mmap -Wl,--wrap,mmap64 -Wl,--wrap,munmap -Wl,--wrap,select