/// <summary> /// Gets the list of DynamicStackFrames for the current exception. /// </summary> internal static DynamicStackFrame[] GetDynamicStackFrames(Exception e) { List <DynamicStackFrame> frames = e.GetFrameList(); if (frames == null) { return(new DynamicStackFrame[0]); } frames = new List <DynamicStackFrame>(frames); List <DynamicStackFrame> identified = new List <DynamicStackFrame>(); // merge .NET frames w/ any dynamic frames that we have try { StackTrace outermostTrace = new StackTrace(e, false); IList <StackTrace> otherTraces = ExceptionHelpers.GetExceptionStackTraces(e) ?? new List <StackTrace>(); List <StackFrame> clrFrames = new List <StackFrame>(); foreach (StackTrace trace in otherTraces) { clrFrames.AddRange(trace.GetFrames() ?? new StackFrame[0]); // rare, sometimes GetFrames returns null } clrFrames.AddRange(outermostTrace.GetFrames() ?? new StackFrame[0]); // rare, sometimes GetFrames returns null int lastFound = 0; foreach (StackFrame clrFrame in InterpretedFrame.GroupStackFrames(clrFrames)) { MethodBase method = clrFrame.GetMethod(); for (int j = lastFound; j < frames.Count; j++) { MethodBase other = frames[j].GetMethod(); // method info's don't always compare equal, check based // upon name/module/declaring type which will always be a correct // check for dynamic methods. if (MethodsMatch(method, other)) { identified.Add(frames[j]); frames.RemoveAt(j); lastFound = j; break; } } } } catch (MemberAccessException) { // can't access new StackTrace(e) due to security } // combine identified and any remaining frames we couldn't find // this is equivalent of adding remaining frames in front of identified frames.AddRange(identified); return(frames.ToArray()); }
public static DynamicStackFrame[] GetDynamicStackFrames(Exception e, bool filter) { List <DynamicStackFrame> frames = e.Data[typeof(DynamicStackFrame)] as List <DynamicStackFrame>; if (frames == null) { // we may have missed a dynamic catch, and our host is looking // for the exception... frames = ExceptionHelpers.AssociateDynamicStackFrames(e); ExceptionHelpers.DynamicStackFrames = null; } if (frames == null) { return(new DynamicStackFrame[0]); } if (!filter) { return(frames.ToArray()); } #if !SILVERLIGHT frames = new List <DynamicStackFrame>(frames); List <DynamicStackFrame> res = new List <DynamicStackFrame>(); // the list of _stackFrames we build up in ScriptingRuntimeHelpers can have // too many frames if exceptions are thrown from script code and // caught outside w/o calling GetDynamicStackFrames. Therefore we // filter down to only script frames which we know are associated // w/ the exception here. try { StackTrace outermostTrace = new StackTrace(e); IList <StackTrace> otherTraces = ExceptionHelpers.GetExceptionStackTraces(e) ?? new List <StackTrace>(); List <StackFrame> clrFrames = new List <StackFrame>(); foreach (StackTrace trace in otherTraces) { clrFrames.AddRange(trace.GetFrames() ?? new StackFrame[0]); // rare, sometimes GetFrames returns null } clrFrames.AddRange(outermostTrace.GetFrames() ?? new StackFrame[0]); // rare, sometimes GetFrames returns null int lastFound = 0; foreach (StackFrame clrFrame in InterpretedFrame.GroupStackFrames(clrFrames)) { MethodBase method = clrFrame.GetMethod(); for (int j = lastFound; j < frames.Count; j++) { MethodBase other = frames[j].GetMethod(); // method info's don't always compare equal, check based // upon name/module/declaring type which will always be a correct // check for dynamic methods. if (method.Module == other.Module && method.DeclaringType == other.DeclaringType && method.Name == other.Name) { res.Add(frames[j]); frames.RemoveAt(j); lastFound = j; break; } } } } catch (MemberAccessException) { // can't access new StackTrace(e) due to security } return(res.ToArray()); #else return(frames.ToArray()); #endif }
private void AddBacktrace(IEnumerable <StackFrame> stackTrace, int skipFrames, bool skipInterpreterRunMethod) { if (stackTrace != null) { foreach (var frame in InterpretedFrame.GroupStackFrames(stackTrace)) { string methodName, file; int line; if (_interpretedFrames != null && _interpretedFrameIndex < _interpretedFrames.Count && InterpretedFrame.IsInterpretedFrame(frame.GetMethod())) { if (skipInterpreterRunMethod) { skipInterpreterRunMethod = false; continue; } InterpretedFrameInfo info = _interpretedFrames[_interpretedFrameIndex++]; if (info.DebugInfo != null) { file = info.DebugInfo.FileName; line = info.DebugInfo.StartLine; } else { file = null; line = 0; } methodName = info.MethodName; // TODO: We need some more general way to recognize and parse non-Ruby interpreted frames TryParseRubyMethodName(ref methodName, ref file, ref line); if (methodName == InterpretedCallSiteName) { // ignore ruby interpreted call sites continue; } } else if (TryGetStackFrameInfo(frame, out methodName, out file, out line)) { // special case: the frame will be added with the next frame's source info: if (line == NextFrameLine) { _nextFrameMethodName = methodName; continue; } } else { continue; } if (_nextFrameMethodName != null) { if (skipFrames == 0) { _trace.Add(MutableString.Create(FormatFrame(file, line, _nextFrameMethodName), _encoding)); } else { skipFrames--; } _nextFrameMethodName = null; } if (skipFrames == 0) { _trace.Add(MutableString.Create(FormatFrame(file, line, methodName), _encoding)); } else { skipFrames--; } } } }