summaryrefslogtreecommitdiff
path: root/src/core/loader/elf.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2015-01-20 12:55:28 -0500
committerGravatar bunnei2015-01-20 12:55:28 -0500
commit205170fa623efdd5eafb0c957d728babe4836f45 (patch)
tree26dd9e4c7ae9cc7a3bb09f42c942c4e47c9cc06f /src/core/loader/elf.cpp
parentMerge pull request #496 from lioncash/warn (diff)
parentLoader: Clean up the ELF AppLoader. (diff)
downloadyuzu-205170fa623efdd5eafb0c957d728babe4836f45.tar.gz
yuzu-205170fa623efdd5eafb0c957d728babe4836f45.tar.xz
yuzu-205170fa623efdd5eafb0c957d728babe4836f45.zip
Merge pull request #241 from linkmauve/better-loader
Improve the loader a bit
Diffstat (limited to 'src/core/loader/elf.cpp')
-rw-r--r--src/core/loader/elf.cpp116
1 files changed, 53 insertions, 63 deletions
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 3ca60c072..e7e5df408 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -18,25 +18,25 @@
18 18
19// File type 19// File type
20enum ElfType { 20enum ElfType {
21 ET_NONE = 0, 21 ET_NONE = 0,
22 ET_REL = 1, 22 ET_REL = 1,
23 ET_EXEC = 2, 23 ET_EXEC = 2,
24 ET_DYN = 3, 24 ET_DYN = 3,
25 ET_CORE = 4, 25 ET_CORE = 4,
26 ET_LOPROC = 0xFF00, 26 ET_LOPROC = 0xFF00,
27 ET_HIPROC = 0xFFFF, 27 ET_HIPROC = 0xFFFF,
28}; 28};
29 29
30// Machine/Architecture 30// Machine/Architecture
31enum ElfMachine { 31enum ElfMachine {
32 EM_NONE = 0, 32 EM_NONE = 0,
33 EM_M32 = 1, 33 EM_M32 = 1,
34 EM_SPARC = 2, 34 EM_SPARC = 2,
35 EM_386 = 3, 35 EM_386 = 3,
36 EM_68K = 4, 36 EM_68K = 4,
37 EM_88K = 5, 37 EM_88K = 5,
38 EM_860 = 7, 38 EM_860 = 7,
39 EM_MIPS = 8 39 EM_MIPS = 8
40}; 40};
41 41
42// File version 42// File version
@@ -54,12 +54,6 @@ enum ElfMachine {
54#define EI_PAD 7 54#define EI_PAD 7
55#define EI_NIDENT 16 55#define EI_NIDENT 16
56 56
57// Magic number
58#define ELFMAG0 0x7F
59#define ELFMAG1 'E'
60#define ELFMAG2 'L'
61#define ELFMAG3 'F'
62
63// Sections constants 57// Sections constants
64 58
65// Section types 59// Section types
@@ -83,10 +77,10 @@ enum ElfMachine {
83// Section flags 77// Section flags
84enum ElfSectionFlags 78enum ElfSectionFlags
85{ 79{
86 SHF_WRITE = 0x1, 80 SHF_WRITE = 0x1,
87 SHF_ALLOC = 0x2, 81 SHF_ALLOC = 0x2,
88 SHF_EXECINSTR = 0x4, 82 SHF_EXECINSTR = 0x4,
89 SHF_MASKPROC = 0xF0000000, 83 SHF_MASKPROC = 0xF0000000,
90}; 84};
91 85
92// Segment types 86// Segment types
@@ -100,11 +94,11 @@ enum ElfSectionFlags
100#define PT_LOPROC 0x70000000 94#define PT_LOPROC 0x70000000
101#define PT_HIPROC 0x7FFFFFFF 95#define PT_HIPROC 0x7FFFFFFF
102 96
103typedef unsigned int Elf32_Addr; 97typedef unsigned int Elf32_Addr;
104typedef unsigned short Elf32_Half; 98typedef unsigned short Elf32_Half;
105typedef unsigned int Elf32_Off; 99typedef unsigned int Elf32_Off;
106typedef signed int Elf32_Sword; 100typedef signed int Elf32_Sword;
107typedef unsigned int Elf32_Word; 101typedef unsigned int Elf32_Word;
108 102
109//////////////////////////////////////////////////////////////////////////////////////////////////// 103////////////////////////////////////////////////////////////////////////////////////////////////////
110// ELF file header 104// ELF file header
@@ -188,7 +182,6 @@ private:
188 182
189public: 183public:
190 ElfReader(void *ptr); 184 ElfReader(void *ptr);
191 ~ElfReader() { }
192 185
193 u32 Read32(int off) const { return base32[off >> 2]; } 186 u32 Read32(int off) const { return base32[off >> 2]; }
194 187
@@ -197,7 +190,7 @@ public:
197 ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); } 190 ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); }
198 u32 GetEntryPoint() const { return entryPoint; } 191 u32 GetEntryPoint() const { return entryPoint; }
199 u32 GetFlags() const { return (u32)(header->e_flags); } 192 u32 GetFlags() const { return (u32)(header->e_flags); }
200 bool LoadInto(u32 vaddr); 193 void LoadInto(u32 vaddr);
201 bool LoadSymbols(); 194 bool LoadSymbols();
202 195
203 int GetNumSegments() const { return (int)(header->e_phnum); } 196 int GetNumSegments() const { return (int)(header->e_phnum); }
@@ -229,11 +222,11 @@ public:
229 222
230ElfReader::ElfReader(void *ptr) { 223ElfReader::ElfReader(void *ptr) {
231 base = (char*)ptr; 224 base = (char*)ptr;
232 base32 = (u32 *)ptr; 225 base32 = (u32*)ptr;
233 header = (Elf32_Ehdr*)ptr; 226 header = (Elf32_Ehdr*)ptr;
234 227
235 segments = (Elf32_Phdr *)(base + header->e_phoff); 228 segments = (Elf32_Phdr*)(base + header->e_phoff);
236 sections = (Elf32_Shdr *)(base + header->e_shoff); 229 sections = (Elf32_Shdr*)(base + header->e_shoff);
237 230
238 entryPoint = header->e_entry; 231 entryPoint = header->e_entry;
239 232
@@ -245,7 +238,7 @@ const char *ElfReader::GetSectionName(int section) const {
245 return nullptr; 238 return nullptr;
246 239
247 int name_offset = sections[section].sh_name; 240 int name_offset = sections[section].sh_name;
248 char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx); 241 const char* ptr = (char*)GetSectionDataPtr(header->e_shstrndx);
249 242
250 if (ptr) 243 if (ptr)
251 return ptr + name_offset; 244 return ptr + name_offset;
@@ -253,7 +246,7 @@ const char *ElfReader::GetSectionName(int section) const {
253 return nullptr; 246 return nullptr;
254} 247}
255 248
256bool ElfReader::LoadInto(u32 vaddr) { 249void ElfReader::LoadInto(u32 vaddr) {
257 LOG_DEBUG(Loader, "String section: %i", header->e_shstrndx); 250 LOG_DEBUG(Loader, "String section: %i", header->e_shstrndx);
258 251
259 // Should we relocate? 252 // Should we relocate?
@@ -271,20 +264,19 @@ bool ElfReader::LoadInto(u32 vaddr) {
271 u32 segment_addr[32]; 264 u32 segment_addr[32];
272 u32 base_addr = relocate ? vaddr : 0; 265 u32 base_addr = relocate ? vaddr : 0;
273 266
274 for (int i = 0; i < header->e_phnum; i++) { 267 for (unsigned i = 0; i < header->e_phnum; i++) {
275 Elf32_Phdr *p = segments + i; 268 Elf32_Phdr* p = segments + i;
276 LOG_DEBUG(Loader, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr, 269 LOG_DEBUG(Loader, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr,
277 p->p_filesz, p->p_memsz); 270 p->p_filesz, p->p_memsz);
278 271
279 if (p->p_type == PT_LOAD) { 272 if (p->p_type == PT_LOAD) {
280 segment_addr[i] = base_addr + p->p_vaddr; 273 segment_addr[i] = base_addr + p->p_vaddr;
281 memcpy(Memory::GetPointer(segment_addr[i]), GetSegmentPtr(i), p->p_filesz); 274 memcpy(Memory::GetPointer(segment_addr[i]), GetSegmentPtr(i), p->p_filesz);
282 LOG_DEBUG(Loader, "Loadable Segment Copied to %08x, size %08x", segment_addr[i], 275 LOG_DEBUG(Loader, "Loadable Segment Copied to %08x, size %08x", segment_addr[i],
283 p->p_memsz); 276 p->p_memsz);
284 } 277 }
285 } 278 }
286 LOG_DEBUG(Loader, "Done loading."); 279 LOG_DEBUG(Loader, "Done loading.");
287 return true;
288} 280}
289 281
290SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const { 282SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const {
@@ -305,9 +297,9 @@ bool ElfReader::LoadSymbols() {
305 const char *stringBase = (const char *)GetSectionDataPtr(stringSection); 297 const char *stringBase = (const char *)GetSectionDataPtr(stringSection);
306 298
307 //We have a symbol table! 299 //We have a symbol table!
308 Elf32_Sym *symtab = (Elf32_Sym *)(GetSectionDataPtr(sec)); 300 Elf32_Sym* symtab = (Elf32_Sym *)(GetSectionDataPtr(sec));
309 int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); 301 int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
310 for (int sym = 0; sym < numSymbols; sym++) { 302 for (unsigned sym = 0; sym < numSymbols; sym++) {
311 int size = symtab[sym].st_size; 303 int size = symtab[sym].st_size;
312 if (size == 0) 304 if (size == 0)
313 continue; 305 continue;
@@ -330,40 +322,38 @@ bool ElfReader::LoadSymbols() {
330 322
331namespace Loader { 323namespace Loader {
332 324
333/// AppLoader_ELF constructor 325FileType AppLoader_ELF::IdentifyType(FileUtil::IOFile& file) {
334AppLoader_ELF::AppLoader_ELF(const std::string& filename) : is_loaded(false) { 326 u32 magic;
335 this->filename = filename; 327 file.Seek(0, SEEK_SET);
336} 328 if (1 != file.ReadArray<u32>(&magic, 1))
329 return FileType::Error;
330
331 if (MakeMagic('\x7f', 'E', 'L', 'F') == magic)
332 return FileType::ELF;
337 333
338/// AppLoader_NCCH destructor 334 return FileType::Error;
339AppLoader_ELF::~AppLoader_ELF() {
340} 335}
341 336
342/**
343 * Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI)
344 * @param error_string Pointer to string to put error message if an error has occurred
345 * @todo Move NCSD parsing out of here and create a separate function for loading these
346 * @return True on success, otherwise false
347 */
348ResultStatus AppLoader_ELF::Load() { 337ResultStatus AppLoader_ELF::Load() {
349 LOG_INFO(Loader, "Loading ELF file %s...", filename.c_str());
350
351 if (is_loaded) 338 if (is_loaded)
352 return ResultStatus::ErrorAlreadyLoaded; 339 return ResultStatus::ErrorAlreadyLoaded;
353 340
354 FileUtil::IOFile file(filename, "rb"); 341 if (!file->IsOpen())
342 return ResultStatus::Error;
355 343
356 if (file.IsOpen()) { 344 // Reset read pointer in case this file has been read before.
357 u32 size = (u32)file.GetSize(); 345 file->Seek(0, SEEK_SET);
358 std::unique_ptr<u8[]> buffer(new u8[size]);
359 file.ReadBytes(&buffer[0], size);
360 346
361 ElfReader elf_reader(&buffer[0]); 347 u32 size = static_cast<u32>(file->GetSize());
362 elf_reader.LoadInto(0x00100000); 348 std::unique_ptr<u8[]> buffer(new u8[size]);
363 Kernel::LoadExec(elf_reader.GetEntryPoint()); 349 if (file->ReadBytes(&buffer[0], size) != size)
364 } else {
365 return ResultStatus::Error; 350 return ResultStatus::Error;
366 } 351
352 ElfReader elf_reader(&buffer[0]);
353 elf_reader.LoadInto(0x00100000);
354 Kernel::LoadExec(elf_reader.GetEntryPoint());
355
356 is_loaded = true;
367 return ResultStatus::Success; 357 return ResultStatus::Success;
368} 358}
369 359