Debugging “Cannot Execute Binary File” Error: Analyzing ELF Relocatable Objects in Linux


4 views

When encountering the error bash: ./myfile: cannot execute binary file, the file command reveals crucial information:

$ file myfile
myfile: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

The key term here is "relocatable" - this indicates the file is an object file (.o) rather than a complete executable. Object files contain machine code but aren't directly executable by the OS.

ELF (Executable and Linkable Format) files come in three primary types:

  • Relocatable (.o files): Intermediate compilation output
  • Executable: Complete programs ready to run
  • Shared object (.so files): Dynamic libraries

To confirm this is indeed an object file, examine the ELF headers:

$ readelf -h myfile
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          488 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         13
  Section header string table index: 10

The user likely stopped after the compilation phase without linking. Here's the complete process:

# Single source file compilation
gcc -c myfile.c -o myfile.o  # Creates relocatable object
gcc myfile.o -o myfile       # Creates executable

# Alternative single-step compilation
gcc myfile.c -o myfile       # Combines compilation and linking

For more complex scenarios, these commands help identify issues:

# Check for missing linker symbols (if partially linked)
nm -C myfile

# Verify dynamic dependencies (for executables)
ldd myfile_executable

# Disassemble object code
objdump -d myfile.o

# Compare with known working executable
file /bin/ls

Case 1: Accidentally distributing .o files instead of executables

# Solution: Rebuild properly
make clean
make

Case 2: Cross-compilation architecture mismatch

# Verify architecture match
file myfile
uname -m

Case 3: Missing linker step in build scripts

# Ensure build system includes linking phase
gcc $(OBJECT_FILES) -o $@

Modern build systems handle these phases automatically. For example in Make:

# Sample Makefile
CC = gcc
CFLAGS = -Wall -O2

myapp: myfile.o utils.o
    $(CC) $(CFLAGS) -o $@ $^

%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

This ensures proper separation of compilation and linking phases while maintaining correct file types.


When encountering the error bash: ./myfile: cannot execute binary file, we're dealing with a fundamental mismatch between the file type and execution requirements. The file command reveals critical information:

$ file myfile
myfile: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

The key identifier here is "relocatable" in the ELF header. Unlike executable files, relocatable objects (.o files) are intermediate compilation outputs not designed for direct execution. They require linking to become complete executables.

Compare these two outputs:

# Typical executable output
$ file /bin/ls
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked

# Your problematic file
$ file myfile
myfile: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

The readelf output confirms this diagnosis. Notice the missing program header table (required for executables) and the presence of relocation sections:

$ readelf -h myfile | grep Type
  Type:                              REL (Relocatable file)

Here are the technical approaches to resolve this:

Option 1: Proper Compilation and Linking

If you have source code available, ensure proper compilation:

# For C programs
gcc -c source.c -o object.o  # Creates relocatable object
gcc object.o -o executable   # Creates proper executable

# Verify with:
file executable

Option 2: Identifying Missing Steps

Common compilation mistakes that lead to this situation:

# Missing linking step (wrong)
gcc -c program.c -o program

# Correct complete compilation
gcc program.c -o program

Advanced Verification Techniques

For deeper analysis, examine the ELF structure:

# Check for program headers (missing in relocatable objects)
readelf -l myfile

# View symbol table
readelf -s myfile

# Disassemble code
objdump -d myfile

When communicating with the user who provided the binary, you should explain:

  • The file is an intermediate compilation product, not a complete executable
  • They likely used gcc -c without final linking
  • The solution requires recompilation with proper linking

To avoid this in development environments:

# Use makefile rules that ensure complete compilation
all: program

program: program.o
    $(CC) $^ -o $@

program.o: program.c
    $(CC) -c $< -o $@