how to port c/c++ applications to legacy linux kernel versions

前端 未结 2 1850
盖世英雄少女心
盖世英雄少女心 2021-02-07 09:00

Ok, this is just a bit of a fun exercise, but it can\'t be too hard compiling programmes for some older linux systems, or can it?

I have access to a couple of ancient sy

相关标签:
2条回答
  • 2021-02-07 09:22

    The reason you can't compile it on the original system likely has nothing to do with kernel version (it could, but 2.2 isn't generally old enough for that to be a stumbling block for most code). The problem is that the toolchain is ancient (at the very least, the compiler). However, nothing stops you from building a newer version of G++ with the egcs that is installed. You may also encounter problems with glibc once you've done that, but you should at least get that far.

    What you should do will look something like this:

    • Build latest GCC with egcs
    • Rebuild latest GCC with the gcc you just built
    • Build latest binutils and ld with your new compiler

    Now you have a well-built modern compiler and (most of a) toolchain with which to build your sample application. If luck is not on your side you may also need to build a newer version of glibc, but this is your problem - the toolchain - not the kernel.

    0 讨论(0)
  • 2021-02-07 09:36

    Have found the reason for the error message:

    user@ancient $ ./prog
    set_thread_area failed when setting up thread-local storage
    Segmentation fault
    

    It's because glibc makes a system call to a function which is only available since kernel 2.4.20. In a way it can be seen as a bug of glibc as it wrongly claims to be compatible with kernel 2.0.10 when it requires at least kernel 2.4.20.

    The details:

    ./glibc-2.14/nptl/sysdeps/i386/tls.h
    [...]
         /* Install the TLS.  */                                                  \
         asm volatile (TLS_LOAD_EBX                                               \
                       "int $0x80\n\t"                                            \
                       TLS_LOAD_EBX                                               \
                       : "=a" (_result), "=m" (_segdescr.desc.entry_number)       \
                       : "0" (__NR_set_thread_area),                              \
                         TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc));    \
    [...]
         _result == 0 ? NULL                                                      \
         : "set_thread_area failed when setting up thread-local storage\n"; })
    [...]
    

    The main thing here is, it calls the assembly function int 0x80 which is a system call to the linux kernel which decides what to do based on the value of eax, which is set to __NR_set_thread_area in this case and is defined in

    $ grep __NR_set_thread_area /usr/src/linux-2.4.20/include/asm-i386/unistd.h
    #define __NR_set_thread_area    243
    

    but not in any earlier kernel versions.

    So the good news is that point "3. Compiling glibc with --enable-kernel=2.0.0" will probably produce executables which run on all linux kernels >= 2.4.20.

    The only chance to make this work with older kernels would be to disable tls (thread-local storage) but which is not possible with glibc 2.14, despite the fact it is offered as a configure option.

    0 讨论(0)
提交回复
热议问题