Allow ` in hex strings (#4379)
authorLee Culver <leculver@microsoft.com>
Tue, 31 Oct 2023 22:26:48 +0000 (15:26 -0700)
committerGitHub <noreply@github.com>
Tue, 31 Oct 2023 22:26:48 +0000 (22:26 +0000)
Update extension command parsing to allow a single \` in the middle of
addresses. We allow "\`0123" because the user might have copied the \`
marker in "0000\`0123". This makes commands more consistent since the
C++ based SOS commands allow for \` in the addresses.

Updated a location where we didn't use TryParseAddress but should have.

Feature request from the GC team.

src/Microsoft.Diagnostics.DebugServices/CommandBase.cs
src/Microsoft.Diagnostics.ExtensionCommands/DumpHeapCommand.cs
src/Microsoft.Diagnostics.ExtensionCommands/EEHeapCommand.cs
src/Microsoft.Diagnostics.ExtensionCommands/HeapWithFilters.cs
src/Microsoft.Diagnostics.ExtensionCommands/VerifyHeapCommand.cs

index e843fd9879338bac4492e7d45f72f3ddffc05e03..39c0508fae960bbffdcda86d7fb73674b3301f04 100644 (file)
@@ -91,7 +91,7 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <returns></returns>
         protected bool TryParseAddress(string addressInHexa, out ulong address)
         {
-            if (addressInHexa == null)
+            if (string.IsNullOrWhiteSpace(addressInHexa))
             {
                 address = 0;
                 return false;
@@ -105,6 +105,13 @@ namespace Microsoft.Diagnostics.DebugServices
 
             addressInHexa = addressInHexa.TrimStart('0');
 
+            int index = addressInHexa.IndexOf('`');
+            if (index >= 0 && index < addressInHexa.Length - 1)
+            {
+                // Remove up to one instance of ` since that's what WinDbg adds to its x64 addresses.
+                addressInHexa = addressInHexa.Substring(0, index) + addressInHexa.Substring(index + 1);
+            }
+
             return ulong.TryParse(addressInHexa, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out address);
         }
 
index da718cf8d64de90408829cfa9566ad2b32b33cae..d23e68e5b07079ea3438bd00ef16d9ba183e1127 100644 (file)
@@ -197,9 +197,13 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                 FilteredHeap.GCHeap = GCHeap;
             }
 
-            if (!string.IsNullOrWhiteSpace(Segment))
+            if (TryParseAddress(Segment, out ulong segment))
             {
-                FilteredHeap.FilterBySegmentHex(Segment);
+                FilteredHeap.FilterBySegmentHex(segment);
+            }
+            else if (!string.IsNullOrWhiteSpace(Segment))
+            {
+                throw new DiagnosticsException($"Failed to parse segment '{Segment}'.");
             }
 
             if (MemoryRange is not null && MemoryRange.Length > 0)
index 59fb9fc3cef166fc87a6053c66cca042bebb3acb..85daeabb62b792c4a542b6efe0bc5cdf2da779a4 100644 (file)
@@ -54,9 +54,13 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                 HeapWithFilters.GCHeap = GCHeap;
             }
 
-            if (!string.IsNullOrWhiteSpace(Segment))
+            if (TryParseAddress(Segment, out ulong segment))
             {
-                HeapWithFilters.FilterBySegmentHex(Segment);
+                HeapWithFilters.FilterBySegmentHex(segment);
+            }
+            else if (!string.IsNullOrWhiteSpace(Segment))
+            {
+                throw new DiagnosticsException($"Failed to parse segment '{Segment}'.");
             }
 
             if (MemoryRange is not null)
index b8abc377828c2ab0ce00219cd12f31eb89ff48c1..36c229157a4a96c403a35229c25b3999558a0f1e 100644 (file)
@@ -85,19 +85,9 @@ namespace Microsoft.Diagnostics.ExtensionCommands
             SortSubHeaps = (heap) => heap.OrderBy(heap => heap.Index);
         }
 
-        public void FilterBySegmentHex(string segmentStr)
+        public void FilterBySegmentHex(ulong segment)
         {
-            if (!ulong.TryParse(segmentStr, NumberStyles.HexNumber, null, out ulong segment))
-            {
-                throw new ArgumentException($"Invalid segment address: {segmentStr}");
-            }
-
-            if (ThrowIfNoMatchingGCRegions && !_heap.Segments.Any(seg => seg.Address == segment || seg.CommittedMemory.Contains(segment)))
-            {
-                throw new ArgumentException($"No segments match address: {segment:x}");
-            }
-
-            Segment = segment;
+            Segment = segment != 0 ? segment : null;
         }
 
         public void FilterByStringMemoryRange(string[] memoryRange, string commandName)
index 30640369822d632182fd7976df70921c368c37e9..a7645b4d820d3062d4ead51cecb92f97409d90f4 100644 (file)
@@ -39,9 +39,13 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                 filteredHeap.GCHeap = GCHeap;
             }
 
-            if (!string.IsNullOrWhiteSpace(Segment))
+            if (TryParseAddress(Segment, out ulong segment))
             {
-                filteredHeap.FilterBySegmentHex(Segment);
+                filteredHeap.FilterBySegmentHex(segment);
+            }
+            else if (!string.IsNullOrWhiteSpace(Segment))
+            {
+                throw new DiagnosticsException($"Failed to parse segment '{Segment}'.");
             }
 
             if (MemoryRange is not null)