1 // Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #include <cstring>
6 #include <memory>
7 #include <string>
8 #include "common/common_funcs.h"
9 #include "common/common_types.h"
10 #include "common/file_util.h"
11 #include "common/logging/log.h"
12 #include "core/hle/kernel/code_set.h"
13 #include "core/hle/kernel/memory/page_table.h"
14 #include "core/hle/kernel/process.h"
15 #include "core/loader/elf.h"
16 #include "core/memory.h"
17 
18 ////////////////////////////////////////////////////////////////////////////////////////////////////
19 // ELF Header Constants
20 
21 // File type
22 enum ElfType {
23     ET_NONE = 0,
24     ET_REL = 1,
25     ET_EXEC = 2,
26     ET_DYN = 3,
27     ET_CORE = 4,
28     ET_LOPROC = 0xFF00,
29     ET_HIPROC = 0xFFFF,
30 };
31 
32 // Machine/Architecture
33 enum ElfMachine {
34     EM_NONE = 0,
35     EM_M32 = 1,
36     EM_SPARC = 2,
37     EM_386 = 3,
38     EM_68K = 4,
39     EM_88K = 5,
40     EM_860 = 7,
41     EM_MIPS = 8
42 };
43 
44 // File version
45 #define EV_NONE 0
46 #define EV_CURRENT 1
47 
48 // Identification index
49 #define EI_MAG0 0
50 #define EI_MAG1 1
51 #define EI_MAG2 2
52 #define EI_MAG3 3
53 #define EI_CLASS 4
54 #define EI_DATA 5
55 #define EI_VERSION 6
56 #define EI_PAD 7
57 #define EI_NIDENT 16
58 
59 // Sections constants
60 
61 // Section types
62 #define SHT_NULL 0
63 #define SHT_PROGBITS 1
64 #define SHT_SYMTAB 2
65 #define SHT_STRTAB 3
66 #define SHT_RELA 4
67 #define SHT_HASH 5
68 #define SHT_DYNAMIC 6
69 #define SHT_NOTE 7
70 #define SHT_NOBITS 8
71 #define SHT_REL 9
72 #define SHT_SHLIB 10
73 #define SHT_DYNSYM 11
74 #define SHT_LOPROC 0x70000000
75 #define SHT_HIPROC 0x7FFFFFFF
76 #define SHT_LOUSER 0x80000000
77 #define SHT_HIUSER 0xFFFFFFFF
78 
79 // Section flags
80 enum ElfSectionFlags {
81     SHF_WRITE = 0x1,
82     SHF_ALLOC = 0x2,
83     SHF_EXECINSTR = 0x4,
84     SHF_MASKPROC = 0xF0000000,
85 };
86 
87 // Segment types
88 #define PT_NULL 0
89 #define PT_LOAD 1
90 #define PT_DYNAMIC 2
91 #define PT_INTERP 3
92 #define PT_NOTE 4
93 #define PT_SHLIB 5
94 #define PT_PHDR 6
95 #define PT_LOPROC 0x70000000
96 #define PT_HIPROC 0x7FFFFFFF
97 
98 // Segment flags
99 #define PF_X 0x1
100 #define PF_W 0x2
101 #define PF_R 0x4
102 #define PF_MASKPROC 0xF0000000
103 
104 typedef unsigned int Elf32_Addr;
105 typedef unsigned short Elf32_Half;
106 typedef unsigned int Elf32_Off;
107 typedef signed int Elf32_Sword;
108 typedef unsigned int Elf32_Word;
109 
110 ////////////////////////////////////////////////////////////////////////////////////////////////////
111 // ELF file header
112 
113 struct Elf32_Ehdr {
114     unsigned char e_ident[EI_NIDENT];
115     Elf32_Half e_type;
116     Elf32_Half e_machine;
117     Elf32_Word e_version;
118     Elf32_Addr e_entry;
119     Elf32_Off e_phoff;
120     Elf32_Off e_shoff;
121     Elf32_Word e_flags;
122     Elf32_Half e_ehsize;
123     Elf32_Half e_phentsize;
124     Elf32_Half e_phnum;
125     Elf32_Half e_shentsize;
126     Elf32_Half e_shnum;
127     Elf32_Half e_shstrndx;
128 };
129 
130 // Section header
131 struct Elf32_Shdr {
132     Elf32_Word sh_name;
133     Elf32_Word sh_type;
134     Elf32_Word sh_flags;
135     Elf32_Addr sh_addr;
136     Elf32_Off sh_offset;
137     Elf32_Word sh_size;
138     Elf32_Word sh_link;
139     Elf32_Word sh_info;
140     Elf32_Word sh_addralign;
141     Elf32_Word sh_entsize;
142 };
143 
144 // Segment header
145 struct Elf32_Phdr {
146     Elf32_Word p_type;
147     Elf32_Off p_offset;
148     Elf32_Addr p_vaddr;
149     Elf32_Addr p_paddr;
150     Elf32_Word p_filesz;
151     Elf32_Word p_memsz;
152     Elf32_Word p_flags;
153     Elf32_Word p_align;
154 };
155 
156 // Symbol table entry
157 struct Elf32_Sym {
158     Elf32_Word st_name;
159     Elf32_Addr st_value;
160     Elf32_Word st_size;
161     unsigned char st_info;
162     unsigned char st_other;
163     Elf32_Half st_shndx;
164 };
165 
166 // Relocation entries
167 struct Elf32_Rel {
168     Elf32_Addr r_offset;
169     Elf32_Word r_info;
170 };
171 
172 ////////////////////////////////////////////////////////////////////////////////////////////////////
173 // ElfReader class
174 
175 typedef int SectionID;
176 
177 class ElfReader {
178 private:
179     char* base;
180     u32* base32;
181 
182     Elf32_Ehdr* header;
183     Elf32_Phdr* segments;
184     Elf32_Shdr* sections;
185 
186     u32* sectionAddrs;
187     bool relocate;
188     VAddr entryPoint;
189 
190 public:
191     explicit ElfReader(void* ptr);
192 
Read32(int off) const193     u32 Read32(int off) const {
194         return base32[off >> 2];
195     }
196 
197     // Quick accessors
GetType() const198     ElfType GetType() const {
199         return (ElfType)(header->e_type);
200     }
GetMachine() const201     ElfMachine GetMachine() const {
202         return (ElfMachine)(header->e_machine);
203     }
GetEntryPoint() const204     VAddr GetEntryPoint() const {
205         return entryPoint;
206     }
GetFlags() const207     u32 GetFlags() const {
208         return (u32)(header->e_flags);
209     }
210     Kernel::CodeSet LoadInto(VAddr vaddr);
211 
GetNumSegments() const212     int GetNumSegments() const {
213         return (int)(header->e_phnum);
214     }
GetNumSections() const215     int GetNumSections() const {
216         return (int)(header->e_shnum);
217     }
GetPtr(int offset) const218     const u8* GetPtr(int offset) const {
219         return (u8*)base + offset;
220     }
221     const char* GetSectionName(int section) const;
GetSectionDataPtr(int section) const222     const u8* GetSectionDataPtr(int section) const {
223         if (section < 0 || section >= header->e_shnum)
224             return nullptr;
225         if (sections[section].sh_type != SHT_NOBITS)
226             return GetPtr(sections[section].sh_offset);
227         else
228             return nullptr;
229     }
IsCodeSection(int section) const230     bool IsCodeSection(int section) const {
231         return sections[section].sh_type == SHT_PROGBITS;
232     }
GetSegmentPtr(int segment)233     const u8* GetSegmentPtr(int segment) {
234         return GetPtr(segments[segment].p_offset);
235     }
GetSectionAddr(SectionID section) const236     u32 GetSectionAddr(SectionID section) const {
237         return sectionAddrs[section];
238     }
GetSectionSize(SectionID section) const239     unsigned int GetSectionSize(SectionID section) const {
240         return sections[section].sh_size;
241     }
242     SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found
243 
DidRelocate() const244     bool DidRelocate() const {
245         return relocate;
246     }
247 };
248 
ElfReader(void * ptr)249 ElfReader::ElfReader(void* ptr) {
250     base = (char*)ptr;
251     base32 = (u32*)ptr;
252     header = (Elf32_Ehdr*)ptr;
253 
254     segments = (Elf32_Phdr*)(base + header->e_phoff);
255     sections = (Elf32_Shdr*)(base + header->e_shoff);
256 
257     entryPoint = header->e_entry;
258 }
259 
GetSectionName(int section) const260 const char* ElfReader::GetSectionName(int section) const {
261     if (sections[section].sh_type == SHT_NULL)
262         return nullptr;
263 
264     int name_offset = sections[section].sh_name;
265     const char* ptr = reinterpret_cast<const char*>(GetSectionDataPtr(header->e_shstrndx));
266 
267     if (ptr)
268         return ptr + name_offset;
269 
270     return nullptr;
271 }
272 
LoadInto(VAddr vaddr)273 Kernel::CodeSet ElfReader::LoadInto(VAddr vaddr) {
274     LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx);
275 
276     // Should we relocate?
277     relocate = (header->e_type != ET_EXEC);
278 
279     if (relocate) {
280         LOG_DEBUG(Loader, "Relocatable module");
281         entryPoint += vaddr;
282     } else {
283         LOG_DEBUG(Loader, "Prerelocated executable");
284     }
285     LOG_DEBUG(Loader, "{} segments:", header->e_phnum);
286 
287     // First pass : Get the bits into RAM
288     const VAddr base_addr = relocate ? vaddr : 0;
289 
290     u64 total_image_size = 0;
291     for (unsigned int i = 0; i < header->e_phnum; ++i) {
292         const Elf32_Phdr* p = &segments[i];
293         if (p->p_type == PT_LOAD) {
294             total_image_size += (p->p_memsz + 0xFFF) & ~0xFFF;
295         }
296     }
297 
298     Kernel::PhysicalMemory program_image(total_image_size);
299     std::size_t current_image_position = 0;
300 
301     Kernel::CodeSet codeset;
302 
303     for (unsigned int i = 0; i < header->e_phnum; ++i) {
304         const Elf32_Phdr* p = &segments[i];
305         LOG_DEBUG(Loader, "Type: {} Vaddr: {:08X} Filesz: {:08X} Memsz: {:08X} ", p->p_type,
306                   p->p_vaddr, p->p_filesz, p->p_memsz);
307 
308         if (p->p_type == PT_LOAD) {
309             Kernel::CodeSet::Segment* codeset_segment;
310             u32 permission_flags = p->p_flags & (PF_R | PF_W | PF_X);
311             if (permission_flags == (PF_R | PF_X)) {
312                 codeset_segment = &codeset.CodeSegment();
313             } else if (permission_flags == (PF_R)) {
314                 codeset_segment = &codeset.RODataSegment();
315             } else if (permission_flags == (PF_R | PF_W)) {
316                 codeset_segment = &codeset.DataSegment();
317             } else {
318                 LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id {} with flags {:X}", i,
319                           p->p_flags);
320                 continue;
321             }
322 
323             if (codeset_segment->size != 0) {
324                 LOG_ERROR(Loader,
325                           "ELF has more than one segment of the same type. Skipping extra "
326                           "segment (id {})",
327                           i);
328                 continue;
329             }
330 
331             const VAddr segment_addr = base_addr + p->p_vaddr;
332             const u32 aligned_size = (p->p_memsz + 0xFFF) & ~0xFFF;
333 
334             codeset_segment->offset = current_image_position;
335             codeset_segment->addr = segment_addr;
336             codeset_segment->size = aligned_size;
337 
338             std::memcpy(program_image.data() + current_image_position, GetSegmentPtr(i),
339                         p->p_filesz);
340             current_image_position += aligned_size;
341         }
342     }
343 
344     codeset.entrypoint = base_addr + header->e_entry;
345     codeset.memory = std::move(program_image);
346 
347     LOG_DEBUG(Loader, "Done loading.");
348 
349     return codeset;
350 }
351 
GetSectionByName(const char * name,int firstSection) const352 SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const {
353     for (int i = firstSection; i < header->e_shnum; i++) {
354         const char* secname = GetSectionName(i);
355 
356         if (secname != nullptr && strcmp(name, secname) == 0)
357             return i;
358     }
359     return -1;
360 }
361 
362 ////////////////////////////////////////////////////////////////////////////////////////////////////
363 // Loader namespace
364 
365 namespace Loader {
366 
AppLoader_ELF(FileSys::VirtualFile file)367 AppLoader_ELF::AppLoader_ELF(FileSys::VirtualFile file) : AppLoader(std::move(file)) {}
368 
IdentifyType(const FileSys::VirtualFile & file)369 FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& file) {
370     static constexpr u16 ELF_MACHINE_ARM{0x28};
371 
372     u32 magic = 0;
373     if (4 != file->ReadObject(&magic))
374         return FileType::Error;
375 
376     u16 machine = 0;
377     if (2 != file->ReadObject(&machine, 18))
378         return FileType::Error;
379 
380     if (Common::MakeMagic('\x7f', 'E', 'L', 'F') == magic && ELF_MACHINE_ARM == machine)
381         return FileType::ELF;
382 
383     return FileType::Error;
384 }
385 
Load(Kernel::Process & process,Core::System & system)386 AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::Process& process,
387                                               [[maybe_unused]] Core::System& system) {
388     if (is_loaded) {
389         return {ResultStatus::ErrorAlreadyLoaded, {}};
390     }
391 
392     std::vector<u8> buffer = file->ReadAllBytes();
393     if (buffer.size() != file->GetSize()) {
394         return {ResultStatus::ErrorIncorrectELFFileSize, {}};
395     }
396 
397     const VAddr base_address = process.PageTable().GetCodeRegionStart();
398     ElfReader elf_reader(&buffer[0]);
399     Kernel::CodeSet codeset = elf_reader.LoadInto(base_address);
400     const VAddr entry_point = codeset.entrypoint;
401 
402     // Setup the process code layout
403     if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), buffer.size()).IsError()) {
404         return {ResultStatus::ErrorNotInitialized, {}};
405     }
406 
407     process.LoadModule(std::move(codeset), entry_point);
408 
409     is_loaded = true;
410     return {ResultStatus::Success, LoadParameters{48, Core::Memory::DEFAULT_STACK_SIZE}};
411 }
412 
413 } // namespace Loader
414