Skip to content

Add Stub IXCLRDataFunctionTableAccess to cDAC#130762

Merged
noahfalk merged 2 commits into
dotnet:mainfrom
noahfalk:noahfalk-add-cdac-function-table-access
Jul 22, 2026
Merged

Add Stub IXCLRDataFunctionTableAccess to cDAC#130762
noahfalk merged 2 commits into
dotnet:mainfrom
noahfalk:noahfalk-add-cdac-function-table-access

Conversation

@noahfalk

Copy link
Copy Markdown
Member

windbg needs an implementation of function table lookup to migrate away from DAC. In DAC this comes from the exported function OutOfProcessFunctionTableCallbackEx but since I didn't want tie the behavior to a specific dll export I created a new interface for it instead.

This just creates the stub of an implementation which will still need to be filled in.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 4 pipeline(s).
11 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@noahfalk

Copy link
Copy Markdown
Member Author

fyi @hoyosjs

Copilot AI review requested due to automatic review settings July 16, 2026 13:03
@noahfalk
noahfalk force-pushed the noahfalk-add-cdac-function-table-access branch from 0c1b26d to ef16b54 Compare July 16, 2026 13:03
@noahfalk
noahfalk force-pushed the noahfalk-add-cdac-function-table-access branch from ef16b54 to f44790a Compare July 16, 2026 13:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new COM surface for function-table lookup in the cDAC “Legacy” layer by introducing IXCLRDataFunctionTableAccess and wiring SOSDacImpl to implement it (currently as an E_NOTIMPL stub), along with a unit test that exercises QueryInterface from IXCLRDataProcess.

Changes:

  • Introduces a new [GeneratedComInterface] COM interface: IXCLRDataFunctionTableAccess with GetFunctionTable(...).
  • Implements IXCLRDataFunctionTableAccess on SOSDacImpl with a stub GetFunctionTable returning E_NOTIMPL.
  • Adds a unit test validating QueryInterface returns the new interface and that calling the stub returns E_NOTIMPL.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

File Description
src/native/managed/cdac/tests/UnitTests/FunctionTableAccessTests.cs Adds a unit test that QIs IXCLRDataProcess for IXCLRDataFunctionTableAccess and calls the stub method.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs Wires SOSDacImpl to implement IXCLRDataFunctionTableAccess and returns E_NOTIMPL from the new method.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/IXCLRData.cs Declares the new IXCLRDataFunctionTableAccess COM interface and GUID.

Comment thread src/native/managed/cdac/tests/UnitTests/FunctionTableAccessTests.cs
Copilot AI review requested due to automatic review settings July 16, 2026 13:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Comment thread src/coreclr/pal/prebuilt/inc/xclrdata.h
Comment thread src/native/managed/cdac/tests/UnitTests/FunctionTableAccessTests.cs Outdated

@max-charlamb max-charlamb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm mod the copilot comment that the C style macros aren't included in xclrdata.h. I don't think this should ever really matter, but its nice for consistency.

@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
  "version": 5,
  "last_dispatched_commit": "f44790a5b5341791c0dbf72a7d1dce50d37d5559",
  "last_dispatched_base_ref": "main",
  "last_dispatched_base_sha": "e5fc9669cc6a67694d46987c753cc13d995b2623",
  "last_reviewed_commit": "f44790a5b5341791c0dbf72a7d1dce50d37d5559",
  "last_reviewed_base_ref": "main",
  "last_reviewed_base_sha": "e5fc9669cc6a67694d46987c753cc13d995b2623",
  "last_recorded_worker_run_id": "29690719329",
  "review_attempt_commit": "",
  "review_attempt_base_ref": "",
  "review_attempt_count": 0,
  "max_review_attempts": 5,
  "review_history_format": "holistic-review-disclosure-v1",
  "review_history": [
    {
      "commit": "f44790a5b5341791c0dbf72a7d1dce50d37d5559",
      "review_id": 4730926021
    }
  ]
}

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holistic Review

Motivation: windbg needs a way to look up dynamic function tables (currently provided by the DAC export OutOfProcessFunctionTableCallbackEx) so it can migrate off the DAC. Rather than tying the behavior to a specific DLL export, the PR introduces a new COM interface for it. This PR establishes only the stub; the actual lookup logic is intentionally deferred.

Approach: A new IXCLRDataProcess3 : IXCLRDataProcess2 interface exposing a single GetFunctionTable method is added to xclrdata.idl, with the matching regenerated MIDL artifacts in pal/prebuilt (xclrdata_i.cpp GUID definition and xclrdata.h interface declaration). The managed cDAC side adds a [GeneratedComInterface] mirror in IXCLRData.cs, implements it on SOSDacImpl returning E_NOTIMPL (while zero-initializing the bytesNeeded/entries outputs), and adds a unit test verifying QueryInterface navigation across IXCLRDataProcess/2/3 (COM identity consistency) plus the E_NOTIMPL contract.

Summary: ✅ LGTM. This is a well-scoped, self-consistent stub. The new GUID ...c798b9 follows the existing sequential convention (...b7, ...b8, ...b9 for IXCLRDataProcess/2/3) and is unique across the IDL, prebuilt, and managed definitions. The IDL, prebuilt .h, and managed signatures agree on parameter order and semantics, the doc comment clearly specifies the intended eventual behavior, and the test exercises both QI identity and the stub contract. These are Legacy/** (SOSDacImpl shim / DacDbi) changes, so per repo cDAC guidance no datacontract doc update or public-API-review is required, and COM ABI/GUID concerns do not apply. One minor, non-blocking observation: the IDL comment states bytesNeeded and entries are "reported on every valid call," while the implementation sets them on the E_NOTIMPL failure path — harmless and arguably safer, just a slight wording mismatch to keep in mind when the method is later implemented.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 56 AIC · ⌖ 10.3 AIC · ⊞ 10K

Copilot AI review requested due to automatic review settings July 21, 2026 07:15
@noahfalk
noahfalk force-pushed the noahfalk-add-cdac-function-table-access branch from f44790a to c17388b Compare July 21, 2026 07:15
@noahfalk
noahfalk enabled auto-merge (squash) July 21, 2026 07:15
@noahfalk
noahfalk disabled auto-merge July 21, 2026 07:16
@noahfalk
noahfalk force-pushed the noahfalk-add-cdac-function-table-access branch from c17388b to f44790a Compare July 21, 2026 07:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (2)

src/coreclr/pal/prebuilt/inc/xclrdata.h:2906

  • The new IXCLRDataProcess3 definition in the prebuilt header only includes the C++ interface form and is missing the corresponding "C style interface" (Vtbl struct + COBJMACROS) that exists for IXCLRDataProcess2. This makes the header inconsistent and breaks C consumers when CINTERFACE is defined; it also suggests the prebuilt file wasn’t regenerated from the IDL.
#ifndef __IXCLRDataProcess3_INTERFACE_DEFINED__
#define __IXCLRDataProcess3_INTERFACE_DEFINED__

/* interface IXCLRDataProcess3 */
/* [uuid][local][object] */

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/IXCLRData.cs:372

  • This introduces a new public interface (IXCLRDataProcess3) in a shipped NuGet (IsPackable=true). If this type is only used for internal COM surface (WinDbg/native callers) and tests already have InternalsVisibleTo, consider making it internal to avoid expanding managed public API surface (and the associated API-approval requirements).
[GeneratedComInterface]
[Guid("5c552ab6-fc09-4cb3-8e36-22fa03c798b9")]
public unsafe partial interface IXCLRDataProcess3 : IXCLRDataProcess2
{

Copilot AI review requested due to automatic review settings July 21, 2026 07:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Comment thread src/native/managed/cdac/tests/UnitTests/FunctionTableAccessTests.cs Outdated
Comment thread src/native/managed/cdac/tests/UnitTests/FunctionTableAccessTests.cs Outdated
Comment thread src/coreclr/inc/xclrdata.idl Outdated
windbg needs an implementation of function table lookup to migrate away from DAC. In DAC this comes from the
exported function OutOfProcessFunctionTableCallbackEx but since I didn't want tie the behavior to a specific dll
export I created a new interface for it instead.

This just creates the stub of an implementation which will still need to be filled in.
Copilot AI review requested due to automatic review settings July 21, 2026 07:29
@noahfalk
noahfalk force-pushed the noahfalk-add-cdac-function-table-access branch from bf4d0a7 to c39bdd2 Compare July 21, 2026 07:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs:35

  • bytesNeeded and entries are documented as required output parameters (see xclrdata.idl) and other SOSDacImpl methods generally return E_POINTER when required out-pointers are null. The current stub silently tolerates null pointers, which would leave callers with undefined outputs and makes debugging harder.
    int IXCLRDataProcess3.GetFunctionTable(
        ClrDataAddress tableAddress,
        uint bufferSize,
        byte* buffer,
        uint* bytesNeeded,
        uint* entries)
    {
        if (bytesNeeded is not null)
            *bytesNeeded = 0;
        if (entries is not null)
            *entries = 0;

        return HResults.E_NOTIMPL;
    }

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/IXCLRData.cs:372

  • This adds a new public API surface (IXCLRDataProcess3) in a packable assembly. If this type isn't intended as a supported public contract, consider making it internal (tests can still access it via the existing InternalsVisibleTo) to avoid taking on a public API compatibility burden / API-approval requirements.
[GeneratedComInterface]
[Guid("5c552ab6-fc09-4cb3-8e36-22fa03c798b9")]
public unsafe partial interface IXCLRDataProcess3 : IXCLRDataProcess2
{

src/coreclr/pal/prebuilt/inc/xclrdata.h:2928

  • xclrdata.h is marked as an ALWAYS GENERATED MIDL output, and the new IXCLRDataProcess3 block is missing the usual #else /* C style interface */ section (present on IXCLRDataProcess2, etc.). This looks like a partial/manual edit or an incomplete regeneration and can break C/CINTERFACE consumers.
#ifndef __IXCLRDataProcess3_INTERFACE_DEFINED__
#define __IXCLRDataProcess3_INTERFACE_DEFINED__

/* interface IXCLRDataProcess3 */
/* [uuid][local][object] */


EXTERN_C const IID IID_IXCLRDataProcess3;

#if defined(__cplusplus) && !defined(CINTERFACE)

    MIDL_INTERFACE("5c552ab6-fc09-4cb3-8e36-22fa03c798b9")
    IXCLRDataProcess3 : public IXCLRDataProcess2
    {
    public:
        virtual HRESULT STDMETHODCALLTYPE GetFunctionTable(
            /* [in] */ CLRDATA_ADDRESS tableAddress,
            /* [in] */ ULONG32 bufferSize,
            /* [size_is][out] */ BYTE *buffer,
            /* [out] */ ULONG32 *bytesNeeded,
            /* [out] */ ULONG32 *entries) = 0;

    };

#endif

#endif 	/* __IXCLRDataProcess3_INTERFACE_DEFINED__ */

Copilot AI review requested due to automatic review settings July 21, 2026 08:06
@noahfalk
noahfalk enabled auto-merge (squash) July 21, 2026 08:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/IXCLRData.cs:380

  • This introduces a new public COM interface (IXCLRDataProcess3) in the managed cDAC Legacy surface. New public API surface in dotnet/runtime requires an approved API proposal/issue (api-approved) or the API should be kept internal until approval is obtained. If this is intended to be internal-only, consider making the interface (and corresponding implementation exposure) internal and using InternalsVisibleTo for the test project; otherwise, please link the approved API issue in the PR description.
[GeneratedComInterface]
[Guid("5c552ab6-fc09-4cb3-8e36-22fa03c798b9")]
public unsafe partial interface IXCLRDataProcess3 : IXCLRDataProcess2
{
    [PreserveSig]
    int GetFunctionTable(
        ClrDataAddress tableAddress,
        uint bufferSize,
        byte* buffer,
        uint* bytesNeeded,
        uint* entries);
}

@noahfalk
noahfalk merged commit 6492ffa into dotnet:main Jul 22, 2026
137 checks passed
max-charlamb pushed a commit to max-charlamb/runtime that referenced this pull request Jul 23, 2026
Fills in the stub added in dotnet#130762 so out-of-process unwinders (windbg)
can enumerate dynamic function tables via cDAC instead of the DAC's
exported OutOfProcessFunctionTableCallbackEx.

- Add ExecutionManager.GetDynamicFunctionTableEntries, a faithful port of
  OutOfProcessFunctionTableCallbackEx: strip the DYNAMIC_FUNCTION_TABLE
  Context flag bits to find the owning EEJitManager, match a code heap by
  module base (HeapList::GetModuleBase - CLRPersonalityRoutine when set,
  else MapBase), then reverse-walk the nibble map collecting each real
  code header's inline RUNTIME_FUNCTION entries (skipping stub blocks).
- Add data descriptors: DynamicFunctionTable (Context, MinimumAddress)
  and CodeHeapListNode.CLRPersonalityRoutine (64-bit only).
- Implement SOSDacImpl.IXCLRDataProcess3.GetFunctionTable marshaling per
  the IDL contract (E_POINTER, size query, S_FALSE, S_OK).
- Update ExecutionManager data contract doc and add unit tests covering
  enumeration order, stub filtering, module-base matching (including the
  zero-personality-routine fallback), and the COM buffer semantics.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1b09fa3f-0aee-4846-84e2-0930640d03cc
max-charlamb pushed a commit to max-charlamb/runtime that referenced this pull request Jul 24, 2026
Fills in the stub added in dotnet#130762 so out-of-process unwinders (windbg)
can enumerate dynamic function tables via cDAC instead of the DAC's
exported OutOfProcessFunctionTableCallbackEx.

- Add ExecutionManager.GetDynamicFunctionTableEntries, a faithful port of
  OutOfProcessFunctionTableCallbackEx: strip the DYNAMIC_FUNCTION_TABLE
  Context flag bits to find the owning EEJitManager, match a code heap by
  module base (HeapList::GetModuleBase - CLRPersonalityRoutine when set,
  else MapBase), then reverse-walk the nibble map collecting each real
  code header's inline RUNTIME_FUNCTION entries (skipping stub blocks).
- Add data descriptors: DynamicFunctionTable (Context, MinimumAddress)
  and CodeHeapListNode.CLRPersonalityRoutine (64-bit only).
- Implement SOSDacImpl.IXCLRDataProcess3.GetFunctionTable marshaling per
  the IDL contract (E_POINTER, size query, S_FALSE, S_OK).
- Update ExecutionManager data contract doc and add unit tests covering
  enumeration order, stub filtering, module-base matching (including the
  zero-personality-routine fallback), and the COM buffer semantics.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1b09fa3f-0aee-4846-84e2-0930640d03cc
hoyosjs pushed a commit that referenced this pull request Jul 25, 2026
Fills in the `IXCLRDataProcess3::GetFunctionTable` stub added in #130762
so out-of-process unwinders (such as windbg) can enumerate dynamic
function tables via cDAC instead of the DAC''s exported
`OutOfProcessFunctionTableCallbackEx`.

## What

- **Contract**: Adds
`IExecutionManager.GetDynamicFunctionTableEntries(tableAddress)`, a
faithful port of `OutOfProcessFunctionTableCallbackEx`
(`src/coreclr/debug/daccess/fntableaccess.cpp`):
- Reads the target `DYNAMIC_FUNCTION_TABLE`, strips the `Context` flag
bits to find the owning `EEJitManager`, and walks its code-heap list.
- Matches the heap by module base using `HeapList::GetModuleBase`
semantics (the personality routine when set, otherwise the map base)
against `MinimumAddress`.
- Reverse-walks the nibble map from the end of the used region, resolves
each real code header (skipping stub code blocks), and collects the
inline `RUNTIME_FUNCTION` entries.
- **Data descriptors**: Adds `DynamicFunctionTable` (`Context`,
`MinimumAddress`) and `CodeHeapListNode.CLRPersonalityRoutine` (64-bit
only).
- **SOS shim**: Implements
`SOSDacImpl.IXCLRDataProcess3.GetFunctionTable` marshaling per the IDL
contract — `E_POINTER` for null out-params, always reports required
byte/entry counts, `S_OK` with zero for an empty/unmatched table,
`S_FALSE` for a size query or undersized buffer, `S_OK` after copying
the contiguous `RUNTIME_FUNCTION` bytes.
- **Docs**: Updates `docs/design/datacontracts/ExecutionManager.md` with
the new API, descriptor fields, and algorithm.

## Testing

- New unit tests (all 4 architectures x c1/c2 nibble-map versions)
covering enumeration order, stub filtering, module-base matching
(including the zero-personality-routine fallback to map base), and the
COM buffer semantics (size query, too-small buffer, successful copy,
unmatched table).
- Full cDAC unit suite passes; `build.cmd clr` succeeds (validates the
descriptor compiles).

> [!NOTE]
> This pull request was authored with the assistance of GitHub Copilot
(AI).

---------

Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1b09fa3f-0aee-4846-84e2-0930640d03cc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants