mirror of
https://github.com/jakcron/nstool
synced 2024-12-25 14:11:14 +00:00
[nstool] Add dynamic symbol processing to NsoProcess.
This commit is contained in:
parent
caeea8f119
commit
36d7d7a5bf
7 changed files with 93 additions and 16 deletions
|
@ -168,6 +168,7 @@
|
|||
<ClInclude Include="source\AesCtrWrappedIFile.h" />
|
||||
<ClInclude Include="source\CnmtProcess.h" />
|
||||
<ClInclude Include="source\CopiedIFile.h" />
|
||||
<ClInclude Include="source\DynamicSymbolParser.h" />
|
||||
<ClInclude Include="source\HashTreeMeta.h" />
|
||||
<ClInclude Include="source\HashTreeWrappedIFile.h" />
|
||||
<ClInclude Include="source\NcaProcess.h" />
|
||||
|
@ -184,6 +185,7 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="source\AesCtrWrappedIFile.cpp" />
|
||||
<ClCompile Include="source\CnmtProcess.cpp" />
|
||||
<ClCompile Include="source\DynamicSymbolParser.cpp" />
|
||||
<ClCompile Include="source\HashTreeMeta.cpp" />
|
||||
<ClCompile Include="source\HashTreeWrappedIFile.cpp" />
|
||||
<ClCompile Include="source\main.cpp" />
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<ClInclude Include="source\NsoProcess.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\DynamicSymbolParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="source\main.cpp">
|
||||
|
@ -101,6 +104,9 @@
|
|||
<ClCompile Include="source\NsoProcess.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\DynamicSymbolParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
#include <nx/NsoHeader.h>
|
||||
|
||||
#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<nx::npdm::InstructionType> mArchType;
|
||||
|
||||
nx::NsoHeader mHdr;
|
||||
fnd::MemoryBlob mTextBlob, mRoBlob, mDataBlob;
|
||||
std::vector<std::string> mApiList;
|
||||
DynamicSymbolParser mDynSymbolList;
|
||||
|
||||
void importHeader();
|
||||
void importCodeSegments();
|
||||
|
|
|
@ -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 <architecture>] <.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<nx::npdm::InstructionType>& UserSettings::getArchType() const
|
||||
{
|
||||
return mArchType;
|
||||
}
|
||||
|
||||
const sOptional<std::string>& 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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <fnd/types.h>
|
||||
#include <nx/npdm.h>
|
||||
#include "nstool.h"
|
||||
|
||||
class UserSettings
|
||||
|
@ -20,6 +21,7 @@ public:
|
|||
|
||||
// specialised toggles
|
||||
bool isListFs() const;
|
||||
const sOptional<nx::npdm::InstructionType>& getArchType() const;
|
||||
|
||||
// specialised paths
|
||||
const sOptional<std::string>& getUpdatePath() const;
|
||||
|
@ -54,6 +56,7 @@ private:
|
|||
sOptional<std::string> part1_path;
|
||||
sOptional<std::string> part2_path;
|
||||
sOptional<std::string> part3_path;
|
||||
sOptional<std::string> 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<std::string> mPart2Path;
|
||||
sOptional<std::string> mPart3Path;
|
||||
|
||||
sOptional<nx::npdm::InstructionType> 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);
|
||||
};
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue