This document aims to provide an explanation on how ELF file generation is supported in Eclipse OMR's Compiler component. Topics of discussion include:
- The two categories of ELF files generated by OMR Compiler
- The ELFGenerator class
- Sample ELF file generated by OMR Compiler
The ELF (Executable and Linkable Format) standard is the dominating file format
in Linux, and is also used in many other operating systems. The standard
specifies various file formats, such as .o
object files, executable files,
.a
archive files, .so
shared object files, core dumps, etc. The OMR Compiler
Technology supports the generating of 2 such variants: executable ELF files, and
.o
object files, which we will mainly refer to as relocatable ELF files.
Executable ELF files can be executed, whereas relocatable ELF files cannot be
executed unless they are linked into an executable resulting in all the symbolic
declarations being connected to their symbolic definitions.
The main difference between executable and relocatable ELF files generated by the OMR Compiler Technology is that executable ELF files have a program header that contain information necessary to execute the file, whereas relocatable ELF files do not have a program header, but have extra information for relocations. Other than that, the 2 variants of ELF files are composed of the same structures.
Due to the fact that the 2 variants of ELF files generated by the compiler share
a lot of similarities, the class ELFGenerator located in codegen
has been
introduced. The class ELFGenerator
is an abstract base class that provides a
mechanism to share code between different kinds of ELF files. Currently the 2
classes that implementation this abstract base class are ELFExecutableGenerator
and ELFRelocatableGenerator
. As their names imply, ELFExecutableGenerator
generates executable ELF files, and ELFRelocatableGenerator
generates relocatable
ELF files.
To enable generating of ELF files, you will need to use the following command-line options:
TR_Options='enableExecutableELFGeneration'
TR_Options='enableRelocatableELFGeneration,objectFile=increment.o'
The command-line options above enables the option bits corresponding to
TR_EmitExecutableELFFile
and TR_EmitRelocatableELFFile
respectively. Note that
when you enable Relocatable ELF file generation, you will also have to specify the
file name for the .o
file to write to using the command line option
objectFile=<object-file-name>.o
. Relocatable ELF Files get generated in the working
directory, and Executable ELF files are written to a file located in /tmp/
directory,
and named perf-
followed by the process ID at the time of writing the ELF file.
The choice of filename and location for executable ELF files are largely historical.
The ELFRelocatableGenerator and ELFExecutableGenerator are instantiated after the code
cache memory has been allocated, since you will need to know the size of the code cache
segment in order to initialize one of the generator class implementations.
ELFRelocatableGenerator
and ELFExecutableGenerator
take the same arguments in the
constructor.
The data structures that are written to the ELF files are defined in the elf.h
system header file. elf.h
defines data structures for both 64-bit and 32-bit
implementations. For example, ELF header structure variants are defined as
Elf32_Ehdr
and Elf64_Ehdr
, relevant to 32 and 64-bit targets, respectively.
Instead of having to check the target bitness every time we use anything from
elf.h
, they are checked once through preprocessor directives, and the 32/64
bit variants are aliased into a generic name, such as ELFEHeader
in the case
of Elf32_Ehdr
/Elf64_Ehdr
.
When either of the generators are instantiated, the ELFEHeader
is initialized.
In the case of executable ELF, ELFProgramHeader
is also set up.
When the Compiler is being shut down, and the option(s) to enable writing the code
segment to an ELF file have been enabled, CodeCacheManager calls the emitElf
method
of the executable and/or relocatable ELF generator. emitElf
method have different
parameters for executable and relocatable ELF, with relocatable ELF requiring
CodeCacheRelocationInfo
containing information for linking, and the number of relocations.
The method emitElf
calls the method that calculates offsets and initializes the section
headers, then calls the method that writes all the initialized headers. This is then followed
by writing the code segments, the symbols, and finally, the relocation entries in the case
of relocatable ELF.
Here is an example of how an ELF file generated by ELFRelocatableGenerator looks like, which
was generated by running make useCall
in jitbuilder/release
. The Makefile in that
directory demonstrates how the command line arguments are being used to generate the ELF file,
and how the relocatable ELF files being generated are linked into an executable. The
generated elf file can be viewed on Linux using the command readelf -a test_calls.o
.
ELF Header:
Magic: 7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
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: 16777256 (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: 6
Section header string table index: 4
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
0000000000ffffe8 0000000000000000 AX 0 0 32
[ 2] .rela.text RELA 0000000000000000 010002e5
0000000000000078 0000000000000018 3 1 8
[ 3] .symtab SYMTAB 0000000000000000 010001d4
00000000000000c0 0000000000000018 5 1 8
[ 4] .shstrtab STRTAB 0000000000000000 010001a8
000000000000002c 0000000000000000 0 0 1
[ 5] .dynstr STRTAB 0000000000000000 01000294
0000000000000051 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
Relocation section '.rela.text' at offset 0x10002e5 contains 5 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000081 000200000001 R_X86_64_64 0000000000000000 doublesum + 0
00000000009b 000300000001 R_X86_64_64 0000000000000000 doublesum + 0
0000000000b5 000400000001 R_X86_64_64 0000000000000000 doublesum + 0
0000000000d5 000500000001 R_X86_64_64 0000000000000000 doublesum + 0
0000000000ff 000600000001 R_X86_64_64 0000000000000000 doublesum + 0
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
Symbol table '.symtab' contains 8 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000034 286 FUNC GLOBAL DEFAULT 1 test_calls
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND doublesum
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND doublesum
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND doublesum
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND doublesum
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND doublesum
7: 0000000000000174 262 FUNC GLOBAL DEFAULT 1 test_computed_call
No version information found in this file.
man elf
- the ELF entry in the Linux Programmer's Manual- Wikipedia article on ELF
- ELF Hello World Tutorial by Ciro Santilli