mirror of
https://github.com/jakcron/nstool
synced 2024-11-15 02:06:40 +00:00
[nx|nstool] Encapsulated NsoHeader parsing into nx::NsoHeader
This commit is contained in:
parent
3363d9152a
commit
915bd80f6f
5 changed files with 409 additions and 56 deletions
|
@ -1,5 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <nx/xci.h>
|
#include <nx/nso.h>
|
||||||
#include <fnd/MemoryBlob.h>
|
#include <fnd/MemoryBlob.h>
|
||||||
#include <fnd/List.h>
|
#include <fnd/List.h>
|
||||||
#include <fnd/ISerialiseableBinary.h>
|
#include <fnd/ISerialiseableBinary.h>
|
||||||
|
@ -10,6 +10,81 @@ namespace nx
|
||||||
public fnd::ISerialiseableBinary
|
public fnd::ISerialiseableBinary
|
||||||
{
|
{
|
||||||
public:
|
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();
|
||||||
NsoHeader(const NsoHeader& other);
|
NsoHeader(const NsoHeader& other);
|
||||||
NsoHeader(const byte_t* bytes, size_t len);
|
NsoHeader(const byte_t* bytes, size_t len);
|
||||||
|
@ -29,7 +104,32 @@ namespace nx
|
||||||
// variables
|
// variables
|
||||||
void clear();
|
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:
|
private:
|
||||||
const std::string kModuleName = "NSO_HEADER";
|
const std::string kModuleName = "NSO_HEADER";
|
||||||
|
|
||||||
|
@ -37,6 +137,15 @@ namespace nx
|
||||||
fnd::MemoryBlob mBinaryBlob;
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
// data
|
// data
|
||||||
|
sModuleId mModuleId;
|
||||||
|
uint32_t mBssSize;
|
||||||
|
sCodeSegment mTextSegmentInfo;
|
||||||
|
sCodeSegment mRoSegmentInfo;
|
||||||
|
sCodeSegment mDataSegmentInfo;
|
||||||
|
sLayout mModuleNameInfo;
|
||||||
|
sLayout mRoEmbeddedInfo;
|
||||||
|
sLayout mRoDynStrInfo;
|
||||||
|
sLayout mRoDynSymInfo;
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
bool isEqual(const NsoHeader& other) const;
|
bool isEqual(const NsoHeader& other) const;
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fnd/types.h>
|
#include <fnd/types.h>
|
||||||
#include <fnd/List.h>
|
#include <fnd/List.h>
|
||||||
#include <crypto/aes.h>
|
|
||||||
#include <crypto/sha.h>
|
#include <crypto/sha.h>
|
||||||
#include <crypto/rsa.h>
|
|
||||||
#include <fnd/ISerialiseableBinary.h>
|
#include <fnd/ISerialiseableBinary.h>
|
||||||
|
|
||||||
namespace nx
|
namespace nx
|
||||||
|
@ -23,6 +21,7 @@ namespace nx
|
||||||
FLAG_DATA_HASH
|
FLAG_DATA_HASH
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint32_t kDefaultFormatVersion = 0;
|
||||||
static const size_t kModuleIdLen = 32;
|
static const size_t kModuleIdLen = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ namespace nx
|
||||||
struct sNsoHeader
|
struct sNsoHeader
|
||||||
{
|
{
|
||||||
char signature[4];
|
char signature[4];
|
||||||
le_uint32_t version;
|
le_uint32_t format_version;
|
||||||
byte_t reserved_1[4];
|
byte_t reserved_1[4];
|
||||||
le_uint32_t flags;
|
le_uint32_t flags;
|
||||||
sNsoCodeSegment text;
|
sNsoCodeSegment text;
|
||||||
|
@ -60,9 +59,9 @@ namespace nx
|
||||||
sNsoSection embedded;
|
sNsoSection embedded;
|
||||||
sNsoSection dyn_str;
|
sNsoSection dyn_str;
|
||||||
sNsoSection dyn_sym;
|
sNsoSection dyn_sym;
|
||||||
byte_t text_hash[crypto::sha::kSha256HashLen];
|
crypto::sha::sSha256Hash text_hash;
|
||||||
byte_t ro_hash[crypto::sha::kSha256HashLen];
|
crypto::sha::sSha256Hash ro_hash;
|
||||||
byte_t data_hash[crypto::sha::kSha256HashLen];
|
crypto::sha::sSha256Hash data_hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
|
@ -42,24 +42,282 @@ size_t nx::NsoHeader::getSize() const
|
||||||
|
|
||||||
void nx::NsoHeader::exportBinary()
|
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)
|
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()
|
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
|
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)
|
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;
|
||||||
}
|
}
|
|
@ -41,11 +41,7 @@ void NsoProcess::process()
|
||||||
scratch.alloc(sizeof(nx::sNsoHeader));
|
scratch.alloc(sizeof(nx::sNsoHeader));
|
||||||
mReader->read(scratch.getBytes(), 0, scratch.getSize());
|
mReader->read(scratch.getBytes(), 0, scratch.getSize());
|
||||||
|
|
||||||
memcpy(&mNso, scratch.getBytes(), sizeof(nx::sNsoHeader));
|
mHdr.importBinary(scratch.getBytes(), scratch.getSize());
|
||||||
if (std::string(mNso.signature, 4) != nx::nso::kNsoSig)
|
|
||||||
{
|
|
||||||
throw fnd::Exception(kModuleName, "Corrupt NSO header");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
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)
|
#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("[NSO Header]\n");
|
||||||
printf(" Format Version: %" PRId32 "\n", mNso.version.get());
|
|
||||||
printf(" Flags: 0x%" PRIx32 "\n", mNso.flags.get());
|
|
||||||
printf(" ModuleId: ");
|
printf(" ModuleId: ");
|
||||||
_HEXDUMP_L(mNso.module_id, 32);
|
_HEXDUMP_L(mHdr.getModuleId().data, nx::nso::kModuleIdLen);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" Program Segments:\n");
|
printf(" Program Segments:\n");
|
||||||
printf(" .module_id:\n");
|
printf(" .module_id:\n");
|
||||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNso.module_name_offset.get());
|
printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getModuleNameInfo().offset);
|
||||||
printf(" FileSize: 0x%" PRIx32 "\n", mNso.module_name_size.get());
|
printf(" FileSize: 0x%" PRIx32 "\n", mHdr.getModuleNameInfo().size);
|
||||||
printf(" .text:\n");
|
printf(" .text:\n");
|
||||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNso.text.file_offset.get());
|
printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getTextSegmentInfo().file_layout.offset);
|
||||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mNso.text_file_size.get(), _HAS_BIT(mNso.flags.get(), nx::nso::FLAG_TEXT_COMPRESS)? " (COMPRESSED)" : "");
|
printf(" FileSize: 0x%" PRIx32 "%s\n", mHdr.getTextSegmentInfo().file_layout.size, mHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||||
//printf(" Compressed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_TEXT_COMPRESS)));
|
|
||||||
printf(" .ro:\n");
|
printf(" .ro:\n");
|
||||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNso.ro.file_offset.get());
|
printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().file_layout.offset);
|
||||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mNso.ro_file_size.get(), _HAS_BIT(mNso.flags.get(), nx::nso::FLAG_RO_COMPRESS)? " (COMPRESSED)" : "");
|
printf(" FileSize: 0x%" PRIx32 "%s\n", mHdr.getRoSegmentInfo().file_layout.size, mHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||||
//printf(" Compressed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_RO_COMPRESS)));
|
|
||||||
printf(" .data:\n");
|
printf(" .data:\n");
|
||||||
printf(" FileOffset: 0x%" PRIx32 "\n", mNso.data.file_offset.get());
|
printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getDataSegmentInfo().file_layout.offset);
|
||||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mNso.data_file_size.get(), _HAS_BIT(mNso.flags.get(), nx::nso::FLAG_DATA_COMPRESS)? " (COMPRESSED)" : "");
|
printf(" FileSize: 0x%" PRIx32 "%s\n", mHdr.getDataSegmentInfo().file_layout.size, mHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||||
//printf(" Compressed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_DATA_COMPRESS)));
|
|
||||||
printf(" Program Sections:\n");
|
printf(" Program Sections:\n");
|
||||||
printf(" .text:\n");
|
printf(" .text:\n");
|
||||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.text.memory_offset.get());
|
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getTextSegmentInfo().memory_layout.offset);
|
||||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNso.text.size.get());
|
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getTextSegmentInfo().memory_layout.size);
|
||||||
//printf(" Hashed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_TEXT_HASH)));
|
if (mHdr.getTextSegmentInfo().is_hashed)
|
||||||
if (_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_TEXT_HASH))
|
|
||||||
{
|
{
|
||||||
printf(" Hash: ");
|
printf(" Hash: ");
|
||||||
_HEXDUMP_L(mNso.text_hash, 32);
|
_HEXDUMP_L(mHdr.getTextSegmentInfo().hash.bytes, 32);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
printf(" .ro:\n");
|
printf(" .ro:\n");
|
||||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.ro.memory_offset.get());
|
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset);
|
||||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNso.ro.size.get());
|
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.size);
|
||||||
//printf(" Hashed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_RO_HASH)));
|
if (mHdr.getRoSegmentInfo().is_hashed)
|
||||||
if (_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_RO_HASH))
|
|
||||||
{
|
{
|
||||||
printf(" Hash: ");
|
printf(" Hash: ");
|
||||||
_HEXDUMP_L(mNso.ro_hash, 32);
|
_HEXDUMP_L(mHdr.getRoSegmentInfo().hash.bytes, 32);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
printf(" .api_info:\n");
|
printf(" .api_info:\n");
|
||||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.ro.memory_offset.get() + mNso.embedded.offset.get());
|
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset + mHdr.getRoEmbeddedInfo().offset);
|
||||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNso.embedded.size.get());
|
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoEmbeddedInfo().size);
|
||||||
printf(" .dynstr:\n");
|
printf(" .dynstr:\n");
|
||||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.ro.memory_offset.get() + mNso.dyn_str.offset.get());
|
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset + mHdr.getRoDynStrInfo().offset);
|
||||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNso.dyn_str.size.get());
|
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoDynStrInfo().size);
|
||||||
printf(" .dynsym:\n");
|
printf(" .dynsym:\n");
|
||||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.ro.memory_offset.get() + mNso.dyn_sym.offset.get());
|
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset + mHdr.getRoDynSymInfo().offset);
|
||||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNso.dyn_sym.size.get());
|
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoDynSymInfo().size);
|
||||||
printf(" .data:\n");
|
printf(" .data:\n");
|
||||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mNso.data.memory_offset.get());
|
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getDataSegmentInfo().memory_layout.offset);
|
||||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNso.data.size.get());
|
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getDataSegmentInfo().memory_layout.size);
|
||||||
//printf(" Hashed: %s\n", getBoolStr(_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_DATA_HASH)));
|
if (mHdr.getDataSegmentInfo().is_hashed)
|
||||||
if (_HAS_BIT(mNso.flags.get(), nx::nso::FLAG_DATA_HASH))
|
|
||||||
{
|
{
|
||||||
printf(" Hash: ");
|
printf(" Hash: ");
|
||||||
_HEXDUMP_L(mNso.data_hash, 32);
|
_HEXDUMP_L(mHdr.getDataSegmentInfo().hash.bytes, 32);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
printf(" .bss:\n");
|
printf(" .bss:\n");
|
||||||
printf(" MemorySize: 0x%" PRIx32 "\n", mNso.bss_size.get());
|
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getBssSize());
|
||||||
|
|
||||||
#undef _HEXDUMP_L
|
#undef _HEXDUMP_L
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fnd/types.h>
|
#include <fnd/types.h>
|
||||||
#include <fnd/IFile.h>
|
#include <fnd/IFile.h>
|
||||||
#include <nx/nso.h>
|
#include <nx/NsoHeader.h>
|
||||||
|
|
||||||
#include "nstool.h"
|
#include "nstool.h"
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ private:
|
||||||
CliOutputType mCliOutputType;
|
CliOutputType mCliOutputType;
|
||||||
bool mVerify;
|
bool mVerify;
|
||||||
|
|
||||||
nx::sNsoHeader mNso;
|
nx::NsoHeader mHdr;
|
||||||
|
|
||||||
void displayHeader();
|
void displayHeader();
|
||||||
};
|
};
|
Loading…
Reference in a new issue