Troubleshooting
Compile iproute2
To cross compile from aarch64 to x86_64, you need to specify some environments before compilation:
make CC=x86_64-linux-gnu-gcc LD=x86_64-linux-gnu-ld HOSTCC=gcc LDFLAGS=-static -j`nproc`
You may encounter a situation where the compiler complains that it cannot find the definitions of certain symbols, many of which are in libz. To resolve it, you just need to add a signle line in iproute2-main/Makefile
.
[...]
LIBNETLINK=../lib/libutil.a ../lib/libnetlink.a
+ LIBNETLINK+=/usr/lib/x86_64-linux-gnu/libz.a
[...]
Another issue is that modules, such as veth, are optionally supported, so they are compiled as .so files. The ip
then loads these .so files at runtime using dlopen()
. You can see how it works in iproute2/ip/iplink.c
.
However, this techique doesn’t work if the user compiles ip
to a static binary, even though these modules are actually compiled into ip
. You can define a constructor in iproute2/ip/iplink.c
to manually link these the exported link_util
objects, allowing ip
to function correctly.
// [...]
extern struct link_util veth_link_util;
void init_func(void) __attribute__((constructor));
void init_func(void) {
struct link_util *l;
l = &veth_link_util;
l->next = linkutil_list;
linkutil_list = l;
}
// [...]
Modifying the iproute2/tc/tc.c
file in the same way to fix the tc
binary.
// [...]
extern struct qdisc_util netem_qdisc_util;
void init_func(void) __attribute__((constructor));
void init_func(void) {
struct qdisc_util *l;
l = &netem_qdisc_util;
l->next = qdisc_list;
qdisc_list = l;
}
// [...]
Compile iputils
LDFLAGS=-static meson setup builddir --cross-file ./meson.cross -DUSE_CAP=false
The file meson.cross
is like:
[binaries]
c = 'x86_64-linux-gnu-gcc'
pkgconfig = 'x86_64-linux-gnu-pkg-config'
[host_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
To rebuild, you need to remove directory builddir/
.
Compile libmnl & libnftnl
# 1. libmnl
cd ./libmnl-1.0.5
./configure --host=x86_64-linux-gnu --enable-static --prefix=<output_path>
make -j`nproc`
# 2. lbnftnl
cd ./libnftnl-1.2.5
./configure --host=x86_64-linux-gnu --enable-static --prefix=<output_path>
make -j`nproc`
# 3. compile with other file
x86_64-linux-gnu-gcc -o test test.c -L./libnftnl_build/<output_path>/lib \
-L./libmnl_build/<output_path>/lib \
-I./libnftnl_build/libnftnl-1.2.5/include \
-I./libmnl_build/libmnl-1.0.5/include -static -lnftnl -lmnl
Ubuntu source list
The file /etc/apt/sources.list
specifies the repositories from which the system can download software packages.
deb http://ports.ubuntu.com/ubuntu-ports lunar main restricted universe multiverse
deb-src http://ports.ubuntu.com/ubuntu-ports lunar main restricted universe multiverse
In some cases, you may want to add support for multiple architecture. To do this, you need to perform two steps. First, use the [arch=]
option to tell Ubuntu which repositories are used for different architectures.
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports lunar main restricted universe multiverse
deb-src [arch=arm64] http://ports.ubuntu.com/ubuntu-ports lunar main restricted universe multiverse
Next, you must add the desired architecture to package manager. The architecture for host is already included by default.
sudo dpkg --add-architecture arm64
sudo apt update
Normally, you don’t need to update the source file once it’s set up. However, some non-LTS releases rearched End of Life very fast quickly, and in such cases, the original repositories URLs may be changed.
In the case I encountered, I updated the URL from http://ports.ubuntu.com/ubuntu-ports/
to http://old-releases.ubuntu.com/ubuntu/
, the apt
command worked normally afterward.
Custom Kernel Module
If the kernel is compiled with CONFIG_SECURITY_LOADPIN
, the LoadPin subsystem will be enabled and block all external kernel modules. You can add parameter loadpin.inforce=0
in boot command line to disable it.