зеркало из https://github.com/dotnet/diagnostics.git
Add the managed SOS code.
Using the Roslyn repo tool set to build (for now).
This commit is contained in:
Родитель
a2ce91d916
Коммит
ad99d3facd
|
@ -0,0 +1,49 @@
|
|||
###############################################################################
|
||||
# Set default behavior to:
|
||||
# automatically normalize line endings on check-in, and
|
||||
# convert to Windows-style line endings on check-out
|
||||
###############################################################################
|
||||
* text=auto encoding=UTF-8
|
||||
*.sh text eol=lf
|
||||
|
||||
###############################################################################
|
||||
# Set file behavior to:
|
||||
# treat as text, and
|
||||
# diff as C# source code
|
||||
###############################################################################
|
||||
*.cs text diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set file behavior to:
|
||||
# treat as text
|
||||
###############################################################################
|
||||
*.cmd text
|
||||
*.config text
|
||||
*.csproj text
|
||||
*.groovy text
|
||||
*.json text
|
||||
*.md text
|
||||
*.nuspec text
|
||||
*.pkgdef text
|
||||
*.proj text
|
||||
*.projitems text
|
||||
*.props text
|
||||
*.ps1 text
|
||||
*.resx text
|
||||
*.ruleset text
|
||||
*.shproj text
|
||||
*.sln text
|
||||
*.targets text
|
||||
*.vb text
|
||||
*.vbproj text
|
||||
*.vcxproj text
|
||||
*.vcxproj.filters text
|
||||
*.vsct text
|
||||
*.vsixmanifest text
|
||||
|
||||
###############################################################################
|
||||
# Set file behavior to:
|
||||
# treat as binary
|
||||
###############################################################################
|
||||
*.png binary
|
||||
*.snk binary
|
|
@ -1,60 +1,29 @@
|
|||
syntax: glob
|
||||
|
||||
[Bb]inaries/
|
||||
|
||||
# Build tools related files
|
||||
/[Tt]ools/
|
||||
|
||||
### VisualStudio ###
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
*.swp
|
||||
.vs/
|
||||
*.VC.db
|
||||
|
||||
# Build results
|
||||
[Aa]rtifacts/
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
msbuild.log
|
||||
.dotnet/
|
||||
.packages/
|
||||
.tools/
|
||||
|
||||
# add back architecture directories ignored in 'Build results'
|
||||
!tests/x86
|
||||
!src/mscorlib/src/System/Runtime/Intrinsics/X86
|
||||
!tests/src/JIT/HardwareIntrinsics/X86
|
||||
|
||||
# Visual Studio 2015
|
||||
.vs/
|
||||
|
||||
# Visual Studio 2015 Pre-CTP6
|
||||
*.sln.ide
|
||||
*.ide/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
#NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
# Per-user project properties
|
||||
launchSettings.json
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
|
@ -62,7 +31,6 @@ dlldata.c
|
|||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
|
@ -70,45 +38,34 @@ dlldata.c
|
|||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.html
|
||||
*.wrn
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.log
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding addin-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
@ -117,106 +74,28 @@ _TeamCity*
|
|||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
*.nuget.g.props
|
||||
*.nuget.g.targets
|
||||
*.nuget.cache
|
||||
**/packages/*
|
||||
project.lock.json
|
||||
project.assets.json
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.[Pp]ublish.xml
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
*.metaproj
|
||||
*.metaproj.tmp
|
||||
.atom-build.json
|
||||
tags
|
||||
TAGS
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
App_Data/*.mdf
|
||||
App_Data/*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# C/C++ extension for Visual Studio Code
|
||||
browse.VC.db
|
||||
|
||||
# Local settings folder for Visual Studio Code
|
||||
.vscode/
|
||||
|
||||
### MonoDevelop ###
|
||||
|
||||
*.pidb
|
||||
*.userprefs
|
||||
|
||||
### Windows ###
|
||||
# =========================
|
||||
# Windows detritus
|
||||
# =========================
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
|
@ -228,95 +107,5 @@ Desktop.ini
|
|||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# Common binary extensions on Windows
|
||||
*.exe
|
||||
*.dll
|
||||
*.lib
|
||||
|
||||
### Linux ###
|
||||
|
||||
*~
|
||||
\#*\#
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
### OSX ###
|
||||
|
||||
# Mac desktop service store files
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear on external disk
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# We have some checked in prebuilt generated files
|
||||
!src/pal/prebuilt/idl/*_i.c
|
||||
|
||||
# Valid 'debug' folder, that contains CLR debugging code
|
||||
!src/debug
|
||||
|
||||
# Ignore folders created by the test build
|
||||
TestWrappers_x64_[d|D]ebug
|
||||
TestWrappers_x64_[c|C]hecked
|
||||
TestWrappers_x64_[r|R]elease
|
||||
TestWrappers_x86_[d|D]ebug
|
||||
TestWrappers_x86_[c|C]hecked
|
||||
TestWrappers_x86_[r|R]elease
|
||||
TestWrappers_arm_[d|D]ebug
|
||||
TestWrappers_arm_[c|C]hecked
|
||||
TestWrappers_arm_[r|R]elease
|
||||
TestWrappers_arm64_[d|D]ebug
|
||||
TestWrappers_arm64_[c|C]hecked
|
||||
TestWrappers_arm64_[r|R]elease
|
||||
tests/src/common/test_runtime/project.json
|
||||
|
||||
Vagrantfile
|
||||
.vagrant
|
||||
|
||||
# CMake files
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
CMakeCache.txt
|
||||
Makefile
|
||||
|
||||
# Cross compilation
|
||||
cross/rootfs/*
|
||||
cross/android-rootfs/*
|
||||
# add x86 as it is ignored in 'Build results'
|
||||
!cross/x86
|
||||
|
||||
#python import files
|
||||
*.pyc
|
||||
|
||||
# JIT32 files
|
||||
src/jit32
|
||||
|
||||
# performance testing sandbox
|
||||
sandbox
|
||||
|
||||
#IL linker for testing
|
||||
linker
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
powershell -ExecutionPolicy ByPass -command "& """%~dp0eng\common\Build.ps1""" -restore -build %*"
|
||||
exit /b %ErrorLevel%
|
|
@ -0,0 +1,12 @@
|
|||
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<RepositoryUrl>https://github.com/dotnet/diagnostics.git</RepositoryUrl>
|
||||
<RepositoryRawUrl>$(RepositoryUrl)</RepositoryRawUrl>
|
||||
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
|
||||
<PackageLicenseUrl>http://go.microsoft.com/fwlink/?LinkId=529443</PackageLicenseUrl>
|
||||
<PackageIconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</PackageIconUrl>
|
||||
<IsPublishable>false</IsPublishable>
|
||||
<NoPackageAnalysis>true</NoPackageAnalysis>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<!-- Only specify feed for RepoToolset SDK (see https://github.com/Microsoft/msbuild/issues/2982) -->
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="roslyn-tools" value="https://dotnet.myget.org/F/roslyn-tools/api/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
powershell -ExecutionPolicy ByPass -command "& """%~dp0eng\common\Build.ps1""" -restore %*"
|
||||
exit /b %ErrorLevel%
|
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
powershell -ExecutionPolicy ByPass -command "& """%~dp0eng\common\Build.ps1""" -test %*"
|
||||
exit /b %ErrorLevel%
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source="${BASH_SOURCE[0]}"
|
||||
|
||||
# resolve $SOURCE until the file is no longer a symlink
|
||||
while [[ -h $source ]]; do
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
source="$(readlink "$source")"
|
||||
|
||||
# if $source was a relative symlink, we need to resolve it relative to the path where the
|
||||
# symlink file was located
|
||||
[[ $source != /* ]] && source="$scriptroot/$source"
|
||||
done
|
||||
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
"$scriptroot/eng/common/build.sh" --build --restore $@
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2005
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SOS.NETCore", "src\SOS\NETCore\SOS.NETCore.csproj", "{20513BA2-A156-4A17-4C70-5AC2DBD4F833}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{20513BA2-A156-4A17-4C70-5AC2DBD4F833}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{20513BA2-A156-4A17-4C70-5AC2DBD4F833}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{20513BA2-A156-4A17-4C70-5AC2DBD4F833}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{20513BA2-A156-4A17-4C70-5AC2DBD4F833}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {46465737-C938-44FC-BE1A-4CE139EBB5E0}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"sign": [
|
||||
{
|
||||
"certificate": "MicrosoftSHA2",
|
||||
"strongName": "MsSharedLib72",
|
||||
"values": [
|
||||
"bin/SOS.NETCore/netcoreapp1.0/SOS.NETCore.dll",
|
||||
]
|
||||
},
|
||||
{
|
||||
"certificate": "NuGet",
|
||||
"strongName": null,
|
||||
"values": [
|
||||
"packages/*.nupkg"
|
||||
]
|
||||
}
|
||||
],
|
||||
"exclude": [
|
||||
"Microsoft.FileFormats.dll",
|
||||
"Microsoft.SymbolStore.dll",
|
||||
"System.Collections.Immutable.dll",
|
||||
"System.Net.Http.dll",
|
||||
"System.Reflection.Metadata.dll",
|
||||
]
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
|
||||
<!-- This repo version -->
|
||||
<VersionPrefix>1.0.0</VersionPrefix>
|
||||
<PreReleaseVersionLabel>beta</PreReleaseVersionLabel>
|
||||
|
||||
<UsingToolNetFrameworkReferenceAssemblies>true</UsingToolNetFrameworkReferenceAssemblies>
|
||||
<UsingToolXliff>false</UsingToolXliff>
|
||||
|
||||
<!-- CoreFX -->
|
||||
<SystemReflectionMetadataVersion>1.6.0-preview2-26406-04</SystemReflectionMetadataVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<RestoreSources>
|
||||
$(RestoreSources);
|
||||
https://dotnet.myget.org/F/symstore/api/v3/index.json;
|
||||
https://dotnet.myget.org/F/roslyn-tools/api/v3/index.json;
|
||||
https://dotnet.myget.org/F/dotnet-core/api/v3/index.json
|
||||
</RestoreSources>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
powershell -ExecutionPolicy ByPass -command "& """%~dp0Build.ps1""" -restore -build -test -sign -pack -ci %*"
|
||||
exit /b %ErrorLevel%
|
|
@ -0,0 +1,252 @@
|
|||
[CmdletBinding(PositionalBinding=$false)]
|
||||
Param(
|
||||
[string] $configuration = "Debug",
|
||||
[string] $solution = "",
|
||||
[string] $verbosity = "minimal",
|
||||
[switch] $restore,
|
||||
[switch] $deployDeps,
|
||||
[switch] $build,
|
||||
[switch] $rebuild,
|
||||
[switch] $deploy,
|
||||
[switch] $test,
|
||||
[switch] $integrationTest,
|
||||
[switch] $sign,
|
||||
[switch] $pack,
|
||||
[switch] $ci,
|
||||
[switch] $prepareMachine,
|
||||
[switch] $help,
|
||||
[Parameter(ValueFromRemainingArguments=$true)][String[]]$properties
|
||||
)
|
||||
|
||||
set-strictmode -version 2.0
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
function Print-Usage() {
|
||||
Write-Host "Common settings:"
|
||||
Write-Host " -configuration <value> Build configuration Debug, Release"
|
||||
Write-Host " -verbosity <value> Msbuild verbosity (q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic])"
|
||||
Write-Host " -help Print help and exit"
|
||||
Write-Host ""
|
||||
|
||||
Write-Host "Actions:"
|
||||
Write-Host " -restore Restore dependencies"
|
||||
Write-Host " -build Build solution"
|
||||
Write-Host " -rebuild Rebuild solution"
|
||||
Write-Host " -deploy Deploy built VSIXes"
|
||||
Write-Host " -deployDeps Deploy dependencies (e.g. VSIXes for integration tests)"
|
||||
Write-Host " -test Run all unit tests in the solution"
|
||||
Write-Host " -integrationTest Run all integration tests in the solution"
|
||||
Write-Host " -sign Sign build outputs"
|
||||
Write-Host " -pack Package build outputs into NuGet packages and Willow components"
|
||||
Write-Host ""
|
||||
|
||||
Write-Host "Advanced settings:"
|
||||
Write-Host " -solution <value> Path to solution to build"
|
||||
Write-Host " -ci Set when running on CI server"
|
||||
Write-Host " -prepareMachine Prepare machine for CI run"
|
||||
Write-Host ""
|
||||
Write-Host "Command line arguments not listed above are passed thru to msbuild."
|
||||
Write-Host "The above arguments can be shortened as much as to be unambiguous (e.g. -co for configuration, -t for test, etc.)."
|
||||
}
|
||||
|
||||
if ($help -or (($properties -ne $null) -and ($properties.Contains("/help") -or $properties.Contains("/?")))) {
|
||||
Print-Usage
|
||||
exit 0
|
||||
}
|
||||
|
||||
function Create-Directory([string[]] $path) {
|
||||
if (!(Test-Path $path)) {
|
||||
New-Item -path $path -force -itemType "Directory" | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
function InitializeDotNetCli {
|
||||
# Don't resolve runtime, shared framework, or SDK from other locations to ensure build determinism
|
||||
$env:DOTNET_MULTILEVEL_LOOKUP=0
|
||||
|
||||
# Disable first run since we do not need all ASP.NET packages restored.
|
||||
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
|
||||
|
||||
# Source Build uses DotNetCoreSdkDir variable
|
||||
if ($env:DotNetCoreSdkDir -ne $null) {
|
||||
$env:DOTNET_INSTALL_DIR = $env:DotNetCoreSdkDir
|
||||
}
|
||||
|
||||
# Use dotnet installation specified in DOTNET_INSTALL_DIR if it contains the required SDK version,
|
||||
# otherwise install the dotnet CLI and SDK to repo local .dotnet directory to avoid potential permission issues.
|
||||
if (($env:DOTNET_INSTALL_DIR -ne $null) -and (Test-Path(Join-Path $env:DOTNET_INSTALL_DIR "sdk\$($GlobalJson.sdk.version)"))) {
|
||||
$dotnetRoot = $env:DOTNET_INSTALL_DIR
|
||||
} else {
|
||||
$dotnetRoot = Join-Path $RepoRoot ".dotnet"
|
||||
$env:DOTNET_INSTALL_DIR = $dotnetRoot
|
||||
|
||||
if ($restore) {
|
||||
InstallDotNetCli $dotnetRoot
|
||||
}
|
||||
}
|
||||
|
||||
$global:BuildDriver = Join-Path $dotnetRoot "dotnet.exe"
|
||||
$global:BuildArgs = "msbuild"
|
||||
}
|
||||
|
||||
function InstallDotNetCli([string] $dotnetRoot) {
|
||||
$installScript = "$dotnetRoot\dotnet-install.ps1"
|
||||
if (!(Test-Path $installScript)) {
|
||||
Create-Directory $dotnetRoot
|
||||
Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile $installScript
|
||||
}
|
||||
|
||||
& $installScript -Version $GlobalJson.sdk.version -InstallDir $dotnetRoot
|
||||
if ($lastExitCode -ne 0) {
|
||||
Write-Host "Failed to install dotnet cli (exit code '$lastExitCode')." -ForegroundColor Red
|
||||
exit $lastExitCode
|
||||
}
|
||||
}
|
||||
|
||||
function InitializeVisualStudioBuild {
|
||||
$inVSEnvironment = !($env:VS150COMNTOOLS -eq $null) -and (Test-Path $env:VS150COMNTOOLS)
|
||||
|
||||
if ($inVSEnvironment) {
|
||||
$vsInstallDir = Join-Path $env:VS150COMNTOOLS "..\.."
|
||||
} else {
|
||||
$vsInstallDir = LocateVisualStudio
|
||||
|
||||
$env:VS150COMNTOOLS = Join-Path $vsInstallDir "Common7\Tools\"
|
||||
$env:VSSDK150Install = Join-Path $vsInstallDir "VSSDK\"
|
||||
$env:VSSDKInstall = Join-Path $vsInstallDir "VSSDK\"
|
||||
}
|
||||
|
||||
$global:BuildDriver = Join-Path $vsInstallDir "MSBuild\15.0\Bin\msbuild.exe"
|
||||
$global:BuildArgs = "/nodeReuse:$(!$ci)"
|
||||
}
|
||||
|
||||
function LocateVisualStudio {
|
||||
$vswhereVersion = $GlobalJson.vswhere.version
|
||||
$toolsRoot = Join-Path $RepoRoot ".tools"
|
||||
$vsWhereDir = Join-Path $toolsRoot "vswhere\$vswhereVersion"
|
||||
$vsWhereExe = Join-Path $vsWhereDir "vswhere.exe"
|
||||
|
||||
if (!(Test-Path $vsWhereExe)) {
|
||||
Create-Directory $vsWhereDir
|
||||
Write-Host "Downloading vswhere"
|
||||
Invoke-WebRequest "https://github.com/Microsoft/vswhere/releases/download/$vswhereVersion/vswhere.exe" -OutFile $vswhereExe
|
||||
}
|
||||
|
||||
$vsInstallDir = & $vsWhereExe -latest -prerelease -property installationPath -requires Microsoft.Component.MSBuild -requires Microsoft.VisualStudio.Component.VSSDK -requires Microsoft.Net.Component.4.6.TargetingPack -requires Microsoft.VisualStudio.Component.Roslyn.Compiler -requires Microsoft.VisualStudio.Component.VSSDK
|
||||
|
||||
if ($lastExitCode -ne 0) {
|
||||
Write-Host "Failed to locate Visual Studio (exit code '$lastExitCode')." -ForegroundColor Red
|
||||
exit $lastExitCode
|
||||
}
|
||||
|
||||
return $vsInstallDir
|
||||
}
|
||||
|
||||
function InitializeToolset {
|
||||
$toolsetVersion = $GlobalJson.'msbuild-sdks'.'RoslynTools.RepoToolset'
|
||||
$toolsetLocationFile = Join-Path $ToolsetDir "$toolsetVersion.txt"
|
||||
|
||||
if (Test-Path $toolsetLocationFile) {
|
||||
$path = Get-Content $toolsetLocationFile
|
||||
if (Test-Path $path) {
|
||||
$global:ToolsetBuildProj = $path
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $restore) {
|
||||
Write-Host "Toolset version $toolsetVersion has not been restored."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$proj = Join-Path $ToolsetDir "restore.proj"
|
||||
|
||||
'<Project Sdk="RoslynTools.RepoToolset"/>' | Set-Content $proj
|
||||
& $BuildDriver $BuildArgs $proj /t:__WriteToolsetLocation /m /nologo /clp:None /warnaserror /bl:$ToolsetRestoreLog /v:$verbosity /p:__ToolsetLocationOutputFile=$toolsetLocationFile
|
||||
|
||||
if ($lastExitCode -ne 0) {
|
||||
Write-Host "Failed to restore toolset (exit code '$lastExitCode')." -Color Red
|
||||
Write-Host "Build log: $ToolsetRestoreLog" -ForegroundColor DarkGray
|
||||
exit $lastExitCode
|
||||
}
|
||||
|
||||
$global:ToolsetBuildProj = Get-Content $toolsetLocationFile
|
||||
}
|
||||
|
||||
function Build {
|
||||
& $BuildDriver $BuildArgs $ToolsetBuildProj /m /nologo /clp:Summary /warnaserror /v:$verbosity /bl:$Log /p:Configuration=$configuration /p:Projects=$solution /p:RepoRoot=$RepoRoot /p:Restore=$restore /p:DeployDeps=$deployDeps /p:Build=$build /p:Rebuild=$rebuild /p:Deploy=$deploy /p:Test=$test /p:IntegrationTest=$integrationTest /p:Sign=$sign /p:Pack=$pack /p:CIBuild=$ci $properties
|
||||
if ($lastExitCode -ne 0) {
|
||||
Write-Host "Build log: $Log" -ForegroundColor DarkGray
|
||||
exit $lastExitCode
|
||||
}
|
||||
}
|
||||
|
||||
function Stop-Processes() {
|
||||
Write-Host "Killing running build processes..."
|
||||
Get-Process -Name "msbuild" -ErrorAction SilentlyContinue | Stop-Process
|
||||
Get-Process -Name "dotnet" -ErrorAction SilentlyContinue | Stop-Process
|
||||
Get-Process -Name "vbcscompiler" -ErrorAction SilentlyContinue | Stop-Process
|
||||
}
|
||||
|
||||
try {
|
||||
$RepoRoot = Join-Path $PSScriptRoot "..\.."
|
||||
$ArtifactsDir = Join-Path $RepoRoot "artifacts"
|
||||
$ToolsetDir = Join-Path $ArtifactsDir "toolset"
|
||||
$LogDir = Join-Path (Join-Path $ArtifactsDir $configuration) "log"
|
||||
$Log = Join-Path $LogDir "Build.binlog"
|
||||
$ToolsetRestoreLog = Join-Path $LogDir "ToolsetRestore.binlog"
|
||||
$TempDir = Join-Path (Join-Path $ArtifactsDir $configuration) "tmp"
|
||||
$GlobalJson = Get-Content(Join-Path $RepoRoot "global.json") | ConvertFrom-Json
|
||||
|
||||
if ($solution -eq "") {
|
||||
$solution = Join-Path $RepoRoot "*.sln"
|
||||
}
|
||||
|
||||
if ($env:NUGET_PACKAGES -eq $null) {
|
||||
# Use local cache on CI to ensure deterministic build,
|
||||
# use global cache in dev builds to avoid cost of downloading packages.
|
||||
$env:NUGET_PACKAGES = if ($ci) { Join-Path $RepoRoot ".packages" }
|
||||
else { Join-Path $env:UserProfile ".nuget\packages" }
|
||||
}
|
||||
|
||||
Create-Directory $ToolsetDir
|
||||
Create-Directory $LogDir
|
||||
|
||||
if ($ci) {
|
||||
Create-Directory $TempDir
|
||||
$env:TEMP = $TempDir
|
||||
$env:TMP = $TempDir
|
||||
}
|
||||
|
||||
# Presence of vswhere.version indicates the repo needs to build using VS msbuild
|
||||
if ((Get-Member -InputObject $GlobalJson -Name "vswhere") -ne $null) {
|
||||
InitializeVisualStudioBuild
|
||||
} elseif ((Get-Member -InputObject $GlobalJson -Name "sdk") -ne $null) {
|
||||
InitializeDotNetCli
|
||||
} else {
|
||||
Write-Host "/global.json must either specify 'sdk.version' or 'vswhere.version'." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($ci) {
|
||||
Write-Host "Using $BuildDriver"
|
||||
}
|
||||
|
||||
InitializeToolset
|
||||
|
||||
Build
|
||||
}
|
||||
catch {
|
||||
Write-Host $_
|
||||
Write-Host $_.Exception
|
||||
Write-Host $_.ScriptStackTrace
|
||||
exit 1
|
||||
}
|
||||
finally {
|
||||
Pop-Location
|
||||
if ($ci -and $prepareMachine) {
|
||||
Stop-Processes
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source="${BASH_SOURCE[0]}"
|
||||
|
||||
# resolve $source until the file is no longer a symlink
|
||||
while [[ -h "$source" ]]; do
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
source="$(readlink "$source")"
|
||||
# if $source was a relative symlink, we need to resolve it relative to the path where the
|
||||
# symlink file was located
|
||||
[[ $source != /* ]] && source="$scriptroot/$source"
|
||||
done
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
|
||||
build=false
|
||||
ci=false
|
||||
configuration='Debug'
|
||||
help=false
|
||||
pack=false
|
||||
prepare_machine=false
|
||||
rebuild=false
|
||||
restore=false
|
||||
sign=false
|
||||
solution=''
|
||||
test=false
|
||||
verbosity='minimal'
|
||||
properties=''
|
||||
|
||||
repo_root="$scriptroot/../.."
|
||||
artifacts_dir="$repo_root/artifacts"
|
||||
artifacts_configuration_dir="$artifacts_dir/$configuration"
|
||||
toolset_dir="$artifacts_dir/toolset"
|
||||
log_dir="$artifacts_configuration_dir/log"
|
||||
log="$log_dir/Build.binlog"
|
||||
toolset_restore_log="$log_dir/ToolsetRestore.binlog"
|
||||
temp_dir="$artifacts_configuration_dir/tmp"
|
||||
|
||||
global_json_file="$repo_root/global.json"
|
||||
build_driver=""
|
||||
toolset_build_proj=""
|
||||
|
||||
while (($# > 0)); do
|
||||
lowerI="$(echo $1 | awk '{print tolower($0)}')"
|
||||
case $lowerI in
|
||||
--build)
|
||||
build=true
|
||||
shift 1
|
||||
;;
|
||||
--ci)
|
||||
ci=true
|
||||
shift 1
|
||||
;;
|
||||
--configuration)
|
||||
configuration=$2
|
||||
shift 2
|
||||
;;
|
||||
--help)
|
||||
echo "Common settings:"
|
||||
echo " --configuration <value> Build configuration Debug, Release"
|
||||
echo " --verbosity <value> Msbuild verbosity (q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic])"
|
||||
echo " --help Print help and exit"
|
||||
echo ""
|
||||
echo "Actions:"
|
||||
echo " --restore Restore dependencies"
|
||||
echo " --build Build solution"
|
||||
echo " --rebuild Rebuild solution"
|
||||
echo " --test Run all unit tests in the solution"
|
||||
echo " --sign Sign build outputs"
|
||||
echo " --pack Package build outputs into NuGet packages and Willow components"
|
||||
echo ""
|
||||
echo "Advanced settings:"
|
||||
echo " --solution <value> Path to solution to build"
|
||||
echo " --ci Set when running on CI server"
|
||||
echo " --prepareMachine Prepare machine for CI run"
|
||||
echo ""
|
||||
echo "Command line arguments not listed above are passed through to MSBuild."
|
||||
exit 0
|
||||
;;
|
||||
--pack)
|
||||
pack=true
|
||||
shift 1
|
||||
;;
|
||||
--preparemachine)
|
||||
prepare_machine=true
|
||||
shift 1
|
||||
;;
|
||||
--rebuild)
|
||||
rebuild=true
|
||||
shift 1
|
||||
;;
|
||||
--restore)
|
||||
restore=true
|
||||
shift 1
|
||||
;;
|
||||
--sign)
|
||||
sign=true
|
||||
shift 1
|
||||
;;
|
||||
--solution)
|
||||
solution=$2
|
||||
shift 2
|
||||
;;
|
||||
--test)
|
||||
test=true
|
||||
shift 1
|
||||
;;
|
||||
--verbosity)
|
||||
verbosity=$2
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
properties="$properties $1"
|
||||
shift 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 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;
|
||||
}
|
||||
|
||||
function InitializeDotNetCli {
|
||||
# Disable first run since we want to control all package sources
|
||||
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
|
||||
|
||||
# Don't resolve runtime, shared framework, or SDK from other locations to ensure build determinism
|
||||
export DOTNET_MULTILEVEL_LOOKUP=0
|
||||
|
||||
# Source Build uses DotNetCoreSdkDir variable
|
||||
if [[ -n "$DotNetCoreSdkDir" ]]; then
|
||||
export DOTNET_INSTALL_DIR="$DotNetCoreSdkDir"
|
||||
fi
|
||||
|
||||
ReadJson "$global_json_file" "version"
|
||||
local dotnet_sdk_version="$readjsonvalue"
|
||||
local dotnet_root=""
|
||||
|
||||
# Use dotnet installation specified in DOTNET_INSTALL_DIR if it contains the required SDK version,
|
||||
# otherwise install the dotnet CLI and SDK to repo local .dotnet directory to avoid potential permission issues.
|
||||
if [[ -d "$DOTNET_INSTALL_DIR/sdk/$dotnet_sdk_version" ]]; then
|
||||
dotnet_root="$DOTNET_INSTALL_DIR"
|
||||
else
|
||||
dotnet_root="$repo_root/.dotnet"
|
||||
export DOTNET_INSTALL_DIR="$dotnet_root"
|
||||
|
||||
if [[ "$restore" == true ]]; then
|
||||
InstallDotNetCli $dotnet_root $dotnet_sdk_version
|
||||
fi
|
||||
fi
|
||||
|
||||
build_driver="$dotnet_root/dotnet"
|
||||
}
|
||||
|
||||
function InstallDotNetCli {
|
||||
local dotnet_root=$1
|
||||
local dotnet_sdk_version=$2
|
||||
local dotnet_install_script="$dotnet_root/dotnet-install.sh"
|
||||
|
||||
if [[ ! -a "$dotnet_install_script" ]]; then
|
||||
mkdir -p "$dotnet_root"
|
||||
|
||||
# Use curl if available, otherwise use wget
|
||||
if command -v curl > /dev/null; then
|
||||
curl "https://dot.net/v1/dotnet-install.sh" -sSL --retry 10 --create-dirs -o "$dotnet_install_script"
|
||||
else
|
||||
wget -q -O "$dotnet_install_script" "https://dot.net/v1/dotnet-install.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
bash "$dotnet_install_script" --version $dotnet_sdk_version --install-dir $dotnet_root
|
||||
local lastexitcode=$?
|
||||
|
||||
if [[ $lastexitcode != 0 ]]; then
|
||||
echo "Failed to install dotnet cli (exit code '$lastexitcode')."
|
||||
ExitWithExitCode $lastexitcode
|
||||
fi
|
||||
}
|
||||
|
||||
function InitializeToolset {
|
||||
ReadJson $global_json_file "RoslynTools.RepoToolset"
|
||||
local toolset_version=$readjsonvalue
|
||||
local toolset_location_file="$toolset_dir/$toolset_version.txt"
|
||||
|
||||
if [[ -a "$toolset_location_file" ]]; then
|
||||
local path=`cat $toolset_location_file`
|
||||
if [[ -a "$path" ]]; then
|
||||
toolset_build_proj=$path
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$restore" != true ]]; then
|
||||
echo "Toolset version $toolsetVersion has not been restored."
|
||||
ExitWithExitCode 2
|
||||
fi
|
||||
|
||||
local proj="$toolset_dir/restore.proj"
|
||||
|
||||
echo '<Project Sdk="RoslynTools.RepoToolset"/>' > $proj
|
||||
"$build_driver" msbuild $proj /t:__WriteToolsetLocation /m /nologo /clp:None /warnaserror /bl:$toolset_restore_log /v:$verbosity /p:__ToolsetLocationOutputFile=$toolset_location_file
|
||||
local lastexitcode=$?
|
||||
|
||||
if [[ $lastexitcode != 0 ]]; then
|
||||
echo "Failed to restore toolset (exit code '$lastexitcode'). See log: $toolset_restore_log"
|
||||
ExitWithExitCode $lastexitcode
|
||||
fi
|
||||
|
||||
toolset_build_proj=`cat $toolset_location_file`
|
||||
}
|
||||
|
||||
function Build {
|
||||
"$build_driver" msbuild $toolset_build_proj /m /nologo /clp:Summary /warnaserror \
|
||||
/v:$verbosity /bl:$log /p:Configuration=$configuration /p:Projects=$solution /p:RepoRoot="$repo_root" \
|
||||
/p:Restore=$restore /p:Build=$build /p:Rebuild=$rebuild /p:Deploy=$deploy /p:Test=$test /p:Sign=$sign /p:Pack=$pack /p:CIBuild=$ci \
|
||||
$properties
|
||||
local lastexitcode=$?
|
||||
|
||||
if [[ $lastexitcode != 0 ]]; then
|
||||
echo "Failed to build $toolset_build_proj"
|
||||
ExitWithExitCode $lastexitcode
|
||||
fi
|
||||
}
|
||||
|
||||
function ExitWithExitCode {
|
||||
if [[ "$ci" == true && "$prepare_machine" == true ]]; then
|
||||
StopProcesses
|
||||
fi
|
||||
exit $1
|
||||
}
|
||||
|
||||
function StopProcesses {
|
||||
echo "Killing running build processes..."
|
||||
pkill -9 "dotnet"
|
||||
pkill -9 "vbcscompiler"
|
||||
}
|
||||
|
||||
function Main {
|
||||
# HOME may not be defined in some scenarios, but it is required by NuGet
|
||||
if [[ -z $HOME ]]; then
|
||||
export HOME="$repo_root/artifacts/.home/"
|
||||
mkdir -p "$HOME"
|
||||
fi
|
||||
|
||||
if [[ -z $solution ]]; then
|
||||
solution="$repo_root/*.sln"
|
||||
fi
|
||||
|
||||
if [[ -z $NUGET_PACKAGES ]]; then
|
||||
if [[ $ci ]]; then
|
||||
export NUGET_PACKAGES="$repo_root/.packages"
|
||||
else
|
||||
export NUGET_PACKAGES="$HOME/.nuget/packages"
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "$toolset_dir"
|
||||
mkdir -p "$log_dir"
|
||||
|
||||
if [[ $ci ]]; then
|
||||
mkdir -p "$temp_dir"
|
||||
export TEMP="$temp_dir"
|
||||
export TMP="$temp_dir"
|
||||
fi
|
||||
|
||||
InitializeDotNetCli
|
||||
InitializeToolset
|
||||
|
||||
Build
|
||||
ExitWithExitCode $?
|
||||
}
|
||||
|
||||
Main
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source="${BASH_SOURCE[0]}"
|
||||
|
||||
# resolve $SOURCE until the file is no longer a symlink
|
||||
while [[ -h $source ]]; do
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
source="$(readlink "$source")"
|
||||
|
||||
# if $source was a relative symlink, we need to resolve it relative to the path where
|
||||
# the symlink file was located
|
||||
[[ $source != /* ]] && source="$scriptroot/$source"
|
||||
done
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
|
||||
. "$scriptroot/build.sh" --restore --build --test --ci $@
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"sdk": {
|
||||
"version": "2.1.101"
|
||||
},
|
||||
"msbuild-sdks": {
|
||||
"RoslynTools.RepoToolset": "1.0.0-beta2-62810-01"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
// Groovy Script: http://www.groovy-lang.org/syntax.html
|
||||
// Jenkins DSL: https://github.com/jenkinsci/job-dsl-plugin/wiki
|
||||
|
||||
import jobs.generation.Utilities;
|
||||
|
||||
static getJobName(def opsysName, def configName) {
|
||||
return "${opsysName}_${configName}"
|
||||
}
|
||||
|
||||
static addArchival(def job, def filesToArchive, def filesToExclude) {
|
||||
def doNotFailIfNothingArchived = false
|
||||
def archiveOnlyIfSuccessful = false
|
||||
|
||||
Utilities.addArchival(job, filesToArchive, filesToExclude, doNotFailIfNothingArchived, archiveOnlyIfSuccessful)
|
||||
}
|
||||
|
||||
static addGithubPRTriggerForBranch(def job, def branchName, def jobName) {
|
||||
def prContext = "prtest/${jobName.replace('_', '/')}"
|
||||
def triggerPhrase = "(?i)^\\s*(@?dotnet-bot\\s+)?(re)?test\\s+(${prContext})(\\s+please)?\\s*\$"
|
||||
def triggerOnPhraseOnly = false
|
||||
|
||||
Utilities.addGithubPRTriggerForBranch(job, branchName, prContext, triggerPhrase, triggerOnPhraseOnly)
|
||||
}
|
||||
|
||||
static addXUnitDotNETResults(def job, def configName) {
|
||||
def resultFilePattern = "**/artifacts/${configName}/TestResults/*.xml"
|
||||
def skipIfNoTestFiles = false
|
||||
|
||||
Utilities.addXUnitDotNETResults(job, resultFilePattern, skipIfNoTestFiles)
|
||||
}
|
||||
|
||||
static addBuildSteps(def job, def projectName, def os, def configName, def isPR) {
|
||||
def buildJobName = getJobName(os, configName)
|
||||
def buildFullJobName = Utilities.getFullJobName(projectName, buildJobName, isPR)
|
||||
|
||||
job.with {
|
||||
steps {
|
||||
if (os == "Windows_NT") {
|
||||
batchFile(""".\\eng\\common\\CIBuild.cmd -configuration ${configName} -prepareMachine""")
|
||||
} else {
|
||||
shell("./eng/common/cibuild.sh --configuration ${configName} --prepareMachine")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[true, false].each { isPR ->
|
||||
['Ubuntu16.04', 'Windows_NT'].each { os ->
|
||||
['Debug', 'Release'].each { configName ->
|
||||
def projectName = GithubProject
|
||||
|
||||
def branchName = GithubBranchName
|
||||
|
||||
def filesToArchive = "**/artifacts/${configName}/**"
|
||||
|
||||
def jobName = getJobName(os, configName)
|
||||
def fullJobName = Utilities.getFullJobName(projectName, jobName, isPR)
|
||||
def myJob = job(fullJobName)
|
||||
|
||||
Utilities.standardJobSetup(myJob, projectName, isPR, "*/${branchName}")
|
||||
|
||||
if (isPR) {
|
||||
addGithubPRTriggerForBranch(myJob, branchName, jobName)
|
||||
} else {
|
||||
Utilities.addGithubPushTrigger(myJob)
|
||||
}
|
||||
|
||||
addArchival(myJob, filesToArchive, "")
|
||||
addXUnitDotNETResults(myJob, configName)
|
||||
|
||||
if (os == 'Windows_NT') {
|
||||
Utilities.setMachineAffinity(myJob, os, 'latest-dev15-3')
|
||||
} else {
|
||||
Utilities.setMachineAffinity(myJob, os, 'latest-or-auto')
|
||||
}
|
||||
|
||||
addBuildSteps(myJob, projectName, os, configName, isPR)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
powershell -ExecutionPolicy ByPass -command "& """%~dp0eng\common\Build.ps1""" -pack %*"
|
||||
exit /b %ErrorLevel%
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source="${BASH_SOURCE[0]}"
|
||||
|
||||
# resolve $SOURCE until the file is no longer a symlink
|
||||
while [[ -h $source ]]; do
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
source="$(readlink "$source")"
|
||||
|
||||
# if $source was a relative symlink, we need to resolve it relative to the path where the
|
||||
# symlink file was located
|
||||
[[ $source != /* ]] && source="$scriptroot/$source"
|
||||
done
|
||||
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
"$scriptroot/eng/common/build.sh" --restore $@
|
|
@ -0,0 +1,24 @@
|
|||
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
|
||||
<Project>
|
||||
<Import Project="..\Directory.Build.props"/>
|
||||
|
||||
<PropertyGroup>
|
||||
<LangVersion>Latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'net45'">
|
||||
<DebugType>full</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' != 'net45'">
|
||||
<DebugType>portable</DebugType>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,7 @@
|
|||
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
|
||||
<Project>
|
||||
<Target Name="PublishForPack" AfterTargets="PostBuildEvent" Condition="'$(NoPublishForPack)' != 'true' and '$(IsPackable)' == 'true'">
|
||||
<Message Importance="High" Text="Executing Publish target on $(MSBuildProjectFullPath) for $(TargetFramework)" />
|
||||
<MSBuild Targets="Publish" Projects="$(MSBuildProjectFullPath)" BuildInParallel="false" Properties="NoBuild=true;NoPublishForPack=true" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,17 @@
|
|||
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
|
||||
<Project Sdk="RoslynTools.RepoToolset">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp1.0</TargetFramework>
|
||||
<AssemblyName>SOS.NETCore</AssemblyName>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn>;1591;1701</NoWarn>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Description>Managed SOS Services</Description>
|
||||
<PackageReleaseNotes>$(Description)</PackageReleaseNotes>
|
||||
<PackageTags>SOS</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,782 @@
|
|||
// 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.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Reflection.PortableExecutable;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SOS
|
||||
{
|
||||
internal class SymbolReader
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct DebugInfo
|
||||
{
|
||||
public int lineNumber;
|
||||
public int ilOffset;
|
||||
public string fileName;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct LocalVarInfo
|
||||
{
|
||||
public int startOffset;
|
||||
public int endOffset;
|
||||
public string name;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct MethodDebugInfo
|
||||
{
|
||||
public IntPtr points;
|
||||
public int size;
|
||||
public IntPtr locals;
|
||||
public int localsSize;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read memory callback
|
||||
/// </summary>
|
||||
/// <returns>number of bytes read or 0 for error</returns>
|
||||
internal unsafe delegate int ReadMemoryDelegate(ulong address, byte* buffer, int count);
|
||||
|
||||
private sealed class OpenedReader : IDisposable
|
||||
{
|
||||
public readonly MetadataReaderProvider Provider;
|
||||
public readonly MetadataReader Reader;
|
||||
|
||||
public OpenedReader(MetadataReaderProvider provider, MetadataReader reader)
|
||||
{
|
||||
Debug.Assert(provider != null);
|
||||
Debug.Assert(reader != null);
|
||||
|
||||
Provider = provider;
|
||||
Reader = reader;
|
||||
}
|
||||
|
||||
public void Dispose() => Provider.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stream implementation to read debugger target memory for in-memory PDBs
|
||||
/// </summary>
|
||||
private class TargetStream : Stream
|
||||
{
|
||||
readonly ulong _address;
|
||||
readonly ReadMemoryDelegate _readMemory;
|
||||
|
||||
public override long Position { get; set; }
|
||||
public override long Length { get; }
|
||||
public override bool CanSeek { get { return true; } }
|
||||
public override bool CanRead { get { return true; } }
|
||||
public override bool CanWrite { get { return false; } }
|
||||
|
||||
public TargetStream(ulong address, int size, ReadMemoryDelegate readMemory)
|
||||
: base()
|
||||
{
|
||||
_address = address;
|
||||
_readMemory = readMemory;
|
||||
Length = size;
|
||||
Position = 0;
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (Position + count > Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* p = &buffer[offset])
|
||||
{
|
||||
int read = _readMemory(_address + (ulong)Position, p, count);
|
||||
Position += read;
|
||||
return read;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SeekOrigin.Begin:
|
||||
Position = offset;
|
||||
break;
|
||||
case SeekOrigin.End:
|
||||
Position = Length + offset;
|
||||
break;
|
||||
case SeekOrigin.Current:
|
||||
Position += offset;
|
||||
break;
|
||||
}
|
||||
return Position;
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quick fix for Path.GetFileName which incorrectly handles Windows-style paths on Linux
|
||||
/// </summary>
|
||||
/// <param name="pathName"> File path to be processed </param>
|
||||
/// <returns>Last component of path</returns>
|
||||
private static string GetFileName(string pathName)
|
||||
{
|
||||
int pos = pathName.LastIndexOfAny(new char[] { '/', '\\'});
|
||||
if (pos < 0)
|
||||
return pathName;
|
||||
return pathName.Substring(pos + 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks availability of debugging information for given assembly.
|
||||
/// </summary>
|
||||
/// <param name="assemblyPath">
|
||||
/// File path of the assembly or null if the module is in-memory or dynamic (generated by Reflection.Emit)
|
||||
/// </param>
|
||||
/// <param name="isFileLayout">type of in-memory PE layout, if true, file based layout otherwise, loaded layout</param>
|
||||
/// <param name="loadedPeAddress">
|
||||
/// Loaded PE image address or zero if the module is dynamic (generated by Reflection.Emit).
|
||||
/// Dynamic modules have their PDBs (if any) generated to an in-memory stream
|
||||
/// (pointed to by <paramref name="inMemoryPdbAddress"/> and <paramref name="inMemoryPdbSize"/>).
|
||||
/// </param>
|
||||
/// <param name="loadedPeSize">loaded PE image size</param>
|
||||
/// <param name="inMemoryPdbAddress">in memory PDB address or zero</param>
|
||||
/// <param name="inMemoryPdbSize">in memory PDB size</param>
|
||||
/// <returns>Symbol reader handle or zero if error</returns>
|
||||
internal static IntPtr LoadSymbolsForModule(string assemblyPath, bool isFileLayout, ulong loadedPeAddress, int loadedPeSize,
|
||||
ulong inMemoryPdbAddress, int inMemoryPdbSize, ReadMemoryDelegate readMemory)
|
||||
{
|
||||
try
|
||||
{
|
||||
TargetStream peStream = null;
|
||||
if (assemblyPath == null && loadedPeAddress != 0)
|
||||
{
|
||||
peStream = new TargetStream(loadedPeAddress, loadedPeSize, readMemory);
|
||||
}
|
||||
TargetStream pdbStream = null;
|
||||
if (inMemoryPdbAddress != 0)
|
||||
{
|
||||
pdbStream = new TargetStream(inMemoryPdbAddress, inMemoryPdbSize, readMemory);
|
||||
}
|
||||
OpenedReader openedReader = GetReader(assemblyPath, isFileLayout, peStream, pdbStream);
|
||||
if (openedReader != null)
|
||||
{
|
||||
GCHandle gch = GCHandle.Alloc(openedReader);
|
||||
return GCHandle.ToIntPtr(gch);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup and dispose of symbol reader handle
|
||||
/// </summary>
|
||||
/// <param name="symbolReaderHandle">symbol reader handle returned by LoadSymbolsForModule</param>
|
||||
internal static void Dispose(IntPtr symbolReaderHandle)
|
||||
{
|
||||
Debug.Assert(symbolReaderHandle != IntPtr.Zero);
|
||||
try
|
||||
{
|
||||
GCHandle gch = GCHandle.FromIntPtr(symbolReaderHandle);
|
||||
((OpenedReader)gch.Target).Dispose();
|
||||
gch.Free();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns method token and IL offset for given source line number.
|
||||
/// </summary>
|
||||
/// <param name="symbolReaderHandle">symbol reader handle returned by LoadSymbolsForModule</param>
|
||||
/// <param name="filePath">source file name and path</param>
|
||||
/// <param name="lineNumber">source line number</param>
|
||||
/// <param name="methodToken">method token return</param>
|
||||
/// <param name="ilOffset">IL offset return</param>
|
||||
/// <returns> true if information is available</returns>
|
||||
internal static bool ResolveSequencePoint(IntPtr symbolReaderHandle, string filePath, int lineNumber, out int methodToken, out int ilOffset)
|
||||
{
|
||||
Debug.Assert(symbolReaderHandle != IntPtr.Zero);
|
||||
methodToken = 0;
|
||||
ilOffset = 0;
|
||||
|
||||
GCHandle gch = GCHandle.FromIntPtr(symbolReaderHandle);
|
||||
MetadataReader reader = ((OpenedReader)gch.Target).Reader;
|
||||
|
||||
try
|
||||
{
|
||||
string fileName = GetFileName(filePath);
|
||||
foreach (MethodDebugInformationHandle methodDebugInformationHandle in reader.MethodDebugInformation)
|
||||
{
|
||||
MethodDebugInformation methodDebugInfo = reader.GetMethodDebugInformation(methodDebugInformationHandle);
|
||||
SequencePointCollection sequencePoints = methodDebugInfo.GetSequencePoints();
|
||||
foreach (SequencePoint point in sequencePoints)
|
||||
{
|
||||
string sourceName = reader.GetString(reader.GetDocument(point.Document).Name);
|
||||
if (point.StartLine == lineNumber && GetFileName(sourceName) == fileName)
|
||||
{
|
||||
methodToken = MetadataTokens.GetToken(methodDebugInformationHandle.ToDefinitionHandle());
|
||||
ilOffset = point.Offset;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns source line number and source file name for given IL offset and method token.
|
||||
/// </summary>
|
||||
/// <param name="symbolReaderHandle">symbol reader handle returned by LoadSymbolsForModule</param>
|
||||
/// <param name="methodToken">method token</param>
|
||||
/// <param name="ilOffset">IL offset</param>
|
||||
/// <param name="lineNumber">source line number return</param>
|
||||
/// <param name="fileName">source file name return</param>
|
||||
/// <returns> true if information is available</returns>
|
||||
internal static bool GetLineByILOffset(IntPtr symbolReaderHandle, int methodToken, long ilOffset, out int lineNumber, out IntPtr fileName)
|
||||
{
|
||||
lineNumber = 0;
|
||||
fileName = IntPtr.Zero;
|
||||
|
||||
string sourceFileName = null;
|
||||
|
||||
if (!GetSourceLineByILOffset(symbolReaderHandle, methodToken, ilOffset, out lineNumber, out sourceFileName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fileName = Marshal.StringToBSTR(sourceFileName);
|
||||
sourceFileName = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to return source line number and source file name for given IL offset and method token.
|
||||
/// </summary>
|
||||
/// <param name="symbolReaderHandle">symbol reader handle returned by LoadSymbolsForModule</param>
|
||||
/// <param name="methodToken">method token</param>
|
||||
/// <param name="ilOffset">IL offset</param>
|
||||
/// <param name="lineNumber">source line number return</param>
|
||||
/// <param name="fileName">source file name return</param>
|
||||
/// <returns> true if information is available</returns>
|
||||
private static bool GetSourceLineByILOffset(IntPtr symbolReaderHandle, int methodToken, long ilOffset, out int lineNumber, out string fileName)
|
||||
{
|
||||
Debug.Assert(symbolReaderHandle != IntPtr.Zero);
|
||||
lineNumber = 0;
|
||||
fileName = null;
|
||||
|
||||
GCHandle gch = GCHandle.FromIntPtr(symbolReaderHandle);
|
||||
MetadataReader reader = ((OpenedReader)gch.Target).Reader;
|
||||
|
||||
try
|
||||
{
|
||||
Handle handle = MetadataTokens.Handle(methodToken);
|
||||
if (handle.Kind != HandleKind.MethodDefinition)
|
||||
return false;
|
||||
|
||||
MethodDebugInformationHandle methodDebugHandle = ((MethodDefinitionHandle)handle).ToDebugInformationHandle();
|
||||
if (methodDebugHandle.IsNil)
|
||||
return false;
|
||||
|
||||
MethodDebugInformation methodDebugInfo = reader.GetMethodDebugInformation(methodDebugHandle);
|
||||
SequencePointCollection sequencePoints = methodDebugInfo.GetSequencePoints();
|
||||
|
||||
SequencePoint nearestPoint = sequencePoints.GetEnumerator().Current;
|
||||
foreach (SequencePoint point in sequencePoints)
|
||||
{
|
||||
if (point.Offset < ilOffset)
|
||||
{
|
||||
nearestPoint = point;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (point.Offset == ilOffset)
|
||||
nearestPoint = point;
|
||||
|
||||
if (nearestPoint.StartLine == 0 || nearestPoint.StartLine == SequencePoint.HiddenLine)
|
||||
return false;
|
||||
|
||||
lineNumber = nearestPoint.StartLine;
|
||||
fileName = reader.GetString(reader.GetDocument(nearestPoint.Document).Name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns local variable name for given local index and IL offset.
|
||||
/// </summary>
|
||||
/// <param name="symbolReaderHandle">symbol reader handle returned by LoadSymbolsForModule</param>
|
||||
/// <param name="methodToken">method token</param>
|
||||
/// <param name="localIndex">local variable index</param>
|
||||
/// <param name="localVarName">local variable name return</param>
|
||||
/// <returns>true if name has been found</returns>
|
||||
internal static bool GetLocalVariableName(IntPtr symbolReaderHandle, int methodToken, int localIndex, out IntPtr localVarName)
|
||||
{
|
||||
localVarName = IntPtr.Zero;
|
||||
|
||||
string localVar = null;
|
||||
if (!GetLocalVariableByIndex(symbolReaderHandle, methodToken, localIndex, out localVar))
|
||||
return false;
|
||||
|
||||
localVarName = Marshal.StringToBSTR(localVar);
|
||||
localVar = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to return local variable name for given local index and IL offset.
|
||||
/// </summary>
|
||||
/// <param name="symbolReaderHandle">symbol reader handle returned by LoadSymbolsForModule</param>
|
||||
/// <param name="methodToken">method token</param>
|
||||
/// <param name="localIndex">local variable index</param>
|
||||
/// <param name="localVarName">local variable name return</param>
|
||||
/// <returns>true if name has been found</returns>
|
||||
internal static bool GetLocalVariableByIndex(IntPtr symbolReaderHandle, int methodToken, int localIndex, out string localVarName)
|
||||
{
|
||||
Debug.Assert(symbolReaderHandle != IntPtr.Zero);
|
||||
localVarName = null;
|
||||
|
||||
GCHandle gch = GCHandle.FromIntPtr(symbolReaderHandle);
|
||||
MetadataReader reader = ((OpenedReader)gch.Target).Reader;
|
||||
|
||||
try
|
||||
{
|
||||
Handle handle = MetadataTokens.Handle(methodToken);
|
||||
if (handle.Kind != HandleKind.MethodDefinition)
|
||||
return false;
|
||||
|
||||
MethodDebugInformationHandle methodDebugHandle = ((MethodDefinitionHandle)handle).ToDebugInformationHandle();
|
||||
LocalScopeHandleCollection localScopes = reader.GetLocalScopes(methodDebugHandle);
|
||||
foreach (LocalScopeHandle scopeHandle in localScopes)
|
||||
{
|
||||
LocalScope scope = reader.GetLocalScope(scopeHandle);
|
||||
LocalVariableHandleCollection localVars = scope.GetLocalVariables();
|
||||
foreach (LocalVariableHandle varHandle in localVars)
|
||||
{
|
||||
LocalVariable localVar = reader.GetLocalVariable(varHandle);
|
||||
if (localVar.Index == localIndex)
|
||||
{
|
||||
if (localVar.Attributes == LocalVariableAttributes.DebuggerHidden)
|
||||
return false;
|
||||
|
||||
localVarName = reader.GetString(localVar.Name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
internal static bool GetLocalsInfoForMethod(string assemblyPath, int methodToken, out List<LocalVarInfo> locals)
|
||||
{
|
||||
locals = null;
|
||||
|
||||
OpenedReader openedReader = GetReader(assemblyPath, isFileLayout: true, peStream: null, pdbStream: null);
|
||||
if (openedReader == null)
|
||||
return false;
|
||||
|
||||
using (openedReader)
|
||||
{
|
||||
try
|
||||
{
|
||||
Handle handle = MetadataTokens.Handle(methodToken);
|
||||
if (handle.Kind != HandleKind.MethodDefinition)
|
||||
return false;
|
||||
|
||||
locals = new List<LocalVarInfo>();
|
||||
|
||||
MethodDebugInformationHandle methodDebugHandle =
|
||||
((MethodDefinitionHandle)handle).ToDebugInformationHandle();
|
||||
LocalScopeHandleCollection localScopes = openedReader.Reader.GetLocalScopes(methodDebugHandle);
|
||||
foreach (LocalScopeHandle scopeHandle in localScopes)
|
||||
{
|
||||
LocalScope scope = openedReader.Reader.GetLocalScope(scopeHandle);
|
||||
LocalVariableHandleCollection localVars = scope.GetLocalVariables();
|
||||
foreach (LocalVariableHandle varHandle in localVars)
|
||||
{
|
||||
LocalVariable localVar = openedReader.Reader.GetLocalVariable(varHandle);
|
||||
if (localVar.Attributes == LocalVariableAttributes.DebuggerHidden)
|
||||
continue;
|
||||
LocalVarInfo info = new LocalVarInfo();
|
||||
info.startOffset = scope.StartOffset;
|
||||
info.endOffset = scope.EndOffset;
|
||||
info.name = openedReader.Reader.GetString(localVar.Name);
|
||||
locals.Add(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns source name, line numbers and IL offsets for given method token.
|
||||
/// </summary>
|
||||
/// <param name="assemblyPath">file path of the assembly</param>
|
||||
/// <param name="methodToken">method token</param>
|
||||
/// <param name="debugInfo">structure with debug information return</param>
|
||||
/// <returns>true if information is available</returns>
|
||||
/// <remarks>used by the gdb JIT support (not SOS). Does not support in-memory PEs or PDBs</remarks>
|
||||
internal static bool GetInfoForMethod(string assemblyPath, int methodToken, ref MethodDebugInfo debugInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<DebugInfo> points = null;
|
||||
List<LocalVarInfo> locals = null;
|
||||
|
||||
if (!GetDebugInfoForMethod(assemblyPath, methodToken, out points))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetLocalsInfoForMethod(assemblyPath, methodToken, out locals))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var structSize = Marshal.SizeOf<DebugInfo>();
|
||||
|
||||
debugInfo.size = points.Count;
|
||||
var ptr = debugInfo.points;
|
||||
|
||||
foreach (var info in points)
|
||||
{
|
||||
Marshal.StructureToPtr(info, ptr, false);
|
||||
ptr = (IntPtr)(ptr.ToInt64() + structSize);
|
||||
}
|
||||
|
||||
structSize = Marshal.SizeOf<LocalVarInfo>();
|
||||
|
||||
debugInfo.localsSize = locals.Count;
|
||||
ptr = debugInfo.locals;
|
||||
|
||||
foreach (var info in locals)
|
||||
{
|
||||
Marshal.StructureToPtr(info, ptr, false);
|
||||
ptr = (IntPtr)(ptr.ToInt64() + structSize);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to return source name, line numbers and IL offsets for given method token.
|
||||
/// </summary>
|
||||
/// <param name="assemblyPath">file path of the assembly</param>
|
||||
/// <param name="methodToken">method token</param>
|
||||
/// <param name="points">list of debug information for each sequence point return</param>
|
||||
/// <returns>true if information is available</returns>
|
||||
/// <remarks>used by the gdb JIT support (not SOS). Does not support in-memory PEs or PDBs</remarks>
|
||||
private static bool GetDebugInfoForMethod(string assemblyPath, int methodToken, out List<DebugInfo> points)
|
||||
{
|
||||
points = null;
|
||||
|
||||
OpenedReader openedReader = GetReader(assemblyPath, isFileLayout: true, peStream: null, pdbStream: null);
|
||||
if (openedReader == null)
|
||||
return false;
|
||||
|
||||
using (openedReader)
|
||||
{
|
||||
try
|
||||
{
|
||||
Handle handle = MetadataTokens.Handle(methodToken);
|
||||
if (handle.Kind != HandleKind.MethodDefinition)
|
||||
return false;
|
||||
|
||||
points = new List<DebugInfo>();
|
||||
MethodDebugInformationHandle methodDebugHandle = ((MethodDefinitionHandle)handle).ToDebugInformationHandle();
|
||||
MethodDebugInformation methodDebugInfo = openedReader.Reader.GetMethodDebugInformation(methodDebugHandle);
|
||||
SequencePointCollection sequencePoints = methodDebugInfo.GetSequencePoints();
|
||||
|
||||
foreach (SequencePoint point in sequencePoints)
|
||||
{
|
||||
|
||||
DebugInfo debugInfo = new DebugInfo();
|
||||
debugInfo.lineNumber = point.StartLine;
|
||||
debugInfo.fileName = openedReader.Reader.GetString(openedReader.Reader.GetDocument(point.Document).Name);
|
||||
debugInfo.ilOffset = point.Offset;
|
||||
points.Add(debugInfo);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the portable PDB reader for the assembly path
|
||||
/// </summary>
|
||||
/// <param name="assemblyPath">file path of the assembly or null if the module is in-memory or dynamic</param>
|
||||
/// <param name="isFileLayout">type of in-memory PE layout, if true, file based layout otherwise, loaded layout</param>
|
||||
/// <param name="peStream">optional in-memory PE stream</param>
|
||||
/// <param name="pdbStream">optional in-memory PDB stream</param>
|
||||
/// <returns>reader/provider wrapper instance</returns>
|
||||
/// <remarks>
|
||||
/// Assumes that neither PE image nor PDB loaded into memory can be unloaded or moved around.
|
||||
/// </remarks>
|
||||
private static OpenedReader GetReader(string assemblyPath, bool isFileLayout, Stream peStream, Stream pdbStream)
|
||||
{
|
||||
return (pdbStream != null) ? TryOpenReaderForInMemoryPdb(pdbStream) : TryOpenReaderFromAssembly(assemblyPath, isFileLayout, peStream);
|
||||
}
|
||||
|
||||
private static OpenedReader TryOpenReaderForInMemoryPdb(Stream pdbStream)
|
||||
{
|
||||
Debug.Assert(pdbStream != null);
|
||||
|
||||
byte[] buffer = new byte[sizeof(uint)];
|
||||
if (pdbStream.Read(buffer, 0, sizeof(uint)) != sizeof(uint))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
uint signature = BitConverter.ToUInt32(buffer, 0);
|
||||
|
||||
// quick check to avoid throwing exceptions below in common cases:
|
||||
const uint ManagedMetadataSignature = 0x424A5342;
|
||||
if (signature != ManagedMetadataSignature)
|
||||
{
|
||||
// not a Portable PDB
|
||||
return null;
|
||||
}
|
||||
|
||||
OpenedReader result = null;
|
||||
MetadataReaderProvider provider = null;
|
||||
try
|
||||
{
|
||||
pdbStream.Position = 0;
|
||||
provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
|
||||
result = new OpenedReader(provider, provider.GetMetadataReader());
|
||||
}
|
||||
catch (Exception e) when (e is BadImageFormatException || e is IOException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
provider?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static OpenedReader TryOpenReaderFromAssembly(string assemblyPath, bool isFileLayout, Stream peStream)
|
||||
{
|
||||
if (assemblyPath == null && peStream == null)
|
||||
return null;
|
||||
|
||||
PEStreamOptions options = isFileLayout ? PEStreamOptions.Default : PEStreamOptions.IsLoadedImage;
|
||||
if (peStream == null)
|
||||
{
|
||||
peStream = TryOpenFile(assemblyPath);
|
||||
if (peStream == null)
|
||||
return null;
|
||||
|
||||
options = PEStreamOptions.Default;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (var peReader = new PEReader(peStream, options))
|
||||
{
|
||||
DebugDirectoryEntry codeViewEntry, embeddedPdbEntry;
|
||||
ReadPortableDebugTableEntries(peReader, out codeViewEntry, out embeddedPdbEntry);
|
||||
|
||||
// First try .pdb file specified in CodeView data (we prefer .pdb file on disk over embedded PDB
|
||||
// since embedded PDB needs decompression which is less efficient than memory-mapping the file).
|
||||
if (codeViewEntry.DataSize != 0)
|
||||
{
|
||||
var result = TryOpenReaderFromCodeView(peReader, codeViewEntry, assemblyPath);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// if it failed try Embedded Portable PDB (if available):
|
||||
if (embeddedPdbEntry.DataSize != 0)
|
||||
{
|
||||
return TryOpenReaderFromEmbeddedPdb(peReader, embeddedPdbEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (e is BadImageFormatException || e is IOException)
|
||||
{
|
||||
// nop
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void ReadPortableDebugTableEntries(PEReader peReader, out DebugDirectoryEntry codeViewEntry, out DebugDirectoryEntry embeddedPdbEntry)
|
||||
{
|
||||
// See spec: https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PE-COFF.md
|
||||
|
||||
codeViewEntry = default(DebugDirectoryEntry);
|
||||
embeddedPdbEntry = default(DebugDirectoryEntry);
|
||||
|
||||
foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory())
|
||||
{
|
||||
if (entry.Type == DebugDirectoryEntryType.CodeView)
|
||||
{
|
||||
const ushort PortableCodeViewVersionMagic = 0x504d;
|
||||
if (entry.MinorVersion != PortableCodeViewVersionMagic)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
codeViewEntry = entry;
|
||||
}
|
||||
else if (entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb)
|
||||
{
|
||||
embeddedPdbEntry = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static OpenedReader TryOpenReaderFromCodeView(PEReader peReader, DebugDirectoryEntry codeViewEntry, string assemblyPath)
|
||||
{
|
||||
OpenedReader result = null;
|
||||
MetadataReaderProvider provider = null;
|
||||
try
|
||||
{
|
||||
var data = peReader.ReadCodeViewDebugDirectoryData(codeViewEntry);
|
||||
|
||||
string pdbPath = data.Path;
|
||||
if (assemblyPath != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
pdbPath = Path.Combine(Path.GetDirectoryName(assemblyPath), GetFileName(pdbPath));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// invalid characters in CodeView path
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
var pdbStream = TryOpenFile(pdbPath);
|
||||
if (pdbStream == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
|
||||
var reader = provider.GetMetadataReader();
|
||||
|
||||
// Validate that the PDB matches the assembly version
|
||||
if (data.Age == 1 && new BlobContentId(reader.DebugMetadataHeader.Id) == new BlobContentId(data.Guid, codeViewEntry.Stamp))
|
||||
{
|
||||
result = new OpenedReader(provider, reader);
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (e is BadImageFormatException || e is IOException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
provider?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static OpenedReader TryOpenReaderFromEmbeddedPdb(PEReader peReader, DebugDirectoryEntry embeddedPdbEntry)
|
||||
{
|
||||
OpenedReader result = null;
|
||||
MetadataReaderProvider provider = null;
|
||||
|
||||
try
|
||||
{
|
||||
// TODO: We might want to cache this provider globally (across stack traces),
|
||||
// since decompressing embedded PDB takes some time.
|
||||
provider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry);
|
||||
result = new OpenedReader(provider, provider.GetMetadataReader());
|
||||
}
|
||||
catch (Exception e) when (e is BadImageFormatException || e is IOException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
provider?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Stream TryOpenFile(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
return File.OpenRead(path);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче