[GH-ISSUE #5150] [Feature] Expose Constant-table default values for literal fields and parameters in inspect_managed_members #3171

Open
opened 2026-10-31 00:37:27 +00:00 by bsakaguchi · 6 comments
Owner

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

Before submitting

  • I searched the open and closed issues and pull requests for a related proposal.
  • I understand the contribution scope must be reviewed before integration; open questions are welcome here.
  • This request does not include credentials, private samples, or sensitive target data.

Area

Native analysis or decompilation

Current limitation

The ECMA-335 Constant table (default values of literal fields, enum members and parameters) is not exposed. Mixed In Key 11's MixedInKey.exe has 957 Constant rows (inspect-managed-artifact table_row_counts). In inspect-managed-members --type MixedInKey.Audio.AudioAnalyser the 26 field records only have name, declaring_type_token, flags, declaring_type, signature, row_offset, token. Four have flags & 0x8000 (HasDefault), for example WMGraphNotify (0x04000f43, flags 32849 = 0x8051, field_type: "i4"); the value is nowhere in the result, and I found no constant/default key in output or schema.

Source-derived: Constant appears only in src/dotnet/ManagedMetadataLayout.ts:23 and ManagedMetadataRowSizes.ts:28 (row sizing); grep -ri constant src/dotnet src/domain/managed finds no row reader or schema field, only the CIL operand kind "constant".

Observed on rea 6.7.0, SHA-256 b014a00e6f6b80ed9313f68ad3da8f42c2de38f9111582e62145cec63c7da843 (rea inspect-managed-members <exe> --type MixedInKey.Audio.AudioAnalyser --json, ran twice).

Use cases

Enum members, version numbers and algorithm selectors are literal fields. Without values an analyst cannot name the 4 in ldloc.s 4; ldc.i4.4; bne.un or map an enum to its members.

Desired outcome and success criteria

For fields and parameters with HasDefault, return the decoded constant (element type and value), with an explicit unknown when the blob is malformed or the type is unsupported, inside the existing representation budget. Success: WMGraphNotify reports its value.

Expected interaction with targets

Read existing files or captured data

Target and scope details (optional)

Read-only metadata; no execution. Adjacent but distinct: open PR #3835 (FieldRVA initial data).

Verification available so far

I have a prototype or observed results

Verification details (optional)

Observed absence on one type. Not checked: parameters (Param flags HasDefault), property constants.

Alternatives considered

An external metadata reader for the Constant table, which is what I would have to use today.

Possible direction

A nullable constant on field (and later parameter) records, parsed by the owner that already reads the row. Proposal only.

References

ECMA-335 II.22.9 (Constant), II.23.1.5 (FieldAttributes.HasDefault).

Originally created by @elricfd on GitHub (Oct 19, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5150 ### Before submitting - [x] I searched the open and closed issues and pull requests for a related proposal. - [x] I understand the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope) must be reviewed before integration; open questions are welcome here. - [x] This request does not include credentials, private samples, or sensitive target data. ### Area Native analysis or decompilation ### Current limitation The ECMA-335 `Constant` table (default values of literal fields, enum members and parameters) is not exposed. Mixed In Key 11's `MixedInKey.exe` has 957 `Constant` rows (`inspect-managed-artifact` `table_row_counts`). In `inspect-managed-members --type MixedInKey.Audio.AudioAnalyser` the 26 field records only have `name, declaring_type_token, flags, declaring_type, signature, row_offset, token`. Four have `flags & 0x8000` (`HasDefault`), for example `WMGraphNotify` (`0x04000f43`, flags 32849 = `0x8051`, `field_type: "i4"`); the value is nowhere in the result, and I found no `constant`/`default` key in output or schema. Source-derived: `Constant` appears only in `src/dotnet/ManagedMetadataLayout.ts:23` and `ManagedMetadataRowSizes.ts:28` (row sizing); `grep -ri constant src/dotnet src/domain/managed` finds no row reader or schema field, only the CIL operand kind "constant". Observed on rea 6.7.0, SHA-256 `b014a00e6f6b80ed9313f68ad3da8f42c2de38f9111582e62145cec63c7da843` (`rea inspect-managed-members <exe> --type MixedInKey.Audio.AudioAnalyser --json`, ran twice). ### Use cases Enum members, version numbers and algorithm selectors are literal fields. Without values an analyst cannot name the `4` in `ldloc.s 4; ldc.i4.4; bne.un` or map an enum to its members. ### Desired outcome and success criteria For fields and parameters with `HasDefault`, return the decoded constant (element type and value), with an explicit unknown when the blob is malformed or the type is unsupported, inside the existing representation budget. Success: `WMGraphNotify` reports its value. ### Expected interaction with targets Read existing files or captured data ### Target and scope details (optional) Read-only metadata; no execution. Adjacent but distinct: open PR #3835 (FieldRVA initial data). ### Verification available so far I have a prototype or observed results ### Verification details (optional) Observed absence on one type. Not checked: parameters (`Param` flags `HasDefault`), property constants. ### Alternatives considered An external metadata reader for the `Constant` table, which is what I would have to use today. ### Possible direction A nullable `constant` on field (and later parameter) records, parsed by the owner that already reads the row. Proposal only. ### References ECMA-335 II.22.9 (Constant), II.23.1.5 (FieldAttributes.HasDefault).
Author
Owner

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

Exposing the Constant table in inspect-managed-members is genuinely useful: literal field defaults, enum values and parameter default values are frequently the quickest signal for what a managed API expects, and right now they are invisible even though the rows are already counted. A couple of design suggestions for the shape of the output: (1) print the default alongside its owner (field/parameter) with the ECMA-335 element type so a 0x0b (boolean) vs 0x08 (string) default is unambiguous; (2) for enum members the Constant is the underlying integral value, so annotate whether the raw value maps to a named member of the declaring enum when one exists; (3) consider a flag to suppress defaults for parameters that simply mirror C# optional-parameter nulls, since those dominate the table in real assemblies and add noise. This would fit the existing row_offset/token reporting style without changing the summary contract.

<!-- gh-comment-id:6257730822 --> @XinwangTao commented on GitHub (Oct 19, 2026): Exposing the Constant table in inspect-managed-members is genuinely useful: literal field defaults, enum values and parameter default values are frequently the quickest signal for what a managed API expects, and right now they are invisible even though the rows are already counted. A couple of design suggestions for the shape of the output: (1) print the default alongside its owner (field/parameter) with the ECMA-335 element type so a 0x0b (boolean) vs 0x08 (string) default is unambiguous; (2) for enum members the Constant is the underlying integral value, so annotate whether the raw value maps to a named member of the declaring enum when one exists; (3) consider a flag to suppress defaults for parameters that simply mirror C# optional-parameter nulls, since those dominate the table in real assemblies and add noise. This would fit the existing row_offset/token reporting style without changing the summary contract.
Author
Owner

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

I’d like to work on this, opening a PR shortly.

<!-- gh-comment-id:6298791573 --> @ShaheryarKhan728 commented on GitHub (Oct 20, 2026): I’d like to work on this, opening a PR shortly.
Author
Owner

@XinwangTao commented on GitHub (Oct 21, 2026):

Good to see someone picking this up. When the PR lands, the acceptance case is WMGraphNotify (0x04000f43) reporting its decoded i4 default, so a test fixture that asserts both the element type (ECMA-335) and the value for a HasDefault field would anchor it. It would also be worth covering the two edges the issue calls out: a malformed blob should produce an explicit unknown rather than a hard failure, and enum members should show whether the underlying value maps to a named member of the declaring enum.

<!-- gh-comment-id:6305621512 --> @XinwangTao commented on GitHub (Oct 21, 2026): Good to see someone picking this up. When the PR lands, the acceptance case is WMGraphNotify (0x04000f43) reporting its decoded i4 default, so a test fixture that asserts both the element type (ECMA-335) and the value for a HasDefault field would anchor it. It would also be worth covering the two edges the issue calls out: a malformed blob should produce an explicit unknown rather than a hard failure, and enum members should show whether the underlying value maps to a named member of the declaring enum.
Author
Owner

@XinwangTao commented on GitHub (Oct 21, 2026):

Good to see someone picking this up. When the PR lands, the acceptance case is WMGraphNotify (0x04000f43) reporting its decoded i4 default, so a test fixture that asserts both the element type (ECMA-335) and the value for a HasDefault field would anchor it. It would also be worth covering the two edges the issue calls out: a malformed blob should produce an explicit unknown rather than a hard failure, and enum members should show whether the underlying value maps to a named member of the declaring enum.

<!-- gh-comment-id:6305657663 --> @XinwangTao commented on GitHub (Oct 21, 2026): Good to see someone picking this up. When the PR lands, the acceptance case is WMGraphNotify (0x04000f43) reporting its decoded i4 default, so a test fixture that asserts both the element type (ECMA-335) and the value for a HasDefault field would anchor it. It would also be worth covering the two edges the issue calls out: a malformed blob should produce an explicit unknown rather than a hard failure, and enum members should show whether the underlying value maps to a named member of the declaring enum.
Author
Owner

@xu91102 commented on GitHub (Oct 29, 2026):

Independent public-CLI reproduction on current main f25d1e3e9fbda7971c312caa3da757dc525a73f6 (Node 24.22.1, npm 11.16.0, macOS arm64), before implementing anything:

  • A source-owned inert PE/CLI fixture declares WMGraphNotify, Field 0x04000001, HasDefault, and one Constant row. An independent ECMA-335 byte reader confirms element type 0x08 (i4), raw bytes 865d0000, value 23942.
  • inspect-managed-artifact counts the Constant row. Actual inspect-managed-members … --json exits 0 and retains the field/name/type/flags, but exposes no constant value. The ordinary field control still succeeds; a missing-target control still returns target_unavailable. Input bytes are retained unchanged. This is an existing feature gap, not a claim of a regression or runtime behavior.

I plan one bounded contribution for field-owned constants, through the existing shared reader, CLI/MCP and retained field pages. It will retain source row coordinates and encoded bytes, decode supported primitive defaults losslessly, and leave missing/duplicate/malformed/unsupported declarations explicitly unavailable with coverage diagnostics. Parameter/property constants, enum-name inference, assembly loading/execution and FieldRVA data are outside this slice.

I found the earlier intent-to-work comment. Current open/closed PR searches for this issue, HasDefault and managed constant readers found no public implementation; that does not establish the absence of unpublished work. I read the related FieldRVA (#3835) and nominal CIL identity (#4516) production changes: those own different facts and will not be duplicated.

No private MixedInKey sample, CLR execution, external provider, other host runtime or performance validation has been performed. New PR author declarations will remain for human confirmation.

Current delivered revision (2026-10-30)

#8015 remains open and ready at normal fork head 008e3455e9e9ddaf7abba3f6446da92e713f2877, after integrating main 317bf3fe235e655b2d752d3be261cc0da7d00f2b for an actual conflict. The field-focused scope above is unchanged; this does not close the broader parameter/property request.

The latest CI-source reproduction had two inherited diagnostic-prose failures (2 FAIL / 17 PASS). Main's canonical typed CLI/Flutter assertions are retained, alongside both-invalid-field and no-Evidence MCP checks; corrected controls pass 28 cases on that exact CI source. Main's independently reproduced unused internal exports/constant aliases were minimally cleaned up with the original Node timer maximum and fixed debugger control allowance unchanged, without gate suppression.

Current integrated source validation: 18 focused files / 616 PASS, fresh README 9 PASS = 19 distinct files / 625 PASS / 0 skip. Full check, docs, discovery (2869 files exactly once), package verifier and pack dry-run pass. Actual compiled CLI 7 cases + installed CLI 7 cases + installed stdio MCP 1 session/6 calls verify complete/partial values, retained fields and negative controls. All 2663 product files match current/archive/install; 233 tools and 6 prompts are observed, with awaited transport/package cleanup.

Independent frozen Standards and Spec reviews both pass. A normal hook's five unrelated rewrites were blocked before push; ordinary revert and exact replay restored all reviewed source/product bytes without rewriting history. The source tested above is byte-identical to the final delivered source; those tests were not counted as another fresh run after replay.

Earlier cleanup uncertainty and external harness failures remain recorded, not relabeled as product failures or erased by later success. Current-head CI/Codex and the human author declarations are separate from local validation. Parameter/property constants, enum-name inference, private MixedInKey input, CLR execution, real external engines/agents, other host runtimes and performance remain unverified/outside this slice.

<!-- gh-comment-id:6490787903 --> @xu91102 commented on GitHub (Oct 29, 2026): Independent public-CLI reproduction on current main `f25d1e3e9fbda7971c312caa3da757dc525a73f6` (Node 24.22.1, npm 11.16.0, macOS arm64), before implementing anything: - A source-owned inert PE/CLI fixture declares `WMGraphNotify`, Field `0x04000001`, `HasDefault`, and one `Constant` row. An independent ECMA-335 byte reader confirms element type `0x08` (`i4`), raw bytes `865d0000`, value **23942**. - `inspect-managed-artifact` counts the Constant row. Actual `inspect-managed-members … --json` exits 0 and retains the field/name/type/flags, but exposes no constant value. The ordinary field control still succeeds; a missing-target control still returns `target_unavailable`. Input bytes are retained unchanged. This is an existing feature gap, not a claim of a regression or runtime behavior. I plan one bounded contribution for **field-owned constants**, through the existing shared reader, CLI/MCP and retained field pages. It will retain source row coordinates and encoded bytes, decode supported primitive defaults losslessly, and leave missing/duplicate/malformed/unsupported declarations explicitly unavailable with coverage diagnostics. Parameter/property constants, enum-name inference, assembly loading/execution and FieldRVA data are outside this slice. I found the earlier intent-to-work comment. Current open/closed PR searches for this issue, HasDefault and managed constant readers found no public implementation; that does not establish the absence of unpublished work. I read the related FieldRVA (#3835) and nominal CIL identity (#4516) production changes: those own different facts and will not be duplicated. No private MixedInKey sample, CLR execution, external provider, other host runtime or performance validation has been performed. New PR author declarations will remain for human confirmation. ### Current delivered revision (2026-10-30) [#8015](https://github.com/morluto/rea/pull/8015) remains open and ready at normal fork head `008e3455e9e9ddaf7abba3f6446da92e713f2877`, after integrating main `317bf3fe235e655b2d752d3be261cc0da7d00f2b` for an actual conflict. The field-focused scope above is unchanged; this does not close the broader parameter/property request. The latest CI-source reproduction had two inherited diagnostic-prose failures (2 FAIL / 17 PASS). Main's canonical typed CLI/Flutter assertions are retained, alongside both-invalid-field and no-Evidence MCP checks; corrected controls pass 28 cases on that exact CI source. Main's independently reproduced unused internal exports/constant aliases were minimally cleaned up with the original Node timer maximum and fixed debugger control allowance unchanged, without gate suppression. Current integrated source validation: 18 focused files / 616 PASS, fresh README 9 PASS = 19 distinct files / 625 PASS / 0 skip. Full check, docs, discovery (2869 files exactly once), package verifier and pack dry-run pass. Actual compiled CLI 7 cases + installed CLI 7 cases + installed stdio MCP 1 session/6 calls verify complete/partial values, retained fields and negative controls. All 2663 product files match current/archive/install; 233 tools and 6 prompts are observed, with awaited transport/package cleanup. Independent frozen Standards and Spec reviews both pass. A normal hook's five unrelated rewrites were blocked before push; ordinary revert and exact replay restored all reviewed source/product bytes without rewriting history. The source tested above is byte-identical to the final delivered source; those tests were not counted as another fresh run after replay. Earlier cleanup uncertainty and external harness failures remain recorded, not relabeled as product failures or erased by later success. Current-head CI/Codex and the human author declarations are separate from local validation. Parameter/property constants, enum-name inference, private MixedInKey input, CLR execution, real external engines/agents, other host runtimes and performance remain unverified/outside this slice.
Author
Owner

@XinwangTao commented on GitHub (Oct 29, 2026):

Thanks for the independent reproduction and for keeping the contribution bounded. The "retain row coordinates/raw bytes, decode supported primitives losslessly, explicitly unavailable for malformed/duplicate/unsupported" split matches the acceptance criteria in the issue. One suggestion: in the coverage diagnostics, distinguish "no Constant row for this parent" from "row present but decode failed" — that keeps the malformed-blob edge testable instead of collapsing both into a single unavailable state. Agreed that parameter/property constants and enum-name inference can wait for a follow-up.

<!-- gh-comment-id:6491340812 --> @XinwangTao commented on GitHub (Oct 29, 2026): Thanks for the independent reproduction and for keeping the contribution bounded. The "retain row coordinates/raw bytes, decode supported primitives losslessly, explicitly unavailable for malformed/duplicate/unsupported" split matches the acceptance criteria in the issue. One suggestion: in the coverage diagnostics, distinguish "no Constant row for this parent" from "row present but decode failed" — that keeps the malformed-blob edge testable instead of collapsing both into a single unavailable state. Agreed that parameter/property constants and enum-name inference can wait for a follow-up.
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#3171
No description provided.