Problems with ELF

I am having some weird issues with ELF binaries in linux.

This is my system ( uname -a ):

 Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u2 (2016-01-02) x86_64 GNU/Linux 

I have the following program (test.asm), I compile it using NASM:

 ; program just exits with code 0 using linux INT 80H SECTION .data SECTION .text GLOBAL _start _start: MOV EAX, 1 XOR EBX, EBX INT 0x80 

I create three different executables:

 nasm -f elf32 -o test32-i386.o test.asm ld -m elf_i386 -o test32-i386 test32-i386.o nasm -f elfx32 -o test32-x86_64.o test.asm ld -m elf32_x86_64 -o test32-x86_64 test32-x86_64.o nasm -f elf64 -o test64-x86_64.o test.asm ld -m elf_x86_64 -o test64-x86_64 test64-x86_64.o 

This is the result of the file command:

 test32-i386: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped test32-x86_64: ELF 32-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped test64-x86_64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped 

It makes sense to me. However, their launch causes problems.

  • ./test32-i386 : no problem, working fine.
  • ./test64-x86_64 : the same, it works fine.
  • ./test32-x86_64 , however, gives bash: ./test32-x86_64: cannot execute binary file: Exec format error

In addition, Valgrind produces ... interesting results.

  • valgrind ./test32-i386 : OK
  • valgrind ./test64-x86_64 : raises SIGILL (?!)
  • valgrind ./test32-x86_64 : gives me ./test32-x86_64: 1: ./test32-x86_64: Syntax error: word unexpected (expecting ")")

So, we summarize:

Question 1: Why does Valgrind raise SIGILL when it starts ./test64-x86_64 , although the program works fine without Valgrind?

Question 2: Why can not I run ./test32-x86_64 ? Valgrind error gives that binary is very obscure ...

+5
source share
2 answers

In question 1: the error against valgrind is that it does not support the int80 instruction in x86_64 . I was able to reproduce this under my own valgrind (v3.11.0), and from viewing the source, it looks like it is not supported.

For question 2: the file type is not supported by your ELF loader. To ensure that 32-bit binaries are compatible on Linux, it must perform some checks on the binary when it tries to execute it.

When we use readelf on test32-x86_64, it shows the header:

 ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2 complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x400060 Start of program headers: 52 (bytes into file) Start of section headers: 288 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 1 Size of section headers: 40 (bytes) Number of section headers: 5 Section header string table index: 2 

i.e. class 32 bits and machine type x86_64. i.e. binary bit x32 ABI

The problem is that this requires your kernel to be configured using CONFIG_X86_X32_ABI , otherwise you will fail the check foul :

 #define compat_elf_check_arch(x) \ (elf_check_arch_ia32(x) || \ (IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64)) 

which only supports 32-bit binaries with no configuration option. This parameter is set if you have kernel parameters: CONFIG_X86_X32 = y and CONFIG_X86_X32_DISABLED unset (this is the source of the Linux 4.0 kernel I'm looking for).

So, you need your kernel configured with this support in order to run the code - the reason the problem did not occur is because its kernel seems to be compiled with the correct parameters to run the x32 code.

valgrind is probably hopelessly confused in binary format - it is not considered particularly common.

+2
source

First of all, I could not reproduce your error on ./test32-x86_64 . Although I used the exact code and command lines to compile it.

I am running on Linux 4.3.3 x86_64 (Debian).

Question 1 : Why does Valgrind raise SIGILL when it starts ./test64-x86_64 , although the program works fine without Valgrind?

My version of Valgrind (3.11.0) does not raise SIGILL on it, but it raises this message (and then runs the program as expected):

 valgrind: wrong ELF executable class (eg. 32-bit instead of 64-bit) 

But when you start text64-x86_64 Valgrind will throw the following message:

 vex amd64->IR: unhandled instruction bytes: 0xCD 0x80 0x0 0x0 0x0 0x0 0x0 0x0 vex amd64->IR: REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0 vex amd64->IR: VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=NONE vex amd64->IR: PFX.66=0 PFX.F2=0 PFX.F3=0 

As stated in the Valgrind FAQ :

3.3. My program dies by typing such a message as follows:

 vex x86->IR: unhandled instruction bytes: 0x66 0xF 0x2E 0x5 

One of the possibilities is that your program has an error and erroneously switches to a non-code address, in which case you will receive a SIGILL signal. Memcheck may issue a warning before this happens, but it may not happen if a jump occurs to get into the address memory.

Another possibility is that Valgrind does not process the instruction. If you are using the old Valgrind, a newer version may process the instruction. However, all instruction sets contain some obscure, rarely used instructions. In addition, amd64 has an almost unlimited number of combinations of redundant instructional prefixes, many of which are undocumented but accepted by processors. Therefore, Valgrind will still have decoding errors from time to time. If this happens, write a bug report.

In our exact case, this simply means that the VEX intermediate language does not recognize the int 0x80 instruction as part of the x86_64 .

Question 2 : Why can not I run ./test32-x86_64 ? Valgrind error gives that binary is very obscure ...

Unfortunately, I cannot reproduce your error using my Valgrind.

+2
source

Source: https://habr.com/ru/post/1240911/


All Articles