Merge pull request #8668 from sepalani/rso-autodetect

RSO: Auto-detect RSO location in RAM
This commit is contained in:
Léo Lam 2020-04-28 14:27:13 +02:00 committed by GitHub
commit 7390767008
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 11 deletions

View File

@ -68,8 +68,8 @@ Accessors::iterator Accessors::end() const
return nullptr;
}
std::optional<u32> Accessors::Search(u32 haystack_start, u8* needle_start, u32 needle_size,
bool forwards) const
std::optional<u32> Accessors::Search(u32 haystack_start, const u8* needle_start,
std::size_t needle_size, bool forwards) const
{
return std::nullopt;
}
@ -91,7 +91,7 @@ struct EffectiveAddressSpaceAccessors : Accessors
void WriteU64(u32 address, u64 value) override { PowerPC::HostWrite_U64(value, address); }
float ReadF32(u32 address) const override { return PowerPC::HostRead_F32(address); };
bool Matches(u32 haystack_start, u8* needle_start, u32 needle_size) const
bool Matches(u32 haystack_start, const u8* needle_start, std::size_t needle_size) const
{
u32 page_base = haystack_start & 0xfffff000;
u32 offset = haystack_start & 0x0000fff;
@ -121,7 +121,7 @@ struct EffectiveAddressSpaceAccessors : Accessors
return false;
}
u32 chunk_size = std::min(0x1000 - offset, needle_size);
std::size_t chunk_size = std::min<std::size_t>(0x1000 - offset, needle_size);
if (memcmp(needle_start, page_ptr + offset, chunk_size) != 0)
{
return false;
@ -134,7 +134,7 @@ struct EffectiveAddressSpaceAccessors : Accessors
return (needle_size == 0);
}
std::optional<u32> Search(u32 haystack_start, u8* needle_start, u32 needle_size,
std::optional<u32> Search(u32 haystack_start, const u8* needle_start, std::size_t needle_size,
bool forward) const override
{
u32 haystack_address = haystack_start;
@ -190,7 +190,7 @@ struct AuxiliaryAddressSpaceAccessors : Accessors
iterator end() const override { return DSP::GetARAMPtr() + GetSize(); }
std::optional<u32> Search(u32 haystack_offset, u8* needle_start, u32 needle_size,
std::optional<u32> Search(u32 haystack_offset, const u8* needle_start, std::size_t needle_size,
bool forward) const override
{
if (!IsValidAddress(haystack_offset))
@ -264,7 +264,7 @@ struct CompositeAddressSpaceAccessors : Accessors
return it->accessors->WriteU8(address, value);
}
std::optional<u32> Search(u32 haystack_offset, u8* needle_start, u32 needle_size,
std::optional<u32> Search(u32 haystack_offset, const u8* needle_start, std::size_t needle_size,
bool forward) const override
{
for (const AccessorMapping& mapping : m_accessor_mappings)
@ -320,10 +320,11 @@ struct SmallBlockAccessors : Accessors
return (*alloc_base == nullptr) ? nullptr : (*alloc_base + size);
}
std::optional<u32> Search(u32 haystack_offset, u8* needle_start, u32 needle_size,
std::optional<u32> Search(u32 haystack_offset, const u8* needle_start, std::size_t needle_size,
bool forward) const override
{
if (!IsValidAddress(haystack_offset) || !IsValidAddress(haystack_offset + needle_size - 1))
if (!IsValidAddress(haystack_offset) ||
!IsValidAddress(haystack_offset + static_cast<u32>(needle_size) - 1))
{
return std::nullopt;
}

View File

@ -40,8 +40,8 @@ struct Accessors
virtual iterator begin() const;
virtual iterator end() const;
virtual std::optional<u32> Search(u32 haystack_offset, u8* needle_start, u32 needle_size,
bool forward) const;
virtual std::optional<u32> Search(u32 haystack_offset, const u8* needle_start,
std::size_t needle_size, bool forward) const;
virtual ~Accessors();
};

View File

@ -25,6 +25,7 @@
#include "Core/Core.h"
#include "Core/Debugger/RSO.h"
#include "Core/HLE/HLE.h"
#include "Core/HW/AddressSpace.h"
#include "Core/HW/WiiSave.h"
#include "Core/HW/Wiimote.h"
#include "Core/IOS/ES/ES.h"
@ -1205,6 +1206,12 @@ void MenuBar::GenerateSymbolsFromSignatureDB()
void MenuBar::GenerateSymbolsFromRSO()
{
// i18n: RSO refers to a proprietary format for shared objects (like DLL files).
const int ret =
ModalMessageBox::question(this, tr("RSO auto-detection"), tr("Auto-detect RSO modules?"));
if (ret == QMessageBox::Yes)
return GenerateSymbolsFromRSOAuto();
QString text = QInputDialog::getText(this, tr("Input"), tr("Enter the RSO module address:"));
bool good;
uint address = text.toUInt(&good, 16);
@ -1227,6 +1234,79 @@ void MenuBar::GenerateSymbolsFromRSO()
}
}
void MenuBar::GenerateSymbolsFromRSOAuto()
{
constexpr std::array<std::string_view, 2> search_for = {".elf", ".plf"};
const AddressSpace::Accessors* accessors =
AddressSpace::GetAccessors(AddressSpace::Type::Effective);
std::vector<std::pair<u32, std::string>> matches;
// Find filepath to elf/plf commonly used by RSO modules
for (const auto& str : search_for)
{
u32 next = 0;
while (true)
{
auto found_addr =
accessors->Search(next, reinterpret_cast<const u8*>(str.data()), str.size() + 1, true);
if (!found_addr.has_value())
break;
next = *found_addr + 1;
// Get the beginning of the string
found_addr = accessors->Search(*found_addr, reinterpret_cast<const u8*>(""), 1, false);
if (!found_addr.has_value())
continue;
// Get the string reference
const u32 ref_addr = *found_addr + 1;
const std::array<u8, 4> ref = {static_cast<u8>(ref_addr >> 24),
static_cast<u8>(ref_addr >> 16),
static_cast<u8>(ref_addr >> 8), static_cast<u8>(ref_addr)};
found_addr = accessors->Search(ref_addr, ref.data(), ref.size(), false);
if (!found_addr.has_value() || *found_addr < 16)
continue;
// Go to the beginning of the RSO header
matches.emplace_back(*found_addr - 16, PowerPC::HostGetString(ref_addr, 128));
}
}
QStringList items;
for (const auto& match : matches)
{
const QString item = QLatin1String("%1 %2");
items << item.arg(QString::number(match.first, 16), QString::fromStdString(match.second));
}
if (items.empty())
{
ModalMessageBox::warning(this, tr("Error"), tr("Unable to auto-detect RSO module"));
return;
}
bool ok;
const QString item = QInputDialog::getItem(
this, tr("Input"), tr("Select the RSO module address:"), items, 0, false, &ok);
if (!ok)
return;
RSOChainView rso_chain;
const u32 address = item.mid(0, item.indexOf(QLatin1Char(' '))).toUInt(nullptr, 16);
if (rso_chain.Load(address))
{
rso_chain.Apply(&g_symbolDB);
emit NotifySymbolsUpdated();
}
else
{
ModalMessageBox::warning(this, tr("Error"), tr("Failed to load RSO module at %1").arg(address));
}
}
void MenuBar::LoadSymbolMap()
{
std::string existing_map_file, writable_map_file;

View File

@ -153,6 +153,7 @@ private:
void GenerateSymbolsFromAddress();
void GenerateSymbolsFromSignatureDB();
void GenerateSymbolsFromRSO();
void GenerateSymbolsFromRSOAuto();
void LoadSymbolMap();
void LoadOtherSymbolMap();
void LoadBadSymbolMap();