diff --git a/src/native/managed/cdacreader/cmake/CMakeLists.txt b/src/native/managed/cdacreader/cmake/CMakeLists.txt
new file mode 100644
index 0000000000000..2a7459c37b851
--- /dev/null
+++ b/src/native/managed/cdacreader/cmake/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_library(cdacreader_api INTERFACE)
+target_include_directories(cdacreader_api INTERFACE ${CLR_SRC_NATIVE_DIR}/managed/cdacreader/inc)
diff --git a/src/native/managed/cdacreader/inc/cdac_reader.h b/src/native/managed/cdacreader/inc/cdac_reader.h
new file mode 100644
index 0000000000000..b6c71b671a6ed
--- /dev/null
+++ b/src/native/managed/cdacreader/inc/cdac_reader.h
@@ -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
diff --git a/src/native/managed/cdacreader/src/Entrypoints.cs b/src/native/managed/cdacreader/src/Entrypoints.cs
new file mode 100644
index 0000000000000..a65ba9c5fa5ea
--- /dev/null
+++ b/src/native/managed/cdacreader/src/Entrypoints.cs
@@ -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;
+ }
+
+ ///
+ /// Get the SOS-DAC interface implementation.
+ ///
+ /// Handle crated via cdac initialization
+ /// IUnknown pointer that can be queried for ISOSDacInterface*
+ ///
+ [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;
+ }
+}
diff --git a/src/native/managed/cdacreader/src/SOSDacImpl.cs b/src/native/managed/cdacreader/src/SOSDacImpl.cs
new file mode 100644
index 0000000000000..893c39bff8830
--- /dev/null
+++ b/src/native/managed/cdacreader/src/SOSDacImpl.cs
@@ -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();
+}
+
+///
+/// Implementation of ISOSDacInterface* interfaces intended to be passed out to consumers
+/// interacting with the DAC via those COM interfaces.
+///
+[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
+ return 4;
+ }
+}
diff --git a/src/native/managed/cdacreader/src/Target.cs b/src/native/managed/cdacreader/src/Target.cs
new file mode 100644
index 0000000000000..1590984f017c3
--- /dev/null
+++ b/src/native/managed/cdacreader/src/Target.cs
@@ -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 _)
+ {
+ }
+}
diff --git a/src/native/managed/cdacreader/src/cdacreader.csproj b/src/native/managed/cdacreader/src/cdacreader.csproj
new file mode 100644
index 0000000000000..51f87fa8908d9
--- /dev/null
+++ b/src/native/managed/cdacreader/src/cdacreader.csproj
@@ -0,0 +1,17 @@
+
+
+
+ $(NetCoreAppToolCurrent)
+ enable
+ true
+
+ false
+
+
+
+
+
+
+
+
+
diff --git a/src/native/managed/compile-native.proj b/src/native/managed/compile-native.proj
index 4203835936ecb..453d84ab4dc07 100644
--- a/src/native/managed/compile-native.proj
+++ b/src/native/managed/compile-native.proj
@@ -12,6 +12,7 @@
+