mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-06 00:30:18 +01:00
Replaces `std::shared_pointer` with `stx::atomic_ptr` and `stx::shared_ptr`. Notes to programmers: * This pr kills the use of `dynamic_cast`, `std::dynamic_pointer_cast` and `std::weak_ptr` on IDM objects, possible replacement is to save the object ID on the base object, then use idm::check/get_unlocked to the destination type via the saved ID which may be null. Null pointer check is how you can tell type mismatch (as dynamic cast) or object destruction (as weak_ptr locking). * Double-inheritance on IDM objects should be used with care, `stx::shared_ptr` does not support constant-evaluated pointer offsetting to parent/child type. * `idm::check/get_unlocked` can now be used anywhere. Misc fixes: * Fixes some segfaults with RPCN with interaction with IDM. * Fix deadlocks in access violation handler due locking recursion. * Fixes race condition in process exit-spawn on memory containers read. * Fix bug that theoretically can prevent RPCS3 from booting - fix `id_manager::typeinfo` comparison to compare members instead of `memcmp` which can fail spuriously on padding bytes. * Ensure all IDM inherited types of base, either has `id_base` or `id_type` defined locally, this allows to make getters such as `idm::get_unlocked<lv2_socket, lv2_socket_raw>()` which were broken before. (requires save-states invalidation) * Removes broken operator[] overload of `stx::shared_ptr` and `stx::single_ptr` for non-array types.
258 lines
8.9 KiB
C++
258 lines
8.9 KiB
C++
#pragma once
|
|
|
|
#include "sys_sync.h"
|
|
|
|
#include "Emu/Cell/PPUAnalyser.h"
|
|
#include "Emu/Cell/ErrorCodes.h"
|
|
#include "Emu/Memory/vm_ptr.h"
|
|
|
|
// Return codes
|
|
enum CellPrxError : u32
|
|
{
|
|
CELL_PRX_ERROR_ERROR = 0x80011001, // Error state
|
|
CELL_PRX_ERROR_ILLEGAL_PERM = 0x800110d1, // No permission to execute API
|
|
CELL_PRX_ERROR_UNKNOWN_MODULE = 0x8001112e, // Specified PRX could not be found
|
|
CELL_PRX_ERROR_ALREADY_STARTED = 0x80011133, // Specified PRX is already started
|
|
CELL_PRX_ERROR_NOT_STARTED = 0x80011134, // Specified PRX is not started
|
|
CELL_PRX_ERROR_ALREADY_STOPPED = 0x80011135, // Specified PRX is already stopped
|
|
CELL_PRX_ERROR_CAN_NOT_STOP = 0x80011136, // Specified PRX must not be stopped
|
|
CELL_PRX_ERROR_NOT_REMOVABLE = 0x80011138, // Specified PRX must not be deleted
|
|
CELL_PRX_ERROR_LIBRARY_NOT_YET_LINKED = 0x8001113a, // Called unlinked function
|
|
CELL_PRX_ERROR_LIBRARY_FOUND = 0x8001113b, // Specified library is already registered
|
|
CELL_PRX_ERROR_LIBRARY_NOTFOUND = 0x8001113c, // Specified library is not registered
|
|
CELL_PRX_ERROR_ILLEGAL_LIBRARY = 0x8001113d, // Library structure is invalid
|
|
CELL_PRX_ERROR_LIBRARY_INUSE = 0x8001113e, // Library cannot be deleted because it is linked
|
|
CELL_PRX_ERROR_ALREADY_STOPPING = 0x8001113f, // Specified PRX is in the process of stopping
|
|
CELL_PRX_ERROR_UNSUPPORTED_PRX_TYPE = 0x80011148, // Specified PRX format is invalid and cannot be loaded
|
|
CELL_PRX_ERROR_INVAL = 0x80011324, // Argument value is invalid
|
|
CELL_PRX_ERROR_ILLEGAL_PROCESS = 0x80011801, // Specified process does not exist
|
|
CELL_PRX_ERROR_NO_LIBLV2 = 0x80011881, // liblv2.sprx does not exist
|
|
CELL_PRX_ERROR_UNSUPPORTED_ELF_TYPE = 0x80011901, // ELF type of specified file is not supported
|
|
CELL_PRX_ERROR_UNSUPPORTED_ELF_CLASS = 0x80011902, // ELF class of specified file is not supported
|
|
CELL_PRX_ERROR_UNDEFINED_SYMBOL = 0x80011904, // References undefined symbols
|
|
CELL_PRX_ERROR_UNSUPPORTED_RELOCATION_TYPE = 0x80011905, // Uses unsupported relocation type
|
|
CELL_PRX_ERROR_ELF_IS_REGISTERED = 0x80011910, // Fixed ELF is already registered
|
|
CELL_PRX_ERROR_NO_EXIT_ENTRY = 0x80011911,
|
|
};
|
|
|
|
enum
|
|
{
|
|
SYS_PRX_MODULE_FILENAME_SIZE = 512
|
|
};
|
|
|
|
struct sys_prx_get_module_id_by_name_option_t
|
|
{
|
|
be_t<u64> size;
|
|
vm::ptr<void> base;
|
|
};
|
|
|
|
struct sys_prx_load_module_option_t
|
|
{
|
|
be_t<u64> size;
|
|
vm::bptr<void> base_addr;
|
|
};
|
|
|
|
struct sys_prx_segment_info_t
|
|
{
|
|
be_t<u64> base;
|
|
be_t<u64> filesz;
|
|
be_t<u64> memsz;
|
|
be_t<u64> index;
|
|
be_t<u64> type;
|
|
};
|
|
|
|
struct sys_prx_module_info_t
|
|
{
|
|
be_t<u64> size; // 0
|
|
char name[30]; // 8
|
|
char version[2]; // 0x26
|
|
be_t<u32> modattribute; // 0x28
|
|
be_t<u32> start_entry; // 0x2c
|
|
be_t<u32> stop_entry; // 0x30
|
|
be_t<u32> all_segments_num; // 0x34
|
|
vm::bptr<char> filename; // 0x38
|
|
be_t<u32> filename_size; // 0x3c
|
|
vm::bptr<sys_prx_segment_info_t> segments; // 0x40
|
|
be_t<u32> segments_num; // 0x44
|
|
};
|
|
|
|
struct sys_prx_module_info_option_t
|
|
{
|
|
be_t<u64> size; // 0x10
|
|
vm::bptr<sys_prx_module_info_t> info;
|
|
};
|
|
|
|
struct sys_prx_start_module_option_t
|
|
{
|
|
be_t<u64> size;
|
|
};
|
|
|
|
struct sys_prx_stop_module_option_t
|
|
{
|
|
be_t<u64> size;
|
|
};
|
|
|
|
struct sys_prx_start_stop_module_option_t
|
|
{
|
|
be_t<u64> size;
|
|
be_t<u64> cmd;
|
|
vm::bptr<s32(u32 argc, vm::ptr<void> argv), u64> entry;
|
|
be_t<u64> res;
|
|
vm::bptr<s32(vm::ptr<s32(u32, vm::ptr<void>), u64>, u32 argc, vm::ptr<void> argv), u64> entry2;
|
|
};
|
|
|
|
struct sys_prx_unload_module_option_t
|
|
{
|
|
be_t<u64> size;
|
|
};
|
|
|
|
struct sys_prx_get_module_list_t
|
|
{
|
|
be_t<u64> size;
|
|
be_t<u32> max;
|
|
be_t<u32> count;
|
|
vm::bptr<u32> idlist;
|
|
};
|
|
|
|
struct sys_prx_get_module_list_option_t
|
|
{
|
|
be_t<u64> size; // 0x20
|
|
be_t<u32> pad;
|
|
be_t<u32> max;
|
|
be_t<u32> count;
|
|
vm::bptr<u32> idlist;
|
|
be_t<u32> unk; // 0
|
|
};
|
|
|
|
struct sys_prx_register_module_0x20_t
|
|
{
|
|
be_t<u64> size; // 0x0
|
|
be_t<u32> toc; // 0x8
|
|
be_t<u32> toc_size; // 0xC
|
|
vm::bptr<void> stubs_ea; // 0x10
|
|
be_t<u32> stubs_size; // 0x14
|
|
vm::bptr<void> error_handler; // 0x18
|
|
char pad[4]; // 0x1C
|
|
};
|
|
|
|
struct sys_prx_register_module_0x30_type_1_t
|
|
{
|
|
be_t<u64> size; // 0x0
|
|
be_t<u64> type; // 0x8
|
|
be_t<u32> unk3; // 0x10
|
|
be_t<u32> unk4; // 0x14
|
|
vm::bptr<void> lib_entries_ea; // 0x18
|
|
be_t<u32> lib_entries_size; // 0x1C
|
|
vm::bptr<void> lib_stub_ea; // 0x20
|
|
be_t<u32> lib_stub_size; // 0x24
|
|
vm::bptr<void> error_handler; // 0x28
|
|
char pad[4]; // 0x2C
|
|
};
|
|
|
|
enum : u32
|
|
{
|
|
SYS_PRX_RESIDENT = 0,
|
|
SYS_PRX_NO_RESIDENT = 1,
|
|
|
|
SYS_PRX_START_OK = 0,
|
|
|
|
SYS_PRX_STOP_SUCCESS = 0,
|
|
SYS_PRX_STOP_OK = 0,
|
|
SYS_PRX_STOP_FAILED = 1
|
|
};
|
|
|
|
// Unofficial names for PRX state
|
|
enum : u32
|
|
{
|
|
PRX_STATE_INITIALIZED,
|
|
PRX_STATE_STARTING, // In-between state between initialized and started (internal)
|
|
PRX_STATE_STARTED,
|
|
PRX_STATE_STOPPING, // In-between state between started and stopped (internal)
|
|
PRX_STATE_STOPPED, // Last state, the module cannot be restarted
|
|
PRX_STATE_DESTROYED, // Last state, the module cannot be restarted
|
|
};
|
|
|
|
struct lv2_prx final : ppu_module<lv2_obj>
|
|
{
|
|
static const u32 id_base = 0x23000000;
|
|
|
|
atomic_t<u32> state = PRX_STATE_INITIALIZED;
|
|
shared_mutex mutex;
|
|
|
|
std::unordered_map<u32, u32> specials;
|
|
std::unordered_map<u32, void*> imports;
|
|
|
|
vm::ptr<s32(u32 argc, vm::ptr<void> argv)> start = vm::null;
|
|
vm::ptr<s32(u32 argc, vm::ptr<void> argv)> stop = vm::null;
|
|
vm::ptr<s32(u64 callback, u64 argc, vm::ptr<void, u64> argv)> prologue = vm::null;
|
|
vm::ptr<s32(u64 callback, u64 argc, vm::ptr<void, u64> argv)> epilogue = vm::null;
|
|
vm::ptr<s32()> exit = vm::null;
|
|
|
|
char module_info_name[28]{};
|
|
u8 module_info_version[2]{};
|
|
be_t<u16> module_info_attributes{};
|
|
|
|
u32 exports_start = umax;
|
|
u32 exports_end = 0;
|
|
|
|
std::basic_string<char> m_loaded_flags;
|
|
std::basic_string<char> m_external_loaded_flags;
|
|
|
|
void load_exports(); // (Re)load exports
|
|
void restore_exports(); // For savestates
|
|
void unload_exports();
|
|
|
|
lv2_prx() noexcept = default;
|
|
lv2_prx(utils::serial&) {}
|
|
static std::function<void(void*)> load(utils::serial&);
|
|
void save(utils::serial& ar);
|
|
};
|
|
|
|
enum : u64
|
|
{
|
|
SYS_PRX_LOAD_MODULE_FLAGS_FIXEDADDR = 0x1ull,
|
|
SYS_PRX_LOAD_MODULE_FLAGS_INVALIDMASK = ~SYS_PRX_LOAD_MODULE_FLAGS_FIXEDADDR,
|
|
};
|
|
|
|
// PPC
|
|
enum
|
|
{
|
|
SYS_PRX_R_PPC_ADDR32 = 1,
|
|
SYS_PRX_R_PPC_ADDR16_LO = 4,
|
|
SYS_PRX_R_PPC_ADDR16_HI = 5,
|
|
SYS_PRX_R_PPC_ADDR16_HA = 6,
|
|
|
|
SYS_PRX_R_PPC64_ADDR32 = SYS_PRX_R_PPC_ADDR32,
|
|
SYS_PRX_R_PPC64_ADDR16_LO = SYS_PRX_R_PPC_ADDR16_LO,
|
|
SYS_PRX_R_PPC64_ADDR16_HI = SYS_PRX_R_PPC_ADDR16_HI,
|
|
SYS_PRX_R_PPC64_ADDR16_HA = SYS_PRX_R_PPC_ADDR16_HA,
|
|
SYS_PRX_R_PPC64_ADDR64 = 38,
|
|
SYS_PRX_VARLINK_TERMINATE32 = 0x00000000
|
|
};
|
|
|
|
// SysCalls
|
|
|
|
error_code sys_prx_get_ppu_guid(ppu_thread& ppu);
|
|
error_code _sys_prx_load_module_by_fd(ppu_thread& ppu, s32 fd, u64 offset, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt);
|
|
error_code _sys_prx_load_module_on_memcontainer_by_fd(ppu_thread& ppu, s32 fd, u64 offset, u32 mem_ct, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt);
|
|
error_code _sys_prx_load_module_list(ppu_thread& ppu, s32 count, vm::cpptr<char, u32, u64> path_list, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt, vm::ptr<u32> id_list);
|
|
error_code _sys_prx_load_module_list_on_memcontainer(ppu_thread& ppu, s32 count, vm::cpptr<char, u32, u64> path_list, u32 mem_ct, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt, vm::ptr<u32> id_list);
|
|
error_code _sys_prx_load_module_on_memcontainer(ppu_thread& ppu, vm::cptr<char> path, u32 mem_ct, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt);
|
|
error_code _sys_prx_load_module(ppu_thread& ppu, vm::cptr<char> path, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt);
|
|
error_code _sys_prx_start_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys_prx_start_stop_module_option_t> pOpt);
|
|
error_code _sys_prx_stop_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys_prx_start_stop_module_option_t> pOpt);
|
|
error_code _sys_prx_unload_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys_prx_unload_module_option_t> pOpt);
|
|
error_code _sys_prx_register_module(ppu_thread& ppu, vm::cptr<char> name, vm::ptr<void> opt);
|
|
error_code _sys_prx_query_module(ppu_thread& ppu);
|
|
error_code _sys_prx_register_library(ppu_thread& ppu, vm::ptr<void> library);
|
|
error_code _sys_prx_unregister_library(ppu_thread& ppu, vm::ptr<void> library);
|
|
error_code _sys_prx_link_library(ppu_thread& ppu);
|
|
error_code _sys_prx_unlink_library(ppu_thread& ppu);
|
|
error_code _sys_prx_query_library(ppu_thread& ppu);
|
|
error_code _sys_prx_get_module_list(ppu_thread& ppu, u64 flags, vm::ptr<sys_prx_get_module_list_option_t> pInfo);
|
|
error_code _sys_prx_get_module_info(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys_prx_module_info_option_t> pOpt);
|
|
error_code _sys_prx_get_module_id_by_name(ppu_thread& ppu, vm::cptr<char> name, u64 flags, vm::ptr<sys_prx_get_module_id_by_name_option_t> pOpt);
|
|
error_code _sys_prx_get_module_id_by_address(ppu_thread& ppu, u32 addr);
|
|
error_code _sys_prx_start(ppu_thread& ppu);
|
|
error_code _sys_prx_stop(ppu_thread& ppu);
|