[GH-ISSUE #5243] Windows Ghidra P0: no path for ELF/arm64 targets (e.g. Android libapp.so) #3206

Open
opened 2026-10-31 00:37:50 +00:00 by bsakaguchi · 4 comments
Owner

Originally created by @avadh-pro on GitHub (Oct 19, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5243

Problem
On Windows, GhidraProvider's P0 boundary (src/ghidra/GhidraProvider.ts, inspectWindowsP0TargetSupport) accepts only format === "pe" (plus raw 6502). Any ELF target — e.g. an Android native library pulled from a device, such as Flutter's libapp.so (arm64) — is rejected with target_format_unsupported, even though the installed Ghidra distribution and JDK are otherwise healthy (confirmed via rea doctor --provider ghidra).

Repro

  1. Install REA + Ghidra 12.1.4 + JDK 21 on Windows x64, set GHIDRA_INSTALL_DIR.
  2. Pull an arm64 ELF shared library from an Android device (e.g. a Flutter app's libapp.so).
  3. Call open_binary on it — succeeds, reports format: "elf", architecture: "arm64".
  4. Call search_strings (or any Ghidra-routed op) — fails with provider_unavailable / target_format_unsupported, reason: "Windows Ghidra P0 accepts native PE and explicitly selected raw 6502 targets only."

Why this isn't just "expected, move on"
docs/windows-ghidra-p0.md documents this as intentional scope, backed by Windows-specific native process/filesystem/DACL controls verified only for PE. That's a reasonable boundary, but it means ELF (a very common target for anyone doing Android native analysis on Windows) has no supported path at all on this platform today — only the Linux/macOS Ghidra providers and the unsupported Hopper/IDA/Kuna paths cover it.

Ask
Not proposing a specific fix — this needs design discussion given the native sandboxing work involved. Possible directions, for maintainers to weigh:

  • Extend the same native process/DACL verification work to ELF targets and widen P0's format check.
  • Document the gap explicitly in windows-ghidra-p0.md's current boundary table so it's discoverable before someone spends time debugging the rejection.
  • Point users at a documented fallback (e.g. WSL2 Ghidra) for ELF-on-Windows in the meantime.

Environment

  • REA (rea-agents) 6.7.0, Windows 10/11 x64, Node 24.14.0, Ghidra 12.1.4, JDK 21 (Temurin)
  • Target: ELF arm64 shared library (Dart AOT snapshot embedded, not relevant to the gap itself)

I'm happy to help validate a fix on Windows once there's a direction, but didn't want to send an unreviewed PR that touches a documented security boundary without maintainer input first.

Originally created by @avadh-pro on GitHub (Oct 19, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5243 **Problem** On Windows, `GhidraProvider`'s P0 boundary (`src/ghidra/GhidraProvider.ts`, `inspectWindowsP0TargetSupport`) accepts only `format === "pe"` (plus raw 6502). Any ELF target — e.g. an Android native library pulled from a device, such as Flutter's `libapp.so` (arm64) — is rejected with `target_format_unsupported`, even though the installed Ghidra distribution and JDK are otherwise healthy (confirmed via `rea doctor --provider ghidra`). **Repro** 1. Install REA + Ghidra 12.1.4 + JDK 21 on Windows x64, set `GHIDRA_INSTALL_DIR`. 2. Pull an arm64 ELF shared library from an Android device (e.g. a Flutter app's `libapp.so`). 3. Call `open_binary` on it — succeeds, reports `format: "elf", architecture: "arm64"`. 4. Call `search_strings` (or any Ghidra-routed op) — fails with `provider_unavailable` / `target_format_unsupported`, reason: "Windows Ghidra P0 accepts native PE and explicitly selected raw 6502 targets only." **Why this isn't just "expected, move on"** `docs/windows-ghidra-p0.md` documents this as intentional scope, backed by Windows-specific native process/filesystem/DACL controls verified only for PE. That's a reasonable boundary, but it means ELF (a very common target for anyone doing Android native analysis on Windows) has no supported path at all on this platform today — only the Linux/macOS Ghidra providers and the unsupported Hopper/IDA/Kuna paths cover it. **Ask** Not proposing a specific fix — this needs design discussion given the native sandboxing work involved. Possible directions, for maintainers to weigh: - Extend the same native process/DACL verification work to ELF targets and widen P0's format check. - Document the gap explicitly in `windows-ghidra-p0.md`'s current boundary table so it's discoverable before someone spends time debugging the rejection. - Point users at a documented fallback (e.g. WSL2 Ghidra) for ELF-on-Windows in the meantime. **Environment** - REA (rea-agents) 6.7.0, Windows 10/11 x64, Node 24.14.0, Ghidra 12.1.4, JDK 21 (Temurin) - Target: ELF arm64 shared library (Dart AOT snapshot embedded, not relevant to the gap itself) I'm happy to help validate a fix on Windows once there's a direction, but didn't want to send an unreviewed PR that touches a documented security boundary without maintainer input first.
Author
Owner

@uyg7x commented on GitHub (Oct 19, 2026):

Hey @avadh-pro and maintainers!
I’d love to take a shot at this issue. I completely agree with holding off on any blind PRs that might mess with the Windows P0 security boundaries.
To start safe and add immediate value, I propose we tackle a mix of Option 2 and 3: explicitly calling out this ELF gap in windows-ghidra-p0.md with a clearer error message, and adding a quick, straightforward guide on using WSL2 Ghidra as a fallback for Windows users.
If the team is actually leaning toward Option 1 (extending the DACL checks to ELF targets), I’m totally down to dig into inspectWindowsP0TargetSupport and map out what that would look like first.
Let me know which direction you prefer! I’ve already got a Windows x64 setup with Ghidra 12.1.4 and JDK 21 ready to test whatever we decide.

<!-- gh-comment-id:6277278471 --> @uyg7x commented on GitHub (Oct 19, 2026): Hey @avadh-pro and maintainers! I’d love to take a shot at this issue. I completely agree with holding off on any blind PRs that might mess with the Windows P0 security boundaries. To start safe and add immediate value, I propose we tackle a mix of Option 2 and 3: explicitly calling out this ELF gap in windows-ghidra-p0.md with a clearer error message, and adding a quick, straightforward guide on using WSL2 Ghidra as a fallback for Windows users. If the team is actually leaning toward Option 1 (extending the DACL checks to ELF targets), I’m totally down to dig into inspectWindowsP0TargetSupport and map out what that would look like first. Let me know which direction you prefer! I’ve already got a Windows x64 setup with Ghidra 12.1.4 and JDK 21 ready to test whatever we decide.
Author
Owner

@avadh-pro commented on GitHub (Oct 20, 2026):

Agreed, Option 2+3 is the right place to start. Being explicit about the gap in windows-ghidra-p0.md plus a documented WSL2 Ghidra fallback gets Windows ELF users unblocked today without touching the P0 security boundary at all, and it doesn't foreclose Option 1 later if a maintainer wants to scope that separately.

On the error message: right now inspectWindowsP0TargetSupport returns target_format_unsupported with a reason that states the boundary but doesn't point anywhere. Surfacing a remediation hint there (pointing at the new doc section) alongside the doc update would close the loop for anyone hitting this the way I did, without any logic changes to the check itself.

Happy to test against my Windows x64 + Ghidra 12.1.4 + JDK 21 setup once there's a draft, including re-confirming the ELF arm64 repro from this issue.

🤖 Generated with Claude Code

<!-- gh-comment-id:6280860031 --> @avadh-pro commented on GitHub (Oct 20, 2026): Agreed, Option 2+3 is the right place to start. Being explicit about the gap in `windows-ghidra-p0.md` plus a documented WSL2 Ghidra fallback gets Windows ELF users unblocked today without touching the P0 security boundary at all, and it doesn't foreclose Option 1 later if a maintainer wants to scope that separately. On the error message: right now `inspectWindowsP0TargetSupport` returns `target_format_unsupported` with a reason that states the boundary but doesn't point anywhere. Surfacing a remediation hint there (pointing at the new doc section) alongside the doc update would close the loop for anyone hitting this the way I did, without any logic changes to the check itself. Happy to test against my Windows x64 + Ghidra 12.1.4 + JDK 21 setup once there's a draft, including re-confirming the ELF arm64 repro from this issue. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Owner

@yuttapichaiARD commented on GitHub (Oct 20, 2026):

Adding a data point and a third route for the docs-first step (#5305), from a Windows 11 host with REA 6.4.0, Ghidra 12.1.4 and JDK 21.

Observed: open_binary on a Cortex-M0 ELF (ARM, with full DWARF) succeeds, then every Ghidra-routed call returns provider_unavailable with per-provider rejections target_format_unsupported ("Windows Ghidra P0 accepts PE targets only."), unsupported_host (Hopper) and not_configured (IDA). The bundled skill's recovery table maps provider_unavailable to "read the diagnostics and resolve the prerequisite", which has no prerequisite to resolve in this case; an agent following it loops on doctor/setup.

Route that worked without WSL2: the same Ghidra install, run headless on the Windows host (support\analyzeHeadless.bat with -processor ARM:LE:32:Cortex, a pre-script and a post-script that exports decompiled C through DecompInterface). Two Ghidra-side issues are worth a sentence in the new doc section because they look like REA failures to an agent:

  1. Unsupported DWARF Form: DW_FORM_ref_sig8 aborts the whole DWARF import when any compile unit uses type signatures (an IAR-compiled library in my case). Rewriting form 0x20 to 0x07 (DW_FORM_data8, same width) in .debug_abbrev of a copy lets the import proceed with the remaining units' types.

  2. GCC -g3 macro data makes DWARFMacroEnumCreator.createEnums recurse until StackOverflowError, and analyzeHeadless.bat then blocks on pause. Setting the analyzer option DWARF.Create Enums from Macros to NONE in a pre-script (and redirecting stdin from nul) avoids it.

Suggestion for the skill side, independent of the P0 decision: give the recovery table an explicit row for "every provider rejects this target format on this host" whose remedy is to stop retrying REA and continue with the documented fallback (WSL2 Ghidra, or a local headless run as above), labelling the results as non-REA evidence. Happy to turn this into a PR against the docs section once #5305 settles the wording.

<!-- gh-comment-id:6282444249 --> @yuttapichaiARD commented on GitHub (Oct 20, 2026): Adding a data point and a third route for the docs-first step (#5305), from a Windows 11 host with REA 6.4.0, Ghidra 12.1.4 and JDK 21. Observed: `open_binary` on a Cortex-M0 ELF (ARM, with full DWARF) succeeds, then every Ghidra-routed call returns `provider_unavailable` with per-provider rejections `target_format_unsupported` ("Windows Ghidra P0 accepts PE targets only."), `unsupported_host` (Hopper) and `not_configured` (IDA). The bundled skill's recovery table maps `provider_unavailable` to "read the diagnostics and resolve the prerequisite", which has no prerequisite to resolve in this case; an agent following it loops on doctor/setup. Route that worked without WSL2: the same Ghidra install, run headless on the Windows host (`support\analyzeHeadless.bat` with `-processor ARM:LE:32:Cortex`, a pre-script and a post-script that exports decompiled C through `DecompInterface`). Two Ghidra-side issues are worth a sentence in the new doc section because they look like REA failures to an agent: 1. `Unsupported DWARF Form: DW_FORM_ref_sig8` aborts the whole DWARF import when any compile unit uses type signatures (an IAR-compiled library in my case). Rewriting form `0x20` to `0x07` (`DW_FORM_data8`, same width) in `.debug_abbrev` of a copy lets the import proceed with the remaining units' types. 2. GCC `-g3` macro data makes `DWARFMacroEnumCreator.createEnums` recurse until `StackOverflowError`, and `analyzeHeadless.bat` then blocks on `pause`. Setting the analyzer option `DWARF.Create Enums from Macros` to `NONE` in a pre-script (and redirecting stdin from `nul`) avoids it. Suggestion for the skill side, independent of the P0 decision: give the recovery table an explicit row for "every provider rejects this target format on this host" whose remedy is to stop retrying REA and continue with the documented fallback (WSL2 Ghidra, or a local headless run as above), labelling the results as non-REA evidence. Happy to turn this into a PR against the docs section once #5305 settles the wording.
Author
Owner

@avadh-pro commented on GitHub (Oct 20, 2026):

@yuttapichaiARD thanks, that's a useful data point for a different device class (Cortex-M0, not just Android arm64 like my repro) hitting the same wall, plus a working non-WSL2 fallback. A few reactions:

  1. The recovery-table gap you flag is real and separate from the P0 doc question: right now provider_unavailable with every candidate rejecting on format sends the skill into a doctor/setup loop with nothing to fix, since the failure isn't a misconfiguration. An explicit "every provider rejected this target's format on this host — stop retrying, use the documented fallback" row seems like it should land regardless of which fallback doc section it points to.

  2. Headless-on-Windows vs WSL2 as the recommended fallback: given your two gotchas (the DW_FORM_ref_sig8 abort and the -g3 macro StackOverflowError+pause hang) are both DWARF-import quirks in Ghidra itself, not Windows-specific, I'd guess WSL2 users hit the same two issues once they get far enough to import DWARF — so documenting those fixes (rewrite 0x20→0x07 in .debug_abbrev, set DWARF.Create Enums from Macros to NONE, redirect stdin from null) probably belongs in the fallback section either way, not as a reason to prefer one route over the other.

  3. My case (Android libapp.so, arm64, no DWARF) wouldn't hit either gotcha, which is a useful contrast — worth the doc section covering both "has debug info" and "stripped, strings/xrefs only" paths so it doesn't read as DWARF-only guidance.

Agree a PR is the right next step once #5305 settles the wording — happy to test the stripped-arm64 side of it when that's ready.

🤖 Generated with Claude Code

<!-- gh-comment-id:6291603437 --> @avadh-pro commented on GitHub (Oct 20, 2026): @yuttapichaiARD thanks, that's a useful data point for a different device class (Cortex-M0, not just Android arm64 like my repro) hitting the same wall, plus a working non-WSL2 fallback. A few reactions: 1. The recovery-table gap you flag is real and separate from the P0 doc question: right now `provider_unavailable` with every candidate rejecting on format sends the skill into a doctor/setup loop with nothing to fix, since the failure isn't a misconfiguration. An explicit "every provider rejected this target's format on this host — stop retrying, use the documented fallback" row seems like it should land regardless of which fallback doc section it points to. 2. Headless-on-Windows vs WSL2 as the recommended fallback: given your two gotchas (the `DW_FORM_ref_sig8` abort and the `-g3` macro `StackOverflowError`+`pause` hang) are both DWARF-import quirks in Ghidra itself, not Windows-specific, I'd guess WSL2 users hit the same two issues once they get far enough to import DWARF — so documenting those fixes (rewrite `0x20`→`0x07` in `.debug_abbrev`, set `DWARF.Create Enums from Macros` to `NONE`, redirect stdin from null) probably belongs in the fallback section either way, not as a reason to prefer one route over the other. 3. My case (Android `libapp.so`, arm64, no DWARF) wouldn't hit either gotcha, which is a useful contrast — worth the doc section covering both "has debug info" and "stripped, strings/xrefs only" paths so it doesn't read as DWARF-only guidance. Agree a PR is the right next step once #5305 settles the wording — happy to test the stripped-arm64 side of it when that's ready. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3206
No description provided.