Skip to content

Commit 9ed640d

Browse files
committed
Handle very large inputs
- Switch to using List<string> instead of string[] to avoid exceeding array dimension limits when parsing large inputs.
1 parent 01b882a commit 9ed640d

4 files changed

Lines changed: 30 additions & 19 deletions

File tree

Engine/DLLOrdinalHelper.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@ internal void Initialize() {
1313
}
1414

1515
/// This function loads DLLs from a specified path, so that we can then build the DLL export's ordinal / address map
16-
internal string[] LoadDllsIfApplicable(string[] callstackFrames, bool recurse, List<string> dllPaths) {
16+
internal List<string> LoadDllsIfApplicable(List<string> callstackFrames, bool recurse, List<string> dllPaths) {
1717
if (dllPaths == null) return callstackFrames;
1818

19-
var processedFrames = new string[callstackFrames.Length];
20-
for (var idx = 0; idx < callstackFrames.Length; idx++) {
21-
var callstack = callstackFrames[idx];
19+
var processedFrames = new List<string>(callstackFrames.Count);
20+
foreach (var callstack in callstackFrames) {
2221
// first we seek out distinct module names in this call stack
2322
// note that such frames will only be seen in the call stack when trace flag 3656 is enabled, but there were no PDBs in the BINN folder
2423
// sample frames are given below
@@ -47,7 +46,7 @@ internal string[] LoadDllsIfApplicable(string[] callstackFrames, bool recurse, L
4746

4847
// finally do a pattern based replace the replace method calls a delegate (ReplaceOrdinalWithRealOffset) which figures
4948
// out the start address of the ordinal and then computes the actual offset
50-
processedFrames[idx] = fullpattern.Replace(callstack, ReplaceOrdinalWithRealOffset);
49+
processedFrames.Add(fullpattern.Replace(callstack, ReplaceOrdinalWithRealOffset));
5150
}
5251
return processedFrames;
5352
}

Engine/ModuleInfoHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public async static Task<Dictionary<string, Symbol>> ParseModuleInfoAsync(List<S
1313
bool anyTaskFailed = false;
1414
await Task.Run(() => Parallel.ForEach(listOfCallStacks.Where(c => c.Callstack.Contains(",")).Select(c => c.CallstackFrames), lines => {
1515
if (cts.IsCancellationRequested) return;
16-
Contract.Requires(lines.Length > 0);
16+
Contract.Requires(lines.Count > 0);
1717
foreach (var line in lines) {
1818
if (cts.IsCancellationRequested) return;
1919
string moduleName = null, pdbName = null;

Engine/StackDetails.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,23 @@ public string Callstack {
2424
set { this._callStack = value; }
2525
}
2626

27-
public string[] CallstackFrames {
27+
public List<string> CallstackFrames {
2828
get {
2929
// sometimes we see call stacks which are arranged horizontally (this typically is seen when copy-pasting directly
3030
// from the SSMS XEvent window (copying the callstack field without opening it in its own viewer)
3131
// in that case, space is a valid delimiter, and we need to support that as an option
3232
var delims = this._framesOnSingleLine ? new char[] { '\t', '\n' } : new char[] { '\n' };
3333
if (!this._relookupSource && this._framesOnSingleLine) delims = delims.Append(' ').ToArray();
34-
return this._callStack.Replace("\r", string.Empty).Split(delims);
34+
35+
var result = new List<string>();
36+
using (var reader = new StringReader(this._callStack.Replace("\r", string.Empty))) {
37+
string line;
38+
while ((line = reader.ReadLine()) != null) {
39+
result.AddRange(line.Split(delims, StringSplitOptions.RemoveEmptyEntries));
40+
}
41+
}
42+
43+
return result;
3544
}
3645
}
3746
public string Resolvedstack {

Engine/StackResolver.cs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,26 @@ public async Task<Tuple<int, string>> ExtractFromXELAsync(string[] xelFiles, boo
3939
}
4040

4141
/// Convert virtual-address only type frames to their module+offset format
42-
private string[] PreProcessVAs(string[] callStackLines, CancellationTokenSource cts) {
43-
string[] retval = new string[callStackLines.Length];
44-
int frameNum = 0;
42+
private List<string> PreProcessVAs(List<string> callStackLines, CancellationTokenSource cts) {
43+
var retval = new List<string>(callStackLines.Count);
44+
4545
foreach (var currentFrame in callStackLines) {
4646
if (cts.IsCancellationRequested) return callStackLines;
47-
// let's see if this is an VA-only address
47+
48+
// Check if the frame is a VA-only address
4849
var matchVA = rgxVAOnly.Match(currentFrame);
4950
if (matchVA.Success) {
5051
ulong virtAddress = Convert.ToUInt64(matchVA.Groups["vaddress"].Value, 16);
51-
retval[frameNum] = TryObtainModuleOffset(virtAddress, out string moduleName, out uint offset)
52-
? string.Format(CultureInfo.CurrentCulture, "{0}+0x{1:X}", moduleName, offset)
53-
: currentFrame.Trim();
52+
if (TryObtainModuleOffset(virtAddress, out string moduleName, out uint offset)) {
53+
retval.Add(string.Format(CultureInfo.CurrentCulture, "{0}+0x{1:X}", moduleName, offset));
54+
} else {
55+
retval.Add(currentFrame.Trim());
56+
}
57+
} else {
58+
retval.Add(currentFrame.Trim());
5459
}
55-
else retval[frameNum] = currentFrame.Trim();
56-
57-
frameNum++;
5860
}
61+
5962
return retval;
6063
}
6164

@@ -83,7 +86,7 @@ public bool IsInputVAOnly(string text) {
8386
}
8487

8588
/// Runs through each of the frames in a call stack and looks up symbols for each
86-
private string ResolveSymbols(Dictionary<string, DiaUtil> _diautils, Dictionary<string, string> moduleNamesMap, string[] callStackLines, string userSuppliedSymPath, string symSrvSymPath, bool searchPDBsRecursively, bool cachePDB, bool includeSourceInfo, bool relookupSource, bool includeOffsets, bool showInlineFrames, List<string> modulesToIgnore, CancellationTokenSource cts) {
89+
private string ResolveSymbols(Dictionary<string, DiaUtil> _diautils, Dictionary<string, string> moduleNamesMap, List<string> callStackLines, string userSuppliedSymPath, string symSrvSymPath, bool searchPDBsRecursively, bool cachePDB, bool includeSourceInfo, bool relookupSource, bool includeOffsets, bool showInlineFrames, List<string> modulesToIgnore, CancellationTokenSource cts) {
8790
var finalCallstack = new StringBuilder();
8891
int runningFrameNum = int.MinValue;
8992
foreach (var iterFrame in callStackLines) {

0 commit comments

Comments
 (0)