<!--
Copyright IBM Corp. and others 2018

This program and the accompanying materials are made available under
the terms of the Eclipse Public License 2.0 which accompanies this
distribution and is available at https://www.eclipse.org/legal/epl-2.0/
or the Apache License, Version 2.0 which accompanies this distribution and
is available at https://www.apache.org/licenses/LICENSE-2.0.

This Source Code may also be made available under the following
Secondary Licenses when the conditions for such availability set
forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
General Public License, version 2 with the GNU Classpath
Exception [1] and GNU General Public License, version 2 with the
OpenJDK Assembly Exception [2].

[1] https://www.gnu.org/software/classpath/license.html
[2] https://openjdk.org/legal/assembly-exception.html

SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
-->

# ELFGenerator

This document aims to provide an explanation on how ELF file generation is
supported in Eclipse OMR's Compiler component. Topics of discussion include:

1. The two categories of ELF files generated by OMR Compiler
2. The ELFGenerator class
3. Sample ELF file generated by OMR Compiler

### Introduction to ELF in 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.

### ELFGenerator and its Derived Classes

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.

### How to Enable ELF Generation
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.

### Brief Implementation Overview
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.

### Sample ELF File
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.

```

### Additional Resources

* `man elf` - the ELF entry in the Linux Programmer's Manual
* [Wikipedia article on ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
* [ELF Hello World Tutorial](https://cirosantilli.com/elf-hello-world) by Ciro Santilli