From f7fe412b015ee4c8ed1513f1605fe69158bc5cd7 Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Thu, 16 Sep 2021 14:39:17 -0700 Subject: [PATCH 1/6] Fix misc SOS bugs Fix bug in the AddFilesFromDirectoryToTpaList issue: https://github.com/dotnet/diagnostics/issues/2596 --- src/SOS/extensions/hostcoreclr.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/SOS/extensions/hostcoreclr.cpp b/src/SOS/extensions/hostcoreclr.cpp index 758a5715fd..68ab572942 100644 --- a/src/SOS/extensions/hostcoreclr.cpp +++ b/src/SOS/extensions/hostcoreclr.cpp @@ -220,19 +220,23 @@ static void AddFilesFromDirectoryToTpaList(const char* directory, std::string& t const char extension[] = ".dll"; std::string filename(find.FileName()); size_t extLen = sizeof(extension) - 1; - size_t extPos = filename.length() - extLen; - - // Check if the extension matches the one we are looking for - if ((extPos > 0) && (filename.compare(extPos, extLen, extension) == 0)) + size_t extPos = filename.length(); + if (extPos > extLen) { - std::string filenameWithoutExt(filename.substr(0, extPos)); + extPos -= extLen; - // Make sure if we have an assembly with multiple extensions present, - // we insert only one version of it. - if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + // Check if the extension matches the one we are looking for + if (filename.compare(extPos, extLen, extension) == 0) { - addedAssemblies.insert(filenameWithoutExt); - AddFileToTpaList(directory, filename.c_str(), tpaList); + std::string filenameWithoutExt(filename.substr(0, extPos)); + + // Make sure if we have an assembly with multiple extensions present, + // we insert only one version of it. + if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end()) + { + addedAssemblies.insert(filenameWithoutExt); + AddFileToTpaList(directory, filename.c_str(), tpaList); + } } } } From 4740ae6abd4e91f6a6f5c6d49f066d3392797d36 Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Fri, 17 Sep 2021 11:45:17 -0700 Subject: [PATCH 2/6] Added some logging to GetLineByOffset --- src/SOS/Strike/util.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/SOS/Strike/util.cpp b/src/SOS/Strike/util.cpp index c81837dae4..67a3c294a2 100644 --- a/src/SOS/Strike/util.cpp +++ b/src/SOS/Strike/util.cpp @@ -5109,23 +5109,30 @@ GetLineByOffset( ___in ULONG cchFileName, ___in BOOL bAdjustOffsetForLineNumber /* = FALSE */) { - HRESULT Status = S_OK; + HRESULT status = S_OK; ULONG32 methodToken; ULONG32 methodOffs; // Find the image, method token and IL offset that correspond to "nativeOffset" ToRelease pModule(NULL); - IfFailRet(ConvertNativeToIlOffset(nativeOffset, bAdjustOffsetForLineNumber, &pModule, &methodToken, &methodOffs)); - + status = ConvertNativeToIlOffset(nativeOffset, bAdjustOffsetForLineNumber, &pModule, &methodToken, &methodOffs); + if (FAILED(status)) + { + ExtDbgOut("GetLineByOffset(%p): ConvertNativeToIlOffset FAILED %08x\n", nativeOffset, status); + return status; + } ToRelease pMDImport(NULL); - Status = pModule->QueryInterface(IID_IMetaDataImport, (LPVOID *) &pMDImport); - if (FAILED(Status)) + status = pModule->QueryInterface(IID_IMetaDataImport, (LPVOID *) &pMDImport); + if (FAILED(status)) { - ExtDbgOut("GetLineByOffset(%p): QueryInterface(IID_IMetaDataImport) FAILED %08x\n", nativeOffset, Status); + ExtDbgOut("GetLineByOffset(%p): QueryInterface(IID_IMetaDataImport) FAILED %08x\n", nativeOffset, status); } SymbolReader symbolReader; - IfFailRet(symbolReader.LoadSymbols(pMDImport, pModule)); - + status = symbolReader.LoadSymbols(pMDImport, pModule); + if (FAILED(status)) + { + return status; + } return symbolReader.GetLineByILOffset(methodToken, methodOffs, pLinenum, pwszFileName, cchFileName); } From 1e0c106b8f687200cfcaa1d5de53fce86002901e Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Fri, 17 Sep 2021 17:21:57 -0700 Subject: [PATCH 3/6] Improve SymbolService.ParseSymbolPath support for Watson. Issue https://github.com/dotnet/diagnostics/issues/2512. Can now handle the various symbol paths that Watson can throw at us. Doesn't support actually calling the symbol server dll like in the symsrv*symaudit.dll*\\server\share syntax. The dll is ignored. --- dotnet.sh | 0 .../SymbolService.cs | 115 ++++++++++------- src/SOS/SOS.Extensions/HostServices.cs | 2 +- .../SOS.Hosting/SymbolServiceExtensions.cs | 18 +++ src/SOS/SOS.Hosting/SymbolServiceWrapper.cs | 8 +- .../SymbolServiceTests.cs | 116 ++++++++++++++++++ 6 files changed, 210 insertions(+), 49 deletions(-) mode change 100644 => 100755 dotnet.sh create mode 100644 src/tests/Microsoft.Diagnostics.DebugServices.UnitTests/SymbolServiceTests.cs diff --git a/dotnet.sh b/dotnet.sh old mode 100644 new mode 100755 diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/SymbolService.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/SymbolService.cs index fffb98fca3..f014c23fc2 100644 --- a/src/Microsoft.Diagnostics.DebugServices.Implementation/SymbolService.cs +++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/SymbolService.cs @@ -8,6 +8,7 @@ using Microsoft.SymbolStore.SymbolStores; using SOS; using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.IO; @@ -27,8 +28,8 @@ public class SymbolService : ISymbolService /// /// Symbol server URLs /// - const string MsdlSymbolServer = "http://msdl.microsoft.com/download/symbols/"; - const string SymwebSymbolServer = "http://symweb.corp.microsoft.com/"; + public const string MsdlSymbolServer = "http://msdl.microsoft.com/download/symbols/"; + public const string SymwebSymbolServer = "http://symweb.corp.microsoft.com/"; private readonly IHost _host; private string _defaultSymbolCache; @@ -96,77 +97,103 @@ public bool ParseSymbolPath(string symbolPath) foreach (string path in paths.Reverse()) { - string[] parts = path.Split(new char[] { '*' }, StringSplitOptions.RemoveEmptyEntries); - - // UNC or directory paths are ignored (paths not prefixed with srv* or cache*). + string[] parts = path.Split(new char[] { '*' }, StringSplitOptions.None); if (parts.Length > 0) { - string symbolServerPath = null; - string symbolCachePath = null; + List symbolCachePaths = new(); string symbolDirectoryPath = null; - bool msdl = false; + string symbolServerPath = null; + + void ParseServer(int start) + { + symbolServerPath = MsdlSymbolServer; + for (int i = start; i < parts.Length; i++) + { + if (string.IsNullOrEmpty(parts[i])) + { + // srv** means use default cache + if (i != (parts.Length - 1)) + { + symbolCachePaths.Add(DefaultSymbolCache); + } + } + else if (i < (parts.Length - 1)) + { + symbolCachePaths.Add(parts[i]); + } + else + { + symbolServerPath = parts[i]; + } + } + } switch (parts[0].ToLowerInvariant()) { + case "symsrv": + if (parts.Length <= 2) + { + return false; + } + // ignore symsrv.dll or other server dlls in parts[2] + ParseServer(2); + break; + case "srv": - switch (parts.Length) - { - case 1: - msdl = true; - symbolCachePath = DefaultSymbolCache; - break; - case 2: - symbolServerPath = parts[1]; - break; - case 3: - symbolCachePath = parts[1]; - symbolServerPath = parts[2]; - break; - default: - return false; + if (parts.Length <= 1) + { + return false; } + ParseServer(1); break; case "cache": - switch (parts.Length) - { - case 1: - symbolCachePath = DefaultSymbolCache; - break; - case 2: - symbolCachePath = parts[1]; - break; - default: - return false; + if (parts.Length <= 1) + { + return false; + } + else + { + for (int i = 1; i < parts.Length; i++) + { + if (string.IsNullOrEmpty(parts[i])) + { + if (i == 1) + { + symbolCachePaths.Add(DefaultSymbolCache); + } + } + else + { + symbolCachePaths.Add(parts[i]); + } + } } break; default: // Directory path search - switch (parts.Length) + if (parts.Length != 1) { - case 1: - symbolDirectoryPath = parts[0]; - break; - default: - return false; + return false; } + symbolDirectoryPath = parts[0]; break; } - if (msdl || symbolServerPath != null) + if (symbolServerPath != null) { - if (!AddSymbolServer(msdl, symweb: false, symbolServerPath, authToken: null, timeoutInMinutes: 0)) + if (!AddSymbolServer(msdl: false, symweb: false, symbolServerPath.Trim(), authToken: null, timeoutInMinutes: 0)) { return false; } } - if (symbolCachePath != null) + foreach (string symbolCachePath in symbolCachePaths.Reverse()) { - AddCachePath(symbolCachePath); + AddCachePath(symbolCachePath.Trim()); } if (symbolDirectoryPath != null) { - AddDirectoryPath(symbolDirectoryPath); + AddDirectoryPath(symbolDirectoryPath.Trim()); } } } diff --git a/src/SOS/SOS.Extensions/HostServices.cs b/src/SOS/SOS.Extensions/HostServices.cs index 7424a7ae7d..fb5e4ab587 100644 --- a/src/SOS/SOS.Extensions/HostServices.cs +++ b/src/SOS/SOS.Extensions/HostServices.cs @@ -236,7 +236,7 @@ private HResult RegisterDebuggerServices( hr = DebuggerServices.GetSymbolPath(out string symbolPath); if (hr == HResult.S_OK) { - if (!_symbolService.ParseSymbolPath(symbolPath)) + if (!_symbolService.ParseSymbolPathFixDefault(symbolPath)) { Trace.TraceError("ParseSymbolPath FAILED: {0}", symbolPath); } diff --git a/src/SOS/SOS.Hosting/SymbolServiceExtensions.cs b/src/SOS/SOS.Hosting/SymbolServiceExtensions.cs index 21b4a629b1..285b1cace5 100644 --- a/src/SOS/SOS.Hosting/SymbolServiceExtensions.cs +++ b/src/SOS/SOS.Hosting/SymbolServiceExtensions.cs @@ -21,6 +21,24 @@ public static class SymbolServiceExtensions // HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) const int E_INSUFFICIENT_BUFFER = unchecked((int)0x8007007a); + /// + /// Set the windows symbol path converting the default "srv*" to the cached public symbol server URL. + /// + /// The windows symbol path to translate and set + /// if false, error parsing symbol path + public static bool ParseSymbolPathFixDefault( + this ISymbolService symbolService, + string symbolPath) + { + // Translate dbgeng's default .sympath to what the public version actually does. Normally "srv*" + // means no caching and the server path depends on whether dbgeng is internal or public. + if (symbolPath.ToLowerInvariant() == "srv*") + { + symbolPath = "cache*;SRV*https://msdl.microsoft.com/download/symbols"; + } + return symbolService.ParseSymbolPath(symbolPath); + } + /// /// Metadata locator helper for the DAC. /// diff --git a/src/SOS/SOS.Hosting/SymbolServiceWrapper.cs b/src/SOS/SOS.Hosting/SymbolServiceWrapper.cs index a5cee29318..ea90410b6a 100644 --- a/src/SOS/SOS.Hosting/SymbolServiceWrapper.cs +++ b/src/SOS/SOS.Hosting/SymbolServiceWrapper.cs @@ -157,16 +157,16 @@ private bool InitializeSymbolStore( /// /// Parse the Windows sympath format /// - /// windows symbol path + /// windows symbol path /// if false, failure private bool ParseSymbolPath( IntPtr self, - string windowsSymbolPath) + string symbolPath) { - if (windowsSymbolPath == null) { + if (string.IsNullOrWhiteSpace(symbolPath)) { return false; } - return _symbolService.ParseSymbolPath(windowsSymbolPath); + return _symbolService.ParseSymbolPathFixDefault(symbolPath); } /// diff --git a/src/tests/Microsoft.Diagnostics.DebugServices.UnitTests/SymbolServiceTests.cs b/src/tests/Microsoft.Diagnostics.DebugServices.UnitTests/SymbolServiceTests.cs new file mode 100644 index 0000000000..ab083dcbbd --- /dev/null +++ b/src/tests/Microsoft.Diagnostics.DebugServices.UnitTests/SymbolServiceTests.cs @@ -0,0 +1,116 @@ +// 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 Microsoft.Diagnostics.DebugServices.Implementation; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Xunit; + +namespace Microsoft.Diagnostics.DebugServices.UnitTests +{ + /// + /// Test the service event implementation + /// + public class SymbolServiceTests : IHost + { + public SymbolServiceTests() + { + } + + [Fact] + public void SymbolPathTests() + { + var symbolService = new SymbolService(this); + Assert.False(symbolService.ParseSymbolPath("srv")); + Assert.False(symbolService.ParseSymbolPath("cache")); + Assert.False(symbolService.ParseSymbolPath("symsrv")); + + string defaultServer = $"Server: {SymbolService.MsdlSymbolServer}"; + string defaultPath = $"Cache: {symbolService.DefaultSymbolCache} {defaultServer}"; + string localSymbolCache = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "c:\\localsymbolcache" : "/home/foo/localsymbolcache"; + + Assert.True(symbolService.ParseSymbolPath("srv*")); + Assert.Equal(defaultServer, symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + Assert.True(symbolService.ParseSymbolPath("srv**")); + Assert.Equal(defaultPath, symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + Assert.True(symbolService.ParseSymbolPath("symsrv*symsrv.dll*")); + Assert.Equal(defaultServer, symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + Assert.True(symbolService.ParseSymbolPath("cache*;srv*")); + Assert.Equal(defaultPath, symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + Assert.True(symbolService.ParseSymbolPath("srv*http://msdl.microsoft.com/download/symbols/")); + Assert.Equal(defaultServer, symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + Assert.True(symbolService.ParseSymbolPath($"srv**{SymbolService.MsdlSymbolServer}")); + Assert.Equal(defaultPath, symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + Assert.True(symbolService.ParseSymbolPath($"srv*{localSymbolCache}*{SymbolService.SymwebSymbolServer}")); + string testpath1 = $"Cache: {localSymbolCache} Server: {SymbolService.SymwebSymbolServer}"; + Assert.Equal(testpath1, symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + Assert.True(symbolService.ParseSymbolPath($"cache*{localSymbolCache};srv*")); + string testpath2 = $"Cache: {localSymbolCache} Server: {SymbolService.MsdlSymbolServer}"; + Assert.Equal(testpath2, symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + Assert.True(symbolService.ParseSymbolPath($"srv**{localSymbolCache}*http://msdl.microsoft.com/download/symbols/")); + Assert.Equal($"Cache: {symbolService.DefaultSymbolCache} Cache: {localSymbolCache} Server: http://msdl.microsoft.com/download/symbols/", symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Assert.True(symbolService.ParseSymbolPath($"symsrv*symsrv.dll*{localSymbolCache}*\\\\server\\share")); + Assert.Equal($"Cache: {localSymbolCache} Cache: \\\\server\\share", symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + Assert.True(symbolService.ParseSymbolPath("symsrv*symsrv.dll*d:\\data\\SYM\\symcache*\\\\aw0eus0symcache.file.core.windows.net\\Symbols*http://localhost/remote200/30e07e1454924e55901d7f693f7eddf1/0/x64/4542784547/remote")); + Assert.Equal("Cache: d:\\data\\SYM\\symcache Cache: \\\\aw0eus0symcache.file.core.windows.net\\Symbols Server: http://localhost/remote200/30e07e1454924e55901d7f693f7eddf1/0/x64/4542784547/remote/", symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + } + + string symbolDirectory = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "c:\\symbols\\" : "/home/foo/symbols/"; + Assert.True(symbolService.ParseSymbolPath(symbolDirectory)); + Assert.Equal($"Directory: {symbolDirectory}", symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + + string symbolDirectory2 = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "c:\\foo\\bar" : "/home/foo/bar"; + Assert.True(symbolService.ParseSymbolPath($"{symbolDirectory};{symbolDirectory2};srv*")); + Assert.Equal($"Directory: {symbolDirectory} Directory: {symbolDirectory2} " + defaultServer, symbolService.FormatSymbolStores()); + symbolService.DisableSymbolStore(); + } + + #region IHost + + public IServiceEvent OnShutdownEvent { get; } = new ServiceEvent(); + + HostType IHost.HostType => HostType.DotnetDump; + + IServiceProvider IHost.Services => throw new NotImplementedException(); + + IEnumerable IHost.EnumerateTargets() => throw new NotImplementedException(); + + void IHost.DestroyTarget(ITarget target) => throw new NotImplementedException(); + + #endregion + } + public static class SymbolServiceExtensions + { + public static string FormatSymbolStores( + this ISymbolService symbolService) + { + return symbolService.ToString().Replace(Environment.NewLine, " ").TrimEnd(); + } + } +} From 36cf3aac5c452981a1afc745e4e63838c39d205a Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Mon, 20 Sep 2021 14:29:34 -0700 Subject: [PATCH 4/6] Minor doc updates --- documentation/FAQ.md | 2 ++ documentation/debugging-coredump.md | 2 ++ documentation/lldb/linux-instructions.md | 10 ++-------- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/documentation/FAQ.md b/documentation/FAQ.md index bc42c7d914..589dc107ae 100644 --- a/documentation/FAQ.md +++ b/documentation/FAQ.md @@ -1,6 +1,8 @@ Frequently Asked Questions ========================== +* `dotnet-dump analyze` running on Windows doesn't support MacOS .NET 5.0 and 6.0 core dumps. `dotnet-dump` running on MacOS does support .NET 5.0 but not 6.0 core dumps (which will be fixed in a future dotnet-dump release). MacOS .NET 6.0 core dumps generated by the runtime via [createdump](https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/xplat-minidump-generation.md#os-x) are supported by lldb/SOS running on MacOS. + * If SOS or dotnet-dump analyze commands display "UNKNOWN" for types or functions names, your core dump may not have all the managed state. Dumps created with gdb or gcore have this problem. Linux system generated core dumps need the `coredump_filter` for the process to be set to at least 0x3f. See [core](http://man7.org/linux/man-pages/man5/core.5.html) for more information. * If dump collection (`dotnet-dump collect` or `createdump`) doesn't work in a docker container, try adding the SYS\_TRACE capability with --cap-add=SYS\_PTRACE or --privileged. diff --git a/documentation/debugging-coredump.md b/documentation/debugging-coredump.md index 1fc9699f93..eb43cee166 100644 --- a/documentation/debugging-coredump.md +++ b/documentation/debugging-coredump.md @@ -72,6 +72,8 @@ Even if the core dump was not generated on this machine, the native and managed Follow the rest of the above Linux steps to set the symbol server and load native symbols. +NOTE: The following issue has been fixed with .NET 6.0 core dumps generated by the runtime (see [createdump](https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/xplat-minidump-generation.md#os-x)) with a recent version of SOS. + The MacOS lldb has a bug that prevents SOS clrstack from properly working. Because of this bug SOS can't properly match the lldb native with with the managed thread OSID displayed by `clrthreads`. The `setsostid` command is a work around for this lldb bug. This command maps the OSID from this command: ``` diff --git a/documentation/lldb/linux-instructions.md b/documentation/lldb/linux-instructions.md index 75155780f9..efb15082a6 100644 --- a/documentation/lldb/linux-instructions.md +++ b/documentation/lldb/linux-instructions.md @@ -88,15 +88,9 @@ To install the lldb packages: This installs lldb version 10.0.0. -#### Alpine 3.9 #### +#### Alpine 3.9 to 3.12 #### -Currently there is no lldb that works on Alpine. - -Issue https://github.com/dotnet/diagnostics/issues/73 - -#### Alpine 3.12 #### - -lldb 10.0 is available for this Apline version. +lldb 10.0 is available and works for these Apline versions. #### CentOS 6 #### From 2f7229cf42b48a39b9fe0da548946b0bd2ebaaed Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Mon, 20 Sep 2021 15:11:55 -0700 Subject: [PATCH 5/6] Better loadsymbols error message when no server is set --- src/SOS/Strike/strike.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index 4e81058a65..74cbfee3ff 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -16748,7 +16748,15 @@ DECLARE_API(SetSymbolServer) #ifdef FEATURE_PAL else if (loadNative) { - Status = LoadNativeSymbols(); + if (g_symbolStoreInitialized) + { + Status = LoadNativeSymbols(); + } + else + { + ExtErr("Symbol server not set\n"); + return E_FAIL; + } } #endif else From 02308e9ae349656291a85c7a089569d97c4cae1b Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Mon, 20 Sep 2021 15:15:33 -0700 Subject: [PATCH 6/6] Better loadsymbols error message when no server is set --- src/SOS/Strike/strike.cpp | 8 ++------ src/SOS/Strike/symbols.cpp | 5 ++--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index 74cbfee3ff..7a6038376a 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -16748,14 +16748,10 @@ DECLARE_API(SetSymbolServer) #ifdef FEATURE_PAL else if (loadNative) { - if (g_symbolStoreInitialized) - { - Status = LoadNativeSymbols(); - } - else + Status = LoadNativeSymbols(); + if (FAILED(Status)) { ExtErr("Symbol server not set\n"); - return E_FAIL; } } #endif diff --git a/src/SOS/Strike/symbols.cpp b/src/SOS/Strike/symbols.cpp index 5076eaf3b5..1ee366f4b8 100644 --- a/src/SOS/Strike/symbols.cpp +++ b/src/SOS/Strike/symbols.cpp @@ -173,12 +173,11 @@ static void LoadNativeSymbolsCallback(void* param, const char* moduleFilePath, U \**********************************************************************/ HRESULT LoadNativeSymbols(bool runtimeOnly) { - HRESULT hr = S_OK; if (g_symbolStoreInitialized) { - hr = g_ExtServices2->LoadNativeSymbols(runtimeOnly, LoadNativeSymbolsCallback); + return g_ExtServices2->LoadNativeSymbols(runtimeOnly, LoadNativeSymbolsCallback); } - return hr; + return E_FAIL; } #endif