-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[cdac] Add basic cdacreader project #100623
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
add_library(cdacreader_api INTERFACE) | ||
target_include_directories(cdacreader_api INTERFACE ${CLR_SRC_NATIVE_DIR}/managed/cdacreader/inc) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
#ifndef CDAC_READER_H | ||
#define CDAC_READER_H | ||
|
||
#ifdef __cplusplus | ||
extern "C" | ||
{ | ||
#endif | ||
|
||
int cdac_reader_init(intptr_t descriptor, intptr_t* handle); | ||
int cdac_reader_free(intptr_t handle); | ||
int cdac_reader_get_sos_interface(intptr_t handle, IUnknown** obj); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif // CDAC_READER_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Runtime.InteropServices; | ||
using System.Runtime.InteropServices.Marshalling; | ||
|
||
namespace Microsoft.Diagnostics.DataContractReader; | ||
|
||
internal static class Entrypoints | ||
{ | ||
private const string CDAC = "cdac_reader_"; | ||
|
||
[UnmanagedCallersOnly(EntryPoint = $"{CDAC}init")] | ||
private static unsafe int Init(nint descriptor, IntPtr* handle) | ||
{ | ||
Target target = new(descriptor); | ||
GCHandle gcHandle = GCHandle.Alloc(target); | ||
*handle = GCHandle.ToIntPtr(gcHandle); | ||
return 0; | ||
} | ||
|
||
[UnmanagedCallersOnly(EntryPoint = $"{CDAC}free")] | ||
private static unsafe int Free(IntPtr handle) | ||
{ | ||
GCHandle h = GCHandle.FromIntPtr(handle); | ||
h.Free(); | ||
return 0; | ||
} | ||
|
||
/// <summary> | ||
/// Get the SOS-DAC interface implementation. | ||
/// </summary> | ||
/// <param name="handle">Handle crated via cdac initialization</param> | ||
/// <param name="obj"><c>IUnknown</c> pointer that can be queried for ISOSDacInterface*</param> | ||
/// <returns></returns> | ||
[UnmanagedCallersOnly(EntryPoint = $"{CDAC}get_sos_interface")] | ||
private static unsafe int GetSOSInterface(IntPtr handle, nint* obj) | ||
{ | ||
ComWrappers cw = new StrategyBasedComWrappers(); | ||
Target? target = GCHandle.FromIntPtr(handle).Target as Target; | ||
if (target == null) | ||
return -1; | ||
|
||
SOSDacImpl impl = new(target); | ||
nint ptr = cw.GetOrCreateComInterfaceForObject(impl, CreateComInterfaceFlags.None); | ||
*obj = ptr; | ||
return 0; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Runtime.InteropServices; | ||
using System.Runtime.InteropServices.Marshalling; | ||
|
||
namespace Microsoft.Diagnostics.DataContractReader; | ||
|
||
[GeneratedComInterface] | ||
[Guid("4eca42d8-7e7b-4c8a-a116-7bfbf6929267")] | ||
internal partial interface ISOSDacInterface9 | ||
{ | ||
int GetBreakingChangeVersion(); | ||
} | ||
|
||
/// <summary> | ||
/// Implementation of ISOSDacInterface* interfaces intended to be passed out to consumers | ||
/// interacting with the DAC via those COM interfaces. | ||
/// </summary> | ||
[GeneratedComClass] | ||
internal sealed partial class SOSDacImpl : ISOSDacInterface9 | ||
{ | ||
private readonly Target _target; | ||
|
||
public SOSDacImpl(Target target) | ||
{ | ||
_target = target; | ||
} | ||
|
||
public int GetBreakingChangeVersion() | ||
{ | ||
// TODO: Return non-hard-coded version | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This API represents versions of (poorly defined) set of algorithmic and data contracts that SOS and CLRMD happens to depend on. It should eventually obsoleted, and SOS and CLRMD switched to use the versions of properly defined contracts. (It is ok to keep it for now if it helps.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we trying to implement the actual C++ ISOSDacInterface9 interface here ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We're trying to implement the actual ISOSDacInterface9 here. This is going to be consumed by the existing DAC in cases where it will delegate to the cdacreader.
It is not a goal right now to define a public interface to the cDAC There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then shouldn't the C# method be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
COM interop has elided the The one caveat for this is when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Agreed. At least for now, since all the sos commands use it, I chose it as the simple starting point for putting together what @lambdageek mentions about the existing DAC consuming/delegating to the cdacreader. |
||
return 4; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
namespace Microsoft.Diagnostics.DataContractReader; | ||
|
||
internal sealed class Target | ||
{ | ||
public Target(nint _) | ||
{ | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>$(NetCoreAppToolCurrent)</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
<!-- Do not produce a public package. This ships as part of the runtime --> | ||
<IsShippingPackage>false</IsShippingPackage> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<InstallRuntimeComponentDestination Include="." /> | ||
<!-- TODO: [cdac] Output to sharedFramework and add PlatformManifestFileEntry for Microsoft.NETCore.App once ready to include in shipping package --> | ||
<!-- <InstallRuntimeComponentDestination Include="sharedFramework" Condition="'$(RuntimeFlavor)' == 'coreclr'"/> --> | ||
</ItemGroup> | ||
|
||
</Project> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to adopt an
HRESULT
pattern for error codes or more of a POSIX pattern?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the
Target
class the data target (likeICLRDataTarget
) that will have read memory etc. methods on it?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's
Target
from https://github.com/dotnet/runtime/blob/main/docs/design/datacontracts/contract_csharp_api_design.cs#L85it's the cDAC's internal abstraction for the target process
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does hosting code provide a ICLRDataTarget instance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not wired up yet in this PR, but in the previous prototypes the cDAC exported a function like:
that was called from the existing DAC, passing a callback that wrapped
ReadDataFromTarget
:https://github.com/lambdageek/runtime/blob/ab6e9603222842034c4f4452816e14371db450d9/src/coreclr/debug/daccess/cdac.cpp#L262-L296
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't feel strongly either way, but I went
HRESULT
of negative being error since that is what exports on coreclr and hosting components do.