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