mirror of
https://github.com/valentderah/totk-pc-recomp.git
synced 2026-11-11 01:41:02 +00:00
Merge task/crash705: list the compound physics shape's children in the crash report (#705)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
1503b17f7d
2 files changed
+79
No files matched your search
@@ -10,6 +10,7 @@
|
||||
#include "cfg.h"
|
||||
#include "host.h"
|
||||
#include "kernel.h"
|
||||
#include "layout.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
#define STACK 0x10000
|
||||
@@ -744,7 +745,36 @@ static void test_platform(void) {
|
||||
static uint64_t crash_host_words[6] = {0, 0, 0x5ca1ab1e0c0de001ull, 0, 0, 0};
|
||||
static uint64_t crash_guest_words[6] = {0, 0, 0x5ca1ab1e0c0de002ull, 0, 0, 0};
|
||||
|
||||
// The compound shape note (main.c crash_compound_shape, 1.2.1): a shape of 3 records whose child 0 has no shape, child
|
||||
// 1 has one but its live bit is clear, child 2 is live and filled.
|
||||
static uint64_t crash_shape[0x1a0 / 8], crash_records[3 * 0x78 / 8], crash_child_shape;
|
||||
|
||||
static void crash_shape_fill(Cpu *c) {
|
||||
uint8_t *s = (uint8_t *)crash_shape, *r = (uint8_t *)crash_records;
|
||||
static const char *const names[3] = {"PartA", "PartB", "PartC"};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
uint64_t name = (uint64_t)(uintptr_t)(r + i * 0x78 + 0x14);
|
||||
memcpy(r + i * 0x78 + 8, &name, 8);
|
||||
memcpy(r + i * 0x78 + 0x14, names[i], strlen(names[i]) + 1);
|
||||
}
|
||||
uint64_t child = (uint64_t)(uintptr_t)&crash_child_shape, vt = MOD_MAIN_BASE + 0x45e1218;
|
||||
uint64_t rec = (uint64_t)(uintptr_t)crash_records;
|
||||
uint32_t n = 3, bits = 0x5;
|
||||
memcpy(r + 0x78, &child, 8);
|
||||
memcpy(r + 2 * 0x78, &child, 8);
|
||||
memcpy(s, &vt, 8);
|
||||
memcpy(s + 0x78, &n, 4);
|
||||
memcpy(s + 0x80, &rec, 8);
|
||||
memcpy(s + 0x88, &bits, 4);
|
||||
memcpy(s + 0x190, &n, 4);
|
||||
c->x[20] = (uint64_t)(uintptr_t)crash_shape;
|
||||
c->x[21] = 0x1000038;
|
||||
c->x[30] = MOD_MAIN_BASE + 0xe056d4;
|
||||
}
|
||||
|
||||
static void crash_child_main(Cpu *c) {
|
||||
const char *mode = getenv(CRASH_CHILD_ENV);
|
||||
if (mode && !strcmp(mode, "shape")) crash_shape_fill(c);
|
||||
c->x[19] = (uint64_t)(uintptr_t)&crash_guest_words[2];
|
||||
c->sp -= 0x100; // a frame on the guest stack, as a crashing function has
|
||||
__asm__ volatile("movq %0, %%rbx\n\tmovq 0x10, %%rax" : : "r"(&crash_host_words[2]) : "rax", "rbx", "memory");
|
||||
@@ -779,6 +809,18 @@ static void test_crash_report(void) {
|
||||
"crash report: no memory commit line");
|
||||
printf("crash report: exit code %d, host registers, code bytes, memory at rbx and x19, guest stack, commit %s\n", code,
|
||||
failures ? "checked with failures" : "present");
|
||||
if (rt_game_version != 121) return;
|
||||
code = plat_run_self(CRASH_CHILD_ENV, "shape", out, sizeof out, 30000);
|
||||
CHECK(report_line(out, " compound shape ", line, sizeof line) && strstr(line, "3 children, 3 records") &&
|
||||
strstr(line, "live bits: 00000005"),
|
||||
"crash report: no compound shape line (%s)", strstr(out, "compound shape") ? line : "none");
|
||||
CHECK(report_line(out, "child 0:", line, sizeof line) && strstr(line, "shape 0 \"PartA\""),
|
||||
"crash report: child 0 should have no shape (%s)", line);
|
||||
CHECK(report_line(out, "child 1:", line, sizeof line) && strstr(line, "(off) \"PartB\""),
|
||||
"crash report: child 1 should be off (%s)", line);
|
||||
CHECK(report_line(out, "child 2:", line, sizeof line) && !strstr(line, "(off)") && strstr(line, "\"PartC\""),
|
||||
"crash report: child 2 should be live (%s)", line);
|
||||
printf("crash report, compound shape: exit code %d, %s\n", code, failures ? "checked with failures" : "children listed");
|
||||
}
|
||||
|
||||
int probe_kernel(void) {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "cfg.h"
|
||||
#include "host.h"
|
||||
#include "layout.h"
|
||||
#include "platform/platform.h"
|
||||
#include "sha256.h"
|
||||
|
||||
@@ -284,6 +285,41 @@ static void crash_memory(const PlatCrash *x, const Cpu *c) {
|
||||
(unsigned long long)s[i + 1], (unsigned long long)s[i + 2], (unsigned long long)s[i + 3]);
|
||||
}
|
||||
|
||||
// 1.2.1: a fault right after a compound physics shape was asked for its first child's material (the call returning to
|
||||
// main+0xe056d4 reads the result without a check). The shape (vtable main+0x45e1218, built by main+0x7359fc) is in x20
|
||||
// there. It returns null when no child slot is both live (bitmap at +0x88) and filled (shape pointer at +0 of the
|
||||
// 0x78-byte records at +0x80). Every child is filled when the shape is built, so the list tells children removed later
|
||||
// (null shape) from children switched off (clear bit), and the names name the object. Runs only in the crash handler.
|
||||
static void crash_compound_shape(const Cpu *c) {
|
||||
if (!c || rt_game_version != 121 || c->x[30] != MOD_MAIN_BASE + 0xe056d4) return;
|
||||
uint64_t shape = c->x[20];
|
||||
if (!readable(shape, 0x1a0) || LD64(shape) != MOD_MAIN_BASE + 0x45e1218) {
|
||||
rt_logf(" compound shape: x20 %#llx is not one\n", (unsigned long long)shape);
|
||||
return;
|
||||
}
|
||||
uint32_t children = LD32(shape + 0x190), records = LD32(shape + 0x78);
|
||||
uint64_t rec = LD64(shape + 0x80);
|
||||
rt_logf(" compound shape %#llx (holder %#llx): %u children, %u records at %#llx, live bits:",
|
||||
(unsigned long long)shape, (unsigned long long)(c->x[21] - 0x38), children, records,
|
||||
(unsigned long long)rec);
|
||||
uint32_t n = children > 0x400 ? 0x400 : children; // the bitmap holds 0x400 bits
|
||||
for (uint32_t w = 0; w < (n + 31) / 32; w++) rt_logf(" %08x", LD32(shape + 0x88 + 4 * w));
|
||||
rt_log_raw("\n", 1);
|
||||
if (records > 0x400 || !readable(rec, (uint64_t)records * 0x78)) return;
|
||||
for (uint32_t i = 0; i < records; i++) {
|
||||
uint64_t r = rec + (uint64_t)i * 0x78, child = LD64(r), s = LD64(r + 8);
|
||||
char name[33];
|
||||
size_t k = 0;
|
||||
for (; k < 32 && readable(s + k, 1); k++) {
|
||||
name[k] = *(const char *)(uintptr_t)(s + k);
|
||||
if (!name[k]) break;
|
||||
}
|
||||
name[k] = 0;
|
||||
int live = LD32(shape + 0x88 + 4 * (i >> 5)) >> (i & 31) & 1;
|
||||
rt_logf(" child %3u: shape %#llx%s \"%s\"\n", i, (unsigned long long)child, live ? "" : " (off)", name);
|
||||
}
|
||||
}
|
||||
|
||||
static void crash_handler(const PlatCrash *x) {
|
||||
static volatile int32_t busy;
|
||||
if (plat_xchg32(&busy, 1)) plat_exit(71);
|
||||
@@ -349,6 +385,7 @@ static void crash_handler(const PlatCrash *x) {
|
||||
rt_logf(" not on a guest thread\n");
|
||||
}
|
||||
crash_memory(x, c);
|
||||
crash_compound_shape(c);
|
||||
kern_free_cores_note();
|
||||
fflush(stderr);
|
||||
plat_exit(71);
|
||||
|
||||
Reference in new issue
Block a user