Build binary (telnet) for 2.4.0 kernel, i586 architecture - linux

I am trying to cross-compile a binary to use on an old Linux distribution (kernel 2.4.25, i586 architecture).
Steps I took
I have downloaded the landley i586 cross-compiler (http://landley.net/aboriginal/downloads/binaries/)
I downloaded the net-utils source: https://ftp.gnu.org/gnu/inetutils/ version 1.9.4
I included the cross-compiler in my path: export PATH=/root/Documents/cross-compiler-i586/bin/:$PATH
I then built the telnet binary as follows: LDFLAGS=”-static" ./configure --host=i586 --build=x86_64 --target=i586 --disable-ifconfig --with-ncurses-include-dir=/root/Documents/tnbuild --disable-hostname --disable-logger --disable-rcp --disable-rexec --disable-rlogin --disable-rsh --disable-tftp --disable-traceroute --disable-inetd --disable-rexecd --disable-syslogd --disable-tftpd
This successfully compiled, and checking (after stripping) the binary with the file command gives: telnet: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped
I compared this with a binary which is already on the old Linux system, and the output is exactly the same: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter lib/ld-linux.so.2, for GNU/Linux 2.4.0, stripped
The problem I am facing
The telnet binary that I compiled is not working on the old Linux system. The error that is thrown is simply 'Segmentation Fault'. Googling this error learns that it is likely due to differences in architecture (i586?), but I have no clue anymore how to fix it, as the 'file' command outputs exactly the same for a working binary as well as for the failing binary.
I then stumbled across this topic: GCC Cross compile to a i586 architecture (Vortex86DX) , but as it is not pursued, I am not sure if I should indeed compile all toolchains for i586 and how exactly I would need to do that.

Is there a specific reason you want to cross-compile this rather than just compiling for generic 32-bit i386? You may need to disable some compiler optimizations if they are not supported by the CPU, but you probably don't need to create a staticly-linked binary.
These instructions for compiling 32-bit (-m 32) seem sufficient to create the telnet binary.
They boil down to:
apt-get install gcc-multilib;
./configure CFLAGS='-m32' -disable-ifconfig \
--with-ncurses-include-dir=/root/Documents/tnbuild \
--disable-hostname --disable-logger --disable-rcp \
--disable-rexec --disable-rlogin --disable-rsh \
--disable-tftp --disable-traceroute --disable-inetd \
--disable-rexecd --disable-syslogd --disable-tftpd
make

Related

Specify the expected Linux version of the output binary of GCC

I'm helping others doing a lab experiment of the "operating systems concepts" course. The experiment task is to compile Linux 2.6.26 and run it in QEMU.
After compiling the Linux kernel, we're told to write a smallest program to serve as the init program. The example we're presented (and we followed) is:
#include <stdio.h>
int main() {
while (1) {
puts("Hello!");
sleep(2);
}
}
The compilation command is:
root#ubuntu:/home/vmware/oslab# gcc --version
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
root#ubuntu:/home/vmware/oslab# gcc -static -o init hello.c
The host environment should be a freshly-installed Ubuntu 14.04.6 (i386).
The problem is, one of my fellow students followed the instruction carefully, and the init program failed to execute. I asked him for his whole initrd.img, and noticed how his init program looks different:
vmware#ubuntu:~/oslab$ file mnt/init
mnt/init: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=7365ac494ef1d924c171899c169dbd3195d2d209, not stripped
To me, that's clearly not something that can run on Linux 2.6.26. With GCC 4.8 provided in the Ubuntu APT repository (trusty), how can I get GCC to output something that runs on Linux 2.6.26?
FYI: On my own testing VM (also Ubuntu 14.04.6, Linux 4.4, same latest GCC version from Ubuntu APT repo as of April 2, 2019), the compiled program shows Linux 2.6.24 in file output. Also, his binary runs perfectly well in QEMU with my freshly compiled 2.6.32.37 kernel.
Specify the expected Linux version of the output binary of GCC
in your question you speak about the version of libc C but that can also concerns a lot of other libs, and may be you want also produce 32b and/or 64b executable(s).
For me the most secure way is to use pbuilder, I use it to produce BoUML debs for Ubuntu Cosmic (18.10) Bionic (18.04), Artful (17.10) Zesty (17.04) Yakkety (16.10) Xenial (16.04) Trusty (14.04) and Precise (12.04) and that in both 32b and 64b, and I do all of that from my Ubuntu Xenial 64b just doing the appropriate sequence of pbuilder commands (without any reboot to go in each Linux release)
That needs time to generate a version but because this is made in the corresponding Linux version you are sure of the result.
The provided lab environment was Ubuntu 14.04, where the package libc6 has version 2.19-0ubuntu6.14.
The lab instruction provided by the teaching assistants contained an instruction to change the APT source by editing /etc/apt/sources.list manually, which had a SERIOUS disaster in it: The "version" string in the edited example was xenial instead of trusty, which, if followed, would factually update your system to Xenial (Ubuntu 16.04). The new version of libc6 was 2.23-0ubuntu11, which would cause as and ld (from binutils, not related to GCC) to output ELF with a minimum Linux version of 2.6.32.
With glibc version 2.19, the output ELF is compatible with Linux 2.6.24, but with glibc 2.23, the output is only compatible with Linux 2.6.32.
I tested and verified this by compiling a test program under Ubuntu 14.04 and checking the ELF information, then replaced all trusty with xenial, did apt-get update and only updated binutils and its dependencies (which includes libc6), and compiled the program and checked it again.

Unknown capability error

I am trying to cross compile the ipsectools(ipsec-tools-0.8.2) downloaded from opensource for the mips architecture.
I downloaded ipsectools from : https://sourceforge.net/projects/ipsec-tools/
and applied a patch as mentioned in : https://dev.openwrt.org/browser/packages/net/ipsec-tools/patches/006-linux-3.7-compat.patch?rev=35312
Susequently after extracting and applying patch, i used the following commands,
./bootstrap
autoconf
./configure --enable-security-context=no CXX=${CROSS_COMPILE}g++ CC=${CROSS_COMPILE}gcc AS=${CROSS_COMPILE}as AR=${CROSS_COMPILE}ar LD=${CROSS_COMPILE}ld NM=${CROSS_COMPILE}nm OBJCOPY=${CROSS_COMPILE}objcopy OBJDUMP=${CROSS_COMPILE}objdump RANLIB=${CROSS_COMPILE}ranlib READELF=${CROSS_COMPILE}readelf STRIP=${CROSS_COMPILE}strip --host=mips-wrs-linux-gnu --build=i586-wrs-linux-gnu
Now if i crosscompile for mips architecture it compiles successfully for mips. But the racoon binary file created shows following
[samb#bhlinv09 racoon]$ file racoon
racoon: ELF 64-bit MSB executable, MIPS, MIPS64 rel2 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, with unknown capability 0x410000000f676e75 = 0x1000000070403, not stripped
Can anyone tell me what is this "unknown capability error"?

difference between i386:x64-32 vs i386 vs i386:x86_64

Can someone explain the difference between the three architectures?
Actually when I built a 64-bit application in Linux, I got a link error saying:
skipping incompatible library.a when searching for library.a
Then I used objdump -f on that library and I got the below output:
a.o: file format elf32-x86-64
architecture: i386:x64-32, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
Does it mean the library is 32-bit? Is that the reason I am getting the linker error?
There are 3 common ABIs usable on standard Intel-compatible machines (not Itanium).
The classic 32-bit architecture, often called "x86" for short, which has triples like i[3-6]86-linux-gnu. Registers and pointers are both 32 bits.
The 64-bit extension originally from AMD, often called "amd64" for short, which has GNU triple of x86_64-linux-gnu. Registers and pointers are both 64 bits.
The new "x32" ABI, with a triple of x86_64-linux-gnux32. Registers are 64 bits, but pointers are only 32 bits, saving a lot of memory in pointer-heavy workflows. It also ensures all the other 64-bit only processor features are available.
Each of the above has its on system call interface, own ld.so, own complete set of libraries, etc. But it is possible to run all 3 on the same kernel.
On Linux, their loaders are:
% objdump -f /lib/ld-linux.so.2 /lib64/ld-linux-x86-64.so.2 /libx32/ld-linux-x32.so.2
/lib/ld-linux.so.2: file format elf32-i386
architecture: i386, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x00000a90
/lib64/ld-linux-x86-64.so.2: file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000000c90
/libx32/ld-linux-x32.so.2: file format elf32-x86-64
architecture: i386:x64-32, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x00000960
Now, if you're getting the message about "skipping incompatible library", that means something is messed up with your configuration. Make sure you don't have bad variables in the environment or passed on the command line, or files installed outside of your package manager's control.
Beyond usual full 64bit and good old 32bit ABI there is a special ABI (inspired by SGI n32 envirnment) where pointers are 32bit (thus they are 32bit apps), but it is designed to run on 64bit host and have full access to all x64 goodies:
native x64 registers and math
more registers
SSE2/3/4, AVX1/2/...
Full 4Gb address space on 64bit host
It is called x32 ABI, link: https://en.wikipedia.org/wiki/X32_ABI
UPDATE
On Ubuntu system I have to install two packages (with deps) to get x32 working:
> sudo apt install gcc-multilib
> sudo apt install libx32stdc++-5-dev
Then compiling simlple C++ code with g++ -mx32 hellow.cpp works, making x32 executable
> file a.out
./a.out: ELF 32-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /libx32/ld-linux-x32.so.2, for GNU/Linux 3.4.0

Build DAHDI for Beablebone Black

I'm planning to build DAHDI for Beagleboneblack
Firstly, I built the kernel for BBB completely by following this tutorial
http://elinux.org/Building_BBB_Kernel,
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- beaglebone_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage dtbs
make ARCH=arm CROSS_COMPILE=arm-linux-gnu- uImage-dtb.am335x-boneblack modules
I used linaro toolchain for armhf (CROSS_COMPILE=arm-linux-gnueabihf-) instead of the instructed one.
And then I start building the DAHDI :
cd dahdi-linux-complete-2.10.1-rc2+2.10.1-rc2
cd linux/ # I build the dahdi only, not their tools
make KSRC=PATH_TO_MY_ABOVE_KERNEL
Unfortunately, process ends with the following error when compiling the dahdi-base.c :
/home/working/dl/dahdi-linux-complete-2.10.1-rc2+2.10.1-rc2/linux/drivers/dahdi/dahdi-base.c:1: error: code model kernel not supported in the 32 bit mode
/home/working/dl/dahdi-linux-complete-2.10.1-rc2+2.10.1-rc2/linux/drivers/dahdi/dahdi-base.c:1: sorry, unimplemented: 64-bit mode not compiled in
I have no idea why, because my linaro toolchain is 32-bit
/home/working/dl/gcc-linaro-arm-linux-gnueabihf-4.7-2012.10-20121022_linux/bin/arm-linux-gnueabihf-gcc-4.7.3:
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
and my gnu gcc toolchain is 32-bit as well.
/usr/bin/gcc: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped
If anybody gets an idea, your help would be appreciated.
Best Regard.
Loi Dang Thanh
I'm making this answer to make sure everyone else who get into my issue can search and solve the problem in the future.
Just add 2 more ARGS to the make command when building DAHDI, and the problem solved pretty well.
make KSRC=PATH_TO_MY_ABOVE_KERNEL ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
A big thanks to Miline who get me out of the stuck.
Best Regards
Loi Dang.

Linux program in FreeBSD

Trying to run my program in FreeBSD OS, I have the following results:
$ ./myprogram
ELF binary type "0" not known
./myprogram: 1: Syntax error: "&" unexpected (expecting ")")
$ file myprogram
myprogram: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.15,
not stripped
The program is built In GCC on Ubuntu computer. What can I do? Can I build the program for FreeBSD on my Ubuntu computer by changing some build options, or I need to build it in FreeBSD OS? Maybe there is some way to convert executable to format recognized by FreeBSD?
You can run a lot of Linux programs on FreeBSD, see http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/linuxemu.html.
If this doesn't work, the easiest solution would be to recompile your program on FreeBSD.
2021-06-21: This answer is outdated. As of 2021, FreeBSD includes Linux® binary compatibility, which will run most Linux binaries, save for those which "overly use i386™ specific calls, as enabling virtual 8086 mode".
A large number of Linux programs can be compiled on BSD systems however they are not the same operating system. Linux and BSD are technically not binary compatible.
These days BSD ships with an ABI (Application Binary Interface) for Linux which will translate Linux sys-calls on the fly (Much how WINE operates). This will allow you to run Linux ELF binaries on BSD systems with a small performance penalty.
That being said, they are not the same operating system and your best bet would be to compile for the target system either by gaining access to it or using a method of cross compiling.
Try branding the executable as a linux executable using brandelf (you still need all the dependent libraries setup though, or try linking it statically
http://www.freebsd.org/cgi/man.cgi?query=brandelf&apropos=0&sektion=0&manpath=FreeBSD+8.0-RELEASE&format=html
brandelf -t "Linux" and it should work.

Resources