private void RoutineTable_RoutineAdded(object sender, ZRoutineAddedEventArgs e) { lines.BeginBulkOperation(); try { // Find routine header line that would follow this routine int nextRoutineIndex = -1; int insertionPoint = -1; for (int i = 0; i < routineAddressAndIndexList.Count; i++) { var addressAndIndex = routineAddressAndIndexList[i]; if (addressAndIndex.Address > e.Routine.Address) { nextRoutineIndex = i; insertionPoint = addressAndIndex.Index; break; } } // If no routine header found, insert at the end of the list. if (nextRoutineIndex == -1) { insertionPoint = lines.Count; } var count = 0; // Is previous line an address gap? If so, we need to either remove it or update it in place. if (insertionPoint > 0) { var addressGap = lines[insertionPoint - 1] as DisassemblyAddressGapLineViewModel; if (addressGap != null) { var priorRoutine = addressGap.Start; var nextRoutine = addressGap.End; if (addressGap.StartAddress == e.Routine.Address) { // If the address gap starts at this routine, we need to remove it. lines.RemoveAt(--insertionPoint); count--; } else if (addressGap.StartAddress < e.Routine.Address) { // If the address gap starts before this routine, we need to update it in place. lines[insertionPoint - 1] = new DisassemblyAddressGapLineViewModel(priorRoutine, e.Routine) { ShowBlankBefore = true }; } if (nextRoutine.Address > e.Routine.Address + e.Routine.Length - 1) { // If there is a gap between this routine and the next one, we need to insert an address gap. var newAddressGap = new DisassemblyAddressGapLineViewModel(e.Routine, nextRoutine) { ShowBlankBefore = true }; lines.Insert(insertionPoint, newAddressGap); count++; } } } var instructions = e.Routine.Instructions; var lastIndex = instructions.Length - 1; for (int i = lastIndex; i >= 0; i--) { var instruction = instructions[i]; var instructionLine = new DisassemblyInstructionLineViewModel(instruction, i == lastIndex); if (breakpointService.Exists(instruction.Address)) { instructionLine.HasBreakpoint = true; } lines.Insert(insertionPoint, instructionLine); count++; addressToLineMap.Add(instruction.Address, instructionLine); } var routineHeaderLine = new DisassemblyRoutineHeaderLineViewModel(e.Routine) { ShowBlankBefore = insertionPoint > 0, ShowBlankAfter = true }; lines.Insert(insertionPoint, routineHeaderLine); count++; addressToLineMap.Add(e.Routine.Address, routineHeaderLine); if (nextRoutineIndex >= 0) { // fix up routine indeces... for (int i = nextRoutineIndex; i < routineAddressAndIndexList.Count; i++) { var addressAndIndex = routineAddressAndIndexList[i]; routineAddressAndIndexList[i] = new AddressAndIndex(addressAndIndex.Address, addressAndIndex.Index + count); } routineAddressAndIndexList.Insert(nextRoutineIndex, new AddressAndIndex(e.Routine.Address, insertionPoint)); } else { routineAddressAndIndexList.Add(new AddressAndIndex(e.Routine.Address, insertionPoint)); } } finally { lines.EndBulkOperation(); } }
private void DebuggerService_MachineCreated(object sender, MachineCreatedEventArgs e) { var reader = new MemoryReader(storyService.Story.Memory, 0); DisassemblyLineViewModel ipLine; lines.BeginBulkOperation(); try { var routineTable = routineService.RoutineTable; for (int rIndex = 0; rIndex < routineTable.Count; rIndex++) { var routine = routineTable[rIndex]; if (rIndex > 0) { var lastRoutine = routineTable[rIndex - 1]; if (lastRoutine.Address + lastRoutine.Length < routine.Address) { var addressGapLine = new DisassemblyAddressGapLineViewModel(lastRoutine, routine) { ShowBlankBefore = true }; lines.Add(addressGapLine); } } var routineHeaderLine = new DisassemblyRoutineHeaderLineViewModel(routine) { ShowBlankBefore = rIndex > 0, ShowBlankAfter = true }; routineAddressAndIndexList.Add(new AddressAndIndex(routineHeaderLine.Address, lines.Count)); lines.Add(routineHeaderLine); addressToLineMap.Add(routine.Address, routineHeaderLine); var instructions = routine.Instructions; var lastIndex = instructions.Length - 1; for (int i = 0; i <= lastIndex; i++) { var instruction = instructions[i]; var instructionLine = new DisassemblyInstructionLineViewModel(instruction, i == lastIndex); if (breakpointService.Exists(instruction.Address)) { instructionLine.HasBreakpoint = true; } lines.Add(instructionLine); addressToLineMap.Add(instruction.Address, instructionLine); } } ipLine = GetLineByAddress(debuggerService.Machine.PC); ipLine.HasIP = true; } finally { lines.EndBulkOperation(); } BringLineIntoView(ipLine); routineService.RoutineTable.RoutineAdded += RoutineTable_RoutineAdded; }