summaryrefslogtreecommitdiff
path: root/src/core/loader/elf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader/elf.cpp')
-rw-r--r--src/core/loader/elf.cpp231
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
26enum ElfType { 26enum 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
37enum ElfMachine { 37enum 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
84enum ElfSectionFlags 84enum 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
109typedef unsigned int Elf32_Addr; 108typedef unsigned int Elf32_Addr;
110typedef unsigned short Elf32_Half; 109typedef unsigned short Elf32_Half;
111typedef unsigned int Elf32_Off; 110typedef unsigned int Elf32_Off;
112typedef signed int Elf32_Sword; 111typedef signed int Elf32_Sword;
113typedef unsigned int Elf32_Word; 112typedef unsigned int Elf32_Word;
114 113
115//////////////////////////////////////////////////////////////////////////////////////////////////// 114////////////////////////////////////////////////////////////////////////////////////////////////////
116// ELF file header 115// ELF file header
117 116
118struct Elf32_Ehdr { 117struct 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
150struct Elf32_Phdr { 149struct 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
162struct Elf32_Sym { 161struct 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
182class ElfReader { 181class ElfReader {
183private: 182private:
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
195public: 194public:
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
235ElfReader::ElfReader(void *ptr) { 254ElfReader::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
248const char *ElfReader::GetSectionName(int section) const { 267const 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
335SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const { 357SectionID 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