Summary
objdiff-cli report generate panics with index out of bounds: the len is 0 but the index is 18446744073709551615 at objdiff-core/src/arch/arm.rs:130:29 when an ARM ELF object has a non-empty .text section but no STT_FUNC symbol covering it — i.e. either zero symbols pointing into the .text section, or only STT_OBJECT/STT_SECTION symbols there.
The 18446744073709551615 is usize::MAX, which suggests a 0_usize - 1 underflow when the code-symbol iteration yields an empty list.
Reproduction
Hit reliably while running objdiff-cli report generate on the Yu-Gi-Oh! GX Spirit Caller decomp project (Nintendo DS, ARM, mwccarm 2.0/sp1p5 toolchain via ds-decomp). Brief 187 ([PR #pending]) ships a workaround filter in the project's own tooling. The relevant tool is objdiff-cli v2.7.1.
Minimal panic command:
RUST_BACKTRACE=1 ./objdiff-cli report generate -p . -o /tmp/r.json -d
(-d forces single-threaded so the panic surfaces deterministically.)
Failure modes that trigger the panic
We bisected to find every crashing unit and grouped them by ELF shape:
-
.text exists with content but no symbol covers it. Example: a delinked TU with .text carrying real ARM instruction bytes (size 0x86 in our case) but only STT_SECTION (type 3) section symbols and external (undefined) function references. No STT_FUNC symbol with non-zero st_size and st_shndx == .text.
-
.text exists with content but only STT_OBJECT symbols cover it. Example: a BuildInfo data blob the linker placed in .text instead of .rodata (size 0xcc, single STT_OBJECT symbol). The ARM arch processor tries to disassemble it as code → crashes.
-
Empty .text section. Often combined with (1) — zero useful symbols.
Backtrace
thread '<unnamed>' panicked at objdiff-core/src/arch/arm.rs:130:29:
index out of bounds: the len is 0 but the index is 18446744073709551615
stack backtrace:
0: _rust_begin_unwind
1: core::panicking::panic_fmt
2: core::panicking::panic_bounds_check
3: <objdiff_core::arch::arm::ObjArchArm as objdiff_core::arch::ObjArch>::process_code
4: objdiff_core::diff::code::process_code_symbol
5: objdiff_core::diff::diff_objs
6: objdiff_cli::cmd::report::report_object
...
Minimal reproducer
Tiny ARM ELF (1020 bytes) that triggers the panic — has .text size 0x86 but only STT_SECTION + external-reference symbols (no STT_FUNC in .text).
Base64-encoded `repro.o`
f0VMRgEBAQAAAAAAAAAAAAEAKAABAAAAAAAAAAAAAADkAgAAAAAAADQAAAAAACgABwAGAP/e/+f/3v/n/97/5//en9uRPDQp6rfavPMZToUu5GvkIJkkiAaBdvlJWIXX5U8uiEcvduaXm2EkY8+44A7gB0JWZ693X7or5yjBkmMf+PkC/TYZvt89ylv7Rc9obFfNWkVPlcq1L+ScC8dR4cF6oLYS9ZGe9a20XMlApUhsM7kufxvm10q+AAAAAAwAAAAYAAAA/////w4AAAD/////DwAAAP////8QAAAA/////wUAAAD/////CAAAAP////8HAAAA/////wkAAAD/////CgAAAP////8LAAAA/////wIAAAD/////EgAAAP////8TAAAA/////xQAAAD/////FQAAAP////8XAAAA/////xkAAAD/////GgAAAP////8lAAAA/////yEAAAD/////HAAAAP////8dAAAA/////x8AAAD/////IAAAAP////8bAAAA/////wQAAAD/////IgAAAP////8jAAAA/////0xDMDgAAAAATEMxMAAAAABMQzEyAAAAAExDMTYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwABAAAAAAAAAAAAAAAAAAMAAgAdAAAAAAAAAAAAAAAgAAAAOQAAAAAAAADoAAAAEQACAA8AAADoAAAACAAAABEAAgBHAAAA8AAAAAgAAAARAAIAAQAAAPgAAAAIAAAAEQACACsAAAAAAQAACAAAABEAAgAAZGF0YV8wMjBjM2NiOABkYXRhXzAyMGMzY2E4AGZ1bmNfMDIwMDBjNDQAZGF0YV8wMjBjM2NjMABkYXRhXzAyMGMzYmMwAGRhdGFfMDIwYzNjYjAAAAAAAAAAAAIDAAAAAAAAAC50ZXh0AC5zaHN0cnRhYgAuc3RydGFiAC5zeW10YWIALnJlbGEuZGF0YQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAGAAAAAAAAADQAAACGAAAAAAAAAAAAAAACAAAAAAAAACYAAAABAAAAAwAAAAAAAAC6AAAACAEAAAAAAAAAAAAAAQAAAAAAAAAhAAAABAAAAEAAAAAAAAAArAIAAAwAAAAEAAAAAgAAAAQAAAAMAAAAGQAAAAIAAAAAAAAAAAAAAMQBAACQAAAABQAAAAQAAAAEAAAAEAAAABEAAAADAAAAAAAAAAAAAABUAgAAVQAAAAAAAAAAAAAAAQAAAAAAAAAHAAAAAwAAAAAAAAAAAAAAuAIAACwAAAAAAAAAAAAAAAEAAAAAAAAA
To repro:
base64 -d > repro.o <<EOF_B64
[paste base64 from above]
EOF_B64
cat > objdiff.json <<EOF_JSON
{
"min_version": "2.0",
"custom_make": "ninja",
"target_dir": "",
"base_dir": "",
"units": [
{"name": "repro", "target_path": "repro.o", "metadata": {}}
]
}
EOF_JSON
objdiff-cli report generate -p . -o /tmp/r.json -d
Expected: report.json generated. Actual: panic at arm.rs:130.
Suggested fix direction
process_code in objdiff-core/src/arch/arm.rs likely iterates over symbols pointing into the code section and then derives a span end via something like symbols[idx + 1].address or symbols.last().address + symbols.last().size — when symbols is empty, the index/range math underflows. Guarding the iteration with if symbols.is_empty() { return Ok(()); } (or equivalent) at the function head should make the panic into a clean no-op for code-less / data-only .text sections.
(Same shape applies whether all symbols are STT_OBJECT or simply absent — happy to test a fix branch against our project's full 3330-unit corpus if helpful.)
Project context
This panic blocks objdiff-verified code-match metrics for the entire decomp — build/<region>/report.json never gets written, so we can't measure function-level matching progress without a workaround. Brief 187 ships a project-local filter (tools/objdiff_filter_panic_units.py) that drops the ~20 affected units before invoking objdiff-cli report generate, but the right fix is upstream.
Filed from the spirit-caller project's brief 187 PR — happy to share more diagnostics or test patches.
Summary
objdiff-cli report generatepanics withindex out of bounds: the len is 0 but the index is 18446744073709551615atobjdiff-core/src/arch/arm.rs:130:29when an ARM ELF object has a non-empty.textsection but noSTT_FUNCsymbol covering it — i.e. either zero symbols pointing into the.textsection, or onlySTT_OBJECT/STT_SECTIONsymbols there.The 18446744073709551615 is
usize::MAX, which suggests a0_usize - 1underflow when the code-symbol iteration yields an empty list.Reproduction
Hit reliably while running
objdiff-cli report generateon the Yu-Gi-Oh! GX Spirit Caller decomp project (Nintendo DS, ARM, mwccarm 2.0/sp1p5 toolchain viads-decomp). Brief 187 ([PR #pending]) ships a workaround filter in the project's own tooling. The relevant tool isobjdiff-cliv2.7.1.Minimal panic command:
(
-dforces single-threaded so the panic surfaces deterministically.)Failure modes that trigger the panic
We bisected to find every crashing unit and grouped them by ELF shape:
.textexists with content but no symbol covers it. Example: a delinked TU with.textcarrying real ARM instruction bytes (size 0x86 in our case) but onlySTT_SECTION(type 3) section symbols and external (undefined) function references. NoSTT_FUNCsymbol with non-zerost_sizeandst_shndx == .text..textexists with content but onlySTT_OBJECTsymbols cover it. Example: aBuildInfodata blob the linker placed in.textinstead of.rodata(size 0xcc, singleSTT_OBJECTsymbol). The ARM arch processor tries to disassemble it as code → crashes.Empty
.textsection. Often combined with (1) — zero useful symbols.Backtrace
Minimal reproducer
Tiny ARM ELF (1020 bytes) that triggers the panic — has
.textsize 0x86 but onlySTT_SECTION+ external-reference symbols (noSTT_FUNCin.text).Base64-encoded `repro.o`
To repro:
Expected: report.json generated. Actual: panic at
arm.rs:130.Suggested fix direction
process_codeinobjdiff-core/src/arch/arm.rslikely iterates over symbols pointing into the code section and then derives a span end via something likesymbols[idx + 1].addressorsymbols.last().address + symbols.last().size— whensymbolsis empty, the index/range math underflows. Guarding the iteration withif symbols.is_empty() { return Ok(()); }(or equivalent) at the function head should make the panic into a clean no-op for code-less / data-only.textsections.(Same shape applies whether all symbols are
STT_OBJECTor simply absent — happy to test a fix branch against our project's full 3330-unit corpus if helpful.)Project context
This panic blocks objdiff-verified code-match metrics for the entire decomp —
build/<region>/report.jsonnever gets written, so we can't measure function-level matching progress without a workaround. Brief 187 ships a project-local filter (tools/objdiff_filter_panic_units.py) that drops the ~20 affected units before invokingobjdiff-cli report generate, but the right fix is upstream.Filed from the spirit-caller project's brief 187 PR — happy to share more diagnostics or test patches.