mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 09:39:55 +00:00
PRX/savestates/VSH: Associate PRX with library, fix VSH browser (#13221)
* PRX/savestate:s Associate PRX with library * VFS/Savestates: Fix host_root resolving * Savestates: Fix segfault in ppu_initialize * SPU: Avoid some log spam * VSH/sys_vm: Fix limit on root processes
This commit is contained in:
parent
1852b370d7
commit
e6a7597444
@ -678,10 +678,10 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||
std::lock_guard lock(link->mutex);
|
||||
|
||||
usz unload_index = 0;
|
||||
ppu_prx_module_info lib{};
|
||||
|
||||
for (u32 addr = exports_start; addr < exports_end; unload_index++)
|
||||
for (u32 addr = exports_start; addr < exports_end; unload_index++, addr += lib.size ? lib.size : sizeof(ppu_prx_module_info))
|
||||
{
|
||||
ppu_prx_module_info lib{};
|
||||
std::memcpy(&lib, vm::base(addr), sizeof(lib));
|
||||
|
||||
const bool is_library = !!(lib.attributes & PRX_EXPORT_LIBRARY_FLAG);
|
||||
@ -712,20 +712,17 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||
result.emplace(nid, addr);
|
||||
}
|
||||
|
||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_library)
|
||||
{
|
||||
// Skipped if none of the flags is set
|
||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (for_observing_callbacks)
|
||||
{
|
||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -738,7 +735,6 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||
ppu_register_library_lock(module_name, false);
|
||||
}
|
||||
|
||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -759,7 +755,6 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||
if (!should_load)
|
||||
{
|
||||
ppu_loader.notice("** Skipped module '%s' (already loaded)", module_name);
|
||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -861,8 +856,6 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addr += lib.size ? lib.size : sizeof(ppu_prx_module_info);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -1516,10 +1509,20 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, const std::stri
|
||||
prx->module_info_version[0] = lib_info->version[0];
|
||||
prx->module_info_version[1] = lib_info->version[1];
|
||||
prx->module_info_attributes = lib_info->attributes;
|
||||
|
||||
|
||||
prx->exports_start = lib_info->exports_start;
|
||||
prx->exports_end = lib_info->exports_end;
|
||||
|
||||
for (usz start = prx->exports_start, size = 0;; size++, start += vm::read8(start) ? vm::read8(start) : sizeof(ppu_prx_module_info))
|
||||
{
|
||||
if (start >= prx->exports_end)
|
||||
{
|
||||
// Preallocate storage
|
||||
prx->m_external_loaded_flags.resize(size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ppu_loader.warning("Library %s (rtoc=0x%x):", lib_name, lib_info->toc);
|
||||
|
||||
prx->specials = ppu_load_exports(&link, prx->exports_start, prx->exports_end, true);
|
||||
|
@ -3208,6 +3208,11 @@ extern void ppu_initialize()
|
||||
|
||||
idm::select<lv2_obj, lv2_prx>([&](u32, lv2_prx& _module)
|
||||
{
|
||||
if (_module.funcs.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_module.path.starts_with(firmware_sprx_path))
|
||||
{
|
||||
// Postpone testing
|
||||
|
@ -1267,7 +1267,7 @@ std::string spu_thread::dump_misc() const
|
||||
|
||||
void spu_thread::cpu_on_stop()
|
||||
{
|
||||
if (current_func)
|
||||
if (current_func && is_stopped(state - cpu_flag::stop))
|
||||
{
|
||||
if (start_time)
|
||||
{
|
||||
@ -1496,7 +1496,7 @@ void spu_thread::cpu_task()
|
||||
unsavable = false;
|
||||
|
||||
// Print some stats
|
||||
spu_log.notice("Stats: Block Weight: %u (Retreats: %u);", block_counter, block_failure);
|
||||
(!group || group->stop_count < 5 ? spu_log.notice : spu_log.trace)("Stats: Block Weight: %u (Retreats: %u);", block_counter, block_failure);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -308,11 +308,12 @@ std::shared_ptr<void> lv2_prx::load(utils::serial& ar)
|
||||
|
||||
if (seg_count)
|
||||
{
|
||||
std::basic_string<bool> loaded_flags;
|
||||
std::basic_string<bool> loaded_flags, external_flags;
|
||||
|
||||
if (version >= 3)
|
||||
if (version >= 4)
|
||||
{
|
||||
ar(loaded_flags);
|
||||
ar(external_flags);
|
||||
}
|
||||
|
||||
fs::file file{path.substr(0, path.size() - (offset ? fmt::format("_x%x", offset).size() : 0))};
|
||||
@ -323,13 +324,14 @@ std::shared_ptr<void> lv2_prx::load(utils::serial& ar)
|
||||
file = make_file_view(std::move(file), offset);
|
||||
prx = ppu_load_prx(ppu_prx_object{ decrypt_self(std::move(file), reinterpret_cast<u8*>(&klic)) }, path, 0, &ar);
|
||||
prx->m_loaded_flags = std::move(loaded_flags);
|
||||
|
||||
if (version == 2 && state == PRX_STATE_STARTED)
|
||||
prx->m_external_loaded_flags = std::move(external_flags);
|
||||
|
||||
if (version == 2 && (state == PRX_STATE_STARTED || state == PRX_STATE_STARTING))
|
||||
{
|
||||
prx->load_exports();
|
||||
}
|
||||
|
||||
if (version == 3 && state == PRX_STATE_STARTED)
|
||||
if (version >= 4 && state <= PRX_STATE_STARTED)
|
||||
{
|
||||
prx->restore_exports();
|
||||
}
|
||||
@ -377,6 +379,7 @@ void lv2_prx::save(utils::serial& ar)
|
||||
if (!segs.empty())
|
||||
{
|
||||
ar(m_loaded_flags);
|
||||
ar(m_external_loaded_flags);
|
||||
}
|
||||
|
||||
for (const ppu_segment& seg : segs)
|
||||
@ -765,9 +768,9 @@ void lv2_prx::restore_exports()
|
||||
|
||||
std::basic_string<bool> loaded_flags_empty;
|
||||
|
||||
for (usz start = exports_start, i = 0; start < exports_end; i++, start += sizeof_export_data)
|
||||
for (usz start = exports_start, i = 0; start < exports_end; i++, start += vm::read8(start) ? vm::read8(start) : sizeof_export_data)
|
||||
{
|
||||
if (::at32(m_loaded_flags, i))
|
||||
if (::at32(m_external_loaded_flags, i) || (!m_loaded_flags.empty() && ::at32(m_loaded_flags, i)))
|
||||
{
|
||||
loaded_flags_empty.clear();
|
||||
ppu_manual_load_imports_exports(0, 0, start, sizeof_export_data, loaded_flags_empty);
|
||||
@ -783,7 +786,14 @@ void lv2_prx::unload_exports()
|
||||
return;
|
||||
}
|
||||
|
||||
ppu_manual_load_imports_exports(0, 0, exports_start, exports_end - exports_start, m_loaded_flags);
|
||||
std::basic_string<bool> merged = m_loaded_flags;
|
||||
|
||||
for (usz i = 0; i < merged.size(); i++)
|
||||
{
|
||||
merged[i] |= ::at32(m_external_loaded_flags, i);
|
||||
}
|
||||
|
||||
ppu_manual_load_imports_exports(0, 0, exports_start, exports_end - exports_start, merged);
|
||||
}
|
||||
|
||||
error_code _sys_prx_register_module(ppu_thread& ppu, vm::cptr<char> name, vm::ptr<void> opt)
|
||||
@ -864,7 +874,39 @@ error_code _sys_prx_register_library(ppu_thread& ppu, vm::ptr<void> library)
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
ppu_manual_load_imports_exports(0, 0, library.addr(), 0x1c, *std::make_unique<std::basic_string<bool>>());
|
||||
constexpr u32 sizeof_lib = 0x1c;
|
||||
|
||||
std::array<char, sizeof_lib> mem_copy{};
|
||||
std::memcpy(mem_copy.data(), library.get_ptr(), sizeof_lib);
|
||||
|
||||
std::basic_string<bool> flags;
|
||||
ppu_manual_load_imports_exports(0, 0, library.addr(), sizeof_lib, flags);
|
||||
|
||||
if (flags.front())
|
||||
{
|
||||
const bool success = idm::select<lv2_obj, lv2_prx>([&](u32 id, lv2_prx& prx)
|
||||
{
|
||||
if (prx.state == PRX_STATE_INITIALIZED)
|
||||
{
|
||||
for (u32 lib_addr = prx.exports_start, index = 0; lib_addr < prx.exports_end; index++, lib_addr += vm::read8(lib_addr) ? vm::read8(lib_addr) : sizeof_lib)
|
||||
{
|
||||
if (std::memcpy(vm::base(lib_addr), mem_copy.data(), sizeof_lib) == 0)
|
||||
{
|
||||
atomic_storage<bool>::release(prx.m_external_loaded_flags[index], true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}).ret;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
sys_prx.error("_sys_prx_register_library(): Failed to associate library to PRX!");
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ struct sys_prx_module_info_t
|
||||
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
|
||||
vm::bptr<sys_prx_segment_info_t> segments; // 0x40
|
||||
be_t<u32> segments_num; // 0x44
|
||||
};
|
||||
|
||||
@ -196,6 +196,7 @@ struct lv2_prx final : lv2_obj, ppu_module
|
||||
u32 exports_end = 0;
|
||||
|
||||
std::basic_string<bool> m_loaded_flags;
|
||||
std::basic_string<bool> m_external_loaded_flags;
|
||||
|
||||
void load_exports(); // (Re)load exports
|
||||
void restore_exports(); // For savestates
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "sys_vm.h"
|
||||
#include "sys_process.h"
|
||||
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
@ -70,7 +71,8 @@ error_code sys_vm_memory_map(ppu_thread& ppu, u32 vsize, u32 psize, u32 cid, u64
|
||||
if (!g_fxo->get<sys_vm_global_t>().total_vsize.fetch_op([vsize](u32& size)
|
||||
{
|
||||
// A single process can hold up to 256MB of virtual memory, even on DECR
|
||||
if (0x10000000 - size < vsize)
|
||||
// VSH can hold more
|
||||
if ((g_ps3_process_info.has_root_perm() ? 0x1E000000 : 0x10000000) - size < vsize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1077,10 +1077,10 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||
m_path = disc;
|
||||
m_path += std::string_view(argv[0]).substr(9);
|
||||
}
|
||||
else if (argv[0].starts_with("/host_root"sv))
|
||||
else if (argv[0].starts_with("/host_root/"sv))
|
||||
{
|
||||
sys_log.error("Host root has been used in path redirection!");
|
||||
m_path = argv[0].substr(9);
|
||||
m_path = argv[0].substr(11);
|
||||
}
|
||||
else if (argv[0].starts_with("/dev_hdd1"sv))
|
||||
{
|
||||
|
@ -75,6 +75,10 @@ bool vfs::mount(std::string_view vpath, std::string_view path, bool is_dir)
|
||||
list.back()->path += '/';
|
||||
if (!is_dir && list.back()->path.ends_with('/'))
|
||||
vfs_log.error("File mounted with trailing /.");
|
||||
|
||||
if (path == "/") // Special
|
||||
list.back()->path = "/";
|
||||
|
||||
vfs_log.notice("Mounted path \"%s\" to \"%s\"", vpath_backup, list.back()->path);
|
||||
return true;
|
||||
}
|
||||
@ -376,21 +380,19 @@ std::string vfs::retrieve(std::string_view path, const vfs_directory* node, std:
|
||||
|
||||
std::vector<std::string_view> mount_path_empty;
|
||||
|
||||
if (std::string res = vfs::retrieve(path, &table.root, &mount_path_empty); !res.empty())
|
||||
const std::string rpath = Emu.GetCallbacks().resolve_path(path);
|
||||
|
||||
if (!rpath.empty())
|
||||
{
|
||||
return res;
|
||||
if (std::string res = vfs::retrieve(rpath, &table.root, &mount_path_empty); !res.empty())
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
mount_path_empty.clear();
|
||||
|
||||
const std::string rpath = Emu.GetCallbacks().resolve_path(path);
|
||||
|
||||
if (rpath.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return vfs::retrieve(rpath, &table.root, &mount_path_empty);
|
||||
return vfs::retrieve(path, &table.root, &mount_path_empty);
|
||||
}
|
||||
|
||||
mount_path->emplace_back();
|
||||
|
@ -42,7 +42,7 @@ SERIALIZATION_VER(lv2_sync, 3, 1)
|
||||
SERIALIZATION_VER(lv2_vm, 4, 1)
|
||||
SERIALIZATION_VER(lv2_net, 5, 1, 2/*RECV/SEND timeout*/)
|
||||
SERIALIZATION_VER(lv2_fs, 6, 1)
|
||||
SERIALIZATION_VER(lv2_prx_overlay, 7, 1, 2/*PRX dynamic exports*/, 3/*Conditionally Loaded Local Exports*/)
|
||||
SERIALIZATION_VER(lv2_prx_overlay, 7, 1, 2/*PRX dynamic exports*/, 4/*Conditionally Loaded Local Exports*/)
|
||||
SERIALIZATION_VER(lv2_memory, 8, 1)
|
||||
SERIALIZATION_VER(lv2_config, 9, 1)
|
||||
|
||||
|
@ -72,7 +72,7 @@ Localized::sound::sound()
|
||||
|
||||
Localized::title_t::title_t()
|
||||
: titles({
|
||||
{ "vsh/module/vsh.self", tr("XMB (VSH)") },
|
||||
{ "vsh/module/vsh.self", tr("The PS3 Interface (XMB, or VSH)") },
|
||||
})
|
||||
{
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user