remove src recomp

This commit is contained in:
Benjamin Palko 2026-10-15 09:08:48 -04:00
parent af36074fed
commit 31ff800b2a
19 changed files with 1398 additions and 644 deletions

View file

@ -16,6 +16,8 @@ per class (e.g. `MagiAgentNetwork`, `MGAgentManagerSession`) indicate multiple
inheritance. Statically linked C++ libraries: ProudNet, TinyXML (`TiXml*`), ATL.
## Outputs
Porting spec (Win32 → Linux substitutions, behaviour to reproduce, original bugs): `porting.md`.
| Path | Content |
|---|---|
| `full/functions/<addr>.c` | Ghidra pseudocode for all 6,423 non-thunk functions (1 failed; see `full/index.tsv`). Includes library code (ProudNet, TinyXML, CRT) — not yet labelled. |

View file

@ -0,0 +1,55 @@
# Agent_Release_x64.exe — porting spec (Win32 → Linux)
This was kept from the removed Linux reconstruction `src/agent_release/`
(removed 2026-10-15). It records the facts about the original binary that a
re-implementation needs, and the nearest Linux equivalent for each Win32 call.
Sources: `evidence.md`, `cpp/AgentProcessControl.cpp`. Names are inferred;
the behaviour is static-analysis evidence only.
## Behaviour to reproduce
The servers being managed are read from config (`option\*.xml`, mapping not
yet recovered).
| Item | Behaviour |
|---|---|
| Single instance (`0x1400100b0`) | Named mutex `Global\RustyHearts_Agent` |
| Launch (`0x1400094e0`) | `CreateProcessW(NULL, "<exe> <arg>", …, CREATE_NEW_CONSOLE, …, workDir)`, console 700×110, fill attribute 0x17. Command line is limited to 260 characters (`MAX_PATH`). Returns the pid, or 0 on failure (logs `=======Server Fail=======`) |
| After each launch attempt | `Sleep(1000)` |
| Command line (`0x140008ea0`) | `<exe for server type> <code>`. An alternative argument builder `FUN_140027540` exists, but its output is unknown |
| Watcher (`0x140008c90`) | Polls `GetExitCodeProcess` every 10 ms. On exit it sends two RMIs to AgentManager, then relaunches if the per-server revive flag (+0xd5) or the global flag (+0x171) is set |
| Kill (`0x140009780`) | Toolhelp32 snapshot, case-insensitive image-name match, terminates the **first** match only (`TerminateProcess(h,0)`) |
| Main loop (`0x1400037a0`) | 100 ms tick, 1 s FPS counter. Optionally auto-starts servers after a configured delay (+0x178). At startup it kills a stale process of type 0x18 (identity unknown) |
## Win32 → Linux substitutions
| Original (address) | Win32 | Linux replacement | Behaviour difference |
|---|---|---|---|
| Single instance (`0x1400100b0`) | `CreateMutexW("Global\\RustyHearts_Agent")` | `flock(LOCK_EX\|LOCK_NB)` on `/tmp/RustyHearts_Agent.lock` | Lock file instead of a kernel object; still released on exit or crash |
| Launch (`0x1400094e0`) | `CreateProcessW(…, CREATE_NEW_CONSOLE, …, workDir)` + `STARTUPINFOW` console geometry | `posix_spawnp` + `POSIX_SPAWN_SETSID` + `posix_spawn_file_actions_addchdir_np` (glibc ≥ 2.29) | No console window; the command line is split on whitespace (no Windows quoting rules) |
| Watcher (`0x140008c90`) | `GetExitCodeProcess` polled every 10 ms | blocking `waitpid` on a detached thread | No polling. Reaping fixes the original handle leak; passing the pid by value fixes the original stack-pointer race |
| Kill (`0x140009780`) | Toolhelp32 + `OpenProcess` + `TerminateProcess(h,0)` | scan `/proc/*/cmdline` for the argv[0] basename with `strcasecmp`, then `kill(SIGKILL)` | Same rule: first match only, case-insensitive |
| Main-loop timer | `QueryPerformanceCounter` (`TimeSourceHRWin32`) | `std::chrono::steady_clock` | — |
| Thread start | `_beginthreadex` | `std::thread` | — |
| `Sleep` | `Sleep` | `std::this_thread::sleep_for` | — |
| Shutdown | console menu (`FUN_140001dc0`, not analysed) | `SIGINT` / `SIGTERM` | Different trigger |
## Original bugs (O)
- **Process handle leak:** the watcher never closes the process handle.
- **Stack-pointer race:** `LaunchProcess` hands the watcher a pointer to a
stack `PROCESS_INFORMATION`. It is only safe because of the
`Sleep(1000)` that follows.
- **Snapshot handle leak:** `KillProcessByName` leaks the snapshot handle on
the success path.
## Unknown / not recovered
- **ProudNet RMI to AgentManager and the game servers:** proprietary
transport. Wire-incompatible with ProudNet 1.8 (see the ProudNet section of
`third-party/README.md`). The proxy vtable slots used are `+0x40` and `+0x50`.
- **XML config field mapping** for the Agent.
- **`FUN_140027540` argument builder; the `type == 1` exit follow-up
(`FUN_140009f20`); the type 0x18 process killed at startup.**
- **Locking around the server table:** not visible in the analysed code.