summaryrefslogtreecommitdiff
path: root/eng/common/CheckSymbols.ps1
blob: b8d84607b89b52199865a65840698c264f315983 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
param(
  [Parameter(Mandatory=$true)][string] $InputPath,       # Full path to directory where NuGet packages to be checked are stored
  [Parameter(Mandatory=$true)][string] $ExtractPath,     # Full path to directory where the packages will be extracted during validation
  [Parameter(Mandatory=$true)][string] $SymbolToolPath   # Full path to directory where dotnet symbol-tool was installed
)

Add-Type -AssemblyName System.IO.Compression.FileSystem

function FirstMatchingSymbolDescriptionOrDefault {
  param( 
    [string] $FullPath,                  # Full path to the module that has to be checked
    [string] $TargetServerParam,         # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols
    [string] $SymbolsPath
  )

  $FileName = [System.IO.Path]::GetFileName($FullPath)
  $Extension = [System.IO.Path]::GetExtension($FullPath)

  # Those below are potential symbol files that the `dotnet symbol` might
  # return. Which one will be returned depend on the type of file we are
  # checking and which type of file was uploaded.

  # The file itself is returned
  $SymbolPath = $SymbolsPath + "\" + $FileName

  # PDB file for the module
  $PdbPath = $SymbolPath.Replace($Extension, ".pdb")

  # PDB file for R2R module (created by crossgen)
  $NGenPdb = $SymbolPath.Replace($Extension, ".ni.pdb")

  # DBG file for a .so library
  $SODbg = $SymbolPath.Replace($Extension, ".so.dbg")

  # DWARF file for a .dylib
  $DylibDwarf = $SymbolPath.Replace($Extension, ".dylib.dwarf")
 
  .\dotnet-symbol.exe --symbols --modules --windows-pdbs $TargetServerParam $FullPath -o $SymbolsPath | Out-Null

  if (Test-Path $PdbPath) {
    return "PDB"
  }
  elseif (Test-Path $NGenPdb) {
    return "NGen PDB"
  }
  elseif (Test-Path $SODbg) {
    return "DBG for SO"
  }  
  elseif (Test-Path $DylibDwarf) {
    return "Dwarf for Dylib"
  }  
  elseif (Test-Path $SymbolPath) {
    return "Module"
  }
  else {
    return $null
  }
}

function CountMissingSymbols {
  param( 
    [string] $PackagePath          # Path to a NuGet package
  )

  # Ensure input file exist
  if (!(Test-Path $PackagePath)) {
    throw "Input file does not exist: $PackagePath"
  }
  
  # Extensions for which we'll look for symbols
  $RelevantExtensions = @(".dll", ".exe", ".so", ".dylib")

  # How many files are missing symbol information
  $MissingSymbols = 0

  $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath)
  $PackageGuid = New-Guid
  $ExtractPath = Join-Path -Path $ExtractPath -ChildPath $PackageGuid
  $SymbolsPath = Join-Path -Path $ExtractPath -ChildPath "Symbols"
  
  [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath)

  # Makes easier to reference `symbol tool`
  Push-Location $SymbolToolPath

  Get-ChildItem -Recurse $ExtractPath |
    Where-Object {$RelevantExtensions -contains $_.Extension} |
    ForEach-Object {
      if ($_.FullName -Match "\\ref\\") {
        Write-Host "`t Ignoring reference assembly file" $_.FullName
        return
      }

      $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--microsoft-symbol-server" $SymbolsPath
      $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--internal-server" $SymbolsPath

      Write-Host -NoNewLine "`t Checking file" $_.FullName "... "
  
      if ($SymbolsOnMSDL -ne $null -and $SymbolsOnSymWeb -ne $null) {
        Write-Host "Symbols found on MSDL (" $SymbolsOnMSDL ") and SymWeb (" $SymbolsOnSymWeb ")"
      }
      else {
        $MissingSymbols++

        if ($SymbolsOnMSDL -eq $null -and $SymbolsOnSymWeb -eq $null) {
          Write-Host "No symbols found on MSDL or SymWeb!"
        }
        else {
          if ($SymbolsOnMSDL -eq $null) {
            Write-Host "No symbols found on MSDL!"
          }
          else {
            Write-Host "No symbols found on SymWeb!"
          }
        }
      }
    }
  
  Pop-Location

  return $MissingSymbols
}

function CheckSymbolsAvailable {
  if (Test-Path $ExtractPath) {
    Remove-Item $ExtractPath -Force  -Recurse -ErrorAction SilentlyContinue
  }

  Get-ChildItem "$InputPath\*.nupkg" |
    ForEach-Object {
      $FileName = $_.Name
	  
      # These packages from Arcade-Services include some native libraries that
      # our current symbol uploader can't handle. Below is a workaround until
      # we get issue: https://github.com/dotnet/arcade/issues/2457 sorted.
      if ($FileName -Match "Microsoft\.DotNet\.Darc\.") {
        Write-Host "Ignoring Arcade-services file: $FileName"
        Write-Host
        return
      }
      elseif ($FileName -Match "Microsoft\.DotNet\.Maestro\.Tasks\.") {
        Write-Host "Ignoring Arcade-services file: $FileName"
        Write-Host
        return
      }
	  
      Write-Host "Validating $FileName "
      $Status = CountMissingSymbols "$InputPath\$FileName"
  
      if ($Status -ne 0) {
        Write-Error "Missing symbols for $Status modules in the package $FileName"
      }

      Write-Host
    }
}

CheckSymbolsAvailable