[GH-ISSUE #8330] [Bug] Procedure search omits secondary names accepted by exact lookup #6548

Closed
opened 2026-11-01 21:12:08 +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/8330

Originally assigned to: @kaoru0822-kitauji on GitHub.

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Native analysis or decompilation

Observed behavior

With a source-built ELF and real Kuna 1.986, search_procedures({pattern:"audit_transform"}) returned [], although procedure_address({procedure:"audit_transform"}) reported two matching entries. A unique alias showed the same mismatch: search for sub_1334 returned [], while exact procedure lookup resolved it to 0x1334. Literal and regex search both missed the shared alias. Primary-name searches found the two procedures.

Reproduction

On a macOS arm64 host with clang and lld, build a disposable x86-64 shared object:

.text
.globl audit_v1
.type audit_v1,@function
audit_v1: mov $1,%eax; ret
.size audit_v1,.-audit_v1
.globl audit_v2
.type audit_v2,@function
audit_v2: mov $2,%eax; ret
.size audit_v2,.-audit_v2
.symver audit_v1,audit_transform@AUDIT_1
.symver audit_v2,audit_transform@@AUDIT_2

Use version script AUDIT_1 { global: audit_transform; local: *; }; AUDIT_2 { global: audit_transform; } AUDIT_1;, clang -target x86_64-unknown-linux-gnu -c versions.s -o versions.o, and ld.lld -shared --version-script=versions.map versions.o -o libversions.so. Open it in stdio MCP with open_binary({path,provider_id:"kuna"}), then call the searches and lookups above. Direct kuna functions libversions.so --json reported primary names audit_v1/audit_v2 and audit_transform among both entries' aliases. Exact addresses may depend on the linker. A fresh cache and connection reproduced the result.

Expected behavior

The advertised search_procedures contract says it searches every analyzed procedure name and results are complete. Decide whether resolvable provider aliases belong in that search, and make the returned coverage and documentation accurate. If aliases are included, retain which name matched, avoid collapsing different entries with the same alias, and preserve their primary names and addresses. Do not infer that every alias is a separate procedure.

Impact and scope

An agent relying on a negative search cannot discover a name that REA's exact lookup accepts; the inventory output used here does not expose those aliases. Exact lookup of the shared alias correctly refuses ambiguity and gives both addresses; selecting an address decompiled the intended distinct bodies. This is a single source-built ELF on one host and one Kuna release; other providers, formats, CLI and autonomous agents were not checked for this particular behavior.

REA version

a989c0e458c91af177e097abd7be0fd021b0401d

Runtime and platform

Node 24.22.1, macOS 26.3 arm64, Kuna 1.986, stdio MCP compact schema profile.

Target and artifact context

Source-built x86-64 ELF shared object; SHA-256 32b6615f3ff75eb25ae9b26bee9cc43f94f5d55896aa69dc670de2c47dca64c6. The static analysis did not execute or modify it.

Interface

MCP

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

list_procedures returned audit_v1 at 0x1334 and audit_v2 at 0x133a; name search returned an empty array for the alias. Exact shared-name lookup returned audit_transform names 2 Kuna entries (0x1334, 0x133a); select one by address. inspect_native_exports independently returned two audit_transform rows with versions AUDIT_1 and AUDIT_2 at those source ELF values. That format evidence is separate from provider inventory and does not prove runtime binding.

Analysis or suspected cause

Source-derived explanation at this revision: KunaSessionClient.#procedureList filters each inventory row's primary name; its #index indexes both name and aliases for exact selection. Direct Kuna JSON exposes the aliases, so this reproduction concerns REA's search projection, not a request for an upstream Kuna fix.

Additional context

Related to candidate name and address handoff in #8183 and cross-image selection in #8221. Suggested validation: real-provider MCP search and exact lookup for unique and shared aliases; negative and primary-name controls; regex and literal search; document omission and duplicate semantics; preserve adapter-specific coverage and avoid implying that all provider names are executable or exhaustive.

@gensokyo-dev @kaoru0822-kitauji @N0zoM1z0

Real-provider control of PR #8520

On exact PR head c37e216f95b3fbc90ed2785c05c1c24e377995fd, real Kuna 1.988 and Ghidra 12.1.4/JDK 21 were exercised through SDK stdio MCP on a source-built x86-64 ELF with audit_primary and audit_alias at the same entry and a direct caller. In both full and compact profiles, literal and anchored case-sensitive regex searches returned one procedure for each name. Kuna chose audit_primary as its primary and returned matched_aliases: [audit_alias] for the alias search; Ghidra chose audit_alias as primary and returned matched_aliases: [audit_primary] for the other search. Exact lookup of either name selected the same provider entry; a negative search returned no rows.

trace_feature for the previously missing secondary name included the procedure and its references for both providers. Kuna retained one owner-unavailable unknown; Ghidra resolved the direct caller and also returned other static references. Successful responses validated against the fetched advertised output schemas using Ajv 2020 with strict and format checks disabled. The fixture SHA-256 01edfcb21b1bd4cd1f2c92ecf7dedfd1b9f3828c7d6a5185fef25a8e088e8f9e remained unchanged; it was not executed. This is a one-host, one-fixture control; the separate shared-alias and offline controls below cover a different fixture. A separate namespace control is recorded below; performance and cancellation were not covered.

Shared-alias and offline handoff control

At the same #8520 head, real Kuna 1.988 and Ghidra 12.1.4 MCP in both compact and full profiles analyzed a separate x86-64 ELF where audit_transform names two versioned entries and audit_caller calls each. Literal and anchored case-sensitive regex searches returned two distinct entries with either provider. Kuna returned primary names audit_v1 and audit_v2, each with matched_aliases: [audit_transform]; Ghidra returned audit_transform as each primary name. Exact lookup refused the shared name and supplied both candidate addresses. trace_feature retained both procedures; Kuna reported two references and two owner-unavailable unknowns, while Ghidra returned four static references and no residual unknowns.

A summary search followed by the selected matched_aliases page was exported, imported into a fresh target-free MCP server, and reproduced the same normalized page for each provider and schema profile. Successful responses validated against the fetched advertised schemas using Ajv 2020 with strict and format checks disabled. The fixture SHA-256 1f158b0ea39494fcd3424844a1b02511325c567e073fbc0ed045e0bef5f0abfe and exported bundle bytes remained unchanged; the target was not executed. The first test-harness run encountered an Ajv duplicate schema ID during reconnection, and an initial retry encountered an existing output file; a corrected harness with fresh validator instances and new bundle paths completed all four cases. This is one host and one fixture, not general provider completeness or runtime binding verification.

Real namespace and leaf-name control

On the same #8520 head and real Ghidra 12.1.4/JDK 21, a source-built macOS arm64 fixture with C++ ABI symbols for alpha::same, beta::same, and outer::inner::same produced three distinct Ghidra procedure entries. Exact lookup same refused ambiguity and listed all three addresses; anchored regex search ^same$ returned all three qualified primary names in both full and compact MCP profiles. Each qualified lookup and each returned-address decompilation succeeded. On the separate #8509 baseline 7f344af1aa0a78fd4e331dbbc9c30d38e4cfb796, the same Ghidra search returned no rows while exact same lookup was ambiguous.

Real Kuna 1.988 on the same fixture did not accept same as an exact selector, and its anchored ^same$ returned no rows in either version; its literal same search found the three qualified primary names, and each qualified exact lookup succeeded. This is an observed provider-specific selection rule, not evidence that Kuna promised leaf-name lookup. Successful output validated against the fetched advertised schemas using Ajv 2020 with strict and formats disabled. The fixture SHA-256 ca042de0b9835367a14718854e861df275bfbd075570d9ca48d97dafd4c3165d was unchanged and it was never executed. One generated Mach-O and host do not establish general namespace or demangler coverage.

Originally created by @morluto on GitHub (Oct 31, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8330 Originally assigned to: @kaoru0822-kitauji on GitHub. ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Native analysis or decompilation ### Observed behavior With a source-built ELF and real Kuna 1.986, `search_procedures({pattern:"audit_transform"})` returned `[]`, although `procedure_address({procedure:"audit_transform"})` reported two matching entries. A unique alias showed the same mismatch: search for `sub_1334` returned `[]`, while exact procedure lookup resolved it to `0x1334`. Literal and regex search both missed the shared alias. Primary-name searches found the two procedures. ### Reproduction On a macOS arm64 host with clang and lld, build a disposable x86-64 shared object: ```asm .text .globl audit_v1 .type audit_v1,@function audit_v1: mov $1,%eax; ret .size audit_v1,.-audit_v1 .globl audit_v2 .type audit_v2,@function audit_v2: mov $2,%eax; ret .size audit_v2,.-audit_v2 .symver audit_v1,audit_transform@AUDIT_1 .symver audit_v2,audit_transform@@AUDIT_2 ``` Use version script `AUDIT_1 { global: audit_transform; local: *; }; AUDIT_2 { global: audit_transform; } AUDIT_1;`, `clang -target x86_64-unknown-linux-gnu -c versions.s -o versions.o`, and `ld.lld -shared --version-script=versions.map versions.o -o libversions.so`. Open it in stdio MCP with `open_binary({path,provider_id:"kuna"})`, then call the searches and lookups above. Direct `kuna functions libversions.so --json` reported primary names `audit_v1`/`audit_v2` and `audit_transform` among both entries' aliases. Exact addresses may depend on the linker. A fresh cache and connection reproduced the result. ### Expected behavior The advertised `search_procedures` contract says it searches every analyzed procedure name and results are complete. Decide whether resolvable provider aliases belong in that search, and make the returned coverage and documentation accurate. If aliases are included, retain which name matched, avoid collapsing different entries with the same alias, and preserve their primary names and addresses. Do not infer that every alias is a separate procedure. ### Impact and scope An agent relying on a negative search cannot discover a name that REA's exact lookup accepts; the inventory output used here does not expose those aliases. Exact lookup of the shared alias correctly refuses ambiguity and gives both addresses; selecting an address decompiled the intended distinct bodies. This is a single source-built ELF on one host and one Kuna release; other providers, formats, CLI and autonomous agents were not checked for this particular behavior. ### REA version `a989c0e458c91af177e097abd7be0fd021b0401d` ### Runtime and platform Node 24.22.1, macOS 26.3 arm64, Kuna 1.986, stdio MCP compact schema profile. ### Target and artifact context Source-built x86-64 ELF shared object; SHA-256 `32b6615f3ff75eb25ae9b26bee9cc43f94f5d55896aa69dc670de2c47dca64c6`. The static analysis did not execute or modify it. ### Interface MCP ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence `list_procedures` returned `audit_v1` at `0x1334` and `audit_v2` at `0x133a`; name search returned an empty array for the alias. Exact shared-name lookup returned `audit_transform names 2 Kuna entries (0x1334, 0x133a); select one by address.` `inspect_native_exports` independently returned two `audit_transform` rows with versions `AUDIT_1` and `AUDIT_2` at those source ELF values. That format evidence is separate from provider inventory and does not prove runtime binding. ### Analysis or suspected cause Source-derived explanation at this revision: [`KunaSessionClient.#procedureList`](https://github.com/morluto/rea/blob/a989c0e458c91af177e097abd7be0fd021b0401d/src/kuna/KunaSessionClient.ts#L789) filters each inventory row's primary `name`; its [`#index`](https://github.com/morluto/rea/blob/a989c0e458c91af177e097abd7be0fd021b0401d/src/kuna/KunaSessionClient.ts#L1390) indexes both `name` and `aliases` for exact selection. Direct Kuna JSON exposes the aliases, so this reproduction concerns REA's search projection, not a request for an upstream Kuna fix. ### Additional context Related to candidate name and address handoff in #8183 and cross-image selection in #8221. Suggested validation: real-provider MCP search and exact lookup for unique and shared aliases; negative and primary-name controls; regex and literal search; document omission and duplicate semantics; preserve adapter-specific coverage and avoid implying that all provider names are executable or exhaustive. @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 ### Real-provider control of PR #8520 On exact PR head `c37e216f95b3fbc90ed2785c05c1c24e377995fd`, real Kuna 1.988 and Ghidra 12.1.4/JDK 21 were exercised through SDK stdio MCP on a source-built x86-64 ELF with `audit_primary` and `audit_alias` at the same entry and a direct caller. In both full and compact profiles, literal and anchored case-sensitive regex searches returned one procedure for each name. Kuna chose `audit_primary` as its primary and returned `matched_aliases: [audit_alias]` for the alias search; Ghidra chose `audit_alias` as primary and returned `matched_aliases: [audit_primary]` for the other search. Exact lookup of either name selected the same provider entry; a negative search returned no rows. `trace_feature` for the previously missing secondary name included the procedure and its references for both providers. Kuna retained one owner-unavailable unknown; Ghidra resolved the direct caller and also returned other static references. Successful responses validated against the fetched advertised output schemas using Ajv 2020 with strict and format checks disabled. The fixture SHA-256 `01edfcb21b1bd4cd1f2c92ecf7dedfd1b9f3828c7d6a5185fef25a8e088e8f9e` remained unchanged; it was not executed. This is a one-host, one-fixture control; the separate shared-alias and offline controls below cover a different fixture. A separate namespace control is recorded below; performance and cancellation were not covered. ### Shared-alias and offline handoff control At the same #8520 head, real Kuna 1.988 and Ghidra 12.1.4 MCP in both compact and full profiles analyzed a separate x86-64 ELF where `audit_transform` names two versioned entries and `audit_caller` calls each. Literal and anchored case-sensitive regex searches returned two distinct entries with either provider. Kuna returned primary names `audit_v1` and `audit_v2`, each with `matched_aliases: [audit_transform]`; Ghidra returned `audit_transform` as each primary name. Exact lookup refused the shared name and supplied both candidate addresses. `trace_feature` retained both procedures; Kuna reported two references and two owner-unavailable unknowns, while Ghidra returned four static references and no residual unknowns. A summary search followed by the selected `matched_aliases` page was exported, imported into a fresh target-free MCP server, and reproduced the same normalized page for each provider and schema profile. Successful responses validated against the fetched advertised schemas using Ajv 2020 with strict and format checks disabled. The fixture SHA-256 `1f158b0ea39494fcd3424844a1b02511325c567e073fbc0ed045e0bef5f0abfe` and exported bundle bytes remained unchanged; the target was not executed. The first test-harness run encountered an Ajv duplicate schema ID during reconnection, and an initial retry encountered an existing output file; a corrected harness with fresh validator instances and new bundle paths completed all four cases. This is one host and one fixture, not general provider completeness or runtime binding verification. ### Real namespace and leaf-name control On the same #8520 head and real Ghidra 12.1.4/JDK 21, a source-built macOS arm64 fixture with C++ ABI symbols for `alpha::same`, `beta::same`, and `outer::inner::same` produced three distinct Ghidra procedure entries. Exact lookup `same` refused ambiguity and listed all three addresses; anchored regex search `^same$` returned all three qualified primary names in both full and compact MCP profiles. Each qualified lookup and each returned-address decompilation succeeded. On the separate #8509 baseline `7f344af1aa0a78fd4e331dbbc9c30d38e4cfb796`, the same Ghidra search returned no rows while exact `same` lookup was ambiguous. Real Kuna 1.988 on the same fixture did not accept `same` as an exact selector, and its anchored `^same$` returned no rows in either version; its literal `same` search found the three qualified primary names, and each qualified exact lookup succeeded. This is an observed provider-specific selection rule, not evidence that Kuna promised leaf-name lookup. Successful output validated against the fetched advertised schemas using Ajv 2020 with strict and formats disabled. The fixture SHA-256 `ca042de0b9835367a14718854e861df275bfbd075570d9ca48d97dafd4c3165d` was unchanged and it was never executed. One generated Mach-O and host do not establish general namespace or demangler coverage.
bsakaguchi 2026-11-01 21:12:08 +00:00
  • closed this issue
  • added the
    bug
    triage
    labels
Author
Owner

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

Effect on a composed analyst workflow

I added an actual source-authored caller to the same versioned ELF fixture. Independent llvm-objdump showed direct calls at 0x1348 → 0x133c and 0x134d → 0x1342. Real REA a989c0e / Kuna 1.986 MCP returned:

  • procedure_address("sub_133c") → 0x133c, but search_procedures("sub_133c") → [].
  • trace_feature({query:"sub_133c"}) succeeded with matches:[], references:[], truncated:false and residual_unknowns:[]. Its limitations warn that Kuna string scanning is incomplete, but do not state that procedure aliases were excluded.
  • xrefs("0x133c") and procedure_callers("0x133c") both returned 0x1348; trace_call_path(0x1348,0x133c) reached it. Exact-address selection is a working manual alternative for this fixture, subject to the reported reference-coverage limitations.
  • trace_feature({query:"audit_v1"}), the primary name for the same entry, found a procedure and reference but then failed on Kuna's unavailable resolve_containing_procedure (#8288). The missing alias avoids that step; it is not evidence that the primary-name workflow succeeds.

The source-export alias audit_transform is shared by two entries: exact lookup reported both as ambiguous, but trace_feature returned two matching strings and no procedure matches or references, again with no residual unknowns. It did not claim those strings were procedures. Real CLI rea trace ... --provider kuna --format json reproduced the same alias outcomes and the primary-name failure. This is one static controlled fixture, not evidence of runtime execution or general reference completeness. Target SHA-256 1f158b0ea39494fcd3424844a1b02511325c567e073fbc0ed045e0bef5f0abfe was unchanged; no target was executed.

A useful regression should check both the primitive search and its composed/CLI consumer, including unique and shared aliases. Preserving partial matches when containment is unavailable is the separate #8288 decision; avoid turning an unobserved alias into a definitive absence.

<!-- gh-comment-id:6545318716 --> @morluto commented on GitHub (Oct 31, 2026): ### Effect on a composed analyst workflow I added an actual source-authored caller to the same versioned ELF fixture. Independent `llvm-objdump` showed direct calls at `0x1348` → `0x133c` and `0x134d` → `0x1342`. Real REA `a989c0e` / Kuna 1.986 MCP returned: - `procedure_address("sub_133c")` → `0x133c`, but `search_procedures("sub_133c")` → `[]`. - `trace_feature({query:"sub_133c"})` succeeded with `matches:[]`, `references:[]`, `truncated:false` and `residual_unknowns:[]`. Its limitations warn that Kuna string scanning is incomplete, but do not state that procedure aliases were excluded. - `xrefs("0x133c")` and `procedure_callers("0x133c")` both returned `0x1348`; `trace_call_path(0x1348,0x133c)` reached it. Exact-address selection is a working manual alternative for this fixture, subject to the reported reference-coverage limitations. - `trace_feature({query:"audit_v1"})`, the primary name for the same entry, found a procedure and reference but then failed on Kuna's unavailable `resolve_containing_procedure` (#8288). The missing alias avoids that step; it is not evidence that the primary-name workflow succeeds. The source-export alias `audit_transform` is shared by two entries: exact lookup reported both as ambiguous, but `trace_feature` returned two matching *strings* and no procedure matches or references, again with no residual unknowns. It did not claim those strings were procedures. Real CLI `rea trace ... --provider kuna --format json` reproduced the same alias outcomes and the primary-name failure. This is one static controlled fixture, not evidence of runtime execution or general reference completeness. Target SHA-256 `1f158b0ea39494fcd3424844a1b02511325c567e073fbc0ed045e0bef5f0abfe` was unchanged; no target was executed. A useful regression should check both the primitive search and its composed/CLI consumer, including unique and shared aliases. Preserving partial matches when containment is unavailable is the separate #8288 decision; avoid turning an unobserved alias into a definitive absence.
Author
Owner

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

Existing checks and a proposed regression

Source inspection at a989c0e: the public real-provider lane verify-real-kuna.mjs asserts that known function addresses appear in list_procedures, then exercises references and pseudocode by address. It does not call search_procedures or trace_feature in that script. The selected simulated-inventory test kunaProvider.test.ts searches primary names and separately tests duplicate primary-name rejection; it does not compare alias search with exact alias lookup. These observations concern those checks, not every test in the repository. No test suite was run for this source review.

Proposed higher-level regression: use a source-owned binary for which the real provider reports a unique alias and a shared alias, verify exact lookup and search against that same provider inventory, then exercise the public feature trace or assert an explicit partial result when containment is unavailable. Include an independently known call site, a primary-name control, both search modes, and CLI/MCP where supported. Keep duplicate-entry ambiguity and provider-reference limitations explicit. The calling fixture in the preceding comment supplies an observed example, but its exact generated alias addresses are linker-dependent.

<!-- gh-comment-id:6545326305 --> @morluto commented on GitHub (Oct 31, 2026): ### Existing checks and a proposed regression Source inspection at `a989c0e`: the public real-provider lane [`verify-real-kuna.mjs`](https://github.com/morluto/rea/blob/a989c0e458c91af177e097abd7be0fd021b0401d/scripts/verify-real-kuna.mjs#L311) asserts that known function **addresses** appear in `list_procedures`, then exercises references and pseudocode by address. It does not call `search_procedures` or `trace_feature` in that script. The selected simulated-inventory test [`kunaProvider.test.ts`](https://github.com/morluto/rea/blob/a989c0e458c91af177e097abd7be0fd021b0401d/tests/boundary/providers/kuna/kunaProvider.test.ts#L315) searches primary names and separately tests duplicate primary-name rejection; it does not compare alias search with exact alias lookup. These observations concern those checks, not every test in the repository. No test suite was run for this source review. Proposed higher-level regression: use a source-owned binary for which the real provider reports a unique alias and a shared alias, verify exact lookup and search against that same provider inventory, then exercise the public feature trace or assert an explicit partial result when containment is unavailable. Include an independently known call site, a primary-name control, both search modes, and CLI/MCP where supported. Keep duplicate-entry ambiguity and provider-reference limitations explicit. The calling fixture in the preceding comment supplies an observed example, but its exact generated alias addresses are linker-dependent.
Author
Owner

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

Same-address exported names: Ghidra and Kuna

A separate source-owned x86-64 ELF has two defined, global function symbols, audit_primary and audit_alias, at the same entry. A caller directly calls that entry; llvm-readelf and llvm-objdump independently show both symbols and the call. The providers chose different primary names, exposing the same task-level gap without relying on Kuna's generated sub_ alias.

On REA a989c0e / Ghidra 12.1.4 through MCP:

  • list_procedures identified the function at 0x1012a0 as audit_alias; list_names also contained audit_primary at the same address as an imported, non-primary label.
  • procedure_address("audit_primary") resolved 0x1012a0, and find_xrefs_to_name("audit_primary") resolved it and included the direct call site 0x1012a6 (as well as other reference sites). search_procedures("audit_primary") returned [].
  • trace_feature("audit_primary") succeeded with two matching string observations, no procedure matches or references, truncated:false and no residual unknowns. The corresponding trace for Ghidra's primary audit_alias included the function and the caller. Real rea trace ... --provider ghidra --format json reproduced both results.

On the same binary, direct Kuna 1.986 listed audit_primary as the primary name and audit_alias as an alias at its source coordinate 0x12a0. REA/Kuna exact lookup accepted both; search and the procedure portion of trace_feature omitted audit_alias. find_xrefs_to_name was unavailable for that provider. The source-derived Ghidra boundary mirrors the earlier Kuna analysis: search matches primary procedure inventory values, while resolveProcedure also checks symbols at exact function entries. Interior labels are deliberately excluded from that selector.

This is one controlled fixture, not a runtime or broad-coverage claim; the target was not executed or changed (SHA-256 01edfcb21b1bd4cd1f2c92ecf7dedfd1b9f3828c7d6a5185fef25a8e088e8f9e). A solution should preserve the selected matching spelling, primary/secondary provenance and same-address identity; arbitrary data or interior labels must not become procedures merely because they have names. For exact Ghidra names the existing name-to-xrefs workflow is a working alternative; a broad discovery query has different needs. I broadened this issue's title to reflect both reproduced providers.

<!-- gh-comment-id:6545348983 --> @morluto commented on GitHub (Oct 31, 2026): ### Same-address exported names: Ghidra and Kuna A separate source-owned x86-64 ELF has two defined, global function symbols, `audit_primary` and `audit_alias`, at the same entry. A caller directly calls that entry; `llvm-readelf` and `llvm-objdump` independently show both symbols and the call. The providers chose **different** primary names, exposing the same task-level gap without relying on Kuna's generated `sub_` alias. On REA `a989c0e` / Ghidra 12.1.4 through MCP: - `list_procedures` identified the function at `0x1012a0` as `audit_alias`; `list_names` also contained `audit_primary` at the same address as an imported, non-primary label. - `procedure_address("audit_primary")` resolved `0x1012a0`, and `find_xrefs_to_name("audit_primary")` resolved it and included the direct call site `0x1012a6` (as well as other reference sites). `search_procedures("audit_primary")` returned `[]`. - `trace_feature("audit_primary")` succeeded with two matching string observations, no procedure matches or references, `truncated:false` and no residual unknowns. The corresponding trace for Ghidra's primary `audit_alias` included the function and the caller. Real `rea trace ... --provider ghidra --format json` reproduced both results. On the same binary, direct Kuna 1.986 listed `audit_primary` as the primary name and `audit_alias` as an alias at its source coordinate `0x12a0`. REA/Kuna exact lookup accepted both; search and the procedure portion of `trace_feature` omitted `audit_alias`. `find_xrefs_to_name` was unavailable for that provider. The source-derived Ghidra boundary mirrors the earlier Kuna analysis: [`search`](https://github.com/morluto/rea/blob/a989c0e458c91af177e097abd7be0fd021b0401d/bridge/ghidra/ReaGhidraBridge.java#L2123) matches primary procedure inventory values, while [`resolveProcedure`](https://github.com/morluto/rea/blob/a989c0e458c91af177e097abd7be0fd021b0401d/bridge/ghidra/ReaGhidraBridge.java#L2258) also checks symbols at exact function entries. Interior labels are deliberately excluded from that selector. This is one controlled fixture, not a runtime or broad-coverage claim; the target was not executed or changed (SHA-256 `01edfcb21b1bd4cd1f2c92ecf7dedfd1b9f3828c7d6a5185fef25a8e088e8f9e`). A solution should preserve the selected matching spelling, primary/secondary provenance and same-address identity; arbitrary data or interior labels must not become procedures merely because they have names. For exact Ghidra names the existing name-to-xrefs workflow is a working alternative; a broad discovery query has different needs. I broadened this issue's title to reflect both reproduced providers.
Author
Owner

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

Evidence handoff control on that same Ghidra fixture: procedure_pseudo_code("audit_primary") succeeded and rendered the primary function name audit_alias. analyze_function(detail:"summary") succeeded for each spelling and reported the same canonical entry 0x1012a0 and primary name. Their retained parent Evidence records had distinct IDs and preserved the respective requested spellings in their parameters; both summary views remained available after bundle export and import into a fresh server with no binary open. The target and bundle hashes were unchanged.

Thus exact selection and retained request provenance are useful existing building blocks for this case; the gap is discovering and carrying a matching secondary name into the feature workflow. This control does not prove two arbitrary names identify the same function or that every Ghidra symbol at a function entry has the same semantics.

<!-- gh-comment-id:6545355577 --> @morluto commented on GitHub (Oct 31, 2026): Evidence handoff control on that same Ghidra fixture: `procedure_pseudo_code("audit_primary")` succeeded and rendered the primary function name `audit_alias`. `analyze_function(detail:"summary")` succeeded for each spelling and reported the same canonical entry `0x1012a0` and primary name. Their retained parent Evidence records had distinct IDs and preserved the respective requested spellings in their `parameters`; both summary views remained available after bundle export and import into a fresh server with no binary open. The target and bundle hashes were unchanged. Thus exact selection and retained request provenance are useful existing building blocks for this case; the gap is discovering and carrying a matching secondary name into the feature workflow. This control does not prove two arbitrary names identify the same function or that every Ghidra symbol at a function entry has the same semantics.
Author
Owner

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

Shipped Mach-O and the provider boundary

A separately built arm64 Mach-O has two exported names at 0x2c0 and two local names at 0x2c8. With REA a989c0e / Ghidra 12.1.4, list_names retained both names at each entry; exact procedure_address resolved all four, but search_procedures returned only the respective primary function names. This extends the search discrepancy in this issue beyond the earlier ELF control.

With Kuna 1.986, exact lookups of the other two names failed because direct Kuna itself did not include them in its inventory. REA inspect_macho independently returned both exported names at 0x2c0 (with source inventory marked non-exhaustive), and the caller could explicitly select that address. The local pair is not exposed by that export inventory. This producer-side loss is separate from REA search filtering aliases that Kuna actually reports; filed Kuna #1357. A solution here should not assume an omitted name exists in a provider inventory or promote arbitrary export/data labels to functions.

A shipped Homebrew Brotli 1.2.0 arm64 library provides a realistic control: nm -nm reports non-external _PrepareH40 and _PrepareH41 at 0x3a04c. Ghidra exact lookup accepted both, but its search for PrepareH4 reported only the primary _PrepareH41 at that address. Kuna's own inventory and exact lookup omitted _PrepareH40, while decompilation by address worked. The fixture and shipped library hashes remained unchanged and neither was executed. This is a bounded witness, not an estimate of prevalence or autonomous-agent behavior.

<!-- gh-comment-id:6545633163 --> @morluto commented on GitHub (Oct 31, 2026): ### Shipped Mach-O and the provider boundary A separately built arm64 Mach-O has two exported names at `0x2c0` and two local names at `0x2c8`. With REA `a989c0e` / Ghidra 12.1.4, `list_names` retained both names at each entry; exact `procedure_address` resolved all four, but `search_procedures` returned only the respective primary function names. This extends the search discrepancy in this issue beyond the earlier ELF control. With Kuna 1.986, exact lookups of the other two names failed because **direct Kuna itself did not include them in its inventory**. REA `inspect_macho` independently returned both exported names at `0x2c0` (with source inventory marked non-exhaustive), and the caller could explicitly select that address. The local pair is not exposed by that export inventory. This producer-side loss is separate from REA search filtering aliases that Kuna actually reports; filed [Kuna #1357](https://github.com/Noelo-Lab/kuna/issues/1357). A solution here should not assume an omitted name exists in a provider inventory or promote arbitrary export/data labels to functions. A shipped Homebrew Brotli 1.2.0 arm64 library provides a realistic control: `nm -nm` reports non-external `_PrepareH40` and `_PrepareH41` at `0x3a04c`. Ghidra exact lookup accepted both, but its search for `PrepareH4` reported only the primary `_PrepareH41` at that address. Kuna's own inventory and exact lookup omitted `_PrepareH40`, while decompilation by address worked. The fixture and shipped library hashes remained unchanged and neither was executed. This is a bounded witness, not an estimate of prevalence or autonomous-agent behavior.
Author
Owner

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

Bounded recovery on the shipped Brotli example

The exact-name case has a short existing Ghidra path: procedure_address("_PrepareH40") returned 0x3a04c, and list_names({address:"0x3a04c"}) returned both _PrepareH40 (imported non-primary label) and _PrepareH41 (primary function) with their symbol metadata. find_xrefs_to_name("_PrepareH40") also resolved the exact name. address_name(0x3a04c) returned only the primary spelling, as designed.

For the partial query PrepareH4, search_procedures found other primary names but omitted _PrepareH40; find_xrefs_to_name("PrepareH4") returned name_not_found because it is an exact-name workflow. list_names(detail:"summary") retained 7,086 Ghidra-reported rows with discovery coverage unknown. Its native-inventory view supports field selection and paging but rejected a names filter as an unknown argument. Paging with 64 rows found both same-address names on page 93 (source indices 5913/5914); a single request for all 7,086 rows also succeeded. These are call/row counts for one manually selected library, not latency, token-cost or autonomous-agent measurements. Page exhaustion does not establish that the provider discovered every symbol.

This suggests a bounded name-search or retained-inventory filtering question in addition to exact lookup. Any solution should preserve every matching label's type, primary status, source and address, and avoid turning arbitrary labels into procedures. It should also keep the selected provider and its discovery limitations explicit; Kuna's separate missing-source-name issue is Kuna #1357. Target hash 32e38a8ab06c8770ea4bfaf11ea324d7bcb6fe5f07eaff9d6260f93984ee6729 was unchanged, and the library was not executed.

<!-- gh-comment-id:6545651865 --> @morluto commented on GitHub (Oct 31, 2026): ### Bounded recovery on the shipped Brotli example The exact-name case has a short existing Ghidra path: `procedure_address("_PrepareH40")` returned `0x3a04c`, and `list_names({address:"0x3a04c"})` returned both `_PrepareH40` (imported non-primary label) and `_PrepareH41` (primary function) with their symbol metadata. `find_xrefs_to_name("_PrepareH40")` also resolved the exact name. `address_name(0x3a04c)` returned only the primary spelling, as designed. For the partial query `PrepareH4`, `search_procedures` found other primary names but omitted `_PrepareH40`; `find_xrefs_to_name("PrepareH4")` returned `name_not_found` because it is an exact-name workflow. `list_names(detail:"summary")` retained 7,086 Ghidra-reported rows with discovery coverage unknown. Its `native-inventory` view supports field selection and paging but rejected a `names` filter as an unknown argument. Paging with 64 rows found both same-address names on page 93 (source indices 5913/5914); a single request for all 7,086 rows also succeeded. These are call/row counts for one manually selected library, not latency, token-cost or autonomous-agent measurements. Page exhaustion does not establish that the provider discovered every symbol. This suggests a bounded name-search or retained-inventory filtering question in addition to exact lookup. Any solution should preserve every matching label's type, primary status, source and address, and avoid turning arbitrary labels into procedures. It should also keep the selected provider and its discovery limitations explicit; Kuna's separate missing-source-name issue is [Kuna #1357](https://github.com/Noelo-Lab/kuna/issues/1357). Target hash `32e38a8ab06c8770ea4bfaf11ea324d7bcb6fe5f07eaff9d6260f93984ee6729` was unchanged, and the library was not executed.
Author
Owner

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

A narrowly scoped unmerged experiment on REA main 60149282 tests one possible shape: for Kuna search_procedures only, match the primary name and each distinct provider alias, returning a row for each matched name/address; leave list_procedures unchanged. This is not a complete fix or a proposal to treat aliases as separate procedures.

Real Kuna 1.986 MCP, on the same-entry ELF from the earlier comment: a regex matching both names returned two rows with one address (primary and alias), while a negative control remained empty and the procedure listing stayed unchanged. On the separate versioned ELF, literal and regex searches returned both addresses for the shared alias; the unique generated alias returned its single address. Exact shared-name lookup continued to reject ambiguity with both choices. No Ghidra changes were made. A row containing only value and address does not independently identify the canonical name, so this experiment does not settle the contract requested above.

The interaction with #8288 matters: on each ELF with a caller, the baseline alias feature trace missed the procedure and returned a successful result; the experiment found it, then the composed trace_feature failed at Kuna's unsupported resolve_containing_procedure and did not return the found matches. In a separate no-caller ELF, direct xrefs to the aliased entry were empty and the experimental trace_feature successfully returned both procedure-name rows at the same address. This shows that alias discovery alone is not sufficient for a useful traced result when a reference requires containment; it does not establish a general rule about all providers or inputs.

The experiment used a temporary worktree and real public MCP workflows, not simulated provider output. All three target digests were unchanged; none were executed. The changed code and captures were not submitted as a fix. Related partial-results discussion: https://github.com/morluto/rea/issues/8288.

<!-- gh-comment-id:6546224822 --> @morluto commented on GitHub (Oct 31, 2026): A narrowly scoped **unmerged experiment** on REA main `60149282` tests one possible shape: for Kuna `search_procedures` only, match the primary name and each distinct provider alias, returning a row for each matched name/address; leave `list_procedures` unchanged. This is not a complete fix or a proposal to treat aliases as separate procedures. Real Kuna 1.986 MCP, on the same-entry ELF from the earlier comment: a regex matching both names returned two rows with one address (primary and alias), while a negative control remained empty and the procedure listing stayed unchanged. On the separate versioned ELF, literal and regex searches returned both addresses for the shared alias; the unique generated alias returned its single address. Exact shared-name lookup continued to reject ambiguity with both choices. No Ghidra changes were made. A row containing only `value` and `address` does not independently identify the canonical name, so this experiment does not settle the contract requested above. The interaction with #8288 matters: on each ELF **with a caller**, the baseline alias feature trace missed the procedure and returned a successful result; the experiment found it, then the composed `trace_feature` failed at Kuna's unsupported `resolve_containing_procedure` and did not return the found matches. In a separate no-caller ELF, direct xrefs to the aliased entry were empty and the experimental `trace_feature` successfully returned both procedure-name rows at the same address. This shows that alias discovery alone is not sufficient for a useful traced result when a reference requires containment; it does not establish a general rule about all providers or inputs. The experiment used a temporary worktree and real public MCP workflows, not simulated provider output. All three target digests were unchanged; none were executed. The changed code and captures were not submitted as a fix. Related partial-results discussion: https://github.com/morluto/rea/issues/8288.
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#6548
No description provided.