mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-05 09:39:58 +00:00
Merge pull request #8668 from sepalani/rso-autodetect
RSO: Auto-detect RSO location in RAM
This commit is contained in:
commit
7390767008
@ -68,8 +68,8 @@ Accessors::iterator Accessors::end() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u32> Accessors::Search(u32 haystack_start, u8* needle_start, u32 needle_size,
|
std::optional<u32> Accessors::Search(u32 haystack_start, const u8* needle_start,
|
||||||
bool forwards) const
|
std::size_t needle_size, bool forwards) const
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ struct EffectiveAddressSpaceAccessors : Accessors
|
|||||||
void WriteU64(u32 address, u64 value) override { PowerPC::HostWrite_U64(value, address); }
|
void WriteU64(u32 address, u64 value) override { PowerPC::HostWrite_U64(value, address); }
|
||||||
float ReadF32(u32 address) const override { return PowerPC::HostRead_F32(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 page_base = haystack_start & 0xfffff000;
|
||||||
u32 offset = haystack_start & 0x0000fff;
|
u32 offset = haystack_start & 0x0000fff;
|
||||||
@ -121,7 +121,7 @@ struct EffectiveAddressSpaceAccessors : Accessors
|
|||||||
return false;
|
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)
|
if (memcmp(needle_start, page_ptr + offset, chunk_size) != 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -134,7 +134,7 @@ struct EffectiveAddressSpaceAccessors : Accessors
|
|||||||
return (needle_size == 0);
|
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
|
bool forward) const override
|
||||||
{
|
{
|
||||||
u32 haystack_address = haystack_start;
|
u32 haystack_address = haystack_start;
|
||||||
@ -190,7 +190,7 @@ struct AuxiliaryAddressSpaceAccessors : Accessors
|
|||||||
|
|
||||||
iterator end() const override { return DSP::GetARAMPtr() + GetSize(); }
|
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
|
bool forward) const override
|
||||||
{
|
{
|
||||||
if (!IsValidAddress(haystack_offset))
|
if (!IsValidAddress(haystack_offset))
|
||||||
@ -264,7 +264,7 @@ struct CompositeAddressSpaceAccessors : Accessors
|
|||||||
return it->accessors->WriteU8(address, value);
|
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
|
bool forward) const override
|
||||||
{
|
{
|
||||||
for (const AccessorMapping& mapping : m_accessor_mappings)
|
for (const AccessorMapping& mapping : m_accessor_mappings)
|
||||||
@ -320,10 +320,11 @@ struct SmallBlockAccessors : Accessors
|
|||||||
return (*alloc_base == nullptr) ? nullptr : (*alloc_base + size);
|
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
|
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;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,8 @@ struct Accessors
|
|||||||
virtual iterator begin() const;
|
virtual iterator begin() const;
|
||||||
virtual iterator end() const;
|
virtual iterator end() const;
|
||||||
|
|
||||||
virtual std::optional<u32> Search(u32 haystack_offset, u8* needle_start, u32 needle_size,
|
virtual std::optional<u32> Search(u32 haystack_offset, const u8* needle_start,
|
||||||
bool forward) const;
|
std::size_t needle_size, bool forward) const;
|
||||||
virtual ~Accessors();
|
virtual ~Accessors();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/Debugger/RSO.h"
|
#include "Core/Debugger/RSO.h"
|
||||||
#include "Core/HLE/HLE.h"
|
#include "Core/HLE/HLE.h"
|
||||||
|
#include "Core/HW/AddressSpace.h"
|
||||||
#include "Core/HW/WiiSave.h"
|
#include "Core/HW/WiiSave.h"
|
||||||
#include "Core/HW/Wiimote.h"
|
#include "Core/HW/Wiimote.h"
|
||||||
#include "Core/IOS/ES/ES.h"
|
#include "Core/IOS/ES/ES.h"
|
||||||
@ -1205,6 +1206,12 @@ void MenuBar::GenerateSymbolsFromSignatureDB()
|
|||||||
|
|
||||||
void MenuBar::GenerateSymbolsFromRSO()
|
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:"));
|
QString text = QInputDialog::getText(this, tr("Input"), tr("Enter the RSO module address:"));
|
||||||
bool good;
|
bool good;
|
||||||
uint address = text.toUInt(&good, 16);
|
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()
|
void MenuBar::LoadSymbolMap()
|
||||||
{
|
{
|
||||||
std::string existing_map_file, writable_map_file;
|
std::string existing_map_file, writable_map_file;
|
||||||
|
@ -153,6 +153,7 @@ private:
|
|||||||
void GenerateSymbolsFromAddress();
|
void GenerateSymbolsFromAddress();
|
||||||
void GenerateSymbolsFromSignatureDB();
|
void GenerateSymbolsFromSignatureDB();
|
||||||
void GenerateSymbolsFromRSO();
|
void GenerateSymbolsFromRSO();
|
||||||
|
void GenerateSymbolsFromRSOAuto();
|
||||||
void LoadSymbolMap();
|
void LoadSymbolMap();
|
||||||
void LoadOtherSymbolMap();
|
void LoadOtherSymbolMap();
|
||||||
void LoadBadSymbolMap();
|
void LoadBadSymbolMap();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user