[nstool] Add dynamic symbol processing to NsoProcess.

This commit is contained in:
jakcron 2018-06-02 20:16:19 +08:00
parent caeea8f119
commit 36d7d7a5bf
7 changed files with 93 additions and 16 deletions

View file

@ -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" />

View file

@ -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" />

View file

@ -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());
}
}
}
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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);
};

View file

@ -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();
}