Generate CrossGen Pdbs as part of bulid (#7298)
authorVance Morrison <vancem@microsoft.com>
Thu, 22 Sep 2016 13:46:49 +0000 (06:46 -0700)
committerJan Kotas <jkotas@microsoft.com>
Thu, 22 Sep 2016 13:46:49 +0000 (06:46 -0700)
This change has two parts.  The first part changes build.cmd and the pkgproj
so that as part of generating a .NET Core package we also generate the PDBS
for the Native System.Private.Corelib.ni.dll.

The second part changes crossgen so that it marks the Native Images as having
a list of 0 exports.   This is important because we want the generated PDBs
to be naturally published on the symbol server, and currently the symbol server
skips DLLs what are 'resource only' (no imports or exports).   Because native
images don't use 'normal' PE imports and exports, they get optimized away
by the symbol server.  Making a empy list of exports fixes this.

build.cmd
src/.nuget/Microsoft.NETCore.Runtime.CoreCLR/win/Microsoft.NETCore.Runtime.CoreCLR.pkgproj
src/zap/zapheaders.cpp
src/zap/zapheaders.h
src/zap/zapimage.cpp

index 0974b00..4e6d4ee 100644 (file)
--- a/build.cmd
+++ b/build.cmd
@@ -167,6 +167,11 @@ if not exist "%__BinDir%"           md "%__BinDir%"
 if not exist "%__IntermediatesDir%" md "%__IntermediatesDir%"
 if not exist "%__LogsDir%"          md "%__LogsDir%"
 
+REM It is convinient to have your Nuget search path include the location where the build
+REM will plass packages.  However nuget used during the build will fail if that directory 
+REM does not exist.   Avoid this in at least one case by agressively creating the directory. 
+if not exist "%__BinDir%\.nuget\pkg"           md "%__BinDir%\.nuget\pkg"
+
 echo %__MsgPrefix%Commencing CoreCLR Repo build
 
 :: Set the remaining variables based upon the determined build configuration
@@ -344,13 +349,22 @@ if %__BuildCoreLib% EQU 1 (
     )
 )
 
+REM Need diasymreader.dll on your path for /CreatePdb
+set PATH=%PATH%;%WinDir%\Microsoft.Net\Framework64\V4.0.30319;%WinDir%\Microsoft.Net\Framework\V4.0.30319
+
 if %__BuildNativeCoreLib% EQU 1 (
     echo %__MsgPrefix%Generating native image of System.Private.CoreLib for %__BuildOS%.%__BuildArch%.%__BuildType%
        
     echo "%__CrossgenExe%" /Platform_Assemblies_Paths "%__BinDir%" /out "%__BinDir%\System.Private.CoreLib.ni.dll" "%__BinDir%\System.Private.CoreLib.dll"
     "%__CrossgenExe%" /Platform_Assemblies_Paths "%__BinDir%" /out "%__BinDir%\System.Private.CoreLib.ni.dll" "%__BinDir%\System.Private.CoreLib.dll" > "%__CrossGenCoreLibLog%" 2>&1
     if NOT !errorlevel! == 0 (
-        echo %__MsgPrefix%Error: CrossGen System.Private.CoreLib build failed. Refer to the build log file for details:
+        echo %__MsgPrefix%Error: CrossGen System.Private.CoreLib build failed. Refer to %__CrossGenCoreLibLog%
+        echo     %__CrossGenCoreLibLog%
+        exit /b 1
+    )
+    "%__CrossgenExe%" /Platform_Assemblies_Paths "%__BinDir%" /CreatePdb "%__BinDir%\PDB" "%__BinDir%\System.Private.CoreLib.ni.dll" >> "%__CrossGenCoreLibLog%" 2>&1
+    if NOT !errorlevel! == 0 (
+        echo %__MsgPrefix%Error: CrossGen /CreatePdb System.Private.CoreLib build failed. Refer to %__CrossGenCoreLibLog%
         echo     %__CrossGenCoreLibLog%
         exit /b 1
     )
@@ -368,6 +382,8 @@ if %__BuildNativeCoreLib% EQU 1 (
 )
 
 if %__BuildPackages% EQU 1 (
+    echo %__MsgPrefix%Building Packages for %__BuildOS%.%__BuildArch%.%__BuildType%
+
     set __MsbuildLog=/flp:Verbosity=normal;LogFile="%__LogsDir%\Nuget_%__BuildOS%__%__BuildArch%__%__BuildType%.log"
        set __MsbuildWrn=/flp1:WarningsOnly;LogFile="%__LogsDir%\Nuget_%__BuildOS%__%__BuildArch%__%__BuildType%.wrn"
        set __MsbuildErr=/flp2:ErrorsOnly;LogFile="%__LogsDir%\Nuget_%__BuildOS%__%__BuildArch%__%__BuildType%.err"
index 97029aa..553838c 100644 (file)
@@ -40,7 +40,7 @@
     <ArchitectureSpecificNativeFileAndSymbol Include="$(BinDir)mscorrc.dll" />
     <ArchitectureSpecificNativeFileAndSymbol Include="$(BinDir)sos.dll" />
     <ArchitectureSpecificNativeFile Include="$(BinDir)mscorlib.ni.dll" />
-    <ArchitectureSpecificNativeFile Include="$(BinDir)System.Private.CoreLib.ni.dll" />
+    <ArchitectureSpecificNativeFileAndSymbol Include="$(BinDir)System.Private.CoreLib.ni.dll" />
     <ArchitectureSpecificLibFile Include="$(BinDir)System.Private.CoreLib.dll" />
     <ArchitectureSpecificLibFile Include="$(BinDir)mscorlib.dll" />
     <ArchitectureSpecificLibFile Include="$(BinDir)SOS.NETCore.dll" />
index d8cd6fa..35032c9 100644 (file)
@@ -288,18 +288,49 @@ void ZapDebugDirectory::Save(ZapWriter * pZapWriter)
     _ASSERTE(pZapWriter);
 
     if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_NGenEnableCreatePdb)) {
-
         SaveOriginalDebugDirectoryEntry(pZapWriter);
         SaveNGenDebugDirectoryEntry(pZapWriter);
-
     } else {
-
         SaveNGenDebugDirectoryEntry(pZapWriter);
         SaveOriginalDebugDirectoryEntry(pZapWriter);
-
     }
 }
 
+ZapPEExports::ZapPEExports(LPCWSTR dllPath) 
+{
+       m_dllFileName = wcsrchr(dllPath, DIRECTORY_SEPARATOR_CHAR_W);
+       if (m_dllFileName != NULL)
+               m_dllFileName++;
+       else 
+               m_dllFileName = dllPath;
+}
+
+DWORD ZapPEExports::GetSize()
+{
+       return DWORD(sizeof(IMAGE_EXPORT_DIRECTORY) + wcslen(m_dllFileName) + 1);
+}
+
+void ZapPEExports::Save(ZapWriter * pZapWriter)
+{
+       _ASSERTE(pZapWriter);
+
+       IMAGE_EXPORT_DIRECTORY exports;
+       ZeroMemory(&exports, sizeof(exports));
+
+       exports.Name = pZapWriter->GetCurrentRVA() + sizeof(exports);
+
+       // Write out exports header 
+       pZapWriter->Write(&exports, sizeof(exports));
+
+       // Write out string that exports.Name points at.  
+       for (LPCWSTR ptr = m_dllFileName; ; ptr++)
+       {
+               pZapWriter->Write((PVOID) ptr, 1);
+               if (*ptr == 0)
+                       break;
+       }
+}
+
 // If the IL image has IMAGE_DIRECTORY_ENTRY_DEBUG with information about the PDB,
 // copy that information over to the ngen image.
 // This lets the debugger find out information about the PDB without loading
index 12b0a18..01366eb 100644 (file)
@@ -269,6 +269,23 @@ public:
 };
 
 //
+// PE Style exports.  Currently can only save an empty list of exports
+// but this is useful because it avoids the DLL being seen as Resource Only
+// (which then causes SymServer to avoid copying its PDB to the cloud).  
+//
+
+class ZapPEExports : public ZapNode
+{
+       LPCWSTR m_dllFileName;  // Just he DLL name without the path.
+
+public:
+       ZapPEExports(LPCWSTR dllPath);
+       virtual DWORD GetSize();
+       virtual UINT GetAlignment() { return sizeof(DWORD);  }
+       virtual void Save(ZapWriter * pZapWriter);
+};
+
+//
 // List of all sections for diagnostic purposes
 
 class ZapVirtualSectionsTable : public ZapNode
index a435d6a..f7737ba 100644 (file)
@@ -1163,6 +1163,14 @@ HANDLE ZapImage::SaveImage(LPCWSTR wszOutputFileName, CORCOMPILE_NGEN_SIGNATURE
 
     OutputTables();
 
+       // Create a empty export table.  This makes tools like symchk not think
+       // that native images are resoure-only DLLs.  It is important to NOT
+       // be a resource-only DLL because those DLL's PDBS are not put up on the
+       // symbol server and we want NEN PDBS to be placed there.  
+       ZapPEExports* exports = new(GetHeap()) ZapPEExports(wszOutputFileName);
+       m_pDebugSection->Place(exports);
+       SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXPORT, exports);
+
     ComputeRVAs();
 
     if (!IsReadyToRunCompilation())