elf.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. // SPDX-FileCopyrightText: 2022 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <cstddef>
  6. #include "common_types.h"
  7. namespace Common {
  8. namespace ELF {
  9. /* Type for a 16-bit quantity. */
  10. using Elf32_Half = u16;
  11. using Elf64_Half = u16;
  12. /* Types for signed and unsigned 32-bit quantities. */
  13. using Elf32_Word = u32;
  14. using Elf32_Sword = s32;
  15. using Elf64_Word = u32;
  16. using Elf64_Sword = s32;
  17. /* Types for signed and unsigned 64-bit quantities. */
  18. using Elf32_Xword = u64;
  19. using Elf32_Sxword = s64;
  20. using Elf64_Xword = u64;
  21. using Elf64_Sxword = s64;
  22. /* Type of addresses. */
  23. using Elf32_Addr = u32;
  24. using Elf64_Addr = u64;
  25. /* Type of file offsets. */
  26. using Elf32_Off = u32;
  27. using Elf64_Off = u64;
  28. /* Type for section indices, which are 16-bit quantities. */
  29. using Elf32_Section = u16;
  30. using Elf64_Section = u16;
  31. /* Type for version symbol information. */
  32. using Elf32_Versym = Elf32_Half;
  33. using Elf64_Versym = Elf64_Half;
  34. constexpr size_t ElfIdentSize = 16;
  35. /* The ELF file header. This appears at the start of every ELF file. */
  36. struct Elf32_Ehdr {
  37. std::array<u8, ElfIdentSize> e_ident; /* Magic number and other info */
  38. Elf32_Half e_type; /* Object file type */
  39. Elf32_Half e_machine; /* Architecture */
  40. Elf32_Word e_version; /* Object file version */
  41. Elf32_Addr e_entry; /* Entry point virtual address */
  42. Elf32_Off e_phoff; /* Program header table file offset */
  43. Elf32_Off e_shoff; /* Section header table file offset */
  44. Elf32_Word e_flags; /* Processor-specific flags */
  45. Elf32_Half e_ehsize; /* ELF header size in bytes */
  46. Elf32_Half e_phentsize; /* Program header table entry size */
  47. Elf32_Half e_phnum; /* Program header table entry count */
  48. Elf32_Half e_shentsize; /* Section header table entry size */
  49. Elf32_Half e_shnum; /* Section header table entry count */
  50. Elf32_Half e_shstrndx; /* Section header string table index */
  51. };
  52. struct Elf64_Ehdr {
  53. std::array<u8, ElfIdentSize> e_ident; /* Magic number and other info */
  54. Elf64_Half e_type; /* Object file type */
  55. Elf64_Half e_machine; /* Architecture */
  56. Elf64_Word e_version; /* Object file version */
  57. Elf64_Addr e_entry; /* Entry point virtual address */
  58. Elf64_Off e_phoff; /* Program header table file offset */
  59. Elf64_Off e_shoff; /* Section header table file offset */
  60. Elf64_Word e_flags; /* Processor-specific flags */
  61. Elf64_Half e_ehsize; /* ELF header size in bytes */
  62. Elf64_Half e_phentsize; /* Program header table entry size */
  63. Elf64_Half e_phnum; /* Program header table entry count */
  64. Elf64_Half e_shentsize; /* Section header table entry size */
  65. Elf64_Half e_shnum; /* Section header table entry count */
  66. Elf64_Half e_shstrndx; /* Section header string table index */
  67. };
  68. constexpr u8 ElfClass32 = 1; /* 32-bit objects */
  69. constexpr u8 ElfClass64 = 2; /* 64-bit objects */
  70. constexpr u8 ElfData2Lsb = 1; /* 2's complement, little endian */
  71. constexpr u8 ElfVersionCurrent = 1; /* EV_CURRENT */
  72. constexpr u8 ElfOsAbiNone = 0; /* System V ABI */
  73. constexpr u16 ElfTypeNone = 0; /* No file type */
  74. constexpr u16 ElfTypeRel = 0; /* Relocatable file */
  75. constexpr u16 ElfTypeExec = 0; /* Executable file */
  76. constexpr u16 ElfTypeDyn = 0; /* Shared object file */
  77. constexpr u16 ElfMachineArm = 40; /* ARM */
  78. constexpr u16 ElfMachineAArch64 = 183; /* ARM AARCH64 */
  79. constexpr std::array<u8, ElfIdentSize> Elf32Ident{
  80. 0x7f, 'E', 'L', 'F', ElfClass32, ElfData2Lsb, ElfVersionCurrent, ElfOsAbiNone};
  81. constexpr std::array<u8, ElfIdentSize> Elf64Ident{
  82. 0x7f, 'E', 'L', 'F', ElfClass64, ElfData2Lsb, ElfVersionCurrent, ElfOsAbiNone};
  83. /* Section header. */
  84. struct Elf32_Shdr {
  85. Elf32_Word sh_name; /* Section name (string tbl index) */
  86. Elf32_Word sh_type; /* Section type */
  87. Elf32_Word sh_flags; /* Section flags */
  88. Elf32_Addr sh_addr; /* Section virtual addr at execution */
  89. Elf32_Off sh_offset; /* Section file offset */
  90. Elf32_Word sh_size; /* Section size in bytes */
  91. Elf32_Word sh_link; /* Link to another section */
  92. Elf32_Word sh_info; /* Additional section information */
  93. Elf32_Word sh_addralign; /* Section alignment */
  94. Elf32_Word sh_entsize; /* Entry size if section holds table */
  95. };
  96. struct Elf64_Shdr {
  97. Elf64_Word sh_name; /* Section name (string tbl index) */
  98. Elf64_Word sh_type; /* Section type */
  99. Elf64_Xword sh_flags; /* Section flags */
  100. Elf64_Addr sh_addr; /* Section virtual addr at execution */
  101. Elf64_Off sh_offset; /* Section file offset */
  102. Elf64_Xword sh_size; /* Section size in bytes */
  103. Elf64_Word sh_link; /* Link to another section */
  104. Elf64_Word sh_info; /* Additional section information */
  105. Elf64_Xword sh_addralign; /* Section alignment */
  106. Elf64_Xword sh_entsize; /* Entry size if section holds table */
  107. };
  108. constexpr u32 ElfShnUndef = 0; /* Undefined section */
  109. constexpr u32 ElfShtNull = 0; /* Section header table entry unused */
  110. constexpr u32 ElfShtProgBits = 1; /* Program data */
  111. constexpr u32 ElfShtSymtab = 2; /* Symbol table */
  112. constexpr u32 ElfShtStrtab = 3; /* String table */
  113. constexpr u32 ElfShtRela = 4; /* Relocation entries with addends */
  114. constexpr u32 ElfShtDynamic = 6; /* Dynamic linking information */
  115. constexpr u32 ElfShtNobits = 7; /* Program space with no data (bss) */
  116. constexpr u32 ElfShtRel = 9; /* Relocation entries, no addends */
  117. constexpr u32 ElfShtDynsym = 11; /* Dynamic linker symbol table */
  118. /* Symbol table entry. */
  119. struct Elf32_Sym {
  120. Elf32_Word st_name; /* Symbol name (string tbl index) */
  121. Elf32_Addr st_value; /* Symbol value */
  122. Elf32_Word st_size; /* Symbol size */
  123. u8 st_info; /* Symbol type and binding */
  124. u8 st_other; /* Symbol visibility */
  125. Elf32_Section st_shndx; /* Section index */
  126. };
  127. struct Elf64_Sym {
  128. Elf64_Word st_name; /* Symbol name (string tbl index) */
  129. u8 st_info; /* Symbol type and binding */
  130. u8 st_other; /* Symbol visibility */
  131. Elf64_Section st_shndx; /* Section index */
  132. Elf64_Addr st_value; /* Symbol value */
  133. Elf64_Xword st_size; /* Symbol size */
  134. };
  135. /* How to extract and insert information held in the st_info field. */
  136. static inline u8 ElfStBind(u8 st_info) {
  137. return st_info >> 4;
  138. }
  139. static inline u8 ElfStType(u8 st_info) {
  140. return st_info & 0xf;
  141. }
  142. static inline u8 ElfStInfo(u8 st_bind, u8 st_type) {
  143. return static_cast<u8>((st_bind << 4) + (st_type & 0xf));
  144. }
  145. constexpr u8 ElfBindLocal = 0; /* Local symbol */
  146. constexpr u8 ElfBindGlobal = 1; /* Global symbol */
  147. constexpr u8 ElfBindWeak = 2; /* Weak symbol */
  148. constexpr u8 ElfTypeUnspec = 0; /* Symbol type is unspecified */
  149. constexpr u8 ElfTypeObject = 1; /* Symbol is a data object */
  150. constexpr u8 ElfTypeFunc = 2; /* Symbol is a code object */
  151. static inline u8 ElfStVisibility(u8 st_other) {
  152. return static_cast<u8>(st_other & 0x3);
  153. }
  154. constexpr u8 ElfVisibilityDefault = 0; /* Default symbol visibility rules */
  155. constexpr u8 ElfVisibilityInternal = 1; /* Processor specific hidden class */
  156. constexpr u8 ElfVisibilityHidden = 2; /* Sym unavailable in other modules */
  157. constexpr u8 ElfVisibilityProtected = 3; /* Not preemptible, not exported */
  158. /* Relocation table entry without addend (in section of type ShtRel). */
  159. struct Elf32_Rel {
  160. Elf32_Addr r_offset; /* Address */
  161. Elf32_Word r_info; /* Relocation type and symbol index */
  162. };
  163. /* Relocation table entry with addend (in section of type ShtRela). */
  164. struct Elf32_Rela {
  165. Elf32_Addr r_offset; /* Address */
  166. Elf32_Word r_info; /* Relocation type and symbol index */
  167. Elf32_Sword r_addend; /* Addend */
  168. };
  169. struct Elf64_Rela {
  170. Elf64_Addr r_offset; /* Address */
  171. Elf64_Xword r_info; /* Relocation type and symbol index */
  172. Elf64_Sxword r_addend; /* Addend */
  173. };
  174. /* RELR relocation table entry */
  175. using Elf32_Relr = Elf32_Word;
  176. using Elf64_Relr = Elf64_Xword;
  177. /* How to extract and insert information held in the r_info field. */
  178. static inline u32 Elf32RelSymIndex(Elf32_Word r_info) {
  179. return r_info >> 8;
  180. }
  181. static inline u8 Elf32RelType(Elf32_Word r_info) {
  182. return static_cast<u8>(r_info & 0xff);
  183. }
  184. static inline Elf32_Word Elf32RelInfo(u32 sym_index, u8 type) {
  185. return (sym_index << 8) + type;
  186. }
  187. static inline u32 Elf64RelSymIndex(Elf64_Xword r_info) {
  188. return static_cast<u32>(r_info >> 32);
  189. }
  190. static inline u32 Elf64RelType(Elf64_Xword r_info) {
  191. return r_info & 0xffffffff;
  192. }
  193. static inline Elf64_Xword Elf64RelInfo(u32 sym_index, u32 type) {
  194. return (static_cast<Elf64_Xword>(sym_index) << 32) + type;
  195. }
  196. constexpr u32 ElfArmCopy = 20; /* Copy symbol at runtime */
  197. constexpr u32 ElfArmGlobDat = 21; /* Create GOT entry */
  198. constexpr u32 ElfArmJumpSlot = 22; /* Create PLT entry */
  199. constexpr u32 ElfArmRelative = 23; /* Adjust by program base */
  200. constexpr u32 ElfAArch64Copy = 1024; /* Copy symbol at runtime */
  201. constexpr u32 ElfAArch64GlobDat = 1025; /* Create GOT entry */
  202. constexpr u32 ElfAArch64JumpSlot = 1026; /* Create PLT entry */
  203. constexpr u32 ElfAArch64Relative = 1027; /* Adjust by program base */
  204. /* Program segment header. */
  205. struct Elf32_Phdr {
  206. Elf32_Word p_type; /* Segment type */
  207. Elf32_Off p_offset; /* Segment file offset */
  208. Elf32_Addr p_vaddr; /* Segment virtual address */
  209. Elf32_Addr p_paddr; /* Segment physical address */
  210. Elf32_Word p_filesz; /* Segment size in file */
  211. Elf32_Word p_memsz; /* Segment size in memory */
  212. Elf32_Word p_flags; /* Segment flags */
  213. Elf32_Word p_align; /* Segment alignment */
  214. };
  215. struct Elf64_Phdr {
  216. Elf64_Word p_type; /* Segment type */
  217. Elf64_Word p_flags; /* Segment flags */
  218. Elf64_Off p_offset; /* Segment file offset */
  219. Elf64_Addr p_vaddr; /* Segment virtual address */
  220. Elf64_Addr p_paddr; /* Segment physical address */
  221. Elf64_Xword p_filesz; /* Segment size in file */
  222. Elf64_Xword p_memsz; /* Segment size in memory */
  223. Elf64_Xword p_align; /* Segment alignment */
  224. };
  225. /* Legal values for p_type (segment type). */
  226. constexpr u32 ElfPtNull = 0; /* Program header table entry unused */
  227. constexpr u32 ElfPtLoad = 1; /* Loadable program segment */
  228. constexpr u32 ElfPtDynamic = 2; /* Dynamic linking information */
  229. constexpr u32 ElfPtInterp = 3; /* Program interpreter */
  230. constexpr u32 ElfPtNote = 4; /* Auxiliary information */
  231. constexpr u32 ElfPtPhdr = 6; /* Entry for header table itself */
  232. constexpr u32 ElfPtTls = 7; /* Thread-local storage segment */
  233. /* Legal values for p_flags (segment flags). */
  234. constexpr u32 ElfPfExec = 0; /* Segment is executable */
  235. constexpr u32 ElfPfWrite = 1; /* Segment is writable */
  236. constexpr u32 ElfPfRead = 2; /* Segment is readable */
  237. /* Dynamic section entry. */
  238. struct Elf32_Dyn {
  239. Elf32_Sword d_tag; /* Dynamic entry type */
  240. union {
  241. Elf32_Word d_val; /* Integer value */
  242. Elf32_Addr d_ptr; /* Address value */
  243. } d_un;
  244. };
  245. struct Elf64_Dyn {
  246. Elf64_Sxword d_tag; /* Dynamic entry type */
  247. union {
  248. Elf64_Xword d_val; /* Integer value */
  249. Elf64_Addr d_ptr; /* Address value */
  250. } d_un;
  251. };
  252. /* Legal values for d_tag (dynamic entry type). */
  253. constexpr u32 ElfDtNull = 0; /* Marks end of dynamic section */
  254. constexpr u32 ElfDtNeeded = 1; /* Name of needed library */
  255. constexpr u32 ElfDtPltRelSz = 2; /* Size in bytes of PLT relocs */
  256. constexpr u32 ElfDtPltGot = 3; /* Processor defined value */
  257. constexpr u32 ElfDtHash = 4; /* Address of symbol hash table */
  258. constexpr u32 ElfDtStrtab = 5; /* Address of string table */
  259. constexpr u32 ElfDtSymtab = 6; /* Address of symbol table */
  260. constexpr u32 ElfDtRela = 7; /* Address of Rela relocs */
  261. constexpr u32 ElfDtRelasz = 8; /* Total size of Rela relocs */
  262. constexpr u32 ElfDtRelaent = 9; /* Size of one Rela reloc */
  263. constexpr u32 ElfDtStrsz = 10; /* Size of string table */
  264. constexpr u32 ElfDtSyment = 11; /* Size of one symbol table entry */
  265. constexpr u32 ElfDtInit = 12; /* Address of init function */
  266. constexpr u32 ElfDtFini = 13; /* Address of termination function */
  267. constexpr u32 ElfDtRel = 17; /* Address of Rel relocs */
  268. constexpr u32 ElfDtRelsz = 18; /* Total size of Rel relocs */
  269. constexpr u32 ElfDtRelent = 19; /* Size of one Rel reloc */
  270. constexpr u32 ElfDtPltRel = 20; /* Type of reloc in PLT */
  271. constexpr u32 ElfDtTextRel = 22; /* Reloc might modify .text */
  272. constexpr u32 ElfDtJmpRel = 23; /* Address of PLT relocs */
  273. constexpr u32 ElfDtBindNow = 24; /* Process relocations of object */
  274. constexpr u32 ElfDtInitArray = 25; /* Array with addresses of init fct */
  275. constexpr u32 ElfDtFiniArray = 26; /* Array with addresses of fini fct */
  276. constexpr u32 ElfDtInitArraySz = 27; /* Size in bytes of DT_INIT_ARRAY */
  277. constexpr u32 ElfDtFiniArraySz = 28; /* Size in bytes of DT_FINI_ARRAY */
  278. constexpr u32 ElfDtSymtabShndx = 34; /* Address of SYMTAB_SHNDX section */
  279. constexpr u32 ElfDtRelrsz = 35; /* Size of RELR relative relocations */
  280. constexpr u32 ElfDtRelr = 36; /* Address of RELR relative relocations */
  281. constexpr u32 ElfDtRelrent = 37; /* Size of one RELR relative relocation */
  282. } // namespace ELF
  283. } // namespace Common