From 915bd80f6f9f3278bef4563343d06dc57fe60930 Mon Sep 17 00:00:00 2001 From: jakcron Date: Fri, 1 Jun 2018 21:35:36 +0800 Subject: [PATCH] [nx|nstool] Encapsulated NsoHeader parsing into nx::NsoHeader --- lib/libnx/include/nx/NsoHeader.h | 111 ++++++++++- lib/libnx/include/nx/nso.h | 11 +- lib/libnx/source/NsoHeader.cpp | 266 +++++++++++++++++++++++++- programs/nstool/source/NsoProcess.cpp | 73 +++---- programs/nstool/source/NsoProcess.h | 4 +- 5 files changed, 409 insertions(+), 56 deletions(-) diff --git a/lib/libnx/include/nx/NsoHeader.h b/lib/libnx/include/nx/NsoHeader.h index 07d5e81..acc4981 100644 --- a/lib/libnx/include/nx/NsoHeader.h +++ b/lib/libnx/include/nx/NsoHeader.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include #include @@ -10,6 +10,81 @@ namespace nx public fnd::ISerialiseableBinary { public: + struct sModuleId + { + byte_t data[nso::kModuleIdLen]; + + void operator=(const sModuleId& other) + { + memcpy(data, other.data, nso::kModuleIdLen); + } + + bool operator==(const sModuleId& other) const + { + return memcmp(data, other.data, nso::kModuleIdLen) == 0; + } + + bool operator!=(const sModuleId& other) const + { + return !(*this == other); + } + }; + + struct sLayout + { + uint32_t offset; + uint32_t size; + + void operator=(const sLayout& other) + { + offset = other.offset; + size = other.size; + } + + bool operator==(const sLayout& other) const + { + return (offset == other.offset) \ + && (size == other.size); + } + + bool operator!=(const sLayout& other) const + { + return !(*this == other); + } + }; + + struct sCodeSegment + { + sLayout file_layout; + sLayout memory_layout; + bool is_compressed; + bool is_hashed; + crypto::sha::sSha256Hash hash; + + void operator=(const sCodeSegment& other) + { + file_layout = other.file_layout; + memory_layout = other.memory_layout; + is_compressed = other.is_compressed; + is_hashed = other.is_hashed; + hash = other.hash; + } + + bool operator==(const sCodeSegment& other) const + { + return (file_layout == other.file_layout) \ + && (memory_layout == other.memory_layout) \ + && (is_compressed == other.is_compressed) \ + && (is_hashed == other.is_hashed) \ + && (hash == other.hash); + } + + bool operator!=(const sCodeSegment& other) const + { + return !(*this == other); + } + }; + NsoHeader(); NsoHeader(const NsoHeader& other); NsoHeader(const byte_t* bytes, size_t len); @@ -29,7 +104,32 @@ namespace nx // variables void clear(); + const sModuleId& getModuleId() const; + void setModuleId(const sModuleId& id); + uint32_t getBssSize() const; + void setBssSize(uint32_t size); + + const sCodeSegment& getTextSegmentInfo() const; + void setTextSegmentInfo(const sCodeSegment& info); + + const sCodeSegment& getRoSegmentInfo() const; + void setRoSegmentInfo(const sCodeSegment& info); + + const sCodeSegment& getDataSegmentInfo() const; + void setDataSegmentInfo(const sCodeSegment& info); + + const sLayout& getModuleNameInfo() const; + void setModuleNameInfo(const sLayout& info); + + const sLayout& getRoEmbeddedInfo() const; + void setRoEmbeddedInfo(const sLayout& info); + + const sLayout& getRoDynStrInfo() const; + void setRoDynStrInfo(const sLayout& info); + + const sLayout& getRoDynSymInfo() const; + void setRoDynSymInfo(const sLayout& info); private: const std::string kModuleName = "NSO_HEADER"; @@ -37,6 +137,15 @@ namespace nx fnd::MemoryBlob mBinaryBlob; // data + sModuleId mModuleId; + uint32_t mBssSize; + sCodeSegment mTextSegmentInfo; + sCodeSegment mRoSegmentInfo; + sCodeSegment mDataSegmentInfo; + sLayout mModuleNameInfo; + sLayout mRoEmbeddedInfo; + sLayout mRoDynStrInfo; + sLayout mRoDynSymInfo; // helpers bool isEqual(const NsoHeader& other) const; diff --git a/lib/libnx/include/nx/nso.h b/lib/libnx/include/nx/nso.h index 2c20877..7f40f8a 100644 --- a/lib/libnx/include/nx/nso.h +++ b/lib/libnx/include/nx/nso.h @@ -2,9 +2,7 @@ #include #include #include -#include #include -#include #include namespace nx @@ -23,6 +21,7 @@ namespace nx FLAG_DATA_HASH }; + static const uint32_t kDefaultFormatVersion = 0; static const size_t kModuleIdLen = 32; } @@ -43,7 +42,7 @@ namespace nx struct sNsoHeader { char signature[4]; - le_uint32_t version; + le_uint32_t format_version; byte_t reserved_1[4]; le_uint32_t flags; sNsoCodeSegment text; @@ -60,9 +59,9 @@ namespace nx sNsoSection embedded; sNsoSection dyn_str; sNsoSection dyn_sym; - byte_t text_hash[crypto::sha::kSha256HashLen]; - byte_t ro_hash[crypto::sha::kSha256HashLen]; - byte_t data_hash[crypto::sha::kSha256HashLen]; + crypto::sha::sSha256Hash text_hash; + crypto::sha::sSha256Hash ro_hash; + crypto::sha::sSha256Hash data_hash; }; #pragma pack(pop) diff --git a/lib/libnx/source/NsoHeader.cpp b/lib/libnx/source/NsoHeader.cpp index 6aa0ad9..e6163e4 100644 --- a/lib/libnx/source/NsoHeader.cpp +++ b/lib/libnx/source/NsoHeader.cpp @@ -42,24 +42,282 @@ size_t nx::NsoHeader::getSize() const void nx::NsoHeader::exportBinary() { - throw fnd::Exception(kModuleName, "exportBinary() not implemented"); + mBinaryBlob.alloc(sizeof(sNsoHeader)); + nx::sNsoHeader* hdr = (nx::sNsoHeader*)mBinaryBlob.getBytes(); + + // set header identifers + memcpy(hdr->signature, nso::kNsoSig.c_str(), 4); + hdr->format_version = nso::kDefaultFormatVersion; + + // variable to store flags before commiting to header + uint32_t flags = 0; + + // set moduleid + memcpy(hdr->module_id, mModuleId.data, nso::kModuleIdLen); + + // set bss size + hdr->bss_size = mBssSize; + + // set text segment + hdr->text.file_offset = mTextSegmentInfo.file_layout.offset; + hdr->text.memory_offset = mTextSegmentInfo.memory_layout.offset; + hdr->text.size = mTextSegmentInfo.memory_layout.size; + hdr->text_file_size = mTextSegmentInfo.file_layout.size; + if (mTextSegmentInfo.is_compressed) + { + flags |= _BIT(nso::FLAG_TEXT_COMPRESS); + } + if (mTextSegmentInfo.is_hashed) + { + flags |= _BIT(nso::FLAG_TEXT_HASH); + hdr->text_hash = mTextSegmentInfo.hash; + } + + // set ro segment + hdr->ro.file_offset = mRoSegmentInfo.file_layout.offset; + hdr->ro.memory_offset = mRoSegmentInfo.memory_layout.offset; + hdr->ro.size = mRoSegmentInfo.memory_layout.size; + hdr->ro_file_size = mRoSegmentInfo.file_layout.size; + if (mRoSegmentInfo.is_compressed) + { + flags |= _BIT(nso::FLAG_RO_COMPRESS); + } + if (mRoSegmentInfo.is_hashed) + { + flags |= _BIT(nso::FLAG_RO_HASH); + hdr->ro_hash = mRoSegmentInfo.hash; + } + + // set data segment + hdr->data.file_offset = mDataSegmentInfo.file_layout.offset; + hdr->data.memory_offset = mDataSegmentInfo.memory_layout.offset; + hdr->data.size = mDataSegmentInfo.memory_layout.size; + hdr->data_file_size = mDataSegmentInfo.file_layout.size; + if (mDataSegmentInfo.is_compressed) + { + flags |= _BIT(nso::FLAG_DATA_COMPRESS); + } + if (mDataSegmentInfo.is_hashed) + { + flags |= _BIT(nso::FLAG_DATA_HASH); + hdr->data_hash = mDataSegmentInfo.hash; + } + + // set module name info + hdr->module_name_offset = mModuleNameInfo.offset; + hdr->module_name_size = mModuleNameInfo.size; + + // set ro embedded info + hdr->embedded.offset = mRoEmbeddedInfo.offset; + hdr->embedded.size = mRoEmbeddedInfo.size; + + // set ro dyn str info + hdr->dyn_str.offset = mRoDynStrInfo.offset; + hdr->dyn_str.size = mRoDynStrInfo.size; + + // set ro dyn sym info + hdr->dyn_sym.offset = mRoDynSymInfo.offset; + hdr->dyn_sym.size = mRoDynSymInfo.size; + + hdr->flags = flags; } void nx::NsoHeader::importBinary(const byte_t* bytes, size_t len) { - throw fnd::Exception(kModuleName, "importBinary() not implemented"); + // check input data size + if (len < sizeof(sNsoHeader)) + { + throw fnd::Exception(kModuleName, "NSO header size is too small"); + } + + // clear internal members + clear(); + + // allocate internal local binary copy + mBinaryBlob.alloc(sizeof(sNsoHeader)); + memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); + + // get sNsoHeader ptr + const nx::sNsoHeader* hdr = (const nx::sNsoHeader*)mBinaryBlob.getBytes(); + + // check NSO signature + if (std::string(hdr->signature, 4) != nso::kNsoSig) + { + throw fnd::Exception(kModuleName, "NSO header corrupt (unrecognised header signature)"); + } + + // check NSO format version + if (hdr->format_version.get() != nso::kDefaultFormatVersion) + { + throw fnd::Exception(kModuleName, "NSO header corrupt (unsupported format version)"); + } + + memcpy(mModuleId.data, hdr->module_id, nso::kModuleIdLen); + + mBssSize = hdr->bss_size.get(); + + mTextSegmentInfo.file_layout.offset = hdr->text.file_offset.get(); + mTextSegmentInfo.file_layout.size = hdr->text_file_size.get(); + mTextSegmentInfo.memory_layout.offset = hdr->text.memory_offset.get(); + mTextSegmentInfo.memory_layout.size = hdr->text.size.get(); + mTextSegmentInfo.is_compressed = _HAS_BIT(hdr->flags.get(), nso::FLAG_TEXT_COMPRESS); + mTextSegmentInfo.is_hashed = _HAS_BIT(hdr->flags.get(), nso::FLAG_TEXT_HASH); + mTextSegmentInfo.hash = hdr->text_hash; + + mRoSegmentInfo.file_layout.offset = hdr->ro.file_offset.get(); + mRoSegmentInfo.file_layout.size = hdr->ro_file_size.get(); + mRoSegmentInfo.memory_layout.offset = hdr->ro.memory_offset.get(); + mRoSegmentInfo.memory_layout.size = hdr->ro.size.get(); + mRoSegmentInfo.is_compressed = _HAS_BIT(hdr->flags.get(), nso::FLAG_RO_COMPRESS); + mRoSegmentInfo.is_hashed = _HAS_BIT(hdr->flags.get(), nso::FLAG_RO_HASH); + mRoSegmentInfo.hash = hdr->ro_hash; + + mDataSegmentInfo.file_layout.offset = hdr->data.file_offset.get(); + mDataSegmentInfo.file_layout.size = hdr->data_file_size.get(); + mDataSegmentInfo.memory_layout.offset = hdr->data.memory_offset.get(); + mDataSegmentInfo.memory_layout.size = hdr->data.size.get(); + mDataSegmentInfo.is_compressed = _HAS_BIT(hdr->flags.get(), nso::FLAG_RO_COMPRESS); + mDataSegmentInfo.is_hashed = _HAS_BIT(hdr->flags.get(), nso::FLAG_RO_HASH); + mDataSegmentInfo.hash = hdr->data_hash; + + mModuleNameInfo.offset = hdr->module_name_offset.get(); + mModuleNameInfo.size = hdr->module_name_size.get(); + + mRoEmbeddedInfo.offset = hdr->embedded.offset.get(); + mRoEmbeddedInfo.size = hdr->embedded.size.get(); + + mRoDynStrInfo.offset = hdr->dyn_str.offset.get(); + mRoDynStrInfo.size = hdr->dyn_str.size.get(); + + mRoDynSymInfo.offset = hdr->dyn_sym.offset.get(); + mRoDynSymInfo.size = hdr->dyn_sym.size.get(); } void nx::NsoHeader::clear() { + mBinaryBlob.clear(); + memset(&mModuleId, 0, sizeof(mModuleId)); + mBssSize = 0; + memset(&mTextSegmentInfo, 0, sizeof(mTextSegmentInfo)); + memset(&mRoSegmentInfo, 0, sizeof(mRoSegmentInfo)); + memset(&mDataSegmentInfo, 0, sizeof(mDataSegmentInfo)); + memset(&mModuleNameInfo, 0, sizeof(mModuleNameInfo)); + memset(&mRoEmbeddedInfo, 0, sizeof(mRoEmbeddedInfo)); + memset(&mRoDynStrInfo, 0, sizeof(mRoDynStrInfo)); + memset(&mRoDynSymInfo, 0, sizeof(mRoDynSymInfo)); +} +const nx::NsoHeader::sModuleId& nx::NsoHeader::getModuleId() const +{ + return mModuleId; +} + +void nx::NsoHeader::setModuleId(const sModuleId& id) +{ + mModuleId = id; +} + +uint32_t nx::NsoHeader::getBssSize() const +{ + return mBssSize; +} + +void nx::NsoHeader::setBssSize(uint32_t size) +{ + mBssSize = size; +} + +const nx::NsoHeader::sCodeSegment& nx::NsoHeader::getTextSegmentInfo() const +{ + return mTextSegmentInfo; +} + +void nx::NsoHeader::setTextSegmentInfo(const sCodeSegment& info) +{ + mTextSegmentInfo = info; +} + +const nx::NsoHeader::sCodeSegment& nx::NsoHeader::getRoSegmentInfo() const +{ + return mRoSegmentInfo; +} + +void nx::NsoHeader::setRoSegmentInfo(const sCodeSegment& info) +{ + mRoSegmentInfo = info; +} + +const nx::NsoHeader::sCodeSegment& nx::NsoHeader::getDataSegmentInfo() const +{ + return mDataSegmentInfo; +} + +void nx::NsoHeader::setDataSegmentInfo(const sCodeSegment& info) +{ + mDataSegmentInfo = info; +} + +const nx::NsoHeader::sLayout& nx::NsoHeader::getModuleNameInfo() const +{ + return mModuleNameInfo; +} + +void nx::NsoHeader::setModuleNameInfo(const sLayout& info) +{ + mModuleNameInfo = info; +} + +const nx::NsoHeader::sLayout& nx::NsoHeader::getRoEmbeddedInfo() const +{ + return mRoEmbeddedInfo; +} + +void nx::NsoHeader::setRoEmbeddedInfo(const sLayout& info) +{ + mRoEmbeddedInfo = info; +} + +const nx::NsoHeader::sLayout& nx::NsoHeader::getRoDynStrInfo() const +{ + return mRoDynStrInfo; +} + +void nx::NsoHeader::setRoDynStrInfo(const sLayout& info) +{ + mRoDynStrInfo = info; +} + +const nx::NsoHeader::sLayout& nx::NsoHeader::getRoDynSymInfo() const +{ + return mRoDynSymInfo; +} + +void nx::NsoHeader::setRoDynSymInfo(const sLayout& info) +{ + mRoDynSymInfo = info; } bool nx::NsoHeader::isEqual(const NsoHeader& other) const { - return false; + return (mModuleId == other.mModuleId) \ + && (mBssSize == other.mBssSize) \ + && (mTextSegmentInfo == other.mTextSegmentInfo) \ + && (mRoSegmentInfo == other.mRoSegmentInfo) \ + && (mDataSegmentInfo == other.mDataSegmentInfo) \ + && (mModuleNameInfo == other.mModuleNameInfo) \ + && (mRoEmbeddedInfo == other.mRoEmbeddedInfo) \ + && (mRoDynStrInfo == other.mRoDynStrInfo) \ + && (mRoDynSymInfo == other.mRoDynSymInfo); } void nx::NsoHeader::copyFrom(const NsoHeader& other) { - + mModuleId = other.mModuleId; + mBssSize = other.mBssSize; + mTextSegmentInfo = other.mTextSegmentInfo; + mRoSegmentInfo = other.mRoSegmentInfo; + mDataSegmentInfo = other.mDataSegmentInfo; + mModuleNameInfo = other.mModuleNameInfo; + mRoEmbeddedInfo = other.mRoEmbeddedInfo; + mRoDynStrInfo = other.mRoDynStrInfo; + mRoDynSymInfo = other.mRoDynSymInfo; } \ No newline at end of file diff --git a/programs/nstool/source/NsoProcess.cpp b/programs/nstool/source/NsoProcess.cpp index c26af03..0f003ad 100644 --- a/programs/nstool/source/NsoProcess.cpp +++ b/programs/nstool/source/NsoProcess.cpp @@ -41,11 +41,7 @@ void NsoProcess::process() 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"); - } + mHdr.importBinary(scratch.getBytes(), scratch.getSize()); if (mCliOutputType >= OUTPUT_NORMAL) { @@ -73,70 +69,61 @@ 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); + _HEXDUMP_L(mHdr.getModuleId().data, nx::nso::kModuleIdLen); printf("\n"); printf(" Program Segments:\n"); printf(" .module_id:\n"); - printf(" FileOffset: 0x%" PRIx32 "\n", mNso.module_name_offset.get()); - printf(" FileSize: 0x%" PRIx32 "\n", mNso.module_name_size.get()); + printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getModuleNameInfo().offset); + printf(" FileSize: 0x%" PRIx32 "\n", mHdr.getModuleNameInfo().size); printf(" .text:\n"); - printf(" FileOffset: 0x%" PRIx32 "\n", mNso.text.file_offset.get()); - printf(" FileSize: 0x%" PRIx32 "%s\n", mNso.text_file_size.get(), _HAS_BIT(mNso.flags.get(), nx::nso::FLAG_TEXT_COMPRESS)? " (COMPRESSED)" : ""); - //printf(" Compressed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_TEXT_COMPRESS))); + printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getTextSegmentInfo().file_layout.offset); + printf(" FileSize: 0x%" PRIx32 "%s\n", mHdr.getTextSegmentInfo().file_layout.size, mHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : ""); printf(" .ro:\n"); - printf(" FileOffset: 0x%" PRIx32 "\n", mNso.ro.file_offset.get()); - printf(" FileSize: 0x%" PRIx32 "%s\n", mNso.ro_file_size.get(), _HAS_BIT(mNso.flags.get(), nx::nso::FLAG_RO_COMPRESS)? " (COMPRESSED)" : ""); - //printf(" Compressed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_RO_COMPRESS))); + printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().file_layout.offset); + printf(" FileSize: 0x%" PRIx32 "%s\n", mHdr.getRoSegmentInfo().file_layout.size, mHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : ""); printf(" .data:\n"); - printf(" FileOffset: 0x%" PRIx32 "\n", mNso.data.file_offset.get()); - printf(" FileSize: 0x%" PRIx32 "%s\n", mNso.data_file_size.get(), _HAS_BIT(mNso.flags.get(), nx::nso::FLAG_DATA_COMPRESS)? " (COMPRESSED)" : ""); - //printf(" Compressed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_DATA_COMPRESS))); + printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getDataSegmentInfo().file_layout.offset); + printf(" FileSize: 0x%" PRIx32 "%s\n", mHdr.getDataSegmentInfo().file_layout.size, mHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : ""); printf(" Program Sections:\n"); printf(" .text:\n"); - printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.text.memory_offset.get()); - printf(" MemorySize: 0x%" PRIx32 "\n", mNso.text.size.get()); - //printf(" Hashed: %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(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getTextSegmentInfo().memory_layout.offset); + printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getTextSegmentInfo().memory_layout.size); + if (mHdr.getTextSegmentInfo().is_hashed) { printf(" Hash: "); - _HEXDUMP_L(mNso.text_hash, 32); + _HEXDUMP_L(mHdr.getTextSegmentInfo().hash.bytes, 32); printf("\n"); } printf(" .ro:\n"); - printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.ro.memory_offset.get()); - printf(" MemorySize: 0x%" PRIx32 "\n", mNso.ro.size.get()); - //printf(" Hashed: %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(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset); + printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.size); + if (mHdr.getRoSegmentInfo().is_hashed) { printf(" Hash: "); - _HEXDUMP_L(mNso.ro_hash, 32); + _HEXDUMP_L(mHdr.getRoSegmentInfo().hash.bytes, 32); printf("\n"); } printf(" .api_info:\n"); - printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.ro.memory_offset.get() + mNso.embedded.offset.get()); - printf(" MemorySize: 0x%" PRIx32 "\n", mNso.embedded.size.get()); + printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset + mHdr.getRoEmbeddedInfo().offset); + printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoEmbeddedInfo().size); printf(" .dynstr:\n"); - printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.ro.memory_offset.get() + mNso.dyn_str.offset.get()); - printf(" MemorySize: 0x%" PRIx32 "\n", mNso.dyn_str.size.get()); + printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset + mHdr.getRoDynStrInfo().offset); + printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoDynStrInfo().size); printf(" .dynsym:\n"); - printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.ro.memory_offset.get() + mNso.dyn_sym.offset.get()); - printf(" MemorySize: 0x%" PRIx32 "\n", mNso.dyn_sym.size.get()); + printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset + mHdr.getRoDynSymInfo().offset); + printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoDynSymInfo().size); printf(" .data:\n"); - printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.data.memory_offset.get()); - printf(" MemorySize: 0x%" PRIx32 "\n", mNso.data.size.get()); - //printf(" Hashed: %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(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getDataSegmentInfo().memory_layout.offset); + printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getDataSegmentInfo().memory_layout.size); + if (mHdr.getDataSegmentInfo().is_hashed) { printf(" Hash: "); - _HEXDUMP_L(mNso.data_hash, 32); + _HEXDUMP_L(mHdr.getDataSegmentInfo().hash.bytes, 32); printf("\n"); } printf(" .bss:\n"); - printf(" MemorySize: 0x%" PRIx32 "\n", mNso.bss_size.get()); + printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getBssSize()); #undef _HEXDUMP_L -} - +} \ No newline at end of file diff --git a/programs/nstool/source/NsoProcess.h b/programs/nstool/source/NsoProcess.h index 8eef37b..5973098 100644 --- a/programs/nstool/source/NsoProcess.h +++ b/programs/nstool/source/NsoProcess.h @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include "nstool.h" @@ -26,7 +26,7 @@ private: CliOutputType mCliOutputType; bool mVerify; - nx::sNsoHeader mNso; + nx::NsoHeader mHdr; void displayHeader(); }; \ No newline at end of file