[GH-ISSUE #8328] [Design] Recover procedure lookup using independent export evidence #6545

Open
opened 2026-11-01 21:12:06 +00:00 by bsakaguchi · 7 comments
Owner

Originally created by @morluto on GitHub (Oct 31, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/8328

Before submitting

  • I searched open and closed issues and pull requests for related reports.
  • I understand the contribution scope must be reviewed before integration.
  • This report does not include private samples or credentials.

Decision needed

When a selected provider cannot resolve a requested procedure name, should REA help the caller find independently observed, target-bound symbol candidates and explicitly hand a chosen address back to that provider? What evidence is needed before presenting any candidate as callable?

Context and evidence

On current REA a989c0e and Kuna 1.986, a synthetic arm64 Mach-O dylib had an export trie containing _audit_exported_function at 0x3b0 and _audit_exported_data at 0x4000, but its conventional symbol-table count was deliberately zeroed. dyld_info -exports and REA inspect_macho(detail: "complete") returned both exports; nm reported no symbols.

In real stdio MCP with Kuna:

  • search_procedures("audit_exported_function") returned no rows; list_procedures returned sub_3b0.
  • procedure_address rejected both the bare name and exact underscored export name. Its recovery suggested correcting the input schema; the message mentioned procedure search, which did not find this spelling.
  • procedure_pseudo_code({procedure: "0x3b0"}) succeeded and returned a sub_3b0 body adding seven.

With Ghidra 12.1.4 on the same target, procedure search and exact _audit_exported_function lookup returned 0x3b0, and address-selected pseudocode succeeded. This control does not establish cross-provider address equivalence generally. The original compiler-produced dylib, before the synthetic symbol-table transformation, supplied the function's known source and export name. The modified file was never run, its runtime signature validity was not checked, and its hash stayed unchanged. This is a constructed edge case, not a prevalence claim. Direct Kuna behavior and full fixture construction are in upstream Kuna #1349.

Expected interaction with targets

Read an explicitly selected artifact and query its selected static provider. No target execution, modification or provider switch is proposed.

Boundary details (optional)

An export name alone does not establish function identity: this same fixture exports data, and #8168 demonstrates that blanket export-to-procedure promotion is unsafe. Preserve exact artifact/slice identity, address coordinates, name spelling, aliases, collisions, reexports, source provenance and provider-specific address mapping. Missing matches or unavailable mapping remain unknown. Do not silently choose a candidate or discard the caller's selected provider. Existing inspect_macho → explicit address handoff worked here; it is not automatically a general solution for every format or rebase.

Options and tradeoffs

Compare focused recovery guidance, a bounded candidate lookup that returns independent Evidence and asks the caller to select, or a richer existing procedure-resolution contract. Any automatic join would require independently justified function and address correspondence. Avoid duplicating the entire provider API or claiming untyped exports are executable functions.

Verification available so far

I have observed results. Test both providers and relevant real formats, multiple names/addresses, same-name data, reexports, stripped exports, rebased projects and malformed/partial sources before integration. Confirm CLI/MCP and Evidence retention; the synthetic fixture does not establish shipped-binary frequency or autonomous-agent behavior.

References

Related but distinct: #8173 (cross-version matching using independent symbol evidence), #8183 (references when general name inventory is unavailable), #8168 (data symbols presented as procedures), and Kuna #1349. @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0

Export coordinates and Ghidra xrefs control

On REA #8753 working tree based on main 9ebbe67e, real Ghidra 12.1.4 and two self-built, unexecuted x86-64 libraries, rea inspect-native-exports reported ELF known_export value 0x1340 and PE known_export address 0x180001000. On the ELF, rea xrefs with the raw 0x1340 value returned an empty list, while the analyzed name and Ghidra's rebased address 0x101340 returned the same five source addresses, including the stored pointer slot 0x1033e0. On the PE, the inspected 0x180001000 address and analyzed name returned the same five sites. This is an address-coordinate control, not proof of comprehensive references or a universal conversion rule. ELF SHA-256 5b8bb1398a664530924f4cc47d0eb84927c67e1f6ed634cdd6ec7cf3b769cd09 and PE SHA-256 d07b32e13602615f31471e365946b04b92abe3ff2d484dffc4acef8fdbd3c232 stayed unchanged. The recovery guidance being tested in #8753 explicitly says to resolve or verify coordinates in the selected provider; it does not automatically map exports.

Same ELF with Kuna 1.989

On the same unexecuted ELF fixture and PR #8753 checkout, direct Kuna 1.989 xrefs --to known_export and --to 0x1340 resolved the target at 0x1340 and reported the dynamic-relocations pointer from 0x33e0. The Ghidra coordinate 0x101340 had no Kuna target name, reported decoded: false, and yielded zero data rows. REA/Kuna CLI returned empty address lists for the name and both numeric selectors: its raw Evidence identified the corresponding selected target, but REA omitted the pointer row as already tracked in #8510. The ELF digest remained 5b8bb1398a664530924f4cc47d0eb84927c67e1f6ed634cdd6ec7cf3b769cd09. This is a two-provider contrast for one fixture; it does not establish a general address conversion or imply that either empty REA result proves absence.

Checking the coordinate with existing Ghidra tools

On the same x86-64 ELF fixture and real Ghidra 12.1.4, CLI inspect-native-instruction at the raw export value 0x1340 returned status: outside-memory; at provider address 0x101340 it returned status: decoded and mnemonic PUSH. inspect-native-load-image reported independent verification status: unsupported for ELF, but retained Ghidra's observed image_base: 0x100000 and .text mapping starting at 0x101340. These observations can help an analyst detect this fixture's coordinate mismatch; they do not constitute verified ELF load-image equivalence or a general conversion rule. CLI search --kind procedures known_export also identified the analyzed function at 0x101340; default string search did not identify that function. Target SHA-256 remained 5b8bb1398a664530924f4cc47d0eb84927c67e1f6ed634cdd6ec7cf3b769cd09 and it was never executed.

Originally created by @morluto on GitHub (Oct 31, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8328 ### Before submitting - [x] I searched open and closed issues and pull requests for related reports. - [x] I understand the contribution scope must be reviewed before integration. - [x] This report does not include private samples or credentials. ### Decision needed When a selected provider cannot resolve a requested procedure name, should REA help the caller find independently observed, target-bound symbol candidates and explicitly hand a chosen address back to that provider? What evidence is needed before presenting any candidate as callable? ### Context and evidence On current REA `a989c0e` and Kuna 1.986, a synthetic arm64 Mach-O dylib had an export trie containing `_audit_exported_function` at `0x3b0` and `_audit_exported_data` at `0x4000`, but its conventional symbol-table count was deliberately zeroed. `dyld_info -exports` and REA `inspect_macho(detail: "complete")` returned both exports; `nm` reported no symbols. In real stdio MCP with Kuna: - `search_procedures("audit_exported_function")` returned no rows; `list_procedures` returned `sub_3b0`. - `procedure_address` rejected both the bare name and exact underscored export name. Its recovery suggested correcting the input schema; the message mentioned procedure search, which did not find this spelling. - `procedure_pseudo_code({procedure: "0x3b0"})` succeeded and returned a `sub_3b0` body adding seven. With Ghidra 12.1.4 on the same target, procedure search and exact `_audit_exported_function` lookup returned `0x3b0`, and address-selected pseudocode succeeded. This control does not establish cross-provider address equivalence generally. The original compiler-produced dylib, before the synthetic symbol-table transformation, supplied the function's known source and export name. The modified file was never run, its runtime signature validity was not checked, and its hash stayed unchanged. This is a constructed edge case, not a prevalence claim. Direct Kuna behavior and full fixture construction are in [upstream Kuna #1349](https://github.com/Noelo-Lab/kuna/issues/1349). ### Expected interaction with targets Read an explicitly selected artifact and query its selected static provider. No target execution, modification or provider switch is proposed. ### Boundary details (optional) An export name alone does not establish function identity: this same fixture exports data, and #8168 demonstrates that blanket export-to-procedure promotion is unsafe. Preserve exact artifact/slice identity, address coordinates, name spelling, aliases, collisions, reexports, source provenance and provider-specific address mapping. Missing matches or unavailable mapping remain unknown. Do not silently choose a candidate or discard the caller's selected provider. Existing `inspect_macho` → explicit address handoff worked here; it is not automatically a general solution for every format or rebase. ### Options and tradeoffs Compare focused recovery guidance, a bounded candidate lookup that returns independent Evidence and asks the caller to select, or a richer existing procedure-resolution contract. Any automatic join would require independently justified function and address correspondence. Avoid duplicating the entire provider API or claiming untyped exports are executable functions. ### Verification available so far I have observed results. Test both providers and relevant real formats, multiple names/addresses, same-name data, reexports, stripped exports, rebased projects and malformed/partial sources before integration. Confirm CLI/MCP and Evidence retention; the synthetic fixture does not establish shipped-binary frequency or autonomous-agent behavior. ### References Related but distinct: #8173 (cross-version matching using independent symbol evidence), #8183 (references when general name inventory is unavailable), #8168 (data symbols presented as procedures), and [Kuna #1349](https://github.com/Noelo-Lab/kuna/issues/1349). @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 ### Export coordinates and Ghidra xrefs control On REA #8753 working tree based on main `9ebbe67e`, real Ghidra 12.1.4 and two self-built, unexecuted x86-64 libraries, `rea inspect-native-exports` reported ELF `known_export` value `0x1340` and PE `known_export` address `0x180001000`. On the ELF, `rea xrefs` with the raw `0x1340` value returned an empty list, while the analyzed name and Ghidra's rebased address `0x101340` returned the same five source addresses, including the stored pointer slot `0x1033e0`. On the PE, the inspected `0x180001000` address and analyzed name returned the same five sites. This is an address-coordinate control, not proof of comprehensive references or a universal conversion rule. ELF SHA-256 `5b8bb1398a664530924f4cc47d0eb84927c67e1f6ed634cdd6ec7cf3b769cd09` and PE SHA-256 `d07b32e13602615f31471e365946b04b92abe3ff2d484dffc4acef8fdbd3c232` stayed unchanged. The recovery guidance being tested in #8753 explicitly says to resolve or verify coordinates in the selected provider; it does not automatically map exports. ### Same ELF with Kuna 1.989 On the same unexecuted ELF fixture and PR #8753 checkout, direct Kuna 1.989 `xrefs --to known_export` and `--to 0x1340` resolved the target at `0x1340` and reported the `dynamic-relocations` pointer from `0x33e0`. The Ghidra coordinate `0x101340` had no Kuna target name, reported `decoded: false`, and yielded zero data rows. REA/Kuna CLI returned empty address lists for the name and both numeric selectors: its raw Evidence identified the corresponding selected target, but REA omitted the pointer row as already tracked in #8510. The ELF digest remained `5b8bb1398a664530924f4cc47d0eb84927c67e1f6ed634cdd6ec7cf3b769cd09`. This is a two-provider contrast for one fixture; it does not establish a general address conversion or imply that either empty REA result proves absence. ### Checking the coordinate with existing Ghidra tools On the same x86-64 ELF fixture and real Ghidra 12.1.4, CLI `inspect-native-instruction` at the raw export value `0x1340` returned `status: outside-memory`; at provider address `0x101340` it returned `status: decoded` and mnemonic `PUSH`. `inspect-native-load-image` reported independent verification `status: unsupported` for ELF, but retained Ghidra's observed `image_base: 0x100000` and `.text` mapping starting at `0x101340`. These observations can help an analyst detect this fixture's coordinate mismatch; they do not constitute verified ELF load-image equivalence or a general conversion rule. CLI `search --kind procedures known_export` also identified the analyzed function at `0x101340`; default string search did not identify that function. Target SHA-256 remained `5b8bb1398a664530924f4cc47d0eb84927c67e1f6ed634cdd6ec7cf3b769cd09` and it was never executed.
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

Reference-finding follow-up on a second synthetic export-trie-only Mach-O, with an actual source-authored direct caller as well as exported data. dyld_info -exports and REA inspect_macho reported _audit_exported_function at 0x3a8, _audit_caller at 0x3c0, and _audit_exported_data at 0x4000; nm reported no symbols. Independent otool on the original pre-transformation dylib showed bl at 0x3d4 to the function, followed by address formation/load of the data.

On current REA a989c0e with real Kuna 1.986, searching for and resolving the function's export name failed as in the original report. A caller who explicitly chose the inspect_macho function candidate's address could then obtain xrefs(0x3a8) = [0x3d4], procedure_callers(0x3a8) = [0x3c0], caller assembly containing the direct branch, and a reached trace_call_path(0x3c0, 0x3a8). Ghidra 12.1.4 resolved the exact name and also found the direct site and caller. The separate export for data reinforces that the selection requires more than an export name. Kuna's data xref was the address-forming instruction 0x3d8; Ghidra reported 0x3dc; those observations have different semantics and should not be silently equated.

This is an explicit multi-call, same-target handoff with separate Evidence records, not proof that REA automatically connects the export Evidence to the xref, that all references were found, or that the function executes. The transformed file's runtime validity was not checked; its digest was unchanged and it was not run. A task-oriented recovery could preserve the selected source Evidence and ambiguity without replacing existing address-based calls.

<!-- gh-comment-id:6545109560 --> @morluto commented on GitHub (Oct 31, 2026): Reference-finding follow-up on a second synthetic export-trie-only Mach-O, with an actual source-authored direct caller as well as exported data. `dyld_info -exports` and REA `inspect_macho` reported `_audit_exported_function` at `0x3a8`, `_audit_caller` at `0x3c0`, and `_audit_exported_data` at `0x4000`; `nm` reported no symbols. Independent `otool` on the original pre-transformation dylib showed `bl` at `0x3d4` to the function, followed by address formation/load of the data. On current REA `a989c0e` with real Kuna 1.986, searching for and resolving the function's export name failed as in the original report. A caller who explicitly chose the `inspect_macho` function candidate's address could then obtain `xrefs(0x3a8) = [0x3d4]`, `procedure_callers(0x3a8) = [0x3c0]`, caller assembly containing the direct branch, and a reached `trace_call_path(0x3c0, 0x3a8)`. Ghidra 12.1.4 resolved the exact name and also found the direct site and caller. The separate export for data reinforces that the selection requires more than an export name. Kuna's data xref was the address-forming instruction `0x3d8`; Ghidra reported `0x3dc`; those observations have different semantics and should not be silently equated. This is an explicit multi-call, same-target handoff with separate Evidence records, not proof that REA automatically connects the export Evidence to the xref, that all references were found, or that the function executes. The transformed file's runtime validity was not checked; its digest was unchanged and it was not run. A task-oriented recovery could preserve the selected source Evidence and ambiguity without replacing existing address-based calls.
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

The same name-to-address handoff now reproduces without the hand-edited symbol-table fixture. I compiled the three-symbol dylib from the previous comment, made a separate copy and ran Apple's documented strip -N. nm reported no symbols, dyld_info -exports retained both function names and the data name, and codesign --verify exited 0 for the ad-hoc linker signature.

On current REA a989c0e with real Kuna 1.986, inspect_macho exposed the exported function at 0x3a8, name search/lookup missed it, and explicit address xrefs found its direct call site at 0x3d4; caller lookup and path tracing also succeeded. Ghidra 12.1.4 resolved the exact exported spelling on the same stripped file. The data export remained distinct, and the stripped target's hash did not change during analysis. The file was not executed; a valid signature check does not establish runtime behavior or prevalence. Full reproducible compiler and strip -N commands are in Kuna #1349.

<!-- gh-comment-id:6545131299 --> @morluto commented on GitHub (Oct 31, 2026): The same name-to-address handoff now reproduces without the hand-edited symbol-table fixture. I compiled the three-symbol dylib from the previous comment, made a separate copy and ran Apple's documented `strip -N`. `nm` reported no symbols, `dyld_info -exports` retained both function names and the data name, and `codesign --verify` exited 0 for the ad-hoc linker signature. On current REA `a989c0e` with real Kuna 1.986, `inspect_macho` exposed the exported function at `0x3a8`, name search/lookup missed it, and explicit address xrefs found its direct call site at `0x3d4`; caller lookup and path tracing also succeeded. Ghidra 12.1.4 resolved the exact exported spelling on the same stripped file. The data export remained distinct, and the stripped target's hash did not change during analysis. The file was not executed; a valid signature check does not establish runtime behavior or prevalence. Full reproducible compiler and `strip -N` commands are in [Kuna #1349](https://github.com/Noelo-Lab/kuna/issues/1349#issuecomment-6545127851).
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

Shipped-artifact follow-up: on this host, Xcode 26.5 (17F42)'s universal libSwiftToolsSupport.dylib contains 2,810 arm64 export records according to dyld_info, while its external-defined nlist range has five entries. One export, _$s10TSCUtility10BuildFlagsV011cxxCompilerC0SaySSGvg, is at 0x6d868; an independent static instruction listing places code there.

REA a989c0e explicitly selected with Kuna 1.986 refused to open the universal source because this provider does not yet support a selected universal slice (#8193). I used lipo -thin arm64 to make a separate caller-owned file; its bytes matched the selected source slice exactly. On that distinct target, inspect_macho(detail: "summary") retained the complete inspection, and the first inspect_analysis_view export page contained the named row and address. search_procedures returned no matching name and procedure_address rejected it with generic schema recovery; explicitly passing the selected address to procedure_pseudo_code succeeded as sub_6d868. The export page itself marked the source inventory non-exhaustive, and the handoff did not automatically link the separate Evidence records.

Direct Kuna on the original universal file with explicit --slice arm64 also missed the name and decompiled the address; upstream details and digests are in Kuna #1349. Source and derivative hashes remained unchanged, neither was executed, and no full-corpus prevalence or runtime behavior is claimed. This is a bounded manual workflow on one symbol; it does not make all exported names callable or establish generic FAT-to-provider coordinate correspondence.

<!-- gh-comment-id:6545216992 --> @morluto commented on GitHub (Oct 31, 2026): Shipped-artifact follow-up: on this host, Xcode 26.5 (17F42)'s universal `libSwiftToolsSupport.dylib` contains 2,810 arm64 export records according to `dyld_info`, while its external-defined nlist range has five entries. One export, `_$s10TSCUtility10BuildFlagsV011cxxCompilerC0SaySSGvg`, is at `0x6d868`; an independent static instruction listing places code there. REA `a989c0e` explicitly selected with Kuna 1.986 refused to open the universal source because this provider does not yet support a selected universal slice (#8193). I used `lipo -thin arm64` to make a separate caller-owned file; its bytes matched the selected source slice exactly. On that distinct target, `inspect_macho(detail: "summary")` retained the complete inspection, and the first `inspect_analysis_view` export page contained the named row and address. `search_procedures` returned no matching name and `procedure_address` rejected it with generic schema recovery; explicitly passing the selected address to `procedure_pseudo_code` succeeded as `sub_6d868`. The export page itself marked the source inventory non-exhaustive, and the handoff did not automatically link the separate Evidence records. Direct Kuna on the original universal file with explicit `--slice arm64` also missed the name and decompiled the address; upstream details and digests are in [Kuna #1349](https://github.com/Noelo-Lab/kuna/issues/1349#issuecomment-6545214285). Source and derivative hashes remained unchanged, neither was executed, and no full-corpus prevalence or runtime behavior is claimed. This is a bounded manual workflow on one symbol; it does not make all exported names callable or establish generic FAT-to-provider coordinate correspondence.
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

Follow-up on the same shipped Xcode library and explicit arm64 derivative: an exact requested export, _$ss6ResultO8TSCBasics5Error_pRs_rlE6tryMapyAByqd__sAD_pGqd__xKXElF, appeared at 0x46518 on page 44 of the retained inspect_macho exports view using the default limit of 64. On REA a989c0e with Kuna 1.986, search_procedures returned no matches and procedure_address rejected the name; explicitly selecting the export address produced pseudocode. An attempted name filter on the Mach-O view was rejected as an unknown argument. The view currently supports offset and limit, and requesting all 2,810 retained export rows in one call also worked.

This shows a concrete navigation tradeoff for the candidate-lookup option in this issue: for a known name, the caller can page through the inventory or retrieve it all, but the retained view cannot return just the matching candidate. The page's exhaustion applies to the retained view; its source inventory was marked non-exhaustive. The example does not establish autonomous-agent behavior, runtime reachability, or that arbitrary exports are procedures. Source and derivative hashes were unchanged, and neither was executed.

<!-- gh-comment-id:6545251441 --> @morluto commented on GitHub (Oct 31, 2026): Follow-up on the same shipped Xcode library and explicit arm64 derivative: an exact requested export, `_$ss6ResultO8TSCBasics5Error_pRs_rlE6tryMapyAByqd__sAD_pGqd__xKXElF`, appeared at `0x46518` on page 44 of the retained `inspect_macho` exports view using the default limit of 64. On REA `a989c0e` with Kuna 1.986, `search_procedures` returned no matches and `procedure_address` rejected the name; explicitly selecting the export address produced pseudocode. An attempted `name` filter on the Mach-O view was rejected as an unknown argument. The view currently supports offset and limit, and requesting all 2,810 retained export rows in one call also worked. This shows a concrete navigation tradeoff for the candidate-lookup option in this issue: for a known name, the caller can page through the inventory or retrieve it all, but the retained view cannot return just the matching candidate. The page's exhaustion applies to the retained view; its source inventory was marked non-exhaustive. The example does not establish autonomous-agent behavior, runtime reachability, or that arbitrary exports are procedures. Source and derivative hashes were unchanged, and neither was executed.
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

Existing-workflow control for the candidate-lookup options: on REA a989c0e, a source-built x86-64 ELF library with two audit_transform dynamic-symbol rows (AUDIT_1 at 0x1334, hidden version; AUDIT_2 at 0x133a, default version) was independently checked with llvm-readelf. inspect_native_exports(detail:"summary") followed by inspect_analysis_view with collection:"exports", names:["audit_transform"] returned both versioned rows. Matching-row pagination preserved their distinct original indices and a source Evidence bundle export/import reproduced the filtered view without opening a provider. A query for the display spelling audit_transform@AUDIT_1 returned no rows; the contract matches ELF source names and exposes the version separately. No blanket splitting on @ is proposed, since a spelling needs its own identity semantics.

This existing PE/ELF view is a useful model for evaluating a bounded Mach-O lookup: retain parent identity and coverage, distinguish aliases and versions, and allow explicit selection. It does not by itself establish that the static export is callable or that coordinates map to a selected provider. On this exact library both Ghidra and Kuna refused the unversioned procedure name as ambiguous, and Ghidra's analysis addresses differed from ELF values. The target was not executed or changed. The separate Kuna search/alias discrepancy observed during this control is tracked in #8330.

<!-- gh-comment-id:6545303177 --> @morluto commented on GitHub (Oct 31, 2026): Existing-workflow control for the candidate-lookup options: on REA `a989c0e`, a source-built x86-64 ELF library with two `audit_transform` dynamic-symbol rows (`AUDIT_1` at `0x1334`, hidden version; `AUDIT_2` at `0x133a`, default version) was independently checked with `llvm-readelf`. `inspect_native_exports(detail:"summary")` followed by `inspect_analysis_view` with `collection:"exports", names:["audit_transform"]` returned both versioned rows. Matching-row pagination preserved their distinct original indices and a source Evidence bundle export/import reproduced the filtered view without opening a provider. A query for the display spelling `audit_transform@AUDIT_1` returned no rows; the contract matches ELF source names and exposes the version separately. No blanket splitting on `@` is proposed, since a spelling needs its own identity semantics. This existing PE/ELF view is a useful model for evaluating a bounded Mach-O lookup: retain parent identity and coverage, distinguish aliases and versions, and allow explicit selection. It does not by itself establish that the static export is callable or that coordinates map to a selected provider. On this exact library both Ghidra and Kuna refused the unversioned procedure name as ambiguous, and Ghidra's analysis addresses differed from ELF values. The target was not executed or changed. The separate Kuna search/alias discrepancy observed during this control is tracked in #8330.
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

I tested a disposable local design experiment on current main d54a4661d: exact source-name selection for the existing retained Mach-O exports view, using the same bounded matching-row selection primitive as the native PE/ELF exports view. This is not a production patch or a proposal to auto-select a function.

  • On the previously described arm64 derivative of the shipped Xcode library, one filtered inspect_analysis_view request found the exact requested export at 0x46518, with original source index 2804. Looking up that index in the unfiltered view returned the identical original row. The earlier manual walk needed 44 pages for this name after obtaining the same kind of parent inspection; this is a call-count comparison, not a timing or token benchmark.
  • Two selected names paged in source order with limit 1 and preserved their original indices. A duplicate requested name did not duplicate a row; an empty name selection and a nonexistent name returned no rows. The source remained source_exhaustive: false, and the incomplete-inventory warning remained present even for an empty page. Page exhaustion is not evidence of absence from the artifact.
  • On a separately built arm64 Mach-O, dyld_info -exports reported an explicitly reexported function, a local function and an exported data symbol. The filtered view retained three separate original rows: the reexport had reexport: true, source audit-dependency, and a null local address; the data and function remained unclassified export rows. Neither artifact was executed or changed.
  • SDK-validated stdio MCP calls passed with compact and full output profiles. Exporting the parent Evidence and importing it in a fresh, targetless MCP server reproduced the filtered view; rea inspect-analysis-view --evidence-bundle ... returned the same normalized view. Existing Mach-O view source tests passed (10 tests); they do not constitute new production regression coverage.

The experiment exposes contract work rather than settling it: it admits names in the shared request shape and rejects non-export facets at runtime, and adds source indices only to filtered rows. A real design should make facet applicability and source-row identity clear in the advertised schema without relying on that inconsistent prototype. It still needs malformed/duplicate source rows, universal slices, non-UTF-8 identity, alias collisions and CLI/MCP schema-client coverage. Neither the selected export nor its address was promoted to a callable function, and provider coordinate correspondence remains a separate question.

<!-- gh-comment-id:6547683907 --> @morluto commented on GitHub (Oct 31, 2026): I tested a **disposable local design experiment** on current main `d54a4661d`: exact source-name selection for the existing retained Mach-O exports view, using the same bounded matching-row selection primitive as the native PE/ELF exports view. This is not a production patch or a proposal to auto-select a function. - On the previously described arm64 derivative of the shipped Xcode library, one filtered `inspect_analysis_view` request found the exact requested export at `0x46518`, with original source index 2804. Looking up that index in the unfiltered view returned the identical original row. The earlier manual walk needed 44 pages for this name after obtaining the same kind of parent inspection; this is a call-count comparison, not a timing or token benchmark. - Two selected names paged in source order with limit 1 and preserved their original indices. A duplicate requested name did not duplicate a row; an empty name selection and a nonexistent name returned no rows. The source remained `source_exhaustive: false`, and the incomplete-inventory warning remained present even for an empty page. Page exhaustion is not evidence of absence from the artifact. - On a separately built arm64 Mach-O, `dyld_info -exports` reported an explicitly reexported function, a local function and an exported data symbol. The filtered view retained three separate original rows: the reexport had `reexport: true`, source `audit-dependency`, and a null local address; the data and function remained unclassified export rows. Neither artifact was executed or changed. - SDK-validated stdio MCP calls passed with compact and full output profiles. Exporting the parent Evidence and importing it in a fresh, targetless MCP server reproduced the filtered view; `rea inspect-analysis-view --evidence-bundle ...` returned the same normalized view. Existing Mach-O view source tests passed (10 tests); they do not constitute new production regression coverage. The experiment exposes contract work rather than settling it: it admits `names` in the shared request shape and rejects non-export facets at runtime, and adds source indices only to filtered rows. A real design should make facet applicability and source-row identity clear in the advertised schema without relying on that inconsistent prototype. It still needs malformed/duplicate source rows, universal slices, non-UTF-8 identity, alias collisions and CLI/MCP schema-client coverage. Neither the selected export nor its address was promoted to a callable function, and provider coordinate correspondence remains a separate question.
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

Rebased-project control for the proposed export-to-provider handoff, on REA main d54a4661d:

I built an unexecuted arm64 Mach-O dylib with two distinct exported functions, aligned 4096 bytes apart. Independent dyld_info -exports and nm reported _audit_first at 0x1000 and _audit_second at 0x2000; the functions add 11 and 22 respectively. Its __TEXT has preferred VM address and file offset zero, so in this specific file the second function's export VM address also corresponds to source-file offset 0x2000.

After importing it into a disposable Ghidra 12.1.4 project, I deliberately changed that project's image base from 0 to the page-aligned value 0x1000 before opening it in REA. Ghidra's project then located _audit_first at 0x2000 and _audit_second at 0x3000.

  • REA inspect_macho still returned the file-derived _audit_second address 0x2000. In the selected Ghidra project, passing that bare value to procedure_pseudo_code succeeded but returned _audit_first; passing _audit_second or the provider address 0x3000 returned the intended function.
  • After independently establishing the file mapping, procedure_pseudo_code({procedure:"file-offset:0x2000"}) returned _audit_second. Its raw_result.selection records source offset 8192 and mapped/provider address 0x3000. address_to_file_offset separately mapped 0x2000 to 4096 and 0x3000 to 8192. inspect_native_load_image retained a matching measured __text source mapping and image base, while reporting status: unsupported for independent Mach-O verification.
  • The equivalent CLI rea decompile ... 0x2000 and rea decompile ... --file-offset 0x2000 gave the same respective bodies and Evidence IDs as MCP. With a fresh Ghidra import and with fresh Kuna, bare 0x2000 instead selected _audit_second on this same file.

This strengthens the need to keep source VM address, source-file offset, and provider analysis address distinct when presenting or handing off an export candidate. The offset happens to equal the source VM value in this fixture; do not generalize that equality or treat all exports as code. The selected project and target SHA-256s remained unchanged during all REA calls, the target was not executed, and selected-project memory need not be byte-identical to the file. The deliberately constructed overlapping coordinates show a possible failure mode, not its prevalence or an automatic REA handoff; the manual bare-address request obeyed the existing address contract.

<!-- gh-comment-id:6547720199 --> @morluto commented on GitHub (Oct 31, 2026): Rebased-project control for the proposed export-to-provider handoff, on REA main `d54a4661d`: I built an unexecuted arm64 Mach-O dylib with two distinct exported functions, aligned 4096 bytes apart. Independent `dyld_info -exports` and `nm` reported `_audit_first` at `0x1000` and `_audit_second` at `0x2000`; the functions add 11 and 22 respectively. Its `__TEXT` has preferred VM address and file offset zero, so in this *specific* file the second function's export VM address also corresponds to source-file offset `0x2000`. After importing it into a disposable Ghidra 12.1.4 project, I deliberately changed that project's image base from 0 to the page-aligned value `0x1000` before opening it in REA. Ghidra's project then located `_audit_first` at `0x2000` and `_audit_second` at `0x3000`. - REA `inspect_macho` still returned the file-derived `_audit_second` address `0x2000`. In the selected Ghidra project, passing that bare value to `procedure_pseudo_code` **succeeded but returned `_audit_first`**; passing `_audit_second` or the provider address `0x3000` returned the intended function. - After independently establishing the file mapping, `procedure_pseudo_code({procedure:"file-offset:0x2000"})` returned `_audit_second`. Its `raw_result.selection` records source offset 8192 and mapped/provider address `0x3000`. `address_to_file_offset` separately mapped `0x2000` to 4096 and `0x3000` to 8192. `inspect_native_load_image` retained a matching measured `__text` source mapping and image base, while reporting `status: unsupported` for independent Mach-O verification. - The equivalent CLI `rea decompile ... 0x2000` and `rea decompile ... --file-offset 0x2000` gave the same respective bodies and Evidence IDs as MCP. With a fresh Ghidra import and with fresh Kuna, bare `0x2000` instead selected `_audit_second` on this same file. This strengthens the need to keep **source VM address, source-file offset, and provider analysis address distinct** when presenting or handing off an export candidate. The offset happens to equal the source VM value in this fixture; do not generalize that equality or treat all exports as code. The selected project and target SHA-256s remained unchanged during all REA calls, the target was not executed, and selected-project memory need not be byte-identical to the file. The deliberately constructed overlapping coordinates show a possible failure mode, not its prevalence or an automatic REA handoff; the manual bare-address request obeyed the existing address contract.
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#6545
No description provided.