Skip to content

Commit cdcb72d

Browse files
authored
Fix misc SOS bugs (#2600)
Fix misc SOS bugs * Fix bug in the AddFilesFromDirectoryToTpaList issue: #2596 * Added some logging to GetLineByOffset * Improve SymbolService.ParseSymbolPath support for Watson. Issue #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. * Minor doc updates * Better loadsymbols error message when no server is set
1 parent 1109289 commit cdcb72d

File tree

13 files changed

+251
-78
lines changed

13 files changed

+251
-78
lines changed

documentation/FAQ.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Frequently Asked Questions
22
==========================
33

4+
* `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.
5+
46
* 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.
57

68
* 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.

documentation/debugging-coredump.md

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ Even if the core dump was not generated on this machine, the native and managed
7272

7373
Follow the rest of the above Linux steps to set the symbol server and load native symbols.
7474

75+
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.
76+
7577
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:
7678

7779
```

documentation/lldb/linux-instructions.md

+2-8
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,9 @@ To install the lldb packages:
8888

8989
This installs lldb version 10.0.0.
9090

91-
#### Alpine 3.9 ####
91+
#### Alpine 3.9 to 3.12 ####
9292

93-
Currently there is no lldb that works on Alpine.
94-
95-
Issue https://github.com/dotnet/diagnostics/issues/73
96-
97-
#### Alpine 3.12 ####
98-
99-
lldb 10.0 is available for this Apline version.
93+
lldb 10.0 is available and works for these Apline versions.
10094

10195
#### CentOS 6 ####
10296

dotnet.sh

100644100755
File mode changed.

src/Microsoft.Diagnostics.DebugServices.Implementation/SymbolService.cs

+71-44
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Microsoft.SymbolStore.SymbolStores;
99
using SOS;
1010
using System;
11+
using System.Collections.Generic;
1112
using System.Collections.Immutable;
1213
using System.Diagnostics;
1314
using System.IO;
@@ -27,8 +28,8 @@ public class SymbolService : ISymbolService
2728
/// <summary>
2829
/// Symbol server URLs
2930
/// </summary>
30-
const string MsdlSymbolServer = "http://msdl.microsoft.com/download/symbols/";
31-
const string SymwebSymbolServer = "http://symweb.corp.microsoft.com/";
31+
public const string MsdlSymbolServer = "http://msdl.microsoft.com/download/symbols/";
32+
public const string SymwebSymbolServer = "http://symweb.corp.microsoft.com/";
3233

3334
private readonly IHost _host;
3435
private string _defaultSymbolCache;
@@ -96,77 +97,103 @@ public bool ParseSymbolPath(string symbolPath)
9697

9798
foreach (string path in paths.Reverse())
9899
{
99-
string[] parts = path.Split(new char[] { '*' }, StringSplitOptions.RemoveEmptyEntries);
100-
101-
// UNC or directory paths are ignored (paths not prefixed with srv* or cache*).
100+
string[] parts = path.Split(new char[] { '*' }, StringSplitOptions.None);
102101
if (parts.Length > 0)
103102
{
104-
string symbolServerPath = null;
105-
string symbolCachePath = null;
103+
List<string> symbolCachePaths = new();
106104
string symbolDirectoryPath = null;
107-
bool msdl = false;
105+
string symbolServerPath = null;
106+
107+
void ParseServer(int start)
108+
{
109+
symbolServerPath = MsdlSymbolServer;
110+
for (int i = start; i < parts.Length; i++)
111+
{
112+
if (string.IsNullOrEmpty(parts[i]))
113+
{
114+
// srv** means use default cache
115+
if (i != (parts.Length - 1))
116+
{
117+
symbolCachePaths.Add(DefaultSymbolCache);
118+
}
119+
}
120+
else if (i < (parts.Length - 1))
121+
{
122+
symbolCachePaths.Add(parts[i]);
123+
}
124+
else
125+
{
126+
symbolServerPath = parts[i];
127+
}
128+
}
129+
}
108130

109131
switch (parts[0].ToLowerInvariant())
110132
{
133+
case "symsrv":
134+
if (parts.Length <= 2)
135+
{
136+
return false;
137+
}
138+
// ignore symsrv.dll or other server dlls in parts[2]
139+
ParseServer(2);
140+
break;
141+
111142
case "srv":
112-
switch (parts.Length)
113-
{
114-
case 1:
115-
msdl = true;
116-
symbolCachePath = DefaultSymbolCache;
117-
break;
118-
case 2:
119-
symbolServerPath = parts[1];
120-
break;
121-
case 3:
122-
symbolCachePath = parts[1];
123-
symbolServerPath = parts[2];
124-
break;
125-
default:
126-
return false;
143+
if (parts.Length <= 1)
144+
{
145+
return false;
127146
}
147+
ParseServer(1);
128148
break;
129149

130150
case "cache":
131-
switch (parts.Length)
132-
{
133-
case 1:
134-
symbolCachePath = DefaultSymbolCache;
135-
break;
136-
case 2:
137-
symbolCachePath = parts[1];
138-
break;
139-
default:
140-
return false;
151+
if (parts.Length <= 1)
152+
{
153+
return false;
154+
}
155+
else
156+
{
157+
for (int i = 1; i < parts.Length; i++)
158+
{
159+
if (string.IsNullOrEmpty(parts[i]))
160+
{
161+
if (i == 1)
162+
{
163+
symbolCachePaths.Add(DefaultSymbolCache);
164+
}
165+
}
166+
else
167+
{
168+
symbolCachePaths.Add(parts[i]);
169+
}
170+
}
141171
}
142172
break;
143173

144174
default:
145175
// Directory path search
146-
switch (parts.Length)
176+
if (parts.Length != 1)
147177
{
148-
case 1:
149-
symbolDirectoryPath = parts[0];
150-
break;
151-
default:
152-
return false;
178+
return false;
153179
}
180+
symbolDirectoryPath = parts[0];
154181
break;
155182
}
156-
if (msdl || symbolServerPath != null)
183+
if (symbolServerPath != null)
157184
{
158-
if (!AddSymbolServer(msdl, symweb: false, symbolServerPath, authToken: null, timeoutInMinutes: 0))
185+
if (!AddSymbolServer(msdl: false, symweb: false, symbolServerPath.Trim(), authToken: null, timeoutInMinutes: 0))
159186
{
160187
return false;
161188
}
162189
}
163-
if (symbolCachePath != null)
190+
foreach (string symbolCachePath in symbolCachePaths.Reverse<string>())
164191
{
165-
AddCachePath(symbolCachePath);
192+
AddCachePath(symbolCachePath.Trim());
166193
}
167194
if (symbolDirectoryPath != null)
168195
{
169-
AddDirectoryPath(symbolDirectoryPath);
196+
AddDirectoryPath(symbolDirectoryPath.Trim());
170197
}
171198
}
172199
}

src/SOS/SOS.Extensions/HostServices.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ private HResult RegisterDebuggerServices(
236236
hr = DebuggerServices.GetSymbolPath(out string symbolPath);
237237
if (hr == HResult.S_OK)
238238
{
239-
if (!_symbolService.ParseSymbolPath(symbolPath))
239+
if (!_symbolService.ParseSymbolPathFixDefault(symbolPath))
240240
{
241241
Trace.TraceError("ParseSymbolPath FAILED: {0}", symbolPath);
242242
}

src/SOS/SOS.Hosting/SymbolServiceExtensions.cs

+18
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ public static class SymbolServiceExtensions
2121
// HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
2222
const int E_INSUFFICIENT_BUFFER = unchecked((int)0x8007007a);
2323

24+
/// <summary>
25+
/// Set the windows symbol path converting the default "srv*" to the cached public symbol server URL.
26+
/// </summary>
27+
/// <param name="symbolPath">The windows symbol path to translate and set</param>
28+
/// <returns>if false, error parsing symbol path</returns>
29+
public static bool ParseSymbolPathFixDefault(
30+
this ISymbolService symbolService,
31+
string symbolPath)
32+
{
33+
// Translate dbgeng's default .sympath to what the public version actually does. Normally "srv*"
34+
// means no caching and the server path depends on whether dbgeng is internal or public.
35+
if (symbolPath.ToLowerInvariant() == "srv*")
36+
{
37+
symbolPath = "cache*;SRV*https://msdl.microsoft.com/download/symbols";
38+
}
39+
return symbolService.ParseSymbolPath(symbolPath);
40+
}
41+
2442
/// <summary>
2543
/// Metadata locator helper for the DAC.
2644
/// </summary>

src/SOS/SOS.Hosting/SymbolServiceWrapper.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -157,16 +157,16 @@ private bool InitializeSymbolStore(
157157
/// <summary>
158158
/// Parse the Windows sympath format
159159
/// </summary>
160-
/// <param name="windowsSymbolPath">windows symbol path</param>
160+
/// <param name="symbolPath">windows symbol path</param>
161161
/// <returns>if false, failure</returns>
162162
private bool ParseSymbolPath(
163163
IntPtr self,
164-
string windowsSymbolPath)
164+
string symbolPath)
165165
{
166-
if (windowsSymbolPath == null) {
166+
if (string.IsNullOrWhiteSpace(symbolPath)) {
167167
return false;
168168
}
169-
return _symbolService.ParseSymbolPath(windowsSymbolPath);
169+
return _symbolService.ParseSymbolPathFixDefault(symbolPath);
170170
}
171171

172172
/// <summary>

src/SOS/Strike/strike.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -16749,6 +16749,10 @@ DECLARE_API(SetSymbolServer)
1674916749
else if (loadNative)
1675016750
{
1675116751
Status = LoadNativeSymbols();
16752+
if (FAILED(Status))
16753+
{
16754+
ExtErr("Symbol server not set\n");
16755+
}
1675216756
}
1675316757
#endif
1675416758
else

src/SOS/Strike/symbols.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,11 @@ static void LoadNativeSymbolsCallback(void* param, const char* moduleFilePath, U
173173
\**********************************************************************/
174174
HRESULT LoadNativeSymbols(bool runtimeOnly)
175175
{
176-
HRESULT hr = S_OK;
177176
if (g_symbolStoreInitialized)
178177
{
179-
hr = g_ExtServices2->LoadNativeSymbols(runtimeOnly, LoadNativeSymbolsCallback);
178+
return g_ExtServices2->LoadNativeSymbols(runtimeOnly, LoadNativeSymbolsCallback);
180179
}
181-
return hr;
180+
return E_FAIL;
182181
}
183182

184183
#endif

src/SOS/Strike/util.cpp

+15-8
Original file line numberDiff line numberDiff line change
@@ -5109,23 +5109,30 @@ GetLineByOffset(
51095109
___in ULONG cchFileName,
51105110
___in BOOL bAdjustOffsetForLineNumber /* = FALSE */)
51115111
{
5112-
HRESULT Status = S_OK;
5112+
HRESULT status = S_OK;
51135113
ULONG32 methodToken;
51145114
ULONG32 methodOffs;
51155115

51165116
// Find the image, method token and IL offset that correspond to "nativeOffset"
51175117
ToRelease<IXCLRDataModule> pModule(NULL);
5118-
IfFailRet(ConvertNativeToIlOffset(nativeOffset, bAdjustOffsetForLineNumber, &pModule, &methodToken, &methodOffs));
5119-
5118+
status = ConvertNativeToIlOffset(nativeOffset, bAdjustOffsetForLineNumber, &pModule, &methodToken, &methodOffs);
5119+
if (FAILED(status))
5120+
{
5121+
ExtDbgOut("GetLineByOffset(%p): ConvertNativeToIlOffset FAILED %08x\n", nativeOffset, status);
5122+
return status;
5123+
}
51205124
ToRelease<IMetaDataImport> pMDImport(NULL);
5121-
Status = pModule->QueryInterface(IID_IMetaDataImport, (LPVOID *) &pMDImport);
5122-
if (FAILED(Status))
5125+
status = pModule->QueryInterface(IID_IMetaDataImport, (LPVOID *) &pMDImport);
5126+
if (FAILED(status))
51235127
{
5124-
ExtDbgOut("GetLineByOffset(%p): QueryInterface(IID_IMetaDataImport) FAILED %08x\n", nativeOffset, Status);
5128+
ExtDbgOut("GetLineByOffset(%p): QueryInterface(IID_IMetaDataImport) FAILED %08x\n", nativeOffset, status);
51255129
}
51265130
SymbolReader symbolReader;
5127-
IfFailRet(symbolReader.LoadSymbols(pMDImport, pModule));
5128-
5131+
status = symbolReader.LoadSymbols(pMDImport, pModule);
5132+
if (FAILED(status))
5133+
{
5134+
return status;
5135+
}
51295136
return symbolReader.GetLineByILOffset(methodToken, methodOffs, pLinenum, pwszFileName, cchFileName);
51305137
}
51315138

src/SOS/extensions/hostcoreclr.cpp

+14-10
Original file line numberDiff line numberDiff line change
@@ -220,19 +220,23 @@ static void AddFilesFromDirectoryToTpaList(const char* directory, std::string& t
220220
const char extension[] = ".dll";
221221
std::string filename(find.FileName());
222222
size_t extLen = sizeof(extension) - 1;
223-
size_t extPos = filename.length() - extLen;
224-
225-
// Check if the extension matches the one we are looking for
226-
if ((extPos > 0) && (filename.compare(extPos, extLen, extension) == 0))
223+
size_t extPos = filename.length();
224+
if (extPos > extLen)
227225
{
228-
std::string filenameWithoutExt(filename.substr(0, extPos));
226+
extPos -= extLen;
229227

230-
// Make sure if we have an assembly with multiple extensions present,
231-
// we insert only one version of it.
232-
if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end())
228+
// Check if the extension matches the one we are looking for
229+
if (filename.compare(extPos, extLen, extension) == 0)
233230
{
234-
addedAssemblies.insert(filenameWithoutExt);
235-
AddFileToTpaList(directory, filename.c_str(), tpaList);
231+
std::string filenameWithoutExt(filename.substr(0, extPos));
232+
233+
// Make sure if we have an assembly with multiple extensions present,
234+
// we insert only one version of it.
235+
if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end())
236+
{
237+
addedAssemblies.insert(filenameWithoutExt);
238+
AddFileToTpaList(directory, filename.c_str(), tpaList);
239+
}
236240
}
237241
}
238242
}

0 commit comments

Comments
 (0)