IOS LLE: IPC trace prints filesystem IOCTL paths (StarletOS phase 11 M1e)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Yaya48andClaude Opus 5.5 committed 2026-10-06 19:44:05 +02:00
1 parent 3ce435786c
commit 81ebec368b
3 files changed
+69 -6

No files matched your search

+47 -4
View File
@@ -3,6 +3,7 @@
#include "Core/HW/WII_IPC.h" #include "Core/HW/WII_IPC.h"
#include <algorithm>
#include <cstdlib> #include <cstdlib>
#include <string> #include <string>
@@ -148,10 +149,11 @@ void WiiIPC::Shutdown()
namespace namespace
{ {
// StarletOS phase 11 (proposal L2): with DOLPHIN_IPC_TRACE=1 while the original IOS runs on the // StarletOS phase 11 (proposal L2): with DOLPHIN_IPC_TRACE=1 while the emulated Starlet runs
// emulated Starlet, each IPC request Broadway posts (X1) and each reply Starlet posts (Y1) is // (the original IOS or a bootstrap ELF), each IPC request Broadway posts (X1) and each reply
// logged with its metadata only: the command, the descriptor and the five argument words (an // Starlet posts (Y1) is logged with its metadata only: the command, the descriptor and the five
// OPEN's path), then the reply's result. Buffer contents are never read. // argument words (an OPEN's path), then the reply's result. Proposal M1e adds the paths of the
// filesystem IOCTLs. No other buffer content is read.
bool IPCTraceEnabled() bool IPCTraceEnabled()
{ {
static const bool enabled = [] { static const bool enabled = [] {
@@ -161,6 +163,45 @@ bool IPCTraceEnabled()
return enabled; return enabled;
} }
// A NUL-terminated absolute path of printable bytes in a 64-byte field, or "" otherwise.
std::string TracePath(Memory::MemoryManager& memory, u32 address)
{
if (memory.GetPointerForRange(address, 64) == nullptr)
return {};
const std::string path = memory.GetString(address, 64);
if (path.empty() || path.size() >= 64 || path[0] != '/' ||
!std::ranges::all_of(path, [](char c) { return c >= 0x20 && c < 0x7f; }))
return {};
return path;
}
// The paths a filesystem request names, by its input shape: a 64-byte path (DELETE, GET_ATTR),
// a 76-byte attribute record with the path at +6 (CREATE_DIR, CREATE_FILE, SET_ATTR), two
// 64-byte paths (RENAME), or an IOCTLV whose first input vector is a 64-byte path (READ_DIR,
// GET_USAGE). " F -" when the field holds no valid path.
std::string TraceFilesystemPaths(Memory::MemoryManager& memory, u32 command, const u32* arg)
{
const auto field = [&memory](u32 address) {
const std::string path = TracePath(memory, address);
return path.empty() ? std::string("-") : path;
};
if (command == 6)
{
if (arg[2] == 0x40)
return " F " + field(arg[1]);
if (arg[2] == 0x4c)
return " F " + field(arg[1] + 6);
if (arg[2] == 0x80)
return " F " + field(arg[1]) + " > " + field(arg[1] + 0x40);
}
else if (command == 7 && arg[1] != 0 && memory.GetPointerForRange(arg[3], 8) != nullptr &&
memory.Read_U32(arg[3] + 4) == 0x40)
{
return " F " + field(memory.Read_U32(arg[3]));
}
return {};
}
void TraceIPCRequest(Core::System& system, u32 address) void TraceIPCRequest(Core::System& system, u32 address)
{ {
auto& memory = system.GetMemory(); auto& memory = system.GetMemory();
@@ -177,6 +218,8 @@ void TraceIPCRequest(Core::System& system, u32 address)
std::string path; std::string path;
if (command == 1 && memory.GetPointerForRange(arg[0], 64) != nullptr) if (command == 1 && memory.GetPointerForRange(arg[0], 64) != nullptr)
path = " P " + memory.GetString(arg[0], 64); path = " P " + memory.GetString(arg[0], 64);
else
path = TraceFilesystemPaths(memory, command, arg);
NOTICE_LOG_FMT(WII_IPC, "IPCTRACE RQ {:08x} C {} FD {} A {:08x} {:08x} {:08x} {:08x} {:08x}{}", NOTICE_LOG_FMT(WII_IPC, "IPCTRACE RQ {:08x} C {} FD {} A {:08x} {:08x} {:08x} {:08x} {:08x}{}",
address, command, static_cast<s32>(fd), arg[0], arg[1], arg[2], arg[3], arg[4], address, command, static_cast<s32>(fd), arg[0], arg[1], arg[2], arg[3], arg[4],
path); path);
+9 -2
View File
@@ -48,8 +48,8 @@
}, },
{ {
"path": "Source/Core/Core/HW/WII_IPC.cpp", "path": "Source/Core/Core/HW/WII_IPC.cpp",
"sha256": "e216d272f7653b4650481a3335989a86550eee3d90aa7e6c7f06bb1ce87822e1", "sha256": "c3faf948533d494243caa229730dac8a8161144647aad22d219f1b4c9f727030",
"bytes": 21443 "bytes": 23116
}, },
{ {
"path": "Source/Core/Core/IOS/Starlet/ARMCore.cpp", "path": "Source/Core/Core/IOS/Starlet/ARMCore.cpp",
@@ -144,6 +144,13 @@
"Source/Core/Core/IOS/Starlet/StarletMemory.cpp", "Source/Core/Core/IOS/Starlet/StarletMemory.cpp",
"Source/Core/Core/IOS/Starlet/StarletMemory.h" "Source/Core/Core/IOS/Starlet/StarletMemory.h"
] ]
},
{
"recordedAt": "2026-10-06",
"purpose": "StarletOS Phase 11 proposal M1e: the IPC trace also prints the paths named by filesystem IOCTLs (64-byte path, 76-byte record at +6, rename pair, first IOCTLV vector of 64 bytes); paths only",
"files": [
"Source/Core/Core/HW/WII_IPC.cpp"
]
} }
] ]
} }
+13
View File
@@ -159,3 +159,16 @@ with Revolution instead of the original IOS, to see where Broadway stops.
Next: the companion's M1b (smoke test with the variable, no window) and M1c Next: the companion's M1b (smoke test with the variable, no window) and M1c
(the user launches the Mii Channel under Revolution in the X11 window). (the user launches the Mii Channel under Revolution in the X11 window).
## Filesystem paths in the IPC trace — 2026-10-06
Companion proposal M1e (approved): under Revolution in the window the System
Menu's save before a launch got -106 on its second CREATE_DIR, and no trace
had the path. `IPCTRACE RQ` lines now end with ` F <path>` for IOCTLs whose
input is a 64-byte path (DELETE, GET_ATTR), a 76-byte attribute record (path
at +6: CREATE_DIR, CREATE_FILE, SET_ATTR) or two paths (` F a > b`, RENAME),
and for IOCTLVs whose first input vector is 64 bytes (READ_DIR, GET_USAGE);
` F -` when that field holds no valid path. Read from memory when X1 is
rung, like the OPEN path; nothing else of the buffers. Checked headless under
Revolution: `/shared2/test2`, `/title/00000001/00000002/data/cache.dat`, the
GET_USAGE directories. 95 Starlet tests passed.