diff --git a/programs/nstool/nstool.vcxproj b/programs/nstool/nstool.vcxproj
index 7a87ad3..fcd32eb 100644
--- a/programs/nstool/nstool.vcxproj
+++ b/programs/nstool/nstool.vcxproj
@@ -168,6 +168,7 @@
+
@@ -184,6 +185,7 @@
+
diff --git a/programs/nstool/nstool.vcxproj.filters b/programs/nstool/nstool.vcxproj.filters
index f35bba6..799b7f4 100644
--- a/programs/nstool/nstool.vcxproj.filters
+++ b/programs/nstool/nstool.vcxproj.filters
@@ -60,6 +60,9 @@
Header Files
+
+ Header Files
+
@@ -101,6 +104,9 @@
Source Files
+
+ Source Files
+
diff --git a/programs/nstool/source/NsoProcess.cpp b/programs/nstool/source/NsoProcess.cpp
index b7fe4ed..8b080c0 100644
--- a/programs/nstool/source/NsoProcess.cpp
+++ b/programs/nstool/source/NsoProcess.cpp
@@ -5,17 +5,12 @@
#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)
{
-
+ mArchType.isSet = false;
}
NsoProcess::~NsoProcess()
@@ -59,6 +54,11 @@ void NsoProcess::setVerifyMode(bool verify)
mVerify = verify;
}
+void NsoProcess::setArchType(nx::npdm::InstructionType type)
+{
+ mArchType = type;
+}
+
const nx::NsoHeader& NsoProcess::getNsoHeader() const
{
return mHdr;
@@ -192,7 +192,7 @@ void NsoProcess::importApiList()
std::stringstream list_stream(std::string((char*)mRoBlob.getBytes() + mHdr.getRoEmbeddedInfo().offset, mHdr.getRoEmbeddedInfo().size));
std::string api;
- while(std::getline(list_stream, api, '+'))
+ while(std::getline(list_stream, api, (char)0x00))
{
mApiList.push_back(api);
}
@@ -201,6 +201,11 @@ void NsoProcess::importApiList()
{
mApiList.clear();
}
+
+ if (mHdr.getRoDynSymInfo().size > 0 && mArchType.isSet == true)
+ {
+ mDynSymbolList.parseData(mRoBlob.getBytes() + mHdr.getRoDynSymInfo().offset, mHdr.getRoDynSymInfo().size, mRoBlob.getBytes() + mHdr.getRoDynStrInfo().offset, mHdr.getRoDynStrInfo().size, *mArchType == nx::npdm::INSTR_64BIT);
+ }
}
void NsoProcess::displayHeader()
@@ -246,13 +251,13 @@ void NsoProcess::displayHeader()
if (mCliOutputType >= OUTPUT_VERBOSE)
{
printf(" .api_info:\n");
- printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset + mHdr.getRoEmbeddedInfo().offset);
+ printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoEmbeddedInfo().offset);
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoEmbeddedInfo().size);
printf(" .dynstr:\n");
- printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset + mHdr.getRoDynStrInfo().offset);
+ printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoDynStrInfo().offset);
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoDynStrInfo().size);
printf(" .dynsym:\n");
- printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset + mHdr.getRoDynSymInfo().offset);
+ printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoDynSymInfo().offset);
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoDynSymInfo().size);
}
@@ -273,13 +278,25 @@ void NsoProcess::displayHeader()
void NsoProcess::displayRoApiList()
{
- printf("[NSO RO Segment]\n");
- if (mApiList.size() > 0)
+ if (mApiList.size() > 0 || mDynSymbolList.getDynamicSymbolList().getSize() > 0)
{
- printf(" API List:\n");
- for (size_t i = 0; i < mApiList.size(); i++)
+ printf("[NSO RO Segment]\n");
+ if (mApiList.size() > 0)
{
- printf(" %s\n", mApiList[i].c_str());
+ printf(" API List:\n");
+ for (size_t i = 0; i < mApiList.size(); i++)
+ {
+ printf(" %s\n", mApiList[i].c_str());
+ }
+ }
+ if (mDynSymbolList.getDynamicSymbolList().getSize() > 0)
+ {
+ printf(" Undefined Symbol List:\n");
+ for (size_t i = 0; i < mDynSymbolList.getDynamicSymbolList().getSize(); i++)
+ {
+ if (mDynSymbolList.getDynamicSymbolList()[i].shn_index == nx::dynsym::SHN_UNDEF && (mDynSymbolList.getDynamicSymbolList()[i].symbol_type == nx::dynsym::STT_FUNC || mDynSymbolList.getDynamicSymbolList()[i].symbol_type == nx::dynsym::STT_NOTYPE))
+ printf(" %s\n", mDynSymbolList.getDynamicSymbolList()[i].name.c_str());
+ }
}
}
}
\ No newline at end of file
diff --git a/programs/nstool/source/NsoProcess.h b/programs/nstool/source/NsoProcess.h
index 6dbc982..a1ab964 100644
--- a/programs/nstool/source/NsoProcess.h
+++ b/programs/nstool/source/NsoProcess.h
@@ -6,6 +6,7 @@
#include
#include "nstool.h"
+#include "DynamicSymbolParser.h"
class NsoProcess
{
@@ -19,6 +20,8 @@ public:
void setCliOutputMode(CliOutputType type);
void setVerifyMode(bool verify);
+ void setArchType(nx::npdm::InstructionType type);
+
// processed data
const nx::NsoHeader& getNsoHeader() const;
const fnd::MemoryBlob& getTextBlob() const;
@@ -32,10 +35,12 @@ private:
fnd::IFile* mReader;
CliOutputType mCliOutputType;
bool mVerify;
+ sOptional mArchType;
nx::NsoHeader mHdr;
fnd::MemoryBlob mTextBlob, mRoBlob, mDataBlob;
std::vector mApiList;
+ DynamicSymbolParser mDynSymbolList;
void importHeader();
void importCodeSegments();
diff --git a/programs/nstool/source/UserSettings.cpp b/programs/nstool/source/UserSettings.cpp
index 7fc07e4..977b4ed 100644
--- a/programs/nstool/source/UserSettings.cpp
+++ b/programs/nstool/source/UserSettings.cpp
@@ -62,6 +62,10 @@ void UserSettings::showHelp()
printf(" --part1 Extract \"partition 1\" to directory \n");
printf(" --part2 Extract \"partition 2\" to directory \n");
printf(" --part3 Extract \"partition 3\" to directory \n");
+ printf("\n NSO (Nintendo Software Object)\n");
+ printf(" nstool [--arch ] <.nso>\n");
+ printf(" --arch Specify code architecture [32bit, 64bit]\n");
+
}
const std::string UserSettings::getInputPath() const
@@ -94,6 +98,11 @@ bool UserSettings::isListFs() const
return mListFs;
}
+const sOptional& UserSettings::getArchType() const
+{
+ return mArchType;
+}
+
const sOptional& UserSettings::getUpdatePath() const
{
return mUpdatePath;
@@ -269,6 +278,12 @@ void UserSettings::populateCmdArgs(int argc, char** argv, sCmdArgs& cmd_args)
cmd_args.part3_path = args[i+1];
}
+ else if (args[i] == "--arch")
+ {
+ if (!hasParamter) throw fnd::Exception(kModuleName, args[i] + " requries a parameter.");
+ cmd_args.arch_type = args[i + 1];
+ }
+
else
{
throw fnd::Exception(kModuleName, args[i] + " is not recognised.");
@@ -524,6 +539,12 @@ void UserSettings::populateUserSettings(sCmdArgs& args)
mPart2Path = args.part2_path;
mPart3Path = args.part3_path;
+ // determine the architecture type for NSO
+ if (args.arch_type.isSet)
+ mArchType = getInstructionTypeFromString(*args.arch_type);
+ else
+ mArchType.isSet = false;
+
// determine output path
if (args.verbose_output.isSet)
mOutputType = OUTPUT_VERBOSE;
@@ -648,4 +669,20 @@ FileType UserSettings::determineFileTypeFromFile(const std::string& path)
#undef _QUICK_CAST
return file_type;
-}
\ No newline at end of file
+}
+
+nx::npdm::InstructionType UserSettings::getInstructionTypeFromString(const std::string & type_str)
+{
+ std::string str = type_str;
+ std::transform(str.begin(), str.end(), str.begin(), ::tolower);
+
+ nx::npdm::InstructionType type;
+ if (str == "32bit")
+ type = nx::npdm::INSTR_32BIT;
+ else if (str == "64bit")
+ type = nx::npdm::INSTR_64BIT;
+ else
+ throw fnd::Exception(kModuleName, "Unsupported architecture type: " + str);
+
+ return type;
+}
diff --git a/programs/nstool/source/UserSettings.h b/programs/nstool/source/UserSettings.h
index 030d6d5..8d508d8 100644
--- a/programs/nstool/source/UserSettings.h
+++ b/programs/nstool/source/UserSettings.h
@@ -1,6 +1,7 @@
#pragma once
#include
#include
+#include
#include "nstool.h"
class UserSettings
@@ -20,6 +21,7 @@ public:
// specialised toggles
bool isListFs() const;
+ const sOptional& getArchType() const;
// specialised paths
const sOptional& getUpdatePath() const;
@@ -54,6 +56,7 @@ private:
sOptional part1_path;
sOptional part2_path;
sOptional part3_path;
+ sOptional arch_type;
void clear()
{
@@ -75,6 +78,7 @@ private:
part1_path.isSet = false;
part2_path.isSet = false;
part3_path.isSet = false;
+ arch_type.isSet = false;
}
};
@@ -95,10 +99,13 @@ private:
sOptional mPart2Path;
sOptional mPart3Path;
+ sOptional mArchType;
+
void populateCmdArgs(int argc, char** argv, sCmdArgs& cmd_args);
void populateKeyset(sCmdArgs& args);
void populateUserSettings(sCmdArgs& args);
void decodeHexStringToBytes(const std::string& name, const std::string& str, byte_t* out, size_t out_len);
FileType getFileTypeFromString(const std::string& type_str);
FileType determineFileTypeFromFile(const std::string& path);
+ nx::npdm::InstructionType getInstructionTypeFromString(const std::string& type_str);
};
\ No newline at end of file
diff --git a/programs/nstool/source/main.cpp b/programs/nstool/source/main.cpp
index 2dd1ef1..0ef0f57 100644
--- a/programs/nstool/source/main.cpp
+++ b/programs/nstool/source/main.cpp
@@ -117,6 +117,9 @@ int main(int argc, char** argv)
nso.setInputFile(&inputFile, 0, inputFile.size());
nso.setCliOutputMode(user_set.getCliOutputType());
nso.setVerifyMode(user_set.isVerifyFile());
+
+ if (user_set.getArchType().isSet)
+ nso.setArchType(user_set.getArchType().var);
nso.process();
}