JosJuice 7cecb28bdf DolphinQt: Properly lock CPU before accessing emulated memory
This fixes a problem I was having where using frame advance with the
debugger open would frequently cause panic alerts about invalid addresses
due to the CPU thread changing MSR.DR while the host thread was trying
to access memory.

To aid in tracking down all the places where we weren't properly locking
the CPU, I've created a new type (in Core.h) that you have to pass as a
reference or pointer to functions that require running as the CPU thread.
2023-02-12 11:27:50 +01:00

287 lines
6.8 KiB
C++

// Copyright 2017 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <cstddef>
#include <list>
#include <string>
#include <vector>
#include "Common/CommonTypes.h"
class PPCSymbolDB;
namespace Core
{
class CPUThreadGuard;
};
struct RSOEntry
{
u32 next_entry;
u32 prev_entry;
u32 section_count;
u32 section_table_offset;
u32 name_offset;
u32 name_size;
u32 version;
u32 bss_size;
};
struct RSOSectionInfo
{
u8 prolog_section_index;
u8 epilog_section_index;
u8 unresolved_section_index;
u8 bss_section_index;
u32 prolog_offset;
u32 epilog_offset;
u32 unresolved_offset;
};
struct RSORelocationTables
{
u32 internals_offset;
u32 internals_size;
u32 externals_offset;
u32 externals_size;
};
struct RSOSymbolTables
{
u32 exports_offset;
u32 exports_size;
u32 exports_name_table;
u32 imports_offset;
u32 imports_size;
u32 imports_name_table;
};
struct RSOHeader
{
RSOEntry entry;
RSOSectionInfo section_info;
RSORelocationTables relocation_tables;
RSOSymbolTables symbol_tables;
};
struct RSOSection
{
u32 offset;
u32 size;
};
struct RSOImport
{
u32 name_offset;
u32 code_offset;
u32 entry_offset;
};
struct RSOExport
{
u32 name_offset;
u32 code_offset;
u32 section_index;
u32 hash;
};
enum class RSORelocationTableType
{
Internals,
Externals
};
template <RSORelocationTableType Disambiguate>
struct RSORelocationTableEntry
{
u32 r_offset;
u32 r_info;
u32 r_addend;
};
using RSOInternalsEntry = RSORelocationTableEntry<RSORelocationTableType::Internals>;
using RSOExternalsEntry = RSORelocationTableEntry<RSORelocationTableType::Externals>;
class RSOHeaderView
{
public:
void Load(const Core::CPUThreadGuard& guard, u32 address);
u32 GetNextEntry() const;
u32 GetPrevEntry() const;
u32 GetSectionCount() const;
u32 GetSectionTableOffset() const;
const std::string& GetName() const;
u32 GetVersion() const;
u32 GetBssSectionSize() const;
u32 GetPrologSectionIndex() const;
u32 GetEpilogSectionIndex() const;
u32 GetUnresolvedSectionIndex() const;
u32 GetBssSectionIndex() const;
u32 GetPrologSectionOffset() const;
u32 GetEpilogSectionOffset() const;
u32 GetUnresolvedSectionOffset() const;
u32 GetInternalsOffset() const;
u32 GetInternalsSize() const;
u32 GetExternalsOffset() const;
u32 GetExternalsSize() const;
u32 GetExportsOffset() const;
u32 GetExportsSize() const;
u32 GetExportsNameTable() const;
u32 GetImportsOffset() const;
u32 GetImportsSize() const;
u32 GetImportsNameTable() const;
private:
RSOHeader m_header{};
std::string m_name;
u32 m_address = 0;
};
class RSOSectionsView
{
public:
void Load(const Core::CPUThreadGuard& guard, u32 address, std::size_t count = 1);
std::size_t Count() const;
const RSOSection& GetSection(std::size_t index) const;
const std::vector<RSOSection>& GetSections() const;
private:
std::vector<RSOSection> m_sections;
u32 m_address = 0;
};
class RSOImportsView
{
public:
void Load(const Core::CPUThreadGuard& guard, u32 address, std::size_t count = 1);
std::size_t Count() const;
const RSOImport& GetImport(std::size_t index) const;
const std::vector<RSOImport>& GetImports() const;
private:
std::vector<RSOImport> m_imports;
u32 m_address = 0;
};
class RSOExportsView
{
public:
void Load(const Core::CPUThreadGuard& guard, u32 address, std::size_t count = 1);
std::size_t Count() const;
const RSOExport& GetExport(std::size_t index) const;
const std::vector<RSOExport>& GetExports() const;
private:
std::vector<RSOExport> m_exports;
u32 m_address = 0;
};
class RSOInternalsView
{
public:
void Load(const Core::CPUThreadGuard& guard, u32 address, std::size_t count = 1);
std::size_t Count() const;
const RSOInternalsEntry& GetEntry(std::size_t index) const;
const std::vector<RSOInternalsEntry>& GetEntries() const;
private:
std::vector<RSOInternalsEntry> m_entries;
u32 m_address = 0;
};
class RSOExternalsView
{
public:
void Load(const Core::CPUThreadGuard& guard, u32 address, std::size_t count = 1);
std::size_t Count() const;
const RSOExternalsEntry& GetEntry(std::size_t index) const;
const std::vector<RSOExternalsEntry>& GetEntries() const;
private:
std::vector<RSOExternalsEntry> m_entries;
u32 m_address = 0;
};
class RSOView
{
public:
void LoadHeader(const Core::CPUThreadGuard& guard, u32 address);
void LoadSections(const Core::CPUThreadGuard& guard);
void LoadImports(const Core::CPUThreadGuard& guard);
void LoadExports(const Core::CPUThreadGuard& guard);
void LoadInternals(const Core::CPUThreadGuard& guard);
void LoadExternals(const Core::CPUThreadGuard& guard);
void LoadAll(const Core::CPUThreadGuard& guard, u32 address);
void Apply(const Core::CPUThreadGuard& guard, PPCSymbolDB* symbol_db) const;
u32 GetNextEntry() const;
u32 GetPrevEntry() const;
u32 GetVersion() const;
u32 GetAddress() const;
std::size_t GetSectionCount() const;
const RSOSection& GetSection(std::size_t index) const;
const std::vector<RSOSection>& GetSections() const;
std::size_t GetImportsCount() const;
const RSOImport& GetImport(std::size_t index) const;
std::string GetImportName(const Core::CPUThreadGuard& guard, const RSOImport& rso_import) const;
const std::vector<RSOImport>& GetImports() const;
std::size_t GetExportsCount() const;
const RSOExport& GetExport(std::size_t index) const;
std::string GetExportName(const Core::CPUThreadGuard& guard, const RSOExport& rso_export) const;
u32 GetExportAddress(const RSOExport& rso_export) const;
const std::vector<RSOExport>& GetExports() const;
std::size_t GetInternalsCount() const;
const RSOInternalsEntry& GetInternalsEntry(std::size_t index) const;
const std::vector<RSOInternalsEntry>& GetInternals() const;
std::size_t GetExternalsCount() const;
const RSOExternalsEntry& GetExternalsEntry(std::size_t index) const;
const std::vector<RSOExternalsEntry>& GetExternals() const;
const std::string& GetName() const;
std::string GetName(const Core::CPUThreadGuard& guard, const RSOImport& rso_import) const;
std::string GetName(const Core::CPUThreadGuard& guard, const RSOExport& rso_export) const;
u32 GetProlog() const;
u32 GetEpilog() const;
u32 GetUnresolved() const;
private:
RSOHeaderView m_header;
RSOSectionsView m_sections;
RSOImportsView m_imports;
RSOExportsView m_exports;
RSOInternalsView m_internals;
RSOExternalsView m_externals;
u32 m_address = 0;
};
class RSOChainView
{
public:
bool Load(const Core::CPUThreadGuard& guard, u32 address);
void Apply(const Core::CPUThreadGuard& guard, PPCSymbolDB* symbol_db) const;
void Clear();
const std::list<RSOView>& GetChain() const;
private:
bool LoadNextChain(const Core::CPUThreadGuard& guard, const RSOView& view);
bool LoadPrevChain(const Core::CPUThreadGuard& guard, const RSOView& view);
std::list<RSOView> m_chain;
};