diff --git a/build/visualstudio/nstool/nstool.vcxproj b/build/visualstudio/nstool/nstool.vcxproj
index f452499..655fbb7 100644
--- a/build/visualstudio/nstool/nstool.vcxproj
+++ b/build/visualstudio/nstool/nstool.vcxproj
@@ -76,7 +76,7 @@
Disabled
true
true
- $(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include
+ $(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include
MultiThreadedDebug
@@ -86,7 +86,7 @@
Disabled
true
true
- $(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include
+ $(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include
MultiThreadedDebug
@@ -98,7 +98,7 @@
true
true
true
- $(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include
+ $(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include
MultiThreaded
@@ -114,7 +114,7 @@
true
true
true
- $(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include
+ $(ProjectDir)..\..\..\include;$(SolutionDir)..\..\deps\libfnd\include;$(SolutionDir)..\..\deps\liblz4\include;$(SolutionDir)..\..\deps\libtoolchain\include;$(SolutionDir)..\..\deps\libfmt\include;$(SolutionDir)..\..\deps\libnintendo-es\include;$(SolutionDir)..\..\deps\libnintendo-pki\include;$(SolutionDir)..\..\deps\libnintendo-hac\include;$(SolutionDir)..\..\deps\libnintendo-hac-hb\include
MultiThreaded
@@ -188,6 +188,8 @@
+
+
diff --git a/build/visualstudio/nstool/nstool.vcxproj.filters b/build/visualstudio/nstool/nstool.vcxproj.filters
index 69e6c9f..a866cc6 100644
--- a/build/visualstudio/nstool/nstool.vcxproj.filters
+++ b/build/visualstudio/nstool/nstool.vcxproj.filters
@@ -143,5 +143,11 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
\ No newline at end of file
diff --git a/src/NroProcess.cpp b/src/NroProcess.cpp
new file mode 100644
index 0000000..66a061c
--- /dev/null
+++ b/src/NroProcess.cpp
@@ -0,0 +1,192 @@
+#include "NroProcess.h"
+
+#include
+
+nstool::NroProcess::NroProcess() :
+ mModuleName("nstool::NroProcess"),
+ mFile(),
+ mCliOutputMode(true, false, false, false),
+ mVerify(false)
+{
+}
+
+void nstool::NroProcess::process()
+{
+ importHeader();
+ importCodeSegments();
+
+ if (mCliOutputMode.show_basic_info)
+ displayHeader();
+
+ processRoMeta();
+
+ if (mIsHomebrewNro)
+ mAssetProc.process();
+}
+
+void nstool::NroProcess::setInputFile(const std::shared_ptr& file)
+{
+ mFile = file;
+}
+
+void nstool::NroProcess::setCliOutputMode(CliOutputMode type)
+{
+ mCliOutputMode = type;
+}
+
+void nstool::NroProcess::setVerifyMode(bool verify)
+{
+ mVerify = verify;
+}
+
+void nstool::NroProcess::setIs64BitInstruction(bool flag)
+{
+ mRoMeta.setIs64BitInstruction(flag);
+}
+
+void nstool::NroProcess::setListApi(bool listApi)
+{
+ mRoMeta.setListApi(listApi);
+}
+
+void nstool::NroProcess::setListSymbols(bool listSymbols)
+{
+ mRoMeta.setListSymbols(listSymbols);
+}
+
+void nstool::NroProcess::setAssetIconExtractPath(const tc::io::Path& path)
+{
+ mAssetProc.setIconExtractPath(path);
+}
+
+void nstool::NroProcess::setAssetNacpExtractPath(const tc::io::Path& path)
+{
+ mAssetProc.setNacpExtractPath(path);
+}
+
+void nstool::NroProcess::setAssetRomfsShowFsTree(bool show_fs_tree)
+{
+ mAssetProc.setRomfsShowFsTree(show_fs_tree);
+}
+
+void nstool::NroProcess::setAssetRomfsExtractJobs(const std::vector& extract_jobs)
+{
+ mAssetProc.setRomfsExtractJobs(extract_jobs);
+}
+
+const nstool::RoMetadataProcess& nstool::NroProcess::getRoMetadataProcess() const
+{
+ return mRoMeta;
+}
+
+void nstool::NroProcess::importHeader()
+{
+ if (mFile == nullptr)
+ {
+ throw tc::Exception(mModuleName, "No file reader set.");
+ }
+ if (mFile->canRead() == false || mFile->canSeek() == false)
+ {
+ throw tc::NotSupportedException(mModuleName, "Input stream requires read/seek permissions.");
+ }
+
+ // check if file_size is smaller than NRO header size
+ if (tc::io::IOUtil::castInt64ToSize(mFile->length()) < sizeof(nn::hac::sNroHeader))
+ {
+ throw tc::Exception(mModuleName, "Corrupt NRO: file too small.");
+ }
+
+ // read nro
+ tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sNroHeader));
+ mFile->seek(0, tc::io::SeekOrigin::Begin);
+ mFile->read(scratch.data(), scratch.size());
+
+ // parse nro header
+ mHdr.fromBytes(scratch.data(), scratch.size());
+
+ // setup homebrew extension
+ nn::hac::sNroHeader* raw_hdr = (nn::hac::sNroHeader*)scratch.data();
+
+ int64_t file_size = mFile->length();
+ if (((tc::bn::le64*)raw_hdr->reserved_0.data())->unwrap() == nn::hac::nro::kNroHomebrewStructMagic && file_size > int64_t(mHdr.getNroSize()))
+ {
+ mIsHomebrewNro = true;
+ mAssetProc.setInputFile(std::make_shared(tc::io::SubStream(mFile, int64_t(mHdr.getNroSize()), file_size - int64_t(mHdr.getNroSize()))));
+ mAssetProc.setCliOutputMode(mCliOutputMode);
+ mAssetProc.setVerifyMode(mVerify);
+ }
+ else
+ mIsHomebrewNro = false;
+}
+
+void nstool::NroProcess::importCodeSegments()
+{
+ if (mHdr.getTextInfo().size > 0)
+ {
+ mTextBlob = tc::ByteData(mHdr.getTextInfo().size);
+ mFile->seek(mHdr.getTextInfo().memory_offset, tc::io::SeekOrigin::Begin);
+ mFile->read(mTextBlob.data(), mTextBlob.size());
+ }
+
+ if (mHdr.getRoInfo().size > 0)
+ {
+ mRoBlob = tc::ByteData(mHdr.getRoInfo().size);
+ mFile->seek(mHdr.getRoInfo().memory_offset, tc::io::SeekOrigin::Begin);
+ mFile->read(mRoBlob.data(), mRoBlob.size());
+ }
+
+ if (mHdr.getDataInfo().size > 0)
+ {
+ mDataBlob = tc::ByteData(mHdr.getDataInfo().size);
+ mFile->seek(mHdr.getDataInfo().memory_offset, tc::io::SeekOrigin::Begin);
+ mFile->read(mDataBlob.data(), mDataBlob.size());
+ }
+}
+
+void nstool::NroProcess::displayHeader()
+{
+ fmt::print("[NRO Header]\n");
+ fmt::print(" RoCrt: \n");
+ fmt::print(" EntryPoint: 0x{:x}\n", mHdr.getRoCrtEntryPoint());
+ fmt::print(" ModOffset: 0x{:x}\n", mHdr.getRoCrtModOffset());
+ fmt::print(" ModuleId: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mHdr.getModuleId().data(), mHdr.getModuleId().size(), false, ""));
+ fmt::print(" NroSize: 0x{:x}\n", mHdr.getNroSize());
+ fmt::print(" Program Sections:\n");
+ fmt::print(" .text:\n");
+ fmt::print(" Offset: 0x{:x}\n", mHdr.getTextInfo().memory_offset);
+ fmt::print(" Size: 0x{:x}\n", mHdr.getTextInfo().size);
+ fmt::print(" .ro:\n");
+ fmt::print(" Offset: 0x{:x}\n", mHdr.getRoInfo().memory_offset);
+ fmt::print(" Size: 0x{:x}\n", mHdr.getRoInfo().size);
+ if (mCliOutputMode.show_extended_info)
+ {
+ fmt::print(" .api_info:\n");
+ fmt::print(" Offset: 0x{:x}\n", mHdr.getRoEmbeddedInfo().memory_offset);
+ fmt::print(" Size: 0x{:x}\n", mHdr.getRoEmbeddedInfo().size);
+ fmt::print(" .dynstr:\n");
+ fmt::print(" Offset: 0x{:x}\n", mHdr.getRoDynStrInfo().memory_offset);
+ fmt::print(" Size: 0x{:x}\n", mHdr.getRoDynStrInfo().size);
+ fmt::print(" .dynsym:\n");
+ fmt::print(" Offset: 0x{:x}\n", mHdr.getRoDynSymInfo().memory_offset);
+ fmt::print(" Size: 0x{:x}\n", mHdr.getRoDynSymInfo().size);
+ }
+ fmt::print(" .data:\n");
+ fmt::print(" Offset: 0x{:x}\n", mHdr.getDataInfo().memory_offset);
+ fmt::print(" Size: 0x{:x}\n", mHdr.getDataInfo().size);
+ fmt::print(" .bss:\n");
+ fmt::print(" Size: 0x{:x}\n", mHdr.getBssSize());
+}
+
+void nstool::NroProcess::processRoMeta()
+{
+ if (mRoBlob.size())
+ {
+ // setup ro metadata
+ mRoMeta.setApiInfo(mHdr.getRoEmbeddedInfo().memory_offset, mHdr.getRoEmbeddedInfo().size);
+ mRoMeta.setDynSym(mHdr.getRoDynSymInfo().memory_offset, mHdr.getRoDynSymInfo().size);
+ mRoMeta.setDynStr(mHdr.getRoDynStrInfo().memory_offset, mHdr.getRoDynStrInfo().size);
+ mRoMeta.setRoBinary(mRoBlob);
+ mRoMeta.setCliOutputMode(mCliOutputMode);
+ mRoMeta.process();
+ }
+}
\ No newline at end of file
diff --git a/src/NroProcess.h b/src/NroProcess.h
index efc8610..ac93711 100644
--- a/src/NroProcess.h
+++ b/src/NroProcess.h
@@ -3,7 +3,6 @@
#include "RoMetadataProcess.h"
#include "AssetProcess.h"
-#include
#include
namespace nstool {
@@ -24,14 +23,14 @@ public:
void setListSymbols(bool listSymbols);
// for homebrew NROs with Asset blobs appended
- void setAssetListFs(bool list);
void setAssetIconExtractPath(const tc::io::Path& path);
void setAssetNacpExtractPath(const tc::io::Path& path);
- void setAssetRomfsExtractPath(const tc::io::Path& path);
+ void setAssetRomfsShowFsTree(bool show_fs_tree);
+ void setAssetRomfsExtractJobs(const std::vector& extract_jobs);
- const RoMetadataProcess& getRoMetadataProcess() const;
+ const nstool::RoMetadataProcess& getRoMetadataProcess() const;
private:
- const std::string kModuleName = "NroProcess";
+ std::string mModuleName;
std::shared_ptr mFile;
CliOutputMode mCliOutputMode;
@@ -39,9 +38,9 @@ private:
nn::hac::NroHeader mHdr;
tc::ByteData mTextBlob, mRoBlob, mDataBlob;
- RoMetadataProcess mRoMeta;
+ nstool::RoMetadataProcess mRoMeta;
bool mIsHomebrewNro;
- AssetProcess mAssetProc;
+ nstool::AssetProcess mAssetProc;
void importHeader();
void importCodeSegments();
diff --git a/src/NsoProcess.cpp b/src/NsoProcess.cpp
new file mode 100644
index 0000000..7680d49
--- /dev/null
+++ b/src/NsoProcess.cpp
@@ -0,0 +1,285 @@
+#include "NsoProcess.h"
+
+#include
+
+nstool::NsoProcess::NsoProcess() :
+ mModuleName("nstool::NsoProcess"),
+ mFile(),
+ mCliOutputMode(true, false, false, false),
+ mVerify(false),
+ mIs64BitInstruction(true),
+ mListApi(false),
+ mListSymbols(false)
+{
+}
+
+void nstool::NsoProcess::process()
+{
+ importHeader();
+ importCodeSegments();
+ if (mCliOutputMode.show_basic_info)
+ displayNsoHeader();
+
+ processRoMeta();
+}
+
+void nstool::NsoProcess::setInputFile(const std::shared_ptr& file)
+{
+ mFile = file;
+}
+
+void nstool::NsoProcess::setCliOutputMode(CliOutputMode type)
+{
+ mCliOutputMode = type;
+}
+
+void nstool::NsoProcess::setVerifyMode(bool verify)
+{
+ mVerify = verify;
+}
+
+void nstool::NsoProcess::setIs64BitInstruction(bool flag)
+{
+ mRoMeta.setIs64BitInstruction(flag);
+}
+
+void nstool::NsoProcess::setListApi(bool listApi)
+{
+ mRoMeta.setListApi(listApi);
+}
+
+void nstool::NsoProcess::setListSymbols(bool listSymbols)
+{
+ mRoMeta.setListSymbols(listSymbols);
+}
+
+const nstool::RoMetadataProcess& nstool::NsoProcess::getRoMetadataProcess() const
+{
+ return mRoMeta;
+}
+
+void nstool::NsoProcess::importHeader()
+{
+ if (mFile == nullptr)
+ {
+ throw tc::Exception(mModuleName, "No file reader set.");
+ }
+ if (mFile->canRead() == false || mFile->canSeek() == false)
+ {
+ throw tc::NotSupportedException(mModuleName, "Input stream requires read/seek permissions.");
+ }
+
+ // check if file_size is smaller than NSO header size
+ size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length());
+ if (file_size < sizeof(nn::hac::sNsoHeader))
+ {
+ throw tc::Exception(mModuleName, "Corrupt NSO: file too small.");
+ }
+
+ // read nso
+ tc::ByteData scratch = tc::ByteData(sizeof(nn::hac::sNsoHeader));
+ mFile->seek(0, tc::io::SeekOrigin::Begin);
+ mFile->read(scratch.data(), scratch.size());
+
+ // parse nso header
+ mHdr.fromBytes(scratch.data(), scratch.size());
+}
+
+void nstool::NsoProcess::importCodeSegments()
+{
+ tc::ByteData scratch;
+ nn::hac::detail::sha256_hash_t calc_hash;
+
+ // process text segment
+ if (mHdr.getTextSegmentInfo().is_compressed)
+ {
+ // allocate/read compressed text
+ scratch = tc::ByteData(mHdr.getTextSegmentInfo().file_layout.size);
+ mFile->seek(mHdr.getTextSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
+ mFile->read(scratch.data(), scratch.size());
+
+ // allocate for decompressed text segment
+ mTextBlob = tc::ByteData(mHdr.getTextSegmentInfo().memory_layout.size);
+
+ // decompress text segment
+ if (decompressData(scratch.data(), scratch.size(), mTextBlob.data(), mTextBlob.size()) != mTextBlob.size())
+ {
+ throw tc::Exception(mModuleName, "NSO text segment failed to decompress");
+ }
+ }
+ else
+ {
+ // read text segment directly (not compressed)
+ mTextBlob = tc::ByteData(mHdr.getTextSegmentInfo().file_layout.size);
+ mFile->seek(mHdr.getTextSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
+ mFile->read(mTextBlob.data(), mTextBlob.size());
+ }
+ if (mHdr.getTextSegmentInfo().is_hashed)
+ {
+ tc::crypto::GenerateSha256Hash(calc_hash.data(), mTextBlob.data(), mTextBlob.size());
+ if (calc_hash != mHdr.getTextSegmentInfo().hash)
+ {
+ throw tc::Exception(mModuleName, "NSO text segment failed SHA256 verification");
+ }
+ }
+
+ // process ro segment
+ if (mHdr.getRoSegmentInfo().is_compressed)
+ {
+ // allocate/read compressed ro segment
+ scratch = tc::ByteData(mHdr.getRoSegmentInfo().file_layout.size);
+ mFile->seek(mHdr.getRoSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
+ mFile->read(scratch.data(), scratch.size());
+
+ // allocate for decompressed ro segment
+ mRoBlob = tc::ByteData(mHdr.getRoSegmentInfo().memory_layout.size);
+
+ // decompress ro segment
+ if (decompressData(scratch.data(), scratch.size(), mRoBlob.data(), mRoBlob.size()) != mRoBlob.size())
+ {
+ throw tc::Exception(mModuleName, "NSO ro segment failed to decompress");
+ }
+ }
+ else
+ {
+ // read ro segment directly (not compressed)
+ mRoBlob = tc::ByteData(mHdr.getRoSegmentInfo().file_layout.size);
+ mFile->seek(mHdr.getRoSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
+ mFile->read(mRoBlob.data(), mRoBlob.size());
+ }
+ if (mHdr.getRoSegmentInfo().is_hashed)
+ {
+ tc::crypto::GenerateSha256Hash(calc_hash.data(), mRoBlob.data(), mRoBlob.size());
+ if (calc_hash != mHdr.getRoSegmentInfo().hash)
+ {
+ throw tc::Exception(mModuleName, "NSO ro segment failed SHA256 verification");
+ }
+ }
+
+ // process ro segment
+ if (mHdr.getDataSegmentInfo().is_compressed)
+ {
+ // allocate/read compressed ro segment
+ scratch = tc::ByteData(mHdr.getDataSegmentInfo().file_layout.size);
+ mFile->seek(mHdr.getDataSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
+ mFile->read(scratch.data(), scratch.size());
+
+ // allocate for decompressed ro segment
+ mDataBlob = tc::ByteData(mHdr.getDataSegmentInfo().memory_layout.size);
+
+ // decompress ro segment
+ if (decompressData(scratch.data(), scratch.size(), mDataBlob.data(), mDataBlob.size()) != mDataBlob.size())
+ {
+ throw tc::Exception(mModuleName, "NSO data segment failed to decompress");
+ }
+ }
+ else
+ {
+ // read ro segment directly (not compressed)
+ mDataBlob = tc::ByteData(mHdr.getDataSegmentInfo().file_layout.size);
+ mFile->seek(mHdr.getDataSegmentInfo().file_layout.offset, tc::io::SeekOrigin::Begin);
+ mFile->read(mDataBlob.data(), mDataBlob.size());
+ }
+ if (mHdr.getDataSegmentInfo().is_hashed)
+ {
+ tc::crypto::GenerateSha256Hash(calc_hash.data(), mDataBlob.data(), mDataBlob.size());
+ if (calc_hash != mHdr.getDataSegmentInfo().hash)
+ {
+ throw tc::Exception(mModuleName, "NSO data segment failed SHA256 verification");
+ }
+ }
+}
+
+void nstool::NsoProcess::displayNsoHeader()
+{
+ fmt::print("[NSO Header]\n");
+ fmt::print(" ModuleId: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mHdr.getModuleId().data(), mHdr.getModuleId().size(), false, ""));
+ if (mCliOutputMode.show_layout)
+ {
+ fmt::print(" Program Segments:\n");
+ fmt::print(" .module_name:\n");
+ fmt::print(" FileOffset: 0x{:x}\n", mHdr.getModuleNameInfo().offset);
+ fmt::print(" FileSize: 0x{:x}\n", mHdr.getModuleNameInfo().size);
+ fmt::print(" .text:\n");
+ fmt::print(" FileOffset: 0x{:x}\n", mHdr.getTextSegmentInfo().file_layout.offset);
+ fmt::print(" FileSize: 0x{:x}{:s}\n", mHdr.getTextSegmentInfo().file_layout.size, (mHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : ""));
+ fmt::print(" .ro:\n");
+ fmt::print(" FileOffset: 0x{:x}\n", mHdr.getRoSegmentInfo().file_layout.offset);
+ fmt::print(" FileSize: 0x{:x}{:s}\n", mHdr.getRoSegmentInfo().file_layout.size, (mHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : ""));
+ fmt::print(" .data:\n");
+ fmt::print(" FileOffset: 0x{:x}\n", mHdr.getDataSegmentInfo().file_layout.offset);
+ fmt::print(" FileSize: 0x{:x}{:s}\n", mHdr.getDataSegmentInfo().file_layout.size, (mHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : ""));
+ }
+ fmt::print(" Program Sections:\n");
+ fmt::print(" .text:\n");
+ fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getTextSegmentInfo().memory_layout.offset);
+ fmt::print(" MemorySize: 0x{:x}\n", mHdr.getTextSegmentInfo().memory_layout.size);
+ if (mHdr.getTextSegmentInfo().is_hashed && mCliOutputMode.show_extended_info)
+ {
+ fmt::print(" Hash: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mHdr.getTextSegmentInfo().hash.data(), mHdr.getTextSegmentInfo().hash.size(), false, ""));
+ }
+ fmt::print(" .ro:\n");
+ fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getRoSegmentInfo().memory_layout.offset);
+ fmt::print(" MemorySize: 0x{:x}\n", mHdr.getRoSegmentInfo().memory_layout.size);
+ if (mHdr.getRoSegmentInfo().is_hashed && mCliOutputMode.show_extended_info)
+ {
+ fmt::print(" Hash: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mHdr.getRoSegmentInfo().hash.data(), mHdr.getRoSegmentInfo().hash.size(), false, ""));
+ }
+ if (mCliOutputMode.show_extended_info)
+ {
+ fmt::print(" .api_info:\n");
+ fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getRoEmbeddedInfo().offset);
+ fmt::print(" MemorySize: 0x{:x}\n", mHdr.getRoEmbeddedInfo().size);
+ fmt::print(" .dynstr:\n");
+ fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getRoDynStrInfo().offset);
+ fmt::print(" MemorySize: 0x{:x}\n", mHdr.getRoDynStrInfo().size);
+ fmt::print(" .dynsym:\n");
+ fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getRoDynSymInfo().offset);
+ fmt::print(" MemorySize: 0x{:x}\n", mHdr.getRoDynSymInfo().size);
+ }
+
+ fmt::print(" .data:\n");
+ fmt::print(" MemoryOffset: 0x{:x}\n", mHdr.getDataSegmentInfo().memory_layout.offset);
+ fmt::print(" MemorySize: 0x{:x}\n", mHdr.getDataSegmentInfo().memory_layout.size);
+ if (mHdr.getDataSegmentInfo().is_hashed && mCliOutputMode.show_extended_info)
+ {
+ fmt::print(" Hash: {:s}\n", tc::cli::FormatUtil::formatBytesAsString(mHdr.getDataSegmentInfo().hash.data(), mHdr.getDataSegmentInfo().hash.size(), false, ""));
+ }
+ fmt::print(" .bss:\n");
+ fmt::print(" MemorySize: 0x{:x}\n", mHdr.getBssSize());
+}
+
+void nstool::NsoProcess::processRoMeta()
+{
+ if (mRoBlob.size())
+ {
+ // setup ro metadata
+ mRoMeta.setApiInfo(mHdr.getRoEmbeddedInfo().offset, mHdr.getRoEmbeddedInfo().size);
+ mRoMeta.setDynSym(mHdr.getRoDynSymInfo().offset, mHdr.getRoDynSymInfo().size);
+ mRoMeta.setDynStr(mHdr.getRoDynStrInfo().offset, mHdr.getRoDynStrInfo().size);
+ mRoMeta.setRoBinary(mRoBlob);
+ mRoMeta.setCliOutputMode(mCliOutputMode);
+ mRoMeta.process();
+ }
+}
+
+size_t nstool::NsoProcess::decompressData(const byte_t* src, size_t src_len, byte_t* dst, size_t dst_capacity)
+{
+ if (src_len >= LZ4_MAX_INPUT_SIZE)
+ {
+ return 0;
+ }
+
+ int32_t src_len_input = int32_t(src_len);
+ int32_t dst_capcacity_input = (dst_capacity < LZ4_MAX_INPUT_SIZE) ? int32_t(dst_capacity) : LZ4_MAX_INPUT_SIZE;
+
+ int32_t decomp_size = LZ4_decompress_safe((const char*)src, (char*)dst, src_len_input, dst_capcacity_input);
+
+ if (decomp_size < 0)
+ {
+ memset(dst, 0, dst_capacity);
+ return 0;
+ }
+
+ return size_t(decomp_size);
+}
\ No newline at end of file
diff --git a/src/NsoProcess.h b/src/NsoProcess.h
index 2f4fbb2..5856e7a 100644
--- a/src/NsoProcess.h
+++ b/src/NsoProcess.h
@@ -22,9 +22,9 @@ public:
void setListApi(bool listApi);
void setListSymbols(bool listSymbols);
- const RoMetadataProcess& getRoMetadataProcess() const;
+ const nstool::RoMetadataProcess& getRoMetadataProcess() const;
private:
- const std::string kModuleName = "NsoProcess";
+ std::string mModuleName;
std::shared_ptr mFile;
CliOutputMode mCliOutputMode;
@@ -35,12 +35,15 @@ private:
nn::hac::NsoHeader mHdr;
tc::ByteData mTextBlob, mRoBlob, mDataBlob;
- RoMetadataProcess mRoMeta;
+ nstool::RoMetadataProcess mRoMeta;
void importHeader();
void importCodeSegments();
void displayNsoHeader();
void processRoMeta();
+
+ size_t decompressData(const byte_t* src, size_t src_len, byte_t* dst, size_t dst_capacity);
+
};
}
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 2eb2230..be46c10 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -9,8 +9,8 @@
//#include "NcaProcess.h"
//#include "MetaProcess.h"
#include "CnmtProcess.h"
-//#include "NsoProcess.h"
-//#include "NroProcess.h"
+#include "NsoProcess.h"
+#include "NroProcess.h"
#include "NacpProcess.h"
//#include "IniProcess.h"
//#include "KipProcess.h"
@@ -115,7 +115,6 @@ int umain(const std::vector& args, const std::vector&
obj.process();
}
- /*
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NSO)
{
nstool::NsoProcess obj;
@@ -147,13 +146,11 @@ int umain(const std::vector& args, const std::vector&
if (set.aset.nacp_extract_path.isSet())
obj.setAssetNacpExtractPath(set.aset.nacp_extract_path.get());
- if (set.fs.extract_path.isSet())
- obj.setAssetRomfsExtractPath(set.fs.extract_path.get());
- obj.setAssetListFs(set.fs.show_fs_tree);
+ obj.setAssetRomfsShowFsTree(set.fs.show_fs_tree);
+ obj.setAssetRomfsExtractJobs(set.fs.extract_jobs);
obj.process();
}
- */
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NACP)
{
nstool::NacpProcess obj;
diff --git a/src/not_ported/NroProcess.cpp b/src/not_ported/NroProcess.cpp
deleted file mode 100644
index c76d845..0000000
--- a/src/not_ported/NroProcess.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "NroProcess.h"
-
-nstool::NroProcess::NroProcess():
- mFile(),
- mCliOutputMode(true, false, false, false),
- mVerify(false)
-{
-}
-
-void nstool::NroProcess::process()
-{
- importHeader();
- importCodeSegments();
-
- if (mCliOutputMode.show_basic_info)
- displayHeader();
-
- processRoMeta();
-
- if (mIsHomebrewNro)
- mAssetProc.process();
-}
-
-void nstool::NroProcess::setInputFile(const std::shared_ptr& file)
-{
- mFile = file;
-}
-
-void nstool::NroProcess::setCliOutputMode(CliOutputMode type)
-{
- mCliOutputMode = type;
-}
-
-void nstool::NroProcess::setVerifyMode(bool verify)
-{
- mVerify = verify;
-}
-
-void nstool::NroProcess::setIs64BitInstruction(bool flag)
-{
- mRoMeta.setIs64BitInstruction(flag);
-}
-
-void nstool::NroProcess::setListApi(bool listApi)
-{
- mRoMeta.setListApi(listApi);
-}
-
-void nstool::NroProcess::setListSymbols(bool listSymbols)
-{
- mRoMeta.setListSymbols(listSymbols);
-}
-
-void nstool::NroProcess::setAssetListFs(bool list)
-{
- mAssetProc.setListFs(list);
-}
-
-void nstool::NroProcess::setAssetIconExtractPath(const std::string& path)
-{
- mAssetProc.setIconExtractPath(path);
-}
-
-void nstool::NroProcess::setAssetNacpExtractPath(const std::string& path)
-{
- mAssetProc.setNacpExtractPath(path);
-}
-
-void nstool::NroProcess::setAssetRomfsExtractPath(const std::string& path)
-{
- mAssetProc.setRomfsExtractPath(path);
-}
-
-const RoMetadataProcess& nstool::NroProcess::getRoMetadataProcess() const
-{
- return mRoMeta;
-}
-
-void nstool::NroProcess::importHeader()
-{
- tc::ByteData scratch;
-
- if (*mFile == nullptr)
- {
- throw tc::Exception(kModuleName, "No file reader set.");
- }
-
- if ((*mFile)->size() < sizeof(nn::hac::sNroHeader))
- {
- throw tc::Exception(kModuleName, "Corrupt NRO: file too small");
- }
-
- scratch.alloc(sizeof(nn::hac::sNroHeader));
- (*mFile)->read(scratch.data(), 0, scratch.size());
-
- mHdr.fromBytes(scratch.data(), scratch.size());
-
- // setup homebrew extension
- nn::hac::sNroHeader* raw_hdr = (nn::hac::sNroHeader*)scratch.data();
- if (((tc::bn::le64*)raw_hdr->reserved_0)->get() == nn::hac::nro::kNroHomebrewStructMagic && (*mFile)->size() > mHdr.getNroSize())
- {
- mIsHomebrewNro = true;
- mAssetProc.setInputFile(new fnd::OffsetAdjustedIFile(mFile, mHdr.getNroSize(), (*mFile)->size() - mHdr.getNroSize()));
- mAssetProc.setCliOutputMode(mCliOutputMode);
- mAssetProc.setVerifyMode(mVerify);
- }
- else
- mIsHomebrewNro = false;
-}
-
-void nstool::NroProcess::importCodeSegments()
-{
- mTextBlob.alloc(mHdr.getTextInfo().size);
- (*mFile)->read(mTextBlob.data(), mHdr.getTextInfo().memory_offset, mTextBlob.size());
- mRoBlob.alloc(mHdr.getRoInfo().size);
- (*mFile)->read(mRoBlob.data(), mHdr.getRoInfo().memory_offset, mRoBlob.size());
- mDataBlob.alloc(mHdr.getDataInfo().size);
- (*mFile)->read(mDataBlob.data(), mHdr.getDataInfo().memory_offset, mDataBlob.size());
-}
-
-void nstool::NroProcess::displayHeader()
-{
- std::cout << "[NRO Header]" << std::endl;
- std::cout << " RoCrt: " << std::endl;
- std::cout << " EntryPoint: 0x" << std::hex << mHdr.getRoCrtEntryPoint() << std::endl;
- std::cout << " ModOffset: 0x" << std::hex << mHdr.getRoCrtModOffset() << std::endl;
- std::cout << " ModuleId: " << fnd::SimpleTextOutput::arrayToString(mHdr.getModuleId().data, nn::hac::nro::kModuleIdSize, false, "") << std::endl;
- std::cout << " NroSize: 0x" << std::hex << mHdr.getNroSize() << std::endl;
- std::cout << " Program Sections:" << std::endl;
- std::cout << " .text:" << std::endl;
- std::cout << " Offset: 0x" << std::hex << mHdr.getTextInfo().memory_offset << std::endl;
- std::cout << " Size: 0x" << std::hex << mHdr.getTextInfo().size << std::endl;
- std::cout << " .ro:" << std::endl;
- std::cout << " Offset: 0x" << std::hex << mHdr.getRoInfo().memory_offset << std::endl;
- std::cout << " Size: 0x" << std::hex << mHdr.getRoInfo().size << std::endl;
- if (mCliOutputMode.show_extended_info)
- {
- std::cout << " .api_info:" << std::endl;
- std::cout << " Offset: 0x" << std::hex << mHdr.getRoEmbeddedInfo().memory_offset << std::endl;
- std::cout << " Size: 0x" << std::hex << mHdr.getRoEmbeddedInfo().size << std::endl;
- std::cout << " .dynstr:" << std::endl;
- std::cout << " Offset: 0x" << std::hex << mHdr.getRoDynStrInfo().memory_offset << std::endl;
- std::cout << " Size: 0x" << std::hex << mHdr.getRoDynStrInfo().size << std::endl;
- std::cout << " .dynsym:" << std::endl;
- std::cout << " Offset: 0x" << std::hex << mHdr.getRoDynSymInfo().memory_offset << std::endl;
- std::cout << " Size: 0x" << std::hex << mHdr.getRoDynSymInfo().size << std::endl;
- }
- std::cout << " .data:" << std::endl;
- std::cout << " Offset: 0x" << std::hex << mHdr.getDataInfo().memory_offset << std::endl;
- std::cout << " Size: 0x" << std::hex << mHdr.getDataInfo().size << std::endl;
- std::cout << " .bss:" << std::endl;
- std::cout << " Size: 0x" << std::hex << mHdr.getBssSize() << std::endl;
-}
-
-void nstool::NroProcess::processRoMeta()
-{
- if (mRoBlob.size())
- {
- // setup ro metadata
- mRoMeta.setApiInfo(mHdr.getRoEmbeddedInfo().memory_offset, mHdr.getRoEmbeddedInfo().size);
- mRoMeta.setDynSym(mHdr.getRoDynSymInfo().memory_offset, mHdr.getRoDynSymInfo().size);
- mRoMeta.setDynStr(mHdr.getRoDynStrInfo().memory_offset, mHdr.getRoDynStrInfo().size);
- mRoMeta.setRoBinary(mRoBlob);
- mRoMeta.setCliOutputMode(mCliOutputMode);
- mRoMeta.process();
- }
-}
\ No newline at end of file
diff --git a/src/not_ported/NsoProcess.cpp b/src/not_ported/NsoProcess.cpp
deleted file mode 100644
index dbdc11f..0000000
--- a/src/not_ported/NsoProcess.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include "NsoProcess.h"
-
-nstool::NsoProcess::NsoProcess():
- mFile(),
- mCliOutputMode(true, false, false, false),
- mVerify(false),
- mIs64BitInstruction(true),
- mListApi(false),
- mListSymbols(false)
-{
-}
-
-void nstool::NsoProcess::process()
-{
- importHeader();
- importCodeSegments();
- if (mCliOutputMode.show_basic_info)
- displayNsoHeader();
-
- processRoMeta();
-}
-
-void nstool::NsoProcess::setInputFile(const std::shared_ptr& file)
-{
- mFile = file;
-}
-
-void nstool::NsoProcess::setCliOutputMode(CliOutputMode type)
-{
- mCliOutputMode = type;
-}
-
-void nstool::NsoProcess::setVerifyMode(bool verify)
-{
- mVerify = verify;
-}
-
-void nstool::NsoProcess::setIs64BitInstruction(bool flag)
-{
- mRoMeta.setIs64BitInstruction(flag);
-}
-
-void nstool::NsoProcess::setListApi(bool listApi)
-{
- mRoMeta.setListApi(listApi);
-}
-
-void nstool::NsoProcess::setListSymbols(bool listSymbols)
-{
- mRoMeta.setListSymbols(listSymbols);
-}
-
-const RoMetadataProcess& nstool::NsoProcess::getRoMetadataProcess() const
-{
- return mRoMeta;
-}
-
-void nstool::NsoProcess::importHeader()
-{
- tc::ByteData scratch;
-
- if (*mFile == nullptr)
- {
- throw tc::Exception(kModuleName, "No file reader set.");
- }
-
- if ((*mFile)->size() < sizeof(nn::hac::sNsoHeader))
- {
- throw tc::Exception(kModuleName, "Corrupt NSO: file too small");
- }
-
- scratch.alloc(sizeof(nn::hac::sNsoHeader));
- (*mFile)->read(scratch.data(), 0, scratch.size());
-
- mHdr.fromBytes(scratch.data(), scratch.size());
-}
-
-void nstool::NsoProcess::importCodeSegments()
-{
- tc::ByteData scratch;
- uint32_t decompressed_len;
- fnd::sha::sSha256Hash calc_hash;
-
- // process text segment
- if (mHdr.getTextSegmentInfo().is_compressed)
- {
- scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size);
- (*mFile)->read(scratch.data(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.size());
- mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size);
- fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mTextBlob.data(), (uint32_t)mTextBlob.size(), decompressed_len);
- if (decompressed_len != mTextBlob.size())
- {
- throw tc::Exception(kModuleName, "NSO text segment failed to decompress");
- }
- }
- else
- {
- mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size);
- (*mFile)->read(mTextBlob.data(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.size());
- }
- if (mHdr.getTextSegmentInfo().is_hashed)
- {
- fnd::sha::Sha256(mTextBlob.data(), mTextBlob.size(), calc_hash.bytes);
- if (calc_hash != mHdr.getTextSegmentInfo().hash)
- {
- throw tc::Exception(kModuleName, "NSO text segment failed SHA256 verification");
- }
- }
-
- // process ro segment
- if (mHdr.getRoSegmentInfo().is_compressed)
- {
- scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size);
- (*mFile)->read(scratch.data(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.size());
- mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size);
- fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mRoBlob.data(), (uint32_t)mRoBlob.size(), decompressed_len);
- if (decompressed_len != mRoBlob.size())
- {
- throw tc::Exception(kModuleName, "NSO ro segment failed to decompress");
- }
- }
- else
- {
- mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size);
- (*mFile)->read(mRoBlob.data(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.size());
- }
- if (mHdr.getRoSegmentInfo().is_hashed)
- {
- fnd::sha::Sha256(mRoBlob.data(), mRoBlob.size(), calc_hash.bytes);
- if (calc_hash != mHdr.getRoSegmentInfo().hash)
- {
- throw tc::Exception(kModuleName, "NSO ro segment failed SHA256 verification");
- }
- }
-
- // process data segment
- if (mHdr.getDataSegmentInfo().is_compressed)
- {
- scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size);
- (*mFile)->read(scratch.data(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.size());
- mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size);
- fnd::lz4::decompressData(scratch.data(), (uint32_t)scratch.size(), mDataBlob.data(), (uint32_t)mDataBlob.size(), decompressed_len);
- if (decompressed_len != mDataBlob.size())
- {
- throw tc::Exception(kModuleName, "NSO data segment failed to decompress");
- }
- }
- else
- {
- mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size);
- (*mFile)->read(mDataBlob.data(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.size());
- }
- if (mHdr.getDataSegmentInfo().is_hashed)
- {
- fnd::sha::Sha256(mDataBlob.data(), mDataBlob.size(), calc_hash.bytes);
- if (calc_hash != mHdr.getDataSegmentInfo().hash)
- {
- throw tc::Exception(kModuleName, "NSO data segment failed SHA256 verification");
- }
- }
-}
-
-void nstool::NsoProcess::displayNsoHeader()
-{
- std::cout << "[NSO Header]" << std::endl;
- std::cout << " ModuleId: " << fnd::SimpleTextOutput::arrayToString(mHdr.getModuleId().data, nn::hac::nso::kModuleIdSize, false, "") << std::endl;
- if (mCliOutputMode.show_layout)
- {
- std::cout << " Program Segments:" << std::endl;
- std::cout << " .module_name:" << std::endl;
- std::cout << " FileOffset: 0x" << std::hex << mHdr.getModuleNameInfo().offset << std::endl;
- std::cout << " FileSize: 0x" << std::hex << mHdr.getModuleNameInfo().size << std::endl;
- std::cout << " .text:" << std::endl;
- std::cout << " FileOffset: 0x" << std::hex << mHdr.getTextSegmentInfo().file_layout.offset << std::endl;
- std::cout << " FileSize: 0x" << std::hex << mHdr.getTextSegmentInfo().file_layout.size << (mHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl;
- std::cout << " .ro:" << std::endl;
- std::cout << " FileOffset: 0x" << std::hex << mHdr.getRoSegmentInfo().file_layout.offset << std::endl;
- std::cout << " FileSize: 0x" << std::hex << mHdr.getRoSegmentInfo().file_layout.size << (mHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl;
- std::cout << " .data:" << std::endl;
- std::cout << " FileOffset: 0x" << std::hex << mHdr.getDataSegmentInfo().file_layout.offset << std::endl;
- std::cout << " FileSize: 0x" << std::hex << mHdr.getDataSegmentInfo().file_layout.size << (mHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : "") << std::endl;
- }
- std::cout << " Program Sections:" << std::endl;
- std::cout << " .text:" << std::endl;
- std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getTextSegmentInfo().memory_layout.offset << std::endl;
- std::cout << " MemorySize: 0x" << std::hex << mHdr.getTextSegmentInfo().memory_layout.size << std::endl;
- if (mHdr.getTextSegmentInfo().is_hashed && mCliOutputMode.show_extended_info)
- {
- std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(mHdr.getTextSegmentInfo().hash.bytes, 32, false, "") << std::endl;
- }
- std::cout << " .ro:" << std::endl;
- std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoSegmentInfo().memory_layout.offset << std::endl;
- std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoSegmentInfo().memory_layout.size << std::endl;
- if (mHdr.getRoSegmentInfo().is_hashed && mCliOutputMode.show_extended_info)
- {
- std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(mHdr.getRoSegmentInfo().hash.bytes, 32, false, "") << std::endl;
- }
- if (mCliOutputMode.show_extended_info)
- {
- std::cout << " .api_info:" << std::endl;
- std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoEmbeddedInfo().offset << std::endl;
- std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoEmbeddedInfo().size << std::endl;
- std::cout << " .dynstr:" << std::endl;
- std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoDynStrInfo().offset << std::endl;
- std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoDynStrInfo().size << std::endl;
- std::cout << " .dynsym:" << std::endl;
- std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getRoDynSymInfo().offset << std::endl;
- std::cout << " MemorySize: 0x" << std::hex << mHdr.getRoDynSymInfo().size << std::endl;
- }
-
- std::cout << " .data:" << std::endl;
- std::cout << " MemoryOffset: 0x" << std::hex << mHdr.getDataSegmentInfo().memory_layout.offset << std::endl;
- std::cout << " MemorySize: 0x" << std::hex << mHdr.getDataSegmentInfo().memory_layout.size << std::endl;
- if (mHdr.getDataSegmentInfo().is_hashed && mCliOutputMode.show_extended_info)
- {
- std::cout << " Hash: " << fnd::SimpleTextOutput::arrayToString(mHdr.getDataSegmentInfo().hash.bytes, 32, false, "") << std::endl;
- }
- std::cout << " .bss:" << std::endl;
- std::cout << " MemorySize: 0x" << std::hex << mHdr.getBssSize() << std::endl;
-}
-
-void nstool::NsoProcess::processRoMeta()
-{
- if (mRoBlob.size())
- {
- // setup ro metadata
- mRoMeta.setApiInfo(mHdr.getRoEmbeddedInfo().offset, mHdr.getRoEmbeddedInfo().size);
- mRoMeta.setDynSym(mHdr.getRoDynSymInfo().offset, mHdr.getRoDynSymInfo().size);
- mRoMeta.setDynStr(mHdr.getRoDynStrInfo().offset, mHdr.getRoDynStrInfo().size);
- mRoMeta.setRoBinary(mRoBlob);
- mRoMeta.setCliOutputMode(mCliOutputMode);
- mRoMeta.process();
- }
-}
\ No newline at end of file