1 /*
2  * Copyright (C) 2020-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #pragma once
9 
10 #include "shared/source/utilities/const_stringref.h"
11 
12 #include <inttypes.h>
13 #include <stddef.h>
14 
15 namespace NEO {
16 
17 namespace Elf {
18 
19 // Elf identifier class
20 enum ELF_IDENTIFIER_CLASS : uint8_t {
21     EI_CLASS_NONE = 0, // undefined
22     EI_CLASS_32 = 1,   // 32-bit elf file
23     EI_CLASS_64 = 2,   // 64-bit elf file
24 };
25 
26 // Elf identifier data
27 enum ELF_IDENTIFIER_DATA : uint8_t {
28     EI_DATA_NONE = 0,          // undefined
29     EI_DATA_LITTLE_ENDIAN = 1, // little-endian
30     EI_DATA_BIG_ENDIAN = 2,    // big-endian
31 };
32 
33 // Target machine
34 enum ELF_MACHINE : uint16_t {
35     EM_NONE = 0, // No specific instruction set
36     EM_INTELGT = 205,
37 };
38 
39 // Elf version
40 enum ELF_VERSION_ : uint8_t {
41     EV_INVALID = 0, // undefined
42     EV_CURRENT = 1, // current
43 };
44 
45 // Elf type
46 enum ELF_TYPE : uint16_t {
47     ET_NONE = 0,                       // undefined
48     ET_REL = 1,                        // relocatable
49     ET_EXEC = 2,                       // executable
50     ET_DYN = 3,                        // shared object
51     ET_CORE = 4,                       // core file
52     ET_LOPROC = 0xff00,                // start of processor-specific type
53     ET_OPENCL_RESERVED_START = 0xff01, // start of Intel OCL ELF_TYPES
54     ET_OPENCL_RESERVED_END = 0xff05,   // end of Intel OCL ELF_TYPES
55     ET_HIPROC = 0xffff                 // end of processor-specific types
56 };
57 
58 // Section header type
59 enum SECTION_HEADER_TYPE : uint32_t {
60     SHT_NULL = 0,                           // inactive section header
61     SHT_PROGBITS = 1,                       // program data
62     SHT_SYMTAB = 2,                         // symbol table
63     SHT_STRTAB = 3,                         // string table
64     SHT_RELA = 4,                           // relocation entries with add
65     SHT_HASH = 5,                           // symbol hash table
66     SHT_DYNAMIC = 6,                        // dynamic linking info
67     SHT_NOTE = 7,                           // notes
68     SHT_NOBITS = 8,                         // program "no data" space (bss)
69     SHT_REL = 9,                            // relocation entries (without add)
70     SHT_SHLIB = 10,                         // reserved
71     SHT_DYNSYM = 11,                        // dynamic linker symbol table
72     SHT_INIT_ARRAY = 14,                    // array of constructors
73     SHT_FINI_ARRAY = 15,                    // array of destructors
74     SHT_PREINIT_ARRAY = 16,                 // aaray of pre-constructors
75     SHT_GROUP = 17,                         // section group
76     SHT_SYMTAB_SHNDX = 18,                  // extended section indices
77     SHT_NUM = 19,                           // number of defined types
78     SHT_LOOS = 0x60000000,                  // start of os-specifc
79     SHT_OPENCL_RESERVED_START = 0xff000000, // start of Intel OCL SHT_TYPES
80     SHT_OPENCL_RESERVED_END = 0xff00000c    // end of Intel OCL SHT_TYPES
81 };
82 
83 enum SPECIAL_SECTION_HEADER_NUMBER : uint16_t {
84     SHN_UNDEF = 0U, // undef section
85 };
86 
87 enum SECTION_HEADER_FLAGS : uint32_t {
88     SHF_NONE = 0x0,            // no flags
89     SHF_WRITE = 0x1,           // writeable data
90     SHF_ALLOC = 0x2,           // occupies memory during execution
91     SHF_EXECINSTR = 0x4,       // executable machine instructions
92     SHF_MERGE = 0x10,          // data of section can be merged
93     SHF_STRINGS = 0x20,        // data of section is null-terminated strings
94     SHF_INFO_LINK = 0x40,      // section's sh_info is valid index
95     SHF_LINK_ORDER = 0x80,     // has ordering requirements
96     SHF_OS_NONCONFORM = 0x100, // requires os-specific processing
97     SHF_GROUP = 0x200,         // section is part of section group
98     SHF_TLS = 0x400,           // thread-local storage
99     SHF_MASKOS = 0x0ff00000,   // operating-system-specific flags
100     SHF_MASKPROC = 0xf0000000, // processor-specific flags
101 };
102 
103 enum PROGRAM_HEADER_TYPE {
104     PT_NULL = 0x0,          // unused segment
105     PT_LOAD = 0x1,          // loadable segment
106     PT_DYNAMIC = 0x2,       // dynamic linking information
107     PT_INTERP = 0x3,        // path name to invoke as an interpreter
108     PT_NOTE = 0x4,          // auxiliary information
109     PT_SHLIB = 0x5,         // reserved
110     PT_PHDR = 0x6,          // location and of programe header table
111     PT_TLS = 0x7,           // thread-local storage template
112     PT_LOOS = 0x60000000,   // start os-specifc segments
113     PT_HIOS = 0x6FFFFFFF,   // end of os-specific segments
114     PT_LOPROC = 0x70000000, // start processor-specific segments
115     PT_HIPROC = 0x7FFFFFFF  // end processor-specific segments
116 };
117 
118 enum PROGRAM_HEADER_FLAGS : uint32_t {
119     PF_NONE = 0x0,           // all access denied
120     PF_X = 0x1,              // execute
121     PF_W = 0x2,              // write
122     PF_R = 0x4,              // read
123     PF_MASKOS = 0x0ff00000,  // operating-system-specific flags
124     PF_MASKPROC = 0xf0000000 // processor-specific flags
125 
126 };
127 
128 enum SYMBOL_TABLE_TYPE : uint32_t {
129     STT_NOTYPE = 0,
130     STT_OBJECT = 1,
131     STT_FUNC = 2,
132     STT_SECTION = 3
133 };
134 
135 enum SYMBOL_TABLE_BIND : uint32_t {
136     STB_LOCAL = 0,
137     STB_GLOBAL = 1
138 };
139 
140 constexpr const char elfMagic[4] = {0x7f, 'E', 'L', 'F'};
141 
142 struct ElfFileHeaderIdentity {
ElfFileHeaderIdentityElfFileHeaderIdentity143     ElfFileHeaderIdentity(ELF_IDENTIFIER_CLASS classBits)
144         : eClass(classBits) {
145     }
146     char magic[4] = {elfMagic[0], elfMagic[1], elfMagic[2], elfMagic[3]}; // should match elfMagic
147     uint8_t eClass = EI_CLASS_NONE;                                       // 32- or 64-bit format
148     uint8_t data = EI_DATA_LITTLE_ENDIAN;                                 // endianness
149     uint8_t version = EV_CURRENT;                                         // elf file version
150     uint8_t osAbi = 0U;                                                   // target system
151     uint8_t abiVersion = 0U;                                              // abi
152     char padding[7] = {};                                                 // pad to 16 bytes
153 };
154 static_assert(sizeof(ElfFileHeaderIdentity) == 16, "");
155 
156 template <int NumBits>
157 struct ElfProgramHeaderTypes;
158 
159 template <>
160 struct ElfProgramHeaderTypes<EI_CLASS_32> {
161     using Type = uint32_t;
162     using Flags = uint32_t;
163     using Offset = uint32_t;
164     using VAddr = uint32_t;
165     using PAddr = uint32_t;
166     using FileSz = uint32_t;
167     using MemSz = uint32_t;
168     using Align = uint32_t;
169 };
170 
171 template <>
172 struct ElfProgramHeaderTypes<EI_CLASS_64> {
173     using Type = uint32_t;
174     using Flags = uint32_t;
175     using Offset = uint64_t;
176     using VAddr = uint64_t;
177     using PAddr = uint64_t;
178     using FileSz = uint64_t;
179     using MemSz = uint64_t;
180     using Align = uint64_t;
181 };
182 
183 template <int NumBits>
184 struct ElfProgramHeader;
185 
186 template <>
187 struct ElfProgramHeader<EI_CLASS_32> {
188     ElfProgramHeaderTypes<EI_CLASS_32>::Type type = PT_NULL;   // type of segment
189     ElfProgramHeaderTypes<EI_CLASS_32>::Offset offset = 0U;    // absolute offset of segment data in file
190     ElfProgramHeaderTypes<EI_CLASS_32>::VAddr vAddr = 0U;      // VA of segment in memory
191     ElfProgramHeaderTypes<EI_CLASS_32>::PAddr pAddr = 0U;      // PA of segment in memory
192     ElfProgramHeaderTypes<EI_CLASS_32>::FileSz fileSz = 0U;    // size of segment in file
193     ElfProgramHeaderTypes<EI_CLASS_32>::MemSz memSz = 0U;      // size of segment in memory
194     ElfProgramHeaderTypes<EI_CLASS_32>::Flags flags = PF_NONE; // segment-dependent flags
195     ElfProgramHeaderTypes<EI_CLASS_32>::Align align = 1U;      // alignment
196 };
197 
198 template <>
199 struct ElfProgramHeader<EI_CLASS_64> {
200     ElfProgramHeaderTypes<EI_CLASS_64>::Type type = PT_NULL;   // type of segment
201     ElfProgramHeaderTypes<EI_CLASS_64>::Flags flags = PF_NONE; // segment-dependent flags
202     ElfProgramHeaderTypes<EI_CLASS_64>::Offset offset = 0U;    // absolute offset of segment data in file
203     ElfProgramHeaderTypes<EI_CLASS_64>::VAddr vAddr = 0U;      // VA of segment in memory
204     ElfProgramHeaderTypes<EI_CLASS_64>::PAddr pAddr = 0U;      // PA of segment in memory
205     ElfProgramHeaderTypes<EI_CLASS_64>::FileSz fileSz = 0U;    // size of segment in file
206     ElfProgramHeaderTypes<EI_CLASS_64>::MemSz memSz = 0U;      // size of segment in memory
207     ElfProgramHeaderTypes<EI_CLASS_64>::Align align = 1U;      // alignment
208 };
209 
210 static_assert(sizeof(ElfProgramHeader<EI_CLASS_32>) == 0x20, "");
211 static_assert(sizeof(ElfProgramHeader<EI_CLASS_64>) == 0x38, "");
212 
213 template <int NumBits>
214 struct ElfSectionHeaderTypes;
215 
216 template <>
217 struct ElfSectionHeaderTypes<EI_CLASS_32> {
218     using Name = uint32_t;
219     using Type = uint32_t;
220     using Flags = uint32_t;
221     using Addr = uint32_t;
222     using Offset = uint32_t;
223     using Size = uint32_t;
224     using Link = uint32_t;
225     using Info = uint32_t;
226     using AddrAlign = uint32_t;
227     using EntSize = uint32_t;
228 };
229 
230 template <>
231 struct ElfSectionHeaderTypes<EI_CLASS_64> {
232     using Name = uint32_t;
233     using Type = uint32_t;
234     using Flags = uint64_t;
235     using Addr = uint64_t;
236     using Offset = uint64_t;
237     using Size = uint64_t;
238     using Link = uint32_t;
239     using Info = uint32_t;
240     using AddrAlign = uint64_t;
241     using EntSize = uint64_t;
242 };
243 
244 template <int NumBits>
245 struct ElfSectionHeader {
246     typename ElfSectionHeaderTypes<NumBits>::Name name = 0U;           // offset to string in string section names
247     typename ElfSectionHeaderTypes<NumBits>::Type type = SHT_NULL;     // section type
248     typename ElfSectionHeaderTypes<NumBits>::Flags flags = SHF_NONE;   // section flags
249     typename ElfSectionHeaderTypes<NumBits>::Addr addr = 0U;           // VA of section in memory
250     typename ElfSectionHeaderTypes<NumBits>::Offset offset = 0U;       // absolute offset of section data in file
251     typename ElfSectionHeaderTypes<NumBits>::Size size = 0U;           // size of section's data
252     typename ElfSectionHeaderTypes<NumBits>::Link link = SHN_UNDEF;    // index of associated section
253     typename ElfSectionHeaderTypes<NumBits>::Info info = 0U;           // extra information
254     typename ElfSectionHeaderTypes<NumBits>::AddrAlign addralign = 0U; // section alignment
255     typename ElfSectionHeaderTypes<NumBits>::EntSize entsize = 0U;     // section's entries size
256 };
257 
258 static_assert(sizeof(ElfSectionHeader<EI_CLASS_32>) == 0x28, "");
259 static_assert(sizeof(ElfSectionHeader<EI_CLASS_64>) == 0x40, "");
260 
261 template <ELF_IDENTIFIER_CLASS NumBits>
262 struct ElfFileHeaderTypes;
263 
264 template <>
265 struct ElfFileHeaderTypes<EI_CLASS_32> {
266     using Type = uint16_t;
267     using Machine = uint16_t;
268     using Version = uint32_t;
269     using Entry = uint32_t;
270     using PhOff = uint32_t;
271     using ShOff = uint32_t;
272     using Flags = uint32_t;
273     using EhSize = uint16_t;
274     using PhEntSize = uint16_t;
275     using PhNum = uint16_t;
276     using ShEntSize = uint16_t;
277     using ShNum = uint16_t;
278     using ShStrNdx = uint16_t;
279 };
280 
281 template <>
282 struct ElfFileHeaderTypes<EI_CLASS_64> {
283     using Type = uint16_t;
284     using Machine = uint16_t;
285     using Version = uint32_t;
286     using Entry = uint64_t;
287     using PhOff = uint64_t;
288     using ShOff = uint64_t;
289     using Flags = uint32_t;
290     using EhSize = uint16_t;
291     using PhEntSize = uint16_t;
292     using PhNum = uint16_t;
293     using ShEntSize = uint16_t;
294     using ShNum = uint16_t;
295     using ShStrNdx = uint16_t;
296 };
297 
298 template <ELF_IDENTIFIER_CLASS NumBits>
299 struct ElfFileHeader {
300     ElfFileHeaderIdentity identity = ElfFileHeaderIdentity(NumBits);                               // elf file identity
301     typename ElfFileHeaderTypes<NumBits>::Type type = ET_NONE;                                     // elf file type
302     typename ElfFileHeaderTypes<NumBits>::Machine machine = EM_NONE;                               // target machine
303     typename ElfFileHeaderTypes<NumBits>::Version version = 1U;                                    // elf file version
304     typename ElfFileHeaderTypes<NumBits>::Entry entry = 0U;                                        // entry point (start address)
305     typename ElfFileHeaderTypes<NumBits>::PhOff phOff = 0U;                                        // absolute offset to program header table in file
306     typename ElfFileHeaderTypes<NumBits>::ShOff shOff = 0U;                                        // absolute offset to section header table in file
307     typename ElfFileHeaderTypes<NumBits>::Flags flags = 0U;                                        // target-dependent flags
308     typename ElfFileHeaderTypes<NumBits>::EhSize ehSize = sizeof(ElfFileHeader<NumBits>);          // header size
309     typename ElfFileHeaderTypes<NumBits>::PhEntSize phEntSize = sizeof(ElfProgramHeader<NumBits>); // size of entries in program header table
310     typename ElfFileHeaderTypes<NumBits>::PhNum phNum = 0U;                                        // number of entries in pogram header table
311     typename ElfFileHeaderTypes<NumBits>::ShEntSize shEntSize = sizeof(ElfSectionHeader<NumBits>); // size of entries section header table
312     typename ElfFileHeaderTypes<NumBits>::ShNum shNum = 0U;                                        // number of entries in section header table
313     typename ElfFileHeaderTypes<NumBits>::ShStrNdx shStrNdx = SHN_UNDEF;                           // index of section header table with section names
314 };
315 
316 static_assert(sizeof(ElfFileHeader<EI_CLASS_32>) == 0x34, "");
317 static_assert(sizeof(ElfFileHeader<EI_CLASS_64>) == 0x40, "");
318 
319 struct ElfNoteSection {
320     uint32_t nameSize;
321     uint32_t descSize;
322     uint32_t type;
323 };
324 static_assert(sizeof(ElfNoteSection) == 0xC, "");
325 
326 template <int NumBits>
327 struct ElfSymbolEntryTypes;
328 
329 template <>
330 struct ElfSymbolEntryTypes<EI_CLASS_32> {
331     using Name = uint32_t;
332     using Info = uint8_t;
333     using Other = uint8_t;
334     using Shndx = uint16_t;
335     using Value = uint32_t;
336     using Size = uint32_t;
337 };
338 
339 template <>
340 struct ElfSymbolEntryTypes<EI_CLASS_64> {
341     using Name = uint32_t;
342     using Info = uint8_t;
343     using Other = uint8_t;
344     using Shndx = uint16_t;
345     using Value = uint64_t;
346     using Size = uint64_t;
347 };
348 
349 template <ELF_IDENTIFIER_CLASS NumBits>
350 struct ElfSymbolEntry;
351 
352 template <>
353 struct ElfSymbolEntry<EI_CLASS_32> {
354     ElfSymbolEntryTypes<EI_CLASS_32>::Name name;
355     ElfSymbolEntryTypes<EI_CLASS_32>::Value value;
356     ElfSymbolEntryTypes<EI_CLASS_32>::Size size;
357     ElfSymbolEntryTypes<EI_CLASS_32>::Info info;
358     ElfSymbolEntryTypes<EI_CLASS_32>::Other other;
359     ElfSymbolEntryTypes<EI_CLASS_32>::Shndx shndx;
360 };
361 
362 template <>
363 struct ElfSymbolEntry<EI_CLASS_64> {
364     ElfSymbolEntryTypes<EI_CLASS_64>::Name name;
365     ElfSymbolEntryTypes<EI_CLASS_64>::Info info;
366     ElfSymbolEntryTypes<EI_CLASS_64>::Other other;
367     ElfSymbolEntryTypes<EI_CLASS_64>::Shndx shndx;
368     ElfSymbolEntryTypes<EI_CLASS_64>::Value value;
369     ElfSymbolEntryTypes<EI_CLASS_64>::Size size;
370 };
371 
372 static_assert(sizeof(ElfSymbolEntry<EI_CLASS_32>) == 0x10, "");
373 static_assert(sizeof(ElfSymbolEntry<EI_CLASS_64>) == 0x18, "");
374 
375 template <ELF_IDENTIFIER_CLASS NumBits>
376 struct ElfRel;
377 
378 template <>
379 struct ElfRel<EI_CLASS_32> {
380     uint32_t offset;
381     uint32_t info;
382 };
383 
384 template <>
385 struct ElfRel<EI_CLASS_64> {
386     uint64_t offset;
387     uint64_t info;
388 };
389 
390 static_assert(sizeof(ElfRel<EI_CLASS_32>) == 0x8, "");
391 static_assert(sizeof(ElfRel<EI_CLASS_64>) == 0x10, "");
392 
393 template <ELF_IDENTIFIER_CLASS NumBits>
394 struct ElfRela;
395 
396 template <>
397 struct ElfRela<EI_CLASS_32> {
398     uint32_t offset;
399     uint32_t info;
400     int32_t addend;
401 };
402 
403 template <>
404 struct ElfRela<EI_CLASS_64> {
405     uint64_t offset;
406     uint64_t info;
407     int64_t addend;
408 };
409 
410 static_assert(sizeof(ElfRela<EI_CLASS_32>) == 0xc, "");
411 static_assert(sizeof(ElfRela<EI_CLASS_64>) == 0x18, "");
412 
413 namespace SpecialSectionNames {
414 static constexpr ConstStringRef bss = ".bss";                    // uninitialized memory
415 static constexpr ConstStringRef comment = ".comment";            // version control information
416 static constexpr ConstStringRef data = ".data";                  // initialized memory
417 static constexpr ConstStringRef data1 = ".data1";                // initialized memory
418 static constexpr ConstStringRef debug = ".debug";                // debug symbols
419 static constexpr ConstStringRef debugInfo = ".debug_info";       // debug info
420 static constexpr ConstStringRef dynamic = ".dynamic";            // dynamic linking information
421 static constexpr ConstStringRef dynstr = ".dynstr";              // strings for dynamic linking
422 static constexpr ConstStringRef dynsym = ".dynsym";              // dynamic linking symbol table
423 static constexpr ConstStringRef fini = ".fini";                  // executable instructions of program termination
424 static constexpr ConstStringRef finiArray = ".fini_array";       // function pointers of termination array
425 static constexpr ConstStringRef got = ".got";                    // global offset table
426 static constexpr ConstStringRef hash = ".hash";                  // symnol hash table
427 static constexpr ConstStringRef init = ".init";                  // executable instructions of program initializaion
428 static constexpr ConstStringRef initArray = ".init_array";       // function pointers of initialization array
429 static constexpr ConstStringRef interp = ".interp";              // path name of program interpreter
430 static constexpr ConstStringRef line = ".line";                  // line number info for symbolic debugging
431 static constexpr ConstStringRef note = ".note";                  // note section
432 static constexpr ConstStringRef plt = ".plt";                    // procedure linkage table
433 static constexpr ConstStringRef preinitArray = ".preinit_array"; // function pointers of pre-initialization array
434 static constexpr ConstStringRef relPrefix = ".rel";              // prefix of .relNAME - relocations for NAME section
435 static constexpr ConstStringRef relaPrefix = ".rela";            // prefix of .relaNAME - rela relocations for NAME section
436 static constexpr ConstStringRef rodata = ".rodata";              // read-only data
437 static constexpr ConstStringRef rodata1 = ".rodata1";            // read-only data
438 static constexpr ConstStringRef shStrTab = ".shstrtab";          // section names (strings)
439 static constexpr ConstStringRef strtab = ".strtab";              // strings
440 static constexpr ConstStringRef symtab = ".symtab";              // symbol table
441 static constexpr ConstStringRef symtabShndx = ".symtab_shndx";   // special symbol table section index array
442 static constexpr ConstStringRef tbss = ".tbss";                  // uninitialized thread-local data
443 static constexpr ConstStringRef tadata = ".tdata";               // initialided thread-local data
444 static constexpr ConstStringRef tdata1 = ".tdata1";              // initialided thread-local data
445 static constexpr ConstStringRef text = ".text";                  // executable instructions
446 } // namespace SpecialSectionNames
447 
448 } // namespace Elf
449 
450 } // namespace NEO
451