From 7f27f344bde64ad317564c8e9dd71580057be448 Mon Sep 17 00:00:00 2001 From: jakcron Date: Sun, 27 May 2018 20:34:10 +0800 Subject: [PATCH] [nstool] Prototype reading NSO header. --- programs/nstool/source/NsoProcess.cpp | 137 ++++++++++++++++++++++++ programs/nstool/source/NsoProcess.h | 32 ++++++ programs/nstool/source/UserSettings.cpp | 3 + programs/nstool/source/main.cpp | 11 ++ programs/nstool/source/nstool.h | 1 + 5 files changed, 184 insertions(+) create mode 100644 programs/nstool/source/NsoProcess.cpp create mode 100644 programs/nstool/source/NsoProcess.h diff --git a/programs/nstool/source/NsoProcess.cpp b/programs/nstool/source/NsoProcess.cpp new file mode 100644 index 0000000..9300b16 --- /dev/null +++ b/programs/nstool/source/NsoProcess.cpp @@ -0,0 +1,137 @@ +#include +#include +#include "OffsetAdjustedIFile.h" +#include "NsoProcess.h" + +inline const char* getBoolStr(bool isTrue) +{ + return isTrue? "TRUE" : "FALSE"; +} + +NsoProcess::NsoProcess(): + mReader(nullptr), + mCliOutputType(OUTPUT_NORMAL), + mVerify(false) +{ + +} + +NsoProcess::~NsoProcess() +{ + if (mReader != nullptr) + { + delete mReader; + } +} + +void NsoProcess::process() +{ + fnd::MemoryBlob scratch; + + if (mReader == nullptr) + { + throw fnd::Exception(kModuleName, "No file reader set."); + } + + if (mReader->size() < sizeof(nx::sNsoHeader)) + { + throw fnd::Exception(kModuleName, "Corrupt NSO file too small"); + } + + scratch.alloc(sizeof(nx::sNsoHeader)); + mReader->read(scratch.getBytes(), 0, scratch.getSize()); + + memcpy(&mNso, scratch.getBytes(), sizeof(nx::sNsoHeader)); + if (std::string(mNso.signature, 4) != nx::nso::kNsoSig) + { + throw fnd::Exception(kModuleName, "Corrupt NSO header"); + } + + if (mCliOutputType >= OUTPUT_NORMAL) + { + displayHeader(); + } +} + +void NsoProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size) +{ + mReader = new OffsetAdjustedIFile(file, offset, size); +} + +void NsoProcess::setCliOutputMode(CliOutputType type) +{ + mCliOutputType = type; +} + +void NsoProcess::setVerifyMode(bool verify) +{ + mVerify = verify; +} + +void NsoProcess::displayHeader() +{ +#define _HEXDUMP_L(var, len) do { for (size_t a__a__A = 0; a__a__A < len; a__a__A++) printf("%02x", var[a__a__A]); } while(0) + + printf("[NSO Header]\n"); + printf(" Format Version: %" PRId32 "\n", mNso.version.get()); + printf(" Flags: 0x%" PRIx32 "\n", mNso.flags.get()); + printf(" ModuleId: "); + _HEXDUMP_L(mNso.module_id, 32); + printf("\n"); + printf(" .text:\n"); + printf(" FileOffset: 0x%" PRIx32 "\n", mNso.text.file_offset.get()); + printf(" FileSize: 0x%" PRIx32 "\n", mNso.text_file_size.get()); + printf(" FileCompressed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_TEXT_COMPRESS))); + printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.text.memory_offset.get()); + printf(" MemorySize: 0x%" PRIx32 "\n", mNso.text.size.get()); + printf(" MemBlobHashed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_TEXT_HASH))); + if (_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_TEXT_HASH)) + { + printf(" MemBlobHash: "); + _HEXDUMP_L(mNso.text_hash, 32); + printf("\n"); + } + printf(" .ro:\n"); + printf(" FileOffset: 0x%" PRIx32 "\n", mNso.ro.file_offset.get()); + printf(" FileSize: 0x%" PRIx32 "\n", mNso.ro_file_size.get()); + printf(" FileCompressed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_RO_COMPRESS))); + printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.ro.memory_offset.get()); + printf(" MemorySize: 0x%" PRIx32 "\n", mNso.ro.size.get()); + printf(" MemBlobHashed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_RO_HASH))); + if (_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_RO_HASH)) + { + printf(" MemBlobHash: "); + _HEXDUMP_L(mNso.ro_hash, 32); + printf("\n"); + } + printf(" .api_info:\n"); + printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.embedded.offset.get()); + printf(" MemorySize: 0x%" PRIx32 "\n", mNso.embedded.size.get()); + printf(" .dynstr:\n"); + printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.dyn_str.offset.get()); + printf(" MemorySize: 0x%" PRIx32 "\n", mNso.dyn_str.size.get()); + printf(" .dynsym:\n"); + printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.dyn_sym.offset.get()); + printf(" MemorySize: 0x%" PRIx32 "\n", mNso.dyn_sym.size.get()); + printf(" .data:\n"); + printf(" FileOffset: 0x%" PRIx32 "\n", mNso.data.file_offset.get()); + printf(" FileSize: 0x%" PRIx32 "\n", mNso.data_file_size.get()); + printf(" FileCompressed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_DATA_COMPRESS))); + printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.data.memory_offset.get()); + printf(" MemorySize: 0x%" PRIx32 "\n", mNso.data.size.get()); + printf(" MemBlobHashed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_DATA_HASH))); + if (_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_DATA_HASH)) + { + printf(" MemBlobHash: "); + _HEXDUMP_L(mNso.data_hash, 32); + printf("\n"); + } + printf(" .bss:\n"); + printf(" MemorySize: 0x%" PRIx32 "\n", mNso.bss_size.get()); + printf(" .module_id:\n"); + printf(" FileOffset: 0x%" PRIx32 "\n", mNso.module_name_offset.get()); + printf(" FileSize: 0x%" PRIx32 "\n", mNso.module_name_size.get()); + +#undef _HEXDUMP_L +} + diff --git a/programs/nstool/source/NsoProcess.h b/programs/nstool/source/NsoProcess.h new file mode 100644 index 0000000..8eef37b --- /dev/null +++ b/programs/nstool/source/NsoProcess.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include +#include + +#include "nstool.h" + +class NsoProcess +{ +public: + NsoProcess(); + ~NsoProcess(); + + void process(); + + void setInputFile(fnd::IFile* file, size_t offset, size_t size); + void setCliOutputMode(CliOutputType type); + void setVerifyMode(bool verify); + + +private: + const std::string kModuleName = "NsoProcess"; + + fnd::IFile* mReader; + CliOutputType mCliOutputType; + bool mVerify; + + nx::sNsoHeader mNso; + + void displayHeader(); +}; \ No newline at end of file diff --git a/programs/nstool/source/UserSettings.cpp b/programs/nstool/source/UserSettings.cpp index 0bb1194..8b00be9 100644 --- a/programs/nstool/source/UserSettings.cpp +++ b/programs/nstool/source/UserSettings.cpp @@ -17,6 +17,7 @@ #include #include #include +#include UserSettings::UserSettings() {} @@ -635,6 +636,8 @@ FileType UserSettings::determineFileTypeFromFile(const std::string& path) // test npdm else if (_ASSERT_SIZE(sizeof(nx::sNpdmHeader)) && std::string(_QUICK_CAST(nx::sNpdmHeader, 0)->signature, 4) == nx::npdm::kNpdmStructSig) file_type = FILE_NPDM; + else if (_ASSERT_SIZE(sizeof(nx::sNsoHeader)) && std::string(_QUICK_CAST(nx::sNsoHeader, 0)->signature, 4) == nx::nso::kNsoSig) + file_type = FILE_NSO; // else unrecognised else file_type = FILE_INVALID; diff --git a/programs/nstool/source/main.cpp b/programs/nstool/source/main.cpp index 3dea72a..2dd1ef1 100644 --- a/programs/nstool/source/main.cpp +++ b/programs/nstool/source/main.cpp @@ -7,6 +7,7 @@ #include "NcaProcess.h" #include "NpdmProcess.h" #include "CnmtProcess.h" +#include "NsoProcess.h" int main(int argc, char** argv) @@ -109,6 +110,16 @@ int main(int argc, char** argv) cnmt.process(); } + else if (user_set.getFileType() == FILE_NSO) + { + NsoProcess nso; + + nso.setInputFile(&inputFile, 0, inputFile.size()); + nso.setCliOutputMode(user_set.getCliOutputType()); + nso.setVerifyMode(user_set.isVerifyFile()); + + nso.process(); + } } catch (const fnd::Exception& e) { printf("\n\n%s\n", e.what()); diff --git a/programs/nstool/source/nstool.h b/programs/nstool/source/nstool.h index b38e085..5325918 100644 --- a/programs/nstool/source/nstool.h +++ b/programs/nstool/source/nstool.h @@ -19,6 +19,7 @@ enum FileType FILE_NCA, FILE_NPDM, FILE_CNMT, + FILE_NSO, FILE_INVALID = -1, };