mirror of
https://github.com/morluto/rea.git
synced 2026-11-05 06:45:22 +00:00
[GH-ISSUE #3624] [Feature] Native C++ semantic reconstruction: RTTI, vtables, class hierarchies, and virtual dispatch #1350
Open
opened 2026-10-16 21:04:33 +00:00 by bsakaguchi
·
4 comments
No Branch/Tag specified
main
codex/procedure-reference-stacked
release-please--branches--main--components--rea-agents
release-please--branches--main--components--rea-agents--release-notes
codex/kuna-independent-retry
codex/byte-search-overlay-coverage
codex/open-failure-target-receipt
codex/kuna-xref-evidence
codex/ghidra-ambiguous-procedure-recovery
codex/function-source-bundle
codex/trace-function-integration-prototype
codex/snapshot-source-closure
codex/recorded-evidence-array-pages
codex/evidence-recovery-redesign
codex/trace-feature-address-scope
codex/call-discovery-scope
codex/ghidra-literal-candidate-evidence
codex/decompile-directory-independent-retry
codex/retry-provenance-base
codex/value-flow-capability-experiment
codex/ghidra-containing-instruction
cursor/readme-discord-button-ef9f
dependabot/github_actions/actions/setup-node-7.1.0
dependabot/github_actions/actions/upload-artifact-7.0.2
dependabot/npm_and_yarn/npm-minor-and-patch-d8d97ce6df
codex/kuna-1989
fix/8559-native-ui-fixture-ownership
fix/8555-go-verifier-mcp-ownership
codex/provider-capability-recovery
fix/8642-rizin-target-stdin
codex/ghidra-memory-effect-scope
codex/ghidra-annotation-entry-selector
codex/ghidra-readonly-recovery
codex/ghidra-regex-verifier-recovery
codex/evidence-discovery-view-guidance
fix/8545-bulk-append-overflow
fix/8428-navigation-refusal-alternatives
codex/address-context-recovery
codex/matching-member-limitations
codex/unknown-scope-contract
codex/evidence-view-guidance
feat/8373-native-trace-views
codex/ghidra-snapshot-verifier-binding
codex/elf-export-visibility
codex/evidence-view-recovery
codex/native-reference-cli-help
codex/provider-candidate-observation-scope
codex/kuna-session-verification
codex/ghidra-switch-lifetime-guidance
codex/pseudocode-paging-discovery
codex/clarify-evidence-view-support
codex/kuna-xrefs-selector-recovery
codex/context-capacity-recovery
codex/evidence-closure-large-links
codex/same-function-evidence-identity
codex/ghidra-verifier-inspected-jdk
codex/audit-guided-workflows
codex/crash-prompt-retained-dossiers
codex/analysis-view-error-recovery
codex/kuna-verifier-target-selection
codex/ghidra-selected-project-call-coverage
codex/docs-native-analysis-scope
codex/ghidra-java-socket-boundary
codex/ghidra-retained-snapshot-verifier
codex/ghidra-search-inventory-facts
fix/8284-zero-argument-parameter-bindings
fix/8198-ui-action-handler-offset
fix/8257-elf-entry-label-identity
fix/8304-deferred-output-schema-projection
fix/8277-call-path-computed-target-uncertainty
fix/pr-8089-conflicts
fix/ci-static-duplicate-export
dependabot/npm_and_yarn/lint-staged-17.6.0
dependabot/github_actions/actions/download-artifact-8.0.2
dependabot/npm_and_yarn/write-file-atomic-8.0.0
dependabot/npm_and_yarn/canonicalize-5.1.0
dependabot/github_actions/actions/cache/restore-6.1.0
dependabot/npm_and_yarn/toon-format/toon-4.4.0
dependabot/github_actions/actions/deploy-pages-5.0.1
codex/review-fixes-pr-2403
codex/review-fixes-pr-2400
codex/process-terminal-width
codex/test-brittleness-cleanup
verify/7167-browser-connect-macos
fix/7167-browser-connect
feat/native-matching-allowance-setting
feat/browser-scenario-dry-run
test/managed-caller-parameters-20261024
codex/parser-fortythird-boundaries
fix/6926-pinvoke-platform-decorations-20261023
fix/6889-har-body-encoding-20261023
fix/6888-sqlite-schema-budget-20261023
fix/dependency-security-gates-6708
cursor/evidence-overwrite-rebase-b4ac
feat/4057-verify-native-exports
fix/windows-acl-observer-overhead-20261022
cursor/erlang-beam-restack-4476
cursor/pe-certificate-review-bf32
fix/6116-javascript-application-fs-errors
fix/6061-unmapped-runtime-script-unknown
feat/browser-scenario-summary
fix/pe-certificates
codex/verify-3407
cursor/rebase-5699
cursor/rebase-5352
cursor/rebase-5600
cursor/fix-cli-schema-omission-10a8
codex/audit-hopper-shutdown-reasons-20261021
fix/demangle-swift-omitted-record
fix/nib-boolean-value-types
cursor/cancellation-partial-observation-a5ac
fix/ib-object-limit-reasons
fix/electron-fuse-limit-advice
fix/kuna-doctor-dangling-cache
fix/fixed-budget-refusal-advice
fix/js-ipc-listener-dedup
fix/js-return-member-provenance
fix/dmg-integrity-retry-advice
fix/ida-doctor-readiness
fix/kuna-version-probe-output-drain
fix/legacy-swift-runtime-name-matching
fix/dylib-lazy-load-commands
fix/browser-scenario-startup-cancel
fix/swift-nested-punycode-classification
fix/compare-unselected-scopes
fix/objc-method-budget-coverage
fix/dmg-mounted-root-observations
audit/ci-tests-20261019-round2
release/6.7.0
fix/wabt-cleanup-retry-resolution
fix/electron-fuse-elf-pe-architecture
fix/native-plist-descriptor-ownership
fix/kuna-caller-cleanup-ownership
experiment/atomic-codemode-20261016
review/first-contributor-3776
fix/call-resolution-full-read-cycles
fix/member-mutation-selection-repeat
experiment/atomic-re-tools-20261015
perf/member-mutation-lazy-origins
perf/static-network-mutation-index
fix/hopper-startup-lifecycle
audit/3050-windows-proof-20261015
feat/windows-window-capture-2183
audit/3049-windows-proof-20261015
audit/3735-macos-fixtures-20261015
fix/batch-decompile-null-pseudocode
fix/kuna-inventory-honors-jobs
experiment/browser-codemode-tool-design-20261015
fix/hopper-clean-runtime-argv
codex/review-2049-27f1b367
review-fixes/pr-2787-routing
fix/3360-scoped-this-emitters
fix/3367-replaced-global-effects
fix/3838-compact-any-value-items
test/hopper-download-probe-20261015
codex/windows-runtime-creation-red-green-20261015
codex/windows-readonly-root-red-green-20261015
codex/windows-root-share-red-green-20261015
codex/exp-1685-win-mcp-startup
codex/bug-sweep-20261015
investigate/2190-windows-package-phases
investigate/3543-macos-cli-deadline
perf/3281-reverse-tools-feedback-quality
fix/3406-hopper-doctor-fixture
fix/3341-wrapper-require-test-context
fix/3301-owned-uninstall-fixtures
fix/3164-compiler-input-ownership
fix/pcap-cleanup-stdout-newline-20261014
perf/interface-builder-summary
codex/review-fixes-pr-1977
fix/ghidra-effective-jvm-platform
fix/docs-turkish-rust-link-20261013
fix/main-maintenance-ci-20261010
fix/recover-binary-session-process-effects
codex/review-fixes-pr-2457
codex/ci-required-cancellation-gate
fix/main-format-baseline-20261013
fix/setup-preserve-entry-fields
cursor/restore-main-checks-1ffc
fix/ghidra-bridge-hashmap-import
codex/shared-ci-jadx-json-default-20261013
codex/shared-ci-ghidra-test-groups-20261013
codex/shared-ci-java-fixture-format-20261013
codex/fix-intrinsic-invocation-boundaries
test/release-preflight-reusable-jobs
test/js-parameter-provenance-expectation
fix/linux-hopper-verification-current
test/2419-ghidra-elf-probe-size
followup/pr-1544-native-ida
codex/fold-pr-2230-contribution
docs/readme-responsible-use
fix/issue-2064
fix/issue-2050
fix/issue-2053
fix/issue-1968
fix/issue-1945
experiment/codemode-bridge-20261011
fix/tool-effects-negative-wording-1904-20261012
fix/1842-electron-interop-provenance
feat/recover-javascript-multi-input
refactor/website-i18n-prep
fix/nativeaot-pe-virtual-extent
fix/browser-verifier-ci-hang
fix/pe-resources-input-selection
docs/beginner-friendly-guides
docs/beginner-setup-guide
fix/javascript-analysis-worker-1563
fix/1649-ghidra-duplicate-names
fix/javascript-export-keys-integration-1369
test/maintenance-boundary-contracts-20261011
review/javascript-export-keys-1369
review/process-live-progress-1483
test/javascript-1495-growth-ratio
fix/ci-escape-timing
docs/normalized-terminal-geometry-1450
release/6.3.0
archive/release-6.3.0-pr1381
release/6.2.0
fix/electron-preload-dynamic-override
fix/javascript-self-referential-bundler-edges
release/6.1.0
cursor/grok-client-cherry-pick-0b56
feat/signature-posture
feat/dyld-shared-cache
feat/artifact-integrity-policy
feat/pkg-inventory
release/6.0.0
chore/sync-release-5.0.0
release/5.0.0
cursor/cloud-agent-node-787e
fix/javascript-xhr-open-endpoints
review/pr-711-realpath-fallback-wording
cleanup/replay-confinement
codex/test-suite-performance
codex/issue-foundations
codex/address-open-issues-2026-07-20
agent/javascript-vite-rollup-esbuild-adapters
agent/process-cleanup
agent/triage-integration
agent/unknown-commands-registry
feat/mcp-identity-metadata
morlvps/issue_cleanup
codex/installer-redesign
morl/roadmap-investigation-core
morl/roadmap-investigation-docs
release-please--branches--main--components--rea
rea-agents-6.8.0
rea-agents-6.7.0
rea-agents-6.6.0
experiment/atomic-codemode-wait-runtime-20261016
rea-agents-6.5.0
rea-agents-6.4.0
rea-agents-6.3.0
rea-agents-6.2.0
rea-agents-6.1.0
rea-agents-6.0.0
rea-agents-5.0.0
rea-agents-4.1.0
rea-agents-4.0.1
rea-agents-4.0.0
rea-agents-3.2.1
rea-agents-3.2.0
rea-agents-3.1.0
rea-agents-3.0.0
rea-agents-2.7.0
rea-agents-2.6.0
rea-agents-2.5.1
rea-agents-2.5.0
rea-agents-2.4.0
rea-agents-2.3.0
rea-agents-2.2.0
rea-agents-2.1.0
rea-agents-2.0.0
rea-agents-1.7.0
rea-agents-1.6.0
rea-agents-1.5.0
rea-agents-1.4.0
rea-agents-1.3.0
rea-agents-1.2.0
rea-agents-1.1.0
rea-agents-1.0.0
rea-agents-0.5.0
rea-agents-0.4.0
rea-agents-0.3.0
rea-0.2.1
rea-0.2.0
Labels
Clear labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
Mirrored from GitHub Pull Request
question
roadmap
triage
No labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
question
roadmap
triage
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
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#1350
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @matbrgz on GitHub (Oct 14, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/3624
Summary
Modern native applications, game engines, operating system utilities, browser engines, and malware are predominantly authored in C++. However, when compiled into native executables and shared libraries (PE/COFF on Windows, ELF on Linux/Android, Mach-O on Apple), the high-level object-oriented architecture is flattened into raw assembly instructions, unannotated memory offsets, and indirect virtual call sites.
Currently, REA's native analysis pipeline (via Ghidra, Hopper, and Rizin) treats native code at the level of isolated functions, basic blocks, and strings. Outside of specialized Swift vtable decoding on Apple targets (
src/native/AppleSwiftVtables.ts), REA does not recover C++ object-oriented semantics. Functions remain anonymous subroutines, virtual calls (call qword ptr [rax + 0x20]) remain unresolved indirect branches, and class inheritance structures are invisible.This feature proposal introduces Native C++ Semantic Reconstruction to REA: extracting Run-Time Type Information (RTTI) and virtual function tables (vtables) across both major compiler ABIs (MSVC and Itanium C++ ABI), reconstructing class inheritance hierarchies and memory layouts, resolving virtual dispatch call sites, and hydrating Ghidra/Rizin with qualified class structures.
Technical Capabilities & Architecture
1. MSVC C++ RTTI & Vftable Reconstruction (Windows PE/COFF)
RTTICompleteObjectLocator):RTTICompleteObjectLocatorstructures.signature == 1).offset), constructor displacement (cdOffset), and type descriptor pointers..?AVPlayerController@@,.?AUInterface@@) and invoke demangling to recover clean C++ namespaces and class names.RTTIClassHierarchyDescriptor):RTTIBaseClassArray) and individualRTTIBaseClassDescriptorrecords.vbtable): Identify and map MSVCvbtablestructures used for resolving virtual base class offsets.2. Itanium C++ ABI RTTI & Vtable Reconstruction (Linux/Android ELF & macOS Mach-O)
_ZTVsymbols or heuristic pointer tables preceded by an offset-to-top and a typeinfo pointer).offset-to-top(offset of the subobject within the complete object) andRTTI pointer.type_info) Hierarchy Traversal:abi::__class_type_info(root classes with no bases).abi::__si_class_type_info(single public, non-virtual inheritance, extracting parent typeinfo pointer).abi::__vmi_class_type_info(multiple and virtual inheritance, parsing base class flags, offsets, and non-virtual/virtual flags)._ZTT) and construction vtables (_ZTC) used during base class construction in complex inheritance hierarchies.3. Virtual Dispatch & Indirect Call Resolution
thispointer initialization in constructors and destructors (this->__vftable = &ClassName::vftable).call [rax + slot_offset]), resolving call targets against the vtable slot index of candidate classes.sub rcx, 0x10; jmp RealMethod) used in multiple inheritance, associating them with the primary virtual implementation.4. Class Memory Layout & Special Member Function Discovery
operator deletewrappers).vptr, virtual base table pointers (vbptr), base class subobjects, and member field offsets inferred from constructor initialization lists.5. Provider Hydration (Ghidra & Rizin)
ClassName_vtbl), and interface types directly into Ghidra and Rizin program databases.FUN_140010200->PlayerController::OnDamageTaken).inspect_native_classesand enrichinspect_native_functionsdossiers.Acceptance Criteria
inspect_native_classesin REA CLI and MCP contracts, accepting PE, ELF, and Mach-O binaries.Related
@morluto commented on GitHub (Oct 31, 2026):
Real-provider control for the analyst question “what might this C++ virtual call reach?” I compiled, but did not run, an arm64 Mach-O with a
Basevirtual method, two derived implementations (DoublerandOffsetter), a sharedaudit_dispatch(Base *, int)and one caller constructing each derived object. The selected source was built with Clang-O1 -g -fno-inline -fno-optimize-sibling-calls; this is a small symbolized single-inheritance fixture, not a general C++ corpus.On REA
e6d0618979f0df3f1d5db218b0fc7b5e6a9cf3f9using real Ghidra 12.1.4 and Kuna 1.986 through MCP:Doublerbefore calling the shared dispatch function. This is a useful existing observation, not proof that stripped C++ functions are named or that a recovered name is a class hierarchy.blrat0x10000055c. Ghidraprocedure_referencesretained it as an unresolved site,resolve_native_call_targetsreturnedunresolved, andtrace_native_valuesretained a call-target unknown. Both providers'trace_call_pathresults from the two callers to their corresponding implementation wereunknownwith partial coverage. Kuna's typed call-reference and call-target operations were unavailable. These are appropriate limits for the genericBase *dispatch, not proof that no implementation can run.read_bytesof the selected slot returned the corresponding method address, and an incoming xref from each method included that slot. The two slots and methods remained separate. This can motivate a provenance-bound candidate for a particular constructor/call context, but these separate facts are not an automatic object-flow proof or runtime dispatch observation.inspect_native_load_imagerelocation page reported anAPPLIEDrelocation at each slot with both byte sequences; independent file reads agreed with the original bytes. A future candidate workflow should preserve source versus loaded bytes, pointer fixups, address space, selection and uncertainty rather than decode an unqualified raw pointer.This narrows the blanket statement that every C++ function is anonymous: the current inventory can retain names on this symbolized sample, and useful low-level primitives already exist. It does not establish RTTI parsing, inheritance completeness, cross-function object flow, stripped-binary support, or safe provider hydration. No additional tool or mutation authority follows from this one case. Both sessions closed, and the target SHA-256 was unchanged.
@morluto commented on GitHub (Oct 31, 2026):
Stripped control for the preceding fixture: I copied the binary and ran
strip -u -ron the copy before analysis.llvm-nmno longer listed the authored C++ methods, constructors, or vtable symbols; the fixture still contained class-name strings and RTTI-related material, so this is not an RTTI-free or metadata-free control.Both real REA/Ghidra and REA/Kuna procedure inventories used generated names for the known code addresses, while
search_stringsfound7Doublerand9Offsetter. The generic virtual call stayed unknown in both providers' call paths. On Ghidra, starting at the selected7Doublerstring,xrefsfound a typeinfo-member address; using the known Itanium layout to select its containing record then exposed an incoming reference from the vtable's typeinfo field. A separately selected vtable function slot pointed through loaded memory to the known implementation, and another xref connected the slot to the constructor. This was a scripted, analyst-guided chain using the unstripped control and ABI knowledge; no agent autonomously derived the structure, and the observations do not prove runtime dispatch.For the same string and selected slots, REA/Kuna
xrefsreturned no rows and itsread_bytesoperation was unavailable. Direct Kuna 1.986xrefs --toalso returned zero references to that string in this fixture, while directreadof the function slot returned3c05000000001000, matching an independent source-file read. Ghidra's initialized-memoryread_bytesat that slot returned3c05000001000000; the earlier relocation control recorded the loader adjustment. This reinforces #8170: forwarding a successful Kuna read as equivalent to the initialized-memory contract would lose an important distinction.The stripped copy's own Ghidra load-image relocation page also reported
APPLIEDat both slots and retained those distinct original and memory byte sequences. The original binary was preserved; the stripped copy's digest stayed unchanged throughout provider analysis and neither was executed. This is one arm64 Mach-O with remaining RTTI material, not general stripped-code coverage or a complete reference inventory.@morluto commented on GitHub (Oct 31, 2026):
Additional
-fno-rtticontrol: I rebuilt the same source with Clang-fno-rtti, copied and stripped it withstrip -u -r, and analyzed the copy without executing it.llvm-nmon the unstripped build showed vtable symbols but notypeinfosymbols; the stripped copy's symbol table no longer listed the authored methods or vtables. This tests one compiler/ABI/fixture, not every possible RTTI-disabled binary.Both REA/Ghidra and REA/Kuna returned generated procedure names and an
unknowncall path to the selected implementation, with partial coverage at the indirect call. With the implementation, constructor, and vtable-slot addresses taken from the unstripped control, Ghidra still showed the constructor's pointer to the slot, read the loaded slot value as the method address, and returned the constructor in the slot's xrefs. Kuna's constructor pseudocode retained the same slot address, but its byte read was unavailable and slot xrefs returned no rows. These are useful selected facts, not an automatically discovered class or runtime target.The string control also matters: REA/Kuna
search_strings("Doubler")returned no rows, while REA/Ghidra returned several fragments. Ghidra's load-image mapping placed the selected fragment in its__LINKEDITblock, andaddress_to_file_offsetmapped it to retained file bytes;xrefsfor that fragment was empty. It is therefore a residual string observation, not evidence that RTTI for that class was recovered. The selected target and original control were not executed or modified during provider analysis. This also reinforces #8245's distinction between string matches, mapping provenance and meaning.@morluto commented on GitHub (Oct 31, 2026):
Multiple-inheritance control for candidate identity: I built an unexecuted arm64 Mach-O with
Both : Left, Right, with a virtualRight::rightoverride. The compiler emitted a secondary vtable entry for a non-virtual adjustment thunk at0x100000558; independent LLVM disassembly showed it subtracts 8 from the incoming object pointer and calls the implementation at0x10000054c. This fixture used-fno-optimize-sibling-calls, so its thunk is a call-and-return wrapper rather than a tail jump.Real REA/Ghidra 12.1.4 showed the constructor installing a second vtable pointer,
read_bytesat the selected secondary slot0x1000040c8returned the thunk address, and an xref linked that slot to the constructor. The thunk's pseudocode retained thethis - 8adjustment;trace_native_valuesretained a derived pointer-add operation flowing into the direct call, andtrace_call_pathfrom thunk to implementation reached the implementation. The generic virtual call remained unresolved, with the constructor-to-implementation pathunknown. These separately selected facts do not establish runtime dispatch.Ghidra
procedure_inforeportedclassification.thunk: falsewithghidra-function-managerprovenance for this compiler-generated adjustment wrapper. That is Ghidra's own function classification, not proof that the entry has no C++ adjustment role; the pseudocode comment and instruction evidence show that distinction here. Ghidra's inventory displayed both entry addresses asBoth::right; a name-only request was refused as ambiguous and supplied both exact addresses for recovery. REA/Kuna gave the wrapper a distinct{virtual override thunk}name and its path to the implementation was reached, but typed byte/call-reference tools remained unavailable. Direct Kuna xrefs from the wrapper reported its direct call.For a future candidate workflow, preserving the actual vtable entry, the adjustment and the separately evidenced implementation avoids silently replacing a callable entry with a different address or losing its object-pointer semantics. This is one symbolized compiler/architecture case; it does not establish all inheritance, thunk, ABI or stripped-target behavior. The target digest stayed unchanged and no target was executed.