[GH-ISSUE #3875] [Bug] Mach-O object file's unnamed segment is reported with the name "unknown" #1496

Closed
opened 2026-10-16 21:06:10 +00:00 by bsakaguchi · 1 comment
Owner

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

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

rea inspect-macho on an ordinary relocatable object (MH_OBJECT) reports the single segment's normalized name as the literal "unknown", while the same response's raw LC_SEGMENT_64 load-command fields preserve the observed segname as "". Apple's mach-o/loader.h defines object files as placing all sections in one unnamed segment, so the empty name is a known source value, not missing data, and the exhaustive segment inventory should not replace it with a display label.

The command succeeds; the raw load-command field is "", but the normalized segment name is "unknown" in an inventory marked exhaustive: true. A caller reading the normalized segment inventory sees a segment literally named unknown.

Reproduction

  1. In an empty directory, compile a relocatable object and inspect it (the object is never executed):
printf 'int qa(void) { return 7; }\n' > qa.c
/usr/bin/clang -c qa.c -o qa.o
rea inspect-macho "$PWD/qa.o" --format json > object-result.json
python3 -c 'import json; n = json.load(open("object-result.json"))["normalized_result"]; print(json.dumps({"file_type": n["file_type"], "raw_segname": n["load_commands"]["items"][0]["fields"]["segname"], "segment_name": n["segments"]["items"][0]["name"], "segments_exhaustive": n["segments"]["exhaustive"]}))'

Expected behavior

normalized_result.segments.items[0].name preserves the observed empty segment name "" (or otherwise distinguishes a known empty name from an absent one), consistent with normalized_result.load_commands.items[0].fields.segname.

Impact and scope

Ordinary Mach-O object files receive an inaccurate normalized segment label in an exhaustive inventory; the original empty value remains in the same response and no analysis failure was demonstrated, so this is bounded metadata identity loss.

Workaround: available. The original segment name is preserved in the corresponding normalized_result.load_commands record's fields.segname, which the reproduction reads directly.

Reporter's impact estimate: P3 (supported).

REA version

6.5.0, built from source at main commit 034342ba28 (latest npm release is 6.5.0)

Runtime and platform

Node.js v26.10.0; macOS 27.0.1 arm64

Target and artifact context

Mach-O arm64 relocatable object (MH_OBJECT) compiled by clang

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

  • Expected source: AGENTS.md:19 and AGENTS.md:29 (preserve identity, uncertainty, and source values; keep identity separate from display formatting); Apple SDK mach-o/loader.h describes MH_OBJECT files as putting all sections in one unnamed segment
  • Failure source: observed inspect-macho JSON for a clang-compiled object file; src/native/parsers/otool.ts:463 passes segname through nonEmptyName, which at lines 547-549 maps both an absent name and an observed empty string to "unknown"
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete
{"file_type": "1", "raw_segname": "", "segment_name": "unknown", "segments_exhaustive": true}

File type 1 is MH_OBJECT. The same response's section entries carry their own segment names (__TEXT, __LD), so only the containing segment's name is replaced.

Typed outcome or recovery expected

The normalized segment record should preserve the observed empty segment name (or an explicit known-empty marker) rather than the display label "unknown", matching the raw load-command segname.

Restoration check:

On the same qa.o, the projection above currently prints "raw_segname": "", "segment_name": "unknown"; after a fix the normalized segment name matches the raw value ("") or is represented as an explicit known-empty name, while segments_exhaustive stays true. Control: a linked executable such as /bin/ls keeps its named segments (__PAGEZERO, __TEXT, and so on) unchanged.

Analysis or suspected cause

Source-derived: src/native/parsers/otool.ts:463 projects segname through nonEmptyName, and src/native/parsers/otool.ts:547-549 maps both null and the empty string to "unknown"; the same helper is used for section segment and section names at src/native/parsers/otool.ts:491-492.

Additional context

Searched open and closed issues for empty or unnamed Mach-O segment names; the nearest reports are open #3397 (unnamed ELF sections in Rust evidence) and closed #33 (Hopper permission metadata), neither of which covers this substitution. Section records use the same nonEmptyName helper for their segment and name fields at src/native/parsers/otool.ts:491-492, so an empty section segment name would be projected the same way; that variant was not separately observed.

This report came from AI-assisted source review with local reproduction where stated above; the evidence labels distinguish observed runs from source-only reasoning.

Originally created by @coygeek on GitHub (Oct 15, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3875 ### 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 `rea inspect-macho` on an ordinary relocatable object (`MH_OBJECT`) reports the single segment's normalized name as the literal `"unknown"`, while the same response's raw `LC_SEGMENT_64` load-command fields preserve the observed `segname` as `""`. Apple's `mach-o/loader.h` defines object files as placing all sections in one unnamed segment, so the empty name is a known source value, not missing data, and the exhaustive segment inventory should not replace it with a display label. The command succeeds; the raw load-command field is `""`, but the normalized segment name is `"unknown"` in an inventory marked `exhaustive: true`. A caller reading the normalized segment inventory sees a segment literally named `unknown`. ### Reproduction 1. In an empty directory, compile a relocatable object and inspect it (the object is never executed): ```sh printf 'int qa(void) { return 7; }\n' > qa.c /usr/bin/clang -c qa.c -o qa.o rea inspect-macho "$PWD/qa.o" --format json > object-result.json python3 -c 'import json; n = json.load(open("object-result.json"))["normalized_result"]; print(json.dumps({"file_type": n["file_type"], "raw_segname": n["load_commands"]["items"][0]["fields"]["segname"], "segment_name": n["segments"]["items"][0]["name"], "segments_exhaustive": n["segments"]["exhaustive"]}))' ``` ### Expected behavior `normalized_result.segments.items[0].name` preserves the observed empty segment name `""` (or otherwise distinguishes a known empty name from an absent one), consistent with `normalized_result.load_commands.items[0].fields.segname`. ### Impact and scope Ordinary Mach-O object files receive an inaccurate normalized segment label in an exhaustive inventory; the original empty value remains in the same response and no analysis failure was demonstrated, so this is bounded metadata identity loss. Workaround: available. The original segment name is preserved in the corresponding `normalized_result.load_commands` record's `fields.segname`, which the reproduction reads directly. Reporter's impact estimate: P3 (supported). ### REA version 6.5.0, built from source at main commit 034342ba28c8e56c3746be92b78aa7299afa02bd (latest npm release is 6.5.0) ### Runtime and platform Node.js v26.10.0; macOS 27.0.1 arm64 ### Target and artifact context Mach-O arm64 relocatable object (MH_OBJECT) compiled by clang ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence - Expected source: AGENTS.md:19 and AGENTS.md:29 (preserve identity, uncertainty, and source values; keep identity separate from display formatting); Apple SDK `mach-o/loader.h` describes `MH_OBJECT` files as putting all sections in one unnamed segment - Failure source: observed `inspect-macho` JSON for a clang-compiled object file; `src/native/parsers/otool.ts:463` passes `segname` through `nonEmptyName`, which at lines 547-549 maps both an absent name and an observed empty string to `"unknown"` - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete ```json {"file_type": "1", "raw_segname": "", "segment_name": "unknown", "segments_exhaustive": true} ``` File type `1` is `MH_OBJECT`. The same response's section entries carry their own segment names (`__TEXT`, `__LD`), so only the containing segment's name is replaced. ### Typed outcome or recovery expected The normalized segment record should preserve the observed empty segment name (or an explicit known-empty marker) rather than the display label "unknown", matching the raw load-command segname. Restoration check: On the same `qa.o`, the projection above currently prints `"raw_segname": "", "segment_name": "unknown"`; after a fix the normalized segment name matches the raw value (`""`) or is represented as an explicit known-empty name, while `segments_exhaustive` stays `true`. Control: a linked executable such as `/bin/ls` keeps its named segments (`__PAGEZERO`, `__TEXT`, and so on) unchanged. ### Analysis or suspected cause Source-derived: src/native/parsers/otool.ts:463 projects segname through nonEmptyName, and src/native/parsers/otool.ts:547-549 maps both null and the empty string to "unknown"; the same helper is used for section segment and section names at src/native/parsers/otool.ts:491-492. ### Additional context Searched open and closed issues for empty or unnamed Mach-O segment names; the nearest reports are open #3397 (unnamed ELF sections in Rust evidence) and closed #33 (Hopper permission metadata), neither of which covers this substitution. Section records use the same `nonEmptyName` helper for their `segment` and `name` fields at `src/native/parsers/otool.ts:491-492`, so an empty section segment name would be projected the same way; that variant was not separately observed. This report came from AI-assisted source review with local reproduction where stated above; the evidence labels distinguish observed runs from source-only reasoning.
Author
Owner

@yankikucuk commented on GitHub (Oct 15, 2026):

Working on this. Reproduced on a clang -c object through rea inspect-macho: raw_segname: "" with segment_name: "unknown" in an exhaustive inventory. The otool projection now keeps an observed name as printed, including the empty name of the MH_OBJECT segment and an all-NUL section name, and uses the unknown label only when otool printed no name field at all. /bin/ls keeps its named segments. Draft PR follows shortly.

<!-- gh-comment-id:6189652698 --> @yankikucuk commented on GitHub (Oct 15, 2026): Working on this. Reproduced on a clang `-c` object through `rea inspect-macho`: `raw_segname: ""` with `segment_name: "unknown"` in an exhaustive inventory. The otool projection now keeps an observed name as printed, including the empty name of the MH_OBJECT segment and an all-NUL section name, and uses the `unknown` label only when otool printed no name field at all. `/bin/ls` keeps its named segments. Draft PR follows shortly.
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#1496
No description provided.