public StackGraphNode GetNodeForFrame(TracebackFrame frameInfo, out bool isNew) { StackGraphNode result; if ((frameInfo.Module == null) || (frameInfo.Function == null)) { isNew = false; return(null); } var key = new StackGraphKey(KeyType, frameInfo.Module, frameInfo.Function, frameInfo.SourceFile); lock (Lock) { if (!this.TryGetValue(key, out result)) { isNew = true; this.Add(result = new StackGraphNode(key)); } else { isNew = false; } } return(result); }
static void Deserialize(ref DeserializationContext context, out TracebackFrame output) { var br = new BinaryReader(context.Stream, Encoding.UTF8); output = new TracebackFrame(); output.Offset = br.ReadUInt32(); if (br.ReadBoolean()) { output.Offset2 = br.ReadUInt32(); } else { output.Offset2 = (UInt32)context.Key.Value; } output.Module = ReadString(br); output.Function = ReadString(br); output.SourceFile = ReadString(br); if (br.ReadBoolean()) { output.SourceLine = br.ReadInt32(); } }
static void Serialize(ref SerializationContext context, ref TracebackFrame input) { var bw = new BinaryWriter(context.Stream, Encoding.UTF8); bw.Write(input.Offset); bw.Write(false); if (input.Offset2.HasValue && (input.Offset2 != (UInt32)context.Key.Value)) { throw new InvalidDataException(); } /* * bw.Write(input.Offset2.HasValue); * if (input.Offset2.HasValue) * bw.Write(input.Offset2.Value); */ WriteString(bw, input.Module); WriteString(bw, input.Function); WriteString(bw, input.SourceFile); bw.Write(input.SourceLine.HasValue); if (input.SourceLine.HasValue) { bw.Write(input.SourceLine.Value); } bw.Flush(); }
public bool IsMatch(TracebackFrame frame) { if ((ModuleRegex != null) && ((frame.Module == null) || !ModuleRegex.IsMatch(frame.Module))) { return(false); } if ((FunctionRegex != null) && ((frame.Function == null) || !FunctionRegex.IsMatch(frame.Function))) { return(false); } return(true); }
public StackGraphNode GetNodeForChildFrame(TracebackFrame frameInfo) { bool isNew; StackGraphNode result; lock (Children) result = Children.GetNodeForFrame(frameInfo, out isNew); if (isNew) { lock (result.Parents) result.Parents.Add(this); } return(result); }
static void Deserialize(ref DeserializationContext context, out TracebackFrame output) { var br = new BinaryReader(context.Stream, Encoding.UTF8); output = new TracebackFrame(); output.Offset = br.ReadUInt32(); if (br.ReadBoolean()) output.Offset2 = br.ReadUInt32(); output.Module = ReadString(br); output.Function = ReadString(br); output.SourceFile = ReadString(br); if (br.ReadBoolean()) output.SourceLine = br.ReadInt32(); }
protected bool ResolveFrame(UInt32 frame, out TracebackFrame resolved, out Future <TracebackFrame> pendingResolve) { if (ResolvedSymbolCache.TryGetValue(frame, out resolved)) { pendingResolve = null; return(true); } if (!PendingSymbolResolves.TryGetValue(frame, out pendingResolve)) { var f = PendingSymbolResolves[frame] = new Future <TracebackFrame>(); var item = new PendingSymbolResolve(frame, f); SymbolResolveQueue.Enqueue(item); } return(false); }
public bool Equals(TracebackFrame rhs) { if (Module != rhs.Module) { return(false); } if (Function != rhs.Function) { return(false); } if (Offset != rhs.Offset) { return(false); } if (Offset2 != rhs.Offset2) { return(false); } return(true); }
static void Serialize(ref SerializationContext context, ref TracebackFrame input) { var bw = new BinaryWriter(context.Stream, Encoding.UTF8); bw.Write(input.Offset); bw.Write(input.Offset2.HasValue); if (input.Offset2.HasValue) { bw.Write(input.Offset2.Value); } WriteString(bw, input.Module); WriteString(bw, input.Function); WriteString(bw, input.SourceFile); bw.Write(input.SourceLine.HasValue); if (input.SourceLine.HasValue) { bw.Write(input.SourceLine.Value); } bw.Flush(); }
protected static string IndexSymbolByFunction(ref TracebackFrame frame) { var fn = (frame.Function ?? "???"); return fn; }
protected static string IndexSymbolByFunction(ref TracebackFrame frame) { var fn = (frame.Function ?? "???"); return(fn); }
protected bool ResolveFrame(UInt32 frame, out TracebackFrame resolved, out Future<TracebackFrame> pendingResolve) { if (ResolvedSymbolCache.TryGetValue(frame, out resolved)) { pendingResolve = null; return true; } if (!PendingSymbolResolves.TryGetValue(frame, out pendingResolve)) { var f = PendingSymbolResolves[frame] = new Future<TracebackFrame>(); var item = new PendingSymbolResolve(frame, f); SymbolResolveQueue.Enqueue(item); } return false; }
public StackGraphNode GetNodeForFrame(TracebackFrame frameInfo) { bool temp; return(GetNodeForFrame(frameInfo, out temp)); }
protected IEnumerator <object> SymbolResolverTask() { var batch = new List <PendingSymbolResolve>(); var nullProgress = new CallbackProgressListener(); ActivityIndicator.CountedItem progress = null; while (true) { var count = SymbolResolveBatchSize - batch.Count; SymbolResolveQueue.DequeueMultiple(batch, count); if (batch.Count == 0) { if (progress != null) { progress.Decrement(); progress = null; } if (!SymbolResolveState.Progress.Active && (SymbolResolveQueue.Count <= 0)) { SymbolResolveState.Count = 0; } var f = SymbolResolveQueue.Dequeue(); using (f) yield return(f); batch.Add(f.Result); } else { if (progress == null) { progress = SymbolResolveState.Progress.Increment(); } var maximum = SymbolResolveState.Count + Math.Max(0, SymbolResolveQueue.Count) + 1; progress.Maximum = maximum; progress.Progress = Math.Min(maximum, SymbolResolveState.Count); string infile = Path.GetTempFileName(), outfile = Path.GetTempFileName(); var padNumberRight = (Func <uint, int, string>)((num, length) => { var result = String.Format("{0:X}", num); if (result.Length < length) { result = new String(' ', length - result.Length) + result; } return(result); }); var symbolModules = SymbolModules.ToArray(); yield return(Future.RunInThread(() => { using (var sw = new StreamWriter(infile, false, Encoding.ASCII)) { sw.WriteLine("// Loaded modules:"); sw.WriteLine("// Base Size Module"); foreach (var module in symbolModules) { sw.WriteLine( "// {0} {1} {2}", padNumberRight(module.BaseAddress, 8), padNumberRight(module.Size, 8), Path.GetFullPath(module.Filename) ); } sw.WriteLine("//"); sw.WriteLine("// Process modules enumerated."); sw.WriteLine(); sw.WriteLine("*- - - - - - - - - - Heap 0 Hogs - - - - - - - - - -"); sw.WriteLine(); for (int i = 0; i < batch.Count; i++) { sw.WriteLine( "{0:X8} bytes + {1:X8} at {2:X8} by BackTrace{3:X8}", 1, 0, i + 1, i + 1 ); sw.WriteLine("\t{0:X8}", batch[i].Frame); sw.WriteLine(); } } })); var psi = new ProcessStartInfo( Settings.UmdhPath, String.Format( "\"{0}\" -f:\"{1}\"", infile, outfile ) ); using (var rp = Scheduler.Start( Program.RunProcess(psi, ProcessPriorityClass.Idle), TaskExecutionPolicy.RunAsBackgroundTask )) yield return(rp); using (Finally.Do(() => { try { File.Delete(infile); } catch { } try { File.Delete(outfile); } catch { } })) { var rtc = new RunToCompletion <HeapDiff>( HeapDiff.FromFile(outfile, nullProgress) ); using (rtc) yield return(rtc); var fProcess = Future.RunInThread(() => { var cacheBatch = Database.SymbolCache.CreateBatch(batch.Count); DecisionUpdateCallback <HashSet <UInt32> > updateCallback = (ref HashSet <UInt32> oldValue, ref HashSet <UInt32> newValue) => { newValue.UnionWith(oldValue); return(true); }; foreach (var traceback in rtc.Result.Tracebacks) { var index = (int)(traceback.Key) - 1; var key = batch[index].Frame; var frame = traceback.Value.Frames.Array[traceback.Value.Frames.Offset]; batch[index].Result.Complete(frame); lock (SymbolResolveLock) { ResolvedSymbolCache[key] = frame; PendingSymbolResolves.Remove(key); } cacheBatch.Add(key, frame); if (frame.Function != null) { var tempHash = new HashSet <uint>(); tempHash.Add(key); } } foreach (var frame in batch) { if (frame.Result.Completed) { continue; } Interlocked.Increment(ref TotalFrameResolveFailures); var tf = new TracebackFrame(frame.Frame); frame.Result.Complete(tf); lock (SymbolResolveLock) { ResolvedSymbolCache[frame.Frame] = tf; PendingSymbolResolves.Remove(frame.Frame); } cacheBatch.Add(frame.Frame, tf); // Console.WriteLine("Could not resolve: {0:X8}", frame.Frame); } return(new IBatch[] { cacheBatch }); }); yield return(fProcess); foreach (var manglerBatch in fProcess.Result) { yield return(manglerBatch.Execute()); } Interlocked.Add(ref SymbolResolveState.Count, batch.Count); batch.Clear(); } } } }
public static IEnumerator <object> FromFile(string filename, IProgressListener progress) { progress.Status = "Loading diff..."; Future <string> fText; // We could stream the lines in from the IO thread while we parse them, but this // part of the load is usually pretty quick even on a regular hard disk, and // loading the whole diff at once eliminates some context switches using (var fda = new FileDataAdapter( filename, FileMode.Open, FileAccess.Read, FileShare.Read, 1024 * 128 )) { var fBytes = fda.ReadToEnd(); yield return(fBytes); fText = Future.RunInThread( () => Encoding.ASCII.GetString(fBytes.Result) ); yield return(fText); } yield return(fText); var lr = new LineReader(fText.Result); LineReader.Line line; progress.Status = "Parsing diff..."; var frames = new List <TracebackFrame>(); var moduleNames = new NameTable(StringComparer.Ordinal); var symbolTypes = new NameTable(StringComparer.Ordinal); var functionNames = new NameTable(StringComparer.Ordinal); var deltas = new List <DeltaInfo>(); var tracebacks = new Dictionary <UInt32, TracebackInfo>(); var regexes = new Regexes(); // Regex.Groups[string] does an inefficient lookup, so we do that lookup once here int groupModule = regexes.DiffModule.GroupNumberFromName("module"); int groupSymbolType = regexes.DiffModule.GroupNumberFromName("symbol_type"); int groupTraceId = regexes.BytesDelta.GroupNumberFromName("trace_id"); int groupType = regexes.BytesDelta.GroupNumberFromName("type"); int groupDeltaBytes = regexes.BytesDelta.GroupNumberFromName("delta_bytes"); int groupNewBytes = regexes.BytesDelta.GroupNumberFromName("new_bytes"); int groupOldBytes = regexes.BytesDelta.GroupNumberFromName("old_bytes"); int groupNewCount = regexes.BytesDelta.GroupNumberFromName("new_count"); int groupOldCount = regexes.CountDelta.GroupNumberFromName("old_count"); int groupCountDelta = regexes.CountDelta.GroupNumberFromName("delta_count"); int groupTracebackModule = regexes.TracebackFrame.GroupNumberFromName("module"); int groupTracebackFunction = regexes.TracebackFrame.GroupNumberFromName("function"); int groupTracebackOffset = regexes.TracebackFrame.GroupNumberFromName("offset"); int groupTracebackOffset2 = regexes.TracebackFrame.GroupNumberFromName("offset2"); int groupTracebackPath = regexes.TracebackFrame.GroupNumberFromName("path"); int groupTracebackLine = regexes.TracebackFrame.GroupNumberFromName("line"); var delay = new Sleep(0.01); int i = 0; while (lr.ReadLine(out line)) { retryFromHere: i += 1; if (i % ProgressInterval == 0) { progress.Maximum = lr.Length; progress.Progress = lr.Position; // Suspend processing for a bit yield return(delay); } Match m; if (regexes.DiffModule.TryMatch(ref line, out m)) { moduleNames.Add(m.Groups[groupModule].Value); } else if (regexes.BytesDelta.TryMatch(ref line, out m)) { var added = (m.Groups[groupType].Value == "+"); var traceId = UInt32.Parse(m.Groups[groupTraceId].Value, NumberStyles.HexNumber); var info = new DeltaInfo { BytesDelta = int.Parse(m.Groups[groupDeltaBytes].Value, NumberStyles.HexNumber) * (added ? 1 : -1), NewBytes = int.Parse(m.Groups[groupNewBytes].Value, NumberStyles.HexNumber), OldBytes = int.Parse(m.Groups[groupOldBytes].Value, NumberStyles.HexNumber), NewCount = int.Parse(m.Groups[groupNewCount].Value, NumberStyles.HexNumber), }; if (lr.ReadLine(out line)) { if (regexes.CountDelta.TryMatch(ref line, out m)) { info.OldCount = int.Parse(m.Groups[groupOldCount].Value, NumberStyles.HexNumber); info.CountDelta = int.Parse(m.Groups[groupCountDelta].Value, NumberStyles.HexNumber) * (added ? 1 : -1); } } bool readingLeadingWhitespace = true, doRetry = false; frames.Clear(); var itemModules = new NameTable(StringComparer.Ordinal); var itemFunctions = new NameTable(StringComparer.Ordinal); while (lr.ReadLine(out line)) { if (line.ToString().Trim().Length == 0) { if (readingLeadingWhitespace) { continue; } else { break; } } else if (regexes.TracebackFrame.TryMatch(ref line, out m)) { readingLeadingWhitespace = false; var moduleName = moduleNames[m.Groups[groupTracebackModule].Value]; itemModules.Add(moduleName); var functionName = functionNames[m.Groups[groupTracebackFunction].Value]; itemFunctions.Add(functionName); var frame = new TracebackFrame { Module = moduleName, Function = functionName, Offset = UInt32.Parse(m.Groups[groupTracebackOffset].Value, NumberStyles.HexNumber) }; if (m.Groups[groupTracebackOffset2].Success) { frame.Offset2 = UInt32.Parse(m.Groups[groupTracebackOffset2].Value, NumberStyles.HexNumber); } if (m.Groups[groupTracebackPath].Success) { frame.SourceFile = m.Groups[groupTracebackPath].Value; } if (m.Groups[groupTracebackLine].Success) { frame.SourceLine = int.Parse(m.Groups[groupTracebackLine].Value); } frames.Add(frame); } else { // We hit the beginning of a new allocation, so make sure it gets parsed doRetry = true; break; } } if (tracebacks.ContainsKey(traceId)) { info.Traceback = tracebacks[traceId]; Program.ErrorList.ReportError("Duplicate traceback for id {0}!", traceId); } else { var frameArray = ImmutableArrayPool <TracebackFrame> .Allocate(frames.Count); frames.CopyTo(frameArray.Array, frameArray.Offset); info.Traceback = tracebacks[traceId] = new TracebackInfo { TraceId = traceId, Frames = frameArray, Modules = itemModules, Functions = itemFunctions }; } deltas.Add(info); if (doRetry) { goto retryFromHere; } } else if (line.StartsWith("//")) { // Comment, ignore it } else if (line.StartsWith("Total increase") || line.StartsWith("Total decrease")) { // Ignore this too } else if (line.StartsWith(" ") && (line.EndsWith(".pdb"))) { // Symbol path for a module, ignore it } else { Program.ErrorList.ReportError("Unrecognized diff content: {0}", line.ToString()); } } var result = new HeapDiff( filename, moduleNames, functionNames, deltas, tracebacks ); yield return(new Result(result)); }
public static IEnumerator<object> FromFile(string filename, IProgressListener progress) { progress.Status = "Loading diff..."; Future<string> fText; // We could stream the lines in from the IO thread while we parse them, but this // part of the load is usually pretty quick even on a regular hard disk, and // loading the whole diff at once eliminates some context switches using (var fda = new FileDataAdapter( filename, FileMode.Open, FileAccess.Read, FileShare.Read, 1024 * 128 )) { var fBytes = fda.ReadToEnd(); yield return fBytes; fText = Future.RunInThread( () => Encoding.ASCII.GetString(fBytes.Result) ); yield return fText; } yield return fText; var lr = new LineReader(fText.Result); LineReader.Line line; progress.Status = "Parsing diff..."; var frames = new List<TracebackFrame>(); var moduleNames = new NameTable(StringComparer.Ordinal); var symbolTypes = new NameTable(StringComparer.Ordinal); var functionNames = new NameTable(StringComparer.Ordinal); var deltas = new List<DeltaInfo>(); var tracebacks = new Dictionary<UInt32, TracebackInfo>(); var regexes = new Regexes(); // Regex.Groups[string] does an inefficient lookup, so we do that lookup once here int groupModule = regexes.DiffModule.GroupNumberFromName("module"); int groupSymbolType = regexes.DiffModule.GroupNumberFromName("symbol_type"); int groupTraceId = regexes.BytesDelta.GroupNumberFromName("trace_id"); int groupType = regexes.BytesDelta.GroupNumberFromName("type"); int groupDeltaBytes = regexes.BytesDelta.GroupNumberFromName("delta_bytes"); int groupNewBytes = regexes.BytesDelta.GroupNumberFromName("new_bytes"); int groupOldBytes = regexes.BytesDelta.GroupNumberFromName("old_bytes"); int groupNewCount = regexes.BytesDelta.GroupNumberFromName("new_count"); int groupOldCount = regexes.CountDelta.GroupNumberFromName("old_count"); int groupCountDelta = regexes.CountDelta.GroupNumberFromName("delta_count"); int groupTracebackModule = regexes.TracebackFrame.GroupNumberFromName("module"); int groupTracebackFunction = regexes.TracebackFrame.GroupNumberFromName("function"); int groupTracebackOffset = regexes.TracebackFrame.GroupNumberFromName("offset"); int groupTracebackOffset2 = regexes.TracebackFrame.GroupNumberFromName("offset2"); int groupTracebackPath = regexes.TracebackFrame.GroupNumberFromName("path"); int groupTracebackLine = regexes.TracebackFrame.GroupNumberFromName("line"); int i = 0; while (lr.ReadLine(out line)) { if (i % ProgressInterval == 0) { progress.Maximum = lr.Length; progress.Progress = lr.Position; // Suspend processing until any messages in the windows message queue have been processed yield return new Yield(); } retryFromHere: Match m; if (regexes.DiffModule.TryMatch(ref line, out m)) { moduleNames.Add(m.Groups[groupModule].Value); } else if (regexes.BytesDelta.TryMatch(ref line, out m)) { var traceId = UInt32.Parse(m.Groups[groupTraceId].Value, NumberStyles.HexNumber); var info = new DeltaInfo { Added = (m.Groups[groupType].Value == "+"), BytesDelta = int.Parse(m.Groups[groupDeltaBytes].Value, NumberStyles.HexNumber), NewBytes = int.Parse(m.Groups[groupNewBytes].Value, NumberStyles.HexNumber), OldBytes = int.Parse(m.Groups[groupOldBytes].Value, NumberStyles.HexNumber), NewCount = int.Parse(m.Groups[groupNewCount].Value, NumberStyles.HexNumber), }; if (lr.ReadLine(out line)) { if (regexes.CountDelta.TryMatch(ref line, out m)) { info.OldCount = int.Parse(m.Groups[groupOldCount].Value, NumberStyles.HexNumber); info.CountDelta = int.Parse(m.Groups[groupCountDelta].Value, NumberStyles.HexNumber); } } bool readingLeadingWhitespace = true, doRetry = false; frames.Clear(); var itemModules = new NameTable(StringComparer.Ordinal); var itemFunctions = new NameTable(StringComparer.Ordinal); while (lr.ReadLine(out line)) { if (line.ToString().Trim().Length == 0) { if (readingLeadingWhitespace) continue; else break; } else if (regexes.TracebackFrame.TryMatch(ref line, out m)) { readingLeadingWhitespace = false; var moduleName = moduleNames[m.Groups[groupTracebackModule].Value]; itemModules.Add(moduleName); var functionName = functionNames[m.Groups[groupTracebackFunction].Value]; itemFunctions.Add(functionName); var frame = new TracebackFrame { Module = moduleName, Function = functionName, Offset = UInt32.Parse(m.Groups[groupTracebackOffset].Value, NumberStyles.HexNumber) }; if (m.Groups[groupTracebackOffset2].Success) frame.Offset2 = UInt32.Parse(m.Groups[groupTracebackOffset2].Value, NumberStyles.HexNumber); if (m.Groups[groupTracebackPath].Success) frame.SourceFile = m.Groups[groupTracebackPath].Value; if (m.Groups[groupTracebackLine].Success) frame.SourceLine = int.Parse(m.Groups[groupTracebackLine].Value); frames.Add(frame); } else { // We hit the beginning of a new allocation, so make sure it gets parsed doRetry = true; break; } } if (tracebacks.ContainsKey(traceId)) { info.Traceback = tracebacks[traceId]; Console.WriteLine("Duplicate traceback for id {0}!", traceId); } else { var frameArray = ImmutableArrayPool<TracebackFrame>.Allocate(frames.Count); frames.CopyTo(frameArray.Array, frameArray.Offset); info.Traceback = tracebacks[traceId] = new TracebackInfo { TraceId = traceId, Frames = frameArray, Modules = itemModules, Functions = itemFunctions }; } deltas.Add(info); if (doRetry) goto retryFromHere; } else if (line.StartsWith("//")) { // Comment, ignore it } else if (line.StartsWith("Total increase") || line.StartsWith("Total decrease")) { // Ignore this too } else if (line.StartsWith(" ") && (line.EndsWith(".pdb"))) { // Symbol path for a module, ignore it } else { Console.WriteLine("Unrecognized diff content: {0}", line.ToString()); } } var result = new HeapDiff( filename, moduleNames, functionNames, deltas, tracebacks ); yield return new Result(result); }
protected IEnumerator<object> SymbolResolverTask() { var batch = new List<UInt32>(); var nullProgress = new CallbackProgressListener(); ActivityIndicator.CountedItem progress = null; while (true) { var count = SymbolResolveBatchSize - batch.Count; SymbolResolveQueue.DequeueMultiple(batch, count); if (batch.Count == 0) { if (progress != null) { progress.Decrement(); progress = null; } if (!SymbolResolveState.Progress.Active && (SymbolResolveQueue.Count <= 0)) { SymbolResolveState.Count = 0; OnSymbolCacheUpdated(); } var f = SymbolResolveQueue.Dequeue(); using (f) yield return f; batch.Add(f.Result); } else { if (progress == null) progress = SymbolResolveState.Progress.Increment(); var maximum = SymbolResolveState.Count + Math.Max(0, SymbolResolveQueue.Count) + 1; progress.Maximum = maximum; progress.Progress = Math.Min(maximum, SymbolResolveState.Count); string infile = Path.GetTempFileName(), outfile = Path.GetTempFileName(); var padNumberRight = (Func<uint, int, string>)((num, length) => { var result = String.Format("{0:X}", num); if (result.Length < length) result = new String(' ', length - result.Length) + result; return result; }); var symbolModules = SymbolModules.ToArray(); yield return Future.RunInThread(() => { using (var sw = new StreamWriter(infile, false, Encoding.ASCII)) { sw.WriteLine("// Loaded modules:"); sw.WriteLine("// Base Size Module"); foreach (var module in symbolModules) sw.WriteLine( "// {0} {1} {2}", padNumberRight(module.BaseAddress, 8), padNumberRight(module.Size, 8), Path.GetFullPath(module.Filename) ); sw.WriteLine("//"); sw.WriteLine("// Process modules enumerated."); sw.WriteLine(); sw.WriteLine("*- - - - - - - - - - Heap 0 Hogs - - - - - - - - - -"); sw.WriteLine(); for (int i = 0; i < batch.Count; i++) { sw.WriteLine( "{0:X8} bytes + {1:X8} at {2:X8} by BackTrace{3:X8}", 1, 0, i + 1, i + 1 ); sw.WriteLine("\t{0:X8}", batch[i]); sw.WriteLine(); } } }); IDictionary<string, string> environment = null; yield return GetEnvironment().Bind(() => environment); var psi = new ProcessStartInfo( Settings.UmdhPath, String.Format( "\"{0}\" -f:\"{1}\"", infile, outfile ) ); using (var rp = Scheduler.Start( Program.RunProcess( psi, ProcessPriorityClass.Idle, environment ), TaskExecutionPolicy.RunAsBackgroundTask )) yield return rp; using (Finally.Do(() => { try { File.Delete(infile); } catch { } try { File.Delete(outfile); } catch { } })) { var rtc = new RunToCompletion<HeapDiff>( HeapDiff.FromFile(outfile, nullProgress) ); using (rtc) yield return rtc; var fProcess = Future.RunInThread(() => { var cacheBatch = Database.SymbolCache.CreateBatch(batch.Count); DecisionUpdateCallback<HashSet<UInt32>> updateCallback = (ref HashSet<UInt32> oldValue, ref HashSet<UInt32> newValue) => { newValue.UnionWith(oldValue); return true; }; foreach (var traceback in rtc.Result.Tracebacks) { var index = (int)(traceback.Key) - 1; var key = batch[index]; var frame = traceback.Value.Frames.Array[traceback.Value.Frames.Offset]; lock (SymbolResolveLock) { ResolvedSymbolCache[key] = frame; PendingSymbolResolves.Remove(key); } cacheBatch.Add(key, frame); if (frame.Function != null) { var tempHash = new HashSet<uint>(); tempHash.Add(key); } } foreach (var frame in batch) { if (!PendingSymbolResolves.Contains(frame)) continue; Interlocked.Increment(ref TotalFrameResolveFailures); var tf = new TracebackFrame(frame); lock (SymbolResolveLock) { ResolvedSymbolCache[frame] = tf; PendingSymbolResolves.Remove(frame); } cacheBatch.Add(frame, tf); // Console.WriteLine("Could not resolve: {0:X8}", frame.Frame); } return new IBatch[] { cacheBatch }; }); yield return fProcess; foreach (var manglerBatch in fProcess.Result) yield return manglerBatch.Execute(); Interlocked.Add(ref SymbolResolveState.Count, batch.Count); batch.Clear(); } } } }
protected bool ResolveFrame(UInt32 frame, out TracebackFrame resolved) { if (ResolvedSymbolCache.TryGetValue(frame, out resolved)) { return true; } bool temp; if (!PendingSymbolResolves.Contains(frame)) { PendingSymbolResolves.Add(frame); SymbolResolveQueue.Enqueue(frame); } return false; }
static void Serialize(ref SerializationContext context, ref TracebackFrame input) { var bw = new BinaryWriter(context.Stream, Encoding.UTF8); bw.Write(input.Offset); bw.Write(input.Offset2.HasValue); if (input.Offset2.HasValue) bw.Write(input.Offset2.Value); WriteString(bw, input.Module); WriteString(bw, input.Function); WriteString(bw, input.SourceFile); bw.Write(input.SourceLine.HasValue); if (input.SourceLine.HasValue) bw.Write(input.SourceLine.Value); bw.Flush(); }