Towards GNU/MINIX - Cross-compiler
![]() |
Cross-compiled executable running on Minix |
In this post, we will cross compile a binary on Linux using GNU tools and run the same in Minix with a minimal setup.
Build a generic cross-compiler
You can build a generic ELF compiler for x86 platform following the instructions here.
Copy C runtime files from the distribution CD. $PREFIX and $TARGET are variables set in previous step.
$ sudo mount /dev/mapper/loop0p3 -t minix /mnt
Create hello.c
#include <stdlib.h>
int
main(int argc, char *argv[])
{
printf("Hello\n");
return 0;
}
Compile and link hello.c . Use -static for static linking and -dynamic-linker /usr/libexec/ld.elf_so (use appropriate ld path) for dynamic linking.
$ i686-elf-ld -static -m elf_i386 -o hello -L./usr/lib ./usr/lib/crt0.o ./usr/lib/crti.o ./usr/lib/crtbegin.o ./usr/lib/crtn.o hello.o -lc ./usr/lib/crtend.o
Create copy.sh
mount /dev/mapper/loop0p2 -t minix /mnt
ls /mnt/bin/h* -als
rm /mnt/bin/hello*
cp hello /mnt/bin/
ls /mnt/bin/h* -als
umount /mnt
kpartx -d myos.iso
Copy the executable to CD image
Now you can boot the CD and run the command.
How is this useful?
This allows you to prepare a custom OS with only the tools that you need. You can make it as bare or as feature rich as you want.
Lessons Learnt
- Link Time Optimization (LTO) gives GCC the capability of dumping its internal representation (GIMPLE) to disk, so that all the different compilation units that make up a single executable can be optimized as a single module. This expands the scope of inter-procedural optimizations to encompass the whole program (or, rather, everything that is visible at link time).
- Most autoconf-based packages ship with a huge shell script called config.sub whose function is to disambiguate target triplet using a long list of known CPUs and known operating systems.
- GCC provides a low-level runtime library, libgcc.a or libgcc_s.so.1 on some platforms. GCC generates calls to routines in this library automatically, whenever it needs to perform some operation that is too complicated to emit inline code for.
- The C standard defines two different kinds of execution environments - "freestanding" and "hosted". A kernel is "freestanding"; everything you do in user space is "hosted". A "freestanding" environment needs to provide only a subset of the C library: float.h, iso646.h, limits.h, stdalign.h, stdarg.h, stdbool.h, stddef.h, stdint.h and stdnoreturn.h (as of C11). All of these consist of typedef s and #define s "only", so you can implement them without a single .c file in sight.
- Use c++filt to demangle C++ symbol names.
operator new(unsigned long)
$ nm -s usr/lib/libc++.so | c++filt
- #include_next includes the named file in next location in the search path.
- sizeof() returns the size in bytes.
- It may not be obvious, but short is equivalent to short int and long is equivalent to long int.
- Explanation for : Link tests are not allowed after GCC_NO_EXECUTABLES
- Summary of steps for creating cross-compiler.
- For clang, libc++abi contains the definition for new operator.
- You can use make DESTDIR=dir install to install to dir directory.
- Use -Wl,-trace-symbol=symbol for tracing symbol during linking.
- Use -Wl,-M=file.map for printing a link map to file.map.
- Use -Wl,--whole-archive for converting an archive file into a shared library.
Linux chroot
Change root directory for the current session. (chroot ~/work)
J=$HOME/work
P="bash ls"
cd $J
mkdir -p $J/{bin,lib64,lib}
for j in $P
do
file=/bin/$j
cp -v $file $J/bin
list="$(ldd $file | egrep -o '/lib.*\.[0-9]')"
for i in $list;
do
mkdir -p $(dirname ${J}${i})
cp -v "$i" "${J}${i}";
done
done
Comments
Post a Comment