[GH-ISSUE #6629] [Bug] Go and Rust inspectors lose Hexagon identity already recognized by the ELF classifier #4014

Closed
opened 2026-10-31 00:46:03 +00:00 by bsakaguchi · 0 comments
Owner

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

Before submitting

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

Area

Evidence, artifacts, or reconstruction

Observed behavior

Both GoBinaryService with the real GoBinaryProvider and RustBinaryService with the real RustBinaryProvider accept a compiler-generated ELF32 Hexagon object but report architecture: "elf-machine-164" and emit subject.architecture: null. On the identical bytes, REA's canonical readElfFixedHeader reports machine: 164 and architecture: "hexagon". A compiler-generated x86 control reports "386" with subject "x86" through both services.

The same mismatch was also observed on an authored ELF32 ET_DYN fixture containing a loadable Hexagon code section and a .dep-v0 section. Rust inspection successfully recovered its package metadata but lost its recognized CPU family. These are executed source application/provider observations; the public CLI and MCP were not run.

Reproduction

From the source checkout below, with locked dependencies installed and Clang's Hexagon backend available:

work="$(mktemp -d)"
printf '%s\n' 'int ordinary_fixture(void) { return 7; }' > "$work/fixture.c"
clang --target=hexagon -ffreestanding -O0 -c "$work/fixture.c" -o "$work/hexagon.o"
clang -m32 -ffreestanding -O0 -c "$work/fixture.c" -o "$work/x86.o"
cat > "$work/probe.mts" <<'TS'
import {readFile} from 'node:fs/promises';
import {resolve} from 'node:path';
import {pathToFileURL} from 'node:url';
const source=(p:string)=>pathToFileURL(resolve(process.argv[2]!,p)).href;
const {readElfFixedHeader}=await import(source('src/domain/elfFixedHeader.ts'));
const {GoBinaryProvider}=await import(source('src/go/GoBinaryProvider.ts'));
const {RustBinaryProvider}=await import(source('src/rust/RustBinaryProvider.ts'));
const {GoBinaryService}=await import(source('src/application/go/GoBinaryService.ts'));
const {RustBinaryService}=await import(source('src/application/rust/RustBinaryService.ts'));
const providers=[new GoBinaryProvider(),new RustBinaryProvider()];
const services=[new GoBinaryService(providers[0]),new RustBinaryService(providers[1])];
for(const path of process.argv.slice(3)) {
 const header=readElfFixedHeader(await readFile(path));
 if(!header.ok) throw new Error(header.error);
 for(const service of services) {
  const result=await service.inspect({path});
  if(!result.ok) throw result.error;
  const e=result.value;
  console.log(JSON.stringify({operation:e.operation,machine:header.value.machine,canonical_architecture:header.value.architecture,report_architecture:e.normalized_result.architecture,subject_architecture:e.subject.architecture}));
 }
}
for(const provider of providers) await provider.close();
TS
node node_modules/tsx/dist/cli.mjs "$work/probe.mts" "$PWD" "$work/hexagon.o" "$work/x86.o"

The compiler-generated inputs and the same probe were executed before drafting. Both services reproduced on the original Hexagon object, on that object with authored cargo-auditable metadata added using llvm-objcopy, and on an authored ET_DYN container with code bytes extracted from the object. The final reduced probe also ran on the original object, x86 control and ET_DYN fixture. No target code was executed.

Expected behavior

Preserve the already recognized Hexagon family in successful metadata results and Evidence subjects. At minimum, the accepted EM_HEXAGON header should yield subject architecture "hexagon", rather than treating that known machine as unknown. This does not establish Go/Rust compiler identity or request execution/decompilation support.

The existing ELF header classifier explicitly maps machine 164 to hexagon, and the canonical architecture list includes hexagon. The Go guide and Rust guide describe architecture as a native-image observation, independent of whether language metadata exists.

Impact and scope

This is a bounded loss of known CPU identity in otherwise successful inspection Evidence. The original bytes and digest remain available, and Rust package metadata was recovered from the authored metadata fixture. No broader analysis failure or data modification was observed.

Observed scope is local source-service inspection on Linux of ELF32 little-endian EM_HEXAGON inputs. The compiler-produced input is a C object, not a Go/Rust-produced executable. The additional ET_DYN container and its cargo-auditable document are authored fixtures, not a deployed library. Real Hexagon Rust binaries, other hosts, published-package runtime, CLI and MCP delivery were not exercised.

REA version

Source revision 00a9e95de91a4bd4d2a41f8aee704a53fa575750 (package.json version 6.7.0), using locked dependencies.

Runtime and platform

Node.js v24.22.1; Linux x86_64; Clang 23.1.3 with Hexagon backend. No disassembler or target execution was used.

Target and artifact context

Compiler-generated ELF32 little-endian ET_REL objects for Hexagon and x86, built from int ordinary_fixture(void) { return 7; }. Additional local checks used the Hexagon object with an authored .dep-v0 zlib JSON section and an LLVM yaml2obj-authored ELF32 Hexagon ET_DYN container containing those compiled code bytes.

The authored dependency document was:

{"format":1,"packages":[{"name":"ordinary_fixture","version":"0.1.0","source":"local","root":true}]}

LLVM readelf independently identified the original object and the authored shared-object fixture as Qualcomm Hexagon. The shared-object fixture's SHA-256 was 62c08f8ff6245512ccba9358a204acea0b40a7ebabf39aa1539bb80349ce7721; its dependency section was 93 bytes at file offset 108, and Rust inspection returned its one root package.

Interface

Other

Executed the shared source application services with their real bundled file providers. Public CLI/MCP delivery was not exercised.

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Reduced executed output for the compiler-generated Hexagon object:

{"operation":"inspect_go_binary","machine":164,"canonical_architecture":"hexagon","report_architecture":"elf-machine-164","subject_architecture":null}
{"operation":"inspect_rust_binary","machine":164,"canonical_architecture":"hexagon","report_architecture":"elf-machine-164","subject_architecture":null}

Matched x86 control:

{"operation":"inspect_go_binary","machine":3,"canonical_architecture":"x86","report_architecture":"386","subject_architecture":"x86"}
{"operation":"inspect_rust_binary","machine":3,"canonical_architecture":"x86","report_architecture":"386","subject_architecture":"x86"}

Evidence provenance: observed source-service/provider results and LLVM header/section output. Local verification: reproduced with benign generated inputs. Reproduction completeness: complete for the described service boundary; public transports and real Hexagon Go/Rust producer binaries are untested.

Typed outcome or recovery expected

Successful image metadata and Evidence should retain the recognized hexagon family. Missing Go build information or a missing Rust dependency section should retain their existing unknown language-metadata semantics.

Analysis or suspected cause

Source-derived explanation: the shared ELF container reader reads the canonical header directory but reconstructs architecture through a separate machine-name table. That table omits machine 164 and returns elf-machine-164. Both the Go and Rust subject mappers consequently treat it as unknown. The independent canonical classifier already recognizes the same machine.

Additional context

Related reports were checked before drafting. #4197 covers the distinct PowerPC alias-to-subject mapping (ppc versus powerpc); it does not cover this missing Hexagon machine entry. #4781 is closed and concerned adding Hexagon to the owning ELF classifier, where the mapping is now present. Searches across open and closed issues for "elf-machine-164", "Go" "Hexagon", and "Hexagon" "inspection" found no report of this inspector-table omission.

No source files were changed, and no restored behavior was tested. The recorded failure was not rerun after drafting.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Both real metadata services discard an already recognized CPU family from successful normalized results and Evidence subjects for the demonstrated bounded Hexagon input class; an x86 control retains it. Package metadata remains usable and no whole-workflow failure was shown.
  • Workaround status: unverified
  • Workaround basis: The canonical header reader and LLVM header output recover Hexagon identity, as observed, but no workaround restoring it within the emitted inspection Evidence was tested.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6629 ## 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 Evidence, artifacts, or reconstruction ## Observed behavior Both `GoBinaryService` with the real `GoBinaryProvider` and `RustBinaryService` with the real `RustBinaryProvider` accept a compiler-generated ELF32 Hexagon object but report `architecture: "elf-machine-164"` and emit `subject.architecture: null`. On the identical bytes, REA's canonical `readElfFixedHeader` reports `machine: 164` and `architecture: "hexagon"`. A compiler-generated x86 control reports `"386"` with subject `"x86"` through both services. The same mismatch was also observed on an authored ELF32 `ET_DYN` fixture containing a loadable Hexagon code section and a `.dep-v0` section. Rust inspection successfully recovered its package metadata but lost its recognized CPU family. These are executed source application/provider observations; the public CLI and MCP were not run. ## Reproduction From the source checkout below, with locked dependencies installed and Clang's Hexagon backend available: ```sh work="$(mktemp -d)" printf '%s\n' 'int ordinary_fixture(void) { return 7; }' > "$work/fixture.c" clang --target=hexagon -ffreestanding -O0 -c "$work/fixture.c" -o "$work/hexagon.o" clang -m32 -ffreestanding -O0 -c "$work/fixture.c" -o "$work/x86.o" cat > "$work/probe.mts" <<'TS' import {readFile} from 'node:fs/promises'; import {resolve} from 'node:path'; import {pathToFileURL} from 'node:url'; const source=(p:string)=>pathToFileURL(resolve(process.argv[2]!,p)).href; const {readElfFixedHeader}=await import(source('src/domain/elfFixedHeader.ts')); const {GoBinaryProvider}=await import(source('src/go/GoBinaryProvider.ts')); const {RustBinaryProvider}=await import(source('src/rust/RustBinaryProvider.ts')); const {GoBinaryService}=await import(source('src/application/go/GoBinaryService.ts')); const {RustBinaryService}=await import(source('src/application/rust/RustBinaryService.ts')); const providers=[new GoBinaryProvider(),new RustBinaryProvider()]; const services=[new GoBinaryService(providers[0]),new RustBinaryService(providers[1])]; for(const path of process.argv.slice(3)) { const header=readElfFixedHeader(await readFile(path)); if(!header.ok) throw new Error(header.error); for(const service of services) { const result=await service.inspect({path}); if(!result.ok) throw result.error; const e=result.value; console.log(JSON.stringify({operation:e.operation,machine:header.value.machine,canonical_architecture:header.value.architecture,report_architecture:e.normalized_result.architecture,subject_architecture:e.subject.architecture})); } } for(const provider of providers) await provider.close(); TS node node_modules/tsx/dist/cli.mjs "$work/probe.mts" "$PWD" "$work/hexagon.o" "$work/x86.o" ``` The compiler-generated inputs and the same probe were executed before drafting. Both services reproduced on the original Hexagon object, on that object with authored cargo-auditable metadata added using `llvm-objcopy`, and on an authored `ET_DYN` container with code bytes extracted from the object. The final reduced probe also ran on the original object, x86 control and `ET_DYN` fixture. No target code was executed. ## Expected behavior Preserve the already recognized Hexagon family in successful metadata results and Evidence subjects. At minimum, the accepted `EM_HEXAGON` header should yield subject architecture `"hexagon"`, rather than treating that known machine as unknown. This does not establish Go/Rust compiler identity or request execution/decompilation support. The existing [ELF header classifier explicitly maps machine 164 to `hexagon`](https://github.com/morluto/rea/blob/00a9e95de91a4bd4d2a41f8aee704a53fa575750/src/domain/elfFixedHeader.ts#L76-L98), and the [canonical architecture list includes `hexagon`](https://github.com/morluto/rea/blob/00a9e95de91a4bd4d2a41f8aee704a53fa575750/src/domain/binaryTargetTypes.ts#L3-L17). The [Go guide](https://github.com/morluto/rea/blob/00a9e95de91a4bd4d2a41f8aee704a53fa575750/docs/go-binaries.md#L75-L80) and [Rust guide](https://github.com/morluto/rea/blob/00a9e95de91a4bd4d2a41f8aee704a53fa575750/docs/rust-binaries.md#L85-L88) describe architecture as a native-image observation, independent of whether language metadata exists. ## Impact and scope This is a bounded loss of known CPU identity in otherwise successful inspection Evidence. The original bytes and digest remain available, and Rust package metadata was recovered from the authored metadata fixture. No broader analysis failure or data modification was observed. Observed scope is local source-service inspection on Linux of ELF32 little-endian `EM_HEXAGON` inputs. The compiler-produced input is a C object, not a Go/Rust-produced executable. The additional `ET_DYN` container and its cargo-auditable document are authored fixtures, not a deployed library. Real Hexagon Rust binaries, other hosts, published-package runtime, CLI and MCP delivery were not exercised. ## REA version Source revision `00a9e95de91a4bd4d2a41f8aee704a53fa575750` (`package.json` version `6.7.0`), using locked dependencies. ## Runtime and platform Node.js v24.22.1; Linux x86_64; Clang 23.1.3 with Hexagon backend. No disassembler or target execution was used. ## Target and artifact context Compiler-generated ELF32 little-endian `ET_REL` objects for Hexagon and x86, built from `int ordinary_fixture(void) { return 7; }`. Additional local checks used the Hexagon object with an authored `.dep-v0` zlib JSON section and an LLVM `yaml2obj`-authored ELF32 Hexagon `ET_DYN` container containing those compiled code bytes. The authored dependency document was: ```json {"format":1,"packages":[{"name":"ordinary_fixture","version":"0.1.0","source":"local","root":true}]} ``` LLVM `readelf` independently identified the original object and the authored shared-object fixture as Qualcomm Hexagon. The shared-object fixture's SHA-256 was `62c08f8ff6245512ccba9358a204acea0b40a7ebabf39aa1539bb80349ce7721`; its dependency section was 93 bytes at file offset 108, and Rust inspection returned its one root package. ## Interface Other Executed the shared source application services with their real bundled file providers. Public CLI/MCP delivery was not exercised. ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence Reduced executed output for the compiler-generated Hexagon object: ```json {"operation":"inspect_go_binary","machine":164,"canonical_architecture":"hexagon","report_architecture":"elf-machine-164","subject_architecture":null} {"operation":"inspect_rust_binary","machine":164,"canonical_architecture":"hexagon","report_architecture":"elf-machine-164","subject_architecture":null} ``` Matched x86 control: ```json {"operation":"inspect_go_binary","machine":3,"canonical_architecture":"x86","report_architecture":"386","subject_architecture":"x86"} {"operation":"inspect_rust_binary","machine":3,"canonical_architecture":"x86","report_architecture":"386","subject_architecture":"x86"} ``` Evidence provenance: observed source-service/provider results and LLVM header/section output. Local verification: reproduced with benign generated inputs. Reproduction completeness: complete for the described service boundary; public transports and real Hexagon Go/Rust producer binaries are untested. ## Typed outcome or recovery expected Successful image metadata and Evidence should retain the recognized `hexagon` family. Missing Go build information or a missing Rust dependency section should retain their existing unknown language-metadata semantics. ## Analysis or suspected cause Source-derived explanation: the [shared ELF container reader](https://github.com/morluto/rea/blob/00a9e95de91a4bd4d2a41f8aee704a53fa575750/src/native/metadata/ElfImage.ts#L93-L120) reads the canonical header directory but reconstructs architecture through a separate machine-name table. That table omits machine 164 and returns `elf-machine-164`. Both the [Go](https://github.com/morluto/rea/blob/00a9e95de91a4bd4d2a41f8aee704a53fa575750/src/domain/go/goBinary.ts#L16-L28) and [Rust](https://github.com/morluto/rea/blob/00a9e95de91a4bd4d2a41f8aee704a53fa575750/src/domain/rust/rustBinary.ts#L15-L27) subject mappers consequently treat it as unknown. The independent canonical classifier already recognizes the same machine. ## Additional context Related reports were checked before drafting. [#4197](https://github.com/morluto/rea/issues/4197) covers the distinct PowerPC alias-to-subject mapping (`ppc` versus `powerpc`); it does not cover this missing Hexagon machine entry. [#4781](https://github.com/morluto/rea/issues/4781) is closed and concerned adding Hexagon to the owning ELF classifier, where the mapping is now present. Searches across open and closed issues for `"elf-machine-164"`, `"Go" "Hexagon"`, and `"Hexagon" "inspection"` found no report of this inspector-table omission. No source files were changed, and no restored behavior was tested. The recorded failure was not rerun after drafting. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: Both real metadata services discard an already recognized CPU family from successful normalized results and Evidence subjects for the demonstrated bounded Hexagon input class; an x86 control retains it. Package metadata remains usable and no whole-workflow failure was shown. - Workaround status: unverified - Workaround basis: The canonical header reader and LLVM header output recover Hexagon identity, as observed, but no workaround restoring it within the emitted inspection Evidence was tested.
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#4014
No description provided.