@@ -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 ;
@@ -75,26 +75,27 @@ await Task.Run(() => Parallel.ForEach(listOfCallStacks, currItem => {
7575 // next, replace any pre-post stuff from the XML frame lines
7676 currItem . Callstack = Regex . Replace ( currItem . Callstack , @"(?<prefix>.*?)(?<retain>\<frame.+\/\>)(?<suffix>.*?)" , "${retain}" ) ;
7777 if ( cts . IsCancellationRequested ) return ;
78-
79- foreach ( var line in currItem . Callstack . Split ( '\n ' ) ) {
78+ using var reader = new StringReader ( currItem . Callstack ) ;
79+ string line ;
80+ while ( ( line = reader . ReadLine ( ) ) != null ) {
8081 if ( cts . IsCancellationRequested ) return ;
8182 if ( ! string . IsNullOrWhiteSpace ( line ) && line . StartsWith ( "<frame" ) ) { // only attempt further formal XML parsing if a simple text check works
8283 try {
8384 using var sreader = new StringReader ( line ) ;
84- using var reader = XmlReader . Create ( sreader , new XmlReaderSettings ( ) { XmlResolver = null } ) ;
85- if ( reader . Read ( ) ) {
85+ using var xmlReader = XmlReader . Create ( sreader , new XmlReaderSettings ( ) { XmlResolver = null } ) ;
86+ if ( xmlReader . Read ( ) ) {
8687 // seems to be XML; start reading attributes
87- var moduleNameAttributeVal = reader . GetAttribute ( "module" ) ;
88- if ( string . IsNullOrEmpty ( moduleNameAttributeVal ) ) moduleNameAttributeVal = reader . GetAttribute ( "name" ) ;
88+ var moduleNameAttributeVal = xmlReader . GetAttribute ( "module" ) ;
89+ if ( string . IsNullOrEmpty ( moduleNameAttributeVal ) ) moduleNameAttributeVal = xmlReader . GetAttribute ( "name" ) ;
8990 var moduleName = Path . GetFileNameWithoutExtension ( moduleNameAttributeVal ) ;
90- var addressAttributeVal = reader . GetAttribute ( "address" ) ;
91+ var addressAttributeVal = xmlReader . GetAttribute ( "address" ) ;
9192 ulong addressIfPresent = string . IsNullOrEmpty ( addressAttributeVal ) ? ulong . MinValue : Convert . ToUInt64 ( addressAttributeVal , 16 ) ;
92- var rvaAttributeVal = reader . GetAttribute ( "rva" ) ;
93+ var rvaAttributeVal = xmlReader . GetAttribute ( "rva" ) ;
9394 ulong rvaIfPresent = string . IsNullOrEmpty ( rvaAttributeVal ) ? ulong . MinValue : Convert . ToUInt64 ( rvaAttributeVal , 16 ) ;
9495 ulong calcBaseAddress = ulong . MinValue ;
9596 if ( rvaIfPresent != ulong . MinValue && addressIfPresent != ulong . MinValue ) calcBaseAddress = addressIfPresent - rvaIfPresent ;
96- var pdbGuid = reader . GetAttribute ( "guid" ) ;
97- var pdbAge = reader . GetAttribute ( "age" ) ;
97+ var pdbGuid = xmlReader . GetAttribute ( "guid" ) ;
98+ var pdbAge = xmlReader . GetAttribute ( "age" ) ;
9899 string uniqueModuleName ;
99100 // Create a map of the last mapped module names to handle future cases when the frame is "truncated" and the above PDB details are not available
100101 if ( pdbGuid != null && pdbAge != null ) {
@@ -112,7 +113,7 @@ await Task.Run(() => Parallel.ForEach(listOfCallStacks, currItem => {
112113 lock ( syms ) {
113114 if ( syms . TryGetValue ( uniqueModuleName , out var existingEntry ) ) {
114115 if ( ulong . MinValue == existingEntry . CalculatedModuleBaseAddress ) existingEntry . CalculatedModuleBaseAddress = calcBaseAddress ;
115- } else syms . Add ( uniqueModuleName , new Symbol ( ) { PDBName = reader . GetAttribute ( "pdb" ) . ToLower ( ) , ModuleName = moduleName , PDBAge = int . Parse ( pdbAge ) , PDBGuid = Guid . Parse ( pdbGuid ) . ToString ( "N" ) . ToUpper ( ) , CalculatedModuleBaseAddress = calcBaseAddress } ) ;
116+ } else syms . Add ( uniqueModuleName , new Symbol ( ) { PDBName = xmlReader . GetAttribute ( "pdb" ) . ToLower ( ) , ModuleName = moduleName , PDBAge = int . Parse ( pdbAge ) , PDBGuid = Guid . Parse ( pdbGuid ) . ToString ( "N" ) . ToUpper ( ) , CalculatedModuleBaseAddress = calcBaseAddress } ) ;
116117 }
117118 string rvaAsIsOrDerived = null ;
118119 if ( ulong . MinValue != rvaIfPresent ) rvaAsIsOrDerived = rvaAttributeVal ;
@@ -121,7 +122,7 @@ await Task.Run(() => Parallel.ForEach(listOfCallStacks, currItem => {
121122
122123 if ( string . IsNullOrEmpty ( rvaAsIsOrDerived ) ) { throw new NullReferenceException ( ) ; }
123124
124- var frameNumHex = string . Format ( System . Globalization . CultureInfo . CurrentCulture , "{0:x2}" , int . Parse ( reader . GetAttribute ( "id" ) ) ) ;
125+ var frameNumHex = string . Format ( System . Globalization . CultureInfo . CurrentCulture , "{0:x2}" , int . Parse ( xmlReader . GetAttribute ( "id" ) ) ) ;
125126 // transform the XML into a simple module+offset notation
126127 outCallstack . AppendFormat ( $ "{ frameNumHex } { uniqueModuleName } +{ rvaAsIsOrDerived } { Environment . NewLine } ") ;
127128 continue ;
0 commit comments