DOL loader cleanup with std::vector and safety checks

This commit is contained in:
JosJuice 2015-05-09 16:49:18 +02:00
parent 268b8fd26f
commit 35c77abbc2
5 changed files with 87 additions and 74 deletions

View File

@ -233,7 +233,7 @@ bool CBoot::BootUp()
DVDInterface::SetVolumeName(_StartupPara.m_strFilename); DVDInterface::SetVolumeName(_StartupPara.m_strFilename);
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid()); DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
if (!DVDInterface::VolumeIsValid()) if (!DVDInterface::VolumeIsValid())
break; return false;
const DiscIO::IVolume& pVolume = DVDInterface::GetVolume(); const DiscIO::IVolume& pVolume = DVDInterface::GetVolume();
@ -296,6 +296,9 @@ bool CBoot::BootUp()
case SCoreStartupParameter::BOOT_DOL: case SCoreStartupParameter::BOOT_DOL:
{ {
CDolLoader dolLoader(_StartupPara.m_strFilename); CDolLoader dolLoader(_StartupPara.m_strFilename);
if (!dolLoader.IsValid())
return false;
// Check if we have gotten a Wii file or not // Check if we have gotten a Wii file or not
bool dolWii = dolLoader.IsWii(); bool dolWii = dolLoader.IsWii();
if (dolWii != _StartupPara.bWii) if (dolWii != _StartupPara.bWii)

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <string> #include <string>
#include <vector>
#include "Common/CommonFuncs.h" #include "Common/CommonFuncs.h"
#include "Common/FileUtil.h" #include "Common/FileUtil.h"
@ -11,106 +12,100 @@
#include "Core/HW/Memmap.h" #include "Core/HW/Memmap.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
CDolLoader::CDolLoader(u8* _pBuffer, u32 _Size) CDolLoader::CDolLoader(u8* buffer, size_t size)
: m_isWii(false)
{ {
Initialize(_pBuffer, _Size); m_is_valid = Initialize(buffer, size);
} }
CDolLoader::CDolLoader(const std::string& filename) CDolLoader::CDolLoader(const std::string& filename)
: m_isWii(false)
{ {
const u64 size = File::GetSize(filename); const u64 size = File::GetSize(filename);
u8* const tmpBuffer = new u8[(size_t)size]; std::vector<u8> temp_buffer(size);
{ {
File::IOFile pStream(filename, "rb"); File::IOFile pStream(filename, "rb");
pStream.ReadBytes(tmpBuffer, (size_t)size); pStream.ReadBytes(temp_buffer.data(), temp_buffer.size());
} }
Initialize(tmpBuffer, (u32)size); m_is_valid = Initialize(temp_buffer.data(), temp_buffer.size());
delete[] tmpBuffer;
} }
CDolLoader::~CDolLoader() CDolLoader::~CDolLoader()
{ {
for (auto& sect : text_section)
{
delete [] sect;
sect = nullptr;
} }
for (auto& sect : data_section) bool CDolLoader::Initialize(u8* buffer, size_t size)
{ {
delete [] sect; if (size < sizeof(SDolHeader))
sect = nullptr; return false;
}
}
void CDolLoader::Initialize(u8* _pBuffer, u32 _Size) memcpy(&m_dolheader, buffer, sizeof(SDolHeader));
{
memcpy(&m_dolheader, _pBuffer, sizeof(SDolHeader));
// swap memory // swap memory
u32* p = (u32*)&m_dolheader; u32* p = (u32*)&m_dolheader;
for (size_t i = 0; i < (sizeof(SDolHeader) / sizeof(u32)); i++) for (size_t i = 0; i < (sizeof(SDolHeader) / sizeof(u32)); i++)
p[i] = Common::swap32(p[i]); p[i] = Common::swap32(p[i]);
for (auto& sect : text_section) const u32 HID4_pattern = Common::swap32(0x7c13fba6);
sect = nullptr; const u32 HID4_mask = Common::swap32(0xfc1fffff);
for (auto& sect : data_section)
sect = nullptr;
u32 HID4_pattern = 0x7c13fba6; m_is_wii = false;
u32 HID4_mask = 0xfc1fffff;
for (int i = 0; i < DOL_NUM_TEXT; i++) m_text_sections.reserve(DOL_NUM_TEXT);
for (int i = 0; i < DOL_NUM_TEXT; ++i)
{ {
if (m_dolheader.textOffset[i] != 0) if (m_dolheader.textSize[i] != 0)
{ {
text_section[i] = new u8[m_dolheader.textSize[i]]; if (size < m_dolheader.textOffset[i] + m_dolheader.textSize[i])
memcpy(text_section[i], _pBuffer + m_dolheader.textOffset[i], m_dolheader.textSize[i]); return false;
for (unsigned int j = 0; j < (m_dolheader.textSize[i]/sizeof(u32)); j++)
u8* text_start = buffer + m_dolheader.textOffset[i];
m_text_sections.emplace_back(text_start, text_start + m_dolheader.textSize[i]);
for (unsigned int j = 0; !m_is_wii && j < (m_dolheader.textSize[i] / sizeof(u32)); ++j)
{ {
u32 word = Common::swap32(((u32*)text_section[i])[j]); u32 word = ((u32*)text_start)[j];
if ((word & HID4_mask) == HID4_pattern) if ((word & HID4_mask) == HID4_pattern)
m_is_wii = true;
}
}
else
{ {
m_isWii = true; // Make sure that m_text_sections indexes match header indexes
break; m_text_sections.emplace_back();
}
}
} }
} }
for (int i = 0; i < DOL_NUM_DATA; i++) m_data_sections.reserve(DOL_NUM_DATA);
for (int i = 0; i < DOL_NUM_DATA; ++i)
{ {
if (m_dolheader.dataOffset[i] != 0) if (m_dolheader.dataSize[i] != 0)
{ {
data_section[i] = new u8[m_dolheader.dataSize[i]]; if (size < m_dolheader.dataOffset[i] + m_dolheader.dataSize[i])
memcpy(data_section[i], _pBuffer + m_dolheader.dataOffset[i], m_dolheader.dataSize[i]); return false;
u8* data_start = buffer + m_dolheader.dataOffset[i];
m_data_sections.emplace_back(data_start, data_start + m_dolheader.dataSize[i]);
} }
else
{
// Make sure that m_data_sections indexes match header indexes
m_data_sections.emplace_back();
} }
} }
void CDolLoader::Load() return true;
}
void CDolLoader::Load() const
{ {
// load all text (code) sections // load all text (code) sections
for (int i = 0; i < DOL_NUM_TEXT; i++) for (size_t i = 0; i < m_text_sections.size(); ++i)
{ if (!m_text_sections[i].empty())
if (m_dolheader.textOffset[i] != 0) Memory::CopyToEmu(m_dolheader.textAddress[i], m_text_sections[i].data(), m_text_sections[i].size());
{
for (u32 num = 0; num < m_dolheader.textSize[i]; num++)
Memory::Write_U8(text_section[i][num], m_dolheader.textAddress[i] + num);
}
}
// load all data sections // load all data sections
for (int i = 0; i < DOL_NUM_DATA; i++) for (size_t i = 0; i < m_data_sections.size(); ++i)
{ if (!m_data_sections[i].empty())
if (m_dolheader.dataOffset[i] != 0) Memory::CopyToEmu(m_dolheader.dataAddress[i], m_data_sections[i].data(), m_data_sections[i].size());
{
for (u32 num = 0; num < m_dolheader.dataSize[i]; num++)
Memory::Write_U8(data_section[i][num], m_dolheader.dataAddress[i] + num);
}
}
} }

View File

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <vector>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
@ -12,14 +13,15 @@ class CDolLoader
{ {
public: public:
CDolLoader(const std::string& filename); CDolLoader(const std::string& filename);
CDolLoader(u8* _pBuffer, u32 _Size); CDolLoader(u8* buffer, size_t size);
~CDolLoader(); ~CDolLoader();
bool IsWii() const { return m_isWii; } bool IsValid() const { return m_is_valid; }
bool IsWii() const { return m_is_wii; }
u32 GetEntryPoint() const { return m_dolheader.entryPoint; } u32 GetEntryPoint() const { return m_dolheader.entryPoint; }
// Load into emulated memory // Load into emulated memory
void Load(); void Load() const;
private: private:
enum enum
@ -42,15 +44,15 @@ private:
u32 bssAddress; u32 bssAddress;
u32 bssSize; u32 bssSize;
u32 entryPoint; u32 entryPoint;
u32 padd[7];
}; };
SDolHeader m_dolheader; SDolHeader m_dolheader;
u8 *data_section[DOL_NUM_DATA]; std::vector<std::vector<u8>> m_data_sections;
u8 *text_section[DOL_NUM_TEXT]; std::vector<std::vector<u8>> m_text_sections;
bool m_isWii; bool m_is_valid;
bool m_is_wii;
// Copy sections to internal buffers // Copy sections to internal buffers
void Initialize(u8* _pBuffer, u32 _Size); bool Initialize(u8* buffer, size_t size);
}; };

View File

@ -106,6 +106,9 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
{ {
pDolLoader = std::make_unique<CDolLoader>(pContent->m_Filename); pDolLoader = std::make_unique<CDolLoader>(pContent->m_Filename);
} }
if (!pDolLoader->IsValid())
return false;
pDolLoader->Load(); pDolLoader->Load();
PC = pDolLoader->GetEntryPoint(); PC = pDolLoader->GetEntryPoint();

View File

@ -924,11 +924,21 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
{ {
pDolLoader = std::make_unique<CDolLoader>(pContent->m_Filename); pDolLoader = std::make_unique<CDolLoader>(pContent->m_Filename);
} }
if (pDolLoader->IsValid())
{
pDolLoader->Load(); // TODO: Check why sysmenu does not load the DOL correctly pDolLoader->Load(); // TODO: Check why sysmenu does not load the DOL correctly
PC = pDolLoader->GetEntryPoint(); PC = pDolLoader->GetEntryPoint();
IOSv = ContentLoader.GetIosVersion();
bSuccess = true; bSuccess = true;
} }
else
{
PanicAlertT("IOCTL_ES_LAUNCH: The DOL file is invalid!");
bSuccess = false;
}
IOSv = ContentLoader.GetIosVersion();
}
} }
} }
else // IOS, MIOS, BC etc else // IOS, MIOS, BC etc