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 kpartx -a myos.iso
$ sudo mount /dev/mapper/loop0p3 -t minix /mnt
$ mkdir usr
$ cp /mnt/lib usr
$ cp /mnt/include usr
$ sudo umount /mnt
$ ln -s $PWD/usr $PREFIX/$TARGET/
 


Create hello.c 

#include <stdio.h>
#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-gcc -o hello.o -c hello.c

$ 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
 
# Optional: dynamically linked
$ i686-elf-ld -dynamic-linker /usr/libexec/ld.elf_so -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 

kpartx -a myos.iso
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 

$ sudo ./copy.sh

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.
$ c++filt _Znwm
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.

 

 

Comments

Popular posts from this blog

GNU Emacs as a Comic Book Reader

Tinylisp and Multi-threaded Emacs

Data Visualization with GNU Emacs