M1: parse .pdata RUNTIME_FUNCTION; cross-validate function boundaries

Adds an authoritative function-boundary source from the linker:
- New `xenia_xex::pdata` parses .pdata 8-byte entries (BeginAddress + packed
  prolog/length/flags). Bit layout per Microsoft PE32 PowerPC spec: prolog in
  bits 0..7, function_length in bits 8..29, flags in 30..31.
- `func::analyze_with_pdata` unions pdata BeginAddresses into the candidate
  set, attaches `pdata_validated`/`pdata_length` to each `FuncInfo`, and trims
  any function whose `end` overlaps the next start (catches mis-merge where
  one row spanned two prologues — the audit-031 sub_824D23B0/sub_824D29F0
  case).
- DB: extends `functions` with `pdata_validated BOOLEAN`, `pdata_length BIGINT`;
  new table `pdata_entries`; index on pdata_validated.
- New `crates/xenia-analysis/SCHEMA.md` documents M1 layer + forward work.

Validation on Sylpheed: 25481 functions (was 12156) / 23073 pdata_validated /
0 orphans / 0 mis-merges. Audit-031 mis-merge resolved: sub_824D29F0 now has
its own row with `pdata_length=280` (70 dwords); sub_824D23B0 now correctly
ends at 0x824D2878 (`pdata_length=1224` matches prologue walk).

Tests 605→610. New 5-test pdata unit suite covers bit layout + sentinel +
out-of-range filtering + real-world layout round-trip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-05-08 19:44:02 +02:00
parent e061e21851
commit 70120465a3
7 changed files with 503 additions and 16 deletions

View File

@@ -4024,13 +4024,21 @@ fn cmd_dis(
}
info!(thunks = import_map.len(), "resolved import thunks");
// Function analysis
// Function analysis (with .pdata-validated boundaries when present)
let code_sections: Vec<(u32, u32, u32)> = sections.iter()
.filter(|s| s.is_code())
.map(|s| (s.virtual_address, s.virtual_size, s.flags))
.collect();
let func_analysis = xenia_analysis::func::analyze(&pe_image, base, entry, &code_sections);
info!(functions = func_analysis.functions.len(), "function detection complete");
let pdata_entries = xenia_xex::pdata::parse_pdata(&pe_image, base, &sections);
info!(pdata_entries = pdata_entries.len(), "parsed .pdata RUNTIME_FUNCTION entries");
let func_analysis = xenia_analysis::func::analyze_with_pdata(
&pe_image, base, entry, &code_sections, &pdata_entries,
);
info!(
functions = func_analysis.functions.len(),
pdata_validated = func_analysis.functions.values().filter(|f| f.pdata_validated).count(),
"function detection complete",
);
// Cross-reference analysis
let xref_result = xenia_analysis::xref::analyze_xrefs(