Enable native SOS build on windows.

Remove libunwind from the PAL

Cleanup and include file trimming.

Change the SOS.NETCore.dll load directory to sos's location.

Load sos from current working directory that the plugin is in.

Update help for stress logs.

Add "sethostruntime" SOS command.
This commit is contained in:
Mike McLaughlin 2018-05-19 18:11:08 -07:00
Родитель 1ed56b7769
Коммит c2905b26bd
4642 изменённых файлов: 6081 добавлений и 384620 удалений

Просмотреть файл

@ -1,3 +1,3 @@
@echo off
powershell -ExecutionPolicy ByPass -command "& """%~dp0eng\common\Build.ps1""" -restore -build %*"
call %~dp0eng\Build.cmd -restore -build %*
exit /b %ErrorLevel%

Просмотреть файл

@ -5,7 +5,7 @@
cmake_minimum_required(VERSION 2.8.12)
if(CMAKE_VERSION VERSION_EQUAL 3.0 OR CMAKE_VERSION VERSION_GREATER 3.0)
cmake_policy(SET CMP0042 NEW)
cmake_policy(SET CMP0042 NEW)
endif()
# Set the project name
@ -19,10 +19,13 @@ if (WIN32)
message(STATUS "VS_PLATFORM_NAME is ${CMAKE_VS_PLATFORM_NAME}")
endif (WIN32)
set(ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
#set(VERSION_FILE_PATH "${CMAKE_BINARY_DIR}/version.cpp")
set(CORECLR_SET_RPATH ON)
if(CORECLR_SET_RPATH)
# Enable @rpath support for shared libraries.
set(MACOSX_RPATH ON)
# Enable @rpath support for shared libraries.
set(MACOSX_RPATH ON)
endif(CORECLR_SET_RPATH)
OPTION(CLR_CMAKE_ENABLE_CODE_COVERAGE "Enable code coverage" OFF)
@ -31,7 +34,7 @@ OPTION(CLR_CMAKE_WARNINGS_ARE_ERRORS "Warnings are errors" ON)
# Ensure that python is present
find_program(PYTHON NAMES python2.7 python2 python)
if (PYTHON STREQUAL "PYTHON-NOTFOUND")
message(FATAL_ERROR "PYTHON not found: Please install Python 2.7.9 or later from https://www.python.org/downloads/")
message(FATAL_ERROR "PYTHON not found: Please install Python 2.7.9 or later from https://www.python.org/downloads/")
endif()
# Ensure other tools are present
@ -450,9 +453,9 @@ endif(WIN32)
# ./build-native.sh cmakeargs "-DCLR_ADDITIONAL_COMPILER_OPTIONS=<...>" cmakeargs "-DCLR_ADDITIONAL_LINKER_FLAGS=<...>"
#
if(CLR_CMAKE_PLATFORM_UNIX)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${CLR_ADDITIONAL_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CLR_ADDITIONAL_LINKER_FLAGS}" )
add_compile_options(${CLR_ADDITIONAL_COMPILER_OPTIONS})
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${CLR_ADDITIONAL_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CLR_ADDITIONAL_LINKER_FLAGS}" )
add_compile_options(${CLR_ADDITIONAL_COMPILER_OPTIONS})
endif(CLR_CMAKE_PLATFORM_UNIX)
if(CLR_CMAKE_PLATFORM_LINUX)
@ -464,6 +467,7 @@ endif(CLR_CMAKE_PLATFORM_LINUX)
#------------------------------------
# Definitions (for platform)
#-----------------------------------
if (CLR_CMAKE_PLATFORM_ARCH_AMD64)
add_definitions(-D_AMD64_)
add_definitions(-D_WIN64)
@ -539,6 +543,86 @@ else ()
clr_unknown_arch()
endif ()
if (CLR_CMAKE_TARGET_ARCH_AMD64)
if (CLR_CMAKE_PLATFORM_UNIX)
add_definitions(-DDBG_TARGET_AMD64_UNIX)
endif()
add_definitions(-D_TARGET_64BIT_=1)
add_definitions(-D_TARGET_AMD64_=1)
add_definitions(-DDBG_TARGET_64BIT=1)
add_definitions(-DDBG_TARGET_AMD64=1)
add_definitions(-DDBG_TARGET_WIN64=1)
elseif (CLR_CMAKE_TARGET_ARCH_ARM64)
if (CLR_CMAKE_PLATFORM_UNIX)
add_definitions(-DDBG_TARGET_ARM64_UNIX)
endif()
add_definitions(-D_TARGET_ARM64_=1)
add_definitions(-D_TARGET_64BIT_=1)
add_definitions(-DDBG_TARGET_64BIT=1)
add_definitions(-DDBG_TARGET_ARM64=1)
add_definitions(-DDBG_TARGET_WIN64=1)
add_definitions(-DFEATURE_MULTIREG_RETURN)
elseif (CLR_CMAKE_TARGET_ARCH_ARM)
if (CLR_CMAKE_PLATFORM_UNIX)
add_definitions(-DDBG_TARGET_ARM_UNIX)
elseif (WIN32 AND NOT DEFINED CLR_CROSS_COMPONENTS_BUILD)
# Set this to ensure we can use Arm SDK for Desktop binary linkage when doing native (Arm32) build
add_definitions(-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1)
add_definitions(-D_ARM_WORKAROUND_)
endif (CLR_CMAKE_PLATFORM_UNIX)
add_definitions(-D_TARGET_ARM_=1)
add_definitions(-D_TARGET_WIN32_=1)
add_definitions(-DDBG_TARGET_32BIT=1)
add_definitions(-DDBG_TARGET_ARM=1)
elseif (CLR_CMAKE_TARGET_ARCH_I386)
add_definitions(-D_TARGET_X86_=1)
add_definitions(-DDBG_TARGET_32BIT=1)
add_definitions(-DDBG_TARGET_X86=1)
else ()
clr_unknown_arch()
endif (CLR_CMAKE_TARGET_ARCH_AMD64)
if(WIN32)
add_definitions(-DWIN32)
add_definitions(-D_WIN32)
add_definitions(-DWINVER=0x0602)
add_definitions(-D_WIN32_WINNT=0x0602)
add_definitions(-DWIN32_LEAN_AND_MEAN=1)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif(WIN32)
#--------------------------------------
# FEATURE Defines
#--------------------------------------
add_definitions(-DFEATURE_CORESYSTEM)
if(CLR_CMAKE_PLATFORM_UNIX)
add_definitions(-DFEATURE_PAL)
add_definitions(-DFEATURE_PAL_ANSI)
endif(CLR_CMAKE_PLATFORM_UNIX)
if(WIN32)
add_definitions(-DFEATURE_COMINTEROP)
endif(WIN32)
if(NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD)
add_definitions(-DFEATURE_HIJACK)
endif(NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD)
if(FEATURE_EVENT_TRACE)
add_definitions(-DFEATURE_EVENT_TRACE=1)
add_definitions(-DFEATURE_PERFTRACING=1)
endif(FEATURE_EVENT_TRACE)
if(CLR_CMAKE_PLATFORM_UNIX_AMD64)
add_definitions(-DFEATURE_MULTIREG_RETURN)
endif (CLR_CMAKE_PLATFORM_UNIX_AMD64)
if(CLR_CMAKE_PLATFORM_UNIX AND CLR_CMAKE_TARGET_ARCH_AMD64)
add_definitions(-DUNIX_AMD64_ABI)
endif(CLR_CMAKE_PLATFORM_UNIX AND CLR_CMAKE_TARGET_ARCH_AMD64)
#--------------------------------------
# Compile Options
#--------------------------------------

Просмотреть файл

@ -1,7 +1,9 @@
.NET Core Diagnostics Repo
==========================
This repository contains the source code for various .NET Core runtime diagnostic tools. It currently contains the managed portion of SOS and the lldb SOS plugin. One of goals of this repo is to build the lldb SOS plugin for the portable Linux platform (Centos 7) and the platforms not supported by the portable build (Centos 6, Alpine, eventually macOS) and to test across various indexes in a very large matrix: OSs/distros (Centos 6/7, Ubuntu, Alpine, Fedora, Debian, RHEL 7.2), architectures (x64, x86, arm, arm64), lldb versions (3.9, 4.0, 5.0, 6.0) and even .NET Core versions (1.1, 2.0.x, 2.1).
**Currently under construction**
This repository contains the source code for various .NET Core runtime diagnostic tools. It currently contains SOS, the managed portion of SOS and the lldb SOS plugin. One of goals of this repo is to build SOS and the lldb SOS plugin for the portable Linux platform (Centos 7) and the platforms not supported by the portable build (Centos 6, Alpine, eventually macOS) and to test across various indexes in a very large matrix: OSs/distros (Centos 6/7, Ubuntu, Alpine, Fedora, Debian, RHEL 7.2), architectures (x64, x86, arm, arm64), lldb versions (3.9, 4.0, 5.0, 6.0) and even .NET Core versions (1.1, 2.0.x, 2.1).
Another goal to make it easier to obtain a version of lldb (currently 3.9) with scripts and documentation for platforms/distros like Centos, Alpine, Fedora, etc. that by default provide really old versions.

Просмотреть файл

@ -1,3 +1,3 @@
@echo off
powershell -ExecutionPolicy ByPass -command "& """%~dp0eng\common\Build.ps1""" -restore %*"
call %~dp0eng\Build.cmd -restore %*
exit /b %ErrorLevel%

Просмотреть файл

@ -1,3 +1,3 @@
@echo off
powershell -ExecutionPolicy ByPass -command "& """%~dp0eng\common\Build.ps1""" -test %*"
call %~dp0eng\Build.cmd -test %*
exit /b %ErrorLevel%

27
crossgen.cmake Normal file
Просмотреть файл

@ -0,0 +1,27 @@
# Contains the crossgen build specific definitions. Included by the leaf crossgen cmake files.
add_definitions(
-DCROSSGEN_COMPILE
-DCROSS_COMPILE
-DFEATURE_NATIVE_IMAGE_GENERATION
-DSELF_NO_HOST)
remove_definitions(
-DFEATURE_CODE_VERSIONING
-DEnC_SUPPORTED
-DFEATURE_EVENT_TRACE=1
-DFEATURE_LOADER_OPTIMIZATION
-DFEATURE_MULTICOREJIT
-DFEATURE_PERFMAP
-DFEATURE_REJIT
-DFEATURE_TIERED_COMPILATION
-DFEATURE_VERSIONING_LOG
)
if(FEATURE_READYTORUN)
add_definitions(-DFEATURE_READYTORUN_COMPILER)
endif(FEATURE_READYTORUN)
if(CLR_CMAKE_PLATFORM_LINUX)
add_definitions(-DFEATURE_PERFMAP)
endif(CLR_CMAKE_PLATFORM_LINUX)

371
eng/Build-Native.cmd Normal file
Просмотреть файл

@ -0,0 +1,371 @@
@if not defined _echo @echo off
setlocal EnableDelayedExpansion EnableExtensions
:: Define a prefix for most output progress messages that come from this script. That makes
:: it easier to see where these are coming from. Note that there is a trailing space here.
set "__MsgPrefix=BUILD: "
echo %__MsgPrefix%Starting Build at %TIME%
set __ThisScriptFull="%~f0"
set __ThisScriptDir="%~dp0"
call "%__ThisScriptDir%"\setup_vs_tools.cmd
if NOT '%ERRORLEVEL%' == '0' exit /b 1
if defined VS150COMNTOOLS (
set "__VSToolsRoot=%VS150COMNTOOLS%"
set "__VCToolsRoot=%VS150COMNTOOLS%\..\..\VC\Auxiliary\Build"
set __VSVersion=vs2017
) else (
set "__VSToolsRoot=%VS140COMNTOOLS%"
set "__VCToolsRoot=%VS140COMNTOOLS%\..\..\VC"
set __VSVersion=vs2015
)
:: Work around Jenkins CI + msbuild problem: Jenkins sometimes creates very large environment
:: variables, and msbuild can't handle environment blocks with such large variables. So clear
:: out the variables that might be too large.
set ghprbCommentBody=
:: Note that the msbuild project files (specifically, dir.proj) will use the following variables, if set:
:: __BuildArch -- default: x64
:: __BuildType -- default: Debug
:: __BuildOS -- default: Windows_NT
:: __ProjectDir -- default: directory of the dir.props file
:: __SourceDir -- default: %__ProjectDir%\src\
:: __RootBinDir -- default: %__ProjectDir%\artifacts\
:: __BinDir -- default: %__RootBinDir%\bin\%__BuildOS%.%__BuildArch.%__BuildType%\
:: __IntermediatesDir -- default: %__RootBinDir%\obj\%__BuildOS%.%__BuildArch.%__BuildType%\
:: __LogDir -- default: %__RootBinDir%\log\%__BuildOS%.%__BuildArch.%__BuildType%\
::
:: Thus, these variables are not simply internal to this script!
:: Set the default arguments for build
set __BuildArch=x64
set __BuildType=Debug
set __BuildOS=Windows_NT
set __Build=0
set __Test=0
:: Set the various build properties here so that CMake and MSBuild can pick them up
set "__ProjectDir=%~dp0"
:: remove trailing slash
if %__ProjectDir:~-1%==\ set "__ProjectDir=%__ProjectDir:~0,-1%"
set "__ProjectDir=%__ProjectDir%\.."
set "__SourceDir=%__ProjectDir%\src"
set "__PackagesDir=%DotNetRestorePackagesPath%"
if [%__PackagesDir%]==[] set "__PackagesDir=%__ProjectDir%\packages"
set "__RootBinDir=%__ProjectDir%\artifacts"
REM __UnprocessedBuildArgs are args that we pass to msbuild (e.g. /p:__BuildArch=x64)
set "__args= %*"
set processedArgs=
set __UnprocessedBuildArgs=
:Arg_Loop
if "%1" == "" goto ArgsDone
if /i "%1" == "-?" goto Usage
if /i "%1" == "-h" goto Usage
if /i "%1" == "-help" goto Usage
if /i "%1" == "--help" goto Usage
if /i "%1" == "-build" (set __Build=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop)
if /i "%1" == "-test" (set __Test=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop)
if /i "%1" == "-configuration" (set __BuildType=%2&set processedArgs=!processedArgs! %1 %2&shift&shift&goto Arg_Loop)
if /i "%1" == "-architecture" (set __BuildArch=%2&set processedArgs=!processedArgs! %1 %2&shift&shift&goto Arg_Loop)
rem these options are ignored for a native build
if /i "%1" == "-restore" (set processedArgs=!processedArgs! %1&shift&goto Arg_Loop)
if /i "%1" == "-sign" (set processedArgs=!processedArgs! %1&shift&goto Arg_Loop)
if /i "%1" == "-pack" (set processedArgs=!processedArgs! %1&shift&goto Arg_Loop)
if /i "%1" == "-ci" (set processedArgs=!processedArgs! %1&shift&goto Arg_Loop)
if /i "%1" == "-prepareMachine" (set processedArgs=!processedArgs! %1&shift&goto Arg_Loop)
if [!processedArgs!]==[] (
set __UnprocessedBuildArgs=%__args%
) else (
set __UnprocessedBuildArgs=%__args%
for %%t in (!processedArgs!) do (
set __UnprocessedBuildArgs=!__UnprocessedBuildArgs:*%%t=!
)
)
:ArgsDone
REM Determine if this is a cross-arch build
if /i "%__BuildArch%"=="arm64" (
set __DoCrossArchBuild=1
set __CrossArch=x86
)
if /i "%__BuildArch%"=="arm" (
set __DoCrossArchBuild=1
set __CrossArch=x64
)
:: Set the remaining variables based upon the determined build configuration
set "__BinDir=%__RootBinDir%\bin\%__BuildOS%.%__BuildArch%.%__BuildType%"
set "__IntermediatesDir=%__RootBinDir%\obj\%__BuildOS%.%__BuildArch%.%__BuildType%"
set "__LogDir=%__RootBinDir%\log\%__BuildOS%.%__BuildArch%.%__BuildType%"
if "%__NMakeMakefiles%"=="1" (set "__IntermediatesDir=%__RootBinDir%\nmakeobj\%__BuildOS%.%__BuildArch%.%__BuildType%")
set "__PackagesBinDir=%__BinDir%\.nuget"
set "__CrossComponentBinDir=%__BinDir%"
set "__CrossCompIntermediatesDir=%__IntermediatesDir%\crossgen"
if NOT "%__CrossArch%" == "" set __CrossComponentBinDir=%__CrossComponentBinDir%\%__CrossArch%
set "__CrossGenCoreLibLog=%__LogDir%\CrossgenCoreLib_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
set "__CrossgenExe=%__CrossComponentBinDir%\crossgen.exe"
:: Generate path to be set for CMAKE_INSTALL_PREFIX to contain forward slash
set "__CMakeBinDir=%__BinDir%"
set "__CMakeBinDir=%__CMakeBinDir:\=/%"
if not exist "%__BinDir%" md "%__BinDir%"
if not exist "%__IntermediatesDir%" md "%__IntermediatesDir%"
if not exist "%__LogDir%" md "%__LogDir%"
echo %__MsgPrefix%Commencing diagnostics repo build
:: Set the remaining variables based upon the determined build configuration
echo %__MsgPrefix%Checking prerequisites
:: Eval the output from probe-win1.ps1
for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy ByPass "& ""%__ProjectDir%\eng\probe-win.ps1"""') do %%a
REM =========================================================================================
REM ===
REM === Start the build steps
REM ===
REM =========================================================================================
@if defined _echo @echo on
REM Parse the optdata package versions out of msbuild so that we can pass them on to CMake
set DotNetCli=%__ProjectDir%\.dotnet\dotnet.exe
if not exist "%DotNetCli%" (
echo %__MsgPrefix%Assertion failed: dotnet.exe not found at path "%DotNetCli%"
exit /b 1
)
set MSBuildPath=%__ProjectDir%\.dotnet\sdk\2.1.300-rc1-008673\msbuild.dll
REM =========================================================================================
REM ===
REM === Build the native code
REM ===
REM =========================================================================================
if %__Build% EQU 1 (
REM Scope environment changes start {
setlocal
echo %__MsgPrefix%Commencing build of native components for %__BuildOS%.%__BuildArch%.%__BuildType%
set __NativePlatformArgs=-platform=%__BuildArch%
if not "%__ToolsetDir%" == "" ( set __NativePlatformArgs=-useEnv )
if not "%__ToolsetDir%" == "" (
rem arm64 builds currently use private toolset which has not been released yet
REM TODO, remove once the toolset is open.
call :PrivateToolSet
goto GenVSSolution
)
:: Set the environment for the native build
set __VCBuildArch=x86_amd64
if /i "%__BuildArch%" == "x86" ( set __VCBuildArch=x86 )
if /i "%__BuildArch%" == "arm" (
set __VCBuildArch=x86_arm
REM Make CMake pick the highest installed version in the 10.0.* range
set ___SDKVersion="-DCMAKE_SYSTEM_VERSION=10.0"
)
if /i "%__BuildArch%" == "arm64" (
set __VCBuildArch=x86_arm64
REM Make CMake pick the highest installed version in the 10.0.* range
set ___SDKVersion="-DCMAKE_SYSTEM_VERSION=10.0"
)
echo %__MsgPrefix%Using environment: "%__VCToolsRoot%\vcvarsall.bat" !__VCBuildArch!
call "%__VCToolsRoot%\vcvarsall.bat" !__VCBuildArch!
@if defined _echo @echo on
if not defined VSINSTALLDIR (
echo %__MsgPrefix%Error: VSINSTALLDIR variable not defined.
exit /b 1
)
if not exist "!VSINSTALLDIR!DIA SDK" goto NoDIA
:GenVSSolution
if defined __SkipConfigure goto SkipConfigure
echo %__MsgPrefix%Regenerating the Visual Studio solution
set "__ManagedBinaryDir=%__RootBinDir%\%__BuildType%\bin"
set "__ManagedBinaryDir=!__ManagedBinaryDir:\=/!"
set __ExtraCmakeArgs=!___SDKVersion! "-DCLR_MANAGED_BINARY_DIR=!__ManagedBinaryDir!"
pushd "%__IntermediatesDir%"
call "%__ProjectDir%\eng\gen-buildsys-win.bat" "%__ProjectDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs!
@if defined _echo @echo on
popd
:SkipConfigure
if defined __ConfigureOnly goto SkipNativeBuild
if not exist "%__IntermediatesDir%\install.vcxproj" (
echo %__MsgPrefix%Error: failed to generate native component build project!
exit /b 1
)
set __BuildLogRootName=Native
set __BuildLog="%__LogDir%\!__BuildLogRootName!.log"
set __BuildWrn="%__LogDir%\!__BuildLogRootName!.wrn"
set __BuildErr="%__LogDir%\!__BuildLogRootName!.err"
set __MsbuildLog=/flp:Verbosity=normal;LogFile=!__BuildLog!
set __MsbuildWrn=/flp1:WarningsOnly;LogFile=!__BuildWrn!
set __MsbuildErr=/flp2:ErrorsOnly;LogFile=!__BuildErr!
msbuild.exe %__IntermediatesDir%\install.vcxproj /v:m !__MsbuildLog! !__MsbuildWrn! !__MsbuildErr! /p:Configuration=%__BuildType% /p:Platform=%__BuildArch% %__UnprocessedBuildArgs%
if not !errorlevel! == 0 (
echo %__MsgPrefix%Error: native component build failed. Refer to the build log files for details:
echo !__BuildLog!
echo !__BuildWrn!
echo !__BuildErr!
exit /b 1
)
:SkipNativeBuild
REM } Scope environment changes end
endlocal
)
REM =========================================================================================
REM ===
REM === Build Cross-Architecture Native Components (if applicable)
REM ===
REM =========================================================================================
if /i "%__DoCrossArchBuild%"=="1" (
REM Scope environment changes start {
setlocal
echo %__MsgPrefix%Commencing build of cross architecture native components for %__BuildOS%.%__BuildArch%.%__BuildType%
:: Set the environment for the native build
set __VCBuildArch=x86_amd64
if /i "%__CrossArch%" == "x86" ( set __VCBuildArch=x86 )
echo %__MsgPrefix%Using environment: "%__VCToolsRoot%\vcvarsall.bat" !__VCBuildArch!
call "%__VCToolsRoot%\vcvarsall.bat" !__VCBuildArch!
@if defined _echo @echo on
if not exist "%__CrossCompIntermediatesDir%" md "%__CrossCompIntermediatesDir%"
if defined __SkipConfigure goto SkipConfigureCrossBuild
set __CMakeBinDir=%__CrossComponentBinDir%
set "__CMakeBinDir=!__CMakeBinDir:\=/!"
set "__ManagedBinaryDir=%__RootBinDir%\%__BuildType%\bin"
set "__ManagedBinaryDir=!__ManagedBinaryDir:\=/!"
set __ExtraCmakeArgs="-DCLR_MANAGED_BINARY_DIR=!__ManagedBinaryDir!" "-DCLR_CROSS_COMPONENTS_BUILD=1" "-DCLR_CMAKE_TARGET_ARCH=%__BuildArch%" "-DCMAKE_SYSTEM_VERSION=10.0"
pushd "%__CrossCompIntermediatesDir%"
call "%__ProjectDir%\eng\gen-buildsys-win.bat" "%__ProjectDir%" %__VSVersion% %__CrossArch% !__ExtraCmakeArgs!
@if defined _echo @echo on
popd
:SkipConfigureCrossBuild
if not exist "%__CrossCompIntermediatesDir%\install.vcxproj" (
echo %__MsgPrefix%Error: failed to generate cross-arch components build project!
exit /b 1
)
if defined __ConfigureOnly goto SkipCrossCompBuild
set __BuildLogRootName=Native.Cross
set __BuildLog="%__LogDir%\!__BuildLogRootName!.log"
set __BuildWrn="%__LogDir%\!__BuildLogRootName!.wrn"
set __BuildErr="%__LogDir%\!__BuildLogRootName!.err"
set __MsbuildLog=/flp:Verbosity=normal;LogFile=!__BuildLog!
set __MsbuildWrn=/flp1:WarningsOnly;LogFile=!__BuildWrn!
set __MsbuildErr=/flp2:ErrorsOnly;LogFile=!__BuildErr!
msbuild.exe %__CrossCompIntermediatesDir%\install.vcxproj /v:m !__MsbuildLog! !__MsbuildWrn! !__MsbuildErr! /p:Configuration=%__BuildType% /p:Platform=%__CrossArch% %__UnprocessedBuildArgs%
if not !errorlevel! == 0 (
echo %__MsgPrefix%Error: cross-arch components build failed. Refer to the build log files for details:
echo !__BuildLog!
echo !__BuildWrn!
echo !__BuildErr!
exit /b 1
)
:SkipCrossCompBuild
REM } Scope environment changes end
endlocal
)
REM =========================================================================================
REM ===
REM === All builds complete!
REM ===
REM =========================================================================================
echo %__MsgPrefix%Repo successfully built. Finished at %TIME%
echo %__MsgPrefix%Product binaries are available at !__BinDir!
exit /b 0
REM =========================================================================================
REM ===
REM === Helper routines
REM ===
REM =========================================================================================
:Usage
echo.
echo Build the Diagnostics repo.
echo.
echo Usage:
echo build-native.cmd [option1] [option2]
echo.
echo All arguments are optional. The options are:
echo.
echo.-? -h -help --help: view this message.
echo -build - build native components
echo -test - test native components
echo -architechure <x64|x86|arm|arm64>
echo -configuration <debug|release>
exit /b 1
:PrivateToolSet
echo %__MsgPrefix%Setting up the usage of __ToolsetDir:%__ToolsetDir%
if /i "%__ToolsetDir%" == "" (
echo %__MsgPrefix%Error: A toolset directory is required for the Arm64 Windows build. Use the toolset_dir argument.
exit /b 1
)
if not exist "%__ToolsetDir%"\buildenv_arm64.cmd goto :Not_EWDK
call "%__ToolsetDir%"\buildenv_arm64.cmd
exit /b 0
:Not_EWDK
set PATH=%__ToolsetDir%\VC_sdk\bin;%PATH%
set LIB=%__ToolsetDir%\VC_sdk\lib\arm64;%__ToolsetDir%\sdpublic\sdk\lib\arm64
set INCLUDE=^
%__ToolsetDir%\VC_sdk\inc;^
%__ToolsetDir%\sdpublic\sdk\inc;^
%__ToolsetDir%\sdpublic\shared\inc;^
%__ToolsetDir%\sdpublic\shared\inc\minwin;^
%__ToolsetDir%\sdpublic\sdk\inc\ucrt;^
%__ToolsetDir%\sdpublic\sdk\inc\minwin;^
%__ToolsetDir%\sdpublic\sdk\inc\mincore;^
%__ToolsetDir%\sdpublic\sdk\inc\abi;^
%__ToolsetDir%\sdpublic\sdk\inc\clientcore;^
%__ToolsetDir%\diasdk\include
exit /b 0

9
eng/Build.cmd Normal file
Просмотреть файл

@ -0,0 +1,9 @@
@echo off
rem build/test managed components
powershell -ExecutionPolicy ByPass -command "& """%~dp0common\Build.ps1""" %*"
if NOT '%ERRORLEVEL%' == '0' exit /b %ERRORLEVEL%
rem build/test native componments
call %~dp0build-native.cmd %*
exit /b %ERRORLEVEL%

3
eng/CIBuild.cmd Normal file
Просмотреть файл

@ -0,0 +1,3 @@
@echo off
call %~dp0Build.cmd -restore -build -test -sign -ci %*
exit /b %ErrorLevel%

Просмотреть файл

@ -11,7 +11,7 @@
<UsingToolXliff>false</UsingToolXliff>
<!-- CoreFX -->
<SystemReflectionMetadataVersion>1.6.0-preview2-26406-04</SystemReflectionMetadataVersion>
<SystemReflectionMetadataVersion>1.5.0</SystemReflectionMetadataVersion>
</PropertyGroup>
<PropertyGroup>

Просмотреть файл

@ -30,6 +30,25 @@ __UnprocessedBuildArgs=
__Build=0
__Test=0
# resolve python-version to use
if [ "$PYTHON" == "" ] ; then
if ! PYTHON=$(command -v python2.7 || command -v python2 || command -v python)
then
echo "Unable to locate build-dependency python2.x!" 1>&2
exit 1
fi
fi
# validate python-dependency
# useful in case of explicitly set option.
if ! command -v $PYTHON > /dev/null
then
echo "Unable to locate build-dependency python2.x ($PYTHON)!" 1>&2
exit 1
fi
echo $PYTHON
usage()
{
echo "Usage: $0 [options]"
@ -37,7 +56,8 @@ usage()
echo "--test - test native components"
echo "--architechure <x64|x86|arm|armel|arm64>"
echo "--configuration <debug|release>"
echo "--clangx.y - optional argument to build using clang version x.y."
echo "--clangx.y - optional argument to build using clang version x.y"
echo "--help - this help message"
exit 1
}
@ -197,6 +217,7 @@ done
__RootBinDir=$__ProjectRoot/artifacts
__IntermediatesDir="$__RootBinDir/obj/$__BuildOS.$__BuildArch.$__BuildType"
__LogFileDir="$__RootBinDir/log/$__BuildOS.$__BuildArch.$__BuildType"
__ExtraCmakeArgs="-DCLR_MANAGED_BINARY_DIR=$__RootBinDir/$__BuildType/bin"
# Specify path to be set for CMAKE_INSTALL_PREFIX.
# This is where all built native libraries will copied to.
@ -213,6 +234,11 @@ if [[ $__ClangMajorVersion == 0 && $__ClangMinorVersion == 0 ]]; then
fi
fi
if [[ "$__BuildArch" == "armel" ]]; then
# Armel cross build is Tizen specific and does not support Portable RID build
__PortableBuild=0
fi
mkdir -p "$__IntermediatesDir"
mkdir -p "$__LogFileDir"
mkdir -p "$__CMakeBinDir"
@ -260,7 +286,14 @@ initHostDistroRid()
if [ "$__HostOS" == "Linux" ]; then
if [ -e /etc/os-release ]; then
source /etc/os-release
if [[ $ID == "rhel" ]]; then
# remove the last version digit
VERSION_ID=${VERSION_ID%.*}
fi
__HostDistroRid="$ID.$VERSION_ID-$__HostArch"
if [[ $ID == "alpine" ]]; then
__HostDistroRid="linux-musl-$__HostArch"
fi
elif [ -e /etc/redhat-release ]; then
local redhatRelease=$(</etc/redhat-release)
if [[ $redhatRelease == "CentOS release 6."* || $redhatRelease == "Red Hat Enterprise Linux Server release 6."* ]]; then
@ -268,6 +301,10 @@ initHostDistroRid()
fi
fi
fi
if [ "$__HostOS" == "FreeBSD" ]; then
__freebsd_version=`sysctl -n kern.osrelease | cut -f1 -d'.'`
__HostDistroRid="freebsd.$__freebsd_version-$__HostArch"
fi
if [ "$__HostDistroRid" == "" ]; then
echo "WARNING: Can not determine runtime id for current distro."
@ -279,8 +316,13 @@ initTargetDistroRid()
if [ $__CrossBuild == 1 ]; then
if [ "$__BuildOS" == "Linux" ]; then
if [ ! -e $ROOTFS_DIR/etc/os-release ]; then
echo "WARNING: Can not determine runtime id for current distro."
export __DistroRid=""
if [ -e $ROOTFS_DIR/android_platform ]; then
source $ROOTFS_DIR/android_platform
export __DistroRid="$RID"
else
echo "WARNING: Can not determine runtime id for current distro."
export __DistroRid=""
fi
else
source $ROOTFS_DIR/etc/os-release
export __DistroRid="$ID.$VERSION_ID-$__BuildArch"
@ -290,16 +332,23 @@ initTargetDistroRid()
export __DistroRid="$__HostDistroRid"
fi
if [ "$__BuildOS" == "OSX" ]; then
__PortableBuild=1
fi
# Portable builds target the base RID
if [ $__PortableBuild == 1 ]; then
if [ "$__BuildOS" == "Linux" ]; then
export __DistroRid="linux-$__BuildArch"
elif [ "$__BuildOS" == "OSX" ]; then
export __DistroRid="osx-$__BuildArch"
elif [ "$__BuildOS" == "FreeBSD" ]; then
export __DistroRid="freebsd-$__BuildArch"
fi
fi
}
# Init the host distro name
initHostDistroRid
@ -315,3 +364,6 @@ fi
if [ $__Test == 1 ]; then
"$__ProjectRoot/src/SOS/tests/testsos.sh" "$__ProjectRoot" "$__CMakeBinDir" "$__RootBinDir/$__BuildType/bin" "$__LogFileDir" "$__BuildArch"
fi
echo "BUILD: Repo sucessfully built."
echo "BUILD: Product binaries are available at $__CMakeBinDir"

Просмотреть файл

@ -16,12 +16,42 @@ done
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
# install .NET Core - setting DOTNET_INSTALL_DIR prevents build.sh from installing it
# ReadJson [filename] [json key]
# Result: Sets 'readjsonvalue' to the value of the provided json key
# Note: this method may return unexpected results if there are duplicate
# keys in the json
function ReadJson {
local file=$1
local key=$2
local unamestr="$(uname)"
local sedextended='-r'
if [[ "$unamestr" == 'Darwin' ]]; then
sedextended='-E'
fi;
readjsonvalue="$(grep -m 1 "\"$key\"" $file | sed $sedextended 's/^ *//;s/.*: *"//;s/",?//')"
if [[ ! "$readjsonvalue" ]]; then
echo "Error: Cannot find \"$key\" in $file" >&2;
ExitWithExitCode 1
fi;
}
# install .NET Core
ReadJson "$scriptroot/../global.json" "version"
# setting DOTNET_INSTALL_DIR prevents build.sh from installing it
export DOTNET_INSTALL_DIR=$scriptroot/../.dotnet
"$scriptroot/install-dotnet.sh" $DOTNET_INSTALL_DIR 2.1.300-rc1-008673
"$scriptroot/install-dotnet.sh" $DOTNET_INSTALL_DIR $readjsonvalue
if [[ $? != 0 ]]; then
exit 1
fi
# build/test managed components
"$scriptroot/common/build.sh" $@
if [[ $? != 0 ]]; then
exit 1
fi
# build/test native components
"$scriptroot/build-native.sh" $@

Просмотреть файл

@ -15,4 +15,4 @@ while [[ -h $source ]]; do
done
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
"$scriptroot/build.sh" --restore --build --test --pack --ci $@
"$scriptroot/build.sh" --restore --build --test --sign --ci $@

Просмотреть файл

Просмотреть файл

@ -0,0 +1,11 @@
{
# Remove the CR character in case the sources are mapped from
# a Windows share and contain CRLF line endings
gsub(/\r/,"", $0);
# Skip empty lines and comment lines starting with semicolon
if (NF && !match($0, /^[:space:]*;/))
{
print "_" $0;
}
}

Просмотреть файл

@ -0,0 +1,19 @@
BEGIN {
print "V1.0 {";
print " global:";
}
{
# Remove the CR character in case the sources are mapped from
# a Windows share and contain CRLF line endings
gsub(/\r/,"", $0);
# Skip empty lines and comment lines starting with semicolon
if (NF && !match($0, /^[ \t]*;/))
{
print " " $0 ";";
}
}
END {
print " local: *;"
print "};";
}

Просмотреть файл

@ -86,3 +86,6 @@ if [ ! -e "$dotnet_root" ]; then
tar -xf "$dotnet_root/dotnet.tar"
fi
echo "Adding to current process PATH: \`$dotnet_root\`. Note: This change will be visible only when sourcing script."
export PATH="$dotnet_root":"$PATH"

Просмотреть файл

48
eng/setup_vs_tools.cmd Normal file
Просмотреть файл

@ -0,0 +1,48 @@
@if not defined _echo @echo off
REM This script is responsible for setting up either the vs2015 or vs2017 env
REM All passed arguments are ignored
REM Script will return with 0 if pass, 1 if there is a failure to find either
REM vs2015 or vs2017
:: Default to highest Visual Studio version available
::
:: For VS2015 (and prior), only a single instance is allowed to be installed on a box
:: and VS140COMNTOOLS is set as a global environment variable by the installer. This
:: allows users to locate where the instance of VS2015 is installed.
::
:: For VS2017, multiple instances can be installed on the same box SxS and VS150COMNTOOLS
:: is no longer set as a global environment variable and is instead only set if the user
:: has launched the VS2017 Developer Command Prompt.
::
:: Following this logic, we will default to the VS2017 toolset if VS150COMNTOOLS tools is
:: set, as this indicates the user is running from the VS2017 Developer Command Prompt and
:: is already configured to use that toolset. Otherwise, we will fallback to using the VS2015
:: toolset if it is installed. Finally, we will fail the script if no supported VS instance
:: can be found.
if defined VisualStudioVersion (
if not defined __VSVersion echo %__MsgPrefix%Detected Visual Studio %VisualStudioVersion% developer command ^prompt environment
goto skip_setup
)
echo %__MsgPrefix%Searching ^for Visual Studio 2017 or 2015 installation
set _VSWHERE="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
if exist %_VSWHERE% (
for /f "usebackq tokens=*" %%i in (`%_VSWHERE% -latest -prerelease -property installationPath`) do set _VSCOMNTOOLS=%%i\Common7\Tools
goto call_vs
)
if not exist "%_VSCOMNTOOLS%" set _VSCOMNTOOLS=%VS140COMNTOOLS%
echo VS2017 not found, using VS2015
:call_vs
if not exist "%_VSCOMNTOOLS%" (
echo %__MsgPrefix%Error: Visual Studio 2015 or 2017 required.
echo Please see https://github.com/dotnet/coreclr/blob/master/Documentation/building/windows-instructions.md for build instructions.
exit /b 1
)
echo %__MsgPrefix%"%_VSCOMNTOOLS%\VsDevCmd.bat"
call "%_VSCOMNTOOLS%\VsDevCmd.bat"
:skip_setup
exit /b 0

Просмотреть файл

@ -11,6 +11,85 @@ function(clr_unknown_arch)
endif()
endfunction()
# Build a list of compiler definitions by putting -D in front of each define.
function(get_compile_definitions DefinitionName)
# Get the current list of definitions
get_directory_property(COMPILE_DEFINITIONS_LIST COMPILE_DEFINITIONS)
foreach(DEFINITION IN LISTS COMPILE_DEFINITIONS_LIST)
if (${DEFINITION} MATCHES "^\\$<\\$<CONFIG:([^>]+)>:([^>]+)>$")
# The entries that contain generator expressions must have the -D inside of the
# expression. So we transform e.g. $<$<CONFIG:Debug>:_DEBUG> to $<$<CONFIG:Debug>:-D_DEBUG>
set(DEFINITION "$<$<CONFIG:${CMAKE_MATCH_1}>:-D${CMAKE_MATCH_2}>")
else()
set(DEFINITION -D${DEFINITION})
endif()
list(APPEND DEFINITIONS ${DEFINITION})
endforeach()
set(${DefinitionName} ${DEFINITIONS} PARENT_SCOPE)
endfunction(get_compile_definitions)
# Build a list of include directories
function(get_include_directories IncludeDirectories)
get_directory_property(dirs INCLUDE_DIRECTORIES)
foreach(dir IN LISTS dirs)
if (CLR_CMAKE_PLATFORM_ARCH_ARM AND WIN32)
list(APPEND INC_DIRECTORIES /I${dir})
else()
list(APPEND INC_DIRECTORIES -I${dir})
endif(CLR_CMAKE_PLATFORM_ARCH_ARM AND WIN32)
endforeach()
set(${IncludeDirectories} ${INC_DIRECTORIES} PARENT_SCOPE)
endfunction(get_include_directories)
# Set the passed in RetSources variable to the list of sources with added current source directory
# to form absolute paths.
# The parameters after the RetSources are the input files.
function(convert_to_absolute_path RetSources)
set(Sources ${ARGN})
foreach(Source IN LISTS Sources)
list(APPEND AbsolutePathSources ${CMAKE_CURRENT_SOURCE_DIR}/${Source})
endforeach()
set(${RetSources} ${AbsolutePathSources} PARENT_SCOPE)
endfunction(convert_to_absolute_path)
#Preprocess exports definition file
function(preprocess_def_file inputFilename outputFilename)
get_compile_definitions(PREPROCESS_DEFINITIONS)
get_include_directories(ASM_INCLUDE_DIRECTORIES)
add_custom_command(
OUTPUT ${outputFilename}
COMMAND ${CMAKE_CXX_COMPILER} ${ASM_INCLUDE_DIRECTORIES} /P /EP /TC ${PREPROCESS_DEFINITIONS} /Fi${outputFilename} ${inputFilename}
DEPENDS ${inputFilename}
COMMENT "Preprocessing ${inputFilename} - ${CMAKE_CXX_COMPILER} ${ASM_INCLUDE_DIRECTORIES} /P /EP /TC ${PREPROCESS_DEFINITIONS} /Fi${outputFilename} ${inputFilename}"
)
set_source_files_properties(${outputFilename}
PROPERTIES GENERATED TRUE)
endfunction()
function(generate_exports_file)
set(INPUT_LIST ${ARGN})
list(GET INPUT_LIST -1 outputFilename)
list(REMOVE_AT INPUT_LIST -1)
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
set(AWK_SCRIPT eng/generateexportedsymbols.awk)
else()
set(AWK_SCRIPT eng/generateversionscript.awk)
endif(CMAKE_SYSTEM_NAME STREQUAL Darwin)
add_custom_command(
OUTPUT ${outputFilename}
COMMAND ${AWK} -f ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT} ${INPUT_LIST} >${outputFilename}
DEPENDS ${INPUT_LIST} ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT}
COMMENT "Generating exports file ${outputFilename}"
)
set_source_files_properties(${outputFilename}
PROPERTIES GENERATED TRUE)
endfunction()
function(strip_symbols targetName outputFilename)
if (CLR_CMAKE_PLATFORM_UNIX)
if (STRIP_SYMBOLS)
@ -69,18 +148,25 @@ function(install_clr targetName)
install(PROGRAMS ${install_source_file} DESTINATION .)
if(WIN32)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/${targetName}.pdb DESTINATION PDB)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/${targetName}.pdb DESTINATION .)
else()
install(FILES ${strip_destination_file} DESTINATION .)
endif()
if(CLR_CMAKE_PGO_INSTRUMENT)
if(WIN32)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/${targetName}.pgd DESTINATION PGD OPTIONAL)
endif()
endif()
endif()
endfunction()
function(_add_executable)
if(NOT WIN32)
add_executable(${ARGV} ${VERSION_FILE_PATH})
else()
add_executable(${ARGV})
endif(NOT WIN32)
list(FIND CLR_CROSS_COMPONENTS_LIST ${ARGV0} INDEX)
if (DEFINED CLR_CROSS_COMPONENTS_LIST AND ${INDEX} EQUAL -1)
set_target_properties(${ARGV0} PROPERTIES EXCLUDE_FROM_ALL 1)
endif()
endfunction()
function(_add_library)
if(NOT WIN32)
add_library(${ARGV} ${VERSION_FILE_PATH})
@ -96,3 +182,14 @@ endfunction()
function(add_library_clr)
_add_library(${ARGV})
endfunction()
function(add_executable_clr)
_add_executable(${ARGV})
endfunction()
function(_install)
if(NOT DEFINED CLR_CROSS_COMPONENTS_BUILD)
install(${ARGV})
endif()
endfunction()

Просмотреть файл

@ -41,7 +41,7 @@ buildConfigurations.each { config ->
stage ('Build/Test') {
if (os == "Windows_NT") {
bat ".\\eng\\common\\CIBuild.cmd -configuration ${config.Configuration} -prepareMachine"
bat ".\\eng\\CIBuild.cmd -configuration ${config.Configuration} -prepareMachine"
} else {
sh "./eng/cibuild.sh --configuration ${config.Configuration} --architechure ${config.Architechure} --prepareMachine"
}

Просмотреть файл

@ -1 +1,11 @@
include_directories(${ROOT_DIR}/src/pal/prebuilt/inc)
include_directories(inc)
if (CLR_CMAKE_PLATFORM_UNIX)
add_subdirectory(palrt)
add_subdirectory(pal)
endif(CLR_CMAKE_PLATFORM_UNIX)
add_subdirectory(inc)
add_subdirectory(SOS)

Просмотреть файл

@ -1,3 +1,30 @@
if(CLR_CMAKE_PLATFORM_UNIX)
include_directories(${ROOT_DIR}/src/pal/inc)
include_directories(${ROOT_DIR}/src/pal/inc/rt)
add_subdirectory(lldbplugin)
endif(CLR_CMAKE_PLATFORM_UNIX)
# lldbplugin doesn't build with these options
if(WIN32)
add_compile_options(/FIWarningControl.h) # force include of WarningControl.h
add_compile_options(/Zl) # omit default library name in .OBJ
endif(WIN32)
add_definitions(-D_SECURE_SCL=0)
add_subdirectory(NETCore)
add_subdirectory(Strike)
if(CLR_CMAKE_PLATFORM_UNIX)
add_compile_options(-fPIC)
# Include the dummy c++ include files
include_directories(${ROOT_DIR}/src/pal/inc/rt/cpp)
# This prevents inclusion of standard C compiler headers
add_compile_options(-nostdinc)
endif(CLR_CMAKE_PLATFORM_UNIX)
add_subdirectory(debugshim)
add_subdirectory(dbgutil)

Просмотреть файл

@ -0,0 +1,8 @@
project(SOS.NETCore)
if(NOT ${CLR_MANAGED_BINARY_DIR} STREQUAL "")
set(MANAGED_BINDIR ${CLR_MANAGED_BINARY_DIR}/SOS.NETCore/netcoreapp1.0)
install(FILES ${MANAGED_BINDIR}/SOS.NETCore.dll DESTINATION .)
install(FILES ${MANAGED_BINDIR}/SOS.NETCore.pdb DESTINATION .)
endif()

Просмотреть файл

@ -1,3 +1,7 @@
project(sos)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Set the RPATH of sos so that it can find dependencies without needing to set LD_LIBRARY_PATH
# For more information: http://www.cmake.org/Wiki/CMake_RPATH_handling.
if (CORECLR_SET_RPATH)
@ -10,44 +14,27 @@ if (CORECLR_SET_RPATH)
endif (CORECLR_SET_RPATH)
if(CLR_CMAKE_PLATFORM_ARCH_AMD64)
add_definitions(-DSOS_TARGET_AMD64=1)
add_definitions(-D_TARGET_WIN64_=1)
add_definitions(-DDBG_TARGET_64BIT)
add_definitions(-DDBG_TARGET_WIN64=1)
add_definitions(-DSOS_TARGET_AMD64=1)
if(WIN32)
add_definitions(-DSOS_TARGET_ARM64=1)
endif(WIN32)
remove_definitions(-D_TARGET_ARM64_=1)
add_definitions(-D_TARGET_AMD64_)
add_definitions(-DDBG_TARGET_AMD64)
elseif(CLR_CMAKE_PLATFORM_ARCH_I386)
add_definitions(-DSOS_TARGET_X86=1)
add_definitions(-D_TARGET_X86_=1)
add_definitions(-DDBG_TARGET_32BIT)
if(WIN32)
add_definitions(-DSOS_TARGET_ARM=1)
endif(WIN32)
elseif(CLR_CMAKE_PLATFORM_ARCH_ARM)
add_definitions(-DSOS_TARGET_ARM=1)
add_definitions(-D_TARGET_WIN32_=1)
add_definitions(-D_TARGET_ARM_=1)
add_definitions(-DDBG_TARGET_32BIT)
elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64)
add_definitions(-DSOS_TARGET_ARM64=1)
add_definitions(-D_TARGET_WIN64_=1)
add_definitions(-DDBG_TARGET_64BIT)
add_definitions(-DDBG_TARGET_WIN64=1)
add_definitions(-DSOS_TARGET_ARM64=1)
endif()
add_definitions(-DSTRIKE)
remove_definitions(-DUNICODE)
remove_definitions(-D_UNICODE)
include_directories(BEFORE ${VM_DIR})
include_directories(${CLR_DIR}/src/gcdump)
include_directories(${CLR_DIR}/src/debug/shim)
include_directories(${CLR_DIR}/src/coreclr/hosts/unixcoreruncommon)
include_directories(${CLR_DIR}/src/coreclr/hosts/inc)
include_directories(${ROOT_DIR}/src/SOS/gcdump)
include_directories(${ROOT_DIR}/src/SOS/debugshim)
if(WIN32)
include_directories(inc)
@ -127,31 +114,50 @@ else(WIN32)
strike.cpp
sos.cpp
util.cpp
../../../coreclr/hosts/unixcoreruncommon/coreruncommon.cpp
)
set(SOS_LIBRARY
corguids
debugshim
dbgutil
# share the PAL in the dac module
mscordaccore
palrt
)
set(DEF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/sos_unixexports.src)
set(EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/sos.exports)
generate_exports_file(${DEF_SOURCES} ${EXPORTS_FILE})
if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker -Bsymbolic -Xlinker -Bsymbolic-functions")
# These options are used to force every object to be included even if it's unused.
set(START_WHOLE_ARCHIVE -Wl,--whole-archive)
set(END_WHOLE_ARCHIVE -Wl,--no-whole-archive)
set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE})
endif(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
# These options are used to force every object to be included even if it's unused.
set(START_WHOLE_ARCHIVE -force_load)
set(END_WHOLE_ARCHIVE )
set(EXPORTS_LINKER_OPTION -Wl,-exported_symbols_list,${EXPORTS_FILE})
endif(CMAKE_SYSTEM_NAME STREQUAL Darwin)
set(SOS_LIBRARY
corguids
debugshim
dbgutil
${START_WHOLE_ARCHIVE} # force all PAL objects to be included so all exports are available
coreclrpal
${END_WHOLE_ARCHIVE}
palrt
)
endif(WIN32)
if(CLR_CMAKE_PLATFORM_ARCH_AMD64)
if(CLR_CMAKE_PLATFORM_LINUX)
list(APPEND
SOS_LIBRARY
createdump_lib
)
add_definitions(-DCREATE_DUMP_SUPPORTED)
endif(CLR_CMAKE_PLATFORM_LINUX)
# if(CLR_CMAKE_PLATFORM_LINUX)
#list(APPEND
# SOS_LIBRARY
# createdump_lib
#)
#add_definitions(-DCREATE_DUMP_SUPPORTED)
# endif(CLR_CMAKE_PLATFORM_LINUX)
set(SOS_SOURCES_ARCH
disasmX86.cpp
)
@ -201,8 +207,6 @@ if(CLR_CMAKE_PLATFORM_UNIX)
set_property(TARGET sos APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION})
set_property(TARGET sos APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE})
add_dependencies(sos mscordaccore)
endif(CLR_CMAKE_PLATFORM_UNIX)
target_link_libraries(sos ${SOS_LIBRARY})

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

426
src/SOS/Strike/dbgutil.cpp Normal file
Просмотреть файл

@ -0,0 +1,426 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//*****************************************************************************
// dbgutil.cpp
//
//
//*****************************************************************************
//
// Various common helpers for PE resource reading used by multiple debug components.
//
#include <dbgutil.h>
#include "corerror.h"
#include <assert.h>
#include <stdio.h>
// Returns the RVA of the resource section for the module specified by the given data target and module base.
// Returns failure if the module doesn't have a resource section.
//
// Arguments
// pDataTarget - dataTarget for the process we are inspecting
// moduleBaseAddress - base address of a module we should inspect
// pwImageFileMachine - updated with the Machine from the IMAGE_FILE_HEADER
// pdwResourceSectionRVA - updated with the resultant RVA on success
HRESULT GetMachineAndResourceSectionRVA(ICorDebugDataTarget* pDataTarget,
ULONG64 moduleBaseAddress,
WORD* pwImageFileMachine,
DWORD* pdwResourceSectionRVA)
{
// Fun code ahead... below is a hand written PE decoder with some of the file offsets hardcoded.
// It supports no more than what we absolutely have to to get to the resources we need. Any of the
// magic numbers used below can be determined by using the public documentation on the web.
//
// Yes utilcode has a PE decoder, no it does not support reading its data through a datatarget
// It was easier to inspect the small portion that I needed than to shove an abstraction layer under
// our utilcode and then make sure everything still worked.
// SECURITY WARNING: all data provided by the data target should be considered untrusted.
// Do not allow malicious data to cause large reads, memory allocations, buffer overflow,
// or any other undesirable behavior.
HRESULT hr = S_OK;
// at offset 3c in the image is a 4 byte file pointer that indicates where the PE signature is
IMAGE_DOS_HEADER dosHeader;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress, (BYTE*)&dosHeader, sizeof(dosHeader));
// verify there is a 4 byte PE signature there
DWORD peSigFilePointer = 0;
if (SUCCEEDED(hr))
{
peSigFilePointer = dosHeader.e_lfanew;
DWORD peSig = 0;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peSigFilePointer, (BYTE*)&peSig, 4);
if (SUCCEEDED(hr) && peSig != IMAGE_NT_SIGNATURE)
{
hr = E_FAIL; // PE signature not present
}
}
// after the signature is a 20 byte image file header
// we need to parse this to figure out the target architecture
IMAGE_FILE_HEADER imageFileHeader;
if (SUCCEEDED(hr))
{
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peSigFilePointer + 4, (BYTE*)&imageFileHeader, IMAGE_SIZEOF_FILE_HEADER);
}
WORD optHeaderMagic = 0;
DWORD peOptImageHeaderFilePointer = 0;
if (SUCCEEDED(hr))
{
if(pwImageFileMachine != NULL)
{
*pwImageFileMachine = imageFileHeader.Machine;
}
// 4 bytes after the signature is the 20 byte image file header
// 24 bytes after the signature is the image-only header
// at the beginning of the image-only header is a 2 byte magic number indicating its format
peOptImageHeaderFilePointer = peSigFilePointer + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD);
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peOptImageHeaderFilePointer, (BYTE*)&optHeaderMagic, 2);
}
// Either 112 or 128 bytes after the beginning of the image-only header is an 8 byte resource table
// depending on whether the image is PE32 or PE32+
DWORD resourceSectionRVA = 0;
if (SUCCEEDED(hr))
{
if (optHeaderMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) // PE32
{
IMAGE_OPTIONAL_HEADER32 header32;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peOptImageHeaderFilePointer,
(BYTE*)&header32, sizeof(header32));
if (SUCCEEDED(hr))
{
resourceSectionRVA = header32.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
}
}
else if (optHeaderMagic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) //PE32+
{
IMAGE_OPTIONAL_HEADER64 header64;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peOptImageHeaderFilePointer,
(BYTE*)&header64, sizeof(header64));
if (SUCCEEDED(hr))
{
resourceSectionRVA = header64.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
}
}
else
{
hr = E_FAIL; // Invalid PE
}
}
*pdwResourceSectionRVA = resourceSectionRVA;
return S_OK;
}
HRESULT GetResourceRvaFromResourceSectionRva(ICorDebugDataTarget* pDataTarget,
ULONG64 moduleBaseAddress,
DWORD resourceSectionRva,
DWORD type,
DWORD name,
DWORD language,
DWORD* pResourceRva,
DWORD* pResourceSize)
{
HRESULT hr = S_OK;
DWORD nameTableRva = 0;
DWORD langTableRva = 0;
DWORD resourceDataEntryRva = 0;
*pResourceRva = 0;
*pResourceSize = 0;
// The resource section begins with a resource directory that indexes all the resources by type.
// Each entry it points to is another resource directory that indexes all the same type
// resources by name. And each entry in that table points to another resource directory that indexes
// all the same type/name resources by language. Entries in the final table give the RVA of the actual
// resource.
// Note all RVAs in this section are relative to the beginning of the resource section,
// not the beginning of the image.
hr = GetNextLevelResourceEntryRVA(pDataTarget, type, moduleBaseAddress, resourceSectionRva, &nameTableRva);
if (SUCCEEDED(hr))
{
nameTableRva += resourceSectionRva;
hr = GetNextLevelResourceEntryRVA(pDataTarget, name, moduleBaseAddress, nameTableRva, &langTableRva);
}
if (SUCCEEDED(hr))
{
langTableRva += resourceSectionRva;
hr = GetNextLevelResourceEntryRVA(pDataTarget, language, moduleBaseAddress, langTableRva, &resourceDataEntryRva);
}
// The resource data entry has the first 4 bytes indicating the RVA of the resource
// The next 4 bytes indicate the size of the resource
if (SUCCEEDED(hr))
{
resourceDataEntryRva += resourceSectionRva;
IMAGE_RESOURCE_DATA_ENTRY dataEntry;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDataEntryRva,
(BYTE*)&dataEntry, sizeof(dataEntry));
*pResourceRva = dataEntry.OffsetToData;
*pResourceSize = dataEntry.Size;
}
return hr;
}
HRESULT GetResourceRvaFromResourceSectionRvaByName(ICorDebugDataTarget* pDataTarget,
ULONG64 moduleBaseAddress,
DWORD resourceSectionRva,
DWORD type,
LPCWSTR pwszName,
DWORD language,
DWORD* pResourceRva,
DWORD* pResourceSize)
{
HRESULT hr = S_OK;
DWORD nameTableRva = 0;
DWORD langTableRva = 0;
DWORD resourceDataEntryRva = 0;
*pResourceRva = 0;
*pResourceSize = 0;
// The resource section begins with a resource directory that indexes all the resources by type.
// Each entry it points to is another resource directory that indexes all the same type
// resources by name. And each entry in that table points to another resource directory that indexes
// all the same type/name resources by language. Entries in the final table give the RVA of the actual
// resource.
// Note all RVAs in this section are relative to the beginning of the resource section,
// not the beginning of the image.
hr = GetNextLevelResourceEntryRVA(pDataTarget, type, moduleBaseAddress, resourceSectionRva, &nameTableRva);
if (SUCCEEDED(hr))
{
nameTableRva += resourceSectionRva;
hr = GetNextLevelResourceEntryRVAByName(pDataTarget, pwszName, moduleBaseAddress, nameTableRva, resourceSectionRva, &langTableRva);
}
if (SUCCEEDED(hr))
{
langTableRva += resourceSectionRva;
hr = GetNextLevelResourceEntryRVA(pDataTarget, language, moduleBaseAddress, langTableRva, &resourceDataEntryRva);
}
// The resource data entry has the first 4 bytes indicating the RVA of the resource
// The next 4 bytes indicate the size of the resource
if (SUCCEEDED(hr))
{
resourceDataEntryRva += resourceSectionRva;
IMAGE_RESOURCE_DATA_ENTRY dataEntry;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDataEntryRva,
(BYTE*)&dataEntry, sizeof(dataEntry));
*pResourceRva = dataEntry.OffsetToData;
*pResourceSize = dataEntry.Size;
}
return hr;
}
// Traverses down one level in the PE resource tree structure
//
// Arguments:
// pDataTarget - the data target for inspecting this process
// id - the id of the next node in the resource tree you want
// moduleBaseAddress - the base address of the module being inspected
// resourceDirectoryRVA - the base address of the beginning of the resource directory for this
// level of the tree
// pNextLevelRVA - out - The RVA for the next level tree directory or the RVA of the resource entry
//
// Returns:
// S_OK if succesful or an appropriate failing HRESULT
HRESULT GetNextLevelResourceEntryRVA(ICorDebugDataTarget* pDataTarget,
DWORD id,
ULONG64 moduleBaseAddress,
DWORD resourceDirectoryRVA,
DWORD* pNextLevelRVA)
{
*pNextLevelRVA = 0;
HRESULT hr = S_OK;
// A resource directory which consists of
// a header followed by a number of entries. In the header at offset 12 is
// the number entries identified by name, followed by the number of entries
// identified by ID at offset 14. Both are 2 bytes.
// This method only supports locating entries by ID, not by name
IMAGE_RESOURCE_DIRECTORY resourceDirectory;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRVA, (BYTE*)&resourceDirectory, sizeof(resourceDirectory));
// The ith resource directory entry is at offset 16 + 8i from the beginning of the resource
// directory table
WORD numNameEntries;
WORD numIDEntries;
if (SUCCEEDED(hr))
{
numNameEntries = resourceDirectory.NumberOfNamedEntries;
numIDEntries = resourceDirectory.NumberOfIdEntries;
for (WORD i = numNameEntries; i < numNameEntries + numIDEntries; i++)
{
IMAGE_RESOURCE_DIRECTORY_ENTRY entry;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRVA + sizeof(resourceDirectory) + sizeof(entry)*i,
(BYTE*)&entry, sizeof(entry));
if (FAILED(hr))
{
break;
}
if (entry.Id == id)
{
*pNextLevelRVA = entry.OffsetToDirectory;
break;
}
}
}
// If we didn't find the entry
if (SUCCEEDED(hr) && *pNextLevelRVA == 0)
{
hr = E_FAIL;
}
return hr; // resource not found
}
// Traverses down one level in the PE resource tree structure
//
// Arguments:
// pDataTarget - the data target for inspecting this process
// name - the name of the next node in the resource tree you want
// moduleBaseAddress - the base address of the module being inspected
// resourceDirectoryRVA - the base address of the beginning of the resource directory for this
// level of the tree
// resourceSectionRVA - the rva of the beginning of the resource section of the PE file
// pNextLevelRVA - out - The RVA for the next level tree directory or the RVA of the resource entry
//
// Returns:
// S_OK if succesful or an appropriate failing HRESULT
HRESULT GetNextLevelResourceEntryRVAByName(ICorDebugDataTarget* pDataTarget,
LPCWSTR pwzName,
ULONG64 moduleBaseAddress,
DWORD resourceDirectoryRva,
DWORD resourceSectionRva,
DWORD* pNextLevelRva)
{
HRESULT hr = S_OK;
DWORD nameLength = (DWORD)wcslen(pwzName);
WCHAR entryName[50];
assert(nameLength < 50); // this implementation won't support matching a name longer
// than 50 characters. We only look up the hard coded name
// of the debug resource in clr.dll though, so it shouldn't be
// an issue. Increase this count if we ever want to look up
// larger names
if (nameLength >= 50)
{
hr = E_FAIL; // invalid name length
}
// A resource directory which consists of
// a header followed by a number of entries. In the header at offset 12 is
// the number entries identified by name, followed by the number of entries
// identified by ID at offset 14. Both are 2 bytes.
// This method only supports locating entries by ID, not by name
IMAGE_RESOURCE_DIRECTORY resourceDirectory = { 0 };
if (SUCCEEDED(hr))
{
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRva, (BYTE*)&resourceDirectory, sizeof(resourceDirectory));
}
// The ith resource directory entry is at offset 16 + 8i from the beginning of the resource
// directory table
if (SUCCEEDED(hr))
{
WORD numNameEntries = resourceDirectory.NumberOfNamedEntries;
for (WORD i = 0; i < numNameEntries; i++)
{
IMAGE_RESOURCE_DIRECTORY_ENTRY entry;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRva + sizeof(resourceDirectory) + sizeof(entry)*i,
(BYTE*)&entry, sizeof(entry));
if (FAILED(hr))
{
break;
}
// the NameRVAOrID field points to a UTF16 string with a 2 byte length in front of it
// read the 2 byte length first. The doc of course doesn't mention this, but the RVA is
// relative to the base of the resource section and needs the leading bit stripped.
WORD entryNameLength = 0;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceSectionRva +
entry.NameOffset, (BYTE*)&entryNameLength, sizeof(entryNameLength));
if (FAILED(hr))
{
break;
}
if (entryNameLength != nameLength)
{
continue; // names aren't the same length, not a match
}
// read the rest of the string data and check for a match
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceSectionRva +
entry.NameOffset + 2, (BYTE*)entryName, entryNameLength*sizeof(WCHAR));
if (FAILED(hr))
{
break;
}
if (memcmp(entryName, pwzName, entryNameLength*sizeof(WCHAR)) == 0)
{
*pNextLevelRva = entry.OffsetToDirectory;
break;
}
}
}
if (SUCCEEDED(hr) && *pNextLevelRva == 0)
{
hr = E_FAIL; // resource not found
}
return hr;
}
// A small wrapper that reads from the data target and throws on error
HRESULT ReadFromDataTarget(ICorDebugDataTarget* pDataTarget,
ULONG64 addr,
BYTE* pBuffer,
ULONG32 bytesToRead)
{
//PRECONDITION(CheckPointer(pDataTarget));
//PRECONDITION(CheckPointer(pBuffer));
HRESULT hr = S_OK;
ULONG32 bytesReadTotal = 0;
ULONG32 bytesRead = 0;
do
{
if (FAILED(pDataTarget->ReadVirtual((CORDB_ADDRESS)(addr + bytesReadTotal),
pBuffer,
bytesToRead - bytesReadTotal,
&bytesRead)))
{
hr = CORDBG_E_READVIRTUAL_FAILURE;
break;
}
bytesReadTotal += bytesRead;
} while (bytesRead != 0 && (bytesReadTotal < bytesToRead));
// If we can't read all the expected memory, then fail
if (SUCCEEDED(hr) && (bytesReadTotal != bytesToRead))
{
hr = HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
}
return hr;
}

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -41,7 +41,6 @@
// functions that read directly from the debuggee address space, vs. using
// the DAC to read the DAC-ized data structures.
#include "daccess.h"
#include "gcinfo.h"
// Convert between CLRDATA_ADDRESS and TADDR.
@ -194,26 +193,26 @@ public:
inline void EENotLoadedMessage(HRESULT Status)
{
ExtOut("Failed to find runtime DLL (%s), 0x%08x\n", MAKEDLLNAME_A("coreclr"), Status);
ExtOut("Failed to find runtime module (%s), 0x%08x\n", MAKEDLLNAME_A("coreclr"), Status);
ExtOut("Extension commands need it in order to have something to do.\n");
}
inline void DACMessage(HRESULT Status)
{
ExtOut("Failed to load data access DLL, 0x%08x\n", Status);
ExtOut("Failed to load data access module, 0x%08x\n", Status);
#ifndef FEATURE_PAL
ExtOut("Verify that 1) you have a recent build of the debugger (6.2.14 or newer)\n");
ExtOut(" 2) the file mscordacwks.dll that matches your version of coreclr.dll is \n");
ExtOut(" 2) the file mscordaccore.dll that matches your version of coreclr.dll is\n");
ExtOut(" in the version directory or on the symbol path\n");
ExtOut(" 3) or, if you are debugging a dump file, verify that the file \n");
ExtOut(" mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path.\n");
ExtOut(" mscordaccore_<arch>_<arch>_<version>.dll is on your symbol path.\n");
ExtOut(" 4) you are debugging on supported cross platform architecture as \n");
ExtOut(" the dump file. For example, an ARM dump file must be debugged\n");
ExtOut(" on an X86 or an ARM machine; an AMD64 dump file must be\n");
ExtOut(" debugged on an AMD64 machine.\n");
ExtOut("\n");
ExtOut("You can also run the debugger command .cordll to control the debugger's\n");
ExtOut("load of mscordacwks.dll. .cordll -ve -u -l will do a verbose reload.\n");
ExtOut("load of mscordaccore.dll. .cordll -ve -u -l will do a verbose reload.\n");
ExtOut("If that succeeds, the SOS command should work on retry.\n");
ExtOut("\n");
ExtOut("If you are debugging a minidump, you need to make sure that your executable\n");
@ -233,16 +232,21 @@ inline void DACMessage(HRESULT Status)
HRESULT CheckEEDll();
#define INIT_API_NOEE() \
// The minimum initialization for a command
#define INIT_API_EXT() \
HRESULT Status; \
__ExtensionCleanUp __extensionCleanUp; \
if ((Status = ExtQuery(client)) != S_OK) return Status; \
if ((Status = ArchQuery()) != S_OK) return Status; \
ControlC = FALSE; \
g_bDacBroken = TRUE; \
g_clrData = NULL; \
g_sos = NULL;
// Also initializes the target machine
#define INIT_API_NOEE() \
INIT_API_EXT() \
if ((Status = ArchQuery()) != S_OK) return Status;
#define INIT_API_EE() \
if ((Status = CheckEEDll()) != S_OK) \
{ \
@ -281,12 +285,12 @@ HRESULT CheckEEDll();
INIT_API_NOEE() \
if ((Status = CheckEEDll()) != S_OK) \
{ \
ExtOut("Failed to find runtime DLL (%s), 0x%08x\n", MAKEDLLNAME_A("coreclr"), Status); \
ExtOut("Failed to find runtime module (%s), 0x%08x\n", MAKEDLLNAME_A("coreclr"), Status); \
ExtOut("Some functionality may be impaired\n"); \
} \
else if ((Status = LoadClrDebugDll()) != S_OK) \
{ \
ExtOut("Failed to load data access DLL (%s), 0x%08x\n", MAKEDLLNAME_A("mscordaccore"), Status); \
ExtOut("Failed to load data access module (%s), 0x%08x\n", MAKEDLLNAME_A("mscordaccore"), Status); \
ExtOut("Some functionality may be impaired\n"); \
} \
else \

Просмотреть файл

@ -38,8 +38,6 @@
// functions that read directly from the debuggee address space, vs. using
// the DAC tgo read the DAC-ized data structures.
#include "daccess.h"
//#include "dbgeng.h"
#ifndef STRESS_LOG
#define STRESS_LOG

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -9,7 +9,7 @@
// ==--==
#include "strike.h"
#include "util.h"
#include "genericstackprobe.h"
//#include "genericstackprobe.h"
/**********************************************************************\
* Routine Description: *

Просмотреть файл

Просмотреть файл

@ -14,7 +14,7 @@
#define __PLATFORM_SPECIFIC_INCLUDED
// The main debugger code already has target platform definitions for CONTEXT.
#include "../../../debug/inc/dbgtargetcontext.h"
#include <dbgtargetcontext.h>
#ifndef FEATURE_PAL

Просмотреть файл

@ -31,6 +31,7 @@
#include "sos_md.h"
#define _BLD_CLR 1
#define SOS_INCLUDE 1
#include "corhlpr.h"
#include "corhlpr.cpp"

Просмотреть файл

Просмотреть файл

@ -91,6 +91,7 @@ EXPORTS
GcWhere=GCWhere
Help
help=Help
soshelp=Help
HistClear
histclear=HistClear
HistInit
@ -119,6 +120,8 @@ EXPORTS
Printexception=PrintException
SaveModule
savemodule=SaveModule
SetHostRuntime
sethostruntime=SetHostRuntime
SOSFlush
sosflush=SOSFlush
StopOnException

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -41,6 +41,7 @@ IP2MD
Name2EE
PrintException
StopOnCatch
SetHostRuntime
Threads
ThreadState
Token2EE

Просмотреть файл

@ -59,9 +59,9 @@ DumpCCW
Examining the GC history Other
----------------------------- -----------------------------
HistInit FAQ
HistRoot
HistObj
HistInit SetHostRuntime (sethostruntime)
HistRoot FAQ
HistObj soshelp
HistObjFind
HistClear
\\
@ -2132,20 +2132,19 @@ default one.
.................
SUCCESS: Stress log dumped
To turn on the stress log, set the following registry keys under
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework:
To turn on the stress log, set the following environment variables before
starting the .NET Core app:
(DWORD) StressLog = 1
(DWORD) LogFacility = 0xffffffbf (this is a bit mask, almost all logging is on.
This is also the default value if the key
isn't specified)
(DWORD) StressLogSize = 65536 (this is the default value if the key isn't
specified)
(DWORD) LogLevel = 6 (this is the default value if the key isn't
specified. The higher the number the more
detailed logs are generated. The maximum
value is decimal 10)
set COMPlus_StressLog = 1
set COMPlus_LogFacility = 0xffffffbf (this is a bit mask, almost all logging is on.
This is also the default value if the key
isn't specified)
set COMPlus_StressLogSize = 65536 (this is the default value if the key isn't
specified)
set COMPlus_LogLevel = 6 (this is the default value if the key isn't
specified. The higher the number the more
detailed logs are generated. The maximum
value is decimal 10)
StressLogSize is the size in bytes of the in-memory log allocated for each
thread in the process. In the case above, each thread gets a 64K log. You
@ -2567,4 +2566,15 @@ The output contains the COM reference count of the CCW, which is useful for
investigating lifetime issues of interop-heavy applications.
\\
COMMAND: sethostruntime.
!SetHostRuntime <runtime-directory>
This command sets the path to the .NET Core runtime to use to host the managed
code that runs as part of SOS in the debugger (cdb/windbg). The runtime needs
to be at least version 2.0.0 or greater. If there are spaces in directory, it
needs to be single-quoted (').
The default is to use the same runtime (coreclr.dll) being debugged. Use this
command when the runtime being debugged isn't working to run the SOS code or
if the version is less than 2.0.0.
\\

Просмотреть файл

@ -36,7 +36,7 @@ PrintException (pe) ClrStack (clrstack)
Examining CLR data structures Diagnostic Utilities
----------------------------- -----------------------------
DumpDomain VerifyHeap
DumpDomain (dumpdomain) VerifyHeap
EEHeap (eeheap) FindAppDomain
Name2EE (name2ee) DumpLog (dumplog)
DumpMT (dumpmt)
@ -52,8 +52,8 @@ DumpSigElem
Examining the GC history Other
----------------------------- -----------------------------
HistInit (histinit) FAQ
HistRoot (histroot) CreateDump (createdump)
HistInit (histinit) SetHostRuntime (sethostruntime)
HistRoot (histroot) FAQ
HistObj (histobj) Help (soshelp)
HistObjFind (histobjfind)
HistClear (histclear)
@ -619,15 +619,7 @@ hyperlinks to inspect the different managed stack frames and managed variables.
\\
COMMAND: createdump.
createdump [options] [dumpFileName]
-n - create minidump.
-h - create minidump with heap (default).
-t - create triage minidump.
-f - create full core dump (everything).
-d - enable diagnostic messages.
Creates a platform (ELF core on Linux, etc.) minidump. The pid can be placed in the dump
file name with %d. The default is '/tmp/coredump.%d'.
Currently not implemented.
\\
COMMAND: ip2md.
@ -1493,20 +1485,19 @@ default one.
.................
SUCCESS: Stress log dumped
To turn on the stress log, set the following registry keys under
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework:
To turn on the stress log, set the following environment variables before
starting the .NET Core app:
(DWORD) StressLog = 1
(DWORD) LogFacility = 0xffffffbf (this is a bit mask, almost all logging is on.
This is also the default value if the key
isn't specified)
(DWORD) StressLogSize = 65536 (this is the default value if the key isn't
specified)
(DWORD) LogLevel = 6 (this is the default value if the key isn't
specified. The higher the number the more
detailed logs are generated. The maximum
value is decimal 10)
export COMPlus_StressLog = 1
export COMPlus_LogFacility = 0xffffffbf (this is a bit mask, almost all logging is on.
This is also the default value if the key
isn't specified)
export COMPlus_StressLogSize = 65536 (this is the default value if the key isn't
specified)
export COMPlus_LogLevel = 6 (this is the default value if the key isn't
specified. The higher the number the more
detailed logs are generated. The maximum
value is decimal 10)
StressLogSize is the size in bytes of the in-memory log allocated for each
thread in the process. In the case above, each thread gets a 64K log. You
@ -1722,3 +1713,16 @@ cleanup the previous resources.
Completed successfully.
\\
COMMAND: sethostruntime.
!SetHostRuntime <runtime-directory>
This command sets the path to the .NET Core runtime to use to host the managed
code that runs as part of SOS in the debugger (lldb). The runtime needs
to be at least version 2.0.0 or greater. If there are spaces in directory, it
needs to be single-quoted (').
The default is to use the same runtime (libcoreclr) being debugged. Use this
command when the runtime being debugged isn't working to run the SOS code or
if the version is less than 2.0.0.
\\

Просмотреть файл

@ -113,7 +113,9 @@
#include "predeftlsslot.h"
#ifndef FEATURE_PAL
#include "hillclimbing.h"
#endif
#include "sos_md.h"
@ -436,10 +438,6 @@ void DumpStackInternal(DumpStackFlag *pDSFlag)
DumpStackWorker(*pDSFlag);
}
#if defined(FEATURE_PAL) && defined(_TARGET_AMD64_)
static BOOL UnwindStackFrames(ULONG32 osThreadId);
#endif
DECLARE_API(DumpStack)
{
INIT_API_NO_RET_ON_FAILURE();
@ -488,16 +486,8 @@ DECLARE_API(DumpStack)
g_ExtSystem->GetCurrentThreadId(&id);
ExtOut("(%d)\n", id);
#if defined(FEATURE_PAL) && defined(_TARGET_AMD64_)
if (unwind)
{
UnwindStackFrames(sysId);
}
else
#endif
{
DumpStackInternal(&DSFlag);
}
DumpStackInternal(&DSFlag);
return Status;
}
@ -1411,8 +1401,8 @@ DECLARE_API(DumpMT)
if (MethodDescData.Request(g_sos, TO_CDADDR(methodDesc)) == S_OK)
{
// Is it an fcall?
if ((TO_TADDR(MethodDescData.NativeCodeAddr) >= TO_TADDR(moduleInfo[MSCORWKS].baseAddr)) &&
((TO_TADDR(MethodDescData.NativeCodeAddr) < TO_TADDR(moduleInfo[MSCORWKS].baseAddr + moduleInfo[MSCORWKS].size))))
if ((TO_TADDR(MethodDescData.NativeCodeAddr) >= TO_TADDR(g_moduleInfo[MSCORWKS].baseAddr)) &&
((TO_TADDR(MethodDescData.NativeCodeAddr) < TO_TADDR(g_moduleInfo[MSCORWKS].baseAddr + g_moduleInfo[MSCORWKS].size))))
{
pszJitType = "FCALL";
}
@ -7084,7 +7074,6 @@ DECLARE_API(bpmd)
return Status;
}
// We keep a list of managed breakpoints the user wants to set, and display pending bps
// bpmd. If you call bpmd <module name> <method> we will set or update an existing bp.
// bpmd acts as a feeder of breakpoints to bp when the time is right.
@ -9007,7 +8996,7 @@ DECLARE_API (EEVersion)
}
else
{
BOOL fRet = IsRetailBuild ((size_t)moduleInfo[eef].baseAddr);
BOOL fRet = IsRetailBuild ((size_t)g_moduleInfo[eef].baseAddr);
if (fRet)
ExtOut(" retail");
@ -14516,6 +14505,43 @@ DECLARE_API(CreateDump)
#endif // FEATURE_PAL
extern LPCSTR g_hostRuntimeDirectory;
//
// Sets the .NET Core runtime path to use to run the managed code within SOS/native debugger.
//
DECLARE_API(SetHostRuntime)
{
INIT_API_EXT();
StringHolder hostRuntimeDirectory;
CMDValue arg[] =
{
{&hostRuntimeDirectory.data, COSTRING},
};
size_t narg;
if (!GetCMDOption(args, nullptr, 0, arg, _countof(arg), &narg))
{
return E_FAIL;
}
if (narg > 0)
{
if (g_hostRuntimeDirectory != nullptr)
{
free((void*)g_hostRuntimeDirectory);
}
g_hostRuntimeDirectory = _strdup(hostRuntimeDirectory.data);
}
else
{
if (g_hostRuntimeDirectory != nullptr)
{
ExtOut("%s\n", g_hostRuntimeDirectory);
}
}
return S_OK;
}
void PrintHelp (__in_z LPCSTR pszCmdName)
{
static LPSTR pText = NULL;
@ -14528,30 +14554,38 @@ void PrintHelp (__in_z LPCSTR pszCmdName)
if (hResource) pText = (LPSTR) LockResource (hResource);
if (pText == NULL)
{
ExtOut("Error loading documentation resource\n");
ExtErr("Error loading documentation resource\n");
return;
}
#else
int err = PAL_InitializeDLL();
if(err != 0)
{
ExtOut("Error initializing PAL\n");
ExtErr("Error initializing PAL\n");
return;
}
ArrayHolder<char> szSOSModulePath = new char[MAX_LONGPATH + 1];
UINT cch = MAX_LONGPATH;
if (!PAL_GetPALDirectoryA(szSOSModulePath, &cch)) {
ExtErr("Error: Failed to get SOS module directory\n");
return;
}
char lpFilename[MAX_LONGPATH + 12]; // + 12 to make enough room for strcat function.
strcpy_s(lpFilename, _countof(lpFilename), g_ExtServices->GetCoreClrDirectory());
strcpy_s(lpFilename, _countof(lpFilename), szSOSModulePath);
strcat_s(lpFilename, _countof(lpFilename), "sosdocsunix.txt");
HANDLE hSosDocFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hSosDocFile == INVALID_HANDLE_VALUE) {
ExtOut("Error finding documentation file\n");
ExtErr("Error finding documentation file\n");
return;
}
HANDLE hMappedSosDocFile = CreateFileMappingA(hSosDocFile, NULL, PAGE_READONLY, 0, 0, NULL);
CloseHandle(hSosDocFile);
if (hMappedSosDocFile == NULL) {
ExtOut("Error mapping documentation file\n");
ExtErr("Error mapping documentation file\n");
return;
}
@ -14559,7 +14593,7 @@ void PrintHelp (__in_z LPCSTR pszCmdName)
CloseHandle(hMappedSosDocFile);
if (pText == NULL)
{
ExtOut("Error loading documentation file\n");
ExtErr("Error loading documentation file\n");
return;
}
#endif
@ -14573,7 +14607,7 @@ void PrintHelp (__in_z LPCSTR pszCmdName)
LPSTR pEnd = NULL;
if (!pStart)
{
ExtOut("Documentation for %s not found.\n", pszCmdName);
ExtErr("Documentation for %s not found.\n", pszCmdName);
return;
}
@ -14581,7 +14615,7 @@ void PrintHelp (__in_z LPCSTR pszCmdName)
pStart = strchr(pStart, '\n');
if (!pStart)
{
ExtOut("Expected newline in documentation resource.\n");
ExtErr("Expected newline in documentation resource.\n");
return;
}
@ -14619,11 +14653,7 @@ void PrintHelp (__in_z LPCSTR pszCmdName)
\**********************************************************************/
DECLARE_API(Help)
{
// Call extension initialization functions directly, because we don't need the DAC dll to be initialized to get help.
HRESULT Status;
__ExtensionCleanUp __extensionCleanUp;
if ((Status = ExtQuery(client)) != S_OK) return Status;
ControlC = FALSE;
INIT_API_EXT();
StringHolder commandName;
CMDValue arg[] =
@ -14665,86 +14695,3 @@ DECLARE_API(Help)
return S_OK;
}
#if defined(FEATURE_PAL) && defined(_TARGET_AMD64_)
static BOOL
ReadMemoryAdapter(PVOID address, PVOID buffer, SIZE_T size)
{
ULONG fetched;
HRESULT hr = g_ExtData->ReadVirtual(TO_CDADDR(address), buffer, size, &fetched);
return SUCCEEDED(hr);
}
static BOOL
GetStackFrame(CONTEXT* context, ULONG numNativeFrames)
{
KNONVOLATILE_CONTEXT_POINTERS contextPointers;
memset(&contextPointers, 0, sizeof(contextPointers));
ULONG64 baseAddress;
HRESULT hr = g_ExtSymbols->GetModuleByOffset(context->Rip, 0, NULL, &baseAddress);
if (FAILED(hr))
{
PDEBUG_STACK_FRAME frame = &g_Frames[0];
for (int i = 0; i < numNativeFrames; i++, frame++) {
if (frame->InstructionOffset == context->Rip)
{
if ((i + 1) >= numNativeFrames) {
return FALSE;
}
memcpy(context, &(g_FrameContexts[i + 1]), sizeof(*context));
return TRUE;
}
}
return FALSE;
}
if (!PAL_VirtualUnwindOutOfProc(context, &contextPointers, baseAddress, ReadMemoryAdapter))
{
return FALSE;
}
return TRUE;
}
static BOOL
UnwindStackFrames(ULONG32 osThreadId)
{
ULONG numNativeFrames = 0;
HRESULT hr = GetContextStackTrace(osThreadId, &numNativeFrames);
if (FAILED(hr))
{
return FALSE;
}
CONTEXT context;
memset(&context, 0, sizeof(context));
context.ContextFlags = CONTEXT_FULL;
hr = g_ExtSystem->GetThreadContextById(osThreadId, CONTEXT_FULL, sizeof(context), (PBYTE)&context);
if (FAILED(hr))
{
return FALSE;
}
TableOutput out(3, POINTERSIZE_HEX, AlignRight);
out.WriteRow("RSP", "RIP", "Call Site");
DEBUG_STACK_FRAME nativeFrame;
memset(&nativeFrame, 0, sizeof(nativeFrame));
do
{
if (context.Rip == 0)
{
break;
}
nativeFrame.InstructionOffset = context.Rip;
nativeFrame.ReturnOffset = context.Rip;
nativeFrame.FrameOffset = context.Rbp;
nativeFrame.StackOffset = context.Rsp;
ClrStackImpl::PrintNativeStackFrame(out, &nativeFrame, FALSE);
} while (GetStackFrame(&context, numNativeFrames));
return TRUE;
}
#endif // FEATURE_PAL && _TARGET_AMD64_

Просмотреть файл

Просмотреть файл

@ -44,13 +44,18 @@ char symBuffer[SYM_BUFFER_SIZE];
PIMAGEHLP_SYMBOL sym = (PIMAGEHLP_SYMBOL) symBuffer;
#else
#include <sys/stat.h>
#include <coreruncommon.h>
#include <dlfcn.h>
#endif // !FEATURE_PAL
#include <coreclrhost.h>
#include <set>
#include <string>
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif
LPCSTR g_hostRuntimeDirectory = nullptr;
LoadSymbolsForModuleDelegate SymbolReader::loadSymbolsForModuleDelegate;
DisposeDelegate SymbolReader::disposeDelegate;
ResolveSequencePointDelegate SymbolReader::resolveSequencePointDelegate;
@ -668,7 +673,7 @@ HRESULT CreateInstanceCustom(
* windbg. *
* *
\**********************************************************************/
DWORD_PTR GetValueFromExpression (___in __in_z const char *const instr)
DWORD_PTR GetValueFromExpression(___in __in_z const char *const instr)
{
ULONG64 dwAddr;
const char *str = instr;
@ -724,7 +729,7 @@ DWORD_PTR GetValueFromExpression (___in __in_z const char *const instr)
#endif // FEATURE_PAL
ModuleInfo moduleInfo[MSCOREND] = {{0,FALSE,0},{0,FALSE,0},{0,FALSE,0}};
ModuleInfo g_moduleInfo[MSCOREND] = {{0, FALSE, 0}, {0, FALSE, 0}, {0, FALSE, 0}};
void ReportOOM()
{
@ -734,75 +739,41 @@ void ReportOOM()
HRESULT CheckEEDll()
{
#ifndef FEATURE_PAL
VS_FIXEDFILEINFO ee = {};
static VS_FIXEDFILEINFO sos = {};
static BOOL sosDataInit = FALSE;
BOOL result = GetEEVersion(&ee);
if (result && !sosDataInit)
// Do we have coreclr.dll
if (g_moduleInfo[MSCORWKS].baseAddr == 0)
{
result = GetSOSVersion(&sos);
DEBUG_MODULE_PARAMETERS Params;
if (result)
sosDataInit = TRUE;
}
// We will ignore errors because it's possible sos is being loaded before CLR.
if (result)
{
if ((ee.dwFileVersionMS != sos.dwFileVersionMS) || (ee.dwFileVersionLS != sos.dwFileVersionLS))
g_ExtSymbols->GetModuleByModuleName(MAIN_CLR_MODULE_NAME_A, 0, NULL, &g_moduleInfo[MSCORWKS].baseAddr);
if (g_moduleInfo[MSCORWKS].baseAddr != 0 && g_moduleInfo[MSCORWKS].hasPdb == FALSE)
{
ExtOut("The version of SOS does not match the version of CLR you are debugging. Please\n");
ExtOut("load the matching version of SOS for the version of CLR you are debugging.\n");
ExtOut("CLR Version: %u.%u.%u.%u\n",
HIWORD(ee.dwFileVersionMS),
LOWORD(ee.dwFileVersionMS),
HIWORD(ee.dwFileVersionLS),
LOWORD(ee.dwFileVersionLS));
ExtOut("SOS Version: %u.%u.%u.%u\n",
HIWORD(sos.dwFileVersionMS),
LOWORD(sos.dwFileVersionMS),
HIWORD(sos.dwFileVersionLS),
LOWORD(sos.dwFileVersionLS));
}
}
DEBUG_MODULE_PARAMETERS Params;
// Do we have clr.dll
if (moduleInfo[MSCORWKS].baseAddr == 0)
{
g_ExtSymbols->GetModuleByModuleName (MAIN_CLR_MODULE_NAME_A,0,NULL,
&moduleInfo[MSCORWKS].baseAddr);
if (moduleInfo[MSCORWKS].baseAddr != 0 && moduleInfo[MSCORWKS].hasPdb == FALSE)
{
g_ExtSymbols->GetModuleParameters (1, &moduleInfo[MSCORWKS].baseAddr, 0, &Params);
g_ExtSymbols->GetModuleParameters(1, &g_moduleInfo[MSCORWKS].baseAddr, 0, &Params);
if (Params.SymbolType == SymDeferred)
{
g_ExtSymbols->Reload("/f " MAIN_CLR_DLL_NAME_A);
g_ExtSymbols->GetModuleParameters (1, &moduleInfo[MSCORWKS].baseAddr, 0, &Params);
g_ExtSymbols->GetModuleParameters(1, &g_moduleInfo[MSCORWKS].baseAddr, 0, &Params);
}
if (Params.SymbolType == SymPdb || Params.SymbolType == SymDia)
{
moduleInfo[MSCORWKS].hasPdb = TRUE;
g_moduleInfo[MSCORWKS].hasPdb = TRUE;
}
moduleInfo[MSCORWKS].size = Params.Size;
g_moduleInfo[MSCORWKS].size = Params.Size;
}
if (g_moduleInfo[MSCORWKS].baseAddr != 0 && g_moduleInfo[MSCORWKS].hasPdb == FALSE)
{
ExtOut("PDB symbol for coreclr.dll not loaded\n");
}
if (moduleInfo[MSCORWKS].baseAddr != 0 && moduleInfo[MSCORWKS].hasPdb == FALSE)
ExtOut("PDB symbol for clr.dll not loaded\n");
}
return (moduleInfo[MSCORWKS].baseAddr != 0) ? S_OK : E_FAIL;
return (g_moduleInfo[MSCORWKS].baseAddr != 0) ? S_OK : E_FAIL;
#else
return S_OK;
#endif // FEATURE_PAL
}
EEFLAVOR GetEEFlavor ()
EEFLAVOR GetEEFlavor()
{
#ifdef FEATURE_PAL
return MSCORWKS;
@ -816,7 +787,7 @@ EEFLAVOR GetEEFlavor ()
#endif // FEATURE_PAL else
}
BOOL IsDumpFile ()
BOOL IsDumpFile()
{
static int g_fDumpFile = -1;
if (g_fDumpFile == -1) {
@ -2749,7 +2720,7 @@ DWORD_PTR *ModuleFromName(__in_opt LPSTR mName, int *numModule)
// >sxe ld:clr
// >g
// ...
// ModLoad: clr.dll
// ModLoad: coreclr.dll
// >!bpmd Foo.dll Foo.Bar
// we will correctly give the answer that whatever module you were looking for, it isn't loaded yet
@ -3661,13 +3632,14 @@ BOOL GetEEVersion(VS_FIXEDFILEINFO *pFileInfo)
{
_ASSERTE(g_ExtSymbols2);
_ASSERTE(pFileInfo);
// Grab the version info directly from the module.
return g_ExtSymbols2->GetModuleVersionInformation(DEBUG_ANY_ID,
moduleInfo[GetEEFlavor()].baseAddr,
"\\", pFileInfo, sizeof(VS_FIXEDFILEINFO), NULL) == S_OK;
return g_ExtSymbols2->GetModuleVersionInformation(
DEBUG_ANY_ID, g_moduleInfo[GetEEFlavor()].baseAddr, "\\", pFileInfo, sizeof(VS_FIXEDFILEINFO), NULL) == S_OK;
}
extern HMODULE g_hInstance;
BOOL GetSOSVersion(VS_FIXEDFILEINFO *pFileInfo)
{
_ASSERTE(pFileInfo);
@ -4226,9 +4198,14 @@ HRESULT LoadClrDebugDll(void)
{
return CORDBG_E_UNSUPPORTED;
}
char dacModulePath[MAX_LONGPATH];
strcpy_s(dacModulePath, _countof(dacModulePath), g_ExtServices->GetCoreClrDirectory());
strcat_s(dacModulePath, _countof(dacModulePath), MAKEDLLNAME_A("mscordaccore"));
LPCSTR coreclrDirectory = g_ExtServices->GetCoreClrDirectory();
if (coreclrDirectory == NULL)
{
return E_FAIL;
}
ArrayHolder<char> dacModulePath = new char[MAX_LONGPATH + 1];
strcpy_s(dacModulePath, MAX_LONGPATH, coreclrDirectory);
strcat_s(dacModulePath, MAX_LONGPATH, MAKEDLLNAME_A("mscordaccore"));
HMODULE hdac = LoadLibraryA(dacModulePath);
if (hdac == NULL)
@ -4303,20 +4280,20 @@ FindFileInPathCallback(
___in PVOID context
)
{
HRESULT hr;
FindFileCallbackData* pCallbackData;
pCallbackData = (FindFileCallbackData*)context;
if (!pCallbackData)
FindFileCallbackData* pCallbackData = (FindFileCallbackData*)context;
if (pCallbackData == NULL)
{
return TRUE;
}
pCallbackData->hModule = LoadLibraryExW(
filename,
NULL, // __reserved
LOAD_WITH_ALTERED_SEARCH_PATH); // Ensure we check the dir in wszFullPath first
if (pCallbackData->hModule == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
ExtOut("Unable to load '%S'. HRESULT = 0x%x.\n", filename, hr);
ExtOut("Unable to load '%S'. hr = 0x%x.\n", filename, HRESULT_FROM_WIN32(GetLastError()));
return TRUE;
}
@ -4328,8 +4305,9 @@ FindFileInPathCallback(
&modInfo,
sizeof(modInfo)))
{
ExtOut("Failed to read module information for '%S'. HRESULT = 0x%x.\n", filename, HRESULT_FROM_WIN32(GetLastError()));
ExtOut("Failed to read module information for '%S'. hr = 0x%x.\n", filename, HRESULT_FROM_WIN32(GetLastError()));
FreeLibrary(pCallbackData->hModule);
pCallbackData->hModule = NULL;
return TRUE;
}
@ -4343,6 +4321,7 @@ FindFileInPathCallback(
ExtOut("Size: Expected '0x%x', Actual '0x%x'\n", pCallbackData->filesize, dwSizeActual);
ExtOut("Time stamp: Expected '0x%x', Actual '0x%x'\n", pCallbackData->timestamp, dwTimeStampActual);
FreeLibrary(pCallbackData->hModule);
pCallbackData->hModule = NULL;
return TRUE;
}
@ -4355,7 +4334,7 @@ FindFileInPathCallback(
//---------------------------------------------------------------------------------------
// Provides a way for the public CLR debugging interface to find the appropriate
// mscordbi.dll, DAC, etc.
class SOSLibraryProvider : public ICLRDebuggingLibraryProvider
class SOSLibraryProvider : public ICLRDebuggingLibraryProvider, ICLRDebuggingLibraryProvider2
{
public:
SOSLibraryProvider() : m_ref(0)
@ -4370,12 +4349,18 @@ public:
{
if (InterfaceId == IID_IUnknown)
{
*pInterface = static_cast<IUnknown *>(this);
*pInterface = static_cast<IUnknown *>(static_cast<ICLRDebuggingLibraryProvider*>(this));
}
#ifndef FEATURE_PAL
else if (InterfaceId == IID_ICLRDebuggingLibraryProvider)
{
*pInterface = static_cast<ICLRDebuggingLibraryProvider *>(this);
}
#endif
else if (InterfaceId == IID_ICLRDebuggingLibraryProvider2)
{
*pInterface = static_cast<ICLRDebuggingLibraryProvider2 *>(this);
}
else
{
*pInterface = NULL;
@ -4401,9 +4386,143 @@ public:
return ref;
}
struct CoTaskStringHolder
{
private:
WCHAR* m_string;
public:
const int Length = MAX_LONGPATH;
CoTaskStringHolder() : m_string((WCHAR*)CoTaskMemAlloc(MAX_LONGPATH + 1)) { }
~CoTaskStringHolder() { if (m_string != NULL) CoTaskMemFree(m_string); }
operator WCHAR* () { return m_string; }
// Called by the shim to locate and load mscordacwks and mscordbi
WCHAR* Detach()
{
WCHAR* ret = m_string;
m_string = NULL;
return ret;
}
};
HRESULT ProvideLibraryInternal(
const WCHAR* pwszFileName,
DWORD dwTimestamp,
DWORD dwSizeOfImage,
HMODULE* phModule,
LPWSTR* ppResolvedModulePath)
{
#ifndef FEATURE_PAL
HRESULT hr = S_OK;
FindFileCallbackData callbackData;
callbackData.hModule = NULL;
callbackData.timestamp = dwTimestamp;
callbackData.filesize = dwSizeOfImage;
// if we are looking for the DAC, just load the one windbg already found
if (_wcsncmp(pwszFileName, W("mscordac"), _wcslen(W("mscordac"))) == 0)
{
HMODULE dacModule;
if (g_sos == NULL)
{
// we ensure that windbg loads DAC first so that we can be sure to use the same one
return E_UNEXPECTED;
}
if (FAILED(hr = g_sos->GetDacModuleHandle(&dacModule)))
{
ExtErr("Failed to get the dac module handle. hr=0x%x.\n", hr);
return hr;
}
CoTaskStringHolder dacPath;
DWORD len = GetModuleFileNameW(dacModule, dacPath, dacPath.Length);
if (len == 0 || len == MAX_LONGPATH)
{
hr = HRESULT_FROM_WIN32(GetLastError());
ExtErr("GetModuleFileName(dacModuleHandle) failed. hr=0x%x.\n", hr);
return hr;
}
FindFileInPathCallback(dacPath, &callbackData);
if (ppResolvedModulePath != NULL)
{
*ppResolvedModulePath = dacPath.Detach();
}
}
else {
ULONG64 hProcess;
hr = g_ExtSystem->GetCurrentProcessHandle(&hProcess);
if (FAILED(hr))
{
ExtErr("IDebugSystemObjects::GetCurrentProcessHandle hr=0x%x.\n", hr);
return hr;
}
ToRelease<IDebugSymbols3> spSym3(NULL);
hr = g_ExtSymbols->QueryInterface(__uuidof(IDebugSymbols3), (void**)&spSym3);
if (FAILED(hr))
{
ExtErr("Unable to query IDebugSymbol3 hr=0x%x.\n", hr);
return hr;
}
ArrayHolder<WCHAR> symbolPath = new WCHAR[MAX_LONGPATH + 1];
hr = spSym3->GetSymbolPathWide(symbolPath, MAX_LONGPATH, NULL);
if (FAILED(hr))
{
ExtErr("Unable to get symbol path. IDebugSymbols3::GetSymbolPathWide hr=0x%x.\n", hr);
return hr;
}
CoTaskStringHolder foundPath;
if (!SymFindFileInPathW(
(HANDLE)hProcess,
symbolPath,
pwszFileName,
(PVOID)(ULONG_PTR)dwTimestamp,
dwSizeOfImage,
0,
SSRVOPT_DWORD,
foundPath,
(PFINDFILEINPATHCALLBACKW)&FindFileInPathCallback,
(PVOID)&callbackData))
{
hr = HRESULT_FROM_WIN32(GetLastError());
ExtErr("SymFindFileInPath failed for %S. hr=0x%x.\nPlease ensure that %S is on your symbol path.", pwszFileName, hr, pwszFileName);
return hr;
}
if (ppResolvedModulePath != NULL)
{
*ppResolvedModulePath = foundPath.Detach();
}
}
if (phModule != NULL)
{
*phModule = callbackData.hModule;
}
return S_OK;
#else
_ASSERTE(phModule == NULL);
LPCSTR coreclrDirectory = g_ExtServices->GetCoreClrDirectory();
if (coreclrDirectory == NULL)
{
ExtErr("Runtime module (%s) not loaded yet", MAKEDLLNAME_A("coreclr"));
return E_FAIL;
}
ArrayHolder<WCHAR> modulePath = new WCHAR[MAX_LONGPATH + 1];
int length = MultiByteToWideChar(CP_ACP, 0, coreclrDirectory, -1, modulePath, MAX_LONGPATH);
if (0 >= length)
{
ExtErr("MultiByteToWideChar(coreclrDirectory) failed. Last error = 0x%x\n", GetLastError());
return E_FAIL;
}
wcscat_s(modulePath, MAX_LONGPATH, pwszFileName);
if (ppResolvedModulePath != NULL)
{
*ppResolvedModulePath = modulePath.Detach();
}
return S_OK;
#endif // FEATURE_PAL
}
// Called by the shim to locate and load mscordaccore and mscordbi
// Parameters:
// pwszFileName - the name of the file to load
// dwTimestamp - the expected timestamp of the file
@ -4416,121 +4535,26 @@ public:
const WCHAR * pwszFileName,
DWORD dwTimestamp,
DWORD dwSizeOfImage,
HMODULE * phModule)
HMODULE* phModule)
{
#ifndef FEATURE_PAL
HRESULT hr;
FindFileCallbackData callbackData = {0};
callbackData.timestamp = dwTimestamp;
callbackData.filesize = dwSizeOfImage;
if ((phModule == NULL) || (pwszFileName == NULL))
{
return E_INVALIDARG;
}
return ProvideLibraryInternal(pwszFileName, dwTimestamp, dwSizeOfImage, phModule, NULL);
}
HMODULE dacModule;
if(g_sos == NULL)
virtual HRESULT STDMETHODCALLTYPE ProvideLibrary2(
const WCHAR* pwszFileName,
DWORD dwTimestamp,
DWORD dwSizeOfImage,
LPWSTR* ppResolvedModulePath)
{
if ((pwszFileName == NULL) || (ppResolvedModulePath == NULL))
{
// we ensure that windbg loads DAC first so that we can be sure to use the same one
return E_UNEXPECTED;
return E_INVALIDARG;
}
if (FAILED(hr = g_sos->GetDacModuleHandle(&dacModule)))
{
ExtOut("Failed to get the dac module handle. hr=0x%x.\n", hr);
return hr;
}
WCHAR dacPath[MAX_LONGPATH];
DWORD len = GetModuleFileNameW(dacModule, dacPath, MAX_LONGPATH);
if(len == 0 || len == MAX_LONGPATH)
{
ExtOut("GetModuleFileName(dacModuleHandle) failed. Last error = 0x%x\n", GetLastError());
return E_FAIL;
}
// if we are looking for the DAC, just load the one windbg already found
if(_wcsncmp(pwszFileName, W("mscordac"), _wcslen(W("mscordac")))==0)
{
FindFileInPathCallback(dacPath, &callbackData);
*phModule = callbackData.hModule;
return hr;
}
ULONG64 hProcess;
hr = g_ExtSystem->GetCurrentProcessHandle(&hProcess);
if (FAILED(hr))
{
ExtOut("IDebugSystemObjects::GetCurrentProcessHandle HRESULT=0x%x.\n", hr);
return hr;
}
ToRelease<IDebugSymbols3> spSym3(NULL);
hr = g_ExtSymbols->QueryInterface(__uuidof(IDebugSymbols3), (void**)&spSym3);
if (FAILED(hr))
{
ExtOut("Unable to query IDebugSymbol3 HRESULT=0x%x.\n", hr);
return hr;
}
ULONG pathSize = 0;
hr = spSym3->GetSymbolPathWide(NULL, 0, &pathSize);
if(FAILED(hr)) //S_FALSE if the path doesn't fit, but if the path was size 0 perhaps we would get S_OK?
{
ExtOut("Unable to get symbol path length. IDebugSymbols3::GetSymbolPathWide HRESULT=0x%x.\n", hr);
return hr;
}
ArrayHolder<WCHAR> symbolPath = new WCHAR[pathSize+MAX_LONGPATH+1];
hr = spSym3->GetSymbolPathWide(symbolPath, pathSize, NULL);
if(S_OK != hr)
{
ExtOut("Unable to get symbol path. IDebugSymbols3::GetSymbolPathWide HRESULT=0x%x.\n", hr);
return hr;
}
WCHAR foundPath[MAX_LONGPATH];
BOOL rc = SymFindFileInPathW((HANDLE)hProcess,
symbolPath,
pwszFileName,
(PVOID)(ULONG_PTR) dwTimestamp,
dwSizeOfImage,
0,
SSRVOPT_DWORD,
foundPath,
(PFINDFILEINPATHCALLBACKW) &FindFileInPathCallback,
(PVOID) &callbackData
);
if(!rc)
{
hr = HRESULT_FROM_WIN32(GetLastError());
ExtOut("SymFindFileInPath failed for %S. HRESULT=0x%x.\nPlease ensure that %S is on your symbol path.", pwszFileName, hr, pwszFileName);
}
*phModule = callbackData.hModule;
return hr;
#else
WCHAR modulePath[MAX_LONGPATH];
int length = MultiByteToWideChar(CP_ACP, 0, g_ExtServices->GetCoreClrDirectory(), -1, modulePath, _countof(modulePath));
if (0 >= length)
{
ExtOut("MultiByteToWideChar(coreclrDirectory) failed. Last error = 0x%x\n", GetLastError());
return E_FAIL;
}
wcscat_s(modulePath, _countof(modulePath), pwszFileName);
*phModule = LoadLibraryW(modulePath);
if (*phModule == NULL)
{
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
ExtOut("Unable to load '%S'. HRESULT = 0x%x.\n", pwszFileName, hr);
return hr;
}
return S_OK;
#endif // FEATURE_PAL
return ProvideLibraryInternal(pwszFileName, dwTimestamp, dwSizeOfImage, NULL, ppResolvedModulePath);
}
protected:
@ -6224,25 +6248,29 @@ HRESULT SymbolReader::LoadSymbolsForPortablePDB(__in_z WCHAR* pModuleName, ___in
return Status;
}
#ifndef FEATURE_PAL
#ifdef FEATURE_PAL
#define TPALIST_SEPARATOR_STR_A ":"
#else
#define TPALIST_SEPARATOR_STR_A ";"
#endif
void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList)
{
const char * const tpaExtensions[] = {
"*.ni.dll", // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir
"*.dll",
"*.ni.exe",
"*.exe",
};
std::set<std::string> addedAssemblies;
// Don't add this file to the list because we don't want to the one from the hosting runtime
addedAssemblies.insert(SymbolReaderDllName);
// Walk the directory for each extension separately so that we first get files with .ni.dll extension,
// then files with .dll extension, etc.
for (int extIndex = 0; extIndex < sizeof(tpaExtensions) / sizeof(tpaExtensions[0]); extIndex++)
{
const char* ext = tpaExtensions[extIndex];
size_t extLength = strlen(ext);
size_t extLength = strlen(ext) - 1; // don't count the "*"
std::string assemblyPath(directory);
assemblyPath.append(DIRECTORY_SEPARATOR_STR_A);
@ -6271,7 +6299,7 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList)
tpaList.append(directory);
tpaList.append(DIRECTORY_SEPARATOR_STR_A);
tpaList.append(filename);
tpaList.append(";");
tpaList.append(TPALIST_SEPARATOR_STR_A);
}
}
}
@ -6282,6 +6310,101 @@ void AddFilesFromDirectoryToTpaList(const char* directory, std::string& tpaList)
}
}
#ifdef FEATURE_PAL
#if defined(__linux__)
#define symlinkEntrypointExecutable "/proc/self/exe"
#elif !defined(__APPLE__)
#define symlinkEntrypointExecutable "/proc/curproc/exe"
#endif
bool GetAbsolutePath(const char* path, std::string& absolutePath)
{
bool result = false;
char realPath[PATH_MAX];
if (realpath(path, realPath) != nullptr && realPath[0] != '\0')
{
absolutePath.assign(realPath);
// realpath should return canonicalized path without the trailing slash
assert(absolutePath.back() != '/');
result = true;
}
return result;
}
bool GetEntrypointExecutableAbsolutePath(std::string& entrypointExecutable)
{
bool result = false;
entrypointExecutable.clear();
// Get path to the executable for the current process using
// platform specific means.
#if defined(__APPLE__)
// On Mac, we ask the OS for the absolute path to the entrypoint executable
uint32_t lenActualPath = 0;
if (_NSGetExecutablePath(nullptr, &lenActualPath) == -1)
{
// OSX has placed the actual path length in lenActualPath,
// so re-attempt the operation
std::string resizedPath(lenActualPath, '\0');
char *pResizedPath = const_cast<char *>(resizedPath.c_str());
if (_NSGetExecutablePath(pResizedPath, &lenActualPath) == 0)
{
entrypointExecutable.assign(pResizedPath);
result = true;
}
}
#elif defined (__FreeBSD__)
static const int name[] = {
CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1
};
char path[PATH_MAX];
size_t len;
len = sizeof(path);
if (sysctl(name, 4, path, &len, nullptr, 0) == 0)
{
entrypointExecutable.assign(path);
result = true;
}
else
{
// ENOMEM
result = false;
}
#elif defined(__NetBSD__) && defined(KERN_PROC_PATHNAME)
static const int name[] = {
CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME,
};
char path[MAXPATHLEN];
size_t len;
len = sizeof(path);
if (sysctl(name, __arraycount(name), path, &len, NULL, 0) != -1)
{
entrypointExecutable.assign(path);
result = true;
}
else
{
result = false;
}
#else
// On other OSs, return the symlink that will be resolved by GetAbsolutePath
// to fetch the entrypoint EXE absolute path, inclusive of filename.
result = GetAbsolutePath(symlinkEntrypointExecutable, entrypointExecutable);
#endif
return result;
}
#else // FEATURE_PAL
bool GetEntrypointExecutableAbsolutePath(std::string& entrypointExecutable)
{
ArrayHolder<char> hostPath = new char[MAX_LONGPATH+1];
@ -6298,6 +6421,58 @@ bool GetEntrypointExecutableAbsolutePath(std::string& entrypointExecutable)
#endif // FEATURE_PAL
HRESULT GetHostRuntime(std::string& coreClrPath, std::string& hostRuntimeDirectory)
{
// If the hosting runtime isn't already set, use the runtime we are debugging
if (g_hostRuntimeDirectory == nullptr)
{
#ifdef FEATURE_PAL
LPCSTR coreClrDirectory = g_ExtServices->GetCoreClrDirectory();
if (coreClrDirectory == NULL)
{
ExtErr("Error: Runtime module (%s) not loaded yet", MAKEDLLNAME_A("coreclr"));
return E_FAIL;
}
if (!GetAbsolutePath(coreClrDirectory, hostRuntimeDirectory))
{
ExtErr("Error: Failed to get coreclr absolute path\n");
return E_FAIL;
}
#else
ULONG index;
HRESULT Status = g_ExtSymbols->GetModuleByModuleName(MAIN_CLR_MODULE_NAME_A, 0, &index, NULL);
if (FAILED(Status))
{
ExtErr("Error: Can't find coreclr module\n");
return Status;
}
ArrayHolder<char> szModuleName = new char[MAX_LONGPATH + 1];
Status = g_ExtSymbols->GetModuleNames(index, 0, szModuleName, MAX_LONGPATH, NULL, NULL, 0, NULL, NULL, 0, NULL);
if (FAILED(Status))
{
ExtErr("Error: Failed to get coreclr module name\n");
return Status;
}
coreClrPath = szModuleName;
// Parse off the module name to get just the path
size_t lastSlash = coreClrPath.rfind(DIRECTORY_SEPARATOR_CHAR_A);
if (lastSlash == std::string::npos)
{
ExtErr("Error: Failed to parse coreclr module name\n");
return E_FAIL;
}
hostRuntimeDirectory.assign(coreClrPath, 0, lastSlash);
#endif
g_hostRuntimeDirectory = _strdup(hostRuntimeDirectory.c_str());
}
hostRuntimeDirectory.assign(g_hostRuntimeDirectory);
coreClrPath.assign(g_hostRuntimeDirectory);
coreClrPath.append(DIRECTORY_SEPARATOR_STR_A);
coreClrPath.append(MAIN_CLR_DLL_NAME_A);
return S_OK;
}
HRESULT SymbolReader::PrepareSymbolReader()
{
static bool attemptedSymbolReaderPreparation = false;
@ -6306,47 +6481,42 @@ HRESULT SymbolReader::PrepareSymbolReader()
// If we already tried to set up the symbol reader, we won't try again.
return E_FAIL;
}
attemptedSymbolReaderPreparation = true;
std::string absolutePath;
std::string hostRuntimeDirectory;
std::string sosModuleDirectory;
std::string coreClrPath;
HRESULT Status;
HRESULT Status = GetHostRuntime(coreClrPath, hostRuntimeDirectory);
if (FAILED(Status))
{
return Status;
}
#ifdef FEATURE_PAL
coreClrPath = g_ExtServices->GetCoreClrDirectory();
if (!GetAbsolutePath(coreClrPath.c_str(), absolutePath))
{
ExtErr("Error: Failed to get coreclr absolute path\n");
ArrayHolder<char> szSOSModulePath = new char[MAX_LONGPATH + 1];
UINT cch = MAX_LONGPATH;
if (!PAL_GetPALDirectoryA(szSOSModulePath, &cch)) {
ExtErr("Error: Failed to get SOS module directory\n");
return E_FAIL;
}
coreClrPath.append(DIRECTORY_SEPARATOR_STR_A);
coreClrPath.append(MAIN_CLR_DLL_NAME_A);
sosModuleDirectory = szSOSModulePath;
#else
ULONG index;
Status = g_ExtSymbols->GetModuleByModuleName(MAIN_CLR_MODULE_NAME_A, 0, &index, NULL);
if (FAILED(Status))
ArrayHolder<char> szSOSModulePath = new char[MAX_LONGPATH + 1];
if (GetModuleFileNameA(g_hInstance, szSOSModulePath, MAX_LONGPATH) == 0)
{
ExtErr("Error: Can't find coreclr module\n");
return Status;
}
ArrayHolder<char> szModuleName = new char[MAX_LONGPATH + 1];
Status = g_ExtSymbols->GetModuleNames(index, 0, szModuleName, MAX_LONGPATH, NULL, NULL, 0, NULL, NULL, 0, NULL);
if (FAILED(Status))
{
ExtErr("Error: Failed to get coreclr module name\n");
return Status;
}
coreClrPath = szModuleName;
// Parse off the module name to get just the path
size_t pos = coreClrPath.rfind(DIRECTORY_SEPARATOR_CHAR_A);
if (pos == std::string::npos)
{
ExtErr("Error: Failed to parse coreclr module name\n");
ExtErr("Error: Failed to get SOS module directory\n");
return E_FAIL;
}
absolutePath.assign(coreClrPath, 0, pos);
sosModuleDirectory = szSOSModulePath;
// Get just the sos module directory
size_t lastSlash = sosModuleDirectory.rfind(DIRECTORY_SEPARATOR_CHAR_A);
if (lastSlash == std::string::npos)
{
ExtErr("Error: Failed to parse sos module name\n");
return E_FAIL;
}
sosModuleDirectory.erase(lastSlash);
#endif // FEATURE_PAL
HMODULE coreclrLib = LoadLibraryA(coreClrPath.c_str());
@ -6366,7 +6536,19 @@ HRESULT SymbolReader::PrepareSymbolReader()
}
std::string tpaList;
AddFilesFromDirectoryToTpaList(absolutePath.c_str(), tpaList);
AddFilesFromDirectoryToTpaList(hostRuntimeDirectory.c_str(), tpaList);
// The SOS managed assembly from the sos directory is the one to trust
tpaList.append(sosModuleDirectory);
tpaList.append(DIRECTORY_SEPARATOR_STR_A);
tpaList.append(SymbolReaderDllName);
tpaList.append(".dll");
tpaList.append(TPALIST_SEPARATOR_STR_A);
std::string appPaths;
appPaths.append(sosModuleDirectory);
appPaths.append(TPALIST_SEPARATOR_STR_A);
appPaths.append(hostRuntimeDirectory);
const char *propertyKeys[] = {
"TRUSTED_PLATFORM_ASSEMBLIES", "APP_PATHS", "APP_NI_PATHS",
@ -6375,11 +6557,11 @@ HRESULT SymbolReader::PrepareSymbolReader()
const char *propertyValues[] = {// TRUSTED_PLATFORM_ASSEMBLIES
tpaList.c_str(),
// APP_PATHS
absolutePath.c_str(),
appPaths.c_str(),
// APP_NI_PATHS
absolutePath.c_str(),
hostRuntimeDirectory.c_str(),
// NATIVE_DLL_SEARCH_DIRECTORIES
absolutePath.c_str(),
hostRuntimeDirectory.c_str(),
// AppDomainCompatSwitch
"UseLatestBehaviorWhenTFMNotSpecified"};

Просмотреть файл

@ -1514,7 +1514,7 @@ struct ModuleInfo
ULONG64 size;
BOOL hasPdb;
};
extern ModuleInfo moduleInfo[];
extern ModuleInfo g_moduleInfo[];
BOOL InitializeHeapData();
BOOL IsServerBuild ();

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -2,7 +2,7 @@
<Project Sdk="RoslynTools.RepoToolset">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp1.0;netcoreapp2.0</TargetFrameworks>
<TargetFramework>netcoreapp2.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<NoWarn>;1591;1701</NoWarn>
</PropertyGroup>

Просмотреть файл

@ -0,0 +1,16 @@
if(WIN32)
#use static crt
add_definitions(-MT)
endif(WIN32)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(DBGUTIL_SOURCES
dbgutil.cpp
)
if(CLR_CMAKE_PLATFORM_UNIX)
add_compile_options(-fPIC)
endif(CLR_CMAKE_PLATFORM_UNIX)
add_library_clr(dbgutil STATIC ${DBGUTIL_SOURCES})

426
src/SOS/dbgutil/dbgutil.cpp Normal file
Просмотреть файл

@ -0,0 +1,426 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//*****************************************************************************
// dbgutil.cpp
//
//
//*****************************************************************************
//
// Various common helpers for PE resource reading used by multiple debug components.
//
#include <dbgutil.h>
#include "corerror.h"
#include <assert.h>
#include <stdio.h>
// Returns the RVA of the resource section for the module specified by the given data target and module base.
// Returns failure if the module doesn't have a resource section.
//
// Arguments
// pDataTarget - dataTarget for the process we are inspecting
// moduleBaseAddress - base address of a module we should inspect
// pwImageFileMachine - updated with the Machine from the IMAGE_FILE_HEADER
// pdwResourceSectionRVA - updated with the resultant RVA on success
HRESULT GetMachineAndResourceSectionRVA(ICorDebugDataTarget* pDataTarget,
ULONG64 moduleBaseAddress,
WORD* pwImageFileMachine,
DWORD* pdwResourceSectionRVA)
{
// Fun code ahead... below is a hand written PE decoder with some of the file offsets hardcoded.
// It supports no more than what we absolutely have to to get to the resources we need. Any of the
// magic numbers used below can be determined by using the public documentation on the web.
//
// Yes utilcode has a PE decoder, no it does not support reading its data through a datatarget
// It was easier to inspect the small portion that I needed than to shove an abstraction layer under
// our utilcode and then make sure everything still worked.
// SECURITY WARNING: all data provided by the data target should be considered untrusted.
// Do not allow malicious data to cause large reads, memory allocations, buffer overflow,
// or any other undesirable behavior.
HRESULT hr = S_OK;
// at offset 3c in the image is a 4 byte file pointer that indicates where the PE signature is
IMAGE_DOS_HEADER dosHeader;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress, (BYTE*)&dosHeader, sizeof(dosHeader));
// verify there is a 4 byte PE signature there
DWORD peSigFilePointer = 0;
if (SUCCEEDED(hr))
{
peSigFilePointer = dosHeader.e_lfanew;
DWORD peSig = 0;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peSigFilePointer, (BYTE*)&peSig, 4);
if (SUCCEEDED(hr) && peSig != IMAGE_NT_SIGNATURE)
{
hr = E_FAIL; // PE signature not present
}
}
// after the signature is a 20 byte image file header
// we need to parse this to figure out the target architecture
IMAGE_FILE_HEADER imageFileHeader;
if (SUCCEEDED(hr))
{
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peSigFilePointer + 4, (BYTE*)&imageFileHeader, IMAGE_SIZEOF_FILE_HEADER);
}
WORD optHeaderMagic = 0;
DWORD peOptImageHeaderFilePointer = 0;
if (SUCCEEDED(hr))
{
if(pwImageFileMachine != NULL)
{
*pwImageFileMachine = imageFileHeader.Machine;
}
// 4 bytes after the signature is the 20 byte image file header
// 24 bytes after the signature is the image-only header
// at the beginning of the image-only header is a 2 byte magic number indicating its format
peOptImageHeaderFilePointer = peSigFilePointer + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD);
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peOptImageHeaderFilePointer, (BYTE*)&optHeaderMagic, 2);
}
// Either 112 or 128 bytes after the beginning of the image-only header is an 8 byte resource table
// depending on whether the image is PE32 or PE32+
DWORD resourceSectionRVA = 0;
if (SUCCEEDED(hr))
{
if (optHeaderMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) // PE32
{
IMAGE_OPTIONAL_HEADER32 header32;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peOptImageHeaderFilePointer,
(BYTE*)&header32, sizeof(header32));
if (SUCCEEDED(hr))
{
resourceSectionRVA = header32.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
}
}
else if (optHeaderMagic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) //PE32+
{
IMAGE_OPTIONAL_HEADER64 header64;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + peOptImageHeaderFilePointer,
(BYTE*)&header64, sizeof(header64));
if (SUCCEEDED(hr))
{
resourceSectionRVA = header64.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
}
}
else
{
hr = E_FAIL; // Invalid PE
}
}
*pdwResourceSectionRVA = resourceSectionRVA;
return S_OK;
}
HRESULT GetResourceRvaFromResourceSectionRva(ICorDebugDataTarget* pDataTarget,
ULONG64 moduleBaseAddress,
DWORD resourceSectionRva,
DWORD type,
DWORD name,
DWORD language,
DWORD* pResourceRva,
DWORD* pResourceSize)
{
HRESULT hr = S_OK;
DWORD nameTableRva = 0;
DWORD langTableRva = 0;
DWORD resourceDataEntryRva = 0;
*pResourceRva = 0;
*pResourceSize = 0;
// The resource section begins with a resource directory that indexes all the resources by type.
// Each entry it points to is another resource directory that indexes all the same type
// resources by name. And each entry in that table points to another resource directory that indexes
// all the same type/name resources by language. Entries in the final table give the RVA of the actual
// resource.
// Note all RVAs in this section are relative to the beginning of the resource section,
// not the beginning of the image.
hr = GetNextLevelResourceEntryRVA(pDataTarget, type, moduleBaseAddress, resourceSectionRva, &nameTableRva);
if (SUCCEEDED(hr))
{
nameTableRva += resourceSectionRva;
hr = GetNextLevelResourceEntryRVA(pDataTarget, name, moduleBaseAddress, nameTableRva, &langTableRva);
}
if (SUCCEEDED(hr))
{
langTableRva += resourceSectionRva;
hr = GetNextLevelResourceEntryRVA(pDataTarget, language, moduleBaseAddress, langTableRva, &resourceDataEntryRva);
}
// The resource data entry has the first 4 bytes indicating the RVA of the resource
// The next 4 bytes indicate the size of the resource
if (SUCCEEDED(hr))
{
resourceDataEntryRva += resourceSectionRva;
IMAGE_RESOURCE_DATA_ENTRY dataEntry;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDataEntryRva,
(BYTE*)&dataEntry, sizeof(dataEntry));
*pResourceRva = dataEntry.OffsetToData;
*pResourceSize = dataEntry.Size;
}
return hr;
}
HRESULT GetResourceRvaFromResourceSectionRvaByName(ICorDebugDataTarget* pDataTarget,
ULONG64 moduleBaseAddress,
DWORD resourceSectionRva,
DWORD type,
LPCWSTR pwszName,
DWORD language,
DWORD* pResourceRva,
DWORD* pResourceSize)
{
HRESULT hr = S_OK;
DWORD nameTableRva = 0;
DWORD langTableRva = 0;
DWORD resourceDataEntryRva = 0;
*pResourceRva = 0;
*pResourceSize = 0;
// The resource section begins with a resource directory that indexes all the resources by type.
// Each entry it points to is another resource directory that indexes all the same type
// resources by name. And each entry in that table points to another resource directory that indexes
// all the same type/name resources by language. Entries in the final table give the RVA of the actual
// resource.
// Note all RVAs in this section are relative to the beginning of the resource section,
// not the beginning of the image.
hr = GetNextLevelResourceEntryRVA(pDataTarget, type, moduleBaseAddress, resourceSectionRva, &nameTableRva);
if (SUCCEEDED(hr))
{
nameTableRva += resourceSectionRva;
hr = GetNextLevelResourceEntryRVAByName(pDataTarget, pwszName, moduleBaseAddress, nameTableRva, resourceSectionRva, &langTableRva);
}
if (SUCCEEDED(hr))
{
langTableRva += resourceSectionRva;
hr = GetNextLevelResourceEntryRVA(pDataTarget, language, moduleBaseAddress, langTableRva, &resourceDataEntryRva);
}
// The resource data entry has the first 4 bytes indicating the RVA of the resource
// The next 4 bytes indicate the size of the resource
if (SUCCEEDED(hr))
{
resourceDataEntryRva += resourceSectionRva;
IMAGE_RESOURCE_DATA_ENTRY dataEntry;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDataEntryRva,
(BYTE*)&dataEntry, sizeof(dataEntry));
*pResourceRva = dataEntry.OffsetToData;
*pResourceSize = dataEntry.Size;
}
return hr;
}
// Traverses down one level in the PE resource tree structure
//
// Arguments:
// pDataTarget - the data target for inspecting this process
// id - the id of the next node in the resource tree you want
// moduleBaseAddress - the base address of the module being inspected
// resourceDirectoryRVA - the base address of the beginning of the resource directory for this
// level of the tree
// pNextLevelRVA - out - The RVA for the next level tree directory or the RVA of the resource entry
//
// Returns:
// S_OK if succesful or an appropriate failing HRESULT
HRESULT GetNextLevelResourceEntryRVA(ICorDebugDataTarget* pDataTarget,
DWORD id,
ULONG64 moduleBaseAddress,
DWORD resourceDirectoryRVA,
DWORD* pNextLevelRVA)
{
*pNextLevelRVA = 0;
HRESULT hr = S_OK;
// A resource directory which consists of
// a header followed by a number of entries. In the header at offset 12 is
// the number entries identified by name, followed by the number of entries
// identified by ID at offset 14. Both are 2 bytes.
// This method only supports locating entries by ID, not by name
IMAGE_RESOURCE_DIRECTORY resourceDirectory;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRVA, (BYTE*)&resourceDirectory, sizeof(resourceDirectory));
// The ith resource directory entry is at offset 16 + 8i from the beginning of the resource
// directory table
WORD numNameEntries;
WORD numIDEntries;
if (SUCCEEDED(hr))
{
numNameEntries = resourceDirectory.NumberOfNamedEntries;
numIDEntries = resourceDirectory.NumberOfIdEntries;
for (WORD i = numNameEntries; i < numNameEntries + numIDEntries; i++)
{
IMAGE_RESOURCE_DIRECTORY_ENTRY entry;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRVA + sizeof(resourceDirectory) + sizeof(entry)*i,
(BYTE*)&entry, sizeof(entry));
if (FAILED(hr))
{
break;
}
if (entry.Id == id)
{
*pNextLevelRVA = entry.OffsetToDirectory;
break;
}
}
}
// If we didn't find the entry
if (SUCCEEDED(hr) && *pNextLevelRVA == 0)
{
hr = E_FAIL;
}
return hr; // resource not found
}
// Traverses down one level in the PE resource tree structure
//
// Arguments:
// pDataTarget - the data target for inspecting this process
// name - the name of the next node in the resource tree you want
// moduleBaseAddress - the base address of the module being inspected
// resourceDirectoryRVA - the base address of the beginning of the resource directory for this
// level of the tree
// resourceSectionRVA - the rva of the beginning of the resource section of the PE file
// pNextLevelRVA - out - The RVA for the next level tree directory or the RVA of the resource entry
//
// Returns:
// S_OK if succesful or an appropriate failing HRESULT
HRESULT GetNextLevelResourceEntryRVAByName(ICorDebugDataTarget* pDataTarget,
LPCWSTR pwzName,
ULONG64 moduleBaseAddress,
DWORD resourceDirectoryRva,
DWORD resourceSectionRva,
DWORD* pNextLevelRva)
{
HRESULT hr = S_OK;
DWORD nameLength = (DWORD)wcslen(pwzName);
WCHAR entryName[50];
assert(nameLength < 50); // this implementation won't support matching a name longer
// than 50 characters. We only look up the hard coded name
// of the debug resource in clr.dll though, so it shouldn't be
// an issue. Increase this count if we ever want to look up
// larger names
if (nameLength >= 50)
{
hr = E_FAIL; // invalid name length
}
// A resource directory which consists of
// a header followed by a number of entries. In the header at offset 12 is
// the number entries identified by name, followed by the number of entries
// identified by ID at offset 14. Both are 2 bytes.
// This method only supports locating entries by ID, not by name
IMAGE_RESOURCE_DIRECTORY resourceDirectory = { 0 };
if (SUCCEEDED(hr))
{
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRva, (BYTE*)&resourceDirectory, sizeof(resourceDirectory));
}
// The ith resource directory entry is at offset 16 + 8i from the beginning of the resource
// directory table
if (SUCCEEDED(hr))
{
WORD numNameEntries = resourceDirectory.NumberOfNamedEntries;
for (WORD i = 0; i < numNameEntries; i++)
{
IMAGE_RESOURCE_DIRECTORY_ENTRY entry;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceDirectoryRva + sizeof(resourceDirectory) + sizeof(entry)*i,
(BYTE*)&entry, sizeof(entry));
if (FAILED(hr))
{
break;
}
// the NameRVAOrID field points to a UTF16 string with a 2 byte length in front of it
// read the 2 byte length first. The doc of course doesn't mention this, but the RVA is
// relative to the base of the resource section and needs the leading bit stripped.
WORD entryNameLength = 0;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceSectionRva +
entry.NameOffset, (BYTE*)&entryNameLength, sizeof(entryNameLength));
if (FAILED(hr))
{
break;
}
if (entryNameLength != nameLength)
{
continue; // names aren't the same length, not a match
}
// read the rest of the string data and check for a match
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + resourceSectionRva +
entry.NameOffset + 2, (BYTE*)entryName, entryNameLength*sizeof(WCHAR));
if (FAILED(hr))
{
break;
}
if (memcmp(entryName, pwzName, entryNameLength*sizeof(WCHAR)) == 0)
{
*pNextLevelRva = entry.OffsetToDirectory;
break;
}
}
}
if (SUCCEEDED(hr) && *pNextLevelRva == 0)
{
hr = E_FAIL; // resource not found
}
return hr;
}
// A small wrapper that reads from the data target and throws on error
HRESULT ReadFromDataTarget(ICorDebugDataTarget* pDataTarget,
ULONG64 addr,
BYTE* pBuffer,
ULONG32 bytesToRead)
{
//PRECONDITION(CheckPointer(pDataTarget));
//PRECONDITION(CheckPointer(pBuffer));
HRESULT hr = S_OK;
ULONG32 bytesReadTotal = 0;
ULONG32 bytesRead = 0;
do
{
if (FAILED(pDataTarget->ReadVirtual((CORDB_ADDRESS)(addr + bytesReadTotal),
pBuffer,
bytesToRead - bytesReadTotal,
&bytesRead)))
{
hr = CORDBG_E_READVIRTUAL_FAILURE;
break;
}
bytesReadTotal += bytesRead;
} while (bytesRead != 0 && (bytesReadTotal < bytesToRead));
// If we can't read all the expected memory, then fail
if (SUCCEEDED(hr) && (bytesReadTotal != bytesToRead))
{
hr = HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
}
return hr;
}

Просмотреть файл

@ -0,0 +1,15 @@
if(WIN32)
#use static crt
add_definitions(-MT)
add_definitions(-DHOST_IS_WINDOWS_OS)
endif(WIN32)
if(CLR_CMAKE_PLATFORM_UNIX)
add_compile_options(-fPIC)
endif(CLR_CMAKE_PLATFORM_UNIX)
set(DEBUGSHIM_SOURCES
debugshim.cpp
)
add_library_clr(debugshim STATIC ${DEBUGSHIM_SOURCES})

Просмотреть файл

@ -0,0 +1,768 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//*****************************************************************************
// debugshim.cpp
//
//
//*****************************************************************************
#include "debugshim.h"
#include "dbgutil.h"
#include <crtdbg.h>
#include <clrinternal.h> //has the CLR_ID_V4_DESKTOP guid in it
#include "palclr.h"
#ifndef IMAGE_FILE_MACHINE_ARMNT
#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
#endif
#ifndef IMAGE_FILE_MACHINE_ARM64
#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian
#endif
// making the defines very clear, these represent the host architecture - aka
// the arch on which this code is running
#if defined(_X86_)
#define _HOST_X86_
#elif defined(_AMD64_)
#define _HOST_AMD64_
#elif defined(_ARM_)
#define _HOST_ARM_
#elif defined(_ARM64_)
#define _HOST_ARM64_
#endif
//*****************************************************************************
// CLRDebuggingImpl implementation (ICLRDebugging)
//*****************************************************************************
typedef HRESULT (STDAPICALLTYPE *OpenVirtualProcessImpl2FnPtr)(ULONG64 clrInstanceId,
IUnknown * pDataTarget,
LPCWSTR pDacModulePath,
CLR_DEBUGGING_VERSION * pMaxDebuggerSupportedVersion,
REFIID riid,
IUnknown ** ppInstance,
CLR_DEBUGGING_PROCESS_FLAGS * pdwFlags);
typedef HRESULT (STDAPICALLTYPE *OpenVirtualProcessImplFnPtr)(ULONG64 clrInstanceId,
IUnknown * pDataTarget,
HMODULE hDacDll,
CLR_DEBUGGING_VERSION * pMaxDebuggerSupportedVersion,
REFIID riid,
IUnknown ** ppInstance,
CLR_DEBUGGING_PROCESS_FLAGS * pdwFlags);
typedef HRESULT (STDAPICALLTYPE *OpenVirtualProcess2FnPtr)(ULONG64 clrInstanceId,
IUnknown * pDataTarget,
HMODULE hDacDll,
REFIID riid,
IUnknown ** ppInstance,
CLR_DEBUGGING_PROCESS_FLAGS * pdwFlags);
typedef HMODULE (STDAPICALLTYPE *LoadLibraryWFnPtr)(LPCWSTR lpLibFileName);
// Implementation of ICLRDebugging::OpenVirtualProcess
//
// Arguments:
// moduleBaseAddress - the address of the module which might be a CLR
// pDataTarget - the data target for inspecting the process
// pLibraryProvider - a callback for locating DBI and DAC
// pMaxDebuggerSupportedVersion - the max version of the CLR that this debugger will support debugging
// riidProcess - the IID of the interface that should be passed back in ppProcess
// ppProcess - output for the ICorDebugProcess# if this module is a CLR
// pVersion - the CLR version if this module is a CLR
// pFlags - output, see the CLR_DEBUGGING_PROCESS_FLAGS for more details. Right now this has only one possible
// value which indicates this runtime had an unhandled exception
STDMETHODIMP CLRDebuggingImpl::OpenVirtualProcess(
ULONG64 moduleBaseAddress,
IUnknown * pDataTarget,
ICLRDebuggingLibraryProvider * pLibraryProvider,
CLR_DEBUGGING_VERSION * pMaxDebuggerSupportedVersion,
REFIID riidProcess,
IUnknown ** ppProcess,
CLR_DEBUGGING_VERSION * pVersion,
CLR_DEBUGGING_PROCESS_FLAGS * pFlags)
{
//PRECONDITION(CheckPointer(pDataTarget));
HRESULT hr = S_OK;
ICorDebugDataTarget * pDt = NULL;
HMODULE hDbi = NULL;
HMODULE hDac = NULL;
LPWSTR pDacModulePath = NULL;
LPWSTR pDbiModulePath = NULL;
DWORD dbiTimestamp;
DWORD dbiSizeOfImage;
WCHAR dbiName[MAX_PATH_FNAME] = { 0 };
DWORD dacTimestamp;
DWORD dacSizeOfImage;
WCHAR dacName[MAX_PATH_FNAME] = { 0 };
CLR_DEBUGGING_VERSION version;
BOOL versionSupportedByCaller = FALSE;
// argument checking
if ((ppProcess != NULL || pFlags != NULL) && pLibraryProvider == NULL)
{
hr = E_POINTER; // the library provider must be specified if either
// ppProcess or pFlags is non-NULL
}
else if ((ppProcess != NULL || pFlags != NULL) && pMaxDebuggerSupportedVersion == NULL)
{
hr = E_POINTER; // the max supported version must be specified if either
// ppProcess or pFlags is non-NULL
}
else if (pVersion != NULL && pVersion->wStructVersion != 0)
{
hr = CORDBG_E_UNSUPPORTED_VERSION_STRUCT;
}
else if (FAILED(pDataTarget->QueryInterface(__uuidof(ICorDebugDataTarget), (void**)&pDt)))
{
hr = CORDBG_E_MISSING_DATA_TARGET_INTERFACE;
}
if (SUCCEEDED(hr))
{
// get CLR version
// The expectation is that new versions of the CLR will continue to use the same GUID
// (unless there's a reason to hide them from older shims), but debuggers will tell us the
// CLR version they're designed for and mscordbi.dll can decide whether or not to accept it.
version.wStructVersion = 0;
hr = GetCLRInfo(pDt,
moduleBaseAddress,
&version,
&dbiTimestamp,
&dbiSizeOfImage,
dbiName,
MAX_PATH_FNAME,
&dacTimestamp,
&dacSizeOfImage,
dacName,
MAX_PATH_FNAME);
}
// If we need to fetch either the process info or the flags info then we need to find
// mscordbi and DAC and do the version specific OVP work
if (SUCCEEDED(hr) && (ppProcess != NULL || pFlags != NULL))
{
ICLRDebuggingLibraryProvider2* pLibraryProvider2;
if (SUCCEEDED(pLibraryProvider->QueryInterface(__uuidof(ICLRDebuggingLibraryProvider2), (void**)&pLibraryProvider2)))
{
if (FAILED(pLibraryProvider2->ProvideLibrary2(dbiName, dbiTimestamp, dbiSizeOfImage, &pDbiModulePath)) ||
pDbiModulePath == NULL)
{
hr = CORDBG_E_LIBRARY_PROVIDER_ERROR;
}
if (SUCCEEDED(hr))
{
hDbi = LoadLibraryW(pDbiModulePath);
if (hDbi == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
if (SUCCEEDED(hr))
{
// Adjust the timestamp and size of image if this DAC is a known buggy version and needs to be retargeted
RetargetDacIfNeeded(&dacTimestamp, &dacSizeOfImage);
// Ask library provider for dac
if (FAILED(pLibraryProvider2->ProvideLibrary2(dacName, dacTimestamp, dacSizeOfImage, &pDacModulePath)) ||
pDacModulePath == NULL)
{
hr = CORDBG_E_LIBRARY_PROVIDER_ERROR;
}
if (SUCCEEDED(hr))
{
hDac = LoadLibraryW(pDacModulePath);
if (hDac == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
}
pLibraryProvider2->Release();
}
else {
// Ask library provider for dbi
if (FAILED(pLibraryProvider->ProvideLibrary(dbiName, dbiTimestamp, dbiSizeOfImage, &hDbi)) ||
hDbi == NULL)
{
hr = CORDBG_E_LIBRARY_PROVIDER_ERROR;
}
if (SUCCEEDED(hr))
{
// Adjust the timestamp and size of image if this DAC is a known buggy version and needs to be retargeted
RetargetDacIfNeeded(&dacTimestamp, &dacSizeOfImage);
// ask library provider for dac
if (FAILED(pLibraryProvider->ProvideLibrary(dacName, dacTimestamp, dacSizeOfImage, &hDac)) ||
hDac == NULL)
{
hr = CORDBG_E_LIBRARY_PROVIDER_ERROR;
}
}
}
*ppProcess = NULL;
if (SUCCEEDED(hr) && pDacModulePath != NULL)
{
// Get access to the latest OVP implementation and call it
OpenVirtualProcessImpl2FnPtr ovpFn = (OpenVirtualProcessImpl2FnPtr)GetProcAddress(hDbi, "OpenVirtualProcessImpl2");
if (ovpFn != NULL)
{
hr = ovpFn(moduleBaseAddress, pDataTarget, pDacModulePath, pMaxDebuggerSupportedVersion, riidProcess, ppProcess, pFlags);
if (FAILED(hr))
{
_ASSERTE(ppProcess == NULL || *ppProcess == NULL);
_ASSERTE(pFlags == NULL || *pFlags == 0);
}
}
#ifdef FEATURE_PAL
else
{
// On Linux/MacOS the DAC module handle needs to be re-created using the DAC PAL instance
// before being passed to DBI's OpenVirtualProcess* implementation. The DBI and DAC share
// the same PAL where dbgshim has it's own.
LoadLibraryWFnPtr loadLibraryWFn = (LoadLibraryWFnPtr)GetProcAddress(hDac, "LoadLibraryW");
if (loadLibraryWFn != NULL)
{
hDac = loadLibraryWFn(pDacModulePath);
if (hDac == NULL)
{
hr = E_HANDLE;
}
}
else
{
hr = E_HANDLE;
}
}
#endif // FEATURE_PAL
}
// If no errors so far and "OpenVirtualProcessImpl2" doesn't exist
if (SUCCEEDED(hr) && *ppProcess == NULL)
{
// Get access to OVP and call it
OpenVirtualProcessImplFnPtr ovpFn = (OpenVirtualProcessImplFnPtr)GetProcAddress(hDbi, "OpenVirtualProcessImpl");
if (ovpFn == NULL)
{
// Fallback to CLR v4 Beta1 path, but skip some of the checking we'd normally do (maxSupportedVersion, etc.)
OpenVirtualProcess2FnPtr ovp2Fn = (OpenVirtualProcess2FnPtr)GetProcAddress(hDbi, "OpenVirtualProcess2");
if (ovp2Fn == NULL)
{
hr = CORDBG_E_LIBRARY_PROVIDER_ERROR;
}
else
{
hr = ovp2Fn(moduleBaseAddress, pDataTarget, hDac, riidProcess, ppProcess, pFlags);
}
}
else
{
// Have a CLR v4 Beta2+ DBI, call it and let it do the version check
hr = ovpFn(moduleBaseAddress, pDataTarget, hDac, pMaxDebuggerSupportedVersion, riidProcess, ppProcess, pFlags);
if (FAILED(hr))
{
_ASSERTE(ppProcess == NULL || *ppProcess == NULL);
_ASSERTE(pFlags == NULL || *pFlags == 0);
}
}
}
}
//version is still valid in some failure cases
if (pVersion != NULL &&
(SUCCEEDED(hr) ||
(hr == CORDBG_E_UNSUPPORTED_DEBUGGING_MODEL) ||
(hr == CORDBG_E_UNSUPPORTED_FORWARD_COMPAT)))
{
memcpy(pVersion, &version, sizeof(CLR_DEBUGGING_VERSION));
}
if (pDacModulePath != NULL)
{
#ifdef FEATURE_PAL
free(pDacModulePath);
#else
CoTaskMemFree(pDacModulePath);
#endif
}
if (pDbiModulePath != NULL)
{
#ifdef FEATURE_PAL
free(pDbiModulePath);
#else
CoTaskMemFree(pDbiModulePath);
#endif
}
// free the data target we QI'ed earlier
if (pDt != NULL)
{
pDt->Release();
}
return hr;
}
// Checks to see if this DAC is one of a known set of old DAC builds which contains an issue.
// If so we retarget to a newer compatible version which has the bug fixed. This is done
// by changing the PE information used to lookup the DAC.
//
// Arguments
// pdwTimeStamp - on input, the timestamp of DAC as embedded in the CLR image
// on output, a potentially new timestamp for an updated DAC to use
// instead
// pdwSizeOfImage - on input, the sizeOfImage of DAC as embedded in the CLR image
// on output, a potentially new sizeOfImage for an updated DAC to use
// instead
VOID CLRDebuggingImpl::RetargetDacIfNeeded(DWORD* pdwTimeStamp,
DWORD* pdwSizeOfImage)
{
// This code is auto generated by the CreateRetargetTable tool
// on 3/4/2011 6:35 PM
// and then copy-pasted here.
//
//
//
// Retarget the GDR1 amd64 build
if( (*pdwTimeStamp == 0x4d536868) && (*pdwSizeOfImage == 0x17b000))
{
*pdwTimeStamp = 0x4d71a160;
*pdwSizeOfImage = 0x17b000;
}
// Retarget the GDR1 x86 build
else if( (*pdwTimeStamp == 0x4d5368f2) && (*pdwSizeOfImage == 0x120000))
{
*pdwTimeStamp = 0x4d71a14f;
*pdwSizeOfImage = 0x120000;
}
// Retarget the RTM amd64 build
else if( (*pdwTimeStamp == 0x4ba21fa7) && (*pdwSizeOfImage == 0x17b000))
{
*pdwTimeStamp = 0x4d71a13c;
*pdwSizeOfImage = 0x17b000;
}
// Retarget the RTM x86 build
else if( (*pdwTimeStamp == 0x4ba1da25) && (*pdwSizeOfImage == 0x120000))
{
*pdwTimeStamp = 0x4d71a128;
*pdwSizeOfImage = 0x120000;
}
// This code is auto generated by the CreateRetargetTable tool
// on 8/17/2011 1:28 AM
// and then copy-pasted here.
//
//
//
// Retarget the GDR2 amd64 build
else if( (*pdwTimeStamp == 0x4da428c7) && (*pdwSizeOfImage == 0x17b000))
{
*pdwTimeStamp = 0x4e4b7bc2;
*pdwSizeOfImage = 0x17b000;
}
// Retarget the GDR2 x86 build
else if( (*pdwTimeStamp == 0x4da3fe52) && (*pdwSizeOfImage == 0x120000))
{
*pdwTimeStamp = 0x4e4b7bb1;
*pdwSizeOfImage = 0x120000;
}
// End auto-generated code
}
#define PE_FIXEDFILEINFO_SIGNATURE 0xFEEF04BD
// The format of the special debugging resource we embed in CLRs starting in
// v4
struct CLR_DEBUG_RESOURCE
{
DWORD dwVersion;
GUID signature;
DWORD dwDacTimeStamp;
DWORD dwDacSizeOfImage;
DWORD dwDbiTimeStamp;
DWORD dwDbiSizeOfImage;
};
// Checks to see if a module is a CLR and if so, fetches the debug data
// from the embedded resource
//
// Arguments
// pDataTarget - dataTarget for the process we are inspecting
// moduleBaseAddress - base address of a module we should inspect
// pVersion - output, the version of the CLR detected if this is a CLR
// pdwDbiTimeStamp - the timestamp of DBI as embedded in the CLR image
// pdwDbiSizeOfImage - the SizeOfImage of DBI as embedded in the CLR image
// pDbiName - output, the filename of DBI (as calculated by this function but that might change)
// dwDbiNameCharCount - input, the number of WCHARs in the buffer pointed to by pDbiName
// pdwDacTimeStampe - the timestamp of DAC as embedded in the CLR image
// pdwDacSizeOfImage - the SizeOfImage of DAC as embedded in the CLR image
// pDacName - output, the filename of DAC (as calculated by this function but that might change)
// dwDacNameCharCount - input, the number of WCHARs in the buffer pointed to by pDacName
HRESULT CLRDebuggingImpl::GetCLRInfo(ICorDebugDataTarget* pDataTarget,
ULONG64 moduleBaseAddress,
CLR_DEBUGGING_VERSION* pVersion,
DWORD* pdwDbiTimeStamp,
DWORD* pdwDbiSizeOfImage,
__out_z __inout_ecount(dwDbiNameCharCount) WCHAR* pDbiName,
DWORD dwDbiNameCharCount,
DWORD* pdwDacTimeStamp,
DWORD* pdwDacSizeOfImage,
__out_z __inout_ecount(dwDacNameCharCount) WCHAR* pDacName,
DWORD dwDacNameCharCount)
{
#ifndef FEATURE_PAL
WORD imageFileMachine = 0;
DWORD resourceSectionRVA = 0;
HRESULT hr = GetMachineAndResourceSectionRVA(pDataTarget, moduleBaseAddress, &imageFileMachine, &resourceSectionRVA);
// We want the version resource which has type = RT_VERSION = 16, name = 1, language = 0x409
DWORD versionResourceRVA = 0;
DWORD versionResourceSize = 0;
if(SUCCEEDED(hr))
{
hr = GetResourceRvaFromResourceSectionRva(pDataTarget, moduleBaseAddress, resourceSectionRVA, 16, 1, 0x409,
&versionResourceRVA, &versionResourceSize);
}
// At last we get our version info
VS_FIXEDFILEINFO fixedFileInfo = {0};
if(SUCCEEDED(hr))
{
// The version resource has 3 words, then the unicode string "VS_VERSION_INFO"
// (16 WCHARS including the null terminator)
// then padding to a 32-bit boundary, then the VS_FIXEDFILEINFO struct
DWORD fixedFileInfoRVA = ((versionResourceRVA + 3*2 + 16*2 + 3)/4)*4;
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + fixedFileInfoRVA, (BYTE*)&fixedFileInfo, sizeof(fixedFileInfo));
}
//Verify the signature on the version resource
if(SUCCEEDED(hr) && fixedFileInfo.dwSignature != PE_FIXEDFILEINFO_SIGNATURE)
{
hr = CORDBG_E_NOT_CLR;
}
// Record the version information
if(SUCCEEDED(hr))
{
pVersion->wMajor = (WORD) (fixedFileInfo.dwProductVersionMS >> 16);
pVersion->wMinor = (WORD) (fixedFileInfo.dwProductVersionMS & 0xFFFF);
pVersion->wBuild = (WORD) (fixedFileInfo.dwProductVersionLS >> 16);
pVersion->wRevision = (WORD) (fixedFileInfo.dwProductVersionLS & 0xFFFF);
}
// Now grab the special clr debug info resource
// We may need to scan a few different names searching though...
// 1) CLRDEBUGINFO<host_os><host_arch> where host_os = 'WINDOWS' or 'CORESYS' and host_arch = 'X86' or 'ARM' or 'AMD64'
// 2) For back-compat if the host os is windows and the host architecture matches the target then CLRDEBUGINFO is used with no suffix.
DWORD debugResourceRVA = 0;
DWORD debugResourceSize = 0;
BOOL useCrossPlatformNaming = FALSE;
if(SUCCEEDED(hr))
{
// the initial state is that we haven't found a proper resource
HRESULT hrGetResource = E_FAIL;
// First check for the resource which has type = RC_DATA = 10, name = "CLRDEBUGINFO<host_os><host_arch>", language = 0
#if defined (HOST_IS_WINDOWS_OS) && defined(_HOST_X86_)
const WCHAR * resourceName = W("CLRDEBUGINFOWINDOWSX86");
#endif
#if !defined (HOST_IS_WINDOWS_OS) && defined(_HOST_X86_)
const WCHAR * resourceName = W("CLRDEBUGINFOCORESYSX86");
#endif
#if defined (HOST_IS_WINDOWS_OS) && defined(_HOST_AMD64_)
const WCHAR * resourceName = W("CLRDEBUGINFOWINDOWSAMD64");
#endif
#if !defined (HOST_IS_WINDOWS_OS) && defined(_HOST_AMD64_)
const WCHAR * resourceName = W("CLRDEBUGINFOCORESYSAMD64");
#endif
#if defined (HOST_IS_WINDOWS_OS) && defined(_HOST_ARM64_)
const WCHAR * resourceName = W("CLRDEBUGINFOWINDOWSARM64");
#endif
#if !defined (HOST_IS_WINDOWS_OS) && defined(_HOST_ARM64_)
const WCHAR * resourceName = W("CLRDEBUGINFOCORESYSARM64");
#endif
#if defined (HOST_IS_WINDOWS_OS) && defined(_HOST_ARM_)
const WCHAR * resourceName = W("CLRDEBUGINFOWINDOWSARM");
#endif
#if !defined (HOST_IS_WINDOWS_OS) && defined(_HOST_ARM_)
const WCHAR * resourceName = W("CLRDEBUGINFOCORESYSARM");
#endif
hrGetResource = GetResourceRvaFromResourceSectionRvaByName(pDataTarget, moduleBaseAddress, resourceSectionRVA, 10, resourceName, 0,
&debugResourceRVA, &debugResourceSize);
useCrossPlatformNaming = SUCCEEDED(hrGetResource);
#if defined(HOST_IS_WINDOWS_OS) && (defined(_HOST_X86_) || defined(_HOST_AMD64_) || defined(_HOST_ARM_))
#if defined(_HOST_X86_)
#define _HOST_MACHINE_TYPE IMAGE_FILE_MACHINE_I386
#elif defined(_HOST_AMD64_)
#define _HOST_MACHINE_TYPE IMAGE_FILE_MACHINE_AMD64
#elif defined(_HOST_ARM_)
#define _HOST_MACHINE_TYPE IMAGE_FILE_MACHINE_ARMNT
#endif
// if this is windows, and if host_arch matches target arch then we can fallback to searching for CLRDEBUGINFO on failure
if(FAILED(hrGetResource) && (imageFileMachine == _HOST_MACHINE_TYPE))
{
hrGetResource = GetResourceRvaFromResourceSectionRvaByName(pDataTarget, moduleBaseAddress, resourceSectionRVA, 10, W("CLRDEBUGINFO"), 0,
&debugResourceRVA, &debugResourceSize);
}
#undef _HOST_MACHINE_TYPE
#endif
// if the search failed, we don't recognize the CLR
if(FAILED(hrGetResource))
hr = CORDBG_E_NOT_CLR;
}
CLR_DEBUG_RESOURCE debugResource;
if(SUCCEEDED(hr) && debugResourceSize != sizeof(debugResource))
{
hr = CORDBG_E_NOT_CLR;
}
// Get the special debug resource from the image and return the results
if(SUCCEEDED(hr))
{
hr = ReadFromDataTarget(pDataTarget, moduleBaseAddress + debugResourceRVA, (BYTE*)&debugResource, sizeof(debugResource));
}
if(SUCCEEDED(hr) && (debugResource.dwVersion != 0))
{
hr = CORDBG_E_NOT_CLR;
}
// The signature needs to match m_skuId exactly, except for m_skuId=CLR_ID_ONECORE_CLR which is
// also compatible with the older CLR_ID_PHONE_CLR signature.
if(SUCCEEDED(hr) &&
(debugResource.signature != m_skuId) &&
!( (debugResource.signature == CLR_ID_PHONE_CLR) && (m_skuId == CLR_ID_ONECORE_CLR) ))
{
hr = CORDBG_E_NOT_CLR;
}
if(SUCCEEDED(hr) &&
(debugResource.signature != CLR_ID_ONECORE_CLR) &&
useCrossPlatformNaming)
{
FormatLongDacModuleName(pDacName, dwDacNameCharCount, imageFileMachine, &fixedFileInfo);
swprintf_s(pDbiName, dwDbiNameCharCount, W("%s_%s.dll"), MAIN_DBI_MODULE_NAME_W, W("x86"));
}
else
{
if(m_skuId == CLR_ID_V4_DESKTOP)
swprintf_s(pDacName, dwDacNameCharCount, W("%s.dll"), CLR_DAC_MODULE_NAME_W);
else
swprintf_s(pDacName, dwDacNameCharCount, W("%s.dll"), CORECLR_DAC_MODULE_NAME_W);
swprintf_s(pDbiName, dwDbiNameCharCount, W("%s.dll"), MAIN_DBI_MODULE_NAME_W);
}
if(SUCCEEDED(hr))
{
*pdwDbiTimeStamp = debugResource.dwDbiTimeStamp;
*pdwDbiSizeOfImage = debugResource.dwDbiSizeOfImage;
*pdwDacTimeStamp = debugResource.dwDacTimeStamp;
*pdwDacSizeOfImage = debugResource.dwDacSizeOfImage;
}
// any failure should be interpreted as this module not being a CLR
if(FAILED(hr))
{
return CORDBG_E_NOT_CLR;
}
else
{
return S_OK;
}
#else
swprintf_s(pDacName, dwDacNameCharCount, W("%s"), MAKEDLLNAME_W(CORECLR_DAC_MODULE_NAME_W));
swprintf_s(pDbiName, dwDbiNameCharCount, W("%s"), MAKEDLLNAME_W(MAIN_DBI_MODULE_NAME_W));
pVersion->wMajor = 0;
pVersion->wMinor = 0;
pVersion->wBuild = 0;
pVersion->wRevision = 0;
*pdwDbiTimeStamp = 0;
*pdwDbiSizeOfImage = 0;
*pdwDacTimeStamp = 0;
*pdwDacSizeOfImage = 0;
return S_OK;
#endif // FEATURE_PAL
}
// Formats the long name for DAC
HRESULT CLRDebuggingImpl::FormatLongDacModuleName(__out_z __inout_ecount(cchBuffer) WCHAR * pBuffer,
DWORD cchBuffer,
DWORD targetImageFileMachine,
VS_FIXEDFILEINFO * pVersion)
{
#ifndef HOST_IS_WINDOWS_OS
_ASSERTE(!"NYI");
return E_NOTIMPL;
#endif
#if defined(_HOST_X86_)
const WCHAR* pHostArch = W("x86");
#elif defined(_HOST_AMD64_)
const WCHAR* pHostArch = W("amd64");
#elif defined(_HOST_ARM_)
const WCHAR* pHostArch = W("arm");
#elif defined(_HOST_ARM64_)
const WCHAR* pHostArch = W("arm64");
#else
_ASSERTE(!"Unknown host arch");
return E_NOTIMPL;
#endif
const WCHAR* pDacBaseName = NULL;
if(m_skuId == CLR_ID_V4_DESKTOP)
pDacBaseName = CLR_DAC_MODULE_NAME_W;
else if(m_skuId == CLR_ID_CORECLR || m_skuId == CLR_ID_PHONE_CLR || m_skuId == CLR_ID_ONECORE_CLR)
pDacBaseName = CORECLR_DAC_MODULE_NAME_W;
else
{
_ASSERTE(!"Unknown SKU id");
return E_UNEXPECTED;
}
const WCHAR* pTargetArch = NULL;
if(targetImageFileMachine == IMAGE_FILE_MACHINE_I386)
{
pTargetArch = W("x86");
}
else if(targetImageFileMachine == IMAGE_FILE_MACHINE_AMD64)
{
pTargetArch = W("amd64");
}
else if(targetImageFileMachine == IMAGE_FILE_MACHINE_ARMNT)
{
pTargetArch = W("arm");
}
else if(targetImageFileMachine == IMAGE_FILE_MACHINE_ARM64)
{
pTargetArch = W("arm64");
}
else
{
_ASSERTE(!"Unknown target image file machine type");
return E_INVALIDARG;
}
const WCHAR* pBuildFlavor = W("");
if(pVersion->dwFileFlags & VS_FF_DEBUG)
{
if(pVersion->dwFileFlags & VS_FF_SPECIALBUILD)
pBuildFlavor = W(".dbg");
else
pBuildFlavor = W(".chk");
}
// WARNING: if you change the formatting make sure you recalculate the maximum
// possible size string and verify callers pass a big enough buffer. This doesn't
// have to be a tight estimate, just make sure its >= the biggest possible DAC name
// and it can be calculated statically
DWORD minCchBuffer =
(DWORD) wcslen(CLR_DAC_MODULE_NAME_W) + (DWORD) wcslen(CORECLR_DAC_MODULE_NAME_W) + // max name
10 + // max host arch
10 + // max target arch
40 + // max version
10 + // max build flavor
(DWORD) wcslen(W("name_host_target_version.flavor.dll")) + // max intermediate formatting chars
1; // null terminator
// validate the output buffer is larger than our estimate above
_ASSERTE(cchBuffer >= minCchBuffer);
if(!(cchBuffer >= minCchBuffer)) return E_INVALIDARG;
swprintf_s(pBuffer, cchBuffer, W("%s_%s_%s_%u.%u.%u.%02u%s.dll"),
pDacBaseName,
pHostArch,
pTargetArch,
pVersion->dwProductVersionMS >> 16,
pVersion->dwProductVersionMS & 0xFFFF,
pVersion->dwProductVersionLS >> 16,
pVersion->dwProductVersionLS & 0xFFFF,
pBuildFlavor);
return S_OK;
}
// An implementation of ICLRDebugging::CanUnloadNow
//
// Arguments:
// hModule - a handle to a module provided earlier by ProvideLibrary
//
// Returns:
// S_OK if the library is no longer in use and can be unloaded, S_FALSE otherwise
//
STDMETHODIMP CLRDebuggingImpl::CanUnloadNow(HMODULE hModule)
{
// In V4 at least we don't support any unloading.
HRESULT hr = S_FALSE;
return hr;
}
STDMETHODIMP CLRDebuggingImpl::QueryInterface(REFIID riid, void **ppvObject)
{
HRESULT hr = S_OK;
if (riid == __uuidof(IUnknown))
{
IUnknown *pItf = static_cast<IUnknown *>(this);
pItf->AddRef();
*ppvObject = pItf;
}
else if (riid == __uuidof(ICLRDebugging))
{
ICLRDebugging *pItf = static_cast<ICLRDebugging *>(this);
pItf->AddRef();
*ppvObject = pItf;
}
else
hr = E_NOINTERFACE;
return hr;
}
// Standard AddRef implementation
ULONG CLRDebuggingImpl::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
// Standard Release implementation.
ULONG CLRDebuggingImpl::Release()
{
_ASSERTE(m_cRef > 0);
ULONG cRef = InterlockedDecrement(&m_cRef);
if (cRef == 0)
delete this; // Relies on virtual dtor to work properly.
return cRef;
}

Просмотреть файл

@ -0,0 +1,90 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//*****************************************************************************
// debugshim.h
//
//
//*****************************************************************************
#ifndef _DEBUG_SHIM_
#define _DEBUG_SHIM_
#include "cor.h"
#include "cordebug.h"
#include <wchar.h>
#include <metahost.h>
#define CORECLR_DAC_MODULE_NAME_W W("mscordaccore")
#define CLR_DAC_MODULE_NAME_W W("mscordacwks")
#define MAIN_DBI_MODULE_NAME_W W("mscordbi")
// forward declaration
struct ICorDebugDataTarget;
// ICLRDebugging implementation.
class CLRDebuggingImpl : public ICLRDebugging
{
public:
CLRDebuggingImpl(GUID skuId) : m_cRef(0), m_skuId(skuId)
{
}
virtual ~CLRDebuggingImpl() {}
public:
// ICLRDebugging methods:
STDMETHOD(OpenVirtualProcess(
ULONG64 moduleBaseAddress,
IUnknown * pDataTarget,
ICLRDebuggingLibraryProvider * pLibraryProvider,
CLR_DEBUGGING_VERSION * pMaxDebuggerSupportedVersion,
REFIID riidProcess,
IUnknown ** ppProcess,
CLR_DEBUGGING_VERSION * pVersion,
CLR_DEBUGGING_PROCESS_FLAGS * pFlags));
STDMETHOD(CanUnloadNow(HMODULE hModule));
//IUnknown methods:
STDMETHOD(QueryInterface(
REFIID riid,
void **ppvObject));
// Standard AddRef implementation
STDMETHOD_(ULONG, AddRef());
// Standard Release implementation.
STDMETHOD_(ULONG, Release());
private:
VOID RetargetDacIfNeeded(DWORD* pdwTimeStamp,
DWORD* pdwSizeOfImage);
HRESULT GetCLRInfo(ICorDebugDataTarget * pDataTarget,
ULONG64 moduleBaseAddress,
CLR_DEBUGGING_VERSION * pVersion,
DWORD * pdwDbiTimeStamp,
DWORD * pdwDbiSizeOfImage,
__out_z __inout_ecount(dwDbiNameCharCount) WCHAR * pDbiName,
DWORD dwDbiNameCharCount,
DWORD * pdwDacTimeStamp,
DWORD * pdwDacSizeOfImage,
__out_z __inout_ecount(dwDacNameCharCount) WCHAR * pDacName,
DWORD dwDacNameCharCount);
HRESULT FormatLongDacModuleName(__out_z __inout_ecount(cchBuffer) WCHAR * pBuffer,
DWORD cchBuffer,
DWORD targetImageFileMachine,
VS_FIXEDFILEINFO * pVersion);
volatile LONG m_cRef;
GUID m_skuId;
}; // class CLRDebuggingImpl
#endif

Просмотреть файл

Просмотреть файл

@ -527,5 +527,5 @@ void GCDump::DumpPtrsInFrame(PTR_CBYTE gcInfoBlock,
#define GET_CALLER_SP(pREGDISPLAY) ((size_t)GetSP(pREGDISPLAY->pCallerContext))
#define VALIDATE_OBJECTREF(objref, fDeep) ((void)0)
#define VALIDATE_ROOT(isInterior, hCallBack, pObjRef) ((void)0)
#include "../vm/gcinfodecoder.cpp"
#include "../gcinfo/gcinfodumper.cpp"
#include "gcinfodecoder.cpp"
#include "gcinfodumper.cpp"

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "common.h"
#include "gcinfodumper.h"
#include "gcinfodecoder.h"

Просмотреть файл

Просмотреть файл

@ -23,24 +23,8 @@ if(SKIP_LLDBPLUGIN)
endif()
if(CLR_CMAKE_PLATFORM_ARCH_AMD64)
add_definitions(-D_TARGET_AMD64_=1)
add_definitions(-DDBG_TARGET_64BIT=1)
add_definitions(-DDBG_TARGET_AMD64=1)
add_definitions(-DDBG_TARGET_WIN64=1)
add_definitions(-DBIT64)
elseif(CLR_CMAKE_PLATFORM_ARCH_I386)
add_definitions(-D_TARGET_X86_=1)
add_definitions(-DDBG_TARGET_32BIT=1)
add_definitions(-DDBG_TARGET_X86=1)
elseif(CLR_CMAKE_PLATFORM_ARCH_ARM)
add_definitions(-D_TARGET_ARM_=1)
add_definitions(-DDBG_TARGET_32BIT=1)
add_definitions(-DDBG_TARGET_ARM=1)
elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64)
add_definitions(-D_TARGET_ARM64_=1)
add_definitions(-DDBG_TARGET_64BIT=1)
add_definitions(-DDBG_TARGET_ARM64=1)
add_definitions(-DDBG_TARGET_WIN64=1)
add_definitions(-DBIT64)
SET(REQUIRE_LLDBPLUGIN false)
endif()

Просмотреть файл

@ -1,365 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// crosscomp.h - cross-compilation enablement structures.
//
#pragma once
#if defined(_X86_) && defined(_TARGET_ARM_) // Host X86 managing ARM related code
#ifndef CROSS_COMPILE
#define CROSS_COMPILE
#endif
#define ARM_MAX_BREAKPOINTS 8
#define ARM_MAX_WATCHPOINTS 1
#define CONTEXT_UNWOUND_TO_CALL 0x20000000
typedef struct _NEON128 {
ULONGLONG Low;
LONGLONG High;
} NEON128, *PNEON128;
typedef struct DECLSPEC_ALIGN(8) _T_CONTEXT {
//
// Control flags.
//
DWORD ContextFlags;
//
// Integer registers
//
DWORD R0;
DWORD R1;
DWORD R2;
DWORD R3;
DWORD R4;
DWORD R5;
DWORD R6;
DWORD R7;
DWORD R8;
DWORD R9;
DWORD R10;
DWORD R11;
DWORD R12;
//
// Control Registers
//
DWORD Sp;
DWORD Lr;
DWORD Pc;
DWORD Cpsr;
//
// Floating Point/NEON Registers
//
DWORD Fpscr;
DWORD Padding;
union {
NEON128 Q[16];
ULONGLONG D[32];
DWORD S[32];
};
//
// Debug registers
//
DWORD Bvr[ARM_MAX_BREAKPOINTS];
DWORD Bcr[ARM_MAX_BREAKPOINTS];
DWORD Wvr[ARM_MAX_WATCHPOINTS];
DWORD Wcr[ARM_MAX_WATCHPOINTS];
DWORD Padding2[2];
} T_CONTEXT, *PT_CONTEXT;
//
// Define function table entry - a function table entry is generated for
// each frame function.
//
#ifndef FEATURE_PAL
typedef struct _RUNTIME_FUNCTION {
DWORD BeginAddress;
DWORD UnwindData;
} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
//
// Define unwind history table structure.
//
#define UNWIND_HISTORY_TABLE_SIZE 12
typedef struct _UNWIND_HISTORY_TABLE_ENTRY {
DWORD ImageBase;
PRUNTIME_FUNCTION FunctionEntry;
} UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY;
typedef struct _UNWIND_HISTORY_TABLE {
DWORD Count;
BYTE LocalHint;
BYTE GlobalHint;
BYTE Search;
BYTE Once;
DWORD LowAddress;
DWORD HighAddress;
UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE];
} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE;
#endif // !FEATURE_PAL
//
// Nonvolatile context pointer record.
//
typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS {
PDWORD R4;
PDWORD R5;
PDWORD R6;
PDWORD R7;
PDWORD R8;
PDWORD R9;
PDWORD R10;
PDWORD R11;
PDWORD Lr;
PULONGLONG D8;
PULONGLONG D9;
PULONGLONG D10;
PULONGLONG D11;
PULONGLONG D12;
PULONGLONG D13;
PULONGLONG D14;
PULONGLONG D15;
} T_KNONVOLATILE_CONTEXT_POINTERS, *PT_KNONVOLATILE_CONTEXT_POINTERS;
//
// Define dynamic function table entry.
//
typedef
PRUNTIME_FUNCTION
(*PGET_RUNTIME_FUNCTION_CALLBACK) (
IN DWORD64 ControlPc,
IN PVOID Context
);
typedef struct _T_DISPATCHER_CONTEXT {
ULONG ControlPc;
ULONG ImageBase;
PRUNTIME_FUNCTION FunctionEntry;
ULONG EstablisherFrame;
ULONG TargetPc;
PT_CONTEXT ContextRecord;
PEXCEPTION_ROUTINE LanguageHandler;
PVOID HandlerData;
PUNWIND_HISTORY_TABLE HistoryTable;
ULONG ScopeIndex;
BOOLEAN ControlPcIsUnwound;
PUCHAR NonVolatileRegisters;
} T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT;
#define T_RUNTIME_FUNCTION RUNTIME_FUNCTION
#define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION
#elif defined(_AMD64_) && defined(_TARGET_ARM64_) // Host amd64 managing ARM64 related code
#ifndef CROSS_COMPILE
#define CROSS_COMPILE
#endif
//
// Specify the number of breakpoints and watchpoints that the OS
// will track. Architecturally, ARM64 supports up to 16. In practice,
// however, almost no one implements more than 4 of each.
//
#define ARM64_MAX_BREAKPOINTS 8
#define ARM64_MAX_WATCHPOINTS 2
#define CONTEXT_UNWOUND_TO_CALL 0x20000000
typedef union _NEON128 {
struct {
ULONGLONG Low;
LONGLONG High;
};
double D[2];
float S[4];
WORD H[8];
BYTE B[16];
} NEON128, *PNEON128;
typedef struct DECLSPEC_ALIGN(16) _T_CONTEXT {
//
// Control flags.
//
/* +0x000 */ DWORD ContextFlags;
//
// Integer registers
//
/* +0x004 */ DWORD Cpsr; // NZVF + DAIF + CurrentEL + SPSel
/* +0x008 */ union {
struct {
DWORD64 X0;
DWORD64 X1;
DWORD64 X2;
DWORD64 X3;
DWORD64 X4;
DWORD64 X5;
DWORD64 X6;
DWORD64 X7;
DWORD64 X8;
DWORD64 X9;
DWORD64 X10;
DWORD64 X11;
DWORD64 X12;
DWORD64 X13;
DWORD64 X14;
DWORD64 X15;
DWORD64 X16;
DWORD64 X17;
DWORD64 X18;
DWORD64 X19;
DWORD64 X20;
DWORD64 X21;
DWORD64 X22;
DWORD64 X23;
DWORD64 X24;
DWORD64 X25;
DWORD64 X26;
DWORD64 X27;
DWORD64 X28;
};
DWORD64 X[29];
};
/* +0x0f0 */ DWORD64 Fp;
/* +0x0f8 */ DWORD64 Lr;
/* +0x100 */ DWORD64 Sp;
/* +0x108 */ DWORD64 Pc;
//
// Floating Point/NEON Registers
//
/* +0x110 */ NEON128 V[32];
/* +0x310 */ DWORD Fpcr;
/* +0x314 */ DWORD Fpsr;
//
// Debug registers
//
/* +0x318 */ DWORD Bcr[ARM64_MAX_BREAKPOINTS];
/* +0x338 */ DWORD64 Bvr[ARM64_MAX_BREAKPOINTS];
/* +0x378 */ DWORD Wcr[ARM64_MAX_WATCHPOINTS];
/* +0x380 */ DWORD64 Wvr[ARM64_MAX_WATCHPOINTS];
/* +0x390 */
} T_CONTEXT, *PT_CONTEXT;
// _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY (see ExternalAPIs\Win9CoreSystem\inc\winnt.h)
typedef struct _T_RUNTIME_FUNCTION {
DWORD BeginAddress;
union {
DWORD UnwindData;
struct {
DWORD Flag : 2;
DWORD FunctionLength : 11;
DWORD RegF : 3;
DWORD RegI : 4;
DWORD H : 1;
DWORD CR : 2;
DWORD FrameSize : 9;
} PackedUnwindData;
};
} T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION;
//
// Define exception dispatch context structure.
//
typedef struct _T_DISPATCHER_CONTEXT {
DWORD64 ControlPc;
DWORD64 ImageBase;
PT_RUNTIME_FUNCTION FunctionEntry;
DWORD64 EstablisherFrame;
DWORD64 TargetPc;
PCONTEXT ContextRecord;
PEXCEPTION_ROUTINE LanguageHandler;
PVOID HandlerData;
PUNWIND_HISTORY_TABLE HistoryTable;
DWORD ScopeIndex;
BOOLEAN ControlPcIsUnwound;
PBYTE NonVolatileRegisters;
} T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT;
//
// Nonvolatile context pointer record.
//
typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS {
PDWORD64 X19;
PDWORD64 X20;
PDWORD64 X21;
PDWORD64 X22;
PDWORD64 X23;
PDWORD64 X24;
PDWORD64 X25;
PDWORD64 X26;
PDWORD64 X27;
PDWORD64 X28;
PDWORD64 Fp;
PDWORD64 Lr;
PDWORD64 D8;
PDWORD64 D9;
PDWORD64 D10;
PDWORD64 D11;
PDWORD64 D12;
PDWORD64 D13;
PDWORD64 D14;
PDWORD64 D15;
} T_KNONVOLATILE_CONTEXT_POINTERS, *PT_KNONVOLATILE_CONTEXT_POINTERS;
#else // !(defined(_X86_) && defined(_TARGET_ARM_)) && !(defined(_AMD64_) && defined(_TARGET_ARM64_))
#define T_CONTEXT CONTEXT
#define PT_CONTEXT PCONTEXT
#define T_DISPATCHER_CONTEXT DISPATCHER_CONTEXT
#define PT_DISPATCHER_CONTEXT PDISPATCHER_CONTEXT
#define T_KNONVOLATILE_CONTEXT_POINTERS KNONVOLATILE_CONTEXT_POINTERS
#define PT_KNONVOLATILE_CONTEXT_POINTERS PKNONVOLATILE_CONTEXT_POINTERS
#define T_RUNTIME_FUNCTION RUNTIME_FUNCTION
#define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION
#endif
#ifdef CROSSGEN_COMPILE
void CrossGenNotSupported(const char * message);
#endif

Просмотреть файл

@ -1,141 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#ifndef __DBG_PORTABLE_INCLUDED
#define __DBG_PORTABLE_INCLUDED
//
// This header defines the template class Portable<T> which is designed to wrap primitive types in such a way
// that their physical representation is in a canonical format that can be safely transferred between hosts on
// different platforms.
//
// This is achieved by storing the wrapped datum in little-endian format (since most of our platforms are
// little-endian this makes the most sense from a performance perspective). On little-endian platforms the
// wrapper code will become a no-op and get optimized away by the compiler. On big-endian platforms
// assignments to a Portable<T> value will reverse the order of the bytes in the T value and reverse them back
// again on a read.
//
// Portable<T> is typically used to wrap the fields of structures sent directly over a network channel. In
// this fashion many of the values that would otherwise require manual endian-ness fixups are now marshalled
// and unmarshalled transparent right at the network transition.
//
// Care must be taken to identify any code that takes the address of a Portable<T>, since this is not
// generally safe (it could expose naive code to the network encoded form of the datum). In such situations
// the code is normally re-written to create a temporary instance of T on the stack, initialized to the
// correct host value by reading from the Portable<T> field. The address of this variable can now be taken
// safely (assuming its value is required only for some lexically scoped operation). Once the value is no
// longer being used, and if there is a possibility that the value may have been updated, the new value can be
// copied back into the Portable<T> field.
//
// Note that this header uses very basic data types only as it is included from both Win32/PAL code and native
// Mac code.
//
#if BIGENDIAN || __BIG_ENDIAN__
#define DBG_BYTE_SWAP_REQUIRED
#endif
#if defined(_ASSERTE)
#define _PASSERT(_expr) _ASSERTE(_expr)
#elif defined(assert)
#define _PASSERT(_expr) assert(_expr)
#else
#define _PASSERT(_expr)
#endif
// Lowest level helper used to reverse the order of a sequence of bytes, either as an in-place operation or as
// part of a copy.
inline void ByteSwapPrimitive(const void *pSrc, void *pDst, unsigned int cbSize)
{
_PASSERT(cbSize == 2 || cbSize == 4 || cbSize == 8);
unsigned char *pbSrc = (unsigned char*)pSrc;
unsigned char *pbDst = (unsigned char*)pDst;
for (unsigned int i = 0; i < (cbSize / 2); i++)
{
unsigned int j = cbSize - i - 1;
unsigned char bTemp = pbSrc[i];
pbDst[i] = pbSrc[j];
pbDst[j] = bTemp;
}
}
template <typename T>
class Portable
{
T m_data;
public:
// No constructors -- this will be used in unions.
// Convert data to portable format on assignment.
T operator = (T value)
{
_PASSERT(sizeof(value) <= sizeof(double));
#ifdef DBG_BYTE_SWAP_REQUIRED
m_data = ByteSwap(value);
#else // DBG_BYTE_SWAP_REQUIRED
m_data = value;
#endif // DBG_BYTE_SWAP_REQUIRED
return value;
}
// Return data in native format on access.
operator T () const
{
#ifdef DBG_BYTE_SWAP_REQUIRED
return ByteSwap(m_data);
#else // DBG_BYTE_SWAP_REQUIRED
return m_data;
#endif // DBG_BYTE_SWAP_REQUIRED
}
bool operator == (T other) const
{
#ifdef DBG_BYTE_SWAP_REQUIRED
return ByteSwap(m_data) == other;
#else // DBG_BYTE_SWAP_REQUIRED
return m_data == other;
#endif // DBG_BYTE_SWAP_REQUIRED
}
bool operator != (T other) const
{
#ifdef DBG_BYTE_SWAP_REQUIRED
return ByteSwap(m_data) != other;
#else // DBG_BYTE_SWAP_REQUIRED
return m_data != other;
#endif // DBG_BYTE_SWAP_REQUIRED
}
T Unwrap()
{
#ifdef DBG_BYTE_SWAP_REQUIRED
return ByteSwap(m_data);
#else // DBG_BYTE_SWAP_REQUIRED
return m_data;
#endif // DBG_BYTE_SWAP_REQUIRED
}
private:
#ifdef DBG_BYTE_SWAP_REQUIRED
// Big endian helper routine to swap the order of bytes of an arbitrary sized type
// (though obviously this type must be an integral primitive for this to make any
// sense).
static T ByteSwap(T inval)
{
if (sizeof(T) > 1)
{
T outval;
ByteSwapPrimitive(&inval, &outval, sizeof(T));
return outval;
}
else
return inval;
}
#endif // DBG_BYTE_SWAP_REQUIRED
};
#endif // !__DBG_PORTABLE_INCLUDED

Просмотреть файл

@ -1,458 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#ifndef __DBG_TARGET_CONTEXT_INCLUDED
#define __DBG_TARGET_CONTEXT_INCLUDED
#include <dbgportable.h>
#include <stddef.h>
#include "crosscomp.h"
//
// The right side of the debugger can now be built to target multiple platforms. This means it is no longer
// safe to use the CONTEXT structure directly: the context of the platform we're building for might not match
// that of the one the debugger is targetting. So now all right side code will use the DT_CONTEXT abstraction
// instead. When the debugger target is the local platform this will just resolve back into CONTEXT, but cross
// platform we'll provide a hand-rolled version.
//
//
// For cross platform cases we also need to provide a helper function for byte-swapping a context structure
// should the endian-ness of the debugger and debuggee platforms differ. This is called ByteSwapContext and is
// obviously a no-op for those cases where the left and right sides agree on storage format.
//
// NOTE: Any changes to the field layout of DT_CONTEXT must be tracked in the associated definition of
// ByteSwapContext.
//
// For now, the only cross-platform CONTEXTs we support are x86/PAL and ARM/Win. Look in
// rotor/pal/inc/rotor_pal.h for the original PAL definitions.
//
// **** NOTE: Keep these in sync with rotor/pal/inc/rotor_pal.h ****
//
// This odd define pattern is needed because in DBI we set _TARGET_ to match the host and
// DBG_TARGET to control our targeting. In x-plat DBI DBG_TARGET won't match _TARGET_ and
// DBG_TARGET needs to take precedence
#if defined(DBG_TARGET_X86)
#define DTCONTEXT_IS_X86
#elif defined (DBG_TARGET_AMD64)
#define DTCONTEXT_IS_AMD64
#elif defined (DBG_TARGET_ARM)
#define DTCONTEXT_IS_ARM
#elif defined (DBG_TARGET_ARM64)
#define DTCONTEXT_IS_ARM64
#elif defined (_TARGET_X86_)
#define DTCONTEXT_IS_X86
#elif defined (_TARGET_AMD64_)
#define DTCONTEXT_IS_AMD64
#elif defined (_TARGET_ARM_)
#define DTCONTEXT_IS_ARM
#elif defined (_TARGET_ARM64_)
#define DTCONTEXT_IS_ARM64
#endif
#if defined(DTCONTEXT_IS_X86)
#define DT_SIZE_OF_80387_REGISTERS 80
#define DT_CONTEXT_i386 0x00010000
#define DT_CONTEXT_CONTROL (DT_CONTEXT_i386 | 0x00000001L) // SS:SP, CS:IP, FLAGS, BP
#define DT_CONTEXT_INTEGER (DT_CONTEXT_i386 | 0x00000002L) // AX, BX, CX, DX, SI, DI
#define DT_CONTEXT_SEGMENTS (DT_CONTEXT_i386 | 0x00000004L)
#define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_i386 | 0x00000008L) // 387 state
#define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_i386 | 0x00000010L)
#define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_SEGMENTS)
#define DT_CONTEXT_EXTENDED_REGISTERS (DT_CONTEXT_i386 | 0x00000020L)
#define DT_MAXIMUM_SUPPORTED_EXTENSION 512
typedef struct {
DWORD ControlWord;
DWORD StatusWord;
DWORD TagWord;
DWORD ErrorOffset;
DWORD ErrorSelector;
DWORD DataOffset;
DWORD DataSelector;
BYTE RegisterArea[DT_SIZE_OF_80387_REGISTERS];
DWORD Cr0NpxState;
} DT_FLOATING_SAVE_AREA;
typedef struct {
ULONG ContextFlags;
ULONG Dr0;
ULONG Dr1;
ULONG Dr2;
ULONG Dr3;
ULONG Dr6;
ULONG Dr7;
DT_FLOATING_SAVE_AREA FloatSave;
ULONG SegGs;
ULONG SegFs;
ULONG SegEs;
ULONG SegDs;
ULONG Edi;
ULONG Esi;
ULONG Ebx;
ULONG Edx;
ULONG Ecx;
ULONG Eax;
ULONG Ebp;
ULONG Eip;
ULONG SegCs;
ULONG EFlags;
ULONG Esp;
ULONG SegSs;
UCHAR ExtendedRegisters[DT_MAXIMUM_SUPPORTED_EXTENSION];
} DT_CONTEXT;
// Since the target is little endian in this case we only have to provide a real implementation of
// ByteSwapContext if the platform we're building on is big-endian.
#ifdef BIGENDIAN
inline void ByteSwapContext(DT_CONTEXT *pContext)
{
// Our job is simplified since the context has large contiguous ranges with fields of the same size. Keep
// the following logic in sync with the definition of DT_CONTEXT above.
BYTE *pbContext = (BYTE*)pContext;
// The first span consists of 4 byte fields.
DWORD cbFields = (offsetof(DT_CONTEXT, FloatSave) + offsetof(DT_FLOATING_SAVE_AREA, RegisterArea)) / 4;
for (DWORD i = 0; i < cbFields; i++)
{
ByteSwapPrimitive(pbContext, pbContext, 4);
pbContext += 4;
}
// Then there's a float save area containing 8 byte fields.
cbFields = sizeof(pContext->FloatSave.RegisterArea);
for (DWORD i = 0; i < cbFields; i++)
{
ByteSwapPrimitive(pbContext, pbContext, 8);
pbContext += 8;
}
// Back to 4 byte fields.
cbFields = (offsetof(DT_CONTEXT, ExtendedRegisters) - offsetof(DT_CONTEXT, SegGs)) / 4;
for (DWORD i = 0; i < cbFields; i++)
{
ByteSwapPrimitive(pbContext, pbContext, 4);
pbContext += 4;
}
// We don't know the formatting of the extended register area, but the debugger doesn't access this data
// on the left side, so just leave it in left-side format for now.
// Validate that we converted up to where we think we did as a hedge against DT_CONTEXT layout changes.
_PASSERT((pbContext - ((BYTE*)pContext)) == (sizeof(DT_CONTEXT) - sizeof(pContext->ExtendedRegisters)));
}
#else // BIGENDIAN
inline void ByteSwapContext(DT_CONTEXT *pContext)
{
}
#endif // BIGENDIAN
#elif defined(DTCONTEXT_IS_AMD64)
#define DT_CONTEXT_AMD64 0x00100000L
#define DT_CONTEXT_CONTROL (DT_CONTEXT_AMD64 | 0x00000001L)
#define DT_CONTEXT_INTEGER (DT_CONTEXT_AMD64 | 0x00000002L)
#define DT_CONTEXT_SEGMENTS (DT_CONTEXT_AMD64 | 0x00000004L)
#define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_AMD64 | 0x00000008L)
#define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_AMD64 | 0x00000010L)
#define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT)
#define DT_CONTEXT_ALL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_SEGMENTS | DT_CONTEXT_FLOATING_POINT | DT_CONTEXT_DEBUG_REGISTERS)
typedef struct {
ULONGLONG Low;
LONGLONG High;
} DT_M128A;
typedef struct {
WORD ControlWord;
WORD StatusWord;
BYTE TagWord;
BYTE Reserved1;
WORD ErrorOpcode;
DWORD ErrorOffset;
WORD ErrorSelector;
WORD Reserved2;
DWORD DataOffset;
WORD DataSelector;
WORD Reserved3;
DWORD MxCsr;
DWORD MxCsr_Mask;
DT_M128A FloatRegisters[8];
DT_M128A XmmRegisters[16];
BYTE Reserved4[96];
} DT_XMM_SAVE_AREA32;
typedef struct DECLSPEC_ALIGN(16) {
DWORD64 P1Home;
DWORD64 P2Home;
DWORD64 P3Home;
DWORD64 P4Home;
DWORD64 P5Home;
DWORD64 P6Home;
DWORD ContextFlags;
DWORD MxCsr;
WORD SegCs;
WORD SegDs;
WORD SegEs;
WORD SegFs;
WORD SegGs;
WORD SegSs;
DWORD EFlags;
DWORD64 Dr0;
DWORD64 Dr1;
DWORD64 Dr2;
DWORD64 Dr3;
DWORD64 Dr6;
DWORD64 Dr7;
DWORD64 Rax;
DWORD64 Rcx;
DWORD64 Rdx;
DWORD64 Rbx;
DWORD64 Rsp;
DWORD64 Rbp;
DWORD64 Rsi;
DWORD64 Rdi;
DWORD64 R8;
DWORD64 R9;
DWORD64 R10;
DWORD64 R11;
DWORD64 R12;
DWORD64 R13;
DWORD64 R14;
DWORD64 R15;
DWORD64 Rip;
union {
DT_XMM_SAVE_AREA32 FltSave;
struct {
DT_M128A Header[2];
DT_M128A Legacy[8];
DT_M128A Xmm0;
DT_M128A Xmm1;
DT_M128A Xmm2;
DT_M128A Xmm3;
DT_M128A Xmm4;
DT_M128A Xmm5;
DT_M128A Xmm6;
DT_M128A Xmm7;
DT_M128A Xmm8;
DT_M128A Xmm9;
DT_M128A Xmm10;
DT_M128A Xmm11;
DT_M128A Xmm12;
DT_M128A Xmm13;
DT_M128A Xmm14;
DT_M128A Xmm15;
};
};
DT_M128A VectorRegister[26];
DWORD64 VectorControl;
DWORD64 DebugControl;
DWORD64 LastBranchToRip;
DWORD64 LastBranchFromRip;
DWORD64 LastExceptionToRip;
DWORD64 LastExceptionFromRip;
} DT_CONTEXT;
#elif defined(DTCONTEXT_IS_ARM)
#define DT_CONTEXT_ARM 0x00200000L
#define DT_CONTEXT_CONTROL (DT_CONTEXT_ARM | 0x1L)
#define DT_CONTEXT_INTEGER (DT_CONTEXT_ARM | 0x2L)
#define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_ARM | 0x4L)
#define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_ARM | 0x8L)
#define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT)
#define DT_CONTEXT_ALL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT | DT_CONTEXT_DEBUG_REGISTERS)
#define DT_ARM_MAX_BREAKPOINTS 8
#define DT_ARM_MAX_WATCHPOINTS 1
typedef struct {
ULONGLONG Low;
LONGLONG High;
} DT_NEON128;
typedef DECLSPEC_ALIGN(8) struct {
//
// Control flags.
//
DWORD ContextFlags;
//
// Integer registers
//
DWORD R0;
DWORD R1;
DWORD R2;
DWORD R3;
DWORD R4;
DWORD R5;
DWORD R6;
DWORD R7;
DWORD R8;
DWORD R9;
DWORD R10;
DWORD R11;
DWORD R12;
//
// Control Registers
//
DWORD Sp;
DWORD Lr;
DWORD Pc;
DWORD Cpsr;
//
// Floating Point/NEON Registers
//
DWORD Fpscr;
DWORD Padding;
union {
DT_NEON128 Q[16];
ULONGLONG D[32];
DWORD S[32];
} DUMMYUNIONNAME;
//
// Debug registers
//
DWORD Bvr[DT_ARM_MAX_BREAKPOINTS];
DWORD Bcr[DT_ARM_MAX_BREAKPOINTS];
DWORD Wvr[DT_ARM_MAX_WATCHPOINTS];
DWORD Wcr[DT_ARM_MAX_WATCHPOINTS];
DWORD Padding2[2];
} DT_CONTEXT;
#elif defined(DTCONTEXT_IS_ARM64)
#define DT_CONTEXT_ARM64 0x00400000L
#define DT_CONTEXT_CONTROL (DT_CONTEXT_ARM64 | 0x1L)
#define DT_CONTEXT_INTEGER (DT_CONTEXT_ARM64 | 0x2L)
#define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_ARM64 | 0x4L)
#define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_ARM64 | 0x8L)
#define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT)
#define DT_CONTEXT_ALL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT | DT_CONTEXT_DEBUG_REGISTERS)
#define DT_ARM64_MAX_BREAKPOINTS 8
#define DT_ARM64_MAX_WATCHPOINTS 2
typedef struct {
ULONGLONG Low;
LONGLONG High;
} DT_NEON128;
typedef DECLSPEC_ALIGN(16) struct {
//
// Control flags.
//
/* +0x000 */ DWORD ContextFlags;
//
// Integer registers
//
/* +0x004 */ DWORD Cpsr; // NZVF + DAIF + CurrentEL + SPSel
/* +0x008 */ union {
struct {
DWORD64 X0;
DWORD64 X1;
DWORD64 X2;
DWORD64 X3;
DWORD64 X4;
DWORD64 X5;
DWORD64 X6;
DWORD64 X7;
DWORD64 X8;
DWORD64 X9;
DWORD64 X10;
DWORD64 X11;
DWORD64 X12;
DWORD64 X13;
DWORD64 X14;
DWORD64 X15;
DWORD64 X16;
DWORD64 X17;
DWORD64 X18;
DWORD64 X19;
DWORD64 X20;
DWORD64 X21;
DWORD64 X22;
DWORD64 X23;
DWORD64 X24;
DWORD64 X25;
DWORD64 X26;
DWORD64 X27;
DWORD64 X28;
};
DWORD64 X[29];
};
/* +0x0f0 */ DWORD64 Fp;
/* +0x0f8 */ DWORD64 Lr;
/* +0x100 */ DWORD64 Sp;
/* +0x108 */ DWORD64 Pc;
//
// Floating Point/NEON Registers
//
/* +0x110 */ DT_NEON128 V[32];
/* +0x310 */ DWORD Fpcr;
/* +0x314 */ DWORD Fpsr;
//
// Debug registers
//
/* +0x318 */ DWORD Bcr[DT_ARM64_MAX_BREAKPOINTS];
/* +0x338 */ DWORD64 Bvr[DT_ARM64_MAX_BREAKPOINTS];
/* +0x378 */ DWORD Wcr[DT_ARM64_MAX_WATCHPOINTS];
/* +0x380 */ DWORD64 Wvr[DT_ARM64_MAX_WATCHPOINTS];
/* +0x390 */
} DT_CONTEXT;
#else
#error Unsupported platform
#endif
#endif // __DBG_TARGET_CONTEXT_INCLUDED

Просмотреть файл

@ -11,6 +11,10 @@
#ifndef __LLDBSERVICES_H__
#define __LLDBSERVICES_H__
#include <stdarg.h>
#include <palrt.h>
#include <unknwn.h>
#ifdef __cplusplus
extern "C" {
#endif

Просмотреть файл

@ -1,222 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// Contains some definitions duplicated from pal.h, palrt.h, rpc.h,
// etc. because they have various conflicits with the linux standard
// runtime h files like wchar_t, memcpy, etc.
#include <stdarg.h>
#include <string.h>
#include <pal_mstypes.h>
#define MAX_PATH 260
#define MAX_LONGPATH 1024 /* max. length of full pathname */
// Platform-specific library naming
//
#ifdef __APPLE__
#define MAKEDLLNAME_W(name) u"lib" name u".dylib"
#define MAKEDLLNAME_A(name) "lib" name ".dylib"
#elif defined(_AIX)
#define MAKEDLLNAME_W(name) L"lib" name L".a"
#define MAKEDLLNAME_A(name) "lib" name ".a"
#elif defined(__hppa__) || defined(_IA64_)
#define MAKEDLLNAME_W(name) L"lib" name L".sl"
#define MAKEDLLNAME_A(name) "lib" name ".sl"
#else
#define MAKEDLLNAME_W(name) u"lib" name u".so"
#define MAKEDLLNAME_A(name) "lib" name ".so"
#endif
#define interface struct
typedef GUID IID;
#ifdef __cplusplus
#define REFGUID const GUID &
#else
#define REFGUID const GUID *
#endif
typedef GUID *LPGUID;
typedef const GUID FAR *LPCGUID;
#ifdef __cplusplus
extern "C++" {
#if !defined _SYS_GUID_OPERATOR_EQ_ && !defined _NO_SYS_GUID_OPERATOR_EQ_
#define _SYS_GUID_OPERATOR_EQ_
inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
{ return !memcmp(&rguid1, &rguid2, sizeof(GUID)); }
inline int operator==(REFGUID guidOne, REFGUID guidOther)
{ return IsEqualGUID(guidOne,guidOther); }
inline int operator!=(REFGUID guidOne, REFGUID guidOther)
{ return !IsEqualGUID(guidOne,guidOther); }
#endif
};
#endif // __cplusplus
#ifdef __cplusplus
#define REFIID const IID &
#else
#define REFIID const IID *
#endif
#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
#ifndef _DECLSPEC_DEFINED_
#define _DECLSPEC_DEFINED_
#if defined(_MSC_VER)
#define DECLSPEC_NOVTABLE __declspec(novtable)
#define DECLSPEC_IMPORT __declspec(dllimport)
#define DECLSPEC_SELECTANY __declspec(selectany)
#elif defined(__GNUC__)
#define DECLSPEC_NOVTABLE
#define DECLSPEC_IMPORT
#define DECLSPEC_SELECTANY __attribute__((weak))
#else
#define DECLSPEC_NOVTABLE
#define DECLSPEC_IMPORT
#define DECLSPEC_SELECTANY
#endif
#if defined(_MSC_VER) || defined(__llvm__)
#define DECLSPEC_ALIGN(x) __declspec(align(x))
#else
#define DECLSPEC_ALIGN(x)
#endif
#endif // !_DECLSPEC_DEFINED_
#define DECLSPEC_UUID(x) __declspec(uuid(x))
#define MIDL_INTERFACE(x) struct DECLSPEC_UUID(x) DECLSPEC_NOVTABLE
#define STDMETHODCALLTYPE __cdecl
#define STDMETHODVCALLTYPE __cdecl
#define STDAPICALLTYPE __cdecl
#define STDAPIVCALLTYPE __cdecl
#ifdef RC_INVOKED
#define _HRESULT_TYPEDEF_(_sc) _sc
#else // RC_INVOKED
#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc)
#endif // RC_INVOKED
#define S_OK _HRESULT_TYPEDEF_(0x00000000L)
#define S_FALSE _HRESULT_TYPEDEF_(0x00000001L)
#define E_NOTIMPL _HRESULT_TYPEDEF_(0x80004001L)
#define E_NOINTERFACE _HRESULT_TYPEDEF_(0x80004002L)
#define E_UNEXPECTED _HRESULT_TYPEDEF_(0x8000FFFFL)
#define E_OUTOFMEMORY _HRESULT_TYPEDEF_(0x8007000EL)
#define E_INVALIDARG _HRESULT_TYPEDEF_(0x80070057L)
#define E_POINTER _HRESULT_TYPEDEF_(0x80004003L)
#define E_HANDLE _HRESULT_TYPEDEF_(0x80070006L)
#define E_ABORT _HRESULT_TYPEDEF_(0x80004004L)
#define E_FAIL _HRESULT_TYPEDEF_(0x80004005L)
#define E_ACCESSDENIED _HRESULT_TYPEDEF_(0x80070005L)
#define E_PENDING _HRESULT_TYPEDEF_(0x8000000AL)
#define EXCEPTION_MAXIMUM_PARAMETERS 15
typedef struct _EXCEPTION_RECORD64 {
DWORD ExceptionCode;
ULONG ExceptionFlags;
ULONG64 ExceptionRecord;
ULONG64 ExceptionAddress;
ULONG NumberParameters;
ULONG __unusedAlignment;
ULONG64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD64, *PEXCEPTION_RECORD64;
#include <unknwn.h>
#ifndef FORCEINLINE
#if _MSC_VER < 1200
#define FORCEINLINE inline
#else
#define FORCEINLINE __forceinline
#endif
#endif
FORCEINLINE void PAL_ArmInterlockedOperationBarrier()
{
#ifdef _ARM64_
// On arm64, most of the __sync* functions generate a code sequence like:
// loop:
// ldaxr (load acquire exclusive)
// ...
// stlxr (store release exclusive)
// cbnz loop
//
// It is possible for a load following the code sequence above to be reordered to occur prior to the store above due to the
// release barrier, this is substantiated by https://github.com/dotnet/coreclr/pull/17508. Interlocked operations in the PAL
// require the load to occur after the store. This memory barrier should be used following a call to a __sync* function to
// prevent that reordering. Code generated for arm32 includes a 'dmb' after 'cbnz', so no issue there at the moment.
__sync_synchronize();
#endif // _ARM64_
}
/*++
Function:
InterlockedIncrement
The InterlockedIncrement function increments (increases by one) the
value of the specified variable and checks the resulting value. The
function prevents more than one thread from using the same variable
simultaneously.
Parameters
lpAddend
[in/out] Pointer to the variable to increment.
Return Values
The return value is the resulting incremented value.
--*/
EXTERN_C
PALIMPORT
inline
LONG
PALAPI
InterlockedIncrement(
IN OUT LONG volatile *lpAddend)
{
LONG result = __sync_add_and_fetch(lpAddend, (LONG)1);
PAL_ArmInterlockedOperationBarrier();
return result;
}
/*++
Function:
InterlockedDecrement
The InterlockedDecrement function decrements (decreases by one) the
value of the specified variable and checks the resulting value. The
function prevents more than one thread from using the same variable
simultaneously.
Parameters
lpAddend
[in/out] Pointer to the variable to decrement.
Return Values
The return value is the resulting decremented value.
--*/
EXTERN_C
PALIMPORT
inline
LONG
PALAPI
InterlockedDecrement(
IN OUT LONG volatile *lpAddend)
{
LONG result = __sync_sub_and_fetch(lpAddend, (LONG)1);
PAL_ArmInterlockedOperationBarrier();
return result;
}

Просмотреть файл

@ -1,721 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
/*++
--*/
////////////////////////////////////////////////////////////////////////
// Extensions to the usual posix header files
////////////////////////////////////////////////////////////////////////
#ifndef __PAL_MSTYPES_H__
#define __PAL_MSTYPES_H__
#ifdef __cplusplus
extern "C" {
#endif
////////////////////////////////////////////////////////////////////////
// calling convention stuff
////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif // __cplusplus
#ifndef _MSC_VER
// Note: Win32-hosted GCC predefines __stdcall and __cdecl, but Unix-
// hosted GCC does not.
#ifdef __i386__
#if !defined(__stdcall)
#define __stdcall __attribute__((stdcall))
#endif
#if !defined(_stdcall)
#define _stdcall __stdcall
#endif
#if !defined(__cdecl)
#define __cdecl __attribute__((cdecl))
#endif
#if !defined(_cdecl)
#define _cdecl __cdecl
#endif
#if !defined(CDECL)
#define CDECL __cdecl
#endif
#else // !defined(__i386__)
#define __stdcall
#define _stdcall
#define __cdecl
#define _cdecl
#define CDECL
// On ARM __fastcall is ignored and causes a compile error
#if !defined(PAL_STDCPP_COMPAT) || defined(__arm__)
# undef __fastcall
# undef _fastcall
# define __fastcall
# define _fastcall
#endif // !defined(PAL_STDCPP_COMPAT) || defined(__arm__)
#endif // !defined(__i386__)
#define CALLBACK __cdecl
#if !defined(_declspec)
#define _declspec(e) __declspec(e)
#endif
#if defined(_VAC_) && defined(__cplusplus)
#define __inline inline
#endif
#define __forceinline inline
#endif // !_MSC_VER
#ifdef _MSC_VER
#if defined(PAL_IMPLEMENTATION)
#define PALIMPORT
#else
#define PALIMPORT __declspec(dllimport)
#endif
#define PAL_NORETURN __declspec(noreturn)
#else
#define PALIMPORT
#define PAL_NORETURN __attribute__((noreturn))
#endif
#define PALAPI __cdecl
#define PALAPIV __cdecl
////////////////////////////////////////////////////////////////////////
// Type attribute stuff
////////////////////////////////////////////////////////////////////////
#define CONST const
#define IN
#define OUT
#define OPTIONAL
#define FAR
#ifdef UNICODE
#define __TEXT(x) L##x
#else
#define __TEXT(x) x
#endif
#define TEXT(x) __TEXT(x)
////////////////////////////////////////////////////////////////////////
// Some special values
////////////////////////////////////////////////////////////////////////
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
////////////////////////////////////////////////////////////////////////
// Misc. type helpers
////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
// MSVC's way of declaring large integer constants
// If you define these in one step, without the _HELPER macros, you
// get extra whitespace when composing these with other concatenating macros.
#define I64_HELPER(x) x ## i64
#define I64(x) I64_HELPER(x)
#define UI64_HELPER(x) x ## ui64
#define UI64(x) UI64_HELPER(x)
#else // _MSC_VER
// GCC's way of declaring large integer constants
// If you define these in one step, without the _HELPER macros, you
// get extra whitespace when composing these with other concatenating macros.
#define I64_HELPER(x) x ## LL
#define I64(x) I64_HELPER(x)
#define UI64_HELPER(x) x ## ULL
#define UI64(x) UI64_HELPER(x)
#endif // _MSC_VER
////////////////////////////////////////////////////////////////////////
// Misc. types
////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER
// A bunch of source files (e.g. most of the ndp tree) include pal.h
// but are written to be LLP64, not LP64. (LP64 => long = 64 bits
// LLP64 => longs = 32 bits, long long = 64 bits)
//
// To handle this difference, we #define long to be int (and thus 32 bits) when
// compiling those files. (See the bottom of this file or search for
// #define long to see where we do this.)
//
// But this fix is more complicated than it seems, because we also use the
// preprocessor to #define __int64 to long for LP64 architectures (__int64
// isn't a builtin in gcc). We don't want __int64 to be an int (by cascading
// macro rules). So we play this little trick below where we add
// __cppmungestrip before "long", which is what we're really #defining __int64
// to. The preprocessor sees __cppmungestriplong as something different than
// long, so it doesn't replace it with int. The during the cppmunge phase, we
// remove the __cppmungestrip part, leaving long for the compiler to see.
//
// Note that we can't just use a typedef to define __int64 as long before
// #defining long because typedefed types can't be signedness-agnostic (i.e.
// they must be either signed or unsigned) and we want to be able to use
// __int64 as though it were intrinsic
#ifdef BIT64
#define __int64 long
#else // BIT64
#define __int64 long long
#endif // BIT64
#define __int32 int
#define __int16 short int
#define __int8 char // assumes char is signed
#endif // _MSC_VER
#ifndef PAL_STDCPP_COMPAT
// Defined in gnu's types.h. For non PAL_IMPLEMENTATION system
// includes are not included, so we need to define them.
#ifndef PAL_IMPLEMENTATION
// OS X already defines these types in 64 bit
#if !defined(_TARGET_MAC64)
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
#endif
#endif // PAL_IMPLEMENTATION
#ifndef _MSC_VER
#if _WIN64
typedef long double LONG_DOUBLE;
#endif
#endif // _MSC_VER
#endif // !PAL_STDCPP_COMPAT
typedef void VOID;
typedef int LONG; // NOTE: diff from windows.h, for LP64 compat
typedef unsigned int ULONG; // NOTE: diff from windows.h, for LP64 compat
typedef __int64 LONGLONG;
typedef unsigned __int64 ULONGLONG;
typedef ULONGLONG DWORD64;
typedef DWORD64 *PDWORD64;
typedef LONGLONG *PLONG64;
typedef ULONGLONG *PULONG64;
typedef ULONGLONG *PULONGLONG;
typedef ULONG *PULONG;
typedef short SHORT;
typedef SHORT *PSHORT;
typedef unsigned short USHORT;
typedef USHORT *PUSHORT;
typedef unsigned char UCHAR;
typedef UCHAR *PUCHAR;
typedef char *PSZ;
typedef ULONGLONG DWORDLONG;
typedef unsigned int DWORD; // NOTE: diff from windows.h, for LP64 compat
typedef unsigned int DWORD32, *PDWORD32;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef float FLOAT;
typedef double DOUBLE;
typedef BOOL *PBOOL;
typedef BOOL *LPBOOL;
typedef BYTE *PBYTE;
typedef BYTE *LPBYTE;
typedef const BYTE *LPCBYTE;
typedef int *PINT;
typedef int *LPINT;
typedef WORD *PWORD;
typedef WORD *LPWORD;
typedef LONG *LPLONG;
typedef LPLONG PLONG;
typedef DWORD *PDWORD;
typedef DWORD *LPDWORD;
typedef void *PVOID;
typedef void *LPVOID;
typedef CONST void *LPCVOID;
typedef int INT;
typedef unsigned int UINT;
typedef unsigned int *PUINT;
typedef BYTE BOOLEAN;
typedef BOOLEAN *PBOOLEAN;
typedef unsigned __int8 UINT8;
typedef signed __int8 INT8;
typedef unsigned __int16 UINT16;
typedef signed __int16 INT16;
typedef unsigned __int32 UINT32, *PUINT32;
typedef signed __int32 INT32, *PINT32;
typedef unsigned __int64 UINT64, *PUINT64;
typedef signed __int64 INT64, *PINT64;
typedef unsigned __int32 ULONG32, *PULONG32;
typedef signed __int32 LONG32, *PLONG32;
typedef unsigned __int64 ULONG64;
typedef signed __int64 LONG64;
#if defined(_X86_) && _MSC_VER >= 1300
#define _W64 __w64
#else
#define _W64
#endif
#ifdef BIT64
#define _atoi64 (__int64)atoll
typedef __int64 INT_PTR, *PINT_PTR;
typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
typedef __int64 LONG_PTR, *PLONG_PTR;
typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
typedef unsigned __int64 DWORD_PTR, *PDWORD_PTR;
/* maximum signed 64 bit value */
#define LONG_PTR_MAX I64(9223372036854775807)
/* maximum unsigned 64 bit value */
#define ULONG_PTR_MAX UI64(0xffffffffffffffff)
#ifndef SIZE_MAX
#define SIZE_MAX _UI64_MAX
#endif
#define __int3264 __int64
#if !defined(BIT64)
__inline
unsigned long
HandleToULong(
const void *h
)
{
return((unsigned long) (ULONG_PTR) h );
}
__inline
long
HandleToLong(
const void *h
)
{
return((long) (LONG_PTR) h );
}
__inline
void *
ULongToHandle(
const unsigned long h
)
{
return((void *) (UINT_PTR) h );
}
__inline
void *
LongToHandle(
const long h
)
{
return((void *) (INT_PTR) h );
}
__inline
unsigned long
PtrToUlong(
const void *p
)
{
return((unsigned long) (ULONG_PTR) p );
}
__inline
unsigned int
PtrToUint(
const void *p
)
{
return((unsigned int) (UINT_PTR) p );
}
__inline
unsigned short
PtrToUshort(
const void *p
)
{
return((unsigned short) (unsigned long) (ULONG_PTR) p );
}
__inline
long
PtrToLong(
const void *p
)
{
return((long) (LONG_PTR) p );
}
__inline
int
PtrToInt(
const void *p
)
{
return((int) (INT_PTR) p );
}
__inline
short
PtrToShort(
const void *p
)
{
return((short) (long) (LONG_PTR) p );
}
__inline
void *
IntToPtr(
const int i
)
// Caution: IntToPtr() sign-extends the int value.
{
return( (void *)(INT_PTR)i );
}
__inline
void *
UIntToPtr(
const unsigned int ui
)
// Caution: UIntToPtr() zero-extends the unsigned int value.
{
return( (void *)(UINT_PTR)ui );
}
__inline
void *
LongToPtr(
const long l
)
// Caution: LongToPtr() sign-extends the long value.
{
return( (void *)(LONG_PTR)l );
}
__inline
void *
ULongToPtr(
const unsigned long ul
)
// Caution: ULongToPtr() zero-extends the unsigned long value.
{
return( (void *)(ULONG_PTR)ul );
}
__inline
void *
ShortToPtr(
const short s
)
// Caution: ShortToPtr() sign-extends the short value.
{
return( (void *)(INT_PTR)s );
}
__inline
void *
UShortToPtr(
const unsigned short us
)
// Caution: UShortToPtr() zero-extends the unsigned short value.
{
return( (void *)(UINT_PTR)us );
}
#else // !defined(BIT64)
#define HandleToULong( h ) ((ULONG)(ULONG_PTR)(h) )
#define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )
#define ULongToHandle( ul ) ((HANDLE)(ULONG_PTR) (ul) )
#define LongToHandle( h ) ((HANDLE)(LONG_PTR) (h) )
#define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )
#define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )
#define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )
#define PtrToInt( p ) ((INT)(INT_PTR) (p) )
#define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )
#define PtrToShort( p ) ((short)(LONG_PTR)(p) )
#define IntToPtr( i ) ((VOID *)(INT_PTR)((int)(i)))
#define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)(ui)))
#define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)(l)))
#define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)(ul)))
#define ShortToPtr( s ) ((VOID *)(INT_PTR)((short)(s)))
#define UShortToPtr( us ) ((VOID *)(UINT_PTR)((unsigned short)(s)))
#endif // !defined(BIT64)
#else
typedef _W64 __int32 INT_PTR;
typedef _W64 unsigned __int32 UINT_PTR;
typedef _W64 __int32 LONG_PTR;
typedef _W64 unsigned __int32 ULONG_PTR, *PULONG_PTR;
typedef _W64 unsigned __int32 DWORD_PTR, *PDWORD_PTR;
/* maximum signed 32 bit value */
#define LONG_PTR_MAX 2147483647L
/* maximum unsigned 32 bit value */
#define ULONG_PTR_MAX 0xffffffffUL
#ifndef SIZE_MAX
#define SIZE_MAX UINT_MAX
#endif
#define __int3264 __int32
#define HandleToULong( h ) ((ULONG)(ULONG_PTR)(h) )
#define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )
#define ULongToHandle( ul ) ((HANDLE)(ULONG_PTR) (ul) )
#define LongToHandle( h ) ((HANDLE)(LONG_PTR) (h) )
#define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )
#define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )
#define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )
#define PtrToInt( p ) ((INT)(INT_PTR) (p) )
#define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )
#define PtrToShort( p ) ((short)(LONG_PTR)(p) )
#define IntToPtr( i ) ((VOID *)(INT_PTR)((int)i))
#define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)ui))
#define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)l))
#define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)ul))
#define ShortToPtr( s ) ((VOID *)(INT_PTR)((short)s))
#define UShortToPtr( us ) ((VOID *)(UINT_PTR)((unsigned short)s))
#endif
#define HandleToUlong(h) HandleToULong(h)
#define UlongToHandle(ul) ULongToHandle(ul)
#define UlongToPtr(ul) ULongToPtr(ul)
#define UintToPtr(ui) UIntToPtr(ui)
typedef ULONG_PTR SIZE_T, *PSIZE_T;
typedef LONG_PTR SSIZE_T, *PSSIZE_T;
#ifndef SIZE_T_MAX
#define SIZE_T_MAX ULONG_PTR_MAX
#endif // SIZE_T_MAX
#ifndef SSIZE_T_MAX
#define SSIZE_T_MAX LONG_PTR_MAX
#endif
#ifndef SSIZE_T_MIN
#define SSIZE_T_MIN I64(0x8000000000000000)
#endif
#ifndef PAL_STDCPP_COMPAT
#if defined(__APPLE_CC__) || defined(__linux__)
#ifdef BIT64
typedef unsigned long size_t;
typedef long ptrdiff_t;
#else // !BIT64
typedef unsigned int size_t;
typedef int ptrdiff_t;
#endif // !BIT64
#else
typedef ULONG_PTR size_t;
typedef LONG_PTR ptrdiff_t;
#endif
#endif // !PAL_STDCPP_COMPAT
#define _SIZE_T_DEFINED
typedef LONG_PTR LPARAM;
#define _PTRDIFF_T_DEFINED
#ifdef _MINGW_
// We need to define _PTRDIFF_T to make sure ptrdiff_t doesn't get defined
// again by system headers - but only for MinGW.
#define _PTRDIFF_T
#endif
#ifdef PAL_STDCPP_COMPAT
#ifdef BIT64
typedef unsigned long int uintptr_t;
#else // !BIT64
typedef unsigned int uintptr_t;
#endif // !BIT64
typedef char16_t WCHAR;
#else // PAL_STDCPP_COMPAT
typedef wchar_t WCHAR;
#if defined(__linux__)
#ifdef BIT64
typedef long int intptr_t;
typedef unsigned long int uintptr_t;
#else // !BIT64
typedef int intptr_t;
typedef unsigned int uintptr_t;
#endif // !BIT64
#else
typedef INT_PTR intptr_t;
typedef UINT_PTR uintptr_t;
#endif
#endif // PAL_STDCPP_COMPAT
#define _INTPTR_T_DEFINED
#define _UINTPTR_T_DEFINED
typedef DWORD LCID;
typedef PDWORD PLCID;
typedef WORD LANGID;
typedef DWORD LCTYPE;
typedef WCHAR *PWCHAR;
typedef WCHAR *LPWCH, *PWCH;
typedef CONST WCHAR *LPCWCH, *PCWCH;
typedef WCHAR *NWPSTR;
typedef WCHAR *LPWSTR, *PWSTR;
typedef CONST WCHAR *LPCWSTR, *PCWSTR;
typedef char CHAR;
typedef CHAR *PCHAR;
typedef CHAR *LPCH, *PCH;
typedef CONST CHAR *LPCCH, *PCCH;
typedef CHAR *NPSTR;
typedef CHAR *LPSTR, *PSTR;
typedef CONST CHAR *LPCSTR, *PCSTR;
#ifdef UNICODE
typedef WCHAR TCHAR;
typedef WCHAR _TCHAR;
#else
typedef CHAR TCHAR;
typedef CHAR _TCHAR;
#endif
typedef TCHAR *PTCHAR;
typedef TCHAR *LPTSTR, *PTSTR;
typedef CONST TCHAR *LPCTSTR;
#define MAKEWORD(a, b) ((WORD)(((BYTE)((DWORD_PTR)(a) & 0xff)) | ((WORD)((BYTE)((DWORD_PTR)(b) & 0xff))) << 8))
#define MAKELONG(a, b) ((LONG)(((WORD)((DWORD_PTR)(a) & 0xffff)) | ((DWORD)((WORD)((DWORD_PTR)(b) & 0xffff))) << 16))
#define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff))
#define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16))
#define LOBYTE(w) ((BYTE)((DWORD_PTR)(w) & 0xff))
#define HIBYTE(w) ((BYTE)((DWORD_PTR)(w) >> 8))
typedef VOID *HANDLE;
typedef HANDLE HWND;
typedef struct __PAL_RemoteHandle__ { HANDLE h; } *RHANDLE;
typedef HANDLE *PHANDLE;
typedef HANDLE *LPHANDLE;
#define INVALID_HANDLE_VALUE ((VOID *)(-1))
#define INVALID_FILE_SIZE ((DWORD)0xFFFFFFFF)
#define INVALID_FILE_ATTRIBUTES ((DWORD) -1)
typedef HANDLE HMODULE;
typedef HANDLE HINSTANCE;
typedef HANDLE HGLOBAL;
typedef HANDLE HLOCAL;
typedef HANDLE HRSRC;
typedef LONG HRESULT;
typedef LONG NTSTATUS;
typedef union _LARGE_INTEGER {
struct {
#if BIGENDIAN
LONG HighPart;
DWORD LowPart;
#else
DWORD LowPart;
LONG HighPart;
#endif
} u;
LONGLONG QuadPart;
} LARGE_INTEGER, *PLARGE_INTEGER;
#ifndef GUID_DEFINED
typedef struct _GUID {
ULONG Data1; // NOTE: diff from Win32, for LP64
USHORT Data2;
USHORT Data3;
UCHAR Data4[ 8 ];
} GUID;
typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;
/* Code Page Default Values */
#define CP_ACP 0 /* default to ANSI code page */
#define CP_OEMCP 1 /* default to OEM code page */
#define CP_MACCP 2 /* default to MAC code page */
#define CP_THREAD_ACP 3 /* current thread's ANSI code page */
#define CP_WINUNICODE 1200
#define CP_UNICODE 1200 /* Unicode */
#define CP_UNICODESWAP 1201 /* Unicode Big-Endian */
#define CP_UTF7 65000 /* UTF-7 translation */
#define CP_UTF8 65001 /* UTF-8 translation */
typedef PVOID PSID;
#ifdef __cplusplus
}
#endif
#endif // __PAL_MSTYPES_H__

Просмотреть файл

@ -1,64 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
//
// ===========================================================================
// File: unknwn.h
//
// ===========================================================================
// simplified unknwn.h for PAL
#ifndef __IUnknown_INTERFACE_DEFINED__
#define __IUnknown_INTERFACE_DEFINED__
typedef interface IUnknown IUnknown;
typedef /* [unique] */ IUnknown *LPUNKNOWN;
// 00000000-0000-0000-C000-000000000046
EXTERN_C const IID IID_IUnknown;
MIDL_INTERFACE("00000000-0000-0000-C000-000000000046")
IUnknown
{
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void **ppvObject) = 0;
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
template<class Q>
HRESULT
STDMETHODCALLTYPE
QueryInterface(Q** pp)
{
return QueryInterface(__uuidof(Q), (void **)pp);
}
};
#endif // __IUnknown_INTERFACE_DEFINED__
#ifndef __IClassFactory_INTERFACE_DEFINED__
#define __IClassFactory_INTERFACE_DEFINED__
// 00000001-0000-0000-C000-000000000046
EXTERN_C const IID IID_IClassFactory;
MIDL_INTERFACE("00000001-0000-0000-C000-000000000046")
IClassFactory : public IUnknown
{
virtual HRESULT STDMETHODCALLTYPE CreateInstance(
IUnknown *pUnkOuter,
REFIID riid,
void **ppvObject) = 0;
virtual HRESULT STDMETHODCALLTYPE LockServer(
BOOL fLock) = 0;
};
#endif // __IClassFactory_INTERFACE_DEFINED__

Просмотреть файл

@ -0,0 +1,27 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// Contains some definitions duplicated from pal.h, palrt.h, rpc.h,
// etc. because they have various conflicits with the linux standard
// runtime h files like wchar_t, memcpy, etc.
#include <pal_mstypes.h>
#define MAX_PATH 260
// Platform-specific library naming
//
#ifdef __APPLE__
#define MAKEDLLNAME_W(name) u"lib" name u".dylib"
#define MAKEDLLNAME_A(name) "lib" name ".dylib"
#elif defined(_AIX)
#define MAKEDLLNAME_W(name) L"lib" name L".a"
#define MAKEDLLNAME_A(name) "lib" name ".a"
#elif defined(__hppa__) || defined(_IA64_)
#define MAKEDLLNAME_W(name) L"lib" name L".sl"
#define MAKEDLLNAME_A(name) "lib" name ".sl"
#else
#define MAKEDLLNAME_W(name) u"lib" name u".so"
#define MAKEDLLNAME_A(name) "lib" name ".so"
#endif

Просмотреть файл

@ -7,12 +7,14 @@
#include "sosplugin.h"
#include <string.h>
#include <string>
#include <dlfcn.h>
#define CONVERT_FROM_SIGN_EXTENDED(offset) ((ULONG_PTR)(offset))
ULONG g_currentThreadIndex = -1;
ULONG g_currentThreadSystemId = -1;
char *g_coreclrDirectory;
char *g_pluginModuleDirectory;
LLDBServices::LLDBServices(lldb::SBDebugger &debugger, lldb::SBCommandReturnObject &returnObject, lldb::SBProcess *process, lldb::SBThread *thread) :
m_ref(1),
@ -77,6 +79,21 @@ LLDBServices::Release()
PCSTR
LLDBServices::GetCoreClrDirectory()
{
if (g_coreclrDirectory == nullptr)
{
const char *coreclrModule = MAKEDLLNAME_A("coreclr");
const char *directory = GetModuleDirectory(coreclrModule);
if (directory != nullptr)
{
std::string path(directory);
path.append("/");
g_coreclrDirectory = strdup(path.c_str());
}
else
{
Output(DEBUG_OUTPUT_WARNING, "The %s module is not loaded yet in the target process\n", coreclrModule);
}
}
return g_coreclrDirectory;
}
@ -1744,3 +1761,32 @@ LLDBServices::GetCurrentFrame()
return frame;
}
void
DummyFunction()
{
}
PCSTR
LLDBServices::GetPluginModuleDirectory()
{
if (g_pluginModuleDirectory == nullptr)
{
Dl_info info;
if (dladdr((void *)&DummyFunction, &info) != 0)
{
std::string path(info.dli_fname);
// Parse off the module name to get just the path
size_t lastSlash = path.rfind('/');
if (lastSlash != std::string::npos)
{
path.erase(lastSlash);
path.append("/");
g_pluginModuleDirectory = strdup(path.c_str());
}
}
}
return g_pluginModuleDirectory;
}

Просмотреть файл

@ -271,4 +271,6 @@ public:
PCSTR GetModuleDirectory(
PCSTR name);
PCSTR GetPluginModuleDirectory();
};

Просмотреть файл

@ -23,7 +23,7 @@ public:
{
if (arguments[0] == NULL)
{
result.Printf("Load path for sos/dac/dbi: '%s'\n", g_coreclrDirectory == NULL ? "<none>" : g_coreclrDirectory);
result.Printf("Load path for dac/dbi: '%s'\n", g_coreclrDirectory == NULL ? "<none>" : g_coreclrDirectory);
}
else {
if (g_coreclrDirectory != NULL)
@ -38,7 +38,7 @@ public:
}
g_coreclrDirectory = strdup(path.c_str());
result.Printf("Set load path for sos/dac/dbi to '%s'\n", g_coreclrDirectory);
result.Printf("Set load path for dac/dbi to '%s'\n", g_coreclrDirectory);
}
return result.Succeeded();
}
@ -48,6 +48,6 @@ bool
setclrpathCommandInitialize(lldb::SBDebugger debugger)
{
lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
lldb::SBCommand command = interpreter.AddCommand("setclrpath", new setclrpathCommand(), "Set the path to load coreclr sos/dac/dbi files. setclrpath <path>");
lldb::SBCommand command = interpreter.AddCommand("setclrpath", new setclrpathCommand(), "Set the path to load coreclr dac/dbi files. setclrpath <path>");
return true;
}

Просмотреть файл

@ -12,11 +12,17 @@ class sosCommand : public lldb::SBCommandPluginInterface
const char *m_command;
void *m_sosHandle;
// If true, use the directory that libsosplugin is in to load
// libsos, otherwise (if false) use the libcoreclr module
// directory (legacy behavior).
bool m_usePluginDirectory;
public:
sosCommand(const char *command)
{
m_command = command;
m_sosHandle = NULL;
m_usePluginDirectory = true;
}
virtual bool
@ -27,7 +33,7 @@ public:
LLDBServices* services = new LLDBServices(debugger, result);
LoadSos(services);
if (m_sosHandle)
if (m_sosHandle != NULL)
{
const char* sosCommand = m_command;
if (sosCommand == NULL)
@ -74,37 +80,33 @@ public:
{
if (m_sosHandle == NULL)
{
if (g_coreclrDirectory == NULL)
if (m_usePluginDirectory)
{
const char *coreclrModule = MAKEDLLNAME_A("coreclr");
const char *directory = services->GetModuleDirectory(coreclrModule);
if (directory != NULL)
const char *loadDirectory = services->GetPluginModuleDirectory();
if (loadDirectory != NULL)
{
std::string path(directory);
path.append("/");
g_coreclrDirectory = strdup(path.c_str());
}
else
{
services->Output(DEBUG_OUTPUT_WARNING, "The %s module is not loaded yet in the target process\n", coreclrModule);
m_sosHandle = LoadModule(services, loadDirectory, MAKEDLLNAME_A("sos"));
}
}
if (g_coreclrDirectory != NULL)
else
{
// Load the DAC module first explicitly because SOS and DBI
// have implicit references to the DAC's PAL.
LoadModule(services, MAKEDLLNAME_A("mscordaccore"));
const char *loadDirectory = services->GetCoreClrDirectory();
if (loadDirectory != NULL)
{
// Load the DAC module first explicitly because SOS and DBI
// have implicit references to the DAC's PAL.
LoadModule(services, loadDirectory, MAKEDLLNAME_A("mscordaccore"));
m_sosHandle = LoadModule(services, MAKEDLLNAME_A("sos"));
m_sosHandle = LoadModule(services, loadDirectory, MAKEDLLNAME_A("sos"));
}
}
}
}
void *
LoadModule(LLDBServices *services, const char *moduleName)
LoadModule(LLDBServices *services, const char *loadDirectory, const char *moduleName)
{
std::string modulePath(g_coreclrDirectory);
std::string modulePath(loadDirectory);
modulePath.append(moduleName);
void *moduleHandle = dlopen(modulePath.c_str(), RTLD_NOW);
@ -128,6 +130,7 @@ sosCommandInitialize(lldb::SBDebugger debugger)
interpreter.AddCommand("createdump", new sosCommand("CreateDump"), "Create a xplat minidump.");
interpreter.AddCommand("clru", new sosCommand("u"), "Displays an annotated disassembly of a managed method.");
interpreter.AddCommand("dumpclass", new sosCommand("DumpClass"), "Displays information about a EE class structure at the specified address.");
interpreter.AddCommand("dumpdomain", new sosCommand("DumpDomain"), "Displays information all the AppDomains and all assemblies within the domains.");
interpreter.AddCommand("dumpheap", new sosCommand("DumpHeap"), "Displays info about the garbage-collected heap and collection statistics about objects.");
interpreter.AddCommand("dumpil", new sosCommand("DumpIL"), "Displays the Microsoft intermediate language (MSIL) that is associated with a managed method.");
interpreter.AddCommand("dumplog", new sosCommand("DumpLog"), "Writes the contents of an in-memory stress log to the specified file.");
@ -148,6 +151,7 @@ sosCommandInitialize(lldb::SBDebugger debugger)
interpreter.AddCommand("histobj", new sosCommand("HistObj"), "Examines all stress log relocation records and displays the chain of garbage collection relocations that may have led to the address passed in as an argument.");
interpreter.AddCommand("histobjfind", new sosCommand("HistObjFind"), "Displays all the log entries that reference an object at the specified address.");
interpreter.AddCommand("histroot", new sosCommand("HistRoot"), "Displays information related to both promotions and relocations of the specified root.");
interpreter.AddCommand("sethostruntime", new sosCommand("SetHostRuntime"), "Sets or displays the .NET Core runtime directory to use to run managed code in SOS.");
interpreter.AddCommand("soshelp", new sosCommand("Help"), "Displays all available commands when no parameter is specified, or displays detailed help information about the specified command. soshelp <command>");
return true;
}

Просмотреть файл

@ -3,8 +3,8 @@
// See the LICENSE file in the project root for more information.
#include <lldb/API/LLDB.h>
#include "mstypes.h"
#define DEFINE_EXCEPTION_RECORD
#include <pal.h>
#include <lldbservices.h>
#include <dbgtargetcontext.h>
#include "services.h"

Просмотреть файл

@ -1,24 +1,24 @@
Testing libsosplugin
=====================================
**Test assembly**
Compile test assembly file using any C# compiler you have, for example:
- `gmcs test.cs`
- `corerun csc.exe /nologo /r:System.Private.CoreLib.dll test.cs`
**Running tests**
Make sure that python's lldb module is accessible. To run the tests, use the following command:
`python2 test_libsosplugin.py --corerun=corerun --sosplugin=sosplugin --assembly=assembly --timeout=timeout`
The test.sh and testsos.sh scripts launches these tests and makes the following a lot easier.
Make sure that python's lldb module is accessible. To run the tests manually, use the following command:
`python2 test_libsosplugin.py --lldb <path-to-lldb> --host <path-to-host> --plugin <path-to-sosplugin> --logfiledir <path-to-logdir> --assembly <path-to-testdebuggee>`
- `lldb` is a path to `lldb` to run
- `clrdir` is a directory with `corerun` and sosplugin
- `assembly` is a compiled test assembly (e.g. Test.exe)
- `host` is a path to .NET Core host like `corerun` or `dotnet`
- `plugin` is the path to the lldb sos plugin
- `logfiledir` is the path to put the log files
- `assembly` is a compiled test assembly (e.g. TestDebuggee.dll)
- `timeout` is a deadline for a single test (in seconds)
- `regex` is a regular expression matching tests to run
- `repeat` is a number of passes for each test
Log files for both failed and passed tests are `*.log` and `*.log.2` for standard output and error correspondingly.

Просмотреть файл

@ -6,7 +6,7 @@ import lldb
import re
import testutils as test
# bpmd -clearall
# bpmd -clear
def runScenario(assembly, debugger, target):
@ -30,10 +30,10 @@ def runScenario(assembly, debugger, target):
# Output is not empty
# Should be at least 'Adding pending breakpoints...'
test.assertTrue(len(out_msg) > 0)
test.assertTrue(res.GetOutputSize() > 0)
# Error message is empty
test.assertTrue(len(err_msg) == 0)
test.assertTrue(res.GetErrorSize() == 0)
# Delete the first breakpoint
@ -50,15 +50,15 @@ def runScenario(assembly, debugger, target):
test.assertTrue(match)
# Error message is empty
test.assertEqual(err_msg, '')
test.assertTrue(res.GetErrorSize() == 0)
process.Continue()
# Process must be exited
test.assertEqual(process.GetState(), lldb.eStateExited)
test.assertEqual(process.GetState(), lldb.eStateStopped)
# The reason of this stop must be a breakpoint
test.assertEqual(process.GetSelectedThread().GetStopReason(),
lldb.eStopReasonNone)
lldb.eStopReasonBreakpoint)
#

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше