nstool/lib/libnx/source/NsoHeader.cpp
2018-06-04 12:00:28 +08:00

323 lines
8.5 KiB
C++

#include <nx/NsoHeader.h>
nx::NsoHeader::NsoHeader()
{
}
nx::NsoHeader::NsoHeader(const NsoHeader& other)
{
copyFrom(other);
}
nx::NsoHeader::NsoHeader(const byte_t* bytes, size_t len)
{
importBinary(bytes, len);
}
bool nx::NsoHeader::operator==(const NsoHeader& other) const
{
return isEqual(other);
}
bool nx::NsoHeader::operator!=(const NsoHeader& other) const
{
return !(*this == other);
}
void nx::NsoHeader::operator=(const NsoHeader& other)
{
copyFrom(other);
}
const byte_t* nx::NsoHeader::getBytes() const
{
return mBinaryBlob.getBytes();
}
size_t nx::NsoHeader::getSize() const
{
return mBinaryBlob.getSize();
}
void nx::NsoHeader::exportBinary()
{
mBinaryBlob.alloc(sizeof(sNsoHeader));
nx::sNsoHeader* hdr = (nx::sNsoHeader*)mBinaryBlob.getBytes();
// set header identifers
hdr->signature = nso::kNsoSig;
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::kModuleIdSize);
// 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)
{
// 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 (hdr->signature.get() != 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::kModuleIdSize);
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()
{
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
{
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)
{
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;
}