M9.5 + M11.5 + VMX + SJIS/UTF-8: close the post-M5.5 deferred set
Closes the four remaining deferred follow-up items in one bundle. All four are smaller-scope and additive; lockstep determinism unaffected (analyzer-only changes). ## M9.5 — __CxxFrameHandler scope-table parsing - New `xenia_analysis::eh_scope` module. Magic-scans .rdata for the three documented MSVC FuncInfo signatures (0x19930520/21/22) on 4-byte alignment. Each match is parsed as the documented struct (BE u32 fields), with sanity caps on max_state / n_try_blocks / pointer validity. - Walks pUnwindMap (UnwindMapEntry, 8 bytes) and pTryBlockMap (TryBlockMapEntry, 20 bytes) into one row each. - New tables eh_funcinfo, eh_unwind_map, eh_try_blocks. - Sylpheed yield: 2,588 FuncInfo (all version 0x19930522) / 10,019 unwind entries / 315 try-blocks. ## M11.5 — Static-init driver chain detection - New `xenia_analysis::static_init` module. Walks every function looking for the canonical _initterm loop: lwz cursor; mtctr; bcctrl; addi cursor, cursor, 4 bounded by a compare against another constant register. Extracts (array_start, array_end) and reads the array. - Reuses `function_pointer_arrays` table — drivers' arrays land with kind='static_init' (replacing M11's prologue-heuristic output where the structurally-grounded pattern fires). - Sylpheed yield: 0 drivers detected — the binary's static-init structure does not match the canonical CRT loop. Infrastructure ready; future M11.6 can relax. ## VMX vector-store xrefs (M6 follow-up) - Adds AltiVec/VMX X-form load/store XOs to the M6 opcode-31 dispatch: lvx/lvxl/lvebx/lvehx/lvewx (reads) and stvx/stvxl/stvebx/stvehx/stvewx (writes), all addr_mode= 'x_form_indexed'. Static resolution still requires both rA and rB constant. - Sylpheed yield: 110 newly-detected stvx writes. ## Shift_JIS + UTF-8 localised-string detection (M7 follow-up) - Extends `xenia_analysis::strings::analyze` with scan_shift_jis (JIS X 0208 lead/trail byte ranges + half-width katakana pass-through) and scan_utf8 (2- and 3-byte sequences). At least one multi-byte unit required so pure-ASCII strings aren't double-counted. - SJIS bytes rendered as \xHH escapes for diagnostic readability; full SJIS→UTF-8 decoding deferred. - Sylpheed yield: 790 Shift_JIS strings (Japanese debug + UI text) + 39 UTF-8. ## Tests - +2 EH (parses_minimal_funcinfo_v0, rejects_bogus_max_state) - +2 static_init (detects_canonical_initterm_loop, rejects_function_without_pattern) - +2 strings (detects_shift_jis_string, detects_utf8_multibyte_string) Tests 649→655 (+6 unit tests). DB schema golden + write_analysis_results signature updated for new EH parameter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4208,14 +4208,45 @@ fn cmd_dis(
|
||||
|
||||
// Generic function-pointer-array scan (M8 + M11). Re-emits M3 vtables
|
||||
// plus dispatch tables and static-init tables in `.rdata`.
|
||||
let fparrays = xenia_analysis::funcptr_arrays::analyze(
|
||||
let mut fparrays = xenia_analysis::funcptr_arrays::analyze(
|
||||
&pe_image, base, §ions, &function_starts, &vtables,
|
||||
);
|
||||
|
||||
// M11.5 — static-init driver chain detection. Replaces M11's prologue
|
||||
// heuristic with a structurally-grounded result where the driver
|
||||
// function shape matches.
|
||||
let static_init = xenia_analysis::static_init::analyze(
|
||||
&pe_image, base, §ions, &func_analysis, &function_starts,
|
||||
&xref_result.labels,
|
||||
);
|
||||
info!(
|
||||
static_init_drivers = static_init.drivers.len(),
|
||||
static_init_arrays = static_init.arrays.len(),
|
||||
"M11.5 static-init driver scan complete",
|
||||
);
|
||||
// Merge M11.5 results into the funcptr_arrays vector. If an array's
|
||||
// address already exists from M8/M11, upgrade its kind from
|
||||
// 'dispatch_table'/'static_init' to a definitive 'static_init'.
|
||||
let static_init_addrs: std::collections::HashSet<u32> =
|
||||
static_init.arrays.iter().map(|a| a.address).collect();
|
||||
fparrays.retain(|a| !static_init_addrs.contains(&a.address));
|
||||
for a in &static_init.arrays {
|
||||
fparrays.push(a.clone());
|
||||
}
|
||||
info!(
|
||||
funcptr_arrays = fparrays.len(),
|
||||
dispatch_tables = fparrays.iter().filter(|a| a.kind == "dispatch_table").count(),
|
||||
static_inits = fparrays.iter().filter(|a| a.kind == "static_init").count(),
|
||||
"function-pointer array scan complete",
|
||||
"function-pointer array set finalised",
|
||||
);
|
||||
|
||||
// M9.5 — MSVC __CxxFrameHandler scope-table magic-scan.
|
||||
let eh_records = xenia_analysis::eh_scope::analyze(&pe_image, base, §ions);
|
||||
info!(
|
||||
eh_funcinfo = eh_records.len(),
|
||||
eh_unwind_entries = eh_records.iter().map(|r| r.unwind_map.len()).sum::<usize>(),
|
||||
eh_try_blocks = eh_records.iter().map(|r| r.try_blocks.len()).sum::<usize>(),
|
||||
"M9.5 EH scope-table scan complete",
|
||||
);
|
||||
|
||||
// M5.5 — typed indirect-dispatch resolution (this->vptr → method).
|
||||
@@ -4274,6 +4305,7 @@ fn cmd_dis(
|
||||
&strings,
|
||||
&fparrays,
|
||||
Some(&typed_ind),
|
||||
&eh_records,
|
||||
)?;
|
||||
w.write_tls(tls_info.as_ref())?;
|
||||
if matches!(analyze, AnalyzeMode::Sql | AnalyzeMode::Both) {
|
||||
|
||||
Reference in New Issue
Block a user