feat(libkernel): implement sceKernelInternalMemoryGetModuleSegmentInfo
This commit is contained in:
parent
43e3a70f81
commit
ea03a22c7f
|
|
@ -280,6 +280,12 @@ struct ModuleInfoForUnwind {
|
|||
std::uint64_t seg0_size;
|
||||
};
|
||||
|
||||
struct InternalSegmentInfo {
|
||||
std::uint64_t address;
|
||||
std::uint64_t size;
|
||||
};
|
||||
static_assert(sizeof(InternalSegmentInfo) == 0x10);
|
||||
|
||||
struct MallocReplace {
|
||||
std::uint64_t size = sizeof(MallocReplace);
|
||||
void* malloc_initialize = nullptr;
|
||||
|
|
|
|||
|
|
@ -241,11 +241,4 @@ int APS5_VABI __elf_phdr_match_addr_nid_postfix(dl_phdr_info* phdrInfo, void* ad
|
|||
return 0;
|
||||
}
|
||||
|
||||
// unknown signature
|
||||
std::int32_t APS5_VABI sceKernelInternalMemoryGetModuleSegmentInfo_nid_postfix(void* result) {
|
||||
(void)result;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -447,6 +447,16 @@ std::int32_t APS5_VABI sceKernelGetLibkernelTextLocation_nid_postfix(void** addr
|
|||
return 0;
|
||||
}
|
||||
|
||||
std::int32_t APS5_VABI sceKernelInternalMemoryGetModuleSegmentInfo_nid_postfix(InternalSegmentInfo* result) {
|
||||
if (!result) throw std::invalid_argument("sceKernelInternalMemoryGetModuleSegmentInfo: result is null");
|
||||
void* address = nullptr;
|
||||
std::size_t size = 0;
|
||||
const auto status = sceKernelGetLibkernelTextLocation_nid_postfix(&address, &size);
|
||||
if (status != 0) return status;
|
||||
*result = {reinterpret_cast<std::uintptr_t>(address), size};
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::uint64_t GuestImageSegmentBytes_nid_no_patch() {
|
||||
return GuestSegmentBytes();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ int APS5_VABI sceKernelGetModuleInfo(KernelModule, ModuleInfo*);
|
|||
int APS5_VABI sceKernelGetModuleList2(KernelModule*, std::size_t, std::size_t*);
|
||||
int APS5_VABI sceKernelGetModuleInfo2(KernelModule, ModuleInfo*);
|
||||
std::int32_t APS5_VABI sceKernelGetLibkernelTextLocation_nid_postfix(void**, std::size_t*);
|
||||
std::int32_t APS5_VABI sceKernelInternalMemoryGetModuleSegmentInfo_nid_postfix(InternalSegmentInfo*);
|
||||
}
|
||||
static void Require(bool value) { if (!value) std::abort(); }
|
||||
template<typename TFunction>
|
||||
|
|
@ -107,6 +108,10 @@ int main(int argc, char** argv) {
|
|||
Require(textSize == program.segments[0].size);
|
||||
Require(ThrowsInvalidArgument([&] { sceKernelGetLibkernelTextLocation_nid_postfix(nullptr, &textSize); }));
|
||||
Require(ThrowsInvalidArgument([&] { sceKernelGetLibkernelTextLocation_nid_postfix(&textAddress, nullptr); }));
|
||||
InternalSegmentInfo segment{};
|
||||
Require(sceKernelInternalMemoryGetModuleSegmentInfo_nid_postfix(&segment) == 0);
|
||||
Require(segment.address == program.segments[0].address && segment.size == program.segments[0].size);
|
||||
Require(ThrowsInvalidArgument([] { sceKernelInternalMemoryGetModuleSegmentInfo_nid_postfix(nullptr); }));
|
||||
for (const std::uint64_t size : {0x158, 0x1a8, 0x1b0, 0x200, 0}) {
|
||||
ModuleInfo sized{};
|
||||
sized.st_size = size;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
- [AMM PRT ranges](../../../core/libs/prx/libkernel/Apr/src/Apr.cpp) (libSceAmpr) - signatures, checks and their order taken from ampr_emu, where `MapAsPrt` is a map with the PRT flag and protection 0 and `AllocatePaForPrt` a memory type and protection change with mask 1019, both checking the buffer memory after its size; the effects are inferred from the names, not confirmed on a title. Unbacked PRT pages are zero-filled pages with GPU read access, so CPU reads see zeros instead of faulting and GPU writes fault instead of being dropped. `AllocatePaForPrt` backs each unbacked page with a pool page and sets the type and protection of backed ones; `RemapIntoPrt` moves a fully mapped range into a PRT range, its opcode argument (1011 when 0, as in ampr_emu) is recorded and ignored; `UnmapToPrt` returns the pages to the pool and zero-fills them again. A plain map, unmap or remap over a PRT range ends it; `AllocatePaForPrt`, `RemapIntoPrt` or `UnmapToPrt` outside a PRT range throws
|
||||
- [AMM kernel write commands](../../../core/libs/prx/libkernel/Apr/src/Apr.cpp) (libkernel) - signatures of `sceKernelWriteModifyMtypeProtectCommand` and `sceKernelWriteRemapIntoPrtCommand` taken from [ampr_emu's libkernel hook targets](https://github.com/drakmor/ampr_emu/blob/cfa85df379f6eeeb165d7badf9b648e266fe77b7/include/ampr_libkernel_hook_targets.h), which forward to the real kernel; the measure mode (`dst` null reports the size, `outSize` null skips the report) follows ampr_emu's measure-then-record calls, not confirmed on a title. The range, protection and mask checks mirror the `libSceAmpr` siblings, and the recorded bytes match them exactly so the submitted buffer executes on the existing paths
|
||||
- [sceCoredumpWriteUserString](../../../core/libs/prx/libkernel/System/src/Coredump.cpp) and [sceSaveDataGetConvertProgress](../../../core/libs/prx/libSceSaveData.native/Export.cpp) - imported by PPSA16064, not called during its start-up and added without an implementation; unknown signatures
|
||||
- [sceKernelInternalMemoryGetModuleSegmentInfo](../../../core/libs/prx/libkernel/Module/src/Module.cpp) (libkernel) - unknown signature
|
||||
- [sceKernelInternalMemoryGetModuleSegmentInfo](../../../core/libs/prx/libkernel/Module/src/ModuleInfo.cpp) (libkernel) - the `(InternalSegmentInfo* result)` signature, the 16-byte `{address, size}` result and the choice of the main program's first segment follow [fpPS4](https://github.com/red-prig/fpPS4/blob/04cefd43e6fddd1ab033e7980cd356d14c964905/kernel/ps4_libkernel.pas#L343-L355) only, which fills it through its `sceKernelGetLibkernelTextLocation` from the first segment of `eboot.bin`; whether the console reports that segment, the text of libkernel itself or the calling module's is unknown. The segment is the first one `sceKernelGetModuleInfo` reports for the main program, and 0 is returned. A null result throws. 44 audited titles that bundle their own `libc.prx` import it; no call has been observed
|
||||
- [sceKernelGetModuleInfoForUnwind](../../../core/libs/prx/libkernel/Module/src/Module.cpp) (libkernel) - on Linux the tables come from `sceKernelGetModuleInfoFromAddr`, whose `eh_frame_size` includes the zero terminator, as measured on firmware 13.60 (reported in [#2419](https://github.com/boykopovar/AnyPS5/issues/2419), not reproduced here); on Windows it is assumed to stop before the terminator. LLVM libunwind's `CFI_Parser::findFDE` stops at the terminator or the length, whichever comes first, so it finds the same FDEs either way. Only the main executable and `.guest.prx` images report tables; other host images report none, as on Windows
|
||||
- [sceKernelGetModuleInfoFromAddr](../../../core/libs/prx/libkernel/Module/src/ModuleInfo.cpp) (libkernel) - the 0x1A8-byte info layout follows the [shadPS4](https://github.com/shadps4-emu/shadPS4) reimplementation; a title's `libc.prx` reads only `id` (PPSA14632). The meaning of `flags` is unknown; only 2 is accepted. The input `st_size` is ignored, because PPSA21703's `libc.prx` passes an uninitialized 0x1A8-byte buffer; the full size is written back. The id is the `sceKernelLoadStartModule` handle of an image opened through the loader and otherwise a stable id from the same range. The name is the host file name without `.guest.prx`. An image with more than 4 load segments (the converted executable has 7) reports its first 4. `tls_offset` is 0 and `ref_count` is 1, as the host loader exposes neither. On Windows the module is the PE image holding the address: a relinked image reports its `.elf` sections as segments and the eh_frame_hdr recorded in `.ehmeta`, any other image its first 4 sections with memory access and the `.ehfram` section without an eh_frame_hdr; the TLS fields and `init_proc_addr`/`fini_proc_addr` are 0
|
||||
- [sceKernelGetModuleList](../../../core/libs/prx/libkernel/Module/src/ModuleInfo.cpp) (libkernel) - lists the main program and every loaded `.prx` image in load order; host runtime libraries are left out. The handles are the ids `sceKernelGetModuleInfoFromAddr` reports, not the console's. The `(int32_t* handles, size_t count, size_t* actual)` signature and returning `ENOMEM` without writing `actual` after filling the first `count` handles when more images are loaded follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/0fe263a4760dfbfa973366890061749b4af0de97/src/core/libraries/kernel/process.cpp#L244-L264); whether the console writes any handles in that case is unknown
|
||||
|
|
|
|||
Loading…
Reference in New Issue