/
fatelf-specification.txt
95 lines (70 loc) · 4.44 KB
/
fatelf-specification.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
FatELF specification, version 1.
This specification is written in plain English, which is less efficient than
just listing a handful of C structs. If you just want the structs, those are
in include/fatelf.h. This file is here to hopefully clarify those data
structures, and also allow for a complete clean-room implementation.
FatELF is a simple container format for storing multiple Executable and
Linkable Format (ELF) binaries in a single file. The file format is as follows.
All fields are little endian on all platforms, and align like Elf64. However,
the ELF binaries stored in the container format follow the usual rules of the
ELF format for their target platform.
FatELF Header:
All FatELF files start with a "magic" number that identifies it as a FatELF
binary. If this magic number is not present, the file in question is not in
FatELF format.
The magic number is four bytes, and when read as a 32-bit little endian value
is 0x1F0E70FA. If read as four unsigned bytes, their hexadecimal value is:
FA 70 0E 1F
If the magic value is present, the file is FatELF. Otherwise, the reader
should treat the file as a regular ELF file (or, perhaps failing that, invalid
data).
Following the magic value is an unsigned, 16-bit value, representing the
version of the FatELF structure. The magic value and this version value are
always guaranteed to be the first data in a FatELF file, but any other
structure can change. As such, FatELF files with unrecognized versions should
be rejected by the reader as invalid.
At this time, the only valid version is 1. Future revisions of this spec may
add new version values. In such a case, implementors are encouraged to handle
legacy versions if possible.
VERSION 1 FORMAT.
Following the version value is an unsigned byte that contains the number of
records in this file. Each ELF binary contained within the file supplies a
separate record. We will call this value the "record count."
The next byte is reserved at this time, and is positioned for the sake of
alignment. It must be set to zero.
Thereafter, we have a series of records equal to the number reported in the
record count, laid out in sequence.
The record format is as follows.
Each record starts with an unsigned, 16-bit value that represents the machine
architecture for this record. This field maps to e_machine in the ELF header.
Next come four unsigned, 8-bit values. These represent, in order, the OSABI,
OSABI version, word size and byte order of the referenced ELF binary. These
fields map to e_ident[EI_OSABI], e_ident[EI_ABIVERSION], e_ident[EI_CLASS] and
e_ident[EI_DATA] in the ELF header. Please note that the FatELF structures
themselves are always little endian and aligned to Elf64 standards, no matter
what these fields contain.
The next two bytes are reserved at this time, and are positioned for the sake of
alignment. They must be set to zero.
The next two fields of the record are unsigned, 64-bit integers that represent
the offset and size of the contained ELF binary. The offset is in bytes and
starts from the beginning of the file. It is illegal for the offset to not
align to the requirements of the specific architecture. For example, if you
have a platform that aligns memory pages on 4096 byte boundaries, then that
platform's ELF binary would have to start at offset 4096, 8192, etc. A
different binary in the same file may have to align different. The FatELF file
should pad the files with null chars where appropriate to supply the proper
alignment. This allows any given ELF binary to be memory-mapped by the system.
It is illegal to have two identical records, that is, two records that only
differ by offset and size. In such a case, behaviour is undefined:
implementors are free to choose whichever record they please.
It is illegal to have two records overlap; a record's offset and size may not
share any bytes with another ELF binary in the file.
Following the list of records are the actual ELF binaries. FatELF makes no
promises about the data, format or layout here, except to say that any given
ELF binary will be aligned in the file to match the platform's requirements,
so that even in a container with other binaries that have different alignment
requirements, the system can still properly memory-map the desired binary.
It is important that the reader not trust the FatELF information and still
properly parse the real ELF headers of a given binary. If they do not match
what is expected, the implementation should reject the file outright as
corrupted or malicious.