// Returns the index of the first thread that contains a keyword in the call stack public bool GetFrameByKeyword(string keyword, out FrameInfo frameInfo, out ThreadInfo threadInfo) { frameInfo = null; threadInfo = null; string pattern = keyword + @"[^\w]"; foreach (ThreadInfo threadInfoAux in Threads) { foreach (FrameInfo frameInfoAux in threadInfoAux.stack) { if (Regex.Match(frameInfoAux.function, pattern, RegexOptions.IgnoreCase).Success) { frameInfo = frameInfoAux; threadInfo = threadInfoAux; return(true); } } } return(false); }
// Complements the information of some Parsers with data from other Parsers public void CombineParserInfo() { // Assign the call stack of the exception thread, if present. // In some cases, the exception thread as it appears in section 'THREAD STACKS' may not provide a meaningful // call stack (e.g, may show 'NtGetContextThread' if the dump was created by calling 'MiniDumpWriteDump') ThreadInfo exceptionThread = excepInfoParser.GetExceptionThread(); if (exceptionThread != null && exceptionThread.threadNum < threadParser.Threads.Count) { threadParser.Threads[exceptionThread.threadNum].stack = exceptionThread.stack; } // Add managed frames to the main thread list foreach (ManagedStackInfo stack in managedStacksParser.Stacks) { threadParser.AddManagedInfo(stack.threadNum, stack); } // Add instruction pointers to the thread list threadParser.SetInstructionPointers(instPtrParser.InstPtrs); }
public override void Parse() { Debug.Assert(lines.Count > 0); ThreadInfo thread = null; Threads = new List <ThreadInfo>(); InitExceptionKeywords(); foreach (string line in lines) { if (line.Contains("Id:")) { pattern = @"(?<thread_num>[0-9]+)\s+Id:\s.*\.(?<thread_id>\w+).+\sTeb:\s(?<teb>[\w,`]+)"; matches = Regex.Matches(line, pattern); if (matches.Count == 1) { thread = new ThreadInfo(); thread.stack = new List <FrameInfo>(); Threads.Add(thread); thread.threadNum = Convert.ToInt32(matches[0].Groups["thread_num"].Value); thread.threadId = matches[0].Groups["thread_id"].Value; numFrames = 0; } } else if (line.Contains("Inline Function")) { string[] parts = line.Split(new string[] { "--------" }, StringSplitOptions.None); FrameInfo frame = new FrameInfo() { numFrame = numFrames++, callSite = parts[parts.Length - 1].Trim(' ', ':'), inline = true }; ParseCallSite(frame); thread.stack.Add(frame); } else { if (Program.is32bitDump) // 32-bits log { pattern = @"^\w+\s(?<child>\w+)\s(?<return_addr>\w+)\s(?<args_to_child1>\w+)\s(?<args_to_child2>\w+)\s(?<args_to_child3>\w+)\s(?<call_site>.*)"; } else // 64-bits log { pattern = @"(?<child>[\w,`]+)\s(?<return_addr>[\w,`]+)\s:\s(?<args_to_child1>[\w,`]+)\s(?<args_to_child2>[\w,`]+)\s(?<args_to_child3>[\w,`]+)\s(?<args_to_child4>[\w,`]+)\s:\s(?<call_site>.*)"; } matches = Regex.Matches(line, pattern); if (matches.Count == 1) { FrameInfo frame = new FrameInfo { numFrame = numFrames++, childSP = matches[0].Groups["child"].Value.Replace("`", string.Empty), returnAddress = matches[0].Groups["return_addr"].Value.Replace("`", string.Empty), argsToChild1 = matches[0].Groups["args_to_child1"].Value.Replace("`", string.Empty), argsToChild2 = matches[0].Groups["args_to_child2"].Value.Replace("`", string.Empty), argsToChild3 = matches[0].Groups["args_to_child3"].Value.Replace("`", string.Empty), argsToChild4 = matches[0].Groups["args_to_child4"].Value.Replace("`", string.Empty), callSite = matches[0].Groups["call_site"].Value }; ParseCallSite(frame); thread.stack.Add(frame); } } } }
ThreadInfo exceptionThread; // The thread that generated the exception public override void Parse() { addressHex = null; frame = null; description = null; module = null; threadNum = -1; Debug.Assert(lines.Count > 0); for (int idx = 0; idx < lines.Count; idx++) { if (lines[idx].Contains("ExceptionAddress:")) { pattern = @"ExceptionAddress:\s(?<excep_addr>[\w]+)"; matches = Regex.Matches(lines[idx], pattern); if (matches.Count == 1) { addressHex = matches[0].Groups["excep_addr"].Value; address = Utils.StrHexToUInt64(addressHex); if (address == 0) // This exception record is not valid { return; } // Find exception frame if (lines[idx].Contains("(")) { pattern = @"\s\((?<excep_frame>.+)\)"; matches = Regex.Matches(lines[idx], pattern); if (matches.Count == 1) { frame = matches[0].Groups["excep_frame"].Value; if (frame.Contains("!")) { string[] parts = frame.Split('!'); if (parts.Length >= 2) { module = parts[0]; } } } } } } else if (lines[idx].Contains("ExceptionCode:")) { pattern = @"ExceptionCode: (?<exception>.+)"; matches = Regex.Matches(lines[idx], pattern); if (matches.Count == 1) { description = matches[0].Groups["exception"].Value; if (description.Contains("CLR exception")) { isClrException = true; } } } else if (lines[idx].Contains("EXCEPTION CALL STACK:")) { ThreadParser threadParser = new ThreadParser(); // Used to extract the exception thread's call stack while (++idx < lines.Count) { threadParser.AddLine(lines[idx]); } threadParser.Parse(); if (threadParser.Threads.Count > 0) { exceptionThread = threadParser.Threads[0]; threadNum = exceptionThread.threadNum; } } else if (lines[idx].Contains("Unable to get exception context")) { return; // The exception info is not useful. } } }