/// <summary> /// Loads and initializes the SOS module. /// </summary> /// <param name="tempDirectory">Temporary directory created to download DAC module</param> /// <param name="isDesktop">if true, desktop runtime, else .NET Core runtime</param> /// <param name="dacFilePath">The path to DAC that CLRMD loaded or downloaded or null</param> /// <param name="dbiFilePath">The path to DBI (for future use) or null</param> public void InitializeSOSHost(string tempDirectory, bool isDesktop, string dacFilePath, string dbiFilePath) { if (_sosLibrary == IntPtr.Zero) { string sosPath = Path.Combine(SOSPath, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "sos.dll" : "libsos.so"); try { _sosLibrary = DataTarget.PlatformFunctions.LoadLibrary(sosPath); } catch (DllNotFoundException ex) { // This is a workaround for the Microsoft SDK docker images. Can fail when LoadLibrary uses libdl.so to load the SOS module. if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { throw new DllNotFoundException("Problem loading SOS module. Try installing libc6-dev (apt-get install libc6-dev) to work around this problem.", ex); } else { throw; } } if (_sosLibrary == IntPtr.Zero) { throw new FileNotFoundException($"SOS module {sosPath} not found"); } IntPtr initializeAddress = DataTarget.PlatformFunctions.GetProcAddress(_sosLibrary, SOSInitialize); if (initializeAddress == IntPtr.Zero) { throw new EntryPointNotFoundException($"Can not find SOS module initialization function: {SOSInitialize}"); } var initializeFunc = (SOSInitializeDelegate)Marshal.GetDelegateForFunctionPointer(initializeAddress, typeof(SOSInitializeDelegate)); // SOS depends on that the temp directory ends with "/". if (!string.IsNullOrEmpty(tempDirectory) && tempDirectory[tempDirectory.Length - 1] != Path.DirectorySeparatorChar) { tempDirectory += Path.DirectorySeparatorChar; } int result = initializeFunc( ref s_callbacks, Marshal.SizeOf <SOSNetCoreCallbacks>(), tempDirectory, AnalyzeContext.RuntimeModuleDirectory, isDesktop, dacFilePath, dbiFilePath, SymbolReader.IsSymbolStoreEnabled()); if (result != 0) { throw new InvalidOperationException($"SOS initialization FAILED 0x{result:X8}"); } Trace.TraceInformation("SOS initialized: tempDirectory '{0}' dacFilePath '{1}' sosPath '{2}'", tempDirectory, dacFilePath, sosPath); } }
/// <summary> /// Metadata locator helper for the DAC. /// </summary> /// <param name="imagePath">file name and path to module</param> /// <param name="imageTimestamp">module timestamp</param> /// <param name="imageSize">module image</param> /// <param name="localFilePath">local file path of the module</param> /// <returns>HRESULT</returns> public static int GetICorDebugMetadataLocator( [MarshalAs(UnmanagedType.LPWStr)] string imagePath, uint imageTimestamp, uint imageSize, uint pathBufferSize, IntPtr pPathBufferSize, IntPtr pPathBuffer) { int hr = S_OK; int actualSize = 0; Debug.Assert(pPathBuffer != IntPtr.Zero); try { if (SymbolReader.IsSymbolStoreEnabled()) { SymbolStoreKey key = PEFileKeyGenerator.GetKey(imagePath, imageTimestamp, imageSize); string localFilePath = SymbolReader.GetSymbolFile(key); localFilePath += "\0"; // null terminate the string actualSize = localFilePath.Length; if (pathBufferSize > actualSize) { Marshal.Copy(localFilePath.ToCharArray(), 0, pPathBuffer, actualSize); } else { hr = E_INSUFFICIENT_BUFFER; } } else { hr = E_FAIL; } } catch (Exception ex) when (ex is UnauthorizedAccessException || ex is BadImageFormatException || ex is InvalidVirtualAddressException || ex is IOException) { hr = E_FAIL; } if (pPathBufferSize != IntPtr.Zero) { Marshal.WriteInt32(pPathBufferSize, actualSize); } return(hr); }
public static int GetMetadataLocator( [MarshalAs(UnmanagedType.LPWStr)] string imagePath, uint imageTimestamp, uint imageSize, [MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] byte[] mvid, uint mdRva, uint flags, uint bufferSize, IntPtr pMetadata, IntPtr pMetadataSize) { int hr = unchecked ((int)0x80004005); int dataSize = 0; Debug.Assert(pMetadata != IntPtr.Zero); Stream peStream = null; if (imagePath != null && File.Exists(imagePath)) { peStream = SymbolReader.TryOpenFile(imagePath); } else if (SymbolReader.IsSymbolStoreEnabled()) { SymbolStoreKey key = PEFileKeyGenerator.GetKey(imagePath, imageTimestamp, imageSize); peStream = SymbolReader.GetSymbolStoreFile(key)?.Stream; } if (peStream != null) { using (var peReader = new PEReader(peStream, PEStreamOptions.Default)) { if (peReader.HasMetadata) { PEMemoryBlock metadataInfo = peReader.GetMetadata(); unsafe { int size = Math.Min((int)bufferSize, metadataInfo.Length); Marshal.Copy(metadataInfo.GetContent().ToArray(), 0, pMetadata, size); } dataSize = metadataInfo.Length; hr = 0; } } } if (pMetadataSize != IntPtr.Zero) { Marshal.WriteInt32(pMetadataSize, dataSize); } return(hr); }
private PEReader GetPEReader(ModuleInfo module) { if (!_pathToPeReader.TryGetValue(module.FileName, out PEReader reader)) { Stream stream = null; string downloadFilePath = module.FileName; if (!File.Exists(downloadFilePath)) { if (SymbolReader.IsSymbolStoreEnabled()) { SymbolStoreKey key = PEFileKeyGenerator.GetKey(Path.GetFileName(downloadFilePath), module.TimeStamp, module.FileSize); if (key != null) { // Now download the module from the symbol server downloadFilePath = SymbolReader.GetSymbolFile(key); } } } if (!string.IsNullOrEmpty(downloadFilePath)) { try { stream = File.OpenRead(downloadFilePath); } catch (Exception ex) when(ex is DirectoryNotFoundException || ex is FileNotFoundException || ex is UnauthorizedAccessException || ex is IOException) { Trace.TraceError("GetPEReader: exception {0}", ex); } if (stream != null) { reader = new PEReader(stream); _pathToPeReader.Add(module.FileName, reader); } } } return(reader); }
/// <summary> /// Metadata locator helper for the DAC. /// </summary> /// <param name="imagePath">file name and path to module</param> /// <param name="imageTimestamp">module timestamp</param> /// <param name="imageSize">module image</param> /// <param name="mvid">not used</param> /// <param name="mdRva">not used</param> /// <param name="flags">not used</param> /// <param name="bufferSize">size of incoming buffer (pMetadata)</param> /// <param name="pMetadata">pointer to buffer</param> /// <param name="pMetadataSize">size of outgoing metadata</param> /// <returns>HRESULT</returns> public static int GetMetadataLocator( [MarshalAs(UnmanagedType.LPWStr)] string imagePath, uint imageTimestamp, uint imageSize, [MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] byte[] mvid, uint mdRva, uint flags, uint bufferSize, IntPtr pMetadata, IntPtr pMetadataSize) { int hr = S_OK; int dataSize = 0; Debug.Assert(pMetadata != IntPtr.Zero); try { Stream peStream = null; if (imagePath != null && File.Exists(imagePath)) { peStream = SymbolReader.TryOpenFile(imagePath); } else if (SymbolReader.IsSymbolStoreEnabled()) { SymbolStoreKey key = PEFileKeyGenerator.GetKey(imagePath, imageTimestamp, imageSize); peStream = SymbolReader.GetSymbolStoreFile(key)?.Stream; } if (peStream != null) { using (var peReader = new PEReader(peStream, PEStreamOptions.Default)) { if (peReader.HasMetadata) { PEMemoryBlock metadataInfo = peReader.GetMetadata(); dataSize = metadataInfo.Length; unsafe { int size = Math.Min((int)bufferSize, metadataInfo.Length); Marshal.Copy(metadataInfo.GetContent().ToArray(), 0, pMetadata, size); } } else { hr = E_FAIL; } } } else { hr = E_FAIL; } } catch (Exception ex) when (ex is UnauthorizedAccessException || ex is BadImageFormatException || ex is InvalidVirtualAddressException || ex is IOException) { hr = E_FAIL; } if (pMetadataSize != IntPtr.Zero) { Marshal.WriteInt32(pMetadataSize, dataSize); } return(hr); }