summaryrefslogtreecommitdiff
path: root/src/core/loader
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader')
-rw-r--r--src/core/loader/3dsx.cpp87
-rw-r--r--src/core/loader/3dsx.h7
-rw-r--r--src/core/loader/elf.cpp233
-rw-r--r--src/core/loader/elf.h3
-rw-r--r--src/core/loader/loader.cpp17
-rw-r--r--src/core/loader/loader.h10
-rw-r--r--src/core/loader/ncch.cpp64
-rw-r--r--src/core/loader/ncch.h40
-rw-r--r--src/core/loader/smdh.cpp3
-rw-r--r--src/core/loader/smdh.h3
10 files changed, 243 insertions, 224 deletions
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index a16411e14..1c10740a0 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -4,9 +4,7 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <vector> 6#include <vector>
7
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9
10#include "core/file_sys/archive_romfs.h" 8#include "core/file_sys/archive_romfs.h"
11#include "core/hle/kernel/process.h" 9#include "core/hle/kernel/process.h"
12#include "core/hle/kernel/resource_limit.h" 10#include "core/hle/kernel/resource_limit.h"
@@ -37,20 +35,14 @@ namespace Loader {
37 * The BSS section must be cleared manually by the application. 35 * The BSS section must be cleared manually by the application.
38 */ 36 */
39 37
40enum THREEDSX_Error { 38enum THREEDSX_Error { ERROR_NONE = 0, ERROR_READ = 1, ERROR_FILE = 2, ERROR_ALLOC = 3 };
41 ERROR_NONE = 0,
42 ERROR_READ = 1,
43 ERROR_FILE = 2,
44 ERROR_ALLOC = 3
45};
46 39
47static const u32 RELOCBUFSIZE = 512; 40static const u32 RELOCBUFSIZE = 512;
48static const unsigned int NUM_SEGMENTS = 3; 41static const unsigned int NUM_SEGMENTS = 3;
49 42
50// File header 43// File header
51#pragma pack(1) 44#pragma pack(1)
52struct THREEDSX_Header 45struct THREEDSX_Header {
53{
54 u32 magic; 46 u32 magic;
55 u16 header_size, reloc_hdr_size; 47 u16 header_size, reloc_hdr_size;
56 u32 format_ver; 48 u32 format_ver;
@@ -66,11 +58,11 @@ struct THREEDSX_Header
66}; 58};
67 59
68// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts. 60// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts.
69struct THREEDSX_RelocHdr 61struct THREEDSX_RelocHdr {
70{
71 // # of absolute relocations (that is, fix address to post-relocation memory layout) 62 // # of absolute relocations (that is, fix address to post-relocation memory layout)
72 u32 cross_segment_absolute; 63 u32 cross_segment_absolute;
73 // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched) 64 // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be
65 // patched)
74 u32 cross_segment_relative; 66 u32 cross_segment_relative;
75 // more? 67 // more?
76 68
@@ -80,21 +72,18 @@ struct THREEDSX_RelocHdr
80}; 72};
81 73
82// Relocation entry: from the current pointer, skip X words and patch Y words 74// Relocation entry: from the current pointer, skip X words and patch Y words
83struct THREEDSX_Reloc 75struct THREEDSX_Reloc {
84{
85 u16 skip, patch; 76 u16 skip, patch;
86}; 77};
87#pragma pack() 78#pragma pack()
88 79
89struct THREEloadinfo 80struct THREEloadinfo {
90{
91 u8* seg_ptrs[3]; // code, rodata & data 81 u8* seg_ptrs[3]; // code, rodata & data
92 u32 seg_addrs[3]; 82 u32 seg_addrs[3];
93 u32 seg_sizes[3]; 83 u32 seg_sizes[3];
94}; 84};
95 85
96static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets) 86static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets) {
97{
98 if (addr < offsets[0]) 87 if (addr < offsets[0])
99 return loadinfo->seg_addrs[0] + addr; 88 return loadinfo->seg_addrs[0] + addr;
100 if (addr < offsets[1]) 89 if (addr < offsets[1])
@@ -105,8 +94,8 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets)
105using Kernel::SharedPtr; 94using Kernel::SharedPtr;
106using Kernel::CodeSet; 95using Kernel::CodeSet;
107 96
108static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, SharedPtr<CodeSet>* out_codeset) 97static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
109{ 98 SharedPtr<CodeSet>* out_codeset) {
110 if (!file.IsOpen()) 99 if (!file.IsOpen())
111 return ERROR_FILE; 100 return ERROR_FILE;
112 101
@@ -118,13 +107,14 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
118 return ERROR_READ; 107 return ERROR_READ;
119 108
120 THREEloadinfo loadinfo; 109 THREEloadinfo loadinfo;
121 //loadinfo segments must be a multiple of 0x1000 110 // loadinfo segments must be a multiple of 0x1000
122 loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) &~0xFFF; 111 loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) & ~0xFFF;
123 loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF; 112 loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) & ~0xFFF;
124 loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF; 113 loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) & ~0xFFF;
125 u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] }; 114 u32 offsets[2] = {loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1]};
126 u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32); 115 u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32);
127 std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]); 116 std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] +
117 loadinfo.seg_sizes[2]);
128 118
129 loadinfo.seg_addrs[0] = base_addr; 119 loadinfo.seg_addrs[0] = base_addr;
130 loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0]; 120 loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0];
@@ -149,7 +139,8 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
149 return ERROR_READ; 139 return ERROR_READ;
150 if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size) 140 if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size)
151 return ERROR_READ; 141 return ERROR_READ;
152 if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) != hdr.data_seg_size - hdr.bss_size) 142 if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) !=
143 hdr.data_seg_size - hdr.bss_size)
153 return ERROR_READ; 144 return ERROR_READ;
154 145
155 // BSS clear 146 // BSS clear
@@ -157,11 +148,12 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
157 148
158 // Relocate the segments 149 // Relocate the segments
159 for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) { 150 for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) {
160 for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { 151 for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables;
152 current_segment_reloc_table++) {
161 u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; 153 u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table];
162 if (current_segment_reloc_table >= 2) { 154 if (current_segment_reloc_table >= 2) {
163 // We are not using this table - ignore it because we don't know what it dose 155 // We are not using this table - ignore it because we don't know what it dose
164 file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR); 156 file.Seek(n_relocs * sizeof(THREEDSX_Reloc), SEEK_CUR);
165 continue; 157 continue;
166 } 158 }
167 THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; 159 THREEDSX_Reloc reloc_table[RELOCBUFSIZE];
@@ -173,17 +165,20 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
173 u32 remaining = std::min(RELOCBUFSIZE, n_relocs); 165 u32 remaining = std::min(RELOCBUFSIZE, n_relocs);
174 n_relocs -= remaining; 166 n_relocs -= remaining;
175 167
176 if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) != remaining * sizeof(THREEDSX_Reloc)) 168 if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) !=
169 remaining * sizeof(THREEDSX_Reloc))
177 return ERROR_READ; 170 return ERROR_READ;
178 171
179 for (unsigned current_inprogress = 0; current_inprogress < remaining && pos < end_pos; current_inprogress++) { 172 for (unsigned current_inprogress = 0;
173 current_inprogress < remaining && pos < end_pos; current_inprogress++) {
180 const auto& table = reloc_table[current_inprogress]; 174 const auto& table = reloc_table[current_inprogress];
181 LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table, 175 LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table,
182 static_cast<u32>(table.skip), static_cast<u32>(table.patch)); 176 static_cast<u32>(table.skip), static_cast<u32>(table.patch));
183 pos += table.skip; 177 pos += table.skip;
184 s32 num_patches = table.patch; 178 s32 num_patches = table.patch;
185 while (0 < num_patches && pos < end_pos) { 179 while (0 < num_patches && pos < end_pos) {
186 u32 in_addr = static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data()); 180 u32 in_addr =
181 static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data());
187 u32 addr = TranslateAddr(*pos, &loadinfo, offsets); 182 u32 addr = TranslateAddr(*pos, &loadinfo, offsets);
188 LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)", 183 LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)",
189 base_addr + in_addr, addr, current_segment_reloc_table, *pos); 184 base_addr + in_addr, addr, current_segment_reloc_table, *pos);
@@ -195,7 +190,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
195 *pos = static_cast<u32>(addr - in_addr); 190 *pos = static_cast<u32>(addr - in_addr);
196 break; 191 break;
197 default: 192 default:
198 break; //this should never happen 193 break; // this should never happen
199 } 194 }
200 pos++; 195 pos++;
201 num_patches--; 196 num_patches--;
@@ -209,23 +204,24 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
209 SharedPtr<CodeSet> code_set = CodeSet::Create("", 0); 204 SharedPtr<CodeSet> code_set = CodeSet::Create("", 0);
210 205
211 code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data(); 206 code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data();
212 code_set->code.addr = loadinfo.seg_addrs[0]; 207 code_set->code.addr = loadinfo.seg_addrs[0];
213 code_set->code.size = loadinfo.seg_sizes[0]; 208 code_set->code.size = loadinfo.seg_sizes[0];
214 209
215 code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data(); 210 code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data();
216 code_set->rodata.addr = loadinfo.seg_addrs[1]; 211 code_set->rodata.addr = loadinfo.seg_addrs[1];
217 code_set->rodata.size = loadinfo.seg_sizes[1]; 212 code_set->rodata.size = loadinfo.seg_sizes[1];
218 213
219 code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data(); 214 code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data();
220 code_set->data.addr = loadinfo.seg_addrs[2]; 215 code_set->data.addr = loadinfo.seg_addrs[2];
221 code_set->data.size = loadinfo.seg_sizes[2]; 216 code_set->data.size = loadinfo.seg_sizes[2];
222 217
223 code_set->entrypoint = code_set->code.addr; 218 code_set->entrypoint = code_set->code.addr;
224 code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); 219 code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
225 220
226 LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]); 221 LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]);
227 LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]); 222 LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]);
228 LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2], hdr.bss_size); 223 LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2],
224 hdr.bss_size);
229 225
230 *out_codeset = code_set; 226 *out_codeset = code_set;
231 return ERROR_NONE; 227 return ERROR_NONE;
@@ -260,17 +256,20 @@ ResultStatus AppLoader_THREEDSX::Load() {
260 Kernel::g_current_process->address_mappings = default_address_mappings; 256 Kernel::g_current_process->address_mappings = default_address_mappings;
261 257
262 // Attach the default resource limit (APPLICATION) to the process 258 // Attach the default resource limit (APPLICATION) to the process
263 Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); 259 Kernel::g_current_process->resource_limit =
260 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
264 261
265 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); 262 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
266 263
267 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS); 264 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this),
265 Service::FS::ArchiveIdCode::RomFS);
268 266
269 is_loaded = true; 267 is_loaded = true;
270 return ResultStatus::Success; 268 return ResultStatus::Success;
271} 269}
272 270
273ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 271ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file,
272 u64& offset, u64& size) {
274 if (!file.IsOpen()) 273 if (!file.IsOpen())
275 return ResultStatus::Error; 274 return ResultStatus::Error;
276 275
diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h
index 90b20c61c..cfcc21cc4 100644
--- a/src/core/loader/3dsx.h
+++ b/src/core/loader/3dsx.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "core/loader/loader.h" 9#include "core/loader/loader.h"
11 10
@@ -17,7 +16,8 @@ namespace Loader {
17/// Loads an 3DSX file 16/// Loads an 3DSX file
18class AppLoader_THREEDSX final : public AppLoader { 17class AppLoader_THREEDSX final : public AppLoader {
19public: 18public:
20 AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename, const std::string& filepath) 19 AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename,
20 const std::string& filepath)
21 : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {} 21 : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {}
22 22
23 /** 23 /**
@@ -55,7 +55,8 @@ public:
55 * @param size Size of the RomFS in bytes 55 * @param size Size of the RomFS in bytes
56 * @return ResultStatus result of function 56 * @return ResultStatus result of function
57 */ 57 */
58 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) override; 58 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
59 u64& size) override;
59 60
60private: 61private:
61 std::string filename; 62 std::string filename;
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 69df94324..8eb5200ab 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -3,14 +3,12 @@
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>
8 7#include <string>
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "common/file_util.h" 9#include "common/file_util.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "common/symbols.h" 11#include "common/symbols.h"
13
14#include "core/hle/kernel/process.h" 12#include "core/hle/kernel/process.h"
15#include "core/hle/kernel/resource_limit.h" 13#include "core/hle/kernel/resource_limit.h"
16#include "core/loader/elf.h" 14#include "core/loader/elf.h"
@@ -24,112 +22,111 @@ using Kernel::CodeSet;
24 22
25// File type 23// File type
26enum ElfType { 24enum ElfType {
27 ET_NONE = 0, 25 ET_NONE = 0,
28 ET_REL = 1, 26 ET_REL = 1,
29 ET_EXEC = 2, 27 ET_EXEC = 2,
30 ET_DYN = 3, 28 ET_DYN = 3,
31 ET_CORE = 4, 29 ET_CORE = 4,
32 ET_LOPROC = 0xFF00, 30 ET_LOPROC = 0xFF00,
33 ET_HIPROC = 0xFFFF, 31 ET_HIPROC = 0xFFFF,
34}; 32};
35 33
36// Machine/Architecture 34// Machine/Architecture
37enum ElfMachine { 35enum ElfMachine {
38 EM_NONE = 0, 36 EM_NONE = 0,
39 EM_M32 = 1, 37 EM_M32 = 1,
40 EM_SPARC = 2, 38 EM_SPARC = 2,
41 EM_386 = 3, 39 EM_386 = 3,
42 EM_68K = 4, 40 EM_68K = 4,
43 EM_88K = 5, 41 EM_88K = 5,
44 EM_860 = 7, 42 EM_860 = 7,
45 EM_MIPS = 8 43 EM_MIPS = 8
46}; 44};
47 45
48// File version 46// File version
49#define EV_NONE 0 47#define EV_NONE 0
50#define EV_CURRENT 1 48#define EV_CURRENT 1
51 49
52// Identification index 50// Identification index
53#define EI_MAG0 0 51#define EI_MAG0 0
54#define EI_MAG1 1 52#define EI_MAG1 1
55#define EI_MAG2 2 53#define EI_MAG2 2
56#define EI_MAG3 3 54#define EI_MAG3 3
57#define EI_CLASS 4 55#define EI_CLASS 4
58#define EI_DATA 5 56#define EI_DATA 5
59#define EI_VERSION 6 57#define EI_VERSION 6
60#define EI_PAD 7 58#define EI_PAD 7
61#define EI_NIDENT 16 59#define EI_NIDENT 16
62 60
63// Sections constants 61// Sections constants
64 62
65// Section types 63// Section types
66#define SHT_NULL 0 64#define SHT_NULL 0
67#define SHT_PROGBITS 1 65#define SHT_PROGBITS 1
68#define SHT_SYMTAB 2 66#define SHT_SYMTAB 2
69#define SHT_STRTAB 3 67#define SHT_STRTAB 3
70#define SHT_RELA 4 68#define SHT_RELA 4
71#define SHT_HASH 5 69#define SHT_HASH 5
72#define SHT_DYNAMIC 6 70#define SHT_DYNAMIC 6
73#define SHT_NOTE 7 71#define SHT_NOTE 7
74#define SHT_NOBITS 8 72#define SHT_NOBITS 8
75#define SHT_REL 9 73#define SHT_REL 9
76#define SHT_SHLIB 10 74#define SHT_SHLIB 10
77#define SHT_DYNSYM 11 75#define SHT_DYNSYM 11
78#define SHT_LOPROC 0x70000000 76#define SHT_LOPROC 0x70000000
79#define SHT_HIPROC 0x7FFFFFFF 77#define SHT_HIPROC 0x7FFFFFFF
80#define SHT_LOUSER 0x80000000 78#define SHT_LOUSER 0x80000000
81#define SHT_HIUSER 0xFFFFFFFF 79#define SHT_HIUSER 0xFFFFFFFF
82 80
83// Section flags 81// Section flags
84enum ElfSectionFlags 82enum ElfSectionFlags {
85{ 83 SHF_WRITE = 0x1,
86 SHF_WRITE = 0x1, 84 SHF_ALLOC = 0x2,
87 SHF_ALLOC = 0x2,
88 SHF_EXECINSTR = 0x4, 85 SHF_EXECINSTR = 0x4,
89 SHF_MASKPROC = 0xF0000000, 86 SHF_MASKPROC = 0xF0000000,
90}; 87};
91 88
92// Segment types 89// Segment types
93#define PT_NULL 0 90#define PT_NULL 0
94#define PT_LOAD 1 91#define PT_LOAD 1
95#define PT_DYNAMIC 2 92#define PT_DYNAMIC 2
96#define PT_INTERP 3 93#define PT_INTERP 3
97#define PT_NOTE 4 94#define PT_NOTE 4
98#define PT_SHLIB 5 95#define PT_SHLIB 5
99#define PT_PHDR 6 96#define PT_PHDR 6
100#define PT_LOPROC 0x70000000 97#define PT_LOPROC 0x70000000
101#define PT_HIPROC 0x7FFFFFFF 98#define PT_HIPROC 0x7FFFFFFF
102 99
103// Segment flags 100// Segment flags
104#define PF_X 0x1 101#define PF_X 0x1
105#define PF_W 0x2 102#define PF_W 0x2
106#define PF_R 0x4 103#define PF_R 0x4
107#define PF_MASKPROC 0xF0000000 104#define PF_MASKPROC 0xF0000000
108 105
109typedef unsigned int Elf32_Addr; 106typedef unsigned int Elf32_Addr;
110typedef unsigned short Elf32_Half; 107typedef unsigned short Elf32_Half;
111typedef unsigned int Elf32_Off; 108typedef unsigned int Elf32_Off;
112typedef signed int Elf32_Sword; 109typedef signed int Elf32_Sword;
113typedef unsigned int Elf32_Word; 110typedef unsigned int Elf32_Word;
114 111
115//////////////////////////////////////////////////////////////////////////////////////////////////// 112////////////////////////////////////////////////////////////////////////////////////////////////////
116// ELF file header 113// ELF file header
117 114
118struct Elf32_Ehdr { 115struct Elf32_Ehdr {
119 unsigned char e_ident[EI_NIDENT]; 116 unsigned char e_ident[EI_NIDENT];
120 Elf32_Half e_type; 117 Elf32_Half e_type;
121 Elf32_Half e_machine; 118 Elf32_Half e_machine;
122 Elf32_Word e_version; 119 Elf32_Word e_version;
123 Elf32_Addr e_entry; 120 Elf32_Addr e_entry;
124 Elf32_Off e_phoff; 121 Elf32_Off e_phoff;
125 Elf32_Off e_shoff; 122 Elf32_Off e_shoff;
126 Elf32_Word e_flags; 123 Elf32_Word e_flags;
127 Elf32_Half e_ehsize; 124 Elf32_Half e_ehsize;
128 Elf32_Half e_phentsize; 125 Elf32_Half e_phentsize;
129 Elf32_Half e_phnum; 126 Elf32_Half e_phnum;
130 Elf32_Half e_shentsize; 127 Elf32_Half e_shentsize;
131 Elf32_Half e_shnum; 128 Elf32_Half e_shnum;
132 Elf32_Half e_shstrndx; 129 Elf32_Half e_shstrndx;
133}; 130};
134 131
135// Section header 132// Section header
@@ -138,7 +135,7 @@ struct Elf32_Shdr {
138 Elf32_Word sh_type; 135 Elf32_Word sh_type;
139 Elf32_Word sh_flags; 136 Elf32_Word sh_flags;
140 Elf32_Addr sh_addr; 137 Elf32_Addr sh_addr;
141 Elf32_Off sh_offset; 138 Elf32_Off sh_offset;
142 Elf32_Word sh_size; 139 Elf32_Word sh_size;
143 Elf32_Word sh_link; 140 Elf32_Word sh_link;
144 Elf32_Word sh_info; 141 Elf32_Word sh_info;
@@ -149,7 +146,7 @@ struct Elf32_Shdr {
149// Segment header 146// Segment header
150struct Elf32_Phdr { 147struct Elf32_Phdr {
151 Elf32_Word p_type; 148 Elf32_Word p_type;
152 Elf32_Off p_offset; 149 Elf32_Off p_offset;
153 Elf32_Addr p_vaddr; 150 Elf32_Addr p_vaddr;
154 Elf32_Addr p_paddr; 151 Elf32_Addr p_paddr;
155 Elf32_Word p_filesz; 152 Elf32_Word p_filesz;
@@ -160,12 +157,12 @@ struct Elf32_Phdr {
160 157
161// Symbol table entry 158// Symbol table entry
162struct Elf32_Sym { 159struct Elf32_Sym {
163 Elf32_Word st_name; 160 Elf32_Word st_name;
164 Elf32_Addr st_value; 161 Elf32_Addr st_value;
165 Elf32_Word st_size; 162 Elf32_Word st_size;
166 unsigned char st_info; 163 unsigned char st_info;
167 unsigned char st_other; 164 unsigned char st_other;
168 Elf32_Half st_shndx; 165 Elf32_Half st_shndx;
169}; 166};
170 167
171// Relocation entries 168// Relocation entries
@@ -181,35 +178,51 @@ typedef int SectionID;
181 178
182class ElfReader { 179class ElfReader {
183private: 180private:
184 char *base; 181 char* base;
185 u32 *base32; 182 u32* base32;
186 183
187 Elf32_Ehdr *header; 184 Elf32_Ehdr* header;
188 Elf32_Phdr *segments; 185 Elf32_Phdr* segments;
189 Elf32_Shdr *sections; 186 Elf32_Shdr* sections;
190 187
191 u32 *sectionAddrs; 188 u32* sectionAddrs;
192 bool relocate; 189 bool relocate;
193 u32 entryPoint; 190 u32 entryPoint;
194 191
195public: 192public:
196 ElfReader(void *ptr); 193 ElfReader(void* ptr);
197 194
198 u32 Read32(int off) const { return base32[off >> 2]; } 195 u32 Read32(int off) const {
196 return base32[off >> 2];
197 }
199 198
200 // Quick accessors 199 // Quick accessors
201 ElfType GetType() const { return (ElfType)(header->e_type); } 200 ElfType GetType() const {
202 ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); } 201 return (ElfType)(header->e_type);
203 u32 GetEntryPoint() const { return entryPoint; } 202 }
204 u32 GetFlags() const { return (u32)(header->e_flags); } 203 ElfMachine GetMachine() const {
204 return (ElfMachine)(header->e_machine);
205 }
206 u32 GetEntryPoint() const {
207 return entryPoint;
208 }
209 u32 GetFlags() const {
210 return (u32)(header->e_flags);
211 }
205 SharedPtr<CodeSet> LoadInto(u32 vaddr); 212 SharedPtr<CodeSet> LoadInto(u32 vaddr);
206 bool LoadSymbols(); 213 bool LoadSymbols();
207 214
208 int GetNumSegments() const { return (int)(header->e_phnum); } 215 int GetNumSegments() const {
209 int GetNumSections() const { return (int)(header->e_shnum); } 216 return (int)(header->e_phnum);
210 const u8 *GetPtr(int offset) const { return (u8*)base + offset; } 217 }
211 const char *GetSectionName(int section) const; 218 int GetNumSections() const {
212 const u8 *GetSectionDataPtr(int section) const { 219 return (int)(header->e_shnum);
220 }
221 const u8* GetPtr(int offset) const {
222 return (u8*)base + offset;
223 }
224 const char* GetSectionName(int section) const;
225 const u8* GetSectionDataPtr(int section) const {
213 if (section < 0 || section >= header->e_shnum) 226 if (section < 0 || section >= header->e_shnum)
214 return nullptr; 227 return nullptr;
215 if (sections[section].sh_type != SHT_NOBITS) 228 if (sections[section].sh_type != SHT_NOBITS)
@@ -220,19 +233,23 @@ public:
220 bool IsCodeSection(int section) const { 233 bool IsCodeSection(int section) const {
221 return sections[section].sh_type == SHT_PROGBITS; 234 return sections[section].sh_type == SHT_PROGBITS;
222 } 235 }
223 const u8 *GetSegmentPtr(int segment) { 236 const u8* GetSegmentPtr(int segment) {
224 return GetPtr(segments[segment].p_offset); 237 return GetPtr(segments[segment].p_offset);
225 } 238 }
226 u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; } 239 u32 GetSectionAddr(SectionID section) const {
227 unsigned int GetSectionSize(SectionID section) const { return sections[section].sh_size; } 240 return sectionAddrs[section];
228 SectionID GetSectionByName(const char *name, int firstSection = 0) const; //-1 for not found 241 }
242 unsigned int GetSectionSize(SectionID section) const {
243 return sections[section].sh_size;
244 }
245 SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found
229 246
230 bool DidRelocate() const { 247 bool DidRelocate() const {
231 return relocate; 248 return relocate;
232 } 249 }
233}; 250};
234 251
235ElfReader::ElfReader(void *ptr) { 252ElfReader::ElfReader(void* ptr) {
236 base = (char*)ptr; 253 base = (char*)ptr;
237 base32 = (u32*)ptr; 254 base32 = (u32*)ptr;
238 header = (Elf32_Ehdr*)ptr; 255 header = (Elf32_Ehdr*)ptr;
@@ -245,7 +262,7 @@ ElfReader::ElfReader(void *ptr) {
245 LoadSymbols(); 262 LoadSymbols();
246} 263}
247 264
248const char *ElfReader::GetSectionName(int section) const { 265const char* ElfReader::GetSectionName(int section) const {
249 if (sections[section].sh_type == SHT_NULL) 266 if (sections[section].sh_type == SHT_NULL)
250 return nullptr; 267 return nullptr;
251 268
@@ -303,12 +320,15 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
303 } else if (permission_flags == (PF_R | PF_W)) { 320 } else if (permission_flags == (PF_R | PF_W)) {
304 codeset_segment = &codeset->data; 321 codeset_segment = &codeset->data;
305 } else { 322 } else {
306 LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i, p->p_flags); 323 LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i,
324 p->p_flags);
307 continue; 325 continue;
308 } 326 }
309 327
310 if (codeset_segment->size != 0) { 328 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); 329 LOG_ERROR(Loader, "ELF has more than one segment of the same type. Skipping extra "
330 "segment (id %i)",
331 i);
312 continue; 332 continue;
313 } 333 }
314 334
@@ -332,9 +352,9 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
332 return codeset; 352 return codeset;
333} 353}
334 354
335SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const { 355SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const {
336 for (int i = firstSection; i < header->e_shnum; i++) { 356 for (int i = firstSection; i < header->e_shnum; i++) {
337 const char *secname = GetSectionName(i); 357 const char* secname = GetSectionName(i);
338 358
339 if (secname != nullptr && strcmp(name, secname) == 0) 359 if (secname != nullptr && strcmp(name, secname) == 0)
340 return i; 360 return i;
@@ -347,9 +367,9 @@ bool ElfReader::LoadSymbols() {
347 SectionID sec = GetSectionByName(".symtab"); 367 SectionID sec = GetSectionByName(".symtab");
348 if (sec != -1) { 368 if (sec != -1) {
349 int stringSection = sections[sec].sh_link; 369 int stringSection = sections[sec].sh_link;
350 const char *stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection)); 370 const char* stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection));
351 371
352 //We have a symbol table! 372 // We have a symbol table!
353 const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec)); 373 const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec));
354 unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); 374 unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
355 for (unsigned sym = 0; sym < numSymbols; sym++) { 375 for (unsigned sym = 0; sym < numSymbols; sym++) {
@@ -359,7 +379,7 @@ bool ElfReader::LoadSymbols() {
359 379
360 int type = symtab[sym].st_info & 0xF; 380 int type = symtab[sym].st_info & 0xF;
361 381
362 const char *name = stringBase + symtab[sym].st_name; 382 const char* name = stringBase + symtab[sym].st_name;
363 383
364 Symbols::Add(symtab[sym].st_value, name, size, type); 384 Symbols::Add(symtab[sym].st_value, name, size, type);
365 385
@@ -411,7 +431,8 @@ ResultStatus AppLoader_ELF::Load() {
411 Kernel::g_current_process->address_mappings = default_address_mappings; 431 Kernel::g_current_process->address_mappings = default_address_mappings;
412 432
413 // Attach the default resource limit (APPLICATION) to the process 433 // Attach the default resource limit (APPLICATION) to the process
414 Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); 434 Kernel::g_current_process->resource_limit =
435 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
415 436
416 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); 437 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
417 438
diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h
index cb3724f9d..584bf6e27 100644
--- a/src/core/loader/elf.h
+++ b/src/core/loader/elf.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "core/loader/loader.h" 9#include "core/loader/loader.h"
11 10
@@ -18,7 +17,7 @@ namespace Loader {
18class AppLoader_ELF final : public AppLoader { 17class AppLoader_ELF final : public AppLoader {
19public: 18public:
20 AppLoader_ELF(FileUtil::IOFile&& file, std::string filename) 19 AppLoader_ELF(FileUtil::IOFile&& file, std::string filename)
21 : AppLoader(std::move(file)), filename(std::move(filename)) { } 20 : AppLoader(std::move(file)), filename(std::move(filename)) {}
22 21
23 /** 22 /**
24 * Returns the type of the file 23 * Returns the type of the file
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 9719d30d5..147bf8591 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -4,10 +4,8 @@
4 4
5#include <memory> 5#include <memory>
6#include <string> 6#include <string>
7
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9#include "common/string_util.h" 8#include "common/string_util.h"
10
11#include "core/hle/kernel/process.h" 9#include "core/hle/kernel/process.h"
12#include "core/loader/3dsx.h" 10#include "core/loader/3dsx.h"
13#include "core/loader/elf.h" 11#include "core/loader/elf.h"
@@ -18,17 +16,17 @@
18namespace Loader { 16namespace Loader {
19 17
20const std::initializer_list<Kernel::AddressMapping> default_address_mappings = { 18const std::initializer_list<Kernel::AddressMapping> default_address_mappings = {
21 { 0x1FF50000, 0x8000, true }, // part of DSP RAM 19 {0x1FF50000, 0x8000, true}, // part of DSP RAM
22 { 0x1FF70000, 0x8000, true }, // part of DSP RAM 20 {0x1FF70000, 0x8000, true}, // part of DSP RAM
23 { 0x1F000000, 0x600000, false }, // entire VRAM 21 {0x1F000000, 0x600000, false}, // entire VRAM
24}; 22};
25 23
26FileType IdentifyFile(FileUtil::IOFile& file) { 24FileType IdentifyFile(FileUtil::IOFile& file) {
27 FileType type; 25 FileType type;
28 26
29#define CHECK_TYPE(loader) \ 27#define CHECK_TYPE(loader) \
30 type = AppLoader_##loader::IdentifyType(file); \ 28 type = AppLoader_##loader::IdentifyType(file); \
31 if (FileType::Error != type) \ 29 if (FileType::Error != type) \
32 return type; 30 return type;
33 31
34 CHECK_TYPE(THREEDSX) 32 CHECK_TYPE(THREEDSX)
@@ -100,7 +98,8 @@ const char* GetFileTypeString(FileType type) {
100 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type 98 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type
101 */ 99 */
102static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileType type, 100static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileType type,
103 const std::string& filename, const std::string& filepath) { 101 const std::string& filename,
102 const std::string& filepath) {
104 switch (type) { 103 switch (type) {
105 104
106 // 3DSX file format. 105 // 3DSX file format.
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 77d87afe1..9652d7ac5 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -9,7 +9,6 @@
9#include <memory> 9#include <memory>
10#include <string> 10#include <string>
11#include <vector> 11#include <vector>
12
13#include "common/common_types.h" 12#include "common/common_types.h"
14#include "common/file_util.h" 13#include "common/file_util.h"
15 14
@@ -30,7 +29,7 @@ enum class FileType {
30 CXI, 29 CXI,
31 CIA, 30 CIA,
32 ELF, 31 ELF,
33 THREEDSX, //3DSX 32 THREEDSX, // 3DSX
34}; 33};
35 34
36/** 35/**
@@ -81,8 +80,8 @@ constexpr u32 MakeMagic(char a, char b, char c, char d) {
81/// Interface for loading an application 80/// Interface for loading an application
82class AppLoader : NonCopyable { 81class AppLoader : NonCopyable {
83public: 82public:
84 AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) { } 83 AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) {}
85 virtual ~AppLoader() { } 84 virtual ~AppLoader() {}
86 85
87 /** 86 /**
88 * Returns the type of this file 87 * Returns the type of this file
@@ -140,7 +139,8 @@ public:
140 * @param size The size of the romfs 139 * @param size The size of the romfs
141 * @return ResultStatus result of function 140 * @return ResultStatus result of function
142 */ 141 */
143 virtual ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 142 virtual ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
143 u64& size) {
144 return ResultStatus::ErrorNotImplemented; 144 return ResultStatus::ErrorNotImplemented;
145 } 145 }
146 146
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index fca091ff9..2e4510857 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -5,11 +5,9 @@
5#include <algorithm> 5#include <algorithm>
6#include <cstring> 6#include <cstring>
7#include <memory> 7#include <memory>
8
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10#include "common/string_util.h" 9#include "common/string_util.h"
11#include "common/swap.h" 10#include "common/swap.h"
12
13#include "core/file_sys/archive_romfs.h" 11#include "core/file_sys/archive_romfs.h"
14#include "core/hle/kernel/process.h" 12#include "core/hle/kernel/process.h"
15#include "core/hle/kernel/resource_limit.h" 13#include "core/hle/kernel/resource_limit.h"
@@ -22,8 +20,8 @@
22 20
23namespace Loader { 21namespace Loader {
24 22
25static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs 23static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs
26static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes) 24static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes)
27 25
28/** 26/**
29 * Get the decompressed size of an LZSS compressed ExeFS file 27 * Get the decompressed size of an LZSS compressed ExeFS file
@@ -44,7 +42,8 @@ static u32 LZSS_GetDecompressedSize(const u8* buffer, u32 size) {
44 * @param decompressed_size Size of decompressed buffer 42 * @param decompressed_size Size of decompressed buffer
45 * @return True on success, otherwise false 43 * @return True on success, otherwise false
46 */ 44 */
47static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decompressed, u32 decompressed_size) { 45static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decompressed,
46 u32 decompressed_size) {
48 const u8* footer = compressed + compressed_size - 8; 47 const u8* footer = compressed + compressed_size - 8;
49 u32 buffer_top_and_bottom = *reinterpret_cast<const u32*>(footer); 48 u32 buffer_top_and_bottom = *reinterpret_cast<const u32*>(footer);
50 u32 out = decompressed_size; 49 u32 out = decompressed_size;
@@ -55,7 +54,7 @@ static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decom
55 memcpy(decompressed, compressed, compressed_size); 54 memcpy(decompressed, compressed, compressed_size);
56 55
57 while (index > stop_index) { 56 while (index > stop_index) {
58 u8 control = compressed[--index]; 57 u8 control = compressed[--index];
59 58
60 for (unsigned i = 0; i < 8; i++) { 59 for (unsigned i = 0; i < 8; i++) {
61 if (index <= stop_index) 60 if (index <= stop_index)
@@ -128,7 +127,7 @@ ResultStatus AppLoader_NCCH::LoadExec() {
128 std::vector<u8> code; 127 std::vector<u8> code;
129 if (ResultStatus::Success == ReadCode(code)) { 128 if (ResultStatus::Success == ReadCode(code)) {
130 std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( 129 std::string process_name = Common::StringFromFixedZeroTerminatedBuffer(
131 (const char*)exheader_header.codeset_info.name, 8); 130 (const char*)exheader_header.codeset_info.name, 8);
132 131
133 SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, ncch_header.program_id); 132 SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, ncch_header.program_id);
134 133
@@ -147,7 +146,8 @@ ResultStatus AppLoader_NCCH::LoadExec() {
147 146
148 codeset->data.offset = codeset->rodata.offset + codeset->rodata.size; 147 codeset->data.offset = codeset->rodata.offset + codeset->rodata.size;
149 codeset->data.addr = exheader_header.codeset_info.data.address; 148 codeset->data.addr = exheader_header.codeset_info.data.address;
150 codeset->data.size = exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE + bss_page_size; 149 codeset->data.size =
150 exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE + bss_page_size;
151 151
152 codeset->entrypoint = codeset->code.addr; 152 codeset->entrypoint = codeset->code.addr;
153 codeset->memory = std::make_shared<std::vector<u8>>(std::move(code)); 153 codeset->memory = std::make_shared<std::vector<u8>>(std::move(code));
@@ -155,15 +155,18 @@ ResultStatus AppLoader_NCCH::LoadExec() {
155 Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); 155 Kernel::g_current_process = Kernel::Process::Create(std::move(codeset));
156 156
157 // Attach a resource limit to the process based on the resource limit category 157 // Attach a resource limit to the process based on the resource limit category
158 Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory( 158 Kernel::g_current_process->resource_limit =
159 static_cast<Kernel::ResourceLimitCategory>(exheader_header.arm11_system_local_caps.resource_limit_category)); 159 Kernel::ResourceLimit::GetForCategory(static_cast<Kernel::ResourceLimitCategory>(
160 exheader_header.arm11_system_local_caps.resource_limit_category));
160 161
161 // Set the default CPU core for this process 162 // Set the default CPU core for this process
162 Kernel::g_current_process->ideal_processor = exheader_header.arm11_system_local_caps.ideal_processor; 163 Kernel::g_current_process->ideal_processor =
164 exheader_header.arm11_system_local_caps.ideal_processor;
163 165
164 // Copy data while converting endianess 166 // Copy data while converting endianess
165 std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps; 167 std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps;
166 std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps)); 168 std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(),
169 begin(kernel_caps));
167 Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); 170 Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size());
168 171
169 s32 priority = exheader_header.arm11_system_local_caps.priority; 172 s32 priority = exheader_header.arm11_system_local_caps.priority;
@@ -192,7 +195,8 @@ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>&
192 LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", section_number, 195 LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", section_number,
193 section.offset, section.size, section.name); 196 section.offset, section.size, section.name);
194 197
195 s64 section_offset = (section.offset + exefs_offset + sizeof(ExeFs_Header) + ncch_offset); 198 s64 section_offset =
199 (section.offset + exefs_offset + sizeof(ExeFs_Header) + ncch_offset);
196 file.Seek(section_offset, SEEK_SET); 200 file.Seek(section_offset, SEEK_SET);
197 201
198 if (strcmp(section.name, ".code") == 0 && is_compressed) { 202 if (strcmp(section.name, ".code") == 0 && is_compressed) {
@@ -254,25 +258,25 @@ ResultStatus AppLoader_NCCH::LoadExeFS() {
254 if (file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)) != sizeof(ExHeader_Header)) 258 if (file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)) != sizeof(ExHeader_Header))
255 return ResultStatus::Error; 259 return ResultStatus::Error;
256 260
257 is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; 261 is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1;
258 entry_point = exheader_header.codeset_info.text.address; 262 entry_point = exheader_header.codeset_info.text.address;
259 code_size = exheader_header.codeset_info.text.code_size; 263 code_size = exheader_header.codeset_info.text.code_size;
260 stack_size = exheader_header.codeset_info.stack_size; 264 stack_size = exheader_header.codeset_info.stack_size;
261 bss_size = exheader_header.codeset_info.bss_size; 265 bss_size = exheader_header.codeset_info.bss_size;
262 core_version = exheader_header.arm11_system_local_caps.core_version; 266 core_version = exheader_header.arm11_system_local_caps.core_version;
263 priority = exheader_header.arm11_system_local_caps.priority; 267 priority = exheader_header.arm11_system_local_caps.priority;
264 resource_limit_category = exheader_header.arm11_system_local_caps.resource_limit_category; 268 resource_limit_category = exheader_header.arm11_system_local_caps.resource_limit_category;
265 269
266 LOG_INFO(Loader, "Name: %s" , exheader_header.codeset_info.name); 270 LOG_INFO(Loader, "Name: %s", exheader_header.codeset_info.name);
267 LOG_INFO(Loader, "Program ID: %016llX" , ncch_header.program_id); 271 LOG_INFO(Loader, "Program ID: %016llX", ncch_header.program_id);
268 LOG_DEBUG(Loader, "Code compressed: %s" , is_compressed ? "yes" : "no"); 272 LOG_DEBUG(Loader, "Code compressed: %s", is_compressed ? "yes" : "no");
269 LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point); 273 LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point);
270 LOG_DEBUG(Loader, "Code size: 0x%08X", code_size); 274 LOG_DEBUG(Loader, "Code size: 0x%08X", code_size);
271 LOG_DEBUG(Loader, "Stack size: 0x%08X", stack_size); 275 LOG_DEBUG(Loader, "Stack size: 0x%08X", stack_size);
272 LOG_DEBUG(Loader, "Bss size: 0x%08X", bss_size); 276 LOG_DEBUG(Loader, "Bss size: 0x%08X", bss_size);
273 LOG_DEBUG(Loader, "Core version: %d" , core_version); 277 LOG_DEBUG(Loader, "Core version: %d", core_version);
274 LOG_DEBUG(Loader, "Thread priority: 0x%X" , priority); 278 LOG_DEBUG(Loader, "Thread priority: 0x%X", priority);
275 LOG_DEBUG(Loader, "Resource limit category: %d" , resource_limit_category); 279 LOG_DEBUG(Loader, "Resource limit category: %d", resource_limit_category);
276 280
277 if (exheader_header.arm11_system_local_caps.program_id != ncch_header.program_id) { 281 if (exheader_header.arm11_system_local_caps.program_id != ncch_header.program_id) {
278 LOG_ERROR(Loader, "ExHeader Program ID mismatch: the ROM is probably encrypted."); 282 LOG_ERROR(Loader, "ExHeader Program ID mismatch: the ROM is probably encrypted.");
@@ -309,7 +313,8 @@ ResultStatus AppLoader_NCCH::Load() {
309 if (ResultStatus::Success != result) 313 if (ResultStatus::Success != result)
310 return result; 314 return result;
311 315
312 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS); 316 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this),
317 Service::FS::ArchiveIdCode::RomFS);
313 return ResultStatus::Success; 318 return ResultStatus::Success;
314} 319}
315 320
@@ -329,7 +334,8 @@ ResultStatus AppLoader_NCCH::ReadLogo(std::vector<u8>& buffer) {
329 return LoadSectionExeFS("logo", buffer); 334 return LoadSectionExeFS("logo", buffer);
330} 335}
331 336
332ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 337ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
338 u64& size) {
333 if (!file.IsOpen()) 339 if (!file.IsOpen())
334 return ResultStatus::Error; 340 return ResultStatus::Error;
335 341
@@ -341,7 +347,7 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_
341 LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); 347 LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset);
342 LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); 348 LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size);
343 349
344 if (file.GetSize () < romfs_offset + romfs_size) 350 if (file.GetSize() < romfs_offset + romfs_size)
345 return ResultStatus::Error; 351 return ResultStatus::Error;
346 352
347 // We reopen the file, to allow its position to be independent from file's 353 // We reopen the file, to allow its position to be independent from file's
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index 75609ee57..04350d006 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -5,11 +5,9 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8
9#include "common/bit_field.h" 8#include "common/bit_field.h"
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "common/swap.h" 10#include "common/swap.h"
12
13#include "core/loader/loader.h" 11#include "core/loader/loader.h"
14 12
15//////////////////////////////////////////////////////////////////////////////////////////////////// 13////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -164,7 +162,7 @@ namespace Loader {
164class AppLoader_NCCH final : public AppLoader { 162class AppLoader_NCCH final : public AppLoader {
165public: 163public:
166 AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath) 164 AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath)
167 : AppLoader(std::move(file)), filepath(filepath) { } 165 : AppLoader(std::move(file)), filepath(filepath) {}
168 166
169 /** 167 /**
170 * Returns the type of the file 168 * Returns the type of the file
@@ -222,10 +220,10 @@ public:
222 * @param size Size of the RomFS in bytes 220 * @param size Size of the RomFS in bytes
223 * @return ResultStatus result of function 221 * @return ResultStatus result of function
224 */ 222 */
225 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) override; 223 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
224 u64& size) override;
226 225
227private: 226private:
228
229 /** 227 /**
230 * Reads an application ExeFS section of an NCCH file into AppLoader (e.g. .code, .logo, etc.) 228 * Reads an application ExeFS section of an NCCH file into AppLoader (e.g. .code, .logo, etc.)
231 * @param name Name of section to read out of NCCH file 229 * @param name Name of section to read out of NCCH file
@@ -246,24 +244,24 @@ private:
246 */ 244 */
247 ResultStatus LoadExeFS(); 245 ResultStatus LoadExeFS();
248 246
249 bool is_exefs_loaded = false; 247 bool is_exefs_loaded = false;
250 bool is_compressed = false; 248 bool is_compressed = false;
251 249
252 u32 entry_point = 0; 250 u32 entry_point = 0;
253 u32 code_size = 0; 251 u32 code_size = 0;
254 u32 stack_size = 0; 252 u32 stack_size = 0;
255 u32 bss_size = 0; 253 u32 bss_size = 0;
256 u32 core_version = 0; 254 u32 core_version = 0;
257 u8 priority = 0; 255 u8 priority = 0;
258 u8 resource_limit_category = 0; 256 u8 resource_limit_category = 0;
259 u32 ncch_offset = 0; // Offset to NCCH header, can be 0 or after NCSD header 257 u32 ncch_offset = 0; // Offset to NCCH header, can be 0 or after NCSD header
260 u32 exefs_offset = 0; 258 u32 exefs_offset = 0;
261 259
262 NCCH_Header ncch_header; 260 NCCH_Header ncch_header;
263 ExeFs_Header exefs_header; 261 ExeFs_Header exefs_header;
264 ExHeader_Header exheader_header; 262 ExHeader_Header exheader_header;
265 263
266 std::string filepath; 264 std::string filepath;
267}; 265};
268 266
269} // namespace Loader 267} // namespace Loader
diff --git a/src/core/loader/smdh.cpp b/src/core/loader/smdh.cpp
index 2d014054a..ccbeb7961 100644
--- a/src/core/loader/smdh.cpp
+++ b/src/core/loader/smdh.cpp
@@ -4,12 +4,9 @@
4 4
5#include <cstring> 5#include <cstring>
6#include <vector> 6#include <vector>
7
8#include "common/common_types.h" 7#include "common/common_types.h"
9
10#include "core/loader/loader.h" 8#include "core/loader/loader.h"
11#include "core/loader/smdh.h" 9#include "core/loader/smdh.h"
12
13#include "video_core/utils.h" 10#include "video_core/utils.h"
14 11
15namespace Loader { 12namespace Loader {
diff --git a/src/core/loader/smdh.h b/src/core/loader/smdh.h
index 2011abda2..ac7726c8f 100644
--- a/src/core/loader/smdh.h
+++ b/src/core/loader/smdh.h
@@ -6,7 +6,6 @@
6 6
7#include <array> 7#include <array>
8#include <vector> 8#include <vector>
9
10#include "common/common_funcs.h" 9#include "common/common_funcs.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "common/swap.h" 11#include "common/swap.h"
@@ -56,7 +55,7 @@ struct SMDH {
56 Italian = 4, 55 Italian = 4,
57 Spanish = 5, 56 Spanish = 5,
58 SimplifiedChinese = 6, 57 SimplifiedChinese = 6,
59 Korean= 7, 58 Korean = 7,
60 Dutch = 8, 59 Dutch = 8,
61 Portuguese = 9, 60 Portuguese = 9,
62 Russian = 10, 61 Russian = 10,