internal PdbEntry TaskStarted(TaskStartedEventArgs e) { PdbEntry taskSymbol = null; // We need to deal with 2 issues (a) batching (b) consecutive targets with same name (c) both // We will make a compromise here - in case of (c), we will have one symbol for the 1st task // and rest of symbols for the 2nd - irrespective of kind of combination we have for (c) // i.e. 3M M or 2M 2M or M 3M are all treated as M 3M string currentTaskName = projectStack.Peek().TargetStack.Peek().TargetSymbol.Children[projectStack.Peek().TargetStack.Peek().TaskNumber].Name; if (!string.Equals(e.TaskName, currentTaskName, StringComparison.OrdinalIgnoreCase)) { taskSymbol = projectStack.Peek().TargetStack.Peek().TargetSymbol.Children[++projectStack.Peek().TargetStack.Peek().TaskNumber]; } else { string nextTaskName = (projectStack.Peek().TargetStack.Peek().TaskNumber < (projectStack.Peek().TargetStack.Peek().TargetSymbol.Children.Count - 1)) ? projectStack.Peek().TargetStack.Peek().TargetSymbol.Children[projectStack.Peek().TargetStack.Peek().TaskNumber + 1].Name : null; if (string.Equals(e.TaskName, nextTaskName, StringComparison.OrdinalIgnoreCase)) { ++projectStack.Peek().TargetStack.Peek().TaskNumber; } taskSymbol = projectStack.Peek().TargetStack.Peek().TargetSymbol.Children[projectStack.Peek().TargetStack.Peek().TaskNumber]; } // Return the symbol Debug.Assert(null != taskSymbol, "taskSymbol is null - this should never happen, we are going to crash!"); return(taskSymbol); }
internal PdbEntry TargetStarted(TargetStartedEventArgs e) { // Get the current target symbol PdbEntry targetSymbol = SymbolStore.Instance[e.TargetFile].TargetSymbolEntries[e.TargetName]; // Create a stackframe projectStack.Peek().TargetStack.Push(new TargetStackFrame(targetSymbol)); return(targetSymbol); }
/// <summary> /// Target Started /// </summary> void eventSource_TargetStarted(object sender, TargetStartedEventArgs e) { // Load symbol information SymbolStore.Instance.LoadSymbols(e.TargetFile); // Create stack frame PdbEntry symbol = _contextCracker.TargetStarted(e); _callStack.Push(new StackFrame { ExecutablePath = e.TargetFile, TargetName = e.TargetName, TaskName = null, StartLocation = symbol.StartLocation, EndLocation = symbol.EndLocation }); LogBuildEventArgs(e, "TargetStarted"); _debuggerHost.DoExecutableBlockStarted(_callStack.ToArray()); }
internal BreakPoint BindBreakPoint(BreakPoint unboundBreakPoint) { BreakPoint boundBreakPoint = null; // Load the symbols, if not loaded already SymbolStore.Instance.LoadSymbols(unboundBreakPoint.ExecutablePath); PDB pdb = SymbolStore.Instance[unboundBreakPoint.ExecutablePath]; PdbEntry bpSymbol = null; // First determine the target PdbEntry targetSymbol = null; PdbEntry[] targetSymbolEntries = pdb.TargetSymbolEntries.Values.ToArray(); for (int i = 0; i < targetSymbolEntries.Length - 1; i++) { PdbEntry currEntry = targetSymbolEntries[i]; PdbEntry nextEntry = targetSymbolEntries[i + 1]; if ( currEntry.StartLocation.Y <= unboundBreakPoint.Location.Y && unboundBreakPoint.Location.Y < nextEntry.StartLocation.Y ) { targetSymbol = currEntry; break; } } // Project with no targets if (0 == targetSymbolEntries.Length) { targetSymbol = pdb.ProjectPdbEntry; } if ((0 != targetSymbolEntries.Length) && (null == targetSymbol)) { // Ok so the break point is not between targets 1-2, 2-3, 3-4, 4-5 // So it can be either before 1 or after 5 // Before 1 => The BP is at project start // After 5 => BP at the last target if (targetSymbolEntries[0].StartLocation.Y >= unboundBreakPoint.Location.Y) { targetSymbol = pdb.ProjectPdbEntry; } else { targetSymbol = targetSymbolEntries[targetSymbolEntries.Length - 1]; } } if (null == targetSymbol) { goto Done; } // Second determine the task PdbEntry taskSymbol = null; for (int i = 0; i < targetSymbol.Children.Count - 1; i++) { PdbEntry currEntry = targetSymbol.Children[i]; PdbEntry nextEntry = targetSymbol.Children[i + 1]; if ( currEntry.StartLocation.Y <= unboundBreakPoint.Location.Y && unboundBreakPoint.Location.Y < nextEntry.StartLocation.Y ) { taskSymbol = currEntry; break; } } if ((0 != targetSymbol.Children.Count) && (null == taskSymbol)) { // Ok so the break point is not between tasks 1-2, 2-3, 3-4, 4-5 // So it can be either before 1 or after 5 // Before 1 => The BP is at target start // After 5 => BP at the last task // Take care of only 'after 5' case since not getting the symbol means 'before 1' case if (targetSymbol.Children[targetSymbol.Children.Count - 1].StartLocation.Y <= unboundBreakPoint.Location.Y) { taskSymbol = targetSymbol.Children[targetSymbol.Children.Count - 1]; } } // If we didnt get a task, no issues, set BP on the target bpSymbol = taskSymbol ?? targetSymbol; // Third create and note down the bound bp boundBreakPoint = _breakPoints.Find(bp => (bp.Location == bpSymbol.StartLocation)); if (null == boundBreakPoint) { boundBreakPoint = new BreakPoint { ExecutablePath = unboundBreakPoint.ExecutablePath, Location = bpSymbol.StartLocation }; _breakPoints.Add(boundBreakPoint); } Done: return(boundBreakPoint); }
internal TargetStackFrame(PdbEntry targetSymbol) { TargetSymbol = targetSymbol; TaskNumber = 0; }
private void PopulateSymbolInformation() { using (XmlTextReader reader = new XmlTextReader(ExecutablePath)) { // Read into the Project Element do { reader.Read(); }while (!reader.Name.Equals("Project", StringComparison.OrdinalIgnoreCase)); // Set the start location ProjectPdbEntry.StartLocation = new Point(reader.LinePosition, reader.LineNumber); if (reader.IsEmptyElement) { ProjectPdbEntry.EndLocation = ProjectPdbEntry.StartLocation; } // Start traversing the XML int currentTask = -1; Stack <PdbEntry> contextStack = new Stack <PdbEntry>(); while (reader.Read()) { // Not interested in things other than Elements if ((XmlNodeType.Element != reader.NodeType) && (XmlNodeType.EndElement != reader.NodeType)) { continue; } // If it is the </Project> tag, set the end location if ((XmlNodeType.EndElement == reader.NodeType) && reader.Name.Equals("Project", StringComparison.OrdinalIgnoreCase)) { ProjectPdbEntry.EndLocation = new Point(reader.LinePosition, reader.LineNumber); continue; } // Ignore everything except a Target element or its children if (0 == contextStack.Count) { if (!reader.Name.Equals("Target", StringComparison.OrdinalIgnoreCase)) { continue; } // We have just entered a Target element PdbEntry symEntry = new PdbEntry(reader["Name"], ExecutablePath); symEntry.StartLocation = new Point(reader.LinePosition, reader.LineNumber); TargetSymbolEntries[reader["Name"]] = symEntry; // Note that this enables the 'oveerriding' behavior of MSBuild Targets contextStack.Push(symEntry); // Close this context if it is an empty element if (reader.IsEmptyElement) { symEntry.EndLocation = new Point(reader.LinePosition, reader.LineNumber); contextStack.Pop(); } // Lets proceed continue; } // We are now in one of the target's children or it closing element. // Lets eat up the PropertyGroup and ItemGroups if ( reader.Name.Equals("PropertyGroup", StringComparison.OrdinalIgnoreCase) || reader.Name.Equals("ItemGroup", StringComparison.OrdinalIgnoreCase) ) { if (!reader.IsEmptyElement) { // Eat up the non-empty node and all its childres - burrrp! string name = reader.Name; int depth = reader.Depth; do { reader.Read(); }while ((XmlNodeType.EndElement != reader.NodeType) || !reader.Name.Equals(name, StringComparison.OrdinalIgnoreCase) || (reader.Depth != depth)); } continue; } // We could now be on a Task if (XmlNodeType.Element == reader.NodeType) { PdbEntry taskSymEntry = new PdbEntry(reader.Name, ExecutablePath); taskSymEntry.StartLocation = new Point(reader.LinePosition, reader.LineNumber); if (!reader.IsEmptyElement) { // Not an empty task element - has some child elements like <Output> - so eat up all children string nodeName = reader.Name; int currDepth = reader.Depth; do { reader.Read(); }while ((XmlNodeType.EndElement != reader.NodeType) || !reader.Name.Equals(nodeName, StringComparison.OrdinalIgnoreCase) || (reader.Depth != currDepth)); } taskSymEntry.EndLocation = new Point(reader.LinePosition, reader.LineNumber); contextStack.Peek().Children.Add(taskSymEntry); currentTask++; continue; } // Consider EndElement if ((XmlNodeType.EndElement == reader.NodeType)) { // Now Name has to be "Target" Debug.Assert(reader.Name.Equals("Target", StringComparison.OrdinalIgnoreCase)); contextStack.Peek().EndLocation = new Point(reader.LinePosition, reader.LineNumber); contextStack.Pop(); currentTask = -1; continue; } } } }