From bc2212106f755f85e55d039ffc783116b15e5df6 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Mon, 5 Jan 2015 20:09:35 +0000 Subject: [PATCH 01/12] Loader: Fix indentation, whitespace, and a few other such cosmetic stuff. --- src/core/loader/3dsx.cpp | 48 +++++++++++++++++++--------------------- src/core/loader/ncch.cpp | 2 +- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 4d072871a..fad544571 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -13,11 +13,9 @@ #include "3dsx.h" - namespace Loader { - -/** +/** * File layout: * - File header * - Code, rodata and data relocation table headers @@ -64,9 +62,9 @@ struct THREEDSX_Header struct THREEDSX_RelocHdr { // # of absolute relocations (that is, fix address to post-relocation memory layout) - u32 cross_segment_absolute; + u32 cross_segment_absolute; // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched) - u32 cross_segment_relative; + u32 cross_segment_relative; // more? // Relocations are written in this order: @@ -207,28 +205,28 @@ int THREEDSXReader::Load3DSXFile(const std::string& filename, u32 base_addr) return ERROR_NONE; } - /// AppLoader_DSX constructor - AppLoader_THREEDSX::AppLoader_THREEDSX(const std::string& filename) : filename(filename) { - } +/// AppLoader_DSX constructor +AppLoader_THREEDSX::AppLoader_THREEDSX(const std::string& filename) : filename(filename) { +} - /// AppLoader_DSX destructor - AppLoader_THREEDSX::~AppLoader_THREEDSX() { - } +/// AppLoader_DSX destructor +AppLoader_THREEDSX::~AppLoader_THREEDSX() { +} - /** - * Loads a 3DSX file - * @return Success on success, otherwise Error - */ - ResultStatus AppLoader_THREEDSX::Load() { - LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str()); - FileUtil::IOFile file(filename, "rb"); - if (file.IsOpen()) { - THREEDSXReader::Load3DSXFile(filename, 0x00100000); - Kernel::LoadExec(0x00100000); - } else { - return ResultStatus::Error; - } - return ResultStatus::Success; +/** +* Loads a 3DSX file +* @return Success on success, otherwise Error +*/ +ResultStatus AppLoader_THREEDSX::Load() { + LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str()); + FileUtil::IOFile file(filename, "rb"); + if (file.IsOpen()) { + THREEDSXReader::Load3DSXFile(filename, 0x00100000); + Kernel::LoadExec(0x00100000); + } else { + return ResultStatus::Error; } + return ResultStatus::Success; +} } // namespace Loader diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 0dc21699e..e246cebc4 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -149,7 +149,7 @@ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector& exefs_header.section[i].name); s64 section_offset = (exefs_header.section[i].offset + exefs_offset + - sizeof(ExeFs_Header)+ncch_offset); + sizeof(ExeFs_Header)+ncch_offset); file.Seek(section_offset, 0); // Section is compressed... From 43e699d849ac5dd7a29ff0eeb5821e2a824c091e Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 6 Jan 2015 23:36:48 +0000 Subject: [PATCH 02/12] =?UTF-8?q?Loader:=20Don=E2=80=99t=20duplicate=20the?= =?UTF-8?q?=20docstring=20into=20the=20cpp=20file.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/loader/3dsx.cpp | 4 ---- src/core/loader/elf.cpp | 6 ------ src/core/loader/loader.cpp | 5 ----- src/core/loader/ncch.cpp | 41 -------------------------------------- 4 files changed, 56 deletions(-) diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index fad544571..06827668f 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -213,10 +213,6 @@ AppLoader_THREEDSX::AppLoader_THREEDSX(const std::string& filename) : filename(f AppLoader_THREEDSX::~AppLoader_THREEDSX() { } -/** -* Loads a 3DSX file -* @return Success on success, otherwise Error -*/ ResultStatus AppLoader_THREEDSX::Load() { LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str()); FileUtil::IOFile file(filename, "rb"); diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 3ca60c072..89664229a 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -339,12 +339,6 @@ AppLoader_ELF::AppLoader_ELF(const std::string& filename) : is_loaded(false) { AppLoader_ELF::~AppLoader_ELF() { } -/** - * Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI) - * @param error_string Pointer to string to put error message if an error has occurred - * @todo Move NCSD parsing out of here and create a separate function for loading these - * @return True on success, otherwise false - */ ResultStatus AppLoader_ELF::Load() { LOG_INFO(Loader, "Loading ELF file %s...", filename.c_str()); diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 45cf425df..32196a1dc 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -53,11 +53,6 @@ FileType IdentifyFile(const std::string &filename) { return FileType::Unknown; } -/** - * Identifies and loads a bootable file - * @param filename String filename of bootable file - * @return ResultStatus result of function - */ ResultStatus LoadFile(const std::string& filename) { LOG_INFO(Loader, "Loading file %s...", filename.c_str()); diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index e246cebc4..f1d01252e 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -113,10 +113,6 @@ AppLoader_NCCH::AppLoader_NCCH(const std::string& filename) { AppLoader_NCCH::~AppLoader_NCCH() { } -/** - * Loads .code section into memory for booting - * @return ResultStatus result of function - */ ResultStatus AppLoader_NCCH::LoadExec() const { if (!is_loaded) return ResultStatus::ErrorNotLoaded; @@ -130,12 +126,6 @@ ResultStatus AppLoader_NCCH::LoadExec() const { return ResultStatus::Error; } -/** - * Reads an application ExeFS section of an NCCH file into AppLoader (e.g. .code, .logo, etc.) - * @param name Name of section to read out of NCCH file - * @param buffer Vector to read data into - * @return ResultStatus result of function - */ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector& buffer) const { // Iterate through the ExeFs archive until we find the .code file... FileUtil::IOFile file(filename, "rb"); @@ -187,12 +177,6 @@ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector& return ResultStatus::ErrorNotUsed; } -/** - * Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI) - * @param error_string Pointer to string to put error message if an error has occurred - * @todo Move NCSD parsing out of here and create a separate function for loading these - * @return True on success, otherwise false - */ ResultStatus AppLoader_NCCH::Load() { LOG_INFO(Loader, "Loading NCCH file %s...", filename.c_str()); @@ -248,47 +232,22 @@ ResultStatus AppLoader_NCCH::Load() { return ResultStatus::Error; } -/** - * Get the code (typically .code section) of the application - * @param buffer Reference to buffer to store data - * @return ResultStatus result of function - */ ResultStatus AppLoader_NCCH::ReadCode(std::vector& buffer) const { return LoadSectionExeFS(".code", buffer); } -/** - * Get the icon (typically icon section) of the application - * @param buffer Reference to buffer to store data - * @return ResultStatus result of function - */ ResultStatus AppLoader_NCCH::ReadIcon(std::vector& buffer) const { return LoadSectionExeFS("icon", buffer); } -/** - * Get the banner (typically banner section) of the application - * @param buffer Reference to buffer to store data - * @return ResultStatus result of function - */ ResultStatus AppLoader_NCCH::ReadBanner(std::vector& buffer) const { return LoadSectionExeFS("banner", buffer); } -/** - * Get the logo (typically logo section) of the application - * @param buffer Reference to buffer to store data - * @return ResultStatus result of function - */ ResultStatus AppLoader_NCCH::ReadLogo(std::vector& buffer) const { return LoadSectionExeFS("logo", buffer); } -/** - * Get the RomFS of the application - * @param buffer Reference to buffer to store data - * @return ResultStatus result of function - */ ResultStatus AppLoader_NCCH::ReadRomFS(std::vector& buffer) const { FileUtil::IOFile file(filename, "rb"); if (file.IsOpen()) { From 85030c6e6bfe83b6671de45b25535fe3ef713319 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 6 Jan 2015 19:49:25 +0000 Subject: [PATCH 03/12] Loader: Never forget to change is_loaded. --- src/core/loader/3dsx.cpp | 7 +++++++ src/core/loader/3dsx.h | 2 +- src/core/loader/elf.cpp | 4 +++- src/core/loader/elf.h | 2 +- src/core/loader/ncch.cpp | 5 ++--- src/core/loader/ncch.h | 2 +- 6 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 06827668f..15032e0ae 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -215,13 +215,20 @@ AppLoader_THREEDSX::~AppLoader_THREEDSX() { ResultStatus AppLoader_THREEDSX::Load() { LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str()); + + if (is_loaded) + return ResultStatus::ErrorAlreadyLoaded; + FileUtil::IOFile file(filename, "rb"); + if (file.IsOpen()) { THREEDSXReader::Load3DSXFile(filename, 0x00100000); Kernel::LoadExec(0x00100000); } else { return ResultStatus::Error; } + + is_loaded = true; return ResultStatus::Success; } diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h index da8836662..f28224628 100644 --- a/src/core/loader/3dsx.h +++ b/src/core/loader/3dsx.h @@ -26,7 +26,7 @@ public: private: std::string filename; - bool is_loaded; + bool is_loaded = false; }; } // namespace Loader diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 89664229a..ee711d8b2 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -331,7 +331,7 @@ bool ElfReader::LoadSymbols() { namespace Loader { /// AppLoader_ELF constructor -AppLoader_ELF::AppLoader_ELF(const std::string& filename) : is_loaded(false) { +AppLoader_ELF::AppLoader_ELF(const std::string& filename) { this->filename = filename; } @@ -358,6 +358,8 @@ ResultStatus AppLoader_ELF::Load() { } else { return ResultStatus::Error; } + + is_loaded = true; return ResultStatus::Success; } diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index c221cce6d..856722f1e 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h @@ -26,7 +26,7 @@ public: private: std::string filename; - bool is_loaded; + bool is_loaded = false; }; } // namespace Loader diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index f1d01252e..0793cc7cd 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -102,7 +102,6 @@ static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompresse /// AppLoader_NCCH constructor AppLoader_NCCH::AppLoader_NCCH(const std::string& filename) { this->filename = filename; - is_loaded = false; is_compressed = false; entry_point = 0; ncch_offset = 0; @@ -221,10 +220,10 @@ ResultStatus AppLoader_NCCH::Load() { file.Seek(exefs_offset + ncch_offset, 0); file.ReadBytes(&exefs_header, sizeof(ExeFs_Header)); - is_loaded = true; // Set state to loaded - LoadExec(); // Load the executable into memory for booting + is_loaded = true; // Set state to loaded + return ResultStatus::Success; } else { LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str()); diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index fd9258970..184a20d98 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -215,7 +215,7 @@ private: std::string filename; - bool is_loaded; + bool is_loaded = false; bool is_compressed; u32 entry_point; From 9d3bb8b7c00b953cfd87479570c25a5e607f3e61 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 6 Jan 2015 19:56:26 +0000 Subject: [PATCH 04/12] Loader: Remove the useless THREEDSXReader class. --- src/core/loader/3dsx.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 15032e0ae..54ee992fc 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -86,11 +86,6 @@ struct THREEloadinfo u32 seg_sizes[3]; }; -class THREEDSXReader { -public: - static int Load3DSXFile(const std::string& filename, u32 base_addr); -}; - static u32 TranslateAddr(u32 addr, THREEloadinfo *loadinfo, u32* offsets) { if (addr < offsets[0]) @@ -100,12 +95,11 @@ static u32 TranslateAddr(u32 addr, THREEloadinfo *loadinfo, u32* offsets) return loadinfo->seg_addrs[2] + addr - offsets[1]; } -int THREEDSXReader::Load3DSXFile(const std::string& filename, u32 base_addr) +static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) { - FileUtil::IOFile file(filename, "rb"); - if (!file.IsOpen()) { + if (!file.IsOpen()) return ERROR_FILE; - } + THREEDSX_Header hdr; if (file.ReadBytes(&hdr, sizeof(hdr)) != sizeof(hdr)) return ERROR_READ; @@ -222,7 +216,7 @@ ResultStatus AppLoader_THREEDSX::Load() { FileUtil::IOFile file(filename, "rb"); if (file.IsOpen()) { - THREEDSXReader::Load3DSXFile(filename, 0x00100000); + Load3DSXFile(file, 0x00100000); Kernel::LoadExec(0x00100000); } else { return ResultStatus::Error; From 2d63df90a9d64d3961be07ef0a959bc48b42c73b Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 6 Jan 2015 21:10:12 +0000 Subject: [PATCH 05/12] Loader: Initialize the default NCCH values in the class declaration, not in the constructor. --- src/core/loader/ncch.cpp | 4 ---- src/core/loader/ncch.h | 8 ++++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 0793cc7cd..883a0f753 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -102,10 +102,6 @@ static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompresse /// AppLoader_NCCH constructor AppLoader_NCCH::AppLoader_NCCH(const std::string& filename) { this->filename = filename; - is_compressed = false; - entry_point = 0; - ncch_offset = 0; - exefs_offset = 0; } /// AppLoader_NCCH destructor diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index 184a20d98..578513f77 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -216,11 +216,11 @@ private: std::string filename; bool is_loaded = false; - bool is_compressed; + bool is_compressed = false; - u32 entry_point; - u32 ncch_offset; // Offset to NCCH header, can be 0 or after NCSD header - u32 exefs_offset; + u32 entry_point = 0; + u32 ncch_offset = 0; // Offset to NCCH header, can be 0 or after NCSD header + u32 exefs_offset = 0; NCCH_Header ncch_header; ExeFs_Header exefs_header; From b5237e885df72f6c37532fc8af9573966e7b07e5 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 6 Jan 2015 21:30:40 +0000 Subject: [PATCH 06/12] Loader: Keep a reference to the file and pass it to the correct AppLoader, instead of loading it multiple times. --- src/core/loader/3dsx.cpp | 21 +--- src/core/loader/3dsx.h | 7 +- src/core/loader/elf.cpp | 32 ++---- src/core/loader/elf.h | 7 +- src/core/loader/loader.cpp | 23 ++-- src/core/loader/loader.h | 7 +- src/core/loader/ncch.cpp | 216 +++++++++++++++++-------------------- src/core/loader/ncch.h | 7 +- 8 files changed, 130 insertions(+), 190 deletions(-) diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 54ee992fc..873ee8b25 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -199,28 +199,15 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) return ERROR_NONE; } -/// AppLoader_DSX constructor -AppLoader_THREEDSX::AppLoader_THREEDSX(const std::string& filename) : filename(filename) { -} - -/// AppLoader_DSX destructor -AppLoader_THREEDSX::~AppLoader_THREEDSX() { -} - ResultStatus AppLoader_THREEDSX::Load() { - LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str()); - if (is_loaded) return ResultStatus::ErrorAlreadyLoaded; - FileUtil::IOFile file(filename, "rb"); - - if (file.IsOpen()) { - Load3DSXFile(file, 0x00100000); - Kernel::LoadExec(0x00100000); - } else { + if (!file->IsOpen()) return ResultStatus::Error; - } + + Load3DSXFile(*file, 0x00100000); + Kernel::LoadExec(0x00100000); is_loaded = true; return ResultStatus::Success; diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h index f28224628..2f2e8bec0 100644 --- a/src/core/loader/3dsx.h +++ b/src/core/loader/3dsx.h @@ -15,18 +15,13 @@ namespace Loader { /// Loads an 3DSX file class AppLoader_THREEDSX final : public AppLoader { public: - AppLoader_THREEDSX(const std::string& filename); - ~AppLoader_THREEDSX() override; + AppLoader_THREEDSX(std::unique_ptr&& file) : AppLoader(std::move(file)) { } /** * Load the bootable file * @return ResultStatus result of function */ ResultStatus Load() override; - -private: - std::string filename; - bool is_loaded = false; }; } // namespace Loader diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index ee711d8b2..d1a1ef595 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -330,34 +330,20 @@ bool ElfReader::LoadSymbols() { namespace Loader { -/// AppLoader_ELF constructor -AppLoader_ELF::AppLoader_ELF(const std::string& filename) { - this->filename = filename; -} - -/// AppLoader_NCCH destructor -AppLoader_ELF::~AppLoader_ELF() { -} - ResultStatus AppLoader_ELF::Load() { - LOG_INFO(Loader, "Loading ELF file %s...", filename.c_str()); - if (is_loaded) return ResultStatus::ErrorAlreadyLoaded; - FileUtil::IOFile file(filename, "rb"); - - if (file.IsOpen()) { - u32 size = (u32)file.GetSize(); - std::unique_ptr buffer(new u8[size]); - file.ReadBytes(&buffer[0], size); - - ElfReader elf_reader(&buffer[0]); - elf_reader.LoadInto(0x00100000); - Kernel::LoadExec(elf_reader.GetEntryPoint()); - } else { + if (!file->IsOpen()) return ResultStatus::Error; - } + + u32 size = static_cast(file->GetSize()); + std::unique_ptr buffer(new u8[size]); + file->ReadBytes(&buffer[0], size); + + ElfReader elf_reader(&buffer[0]); + elf_reader.LoadInto(0x00100000); + Kernel::LoadExec(elf_reader.GetEntryPoint()); is_loaded = true; return ResultStatus::Success; diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index 856722f1e..1c476c86b 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h @@ -15,18 +15,13 @@ namespace Loader { /// Loads an ELF/AXF file class AppLoader_ELF final : public AppLoader { public: - AppLoader_ELF(const std::string& filename); - ~AppLoader_ELF() override; + AppLoader_ELF(std::unique_ptr&& file) : AppLoader(std::move(file)) { } /** * Load the bootable file * @return ResultStatus result of function */ ResultStatus Load() override; - -private: - std::string filename; - bool is_loaded = false; }; } // namespace Loader diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 32196a1dc..fd32b7b20 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -56,20 +56,24 @@ FileType IdentifyFile(const std::string &filename) { ResultStatus LoadFile(const std::string& filename) { LOG_INFO(Loader, "Loading file %s...", filename.c_str()); + std::unique_ptr file(new FileUtil::IOFile(filename, "rb")); + if (!file->IsOpen()) + return ResultStatus::Error; + switch (IdentifyFile(filename)) { //3DSX file format... case FileType::THREEDSX: - return AppLoader_THREEDSX(filename).Load(); + return AppLoader_THREEDSX(std::move(file)).Load(); // Standard ELF file format... case FileType::ELF: - return AppLoader_ELF(filename).Load(); + return AppLoader_ELF(std::move(file)).Load(); // NCCH/NCSD container formats... case FileType::CXI: case FileType::CCI: { - AppLoader_NCCH app_loader(filename); + AppLoader_NCCH app_loader(std::move(file)); // Load application and RomFS if (ResultStatus::Success == app_loader.Load()) { @@ -83,16 +87,11 @@ ResultStatus LoadFile(const std::string& filename) { // Raw BIN file format... case FileType::BIN: { - LOG_INFO(Loader, "Loading BIN file %s...", filename.c_str()); - - FileUtil::IOFile file(filename, "rb"); - - if (file.IsOpen()) { - file.ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), (size_t)file.GetSize()); - Kernel::LoadExec(Memory::EXEFS_CODE_VADDR); - } else { + size_t size = (size_t)file->GetSize(); + if (file->ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), size) != size) return ResultStatus::Error; - } + + Kernel::LoadExec(Memory::EXEFS_CODE_VADDR); return ResultStatus::Success; } diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index ec5534d41..b4fc8636d 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -7,6 +7,7 @@ #include #include "common/common.h" +#include "common/file_util.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Loader namespace @@ -40,7 +41,7 @@ enum class ResultStatus { /// Interface for loading an application class AppLoader : NonCopyable { public: - AppLoader() { } + AppLoader(std::unique_ptr&& file) : file(std::move(file)) { } virtual ~AppLoader() { } /** @@ -93,6 +94,10 @@ public: virtual ResultStatus ReadRomFS(std::vector& buffer) const { return ResultStatus::ErrorNotImplemented; } + +protected: + std::unique_ptr file; + bool is_loaded = false; }; /** diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 883a0f753..eca57d14b 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -4,8 +4,6 @@ #include -#include "common/file_util.h" - #include "core/loader/ncch.h" #include "core/hle/kernel/kernel.h" #include "core/mem_map.h" @@ -99,15 +97,6 @@ static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompresse //////////////////////////////////////////////////////////////////////////////////////////////////// // AppLoader_NCCH class -/// AppLoader_NCCH constructor -AppLoader_NCCH::AppLoader_NCCH(const std::string& filename) { - this->filename = filename; -} - -/// AppLoader_NCCH destructor -AppLoader_NCCH::~AppLoader_NCCH() { -} - ResultStatus AppLoader_NCCH::LoadExec() const { if (!is_loaded) return ResultStatus::ErrorNotLoaded; @@ -123,108 +112,100 @@ ResultStatus AppLoader_NCCH::LoadExec() const { ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector& buffer) const { // Iterate through the ExeFs archive until we find the .code file... - FileUtil::IOFile file(filename, "rb"); - if (file.IsOpen()) { - LOG_DEBUG(Loader, "%d sections:", kMaxSections); - for (int i = 0; i < kMaxSections; i++) { - // Load the specified section... - if (strcmp((const char*)exefs_header.section[i].name, name) == 0) { - LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", i, - exefs_header.section[i].offset, exefs_header.section[i].size, - exefs_header.section[i].name); - - s64 section_offset = (exefs_header.section[i].offset + exefs_offset + - sizeof(ExeFs_Header)+ncch_offset); - file.Seek(section_offset, 0); - - // Section is compressed... - if (i == 0 && is_compressed) { - // Read compressed .code section... - std::unique_ptr temp_buffer; - try { - temp_buffer.reset(new u8[exefs_header.section[i].size]); - } catch (std::bad_alloc&) { - return ResultStatus::ErrorMemoryAllocationFailed; - } - file.ReadBytes(&temp_buffer[0], exefs_header.section[i].size); - - // Decompress .code section... - u32 decompressed_size = LZSS_GetDecompressedSize(&temp_buffer[0], - exefs_header.section[i].size); - buffer.resize(decompressed_size); - if (!LZSS_Decompress(&temp_buffer[0], exefs_header.section[i].size, &buffer[0], - decompressed_size)) { - return ResultStatus::ErrorInvalidFormat; - } - // Section is uncompressed... - } - else { - buffer.resize(exefs_header.section[i].size); - file.ReadBytes(&buffer[0], exefs_header.section[i].size); - } - return ResultStatus::Success; - } - } - } else { - LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str()); + if (!file->IsOpen()) return ResultStatus::Error; + + LOG_DEBUG(Loader, "%d sections:", kMaxSections); + for (int i = 0; i < kMaxSections; i++) { + // Load the specified section... + if (strcmp((const char*)exefs_header.section[i].name, name) == 0) { + LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", i, + exefs_header.section[i].offset, exefs_header.section[i].size, + exefs_header.section[i].name); + + s64 section_offset = (exefs_header.section[i].offset + exefs_offset + + sizeof(ExeFs_Header)+ncch_offset); + file->Seek(section_offset, 0); + + // Section is compressed... + if (i == 0 && is_compressed) { + // Read compressed .code section... + std::unique_ptr temp_buffer; + try { + temp_buffer.reset(new u8[exefs_header.section[i].size]); + } catch (std::bad_alloc&) { + return ResultStatus::ErrorMemoryAllocationFailed; + } + file->ReadBytes(&temp_buffer[0], exefs_header.section[i].size); + + // Decompress .code section... + u32 decompressed_size = LZSS_GetDecompressedSize(&temp_buffer[0], + exefs_header.section[i].size); + buffer.resize(decompressed_size); + if (!LZSS_Decompress(&temp_buffer[0], exefs_header.section[i].size, &buffer[0], + decompressed_size)) { + return ResultStatus::ErrorInvalidFormat; + } + // Section is uncompressed... + } + else { + buffer.resize(exefs_header.section[i].size); + file->ReadBytes(&buffer[0], exefs_header.section[i].size); + } + return ResultStatus::Success; + } } return ResultStatus::ErrorNotUsed; } ResultStatus AppLoader_NCCH::Load() { - LOG_INFO(Loader, "Loading NCCH file %s...", filename.c_str()); - if (is_loaded) return ResultStatus::ErrorAlreadyLoaded; - FileUtil::IOFile file(filename, "rb"); - if (file.IsOpen()) { - file.ReadBytes(&ncch_header, sizeof(NCCH_Header)); + if (!file->IsOpen()) + return ResultStatus::Error; - // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)... - if (0 == memcmp(&ncch_header.magic, "NCSD", 4)) { - LOG_WARNING(Loader, "Only loading the first (bootable) NCCH within the NCSD file!"); - ncch_offset = 0x4000; - file.Seek(ncch_offset, 0); - file.ReadBytes(&ncch_header, sizeof(NCCH_Header)); - } + file->ReadBytes(&ncch_header, sizeof(NCCH_Header)); - // Verify we are loading the correct file type... - if (0 != memcmp(&ncch_header.magic, "NCCH", 4)) - return ResultStatus::ErrorInvalidFormat; - - // Read ExHeader... - - file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)); - - is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; - entry_point = exheader_header.codeset_info.text.address; - - LOG_INFO(Loader, "Name: %s", exheader_header.codeset_info.name); - LOG_DEBUG(Loader, "Code compressed: %s", is_compressed ? "yes" : "no"); - LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point); - - // Read ExeFS... - - exefs_offset = ncch_header.exefs_offset * kBlockSize; - u32 exefs_size = ncch_header.exefs_size * kBlockSize; - - LOG_DEBUG(Loader, "ExeFS offset: 0x%08X", exefs_offset); - LOG_DEBUG(Loader, "ExeFS size: 0x%08X", exefs_size); - - file.Seek(exefs_offset + ncch_offset, 0); - file.ReadBytes(&exefs_header, sizeof(ExeFs_Header)); - - LoadExec(); // Load the executable into memory for booting - - is_loaded = true; // Set state to loaded - - return ResultStatus::Success; - } else { - LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str()); + // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)... + if (0 == memcmp(&ncch_header.magic, "NCSD", 4)) { + LOG_WARNING(Loader, "Only loading the first (bootable) NCCH within the NCSD file!"); + ncch_offset = 0x4000; + file->Seek(ncch_offset, 0); + file->ReadBytes(&ncch_header, sizeof(NCCH_Header)); } - return ResultStatus::Error; + + // Verify we are loading the correct file type... + if (0 != memcmp(&ncch_header.magic, "NCCH", 4)) + return ResultStatus::ErrorInvalidFormat; + + // Read ExHeader... + + file->ReadBytes(&exheader_header, sizeof(ExHeader_Header)); + + is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; + entry_point = exheader_header.codeset_info.text.address; + + LOG_INFO(Loader, "Name: %s", exheader_header.codeset_info.name); + LOG_DEBUG(Loader, "Code compressed: %s", is_compressed ? "yes" : "no"); + LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point); + + // Read ExeFS... + + exefs_offset = ncch_header.exefs_offset * kBlockSize; + u32 exefs_size = ncch_header.exefs_size * kBlockSize; + + LOG_DEBUG(Loader, "ExeFS offset: 0x%08X", exefs_offset); + LOG_DEBUG(Loader, "ExeFS size: 0x%08X", exefs_size); + + file->Seek(exefs_offset + ncch_offset, 0); + file->ReadBytes(&exefs_header, sizeof(ExeFs_Header)); + + LoadExec(); // Load the executable into memory for booting + + is_loaded = true; // Set state to loaded + + return ResultStatus::Success; } ResultStatus AppLoader_NCCH::ReadCode(std::vector& buffer) const { @@ -244,29 +225,26 @@ ResultStatus AppLoader_NCCH::ReadLogo(std::vector& buffer) const { } ResultStatus AppLoader_NCCH::ReadRomFS(std::vector& buffer) const { - FileUtil::IOFile file(filename, "rb"); - if (file.IsOpen()) { - // Check if the NCCH has a RomFS... - if (ncch_header.romfs_offset != 0 && ncch_header.romfs_size != 0) { - u32 romfs_offset = ncch_offset + (ncch_header.romfs_offset * kBlockSize) + 0x1000; - u32 romfs_size = (ncch_header.romfs_size * kBlockSize) - 0x1000; + if (!file->IsOpen()) + return ResultStatus::Error; - LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); - LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); + // Check if the NCCH has a RomFS... + if (ncch_header.romfs_offset != 0 && ncch_header.romfs_size != 0) { + u32 romfs_offset = ncch_offset + (ncch_header.romfs_offset * kBlockSize) + 0x1000; + u32 romfs_size = (ncch_header.romfs_size * kBlockSize) - 0x1000; - buffer.resize(romfs_size); + LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); + LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); - file.Seek(romfs_offset, 0); - file.ReadBytes(&buffer[0], romfs_size); + buffer.resize(romfs_size); - return ResultStatus::Success; - } - LOG_DEBUG(Loader, "NCCH has no RomFS"); - return ResultStatus::ErrorNotUsed; - } else { - LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str()); + file->Seek(romfs_offset, 0); + file->ReadBytes(&buffer[0], romfs_size); + + return ResultStatus::Success; } - return ResultStatus::Error; + LOG_DEBUG(Loader, "NCCH has no RomFS"); + return ResultStatus::ErrorNotUsed; } u64 AppLoader_NCCH::GetProgramId() const { diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index 578513f77..d9d68f154 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -5,7 +5,6 @@ #pragma once #include "common/common.h" -#include "common/file_util.h" #include "core/loader/loader.h" @@ -147,8 +146,7 @@ namespace Loader { /// Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI) class AppLoader_NCCH final : public AppLoader { public: - AppLoader_NCCH(const std::string& filename); - ~AppLoader_NCCH() override; + AppLoader_NCCH(std::unique_ptr&& file) : AppLoader(std::move(file)) { } /** * Load the application @@ -213,9 +211,6 @@ private: */ ResultStatus LoadExec() const; - std::string filename; - - bool is_loaded = false; bool is_compressed = false; u32 entry_point = 0; From 04622a859cc748745cbbeb0b332f930085438077 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 6 Jan 2015 22:47:43 +0000 Subject: [PATCH 07/12] =?UTF-8?q?Loader:=20Don=E2=80=99t=20assume=20the=20?= =?UTF-8?q?file=20hasn=E2=80=99t=20been=20read=20before.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/loader/3dsx.cpp | 3 +++ src/core/loader/elf.cpp | 3 +++ src/core/loader/ncch.cpp | 11 +++++++---- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 873ee8b25..e239808f3 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -100,6 +100,9 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) if (!file.IsOpen()) return ERROR_FILE; + // Reset read pointer in case this file has been read before. + file.Seek(0, SEEK_SET); + THREEDSX_Header hdr; if (file.ReadBytes(&hdr, sizeof(hdr)) != sizeof(hdr)) return ERROR_READ; diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index d1a1ef595..712d564d1 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -337,6 +337,9 @@ ResultStatus AppLoader_ELF::Load() { if (!file->IsOpen()) return ResultStatus::Error; + // Reset read pointer in case this file has been read before. + file->Seek(0, SEEK_SET); + u32 size = static_cast(file->GetSize()); std::unique_ptr buffer(new u8[size]); file->ReadBytes(&buffer[0], size); diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index eca57d14b..edf53c2c0 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -125,7 +125,7 @@ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector& s64 section_offset = (exefs_header.section[i].offset + exefs_offset + sizeof(ExeFs_Header)+ncch_offset); - file->Seek(section_offset, 0); + file->Seek(section_offset, SEEK_SET); // Section is compressed... if (i == 0 && is_compressed) { @@ -165,13 +165,16 @@ ResultStatus AppLoader_NCCH::Load() { if (!file->IsOpen()) return ResultStatus::Error; + // Reset read pointer in case this file has been read before. + file->Seek(0, SEEK_SET); + file->ReadBytes(&ncch_header, sizeof(NCCH_Header)); // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)... if (0 == memcmp(&ncch_header.magic, "NCSD", 4)) { LOG_WARNING(Loader, "Only loading the first (bootable) NCCH within the NCSD file!"); ncch_offset = 0x4000; - file->Seek(ncch_offset, 0); + file->Seek(ncch_offset, SEEK_SET); file->ReadBytes(&ncch_header, sizeof(NCCH_Header)); } @@ -198,7 +201,7 @@ ResultStatus AppLoader_NCCH::Load() { LOG_DEBUG(Loader, "ExeFS offset: 0x%08X", exefs_offset); LOG_DEBUG(Loader, "ExeFS size: 0x%08X", exefs_size); - file->Seek(exefs_offset + ncch_offset, 0); + file->Seek(exefs_offset + ncch_offset, SEEK_SET); file->ReadBytes(&exefs_header, sizeof(ExeFs_Header)); LoadExec(); // Load the executable into memory for booting @@ -238,7 +241,7 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::vector& buffer) const { buffer.resize(romfs_size); - file->Seek(romfs_offset, 0); + file->Seek(romfs_offset, SEEK_SET); file->ReadBytes(&buffer[0], romfs_size); return ResultStatus::Success; From 82ec17db7df53ed1c376d1cdaa9a6587719a546d Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 6 Jan 2015 23:10:13 +0000 Subject: [PATCH 08/12] Loader: Guess filetype from the magic, or fallback to the extension. --- src/core/loader/3dsx.cpp | 13 +++++++- src/core/loader/3dsx.h | 7 +++++ src/core/loader/elf.cpp | 12 ++++++++ src/core/loader/elf.h | 7 +++++ src/core/loader/loader.cpp | 62 ++++++++++++++++++++++++++++---------- src/core/loader/loader.h | 11 +++---- src/core/loader/ncch.cpp | 19 ++++++++++-- src/core/loader/ncch.h | 9 +++++- 8 files changed, 113 insertions(+), 27 deletions(-) diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index e239808f3..f3e09ecd6 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -44,7 +44,6 @@ enum THREEDSX_Error { static const u32 RELOCBUFSIZE = 512; // File header -static const u32 THREEDSX_MAGIC = 0x58534433; // '3DSX' #pragma pack(1) struct THREEDSX_Header { @@ -202,6 +201,18 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) return ERROR_NONE; } +FileType AppLoader_THREEDSX::IdentifyType(FileUtil::IOFile& file) { + u32 magic; + file.Seek(0, SEEK_SET); + if (1 != file.ReadArray(&magic, 1)) + return FileType::Error; + + if (MakeMagic('3', 'D', 'S', 'X') == magic) + return FileType::THREEDSX; + + return FileType::Error; +} + ResultStatus AppLoader_THREEDSX::Load() { if (is_loaded) return ResultStatus::ErrorAlreadyLoaded; diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h index 2f2e8bec0..a11667400 100644 --- a/src/core/loader/3dsx.h +++ b/src/core/loader/3dsx.h @@ -17,6 +17,13 @@ class AppLoader_THREEDSX final : public AppLoader { public: AppLoader_THREEDSX(std::unique_ptr&& file) : AppLoader(std::move(file)) { } + /** + * Returns the type of the file + * @param file FileUtil::IOFile open file + * @return FileType found, or FileType::Error if this loader doesn't know it + */ + static FileType IdentifyType(FileUtil::IOFile& file); + /** * Load the bootable file * @return ResultStatus result of function diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 712d564d1..d1c3aea72 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -330,6 +330,18 @@ bool ElfReader::LoadSymbols() { namespace Loader { +FileType AppLoader_ELF::IdentifyType(FileUtil::IOFile& file) { + u32 magic; + file.Seek(0, SEEK_SET); + if (1 != file.ReadArray(&magic, 1)) + return FileType::Error; + + if (MakeMagic('\x7f', 'E', 'L', 'F') == magic) + return FileType::ELF; + + return FileType::Error; +} + ResultStatus AppLoader_ELF::Load() { if (is_loaded) return ResultStatus::ErrorAlreadyLoaded; diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index 1c476c86b..b6e6651f5 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h @@ -17,6 +17,13 @@ class AppLoader_ELF final : public AppLoader { public: AppLoader_ELF(std::unique_ptr&& file) : AppLoader(std::move(file)) { } + /** + * Returns the type of the file + * @param file FileUtil::IOFile open file + * @return FileType found, or FileType::Error if this loader doesn't know it + */ + static FileType IdentifyType(FileUtil::IOFile& file); + /** * Load the bootable file * @return ResultStatus result of function diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index fd32b7b20..01b415215 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -19,11 +19,32 @@ namespace Loader { /** * Identifies the type of a bootable file - * @param filename String filename of bootable file - * @todo (ShizZy) this function sucks... make it actually check file contents etc. + * @param file open file * @return FileType of file */ -FileType IdentifyFile(const std::string &filename) { +static FileType IdentifyFile(FileUtil::IOFile& file) { + FileType type; + +#define CHECK_TYPE(loader) \ + type = AppLoader_##loader::IdentifyType(file); \ + if (FileType::Error != type) \ + return type; + + CHECK_TYPE(THREEDSX) + CHECK_TYPE(ELF) + CHECK_TYPE(NCCH) + +#undef CHECK_TYPE + + return FileType::Unknown; +} + +/** + * Guess the type of a bootable file from its extension + * @param filename String filename of bootable file + * @return FileType of file + */ +static FileType GuessFromFilename(const std::string& filename) { if (filename.size() == 0) { LOG_ERROR(Loader, "invalid filename %s", filename.c_str()); return FileType::Error; @@ -34,22 +55,20 @@ FileType IdentifyFile(const std::string &filename) { return FileType::Unknown; std::string extension = Common::ToLower(filename.substr(extension_loc)); - // TODO(bunnei): Do actual filetype checking instead of naively checking the extension - if (extension == ".elf") { + if (extension == ".elf") return FileType::ELF; - } else if (extension == ".axf") { + else if (extension == ".axf") return FileType::ELF; - } else if (extension == ".cxi") { + else if (extension == ".cxi") return FileType::CXI; - } else if (extension == ".cci") { + else if (extension == ".cci") return FileType::CCI; - } else if (extension == ".bin") { + else if (extension == ".bin") return FileType::BIN; - } else if (extension == ".3ds") { + else if (extension == ".3ds") return FileType::CCI; - } else if (extension == ".3dsx") { + else if (extension == ".3dsx") return FileType::THREEDSX; - } return FileType::Unknown; } @@ -60,7 +79,16 @@ ResultStatus LoadFile(const std::string& filename) { if (!file->IsOpen()) return ResultStatus::Error; - switch (IdentifyFile(filename)) { + FileType type = IdentifyFile(*file); + FileType filename_type = GuessFromFilename(filename); + + if (type != filename_type) { + LOG_WARNING(Loader, "File %s has a different type than its extension.", filename.c_str()); + if (FileType::Unknown == type) + type = filename_type; + } + + switch (type) { //3DSX file format... case FileType::THREEDSX: @@ -72,7 +100,8 @@ ResultStatus LoadFile(const std::string& filename) { // NCCH/NCSD container formats... case FileType::CXI: - case FileType::CCI: { + case FileType::CCI: + { AppLoader_NCCH app_loader(std::move(file)); // Load application and RomFS @@ -100,10 +129,11 @@ ResultStatus LoadFile(const std::string& filename) { // IdentifyFile could know identify file type... case FileType::Unknown: - - default: + { + LOG_CRITICAL(Loader, "File %s is of unknown type."); return ResultStatus::ErrorInvalidFormat; } + } return ResultStatus::Error; } diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index b4fc8636d..7456b019b 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -38,6 +38,10 @@ enum class ResultStatus { ErrorMemoryAllocationFailed, }; +static u32 MakeMagic(char a, char b, char c, char d) { + return a | b << 8 | c << 16 | d << 24; +} + /// Interface for loading an application class AppLoader : NonCopyable { public: @@ -100,13 +104,6 @@ protected: bool is_loaded = false; }; -/** - * Identifies the type of a bootable file - * @param filename String filename of bootable file - * @return FileType of file - */ -FileType IdentifyFile(const std::string &filename); - /** * Identifies and loads a bootable file * @param filename String filename of bootable file diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index edf53c2c0..d6eb549b7 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -97,6 +97,21 @@ static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompresse //////////////////////////////////////////////////////////////////////////////////////////////////// // AppLoader_NCCH class +FileType AppLoader_NCCH::IdentifyType(FileUtil::IOFile& file) { + u32 magic; + file.Seek(0x100, SEEK_SET); + if (1 != file.ReadArray(&magic, 1)) + return FileType::Error; + + if (MakeMagic('N', 'C', 'S', 'D') == magic) + return FileType::CCI; + + if (MakeMagic('N', 'C', 'C', 'H') == magic) + return FileType::CXI; + + return FileType::Error; +} + ResultStatus AppLoader_NCCH::LoadExec() const { if (!is_loaded) return ResultStatus::ErrorNotLoaded; @@ -171,7 +186,7 @@ ResultStatus AppLoader_NCCH::Load() { file->ReadBytes(&ncch_header, sizeof(NCCH_Header)); // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)... - if (0 == memcmp(&ncch_header.magic, "NCSD", 4)) { + if (MakeMagic('N', 'C', 'S', 'D') == ncch_header.magic) { LOG_WARNING(Loader, "Only loading the first (bootable) NCCH within the NCSD file!"); ncch_offset = 0x4000; file->Seek(ncch_offset, SEEK_SET); @@ -179,7 +194,7 @@ ResultStatus AppLoader_NCCH::Load() { } // Verify we are loading the correct file type... - if (0 != memcmp(&ncch_header.magic, "NCCH", 4)) + if (MakeMagic('N', 'C', 'C', 'H') != ncch_header.magic) return ResultStatus::ErrorInvalidFormat; // Read ExHeader... diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index d9d68f154..9ae2de99f 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -13,7 +13,7 @@ struct NCCH_Header { u8 signature[0x100]; - char magic[4]; + u32 magic; u32 content_size; u8 partition_id[8]; u16 maker_code; @@ -148,6 +148,13 @@ class AppLoader_NCCH final : public AppLoader { public: AppLoader_NCCH(std::unique_ptr&& file) : AppLoader(std::move(file)) { } + /** + * Returns the type of the file + * @param file FileUtil::IOFile open file + * @return FileType found, or FileType::Error if this loader doesn't know it + */ + static FileType IdentifyType(FileUtil::IOFile& file); + /** * Load the application * @return ResultStatus result of function From 2c24e539a23438c84653f00f08df455d9837a20f Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 7 Jan 2015 00:33:00 +0000 Subject: [PATCH 09/12] Loader: Display the type of the file being loaded. --- src/core/loader/loader.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 01b415215..60460292d 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -72,12 +72,30 @@ static FileType GuessFromFilename(const std::string& filename) { return FileType::Unknown; } -ResultStatus LoadFile(const std::string& filename) { - LOG_INFO(Loader, "Loading file %s...", filename.c_str()); +static const char* GetFileTypeString(FileType type) { + switch (type) { + case FileType::CCI: + return "NCSD"; + case FileType::CXI: + return "NCCH"; + case FileType::ELF: + return "ELF"; + case FileType::THREEDSX: + return "3DSX"; + case FileType::BIN: + return "raw"; + case FileType::Error: + case FileType::Unknown: + return "unknown"; + } +} +ResultStatus LoadFile(const std::string& filename) { std::unique_ptr file(new FileUtil::IOFile(filename, "rb")); - if (!file->IsOpen()) + if (!file->IsOpen()) { + LOG_ERROR(Loader, "Failed to load file %s", filename.c_str()); return ResultStatus::Error; + } FileType type = IdentifyFile(*file); FileType filename_type = GuessFromFilename(filename); @@ -88,6 +106,8 @@ ResultStatus LoadFile(const std::string& filename) { type = filename_type; } + LOG_INFO(Loader, "Loading file %s as %s...", filename.c_str(), GetFileTypeString(type)); + switch (type) { //3DSX file format... From 08aaa3350066b5d506368d18dddba3f829c85b7a Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 7 Jan 2015 01:01:19 +0000 Subject: [PATCH 10/12] Loader: Clean up the NCCH AppLoader. --- src/core/loader/ncch.cpp | 105 +++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 54 deletions(-) diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index d6eb549b7..aaaa4d650 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -13,8 +13,8 @@ namespace Loader { -static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs -static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes) +static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs +static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes) /** * Get the decompressed size of an LZSS compressed ExeFS file @@ -22,7 +22,7 @@ static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes) * @param size Size of compressed buffer * @return Size of decompressed buffer */ -static u32 LZSS_GetDecompressedSize(u8* buffer, u32 size) { +static u32 LZSS_GetDecompressedSize(const u8* buffer, u32 size) { u32 offset_size = *(u32*)(buffer + size - 4); return offset_size + size; } @@ -35,9 +35,9 @@ static u32 LZSS_GetDecompressedSize(u8* buffer, u32 size) { * @param decompressed_size Size of decompressed buffer * @return True on success, otherwise false */ -static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompressed, u32 decompressed_size) { - u8* footer = compressed + compressed_size - 8; - u32 buffer_top_and_bottom = *(u32*)footer; +static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decompressed, u32 decompressed_size) { + const u8* footer = compressed + compressed_size - 8; + u32 buffer_top_and_bottom = *reinterpret_cast(footer); u32 out = decompressed_size; u32 index = compressed_size - ((buffer_top_and_bottom >> 24) & 0xFF); u32 stop_index = compressed_size - (buffer_top_and_bottom & 0xFFFFFF); @@ -45,22 +45,21 @@ static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompresse memset(decompressed, 0, decompressed_size); memcpy(decompressed, compressed, compressed_size); - while(index > stop_index) { + while (index > stop_index) { u8 control = compressed[--index]; - for(u32 i = 0; i < 8; i++) { - if(index <= stop_index) + for (unsigned i = 0; i < 8; i++) { + if (index <= stop_index) break; - if(index <= 0) + if (index <= 0) break; - if(out <= 0) + if (out <= 0) break; - if(control & 0x80) { + if (control & 0x80) { // Check if compression is out of bounds - if(index < 2) { + if (index < 2) return false; - } index -= 2; u32 segment_offset = compressed[index] | (compressed[index + 1] << 8); @@ -69,23 +68,21 @@ static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompresse segment_offset += 2; // Check if compression is out of bounds - if(out < segment_size) { + if (out < segment_size) return false; - } - for(u32 j = 0; j < segment_size; j++) { - // Check if compression is out of bounds - if(out + segment_offset >= decompressed_size) { - return false; - } - u8 data = decompressed[out + segment_offset]; + for (unsigned j = 0; j < segment_size; j++) { + // Check if compression is out of bounds + if (out + segment_offset >= decompressed_size) + return false; + + u8 data = decompressed[out + segment_offset]; decompressed[--out] = data; } } else { // Check if compression is out of bounds - if(out < 1) { + if (out < 1) return false; - } decompressed[--out] = compressed[--index]; } control <<= 1; @@ -126,46 +123,44 @@ ResultStatus AppLoader_NCCH::LoadExec() const { } ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector& buffer) const { - // Iterate through the ExeFs archive until we find the .code file... if (!file->IsOpen()) return ResultStatus::Error; LOG_DEBUG(Loader, "%d sections:", kMaxSections); - for (int i = 0; i < kMaxSections; i++) { - // Load the specified section... - if (strcmp((const char*)exefs_header.section[i].name, name) == 0) { - LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", i, - exefs_header.section[i].offset, exefs_header.section[i].size, - exefs_header.section[i].name); + // Iterate through the ExeFs archive until we find the .code file... + for (unsigned section_number = 0; section_number < kMaxSections; section_number++) { + const auto& section = exefs_header.section[section_number]; - s64 section_offset = (exefs_header.section[i].offset + exefs_offset + - sizeof(ExeFs_Header)+ncch_offset); + // Load the specified section... + if (strcmp(section.name, name) == 0) { + LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", section_number, + section.offset, section.size, section.name); + + s64 section_offset = (section.offset + exefs_offset + sizeof(ExeFs_Header) + ncch_offset); file->Seek(section_offset, SEEK_SET); - // Section is compressed... - if (i == 0 && is_compressed) { - // Read compressed .code section... + if (is_compressed) { + // Section is compressed, read compressed .code section... std::unique_ptr temp_buffer; try { - temp_buffer.reset(new u8[exefs_header.section[i].size]); + temp_buffer.reset(new u8[section.size]); } catch (std::bad_alloc&) { return ResultStatus::ErrorMemoryAllocationFailed; } - file->ReadBytes(&temp_buffer[0], exefs_header.section[i].size); + + if (file->ReadBytes(&temp_buffer[0], section.size) != section.size) + return ResultStatus::Error; // Decompress .code section... - u32 decompressed_size = LZSS_GetDecompressedSize(&temp_buffer[0], - exefs_header.section[i].size); + u32 decompressed_size = LZSS_GetDecompressedSize(&temp_buffer[0], section.size); buffer.resize(decompressed_size); - if (!LZSS_Decompress(&temp_buffer[0], exefs_header.section[i].size, &buffer[0], - decompressed_size)) { + if (!LZSS_Decompress(&temp_buffer[0], section.size, &buffer[0], decompressed_size)) return ResultStatus::ErrorInvalidFormat; - } + } else { // Section is uncompressed... - } - else { - buffer.resize(exefs_header.section[i].size); - file->ReadBytes(&buffer[0], exefs_header.section[i].size); + buffer.resize(section.size); + if (file->ReadBytes(&buffer[0], section.size) != section.size) + return ResultStatus::Error; } return ResultStatus::Success; } @@ -183,7 +178,8 @@ ResultStatus AppLoader_NCCH::Load() { // Reset read pointer in case this file has been read before. file->Seek(0, SEEK_SET); - file->ReadBytes(&ncch_header, sizeof(NCCH_Header)); + if (file->ReadBytes(&ncch_header, sizeof(NCCH_Header)) != sizeof(NCCH_Header)) + return ResultStatus::Error; // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)... if (MakeMagic('N', 'C', 'S', 'D') == ncch_header.magic) { @@ -199,7 +195,8 @@ ResultStatus AppLoader_NCCH::Load() { // Read ExHeader... - file->ReadBytes(&exheader_header, sizeof(ExHeader_Header)); + if (file->ReadBytes(&exheader_header, sizeof(ExHeader_Header)) != sizeof(ExHeader_Header)) + return ResultStatus::Error; is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; entry_point = exheader_header.codeset_info.text.address; @@ -217,13 +214,12 @@ ResultStatus AppLoader_NCCH::Load() { LOG_DEBUG(Loader, "ExeFS size: 0x%08X", exefs_size); file->Seek(exefs_offset + ncch_offset, SEEK_SET); - file->ReadBytes(&exefs_header, sizeof(ExeFs_Header)); - - LoadExec(); // Load the executable into memory for booting + if (file->ReadBytes(&exefs_header, sizeof(ExeFs_Header)) != sizeof(ExeFs_Header)) + return ResultStatus::Error; is_loaded = true; // Set state to loaded - return ResultStatus::Success; + return LoadExec(); // Load the executable into memory for booting } ResultStatus AppLoader_NCCH::ReadCode(std::vector& buffer) const { @@ -257,7 +253,8 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::vector& buffer) const { buffer.resize(romfs_size); file->Seek(romfs_offset, SEEK_SET); - file->ReadBytes(&buffer[0], romfs_size); + if (file->ReadBytes(&buffer[0], romfs_size) != romfs_size) + return ResultStatus::Error; return ResultStatus::Success; } From 84e52a944d0c5dba8c5c9c6c9a0b106f571c7041 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 7 Jan 2015 01:21:50 +0000 Subject: [PATCH 11/12] Loader: Clean up the 3DSX AppLoader. --- src/core/loader/3dsx.cpp | 41 +++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index f3e09ecd6..c3ac1f417 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -85,7 +85,7 @@ struct THREEloadinfo u32 seg_sizes[3]; }; -static u32 TranslateAddr(u32 addr, THREEloadinfo *loadinfo, u32* offsets) +static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets) { if (addr < offsets[0]) return loadinfo->seg_addrs[0] + addr; @@ -130,8 +130,9 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) // Read the relocation headers u32* relocs = (u32*)(loadinfo.seg_ptrs[2] + hdr.data_seg_size); - for (u32 current_segment = 0; current_segment < 3; current_segment++) { - if (file.ReadBytes(&relocs[current_segment*n_reloc_tables], n_reloc_tables * 4) != n_reloc_tables * 4) + for (unsigned current_segment = 0; current_segment < 3; current_segment++) { + size_t size = n_reloc_tables * 4; + if (file.ReadBytes(&relocs[current_segment * n_reloc_tables], size) != size) return ERROR_READ; } @@ -147,9 +148,9 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) memset((char*)loadinfo.seg_ptrs[2] + hdr.data_seg_size - hdr.bss_size, 0, hdr.bss_size); // Relocate the segments - for (u32 current_segment = 0; current_segment < 3; current_segment++) { - for (u32 current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { - u32 n_relocs = relocs[current_segment*n_reloc_tables + current_segment_reloc_table]; + for (unsigned current_segment = 0; current_segment < 3; current_segment++) { + for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { + u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; if (current_segment_reloc_table >= 2) { // We are not using this table - ignore it because we don't know what it dose file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR); @@ -158,29 +159,35 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) static THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; u32* pos = (u32*)loadinfo.seg_ptrs[current_segment]; - u32* end_pos = pos + (loadinfo.seg_sizes[current_segment] / 4); + const u32* end_pos = pos + (loadinfo.seg_sizes[current_segment] / 4); while (n_relocs) { u32 remaining = std::min(RELOCBUFSIZE, n_relocs); n_relocs -= remaining; - if (file.ReadBytes(reloc_table, remaining*sizeof(THREEDSX_Reloc)) != remaining*sizeof(THREEDSX_Reloc)) + if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) != remaining * sizeof(THREEDSX_Reloc)) return ERROR_READ; - for (u32 current_inprogress = 0; current_inprogress < remaining && pos < end_pos; current_inprogress++) { - LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)\n", - current_segment_reloc_table, (u32)reloc_table[current_inprogress].skip, (u32)reloc_table[current_inprogress].patch); - pos += reloc_table[current_inprogress].skip; - s32 num_patches = reloc_table[current_inprogress].patch; + for (unsigned current_inprogress = 0; current_inprogress < remaining && pos < end_pos; current_inprogress++) { + const auto& table = reloc_table[current_inprogress]; + LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)\n", current_segment_reloc_table, + (u32)table.skip, (u32)table.patch); + pos += table.skip; + s32 num_patches = table.patch; while (0 < num_patches && pos < end_pos) { u32 in_addr = (char*)pos - (char*)&all_mem[0]; u32 addr = TranslateAddr(*pos, &loadinfo, offsets); LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)\n", - base_addr + in_addr, addr, current_segment_reloc_table, *pos); + base_addr + in_addr, addr, current_segment_reloc_table, *pos); switch (current_segment_reloc_table) { - case 0: *pos = (addr); break; - case 1: *pos = (addr - in_addr); break; - default: break; //this should never happen + case 0: + *pos = (addr); + break; + case 1: + *pos = (addr - in_addr); + break; + default: + break; //this should never happen } pos++; num_patches--; From df0d66c7cf518638112843b0bf0a8d7950b9041c Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 7 Jan 2015 01:30:32 +0000 Subject: [PATCH 12/12] Loader: Clean up the ELF AppLoader. --- src/core/loader/3dsx.cpp | 4 +-- src/core/loader/elf.cpp | 73 ++++++++++++++++++---------------------- 2 files changed, 35 insertions(+), 42 deletions(-) diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index c3ac1f417..958dd03e8 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -130,7 +130,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) // Read the relocation headers u32* relocs = (u32*)(loadinfo.seg_ptrs[2] + hdr.data_seg_size); - for (unsigned current_segment = 0; current_segment < 3; current_segment++) { + for (unsigned current_segment : {0, 1, 2}) { size_t size = n_reloc_tables * 4; if (file.ReadBytes(&relocs[current_segment * n_reloc_tables], size) != size) return ERROR_READ; @@ -148,7 +148,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) memset((char*)loadinfo.seg_ptrs[2] + hdr.data_seg_size - hdr.bss_size, 0, hdr.bss_size); // Relocate the segments - for (unsigned current_segment = 0; current_segment < 3; current_segment++) { + for (unsigned current_segment : {0, 1, 2}) { for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; if (current_segment_reloc_table >= 2) { diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index d1c3aea72..e7e5df408 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -18,25 +18,25 @@ // File type enum ElfType { - ET_NONE = 0, - ET_REL = 1, - ET_EXEC = 2, - ET_DYN = 3, - ET_CORE = 4, + ET_NONE = 0, + ET_REL = 1, + ET_EXEC = 2, + ET_DYN = 3, + ET_CORE = 4, ET_LOPROC = 0xFF00, ET_HIPROC = 0xFFFF, }; // Machine/Architecture enum ElfMachine { - EM_NONE = 0, - EM_M32 = 1, + EM_NONE = 0, + EM_M32 = 1, EM_SPARC = 2, - EM_386 = 3, - EM_68K = 4, - EM_88K = 5, - EM_860 = 7, - EM_MIPS = 8 + EM_386 = 3, + EM_68K = 4, + EM_88K = 5, + EM_860 = 7, + EM_MIPS = 8 }; // File version @@ -54,12 +54,6 @@ enum ElfMachine { #define EI_PAD 7 #define EI_NIDENT 16 -// Magic number -#define ELFMAG0 0x7F -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' - // Sections constants // Section types @@ -83,10 +77,10 @@ enum ElfMachine { // Section flags enum ElfSectionFlags { - SHF_WRITE = 0x1, - SHF_ALLOC = 0x2, + SHF_WRITE = 0x1, + SHF_ALLOC = 0x2, SHF_EXECINSTR = 0x4, - SHF_MASKPROC = 0xF0000000, + SHF_MASKPROC = 0xF0000000, }; // Segment types @@ -100,11 +94,11 @@ enum ElfSectionFlags #define PT_LOPROC 0x70000000 #define PT_HIPROC 0x7FFFFFFF -typedef unsigned int Elf32_Addr; +typedef unsigned int Elf32_Addr; typedef unsigned short Elf32_Half; -typedef unsigned int Elf32_Off; -typedef signed int Elf32_Sword; -typedef unsigned int Elf32_Word; +typedef unsigned int Elf32_Off; +typedef signed int Elf32_Sword; +typedef unsigned int Elf32_Word; //////////////////////////////////////////////////////////////////////////////////////////////////// // ELF file header @@ -188,7 +182,6 @@ private: public: ElfReader(void *ptr); - ~ElfReader() { } u32 Read32(int off) const { return base32[off >> 2]; } @@ -197,7 +190,7 @@ public: ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); } u32 GetEntryPoint() const { return entryPoint; } u32 GetFlags() const { return (u32)(header->e_flags); } - bool LoadInto(u32 vaddr); + void LoadInto(u32 vaddr); bool LoadSymbols(); int GetNumSegments() const { return (int)(header->e_phnum); } @@ -229,11 +222,11 @@ public: ElfReader::ElfReader(void *ptr) { base = (char*)ptr; - base32 = (u32 *)ptr; + base32 = (u32*)ptr; header = (Elf32_Ehdr*)ptr; - segments = (Elf32_Phdr *)(base + header->e_phoff); - sections = (Elf32_Shdr *)(base + header->e_shoff); + segments = (Elf32_Phdr*)(base + header->e_phoff); + sections = (Elf32_Shdr*)(base + header->e_shoff); entryPoint = header->e_entry; @@ -245,7 +238,7 @@ const char *ElfReader::GetSectionName(int section) const { return nullptr; int name_offset = sections[section].sh_name; - char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx); + const char* ptr = (char*)GetSectionDataPtr(header->e_shstrndx); if (ptr) return ptr + name_offset; @@ -253,7 +246,7 @@ const char *ElfReader::GetSectionName(int section) const { return nullptr; } -bool ElfReader::LoadInto(u32 vaddr) { +void ElfReader::LoadInto(u32 vaddr) { LOG_DEBUG(Loader, "String section: %i", header->e_shstrndx); // Should we relocate? @@ -271,20 +264,19 @@ bool ElfReader::LoadInto(u32 vaddr) { u32 segment_addr[32]; u32 base_addr = relocate ? vaddr : 0; - for (int i = 0; i < header->e_phnum; i++) { - Elf32_Phdr *p = segments + i; + for (unsigned i = 0; i < header->e_phnum; i++) { + Elf32_Phdr* p = segments + i; LOG_DEBUG(Loader, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr, - p->p_filesz, p->p_memsz); + p->p_filesz, p->p_memsz); if (p->p_type == PT_LOAD) { segment_addr[i] = base_addr + p->p_vaddr; memcpy(Memory::GetPointer(segment_addr[i]), GetSegmentPtr(i), p->p_filesz); LOG_DEBUG(Loader, "Loadable Segment Copied to %08x, size %08x", segment_addr[i], - p->p_memsz); + p->p_memsz); } } LOG_DEBUG(Loader, "Done loading."); - return true; } SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const { @@ -305,9 +297,9 @@ bool ElfReader::LoadSymbols() { const char *stringBase = (const char *)GetSectionDataPtr(stringSection); //We have a symbol table! - Elf32_Sym *symtab = (Elf32_Sym *)(GetSectionDataPtr(sec)); + Elf32_Sym* symtab = (Elf32_Sym *)(GetSectionDataPtr(sec)); int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); - for (int sym = 0; sym < numSymbols; sym++) { + for (unsigned sym = 0; sym < numSymbols; sym++) { int size = symtab[sym].st_size; if (size == 0) continue; @@ -354,7 +346,8 @@ ResultStatus AppLoader_ELF::Load() { u32 size = static_cast(file->GetSize()); std::unique_ptr buffer(new u8[size]); - file->ReadBytes(&buffer[0], size); + if (file->ReadBytes(&buffer[0], size) != size) + return ResultStatus::Error; ElfReader elf_reader(&buffer[0]); elf_reader.LoadInto(0x00100000);