From: Mike McLaughlin Date: Wed, 21 Aug 2019 21:49:56 +0000 (-0700) Subject: Add directory symbol search X-Git-Tag: submit/tizen/20191015.063341~12^2^2~5^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d28db926285039a43a97b82e36b1219ef37dfbfc;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git Add directory symbol search Adds a setsymbolserver option (-directory) to add directories to the symbol search path. Cleaned up how the symbol code added the "default" symbol cache. It is done when the server URI is added if a cache path wasn't specified. Ignore adding duplicate server URI's and search directories. Ignore adding the same cache directory twice in a row. Add -sympath option to setsymbolserver and lldb "sympath" command alias for devs that want to use the Window symbol path syntax. Change to Preview9 prerelease label. Issues: https://github.com/dotnet/diagnostics/issues/422 https://github.com/dotnet/diagnostics/issues/420 --- diff --git a/eng/Versions.props b/eng/Versions.props index e4e3c41c4..0efd7a0b4 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -2,7 +2,7 @@ https://github.com/dotnet/diagnostics - preview8 + preview9 3.0.0 true true @@ -22,7 +22,7 @@ 4.3.0 - 1.0.0-dev-64131-02 + 1.0.41901 1.1.37504 1.7.0 2.0.44 @@ -40,7 +40,6 @@ $(RestoreSources); https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; - https://dotnet.myget.org/F/symstore/api/v3/index.json; https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json; https://dotnet.myget.org/F/system-commandline/api/v3/index.json diff --git a/src/SOS/SOS.Hosting/SOSHost.cs b/src/SOS/SOS.Hosting/SOSHost.cs index e4f3f2816..e19e4e69b 100644 --- a/src/SOS/SOS.Hosting/SOSHost.cs +++ b/src/SOS/SOS.Hosting/SOSHost.cs @@ -62,6 +62,7 @@ namespace SOS string tempDirectory, string symbolServerPath, string symbolCachePath, + string symbolDirectoryPath, string windowsSymbolPath); private delegate void DisplaySymbolStoreDelegate( diff --git a/src/SOS/SOS.NETCore/SymbolReader.cs b/src/SOS/SOS.NETCore/SymbolReader.cs index ed42d7776..392c42ca3 100644 --- a/src/SOS/SOS.NETCore/SymbolReader.cs +++ b/src/SOS/SOS.NETCore/SymbolReader.cs @@ -137,8 +137,8 @@ namespace SOS /// /// Symbol server URLs /// - const string MsdlsymbolServer = "http://msdl.microsoft.com/download/symbols/"; - const string SymwebSymbolService = "http://symweb.corp.microsoft.com/"; + const string MsdlSymbolServer = "http://msdl.microsoft.com/download/symbols/"; + const string SymwebSymbolServer = "http://symweb.corp.microsoft.com/"; /// /// Read memory callback @@ -166,7 +166,6 @@ namespace SOS static readonly ITracer s_tracer = new Tracer(); static SymbolStore s_symbolStore = null; - static bool s_symbolCacheAdded = false; /// /// Initializes symbol loading. Adds the symbol server and/or the cache path (if not null) to the list of @@ -178,9 +177,10 @@ namespace SOS /// temp directory unique to this instance of SOS /// symbol server url (optional) /// symbol cache directory path (optional) + /// symbol directory path to search (optional) /// windows symbol path (optional) /// if false, failure - public static bool InitializeSymbolStore(bool logging, bool msdl, bool symweb, string tempDirectory, string symbolServerPath, string symbolCachePath, string windowsSymbolPath) + public static bool InitializeSymbolStore(bool logging, bool msdl, bool symweb, string tempDirectory, string symbolServerPath, string symbolCachePath, string symbolDirectoryPath, string windowsSymbolPath) { if (logging) { // Uses the standard console to do the logging instead of sending it to the hosting debugger console @@ -201,8 +201,15 @@ namespace SOS } } else { + // Add the default symbol cache if no cache specified and adding server + if (symbolCachePath == null) + { + if (msdl || symweb || symbolServerPath != null) { + symbolCachePath = GetDefaultSymbolCache(); + } + } // Build the symbol stores using the other parameters - if (!GetServerSymbolStore(ref store, msdl, symweb, symbolServerPath, symbolCachePath)) { + if (!GetServerSymbolStore(ref store, msdl, symweb, symbolServerPath, symbolCachePath, symbolDirectoryPath)) { return false; } } @@ -222,9 +229,12 @@ namespace SOS if (symbolStore is CacheSymbolStore cache) { writeLine($"Cache: {cache.CacheDirectory}"); } - else if (symbolStore is HttpSymbolStore http) { + else if (symbolStore is HttpSymbolStore http) { writeLine($"Server: {http.Uri}"); } + else if (symbolStore is DirectorySymbolStore directory) { + writeLine($"Directory: {directory.Directory}"); + } else { writeLine("Unknown symbol store"); } @@ -238,7 +248,6 @@ namespace SOS public static void DisableSymbolStore() { s_symbolStore = null; - s_symbolCacheAdded = false; } /// @@ -992,11 +1001,6 @@ namespace SOS { try { - // Add the default symbol cache if it hasn't already been added - if (!s_symbolCacheAdded) { - s_symbolStore = new CacheSymbolStore(s_tracer, s_symbolStore, GetDefaultSymbolCache()); - s_symbolCacheAdded = true; - } return s_symbolStore.GetFile(key, CancellationToken.None).GetAwaiter().GetResult(); } catch (Exception ex) when (ex is UnauthorizedAccessException || ex is BadImageFormatException || ex is IOException) @@ -1025,6 +1029,7 @@ namespace SOS { string symbolServerPath = null; string symbolCachePath = null; + string symbolDirectoryPath = null; bool msdl = false; switch (parts[0].ToLowerInvariant()) @@ -1034,6 +1039,7 @@ namespace SOS { case 1: msdl = true; + symbolCachePath = GetDefaultSymbolCache(); break; case 2: symbolServerPath = parts[1]; @@ -1062,12 +1068,20 @@ namespace SOS break; default: - // Directory path search (currently ignored) + // Directory path search + switch (parts.Length) + { + case 1: + symbolDirectoryPath = parts[0]; + break; + default: + return false; + } break; } // Add the symbol stores to the chain - if (!GetServerSymbolStore(ref store, msdl, false, symbolServerPath, symbolCachePath)) + if (!GetServerSymbolStore(ref store, msdl, false, symbolServerPath, symbolCachePath, symbolDirectoryPath)) { return false; } @@ -1077,7 +1091,7 @@ namespace SOS return true; } - private static bool GetServerSymbolStore(ref SymbolStore store, bool msdl, bool symweb, string symbolServerPath, string symbolCachePath) + private static bool GetServerSymbolStore(ref SymbolStore store, bool msdl, bool symweb, string symbolServerPath, string symbolCachePath, string symbolDirectoryPath) { bool internalServer = false; @@ -1086,11 +1100,11 @@ namespace SOS { if (msdl) { - symbolServerPath = MsdlsymbolServer; + symbolServerPath = MsdlSymbolServer; } else if (symweb) { - symbolServerPath = SymwebSymbolService; + symbolServerPath = SymwebSymbolServer; internalServer = true; } } @@ -1105,33 +1119,69 @@ namespace SOS if (symbolServerPath != null) { + // Validate symbol server path if (!Uri.TryCreate(symbolServerPath, UriKind.Absolute, out Uri uri) || uri.IsFile) { return false; } - // Create symbol server store - if (internalServer) + if (!IsDuplicateSymbolStore(store, (httpSymbolStore) => uri.Equals(httpSymbolStore.Uri))) { - store = new SymwebHttpSymbolStore(s_tracer, store, uri); + // Create symbol server store + if (internalServer) + { + store = new SymwebHttpSymbolStore(s_tracer, store, uri); + } + else + { + store = new HttpSymbolStore(s_tracer, store, uri); + } } - else + } + + if (symbolCachePath != null) + { + symbolCachePath = Path.GetFullPath(symbolCachePath); + + // Check only the first symbol store for duplication. The same cache directory can be + // added more than once but just not more than once in a row. + if (!(store is CacheSymbolStore cacheSymbolStore && IsPathEqual(symbolCachePath, cacheSymbolStore.CacheDirectory))) { - store = new HttpSymbolStore(s_tracer, store, uri); + store = new CacheSymbolStore(s_tracer, store, symbolCachePath); } } - if (symbolCachePath != null) + if (symbolDirectoryPath != null) { - store = new CacheSymbolStore(s_tracer, store, symbolCachePath); + symbolDirectoryPath = Path.GetFullPath(symbolDirectoryPath); - // Don't add the default cache later - s_symbolCacheAdded = true; + if (!IsDuplicateSymbolStore(store, (directorySymbolStore) => IsPathEqual(symbolDirectoryPath, directorySymbolStore.Directory))) + { + store = new DirectorySymbolStore(s_tracer, store, symbolDirectoryPath); + } } return true; } + private static bool IsDuplicateSymbolStore(SymbolStore symbolStore, Func match) + where T : SymbolStore + { + while (symbolStore != null) + { + if (symbolStore is T store) + { + // TODO: replace this by adding an Equal override to the symbol stores + if (match(store)) + { + return true; + } + } + symbolStore = symbolStore.BackingStore; + } + return false; + } + private static string GetDefaultSymbolCache() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -1151,17 +1201,31 @@ namespace SOS /// stream or null if doesn't exist or error internal static Stream TryOpenFile(string path) { - if (!File.Exists(path)) + if (File.Exists(path)) { - return null; + try + { + return File.OpenRead(path); + } + catch (Exception ex) when (ex is UnauthorizedAccessException || ex is NotSupportedException || ex is IOException) + { + } } - try + return null; + } + + /// + /// Compares two file paths using OS specific casing. + /// + private static bool IsPathEqual(string path1, string path2) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - return File.OpenRead(path); + return StringComparer.OrdinalIgnoreCase.Equals(path1, path2); } - catch + else { - return null; + return string.Equals(path1, path2); } } diff --git a/src/SOS/Strike/hostcoreclr.cpp b/src/SOS/Strike/hostcoreclr.cpp index 670617dca..41dfe1b78 100644 --- a/src/SOS/Strike/hostcoreclr.cpp +++ b/src/SOS/Strike/hostcoreclr.cpp @@ -42,6 +42,7 @@ static bool g_hostingInitialized = false; static bool g_symbolStoreInitialized = false; +static bool g_windowsSymbolPathInitialized = false; LPCSTR g_hostRuntimeDirectory = nullptr; LPCSTR g_dacFilePath = nullptr; LPCSTR g_dbiFilePath = nullptr; @@ -777,13 +778,13 @@ static int ReadMemoryForSymbols(ULONG64 address, uint8_t *buffer, int cb) /**********************************************************************\ * Setup and initialize the symbol server support. \**********************************************************************/ -HRESULT InitializeSymbolStore(BOOL logging, BOOL msdl, BOOL symweb, const char* symbolServer, const char* cacheDirectory) +HRESULT InitializeSymbolStore(BOOL logging, BOOL msdl, BOOL symweb, const char* symbolServer, const char* cacheDirectory, const char* searchDirectory, const char* windowsSymbolPath) { HRESULT Status = S_OK; IfFailRet(InitializeHosting()); _ASSERTE(g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate != nullptr); - if (!g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate(logging, msdl, symweb, GetTempDirectory(), symbolServer, cacheDirectory, nullptr)) + if (!g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate(logging, msdl, symweb, GetTempDirectory(), symbolServer, cacheDirectory, searchDirectory, windowsSymbolPath)) { ExtErr("Error initializing symbol server support\n"); return E_FAIL; @@ -792,6 +793,7 @@ HRESULT InitializeSymbolStore(BOOL logging, BOOL msdl, BOOL symweb, const char* return S_OK; } + /**********************************************************************\ * Setup and initialize the symbol server support using the .sympath \**********************************************************************/ @@ -800,19 +802,20 @@ void InitializeSymbolStore() _ASSERTE(g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate != nullptr); #ifndef FEATURE_PAL - if (!g_symbolStoreInitialized) + if (!g_windowsSymbolPathInitialized) { - g_symbolStoreInitialized = true; - ArrayHolder symbolPath = new char[MAX_LONGPATH]; if (SUCCEEDED(g_ExtSymbols->GetSymbolPath(symbolPath, MAX_LONGPATH, nullptr))) { if (strlen(symbolPath) > 0) { - if (!g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate(false, false, false, GetTempDirectory(), nullptr, nullptr, symbolPath)) + if (!g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate(false, false, false, GetTempDirectory(), nullptr, nullptr, nullptr, symbolPath)) { ExtErr("Windows symbol path parsing FAILED\n"); + return; } + g_windowsSymbolPathInitialized = true; + g_symbolStoreInitialized = true; } } } @@ -926,6 +929,7 @@ void DisableSymbolStore() if (g_symbolStoreInitialized) { g_symbolStoreInitialized = false; + g_windowsSymbolPathInitialized = false; _ASSERTE(g_SOSNetCoreCallbacks.DisableSymbolStoreDelegate != nullptr); g_SOSNetCoreCallbacks.DisableSymbolStoreDelegate(); @@ -1528,4 +1532,4 @@ HRESULT SymbolReader::ResolveSequencePoint(__in_z WCHAR* pFilename, ___in ULONG3 #endif // FEATURE_PAL return E_FAIL; -} \ No newline at end of file +} diff --git a/src/SOS/Strike/hostcoreclr.h b/src/SOS/Strike/hostcoreclr.h index a5fe423cb..ef260a399 100644 --- a/src/SOS/Strike/hostcoreclr.h +++ b/src/SOS/Strike/hostcoreclr.h @@ -16,7 +16,7 @@ typedef void (*WriteLineDelegate)(const char*); typedef int (*ReadMemoryDelegate)(ULONG64, uint8_t*, int); typedef void (*SymbolFileCallbackDelegate)(void*, const char* moduleFileName, const char* symbolFilePath); -typedef BOOL (*InitializeSymbolStoreDelegate)(BOOL, BOOL, BOOL, const char*, const char*, const char*, const char*); +typedef BOOL (*InitializeSymbolStoreDelegate)(BOOL, BOOL, BOOL, const char*, const char*, const char*, const char*, const char*); typedef void (*DisplaySymbolStoreDelegate)(WriteLineDelegate); typedef void (*DisableSymbolStoreDelegate)(); typedef void (*LoadNativeSymbolsDelegate)(SymbolFileCallbackDelegate, void*, const char*, ULONG64, int, ReadMemoryDelegate); @@ -67,7 +67,7 @@ extern LPCSTR GetDacFilePath(); extern LPCSTR GetDbiFilePath(); extern BOOL IsHostingInitialized(); extern HRESULT InitializeHosting(); -extern HRESULT InitializeSymbolStore(BOOL logging, BOOL msdl, BOOL symweb, const char* symbolServer, const char* cacheDirectory); +extern HRESULT InitializeSymbolStore(BOOL logging, BOOL msdl, BOOL symweb, const char* symbolServer, const char* cacheDirectory, const char* searchDirectory, const char* windowsSymbolPath); extern void InitializeSymbolStore(); extern HRESULT LoadNativeSymbols(bool runtimeOnly = false); extern void DisplaySymbolStore(); diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index 77577adb3..afb2c21a6 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -15527,6 +15527,8 @@ DECLARE_API(SetSymbolServer) INIT_API_EXT(); StringHolder symbolCache; + StringHolder searchDirectory; + StringHolder windowsSymbolPath; BOOL disable = FALSE; BOOL loadNative = FALSE; BOOL msdl = FALSE; @@ -15535,11 +15537,13 @@ DECLARE_API(SetSymbolServer) CMDOption option[] = { // name, vptr, type, hasValue {"-disable", &disable, COBOOL, FALSE}, - {"-cache", &symbolCache.data, COSTRING, FALSE}, + {"-cache", &symbolCache.data, COSTRING, TRUE}, + {"-directory", &searchDirectory.data, COSTRING, TRUE}, {"-ms", &msdl, COBOOL, FALSE}, {"-log", &logging, COBOOL, FALSE}, #ifdef FEATURE_PAL {"-loadsymbols", &loadNative, COBOOL, FALSE}, + {"-sympath", &windowsSymbolPath.data, COSTRING, TRUE}, #else {"-mi", &symweb, COBOOL, FALSE}, #endif @@ -15555,11 +15559,6 @@ DECLARE_API(SetSymbolServer) return E_FAIL; } - if (disable) { - DisableSymbolStore(); - return S_OK; - } - if (msdl && symweb) { ExtErr("Cannot have both -ms and -mi options\n"); @@ -15572,9 +15571,13 @@ DECLARE_API(SetSymbolServer) return E_FAIL; } - if (msdl || symweb || symbolServer.data != nullptr || symbolCache.data != nullptr) + if (disable) { + DisableSymbolStore(); + } + + if (msdl || symweb || symbolServer.data != nullptr || symbolCache.data != nullptr || searchDirectory.data != nullptr || windowsSymbolPath.data != nullptr) { - Status = InitializeSymbolStore(logging, msdl, symweb, symbolServer.data, symbolCache.data); + Status = InitializeSymbolStore(logging, msdl, symweb, symbolServer.data, symbolCache.data, searchDirectory.data, windowsSymbolPath.data); if (FAILED(Status)) { return Status; @@ -15593,7 +15596,15 @@ DECLARE_API(SetSymbolServer) } if (symbolCache.data != nullptr) { - ExtOut("Symbol cache path: %s\n", symbolCache.data); + ExtOut("Added symbol cache path: %s\n", symbolCache.data); + } + if (searchDirectory.data != nullptr) + { + ExtOut("Added symbol directory path: %s\n", searchDirectory.data); + } + if (windowsSymbolPath.data != nullptr) + { + ExtOut("Added Windows symbol path: %s\n", windowsSymbolPath.data); } } else if (loadNative) diff --git a/src/SOS/lldbplugin/soscommand.cpp b/src/SOS/lldbplugin/soscommand.cpp index da21b02fa..b6a4edc8f 100644 --- a/src/SOS/lldbplugin/soscommand.cpp +++ b/src/SOS/lldbplugin/soscommand.cpp @@ -165,6 +165,7 @@ sosCommandInitialize(lldb::SBDebugger debugger) 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("setsymbolserver", new sosCommand("SetSymbolServer"), "Enables the symbol server support "); + interpreter.AddCommand("sympath", new sosCommand("SetSymbolServer", "-sympath"), "Add server, cache and directory paths in the Windows symbol path format."); 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 "); return true; } diff --git a/src/Tools/dotnet-dump/Analyzer.cs b/src/Tools/dotnet-dump/Analyzer.cs index d462f0269..81c1a342b 100644 --- a/src/Tools/dotnet-dump/Analyzer.cs +++ b/src/Tools/dotnet-dump/Analyzer.cs @@ -71,7 +71,7 @@ namespace Microsoft.Diagnostics.Tools.Dump AddServices(target); // Automatically enable symbol server support - SymbolReader.InitializeSymbolStore(logging: false, msdl: true, symweb: false, tempDirectory: null, symbolServerPath: null, symbolCachePath: null, windowsSymbolPath: null); + SymbolReader.InitializeSymbolStore(logging: false, msdl: true, symweb: false, tempDirectory: null, symbolServerPath: null, symbolCachePath: null, symbolDirectoryPath: null, windowsSymbolPath: null); // Run the commands from the dotnet-dump command line if (command != null) diff --git a/src/Tools/dotnet-dump/Commands/HelpCommand.cs b/src/Tools/dotnet-dump/Commands/HelpCommand.cs index d2f3ce850..687ae1278 100644 --- a/src/Tools/dotnet-dump/Commands/HelpCommand.cs +++ b/src/Tools/dotnet-dump/Commands/HelpCommand.cs @@ -8,6 +8,7 @@ using System.CommandLine; namespace Microsoft.Diagnostics.Tools.Dump { [Command(Name = "help", Help = "Display help for a command.")] + [CommandAlias(Name = "soshelp")] public class HelpCommand : CommandBase { [Argument(Help = "Command to find help.")]