diff options
| author | 2016-09-18 09:38:01 +0900 | |
|---|---|---|
| committer | 2016-09-18 09:38:01 +0900 | |
| commit | dc8479928c5aee4c6ad6fe4f59006fb604cee701 (patch) | |
| tree | 569a7f13128450bbab973236615587ff00bced5f /src/core/loader/elf.cpp | |
| parent | Travis: Import Dolphin’s clang-format hook. (diff) | |
| download | yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.gz yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.xz yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.zip | |
Sources: Run clang-format on everything.
Diffstat (limited to 'src/core/loader/elf.cpp')
| -rw-r--r-- | src/core/loader/elf.cpp | 231 |
1 files changed, 127 insertions, 104 deletions
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 69df94324..53c10a456 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include <string> | ||
| 7 | #include <memory> | 6 | #include <memory> |
| 7 | #include <string> | ||
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/file_util.h" | 10 | #include "common/file_util.h" |
| @@ -24,112 +24,111 @@ using Kernel::CodeSet; | |||
| 24 | 24 | ||
| 25 | // File type | 25 | // File type |
| 26 | enum ElfType { | 26 | enum ElfType { |
| 27 | ET_NONE = 0, | 27 | ET_NONE = 0, |
| 28 | ET_REL = 1, | 28 | ET_REL = 1, |
| 29 | ET_EXEC = 2, | 29 | ET_EXEC = 2, |
| 30 | ET_DYN = 3, | 30 | ET_DYN = 3, |
| 31 | ET_CORE = 4, | 31 | ET_CORE = 4, |
| 32 | ET_LOPROC = 0xFF00, | 32 | ET_LOPROC = 0xFF00, |
| 33 | ET_HIPROC = 0xFFFF, | 33 | ET_HIPROC = 0xFFFF, |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | // Machine/Architecture | 36 | // Machine/Architecture |
| 37 | enum ElfMachine { | 37 | enum ElfMachine { |
| 38 | EM_NONE = 0, | 38 | EM_NONE = 0, |
| 39 | EM_M32 = 1, | 39 | EM_M32 = 1, |
| 40 | EM_SPARC = 2, | 40 | EM_SPARC = 2, |
| 41 | EM_386 = 3, | 41 | EM_386 = 3, |
| 42 | EM_68K = 4, | 42 | EM_68K = 4, |
| 43 | EM_88K = 5, | 43 | EM_88K = 5, |
| 44 | EM_860 = 7, | 44 | EM_860 = 7, |
| 45 | EM_MIPS = 8 | 45 | EM_MIPS = 8 |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | // File version | 48 | // File version |
| 49 | #define EV_NONE 0 | 49 | #define EV_NONE 0 |
| 50 | #define EV_CURRENT 1 | 50 | #define EV_CURRENT 1 |
| 51 | 51 | ||
| 52 | // Identification index | 52 | // Identification index |
| 53 | #define EI_MAG0 0 | 53 | #define EI_MAG0 0 |
| 54 | #define EI_MAG1 1 | 54 | #define EI_MAG1 1 |
| 55 | #define EI_MAG2 2 | 55 | #define EI_MAG2 2 |
| 56 | #define EI_MAG3 3 | 56 | #define EI_MAG3 3 |
| 57 | #define EI_CLASS 4 | 57 | #define EI_CLASS 4 |
| 58 | #define EI_DATA 5 | 58 | #define EI_DATA 5 |
| 59 | #define EI_VERSION 6 | 59 | #define EI_VERSION 6 |
| 60 | #define EI_PAD 7 | 60 | #define EI_PAD 7 |
| 61 | #define EI_NIDENT 16 | 61 | #define EI_NIDENT 16 |
| 62 | 62 | ||
| 63 | // Sections constants | 63 | // Sections constants |
| 64 | 64 | ||
| 65 | // Section types | 65 | // Section types |
| 66 | #define SHT_NULL 0 | 66 | #define SHT_NULL 0 |
| 67 | #define SHT_PROGBITS 1 | 67 | #define SHT_PROGBITS 1 |
| 68 | #define SHT_SYMTAB 2 | 68 | #define SHT_SYMTAB 2 |
| 69 | #define SHT_STRTAB 3 | 69 | #define SHT_STRTAB 3 |
| 70 | #define SHT_RELA 4 | 70 | #define SHT_RELA 4 |
| 71 | #define SHT_HASH 5 | 71 | #define SHT_HASH 5 |
| 72 | #define SHT_DYNAMIC 6 | 72 | #define SHT_DYNAMIC 6 |
| 73 | #define SHT_NOTE 7 | 73 | #define SHT_NOTE 7 |
| 74 | #define SHT_NOBITS 8 | 74 | #define SHT_NOBITS 8 |
| 75 | #define SHT_REL 9 | 75 | #define SHT_REL 9 |
| 76 | #define SHT_SHLIB 10 | 76 | #define SHT_SHLIB 10 |
| 77 | #define SHT_DYNSYM 11 | 77 | #define SHT_DYNSYM 11 |
| 78 | #define SHT_LOPROC 0x70000000 | 78 | #define SHT_LOPROC 0x70000000 |
| 79 | #define SHT_HIPROC 0x7FFFFFFF | 79 | #define SHT_HIPROC 0x7FFFFFFF |
| 80 | #define SHT_LOUSER 0x80000000 | 80 | #define SHT_LOUSER 0x80000000 |
| 81 | #define SHT_HIUSER 0xFFFFFFFF | 81 | #define SHT_HIUSER 0xFFFFFFFF |
| 82 | 82 | ||
| 83 | // Section flags | 83 | // Section flags |
| 84 | enum ElfSectionFlags | 84 | enum ElfSectionFlags { |
| 85 | { | 85 | SHF_WRITE = 0x1, |
| 86 | SHF_WRITE = 0x1, | 86 | SHF_ALLOC = 0x2, |
| 87 | SHF_ALLOC = 0x2, | ||
| 88 | SHF_EXECINSTR = 0x4, | 87 | SHF_EXECINSTR = 0x4, |
| 89 | SHF_MASKPROC = 0xF0000000, | 88 | SHF_MASKPROC = 0xF0000000, |
| 90 | }; | 89 | }; |
| 91 | 90 | ||
| 92 | // Segment types | 91 | // Segment types |
| 93 | #define PT_NULL 0 | 92 | #define PT_NULL 0 |
| 94 | #define PT_LOAD 1 | 93 | #define PT_LOAD 1 |
| 95 | #define PT_DYNAMIC 2 | 94 | #define PT_DYNAMIC 2 |
| 96 | #define PT_INTERP 3 | 95 | #define PT_INTERP 3 |
| 97 | #define PT_NOTE 4 | 96 | #define PT_NOTE 4 |
| 98 | #define PT_SHLIB 5 | 97 | #define PT_SHLIB 5 |
| 99 | #define PT_PHDR 6 | 98 | #define PT_PHDR 6 |
| 100 | #define PT_LOPROC 0x70000000 | 99 | #define PT_LOPROC 0x70000000 |
| 101 | #define PT_HIPROC 0x7FFFFFFF | 100 | #define PT_HIPROC 0x7FFFFFFF |
| 102 | 101 | ||
| 103 | // Segment flags | 102 | // Segment flags |
| 104 | #define PF_X 0x1 | 103 | #define PF_X 0x1 |
| 105 | #define PF_W 0x2 | 104 | #define PF_W 0x2 |
| 106 | #define PF_R 0x4 | 105 | #define PF_R 0x4 |
| 107 | #define PF_MASKPROC 0xF0000000 | 106 | #define PF_MASKPROC 0xF0000000 |
| 108 | 107 | ||
| 109 | typedef unsigned int Elf32_Addr; | 108 | typedef unsigned int Elf32_Addr; |
| 110 | typedef unsigned short Elf32_Half; | 109 | typedef unsigned short Elf32_Half; |
| 111 | typedef unsigned int Elf32_Off; | 110 | typedef unsigned int Elf32_Off; |
| 112 | typedef signed int Elf32_Sword; | 111 | typedef signed int Elf32_Sword; |
| 113 | typedef unsigned int Elf32_Word; | 112 | typedef unsigned int Elf32_Word; |
| 114 | 113 | ||
| 115 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 114 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 116 | // ELF file header | 115 | // ELF file header |
| 117 | 116 | ||
| 118 | struct Elf32_Ehdr { | 117 | struct Elf32_Ehdr { |
| 119 | unsigned char e_ident[EI_NIDENT]; | 118 | unsigned char e_ident[EI_NIDENT]; |
| 120 | Elf32_Half e_type; | 119 | Elf32_Half e_type; |
| 121 | Elf32_Half e_machine; | 120 | Elf32_Half e_machine; |
| 122 | Elf32_Word e_version; | 121 | Elf32_Word e_version; |
| 123 | Elf32_Addr e_entry; | 122 | Elf32_Addr e_entry; |
| 124 | Elf32_Off e_phoff; | 123 | Elf32_Off e_phoff; |
| 125 | Elf32_Off e_shoff; | 124 | Elf32_Off e_shoff; |
| 126 | Elf32_Word e_flags; | 125 | Elf32_Word e_flags; |
| 127 | Elf32_Half e_ehsize; | 126 | Elf32_Half e_ehsize; |
| 128 | Elf32_Half e_phentsize; | 127 | Elf32_Half e_phentsize; |
| 129 | Elf32_Half e_phnum; | 128 | Elf32_Half e_phnum; |
| 130 | Elf32_Half e_shentsize; | 129 | Elf32_Half e_shentsize; |
| 131 | Elf32_Half e_shnum; | 130 | Elf32_Half e_shnum; |
| 132 | Elf32_Half e_shstrndx; | 131 | Elf32_Half e_shstrndx; |
| 133 | }; | 132 | }; |
| 134 | 133 | ||
| 135 | // Section header | 134 | // Section header |
| @@ -138,7 +137,7 @@ struct Elf32_Shdr { | |||
| 138 | Elf32_Word sh_type; | 137 | Elf32_Word sh_type; |
| 139 | Elf32_Word sh_flags; | 138 | Elf32_Word sh_flags; |
| 140 | Elf32_Addr sh_addr; | 139 | Elf32_Addr sh_addr; |
| 141 | Elf32_Off sh_offset; | 140 | Elf32_Off sh_offset; |
| 142 | Elf32_Word sh_size; | 141 | Elf32_Word sh_size; |
| 143 | Elf32_Word sh_link; | 142 | Elf32_Word sh_link; |
| 144 | Elf32_Word sh_info; | 143 | Elf32_Word sh_info; |
| @@ -149,7 +148,7 @@ struct Elf32_Shdr { | |||
| 149 | // Segment header | 148 | // Segment header |
| 150 | struct Elf32_Phdr { | 149 | struct Elf32_Phdr { |
| 151 | Elf32_Word p_type; | 150 | Elf32_Word p_type; |
| 152 | Elf32_Off p_offset; | 151 | Elf32_Off p_offset; |
| 153 | Elf32_Addr p_vaddr; | 152 | Elf32_Addr p_vaddr; |
| 154 | Elf32_Addr p_paddr; | 153 | Elf32_Addr p_paddr; |
| 155 | Elf32_Word p_filesz; | 154 | Elf32_Word p_filesz; |
| @@ -160,12 +159,12 @@ struct Elf32_Phdr { | |||
| 160 | 159 | ||
| 161 | // Symbol table entry | 160 | // Symbol table entry |
| 162 | struct Elf32_Sym { | 161 | struct Elf32_Sym { |
| 163 | Elf32_Word st_name; | 162 | Elf32_Word st_name; |
| 164 | Elf32_Addr st_value; | 163 | Elf32_Addr st_value; |
| 165 | Elf32_Word st_size; | 164 | Elf32_Word st_size; |
| 166 | unsigned char st_info; | 165 | unsigned char st_info; |
| 167 | unsigned char st_other; | 166 | unsigned char st_other; |
| 168 | Elf32_Half st_shndx; | 167 | Elf32_Half st_shndx; |
| 169 | }; | 168 | }; |
| 170 | 169 | ||
| 171 | // Relocation entries | 170 | // Relocation entries |
| @@ -181,35 +180,51 @@ typedef int SectionID; | |||
| 181 | 180 | ||
| 182 | class ElfReader { | 181 | class ElfReader { |
| 183 | private: | 182 | private: |
| 184 | char *base; | 183 | char* base; |
| 185 | u32 *base32; | 184 | u32* base32; |
| 186 | 185 | ||
| 187 | Elf32_Ehdr *header; | 186 | Elf32_Ehdr* header; |
| 188 | Elf32_Phdr *segments; | 187 | Elf32_Phdr* segments; |
| 189 | Elf32_Shdr *sections; | 188 | Elf32_Shdr* sections; |
| 190 | 189 | ||
| 191 | u32 *sectionAddrs; | 190 | u32* sectionAddrs; |
| 192 | bool relocate; | 191 | bool relocate; |
| 193 | u32 entryPoint; | 192 | u32 entryPoint; |
| 194 | 193 | ||
| 195 | public: | 194 | public: |
| 196 | ElfReader(void *ptr); | 195 | ElfReader(void* ptr); |
| 197 | 196 | ||
| 198 | u32 Read32(int off) const { return base32[off >> 2]; } | 197 | u32 Read32(int off) const { |
| 198 | return base32[off >> 2]; | ||
| 199 | } | ||
| 199 | 200 | ||
| 200 | // Quick accessors | 201 | // Quick accessors |
| 201 | ElfType GetType() const { return (ElfType)(header->e_type); } | 202 | ElfType GetType() const { |
| 202 | ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); } | 203 | return (ElfType)(header->e_type); |
| 203 | u32 GetEntryPoint() const { return entryPoint; } | 204 | } |
| 204 | u32 GetFlags() const { return (u32)(header->e_flags); } | 205 | ElfMachine GetMachine() const { |
| 206 | return (ElfMachine)(header->e_machine); | ||
| 207 | } | ||
| 208 | u32 GetEntryPoint() const { | ||
| 209 | return entryPoint; | ||
| 210 | } | ||
| 211 | u32 GetFlags() const { | ||
| 212 | return (u32)(header->e_flags); | ||
| 213 | } | ||
| 205 | SharedPtr<CodeSet> LoadInto(u32 vaddr); | 214 | SharedPtr<CodeSet> LoadInto(u32 vaddr); |
| 206 | bool LoadSymbols(); | 215 | bool LoadSymbols(); |
| 207 | 216 | ||
| 208 | int GetNumSegments() const { return (int)(header->e_phnum); } | 217 | int GetNumSegments() const { |
| 209 | int GetNumSections() const { return (int)(header->e_shnum); } | 218 | return (int)(header->e_phnum); |
| 210 | const u8 *GetPtr(int offset) const { return (u8*)base + offset; } | 219 | } |
| 211 | const char *GetSectionName(int section) const; | 220 | int GetNumSections() const { |
| 212 | const u8 *GetSectionDataPtr(int section) const { | 221 | return (int)(header->e_shnum); |
| 222 | } | ||
| 223 | const u8* GetPtr(int offset) const { | ||
| 224 | return (u8*)base + offset; | ||
| 225 | } | ||
| 226 | const char* GetSectionName(int section) const; | ||
| 227 | const u8* GetSectionDataPtr(int section) const { | ||
| 213 | if (section < 0 || section >= header->e_shnum) | 228 | if (section < 0 || section >= header->e_shnum) |
| 214 | return nullptr; | 229 | return nullptr; |
| 215 | if (sections[section].sh_type != SHT_NOBITS) | 230 | if (sections[section].sh_type != SHT_NOBITS) |
| @@ -220,19 +235,23 @@ public: | |||
| 220 | bool IsCodeSection(int section) const { | 235 | bool IsCodeSection(int section) const { |
| 221 | return sections[section].sh_type == SHT_PROGBITS; | 236 | return sections[section].sh_type == SHT_PROGBITS; |
| 222 | } | 237 | } |
| 223 | const u8 *GetSegmentPtr(int segment) { | 238 | const u8* GetSegmentPtr(int segment) { |
| 224 | return GetPtr(segments[segment].p_offset); | 239 | return GetPtr(segments[segment].p_offset); |
| 225 | } | 240 | } |
| 226 | u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; } | 241 | u32 GetSectionAddr(SectionID section) const { |
| 227 | unsigned int GetSectionSize(SectionID section) const { return sections[section].sh_size; } | 242 | return sectionAddrs[section]; |
| 228 | SectionID GetSectionByName(const char *name, int firstSection = 0) const; //-1 for not found | 243 | } |
| 244 | unsigned int GetSectionSize(SectionID section) const { | ||
| 245 | return sections[section].sh_size; | ||
| 246 | } | ||
| 247 | SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found | ||
| 229 | 248 | ||
| 230 | bool DidRelocate() const { | 249 | bool DidRelocate() const { |
| 231 | return relocate; | 250 | return relocate; |
| 232 | } | 251 | } |
| 233 | }; | 252 | }; |
| 234 | 253 | ||
| 235 | ElfReader::ElfReader(void *ptr) { | 254 | ElfReader::ElfReader(void* ptr) { |
| 236 | base = (char*)ptr; | 255 | base = (char*)ptr; |
| 237 | base32 = (u32*)ptr; | 256 | base32 = (u32*)ptr; |
| 238 | header = (Elf32_Ehdr*)ptr; | 257 | header = (Elf32_Ehdr*)ptr; |
| @@ -245,7 +264,7 @@ ElfReader::ElfReader(void *ptr) { | |||
| 245 | LoadSymbols(); | 264 | LoadSymbols(); |
| 246 | } | 265 | } |
| 247 | 266 | ||
| 248 | const char *ElfReader::GetSectionName(int section) const { | 267 | const char* ElfReader::GetSectionName(int section) const { |
| 249 | if (sections[section].sh_type == SHT_NULL) | 268 | if (sections[section].sh_type == SHT_NULL) |
| 250 | return nullptr; | 269 | return nullptr; |
| 251 | 270 | ||
| @@ -303,12 +322,15 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { | |||
| 303 | } else if (permission_flags == (PF_R | PF_W)) { | 322 | } else if (permission_flags == (PF_R | PF_W)) { |
| 304 | codeset_segment = &codeset->data; | 323 | codeset_segment = &codeset->data; |
| 305 | } else { | 324 | } else { |
| 306 | LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i, p->p_flags); | 325 | LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i, |
| 326 | p->p_flags); | ||
| 307 | continue; | 327 | continue; |
| 308 | } | 328 | } |
| 309 | 329 | ||
| 310 | if (codeset_segment->size != 0) { | 330 | if (codeset_segment->size != 0) { |
| 311 | LOG_ERROR(Loader, "ELF has more than one segment of the same type. Skipping extra segment (id %i)", i); | 331 | LOG_ERROR(Loader, "ELF has more than one segment of the same type. Skipping extra " |
| 332 | "segment (id %i)", | ||
| 333 | i); | ||
| 312 | continue; | 334 | continue; |
| 313 | } | 335 | } |
| 314 | 336 | ||
| @@ -332,9 +354,9 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { | |||
| 332 | return codeset; | 354 | return codeset; |
| 333 | } | 355 | } |
| 334 | 356 | ||
| 335 | SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const { | 357 | SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const { |
| 336 | for (int i = firstSection; i < header->e_shnum; i++) { | 358 | for (int i = firstSection; i < header->e_shnum; i++) { |
| 337 | const char *secname = GetSectionName(i); | 359 | const char* secname = GetSectionName(i); |
| 338 | 360 | ||
| 339 | if (secname != nullptr && strcmp(name, secname) == 0) | 361 | if (secname != nullptr && strcmp(name, secname) == 0) |
| 340 | return i; | 362 | return i; |
| @@ -347,9 +369,9 @@ bool ElfReader::LoadSymbols() { | |||
| 347 | SectionID sec = GetSectionByName(".symtab"); | 369 | SectionID sec = GetSectionByName(".symtab"); |
| 348 | if (sec != -1) { | 370 | if (sec != -1) { |
| 349 | int stringSection = sections[sec].sh_link; | 371 | int stringSection = sections[sec].sh_link; |
| 350 | const char *stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection)); | 372 | const char* stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection)); |
| 351 | 373 | ||
| 352 | //We have a symbol table! | 374 | // We have a symbol table! |
| 353 | const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec)); | 375 | const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec)); |
| 354 | unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); | 376 | unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); |
| 355 | for (unsigned sym = 0; sym < numSymbols; sym++) { | 377 | for (unsigned sym = 0; sym < numSymbols; sym++) { |
| @@ -359,7 +381,7 @@ bool ElfReader::LoadSymbols() { | |||
| 359 | 381 | ||
| 360 | int type = symtab[sym].st_info & 0xF; | 382 | int type = symtab[sym].st_info & 0xF; |
| 361 | 383 | ||
| 362 | const char *name = stringBase + symtab[sym].st_name; | 384 | const char* name = stringBase + symtab[sym].st_name; |
| 363 | 385 | ||
| 364 | Symbols::Add(symtab[sym].st_value, name, size, type); | 386 | Symbols::Add(symtab[sym].st_value, name, size, type); |
| 365 | 387 | ||
| @@ -411,7 +433,8 @@ ResultStatus AppLoader_ELF::Load() { | |||
| 411 | Kernel::g_current_process->address_mappings = default_address_mappings; | 433 | Kernel::g_current_process->address_mappings = default_address_mappings; |
| 412 | 434 | ||
| 413 | // Attach the default resource limit (APPLICATION) to the process | 435 | // Attach the default resource limit (APPLICATION) to the process |
| 414 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 436 | Kernel::g_current_process->resource_limit = |
| 437 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | ||
| 415 | 438 | ||
| 416 | Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); | 439 | Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); |
| 417 | 440 | ||