How to convert ELF file to binary file?

In general

An ELF file does not need to use "NO-Fixed memory addresses". In fact, the typical ELF executable file (ET_EXEC) is using a fixed address.

A binary file is usually understood as a file containing non-text data. In the context of programs, it is usually understood to mean the compiled form of the program (in opposition to the source form which is usually a bunch of text files). ELF file are binary files.

Now you might want to know how the ELF file is transformed into the in-memory-representation of the program: the ELF file contains additional information such as where in the program (virtual) address-space each segment of the program should be loaded, which dynamic-libraries should be loaded, how to link the main program and the dynamic libraries together, how to initialise the program, where is the entry point of the program, etc.

One important part of an executable or shared-object is the location of the segments which must be loaded into the program address space. You can look at them using readelf -l:

$ readelf -l /bin/bash

Elf file type is EXEC (Executable file)
Entry point 0x4205bc
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R E    8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000f1a74 0x00000000000f1a74  R E    200000
  LOAD           0x00000000000f1de0 0x00000000006f1de0 0x00000000006f1de0
                 0x0000000000009068 0x000000000000f298  RW     200000
  DYNAMIC        0x00000000000f1df8 0x00000000006f1df8 0x00000000006f1df8
                 0x0000000000000200 0x0000000000000200  RW     8
  NOTE           0x0000000000000254 0x0000000000400254 0x0000000000400254
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_EH_FRAME   0x00000000000d6af0 0x00000000004d6af0 0x00000000004d6af0
                 0x000000000000407c 0x000000000000407c  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     10
  GNU_RELRO      0x00000000000f1de0 0x00000000006f1de0 0x00000000006f1de0
                 0x0000000000000220 0x0000000000000220  R      1

Each LOAD (PT_LOAD) entry describes a segment which must be loaded in the program address-space.

Reading and processing this information is the job of the ELF loaders: on your typical OS this is done in part by the kernel and in part by the dynamic-linker (ld.so, also called "program interpreter" in ELF parlance).

ARM plain binary files

(I don't really known about ARM stuff.)

You're apparently talking about embedded platforms. On ARM, a plain binary file contains the raw content of the initial memory of the program. It does not contain things such as string tables, symbol tables, relocation tables, debug informations but only the data of the (PT_LOAD) segments.

It is a binary file, not hex-encoded. The vhx files are hex-encoded.

Plain binary files can be generated from the ELF files with fromelf.

The basic idea here is that each PT_LOAD entry of a ELF file is dumped at its correct position in the file and remaining gaps (if any) between them are filled with zeros.

The ELF file already has addresses assigned in the p_vaddr field of each segment so this conversion process does not need to determine addresses: this has already been done by the link editor (and the linker script).

References

  • ARM ELF file format

Tags:

Elf