Skip to content
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] Implement basic stackwalking #111759

Open
wants to merge 53 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
a213ec2
thread context fetching
Jan 6, 2025
8f2b7e7
iterate and debug print Frames
Jan 8, 2025
6f2f4ab
add more functionality needed for stack walking
Jan 16, 2025
0259f83
implement R2R unwind info fetching
Jan 16, 2025
cd8854c
stackwalking on amd64
Jan 22, 2025
17e34fd
AMD64 stack unwinding impl
Jan 23, 2025
22a3c9a
Merge branch 'cdac-stackwalk' of github.com:max-charlamb/runtime into…
Jan 23, 2025
5d9317a
crossplatform LazyMachState fixes
Jan 23, 2025
2a1e410
add support for building arm64 and amd64 unwinders
Jan 24, 2025
da73082
add GetPlatform
Jan 24, 2025
a794374
AMD64/ARM64 stackwalking backend
Jan 28, 2025
3d22034
AMD64 stackwalking through SOS
Jan 31, 2025
18e63a3
clean up PR
Feb 6, 2025
25f25c2
Merge remote-tracking branch 'origin/main' into cdac-stackwalk
Feb 6, 2025
831fb14
fix issues caused by merge from origin/main
Feb 6, 2025
4f97647
remove unused datatype
Feb 6, 2025
721042c
only build native unwinders on windows amd64
Feb 7, 2025
2887c4c
change cmakelists order
Feb 7, 2025
1df3093
remove eventing_header dependency for cdac_unwinders
Feb 7, 2025
3696838
fix loading cDAC on non-windows platforms
Feb 8, 2025
373f9ef
use unused variable
max-charlamb Feb 9, 2025
5edb98d
move to testhost for library tests
Feb 10, 2025
1d1beda
Merge branch 'cdac-stackwalk' of github.com:max-charlamb/runtime into…
Feb 10, 2025
a1703a0
don't build cDAC in Libraries_WithPackages run
Feb 10, 2025
71d5590
isolate context datastructures from logic
Feb 10, 2025
fb4109c
clean up
Feb 10, 2025
4fc3f22
address easy to fix feedback
Feb 11, 2025
bfb63ee
move frame down casting logic to FrameIterator
Feb 11, 2025
1961e4d
wip improve documentation
Feb 11, 2025
ce13fdc
typo
Feb 11, 2025
1d3799e
Merge remote-tracking branch 'origin/main' into cdac-stackwalk
Feb 11, 2025
4e40652
use FrameIdentifier instead of VPtr
Feb 12, 2025
af93b5d
docs wip
Feb 12, 2025
0d2c3d9
improve docs
Feb 12, 2025
82e9ece
be more consistent when referring to Windows "style" unwinding/context
Feb 13, 2025
333a932
refactor unwinder CMakeLists.txt
Feb 13, 2025
bcdf2e4
move UNWINDER_ASSERT define into base unwinder
Feb 13, 2025
d3fdf0b
refactor unwinder to use same InstructionBuffer for DAC/cDAC
Feb 13, 2025
a246775
prefix class members with m_
Feb 13, 2025
90fd607
implement cDAC native unwinder assertions through refactor using thre…
Feb 13, 2025
93a8345
clean up diff
Feb 13, 2025
746f584
use MSTypes
Feb 13, 2025
bd41361
make comment inclusive of cDAC
Feb 13, 2025
da0425a
convert to use IEnumerable<IStackDataFrameHandle>
Feb 13, 2025
c7ad322
Merge remote-tracking branch 'origin/main' into cdac-stackwalk
Feb 14, 2025
bf1743b
rework docs to better explain skipped Frame check
Feb 14, 2025
0a03272
Merge branch 'main' into cdac-stackwalk
max-charlamb Feb 24, 2025
0295a95
improve ExecutionManager docs
Feb 25, 2025
fa50b1c
add tests for GetModuleBaseAddress
Feb 25, 2025
54e3cb3
fix build issue
Feb 25, 2025
ba2a8ab
re-add Create(...)
Feb 25, 2025
4945be7
fix StressLogAnalyzer support
Feb 25, 2025
cd15192
rename GetModuleBaseAddress -> GetUnwindInfoBaseAddress
Feb 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/design/datacontracts/ExecutionManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ struct CodeBlockHandle
TargetPointer GetMethodDesc(CodeBlockHandle codeInfoHandle);
// Get the instruction pointer address of the start of the code block
TargetCodePointer GetStartAddress(CodeBlockHandle codeInfoHandle);
// Gets the base address of the module containing the code block
TargetPointer GetModuleBaseAddress(CodeBlockHandle codeInfoHandle);
Copy link
Member

Choose a reason for hiding this comment

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

I don't like this naming/meaning. Looking closer at this, this concept of "module" isn't used anywhere else in the documentation. Other parts of the documentation refer to modules as the IL concept, but in this case it refers to the concept of a module which is either a PE binary which holds R2R code, or a CodeHeap which may have code from many different IL modules within it. Possibly change the name here to something like "GetUnwindInfoBaseAddress" and document that it serves as the base pointer for the RUNTIME_FUNCTION found in the GetUnwindInfo api?

Copy link
Contributor Author

@max-charlamb max-charlamb Feb 25, 2025

Choose a reason for hiding this comment

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

I renamed GetModuleBaseAddress -> GetUnwindInfoBaseAddress. It's documented as "returning the base address that the unwind info for a given CodeBlockHandle is relative to."

I changed all of cDAC to reference the base address using unwindInfoBase but left the pre-existing native references to moduleBase and imageBase.

// Gets the unwind info of the code block at the specified code pointer
TargetPointer GetUnwindInfo(CodeBlockHandle codeInfoHandle, TargetCodePointer ip);
```

## Version 1
Expand Down Expand Up @@ -53,6 +57,8 @@ Data descriptors used:
| `CodeHeapListNode` | `MapBase` | Start of the map - start address rounded down based on OS page size |
| `CodeHeapListNode` | `HeaderMap` | Bit array used to find the start of methods - relative to `MapBase` |
| `RealCodeHeader` | `MethodDesc` | Pointer to the corresponding `MethodDesc` |
| `RealCodeHeader` | `NumUnwindInfos` | Number of Unwind Infos |
| `RealCodeHeader` | `UnwindInfos` | Start address of Unwind Infos |
| `Module` | `ReadyToRunInfo` | Pointer to the `ReadyToRunInfo` for the module |
| `ReadyToRunInfo` | `CompositeInfo` | Pointer to composite R2R info - or itself for non-composite |
| `ReadyToRunInfo` | `NumRuntimeFunctions` | Number of `RuntimeFunctions` |
Expand Down
67 changes: 67 additions & 0 deletions docs/design/datacontracts/StackWalk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Contract StackWalk

This contract encapsulates support for StackWalking managed threads.

## APIs of contract

```csharp
public interface IStackWalkHandle { };
public interface IStackDataFrameHandle { };
```

```csharp
// Creates a stack walk and returns a handle
IStackWalkHandle CreateStackWalk(ThreadData threadData);
// Iterates the stackWalkHandle to the next frame. If successful, returns true. Otherwise false.
bool Next(IStackWalkHandle stackWalkHandle);
// Gets the current frame from a stack walk and returns a IStackDataFrameHandle to it.
IStackDataFrameHandle GetCurrentFrame(IStackWalkHandle stackWalkHandle);
// Gets the thread context at the given stack dataframe.
byte[] GetRawContext(IStackDataFrameHandle stackDataFrameHandle);
// Gets the Frame address at the given stack dataframe. Returns TargetPointer.Null if the current dataframe does not have a valid Frame.
TargetPointer GetFrameAddress(IStackDataFrameHandle stackDataFrameHandle);
```

## Version 1

The `StackWalk` contract provides an interface for walking the stack of a managed thread. It includes methods to create a stack walk, move to the next frame, get the current frame, retrieve the raw context, and get the frame address.

### CreateStackWalk

```csharp
IStackWalkHandle CreateStackWalk(ThreadData threadData);
```

Creates a stack walk handle for the given thread data. This initializes the context and frame iterator for the stack walk.
Copy link
Member

Choose a reason for hiding this comment

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

I don't see documentation about how to do all of this. We need that before we can actually merge this change, not just C# implementation in the actual cDAC codebase. Where we use the a well documented standard like the Win32 unwinder, you can just drop in a link, but for everything else... it needs correct documentation/algorithms


### Next

```csharp
bool Next(IStackWalkHandle stackWalkHandle);
```

Moves to the next frame in the stack walk. Returns `true` if successfully moved to the next frame. Otherwise returns `false`.

### GetCurrentFrame

```csharp
IStackDataFrameHandle GetCurrentFrame(IStackWalkHandle stackWalkHandle);
```

Gets the current frame in the stack walk. Returns a handle to the stack data frame.

### GetRawContext

```csharp
byte[] GetRawContext(IStackDataFrameHandle stackDataFrameHandle);
```

Retrieves the raw Windows thread context of the current frame as a byte array. The size and shape of the context is platform dependent. See [CONTEXT structure](https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-context) for more info.

### GetFrameAddress

```csharp
TargetPointer GetFrameAddress(IStackDataFrameHandle stackDataFrameHandle);
```

Gets the frame address of the current frame. Returns `TargetPointer.Null` if the frame is not valid.
15 changes: 10 additions & 5 deletions eng/native/functions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -515,11 +515,11 @@ function(install_static_library targetName destination component)
endif()
endfunction()

# install_clr(TARGETS targetName [targetName2 ...] [DESTINATIONS destination [destination2 ...]] [COMPONENT componentName])
# install_clr(TARGETS targetName [targetName2 ...] [DESTINATIONS destination [destination2 ...]] [COMPONENT componentName] [INSTALL_ALL_ARTIFACTS])
function(install_clr)
set(multiValueArgs TARGETS DESTINATIONS)
set(singleValueArgs COMPONENT)
set(options "")
set(options INSTALL_ALL_ARTIFACTS)
cmake_parse_arguments(INSTALL_CLR "${options}" "${singleValueArgs}" "${multiValueArgs}" ${ARGV})

if ("${INSTALL_CLR_TARGETS}" STREQUAL "")
Expand Down Expand Up @@ -555,9 +555,14 @@ function(install_clr)
endif()

foreach(destination ${destinations})
# We don't need to install the export libraries for our DLLs
# since they won't be directly linked against.
install(PROGRAMS $<TARGET_FILE:${targetName}> DESTINATION ${destination} COMPONENT ${INSTALL_CLR_COMPONENT})
# Install the export libraries for static libraries.
if (${INSTALL_CLR_INSTALL_ALL_ARTIFACTS})
install(TARGETS ${targetName} DESTINATION ${destination} COMPONENT ${INSTALL_CLR_COMPONENT})
else()
# We don't need to install the export libraries for our DLLs
# since they won't be directly linked against.
install(PROGRAMS $<TARGET_FILE:${targetName}> DESTINATION ${destination} COMPONENT ${INSTALL_CLR_COMPONENT})
endif()
if (NOT "${symbolFile}" STREQUAL "")
install_symbol_file(${symbolFile} ${destination} COMPONENT ${INSTALL_CLR_COMPONENT})
endif()
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/runtime-official.yml
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ extends:
- windows_x64
jobParameters:
templatePath: 'templates-official'
buildArgs: -s tools+libs -pack -c $(_BuildConfig) /p:TestAssemblies=false /p:TestPackages=true
buildArgs: -s tools.illink+libs -pack -c $(_BuildConfig) /p:TestAssemblies=false /p:TestPackages=true
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed with @jkoritzinsky , cDAC should not currently be built in the Libraries_WithPackages run. This started failing because the native cDAC components were not available.

nameSuffix: Libraries_WithPackages
isOfficialBuild: ${{ variables.isOfficialBuild }}
postBuildSteps:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,7 @@ extends:
platforms:
- windows_x64
jobParameters:
buildArgs: -test -s tools+libs+libs.tests -pack -c $(_BuildConfig) /p:TestAssemblies=false /p:TestPackages=true
buildArgs: -test -s tools.illink+libs+libs.tests -pack -c $(_BuildConfig) /p:TestAssemblies=false /p:TestPackages=true
nameSuffix: Libraries_WithPackages
timeoutInMinutes: 150
condition: >-
Expand Down
30 changes: 29 additions & 1 deletion src/coreclr/debug/daccess/cdac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,15 @@ namespace
iter++;
path.Truncate(iter);
path.Append(CDAC_LIB_NAME);

#ifdef HOST_WINDOWS
// LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR tells the native windows loader to load dependencies
// from the same directory as cdacreader.dll. Once the native portions of the cDAC
// are statically linked, this won't be required.
*phCDAC = CLRLoadLibraryEx(path.GetUnicode(), NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
#else // !HOST_WINDOWS
*phCDAC = CLRLoadLibrary(path.GetUnicode());
#endif // HOST_WINDOWS
if (*phCDAC == NULL)
return false;

Expand All @@ -41,6 +49,26 @@ namespace

return S_OK;
}

int ReadThreadContext(uint32_t threadId, uint32_t contextFlags, uint32_t contextBufferSize, uint8_t* contextBuffer, void* context)
{
ICorDebugDataTarget* target = reinterpret_cast<ICorDebugDataTarget*>(context);
HRESULT hr = target->GetThreadContext(threadId, contextFlags, contextBufferSize, contextBuffer);
if (FAILED(hr))
return hr;

return S_OK;
}

int GetPlatform(uint32_t* platform, void* context)
{
ICorDebugDataTarget* target = reinterpret_cast<ICorDebugDataTarget*>(context);
HRESULT hr = target->GetPlatform((CorDebugPlatform*)platform);
if (FAILED(hr))
return hr;

return S_OK;
}
}

CDAC CDAC::Create(uint64_t descriptorAddr, ICorDebugDataTarget* target, IUnknown* legacyImpl)
Expand All @@ -53,7 +81,7 @@ CDAC CDAC::Create(uint64_t descriptorAddr, ICorDebugDataTarget* target, IUnknown
_ASSERTE(init != nullptr);

intptr_t handle;
if (init(descriptorAddr, &ReadFromTargetCallback, target, &handle) != 0)
if (init(descriptorAddr, &ReadFromTargetCallback, &ReadThreadContext, &GetPlatform, target, &handle) != 0)
{
::FreeLibrary(cdacLib);
return {};
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/debug/runtimeinfo/contracts.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
"PrecodeStubs": 1,
"ReJIT": 1,
"RuntimeTypeSystem": 1,
"StackWalk": 1,
"Thread": 1
}
33 changes: 33 additions & 0 deletions src/coreclr/debug/runtimeinfo/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,13 @@ CDAC_TYPE_END(RangeSection)
CDAC_TYPE_BEGIN(RealCodeHeader)
CDAC_TYPE_INDETERMINATE(RealCodeHeader)
CDAC_TYPE_FIELD(RealCodeHeader, /*pointer*/, MethodDesc, offsetof(RealCodeHeader, phdrMDesc))
#ifdef FEATURE_EH_FUNCLETS
CDAC_TYPE_FIELD(RealCodeHeader, /*uint32*/, NumUnwindInfos, offsetof(RealCodeHeader, nUnwindInfos))
CDAC_TYPE_FIELD(RealCodeHeader, /* T_RUNTIME_FUNCTION */, UnwindInfos, offsetof(RealCodeHeader, unwindInfos))
#endif // FEATURE_EH_FUNCLETS
CDAC_TYPE_END(RealCodeHeader)


CDAC_TYPE_BEGIN(CodeHeapListNode)
CDAC_TYPE_FIELD(CodeHeapListNode, /*pointer*/, Next, offsetof(HeapList, hpNext))
CDAC_TYPE_FIELD(CodeHeapListNode, /*pointer*/, StartAddress, offsetof(HeapList, startAddress))
Expand Down Expand Up @@ -570,13 +575,41 @@ CDAC_TYPE_FIELD(GCCoverageInfo, /*pointer*/, SavedCode, offsetof(GCCoverageInfo,
CDAC_TYPE_END(GCCoverageInfo)
#endif // HAVE_GCCOVER

CDAC_TYPE_BEGIN(Frame)
CDAC_TYPE_INDETERMINATE(Frame)
CDAC_TYPE_FIELD(Frame, /*pointer*/, Next, cdac_data<Frame>::Next)
CDAC_TYPE_END(Frame)

CDAC_TYPE_BEGIN(InlinedCallFrame)
CDAC_TYPE_SIZE(sizeof(InlinedCallFrame))
CDAC_TYPE_FIELD(InlinedCallFrame, /*pointer*/, CallSiteSP, offsetof(InlinedCallFrame, m_pCallSiteSP))
CDAC_TYPE_FIELD(InlinedCallFrame, /*pointer*/, CallerReturnAddress, offsetof(InlinedCallFrame, m_pCallerReturnAddress))
CDAC_TYPE_FIELD(InlinedCallFrame, /*pointer*/, CalleeSavedFP, offsetof(InlinedCallFrame, m_pCalleeSavedFP))
CDAC_TYPE_END(InlinedCallFrame)

#ifdef FEATURE_EH_FUNCLETS
CDAC_TYPE_BEGIN(SoftwareExceptionFrame)
CDAC_TYPE_SIZE(sizeof(SoftwareExceptionFrame))
CDAC_TYPE_FIELD(SoftwareExceptionFrame, /*T_CONTEXT*/, TargetContext, cdac_data<SoftwareExceptionFrame>::TargetContext)
CDAC_TYPE_FIELD(SoftwareExceptionFrame, /*pointer*/, ReturnAddress, cdac_data<SoftwareExceptionFrame>::ReturnAddress)
CDAC_TYPE_END(SoftwareExceptionFrame)
#endif // FEATURE_EH_FUNCLETS

CDAC_TYPES_END()

CDAC_GLOBALS_BEGIN()
CDAC_GLOBAL_POINTER(AppDomain, &AppDomain::m_pTheAppDomain)
CDAC_GLOBAL_POINTER(ThreadStore, &ThreadStore::s_pThreadStore)
CDAC_GLOBAL_POINTER(FinalizerThread, &::g_pFinalizerThread)
CDAC_GLOBAL_POINTER(GCThread, &::g_pSuspensionThread)

// Add VPtr for all defined Frame types. Used to differentiate Frame objects.
#define FRAME_TYPE_NAME(frameType) \
CDAC_GLOBAL_POINTER(frameType##VPtr, frameType::GetMethodFrameVPtr())

#include "frames.h"
#undef FRAME_TYPE_NAME

CDAC_GLOBAL(MethodDescTokenRemainderBitCount, uint8, METHOD_TOKEN_REMAINDER_BIT_COUNT)
#if FEATURE_EH_FUNCLETS
CDAC_GLOBAL(FeatureEHFunclets, uint8, 1)
Expand Down
89 changes: 75 additions & 14 deletions src/coreclr/unwinder/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,31 +1,92 @@
include_directories(BEFORE ${VM_DIR})
include_directories(BEFORE ${VM_DIR}/${ARCH_SOURCES_DIR})
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(BEFORE ${CLR_DIR}/unwinder)
include_directories(${CLR_DIR}/debug/ee)
include_directories(${CLR_DIR}/gc)
include_directories(${CLR_DIR}/gcdump)
include_directories(${CLR_DIR}/debug/daccess)

set(UNWINDER_SOURCES
baseunwinder.cpp
)

# Include platform specific unwinder for applicable (native and cross-target) builds.
include_directories(${ARCH_SOURCES_DIR})
list(APPEND UNWINDER_SOURCES
${ARCH_SOURCES_DIR}/unwinder.cpp
)

convert_to_absolute_path(UNWINDER_SOURCES ${UNWINDER_SOURCES})

if(CLR_CMAKE_HOST_UNIX)
add_library_clr(unwinder_wks OBJECT ${UNWINDER_SOURCES})
target_include_directories(unwinder_wks BEFORE PRIVATE ${VM_DIR})
target_include_directories(unwinder_wks BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR})
target_include_directories(unwinder_wks BEFORE PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(unwinder_wks BEFORE PRIVATE ${CLR_DIR}/unwinder)
target_include_directories(unwinder_wks PRIVATE ${CLR_DIR}/debug/ee)
target_include_directories(unwinder_wks PRIVATE ${CLR_DIR}/gc)
target_include_directories(unwinder_wks PRIVATE ${CLR_DIR}/gcdump)
target_include_directories(unwinder_wks PRIVATE ${CLR_DIR}/debug/daccess)
target_include_directories(unwinder_wks PRIVATE ${ARCH_SOURCES_DIR})
add_dependencies(unwinder_wks eventing_headers)
endif(CLR_CMAKE_HOST_UNIX)

add_library_clr(unwinder_dac ${UNWINDER_SOURCES})
target_include_directories(unwinder_dac BEFORE PRIVATE ${VM_DIR})
target_include_directories(unwinder_dac BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR})
target_include_directories(unwinder_dac BEFORE PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(unwinder_dac BEFORE PRIVATE ${CLR_DIR}/unwinder)
target_include_directories(unwinder_dac PRIVATE ${CLR_DIR}/debug/ee)
target_include_directories(unwinder_dac PRIVATE ${CLR_DIR}/gc)
target_include_directories(unwinder_dac PRIVATE ${CLR_DIR}/gcdump)
target_include_directories(unwinder_dac PRIVATE ${CLR_DIR}/debug/daccess)
target_include_directories(unwinder_dac PRIVATE ${ARCH_SOURCES_DIR})
add_dependencies(unwinder_dac eventing_headers)
set_target_properties(unwinder_dac PROPERTIES DAC_COMPONENT TRUE)
target_compile_definitions(unwinder_dac PRIVATE FEATURE_NO_HOST)

# Helper function for platform specific cDAC uwninder builds.
function(create_platform_unwinder)
set(oneValueArgs TARGET ARCH)
set(multiValueArgs DESTINATIONS)
cmake_parse_arguments(TARGETDETAILS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

if(TARGETDETAILS_ARCH STREQUAL "x64")
set(ARCH_SOURCES_DIR amd64)
elseif((TARGETDETAILS_ARCH STREQUAL "arm") OR (TARGETDETAILS_ARCH STREQUAL "armel"))
set(ARCH_SOURCES_DIR arm)
elseif(TARGETDETAILS_ARCH STREQUAL "x86")
set(ARCH_SOURCES_DIR i386)
elseif(TARGETDETAILS_ARCH STREQUAL "arm64")
set(ARCH_SOURCES_DIR arm64)
else()
clr_unknown_arch()
endif()

set(UNWINDER_SOURCES
baseunwinder.cpp
${ARCH_SOURCES_DIR}/unwinder.cpp
)

convert_to_absolute_path(UNWINDER_SOURCES ${UNWINDER_SOURCES})

add_library_clr(${TARGETDETAILS_TARGET}
SHARED
${UNWINDER_SOURCES}
)

target_include_directories(${TARGETDETAILS_TARGET} BEFORE PRIVATE ${VM_DIR})
target_include_directories(${TARGETDETAILS_TARGET} BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR})
target_include_directories(${TARGETDETAILS_TARGET} BEFORE PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${TARGETDETAILS_TARGET} BEFORE PRIVATE ${CLR_DIR}/unwinder)
target_include_directories(${TARGETDETAILS_TARGET} PRIVATE ${CLR_DIR}/debug/ee)
target_include_directories(${TARGETDETAILS_TARGET} PRIVATE ${CLR_DIR}/gc)
target_include_directories(${TARGETDETAILS_TARGET} PRIVATE ${CLR_DIR}/gcdump)
target_include_directories(${TARGETDETAILS_TARGET} PRIVATE ${CLR_DIR}/debug/daccess)
target_include_directories(${TARGETDETAILS_TARGET} PRIVATE ${ARCH_SOURCES_DIR})

target_link_libraries(${TARGETDETAILS_TARGET} PRIVATE ${STATIC_MT_CRT_LIB} ${STATIC_MT_VCRT_LIB})

# add the install targets
install_clr(TARGETS ${TARGETDETAILS_TARGET} DESTINATIONS ${TARGETDETAILS_DESTINATIONS} COMPONENT debug INSTALL_ALL_ARTIFACTS)

# Set the target to be built for the specified OS and ARCH
set_target_definitions_to_custom_os_and_arch(TARGET ${TARGETDETAILS_TARGET} OS win ARCH ${TARGETDETAILS_ARCH})

target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE FEATURE_NO_HOST FEATURE_CDAC_UNWINDER)
endfunction()

# TODO: Support building cDAC unwinders on other platforms
# https://github.com/dotnet/runtime/issues/112272#issue-2838611496
if(CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_TARGET_ARCH_AMD64)
create_platform_unwinder(TARGET unwinder_cdac_amd64 ARCH x64 DESTINATIONS cdaclibs)
create_platform_unwinder(TARGET unwinder_cdac_arm64 ARCH arm64 DESTINATIONS cdaclibs)
endif(CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_TARGET_ARCH_AMD64)
Loading
Loading