1 using System;
   2 using System.Collections;
   3 
   4 namespace cmsx.debug
   5 {
   6     public enum State
   7     {
   8         runningexit
   9     }
  10 
  11     public enum CommandResult
  12     {
  13         retcontupdate
  14     }
  15 
  16     class ByStart : Rel<cmsx.object.Symbol*>
  17     {
  18         public bool operator()(cmsx.object.Symbol* leftcmsx.object.Symbol* right) const
  19         {
  20             return left->start < right->start;
  21         }
  22     }
  23 
  24     public const short blackOnWhite = 1;
  25     public const short whiteOnBlue = 2;
  26     public const short cyanOnBlue = 3;
  27     public const short whiteOnRed = 4;
  28     public const short redOnWhite = 5;
  29     public const short whiteOnCyan = 6;
  30 
  31     public class Screen
  32     {
  33         public nothrow Screen()
  34         {
  35             RtInitScreen();
  36             RtNoEcho();
  37             RtRaw();
  38             RtKeyPad();
  39             GetDimensions();
  40             RtStartColor();
  41             RtInitPair(blackOnWhiteRtBlack()RtWhite());
  42             RtInitPair(whiteOnBlueRtWhite()RtBlue());
  43             RtInitPair(cyanOnBlueRtCyan()RtBlue());
  44             RtInitPair(whiteOnRedRtWhite()RtRed());
  45             RtInitPair(redOnWhiteRtRed()RtWhite());
  46             RtInitPair(whiteOnCyanRtWhite()RtCyan());
  47         }
  48         public ~Screen()
  49         {
  50             RtDoneScreen();
  51         }
  52         public nothrow void MoveCursorTo(int rowint col)
  53         {
  54             RtMove(rowcol);
  55         }
  56         public nothrow void Update()
  57         {
  58             Window* window = focusedWindow->next;
  59             while (window != focusedWindow)
  60             {
  61                 if (window->visible)
  62                 {
  63                     window->Draw();
  64                 }
  65                 window = window->next;
  66             }
  67             focusedWindow->Draw();
  68             focusedWindow->ShowCursor();
  69             RtRefresh();
  70         }
  71         public nothrow void GetDimensions()
  72         {
  73             RtGetMaxYX(&rows&cols);
  74             commandWindowHeight = 3;
  75             outputWindowHeight = 10;
  76         }
  77         public int rows;
  78         public int cols;
  79         public int outputWindowHeight;
  80         public int commandWindowHeight;
  81         public Window* focusedWindow;
  82     }
  83 
  84     public static class Box
  85     {
  86         static Box() : chars()doubleChars()
  87         {
  88             chars.Append(cast<uchar>(0x250C));
  89             chars.Append(cast<uchar>(0x2500));
  90             chars.Append(cast<uchar>(0x2502));
  91             chars.Append(cast<uchar>(0x2510));
  92             chars.Append(cast<uchar>(0x2514));
  93             chars.Append(cast<uchar>(0x2518));
  94             doubleChars.Append(cast<uchar>(0x2554));
  95             doubleChars.Append(cast<uchar>(0x2550));
  96             doubleChars.Append(cast<uchar>(0x2551));
  97             doubleChars.Append(cast<uchar>(0x2557));
  98             doubleChars.Append(cast<uchar>(0x255A));
  99             doubleChars.Append(cast<uchar>(0x255D));
 100         }
 101         public static ustring* GetChars()
 102         {
 103             return &chars;
 104         }
 105         public static ustring* GetDoubleChars()
 106         {
 107             return &doubleChars;
 108         }
 109         public static ustring chars;
 110         public static ustring doubleChars;
 111     }
 112 
 113     public abstract class Window
 114     {
 115         public nothrow Window(const string& name_) : name(name_)
 116         {
 117         }
 118         public virtual default ~Window();
 119         public void SetDebugger(Debugger* debugger_)
 120         {
 121             debugger = debugger_;
 122         }
 123         public abstract void Draw();
 124         public void DrawFrame()
 125         {
 126             ustring* frameChars = null;
 127             if (screen->focusedWindow == this)
 128             {
 129                 frameChars = Box.GetDoubleChars();
 130             }
 131             else
 132             {
 133                 frameChars = Box.GetChars();
 134             }
 135             RtAttrOn(RtColorPair(color));
 136             screen->MoveCursorTo(Top()Left());
 137             int leftTop = cast<int>((*frameChars)[0]);
 138             RtAddCh(leftTop);
 139             int horizontal =  cast<int>((*frameChars)[1]);
 140             for (int i = Left() + 1; i < Left() + Width() - 1; ++i;)
 141             {
 142                 screen->MoveCursorTo(Top()i);
 143                 RtAddCh(horizontal);
 144                 screen->MoveCursorTo(Top() + Height() - 1i);
 145                 RtAddCh(horizontal);
 146             }
 147             int rightTop = cast<int>((*frameChars)[3]);
 148             screen->MoveCursorTo(Top()Left() + Width() - 1);
 149             RtAddCh(rightTop);
 150             int vertical = cast<int>((*frameChars)[2]);
 151             for (int i = Top() + 1; i < Top() + Height() - 1; ++i;)
 152             {
 153                 screen->MoveCursorTo(iLeft());
 154                 RtAddCh(vertical);
 155                 screen->MoveCursorTo(iLeft() + Width() - 1);
 156                 RtAddCh(vertical);
 157             }
 158             int leftBottom = cast<int>((*frameChars)[4]);
 159             screen->MoveCursorTo(Top() + Height() - 1Left());
 160             RtAddCh(leftBottom);
 161             int rightBottom = cast<int>((*frameChars)[5]);
 162             screen->MoveCursorTo(Top() + Height() - 1Left() + Width() - 1);
 163             RtAddCh(rightBottom);
 164             RtAttrOff(RtColorPair(color));
 165             if (!name.IsEmpty())
 166             {
 167                 RtAttrOn(RtColorPair(color));
 168                 screen->MoveCursorTo(Top()Left() + 2);
 169                 string s;
 170                 s.Append(' ');
 171                 s.Append(name);
 172                 s.Append(' ');
 173                 for (char c : s)
 174                 {
 175                     int ch = cast<int>(c);
 176                     RtAddCh(ch);
 177                 }
 178                 RtAttrOff(RtColorPair(color));
 179             }
 180         }
 181         public abstract CommandResult HandleKey(int key);
 182         public int Top()
 183         {
 184             if (zoomed)
 185             {
 186                 return 1;
 187             }
 188             else
 189             {
 190                 return top;
 191             }
 192         }
 193         public int Height()
 194         {
 195             if (zoomed)
 196             {
 197                 return screen->rows;
 198             }
 199             else
 200             {
 201                 return height;
 202             }
 203         }
 204         public int Left()
 205         {
 206             if (zoomed)
 207             {
 208                 return 0;
 209             }
 210             else
 211             {
 212                 return left;
 213             }
 214         }
 215         public int Width()
 216         {
 217             if (zoomed)
 218             {
 219                 return screen->cols;
 220             }
 221             else
 222             {
 223                 return width;
 224             }
 225         }
 226         public void ShowCursor()
 227         {
 228             screen->MoveCursorTo(cursorRowcursorCol);
 229         }
 230         public string name;
 231         public Screen* screen;
 232         public Debugger* debugger;
 233         public short color;
 234         public bool visible;
 235         public bool zoomed;
 236         public int top;
 237         public int height;
 238         public int left;
 239         public int width;
 240         public int cursorRow;
 241         public int cursorCol;
 242         public Window* next;
 243     }
 244 
 245     public const uint stoiFpSpInst = (cmsx.machine.STOI << 24u) | (cmsx.machine.regFP << 16u) | (cmsx.machine.regSP << 8u) | (0u << 0u);
 246     public const uint oriFpSpInst = (cmsx.machine.ORI << 24u) | (cmsx.machine.regFP << 16u) | (cmsx.machine.regSP << 8u) | (0u << 0u);
 247     public const uint retInst = (cmsx.machine.RET << 24u) | (0u << 16u) | (0u << 8u) | (0u << 0u);
 248 
 249     public nothrow bool InProlog(uint currentInst)
 250     {
 251         return currentInst == stoiFpSpInst || currentInst == oriFpSpInst;
 252     }
 253 
 254     public nothrow bool InEpilog(uint currentInst)
 255     {
 256         return currentInst == retInst;
 257     }
 258 
 259     public uint ReadInst(cmsx.kernel.Process* processulong address)
 260     {
 261         ulong inst = 0u;
 262         try
 263         {
 264             cmsx.kernel.ReadProcessMemory(cmsx.machine.GetMachine()processaddressinst4ufalse);
 265         }
 266         catch (Exception& ex)
 267         {
 268             cmsx.machine.Panic("debugger could not read process memory: " + ex.ToString());
 269         }
 270         return cast<uint>(inst);
 271     }
 272 
 273     public void WriteInst(cmsx.kernel.Process* processulong addressuint inst)
 274     {
 275         try
 276         {
 277             cmsx.kernel.WriteProcessMemory(cmsx.machine.GetMachine()processaddressinst4ucmsx.machine.Protection.execute);
 278         }
 279         catch (Exception& ex)
 280         {
 281             cmsx.machine.Panic("debugger could not writer to process memory: " + ex.ToString());
 282         }
 283     }
 284 
 285     public class Breakpoint
 286     {
 287         public enum Kind
 288         {
 289             stephard
 290         }
 291         public nothrow Breakpoint(Kind kind_ulong address_uint inst_) : kind(kind_)address(address_)inst(inst_)fp(0u)
 292         {
 293         }
 294         public Kind kind;
 295         public ulong address;
 296         public uint inst;
 297         public ulong fp;
 298     }
 299 
 300     public class Breakpoints
 301     {
 302         public nothrow Breakpoint* GetBreakpoint(ulong address) const
 303         {
 304             HashMap<ulongBreakpoint>.ConstIterator it = breakpoints.CFind(address);
 305             if (it != breakpoints.CEnd())
 306             {
 307                 return &it->second;
 308             }
 309             else
 310             {
 311                 return null;
 312             }
 313         }
 314         public nothrow void SetBreakpoint(const Breakpoint& bp)
 315         {
 316             breakpoints[bp.address] = bp;
 317         }
 318         public nothrow void RemoveBreakpoint(ulong address)
 319         {
 320             breakpoints.Remove(address);
 321         }
 322         private HashMap<ulongBreakpoint> breakpoints;
 323     }
 324 
 325     public class HeaderLine
 326     {
 327         public nothrow HeaderLine() : header()
 328         {
 329         }
 330         public void SetHeader(const string& header_)
 331         {
 332             header = header_;
 333         }
 334         public void Draw(Screen* screen)
 335         {
 336             int col = 0;
 337             bool hilite = false;
 338             RtAttrOn(RtColorPair(blackOnWhite));
 339             for (char c : header)
 340             {
 341                 if (c == '*')
 342                 {
 343                     if (!hilite)
 344                     {
 345                         RtAttrOff(RtColorPair(blackOnWhite));
 346                         RtAttrOn(RtColorPair(redOnWhite));
 347                         hilite = true;
 348                     }
 349                     else
 350                     {
 351                         RtAttrOff(RtColorPair(redOnWhite));
 352                         RtAttrOn(RtColorPair(blackOnWhite));
 353                         hilite = false;
 354                     }
 355                 }
 356                 else
 357                 {
 358                     int ch = cast<int>(c);
 359                     screen->MoveCursorTo(0col);
 360                     RtAddCh(ch);
 361                     ++col;
 362                 }
 363             }
 364             for (int i = col; i < screen->cols; ++i;)
 365             {
 366                 int ch = cast<int>(' ');
 367                 screen->MoveCursorTo(0i);
 368                 RtAddCh(ch);
 369             }
 370             RtAttrOff(RtColorPair(blackOnWhite));
 371         }
 372         private string header;
 373     }
 374 
 375     public class DissamblyFormatter : cmsx.machine.Formatter
 376     {
 377         public nothrow DissamblyFormatter() : symbolTable(null)
 378         {
 379         }
 380         public nothrow void SetSymbolTable(cmsx.object.SymbolTable* symbolTable_)
 381         {
 382             symbolTable = symbolTable_;
 383         }
 384         public nothrow void SetBreakpoints(Breakpoints* breakpoints_)
 385         {
 386             breakpoints = breakpoints_;
 387         }
 388         public nothrow void SetPC(ulong pc)
 389         {
 390             this->pc = pc;
 391         }
 392         public override string FormatRegisterNumber(byte x)
 393         {
 394             cmsx.object.Symbol* registerSymbol = symbolTable->GetRegisterSymbol(x);
 395             if (registerSymbol != null)
 396             {
 397                 return registerSymbol->name;
 398             }
 399             else
 400             {
 401                 return base->FormatRegisterNumber(x);
 402             }
 403         }
 404         public override string GetLabel(ulong address)
 405         {
 406             cmsx.object.Symbol* symbol = symbolTable->GetSymbolByAddress(address);
 407             if (symbol != null)
 408             {
 409                 if (!symbol->localName.IsEmpty())
 410                 {
 411                     return symbol->localName;
 412                 }
 413                 else
 414                 {
 415                     return symbol->name;
 416                 }
 417             }
 418             else
 419             {
 420                 return string();
 421             }
 422         }
 423         public override string GetTags(ulong address)
 424         {
 425             string tags;
 426             if (breakpoints->GetBreakpoint(address) != null)
 427             {
 428                 tags = tags + "*";
 429             }
 430             else
 431             {
 432                 tags = tags + " ";
 433             }
 434             if (address == pc)
 435             {
 436                 tags = tags + ">";
 437             }
 438             else
 439             {
 440                 tags = tags + " ";
 441             }
 442             tags = tags + " ";
 443             return tags;
 444         }
 445         private cmsx.object.SymbolTable* symbolTable;
 446         private ulong pc;
 447         private Breakpoints* breakpoints;
 448     }
 449 
 450     public class Disassembly : Window
 451     {
 452         public nothrow Disassembly(Breakpoints* breakpoints_) : base("Disassembly")disassemblyFormatter()breakpoints(breakpoints_)
 453         {
 454             header.SetHeader("*ESC* Exit *F1* Help *F2* Enter Command *F4* Output *F5* Run *F6* Memory *F8* Focus Next *F9* Toggle Breakpoint *F10* Step Over *F11* Step Into *F12* Step Out");
 455         }
 456         public nothrow void SetSymbolTable(cmsx.object.SymbolTable* symbolTable)
 457         {
 458             disassemblyFormatter.SetSymbolTable(symbolTable);
 459         }
 460         public nothrow void SetBreakpoints(Breakpoints* breakpoints)
 461         {
 462             disassemblyFormatter.SetBreakpoints(breakpoints);
 463         }
 464         public nothrow void SetScreen(Screen* screen_)
 465         {
 466             screen = screen_;
 467             color = whiteOnBlue;
 468             top = 1;
 469             left = 0;
 470             height = screen->rows - top - screen->commandWindowHeight - screen->outputWindowHeight;
 471             width = screen->cols - left;
 472             cursorRow = top;
 473             cursorCol = left;
 474         }
 475         public override CommandResult HandleKey(int key)
 476         {
 477             switch (key)
 478             {
 479                 case keyDown:
 480                 {
 481                     debugger->middle = debugger->middle + 4u;
 482                     return CommandResult.update;
 483                 }
 484                 case keyUp:
 485                 {
 486                     if (debugger->start >= 4u)
 487                     {
 488                         debugger->middle = debugger->middle - 4u;
 489                     }
 490                     return CommandResult.update;
 491                 }
 492                 case keyPgDown:
 493                 {
 494                     debugger->middle = debugger->middle + 4u * debugger->numInstsInWindow;
 495                     return CommandResult.update;
 496                 }
 497                 case keyPgUp:
 498                 {
 499                     if (debugger->start >= 4 * debugger->numInstsInWindow)
 500                     {
 501                         debugger->middle = debugger->middle - 4u * debugger->numInstsInWindow;
 502                     }
 503                     return CommandResult.update;
 504                 }
 505                 case keyHome:
 506                 {
 507                     debugger->middle = debugger->pc;
 508                     return CommandResult.update;
 509                 }
 510                 case keyF5:
 511                 {
 512                     debugger->Run();
 513                     return CommandResult.ret;
 514                 }
 515                 case keyF9:
 516                 {
 517                     debugger->ToggleBreakpoint(debugger->middle);
 518                     return CommandResult.update;
 519                 }
 520                 case keyF10:
 521                 {
 522                     debugger->StepOver();
 523                     return CommandResult.ret;
 524                 }
 525                 case keyF11:
 526                 {
 527                     debugger->StepInto();
 528                     return CommandResult.ret;
 529                 }
 530                 case keyF12:
 531                 {
 532                     debugger->StepOut();
 533                     return CommandResult.ret;
 534                 }
 535             }
 536             return CommandResult.cont;
 537         }
 538         public void RetrieveInstructions(ulong pccmsx.kernel.Process* process)
 539         {
 540             ulong numInstsInWindow = cast<ulong>(Height() - 2);
 541             ulong start = pc - 4u * (numInstsInWindow / 2u);
 542             ulong end = start + (4u * numInstsInWindow);
 543             for (ulong address = start; address < end; address = address + 4u;)
 544             {
 545                 HashMap<ulonglong>.ConstIterator it = instructions.CFind(address);
 546                 if (it == instructions.CEnd())
 547                 {
 548                     if (address < entryPointAddress || address >= instructionEndAddress)
 549                     {
 550                         instructions[address] = -1;
 551                     }
 552                     else
 553                     {
 554                         uint inst = ReadInst(processaddress);
 555                         Breakpoint* bp = breakpoints->GetBreakpoint(address);
 556                         if (bp != null)
 557                         {
 558                             inst = bp->inst;
 559                         }
 560                         instructions[address] = cast<long>(inst);
 561                     }
 562                 }
 563             }
 564         }
 565         public override void Draw()
 566         {
 567             header.Draw(screen);
 568             DrawFrame();
 569             disassemblyFormatter.SetPC(debugger->pc);
 570             RetrieveInstructions(debugger->middledebugger->process);
 571             ulong numInstsInWindow = cast<ulong>(Height() - 2);
 572             ulong start = debugger->middle - 4u * (numInstsInWindow / 2u);
 573             ulong end = start + (4u * numInstsInWindow);
 574             int row = Top() + 1;
 575             cursorRow = row;
 576             cursorCol = Left() + 1;
 577             for (ulong address = start; address < end; address = address + 4u;)
 578             {
 579                 screen->MoveCursorTo(rowLeft() + 1);
 580                 ustring line = GetInstructionLine(address);
 581                 if (address == debugger->middle)
 582                 {
 583                     if (breakpoints->GetBreakpoint(address) != null)
 584                     {
 585                         RtAttrOn(RtColorPair(redOnWhite));
 586                     }
 587                     else
 588                     {
 589                         RtAttrOn(RtColorPair(blackOnWhite));
 590                     }
 591                 }
 592                 else if (breakpoints->GetBreakpoint(address) != null)
 593                 {
 594                     RtAttrOn(RtColorPair(whiteOnRed));
 595                 }
 596                 else if (address == debugger->pc)
 597                 {
 598                     RtAttrOn(RtColorPair(cyanOnBlue));
 599                 }
 600                 else
 601                 {
 602                     RtAttrOn(RtColorPair(color));
 603                 }
 604                 for (int col = Left() + 1; col < Left() + Width() - 1; ++col;)
 605                 {
 606                     int ch = cast<int>(' ');
 607                     int charIndex = col - (Left() + 1);
 608                     if (charIndex < line.Length())
 609                     {
 610                         ch = cast<int>(line[charIndex]);
 611                     }
 612                     RtAddCh(ch);
 613                 }
 614                 if (address == debugger->middle)
 615                 {
 616                     if (breakpoints->GetBreakpoint(address) != null)
 617                     {
 618                         RtAttrOff(RtColorPair(redOnWhite));
 619                     }
 620                     else
 621                     {
 622                         RtAttrOff(RtColorPair(blackOnWhite));
 623                     }
 624                     cursorRow = row;
 625                 }
 626                 else if (breakpoints->GetBreakpoint(address) != null)
 627                 {
 628                     RtAttrOff(RtColorPair(whiteOnRed));
 629                 }
 630                 else if (address == debugger->pc)
 631                 {
 632                     RtAttrOff(RtColorPair(cyanOnBlue));
 633                 }
 634                 else
 635                 {
 636                     RtAttrOff(RtColorPair(color));
 637                 }
 638                 ++row;
 639             }
 640             if (screen->focusedWindow == this)
 641             {
 642                 screen->MoveCursorTo(cursorRowcursorCol);
 643             }
 644         }
 645         public nothrow void SetEntryPointAddress(ulong entryPointAddress_)
 646         {
 647             entryPointAddress = entryPointAddress_;
 648         }
 649         public nothrow void SetInstructionEndAddress(ulong instructionEndAddress_)
 650         {
 651             instructionEndAddress = instructionEndAddress_;
 652         }
 653         private ustring GetInstructionLine(ulong address)
 654         {
 655             HashMap<ulonglong>.ConstIterator it = instructions.CFind(address);
 656             long instruction = -1;
 657             if (it != instructions.CEnd())
 658             {
 659                 instruction = it->second;
 660             }
 661             if (instruction == -1)
 662             {
 663                 string result = "#" + ToHexString(address);
 664                 return ToUtf32(result);
 665             }
 666             uint inst = cast<uint>(instruction);
 667             byte opCode = cast<byte>(inst >> 24u);
 668             byte x = cast<byte>(inst >> 16u);
 669             byte y = cast<byte>(inst >> 8u);
 670             byte z = cast<byte>(inst);
 671             string instructionLine = cmsx.machine.FormatInstruction(addressopCodexyzdisassemblyFormatter);
 672             return ToUtf32(instructionLine);
 673         }
 674         private HeaderLine header;
 675         private Breakpoints* breakpoints;
 676         private DissamblyFormatter disassemblyFormatter;
 677         private HashMap<ulonglong> instructions;
 678         private ulong entryPointAddress;
 679         private ulong instructionEndAddress;
 680     }
 681 
 682     public class Memory : Window
 683     {
 684         public enum Format
 685         {
 686             byteswydestetrasoctas
 687         }
 688         public nothrow Memory() : 
 689             base("Memory - data segment")header()segmentIndex(cmsx.machine.dataSegmentIndex)start(0u)end(0u)bufferStartAddress(0u)topAddress(0u)numBytesInRow(0)init(true)
 690             format(Format.bytes)
 691         {
 692             header.SetHeader("*ESC* Exit *F1* Help *F2* Enter Command *F3* Disassembly *F4* Output *F8* Focus Next *D* Data Segment *P* Pool Segment *S* Stack Segment *B* Bytes *W* Wydes *T* Tetras *O* Octas");
 693         }
 694         public nothrow void SetScreen(Screen* screen_)
 695         {
 696             screen = screen_;
 697             color = whiteOnBlue;
 698             top = 1;
 699             left = 0;
 700             height = screen->rows - top - screen->commandWindowHeight - screen->outputWindowHeight;
 701             width = screen->cols - left;
 702             cursorRow = top + 1;
 703             cursorCol = left + 1;
 704             numBytesInRow = 16;
 705         }
 706         public override void Draw()
 707         {
 708             header.Draw(screen);
 709             DrawFrame();
 710             RtAttrOn(RtColorPair(color));
 711             if (init)
 712             {
 713                 ResolveLimits(debugger->process);
 714                 init = false;
 715             }
 716             int n = Height() - 2;
 717             for (int i = 0; i < n; ++i;)
 718             {
 719                 int row = Top() + 1 + i;
 720                 int col = Left() + 1;
 721                 screen->MoveCursorTo(rowcol);
 722                 ulong addr = topAddress + cast<ulong>(i * numBytesInRow);
 723                 string line = GetLine(addr);
 724                 for (int j = 0; j < Width() - 2; ++j;)
 725                 {
 726                     int ch = cast<int>(' ');
 727                     if (j < line.Length())
 728                     {
 729                         ch = cast<int>(line[j]);
 730                     }
 731                     RtAddCh(ch);
 732                 }
 733             }
 734             RtAttrOff(RtColorPair(color));
 735         }
 736         public void ShowAddress(byte segmentulong address)
 737         {
 738             segmentIndex = segment;
 739             topAddress = address;
 740             init = true;
 741         }
 742         public override CommandResult HandleKey(int key)
 743         {
 744             switch (key)
 745             {
 746                 case keyHome: GoStart(); return CommandResult.update;
 747                 case keyEnd: GoEnd(); return CommandResult.update;
 748                 case keyUp: GoUp(); return CommandResult.update;
 749                 case keyDown: GoDown(); return CommandResult.update;
 750                 case keyPgUp: GoPageUp(); return CommandResult.update;
 751                 case keyPgDown: GoPageDown(); return CommandResult.update;
 752                 case cast<int>('d'):  segmentIndex = cmsx.machine.dataSegmentIndex; name = "Memory - data segment"; init = true; return CommandResult.update;
 753                 case cast<int>('p'):  segmentIndex = cmsx.machine.poolSegmentIndex; name = "Memory - pool segment"; init = true; return CommandResult.update;
 754                 case cast<int>('s'):  segmentIndex = cmsx.machine.stackSegmentIndex; name = "Memory - stack segment"; init = true; return CommandResult.update;
 755                 case cast<int>('b'):  format = Format.bytes; init = true; return CommandResult.update;
 756                 case cast<int>('w'):  format = Format.wydes; init = true; return CommandResult.update;
 757                 case cast<int>('t'):  format = Format.tetras; init = true; return CommandResult.update;
 758                 case cast<int>('o'):  format = Format.octas; init = true; return CommandResult.update;
 759             }
 760             return CommandResult.cont;
 761         }
 762         private long NumBytesInWindow()
 763         {
 764             long numBytesInWindow = (cast<long>(Height()) - 2) * numBytesInRow;
 765             return numBytesInWindow;
 766         }
 767         private void GoStart()
 768         {
 769             topAddress = start;
 770         }
 771         private void GoEnd()
 772         {
 773             long addr = cast<long>(end);
 774             addr = addr - NumBytesInWindow();
 775             if (addr < cast<long>(start))
 776             {
 777                 addr = cast<long>(start);
 778             }
 779             topAddress = cast<ulong>(addr);
 780         }
 781         private void GoUp()
 782         {
 783             topAddress = Max(starttopAddress - cast<ulong>(numBytesInRow));
 784         }
 785         private void GoDown()
 786         {
 787             topAddress = topAddress + cast<ulong>(numBytesInRow);
 788             if (topAddress + cast<ulong>(NumBytesInWindow()) >= end)
 789             {
 790                 GoEnd();
 791             }
 792         }
 793         private void GoPageUp()
 794         {
 795             long addr = cast<long>(topAddress);
 796             addr = addr - NumBytesInWindow();
 797             if (addr < cast<long>(start))
 798             {
 799                 addr = cast<long>(start);
 800             }
 801             topAddress = cast<ulong>(addr);
 802         }
 803         private void GoPageDown()
 804         {
 805             long numBytesInWindow = NumBytesInWindow();
 806             long addr = cast<long>(topAddress);
 807             addr = addr + numBytesInWindow;
 808             if (addr + numBytesInWindow >= cast<long>(end))
 809             {
 810                 GoEnd();
 811             }
 812             else
 813             {
 814                 topAddress = cast<ulong>(addr);
 815             }
 816         }
 817         private void ResolveLimits(cmsx.kernel.Process* process)
 818         {
 819             cmsx.kernel.SegmentDescriptor* segmentDescriptor = process->memoryTable.segmentDescriptors[segmentIndex];
 820             start = segmentDescriptor->baseAddress + segmentDescriptor->startAddress;
 821             end = start + segmentDescriptor->length;
 822             topAddress = start;
 823             bufferStartAddress = 0u;
 824         }
 825         private string GetLine(ulong addr)
 826         {
 827             if (addr >= end)
 828             {
 829                 return string();
 830             }
 831             string line = "#";
 832             line.Append(ToHexString(addr));
 833             if (format == Format.bytes)
 834             {
 835                 string chars;
 836                 for (int j = 0; j < numBytesInRow; ++j;)
 837                 {
 838                     if (j == numBytesInRow / 2)
 839                     {
 840                         line.Append(" -");
 841                     }
 842                     int x = GetByte(addr + cast<ulong>(j));
 843                     if (x != -1)
 844                     {
 845                         byte b = cast<byte>(x);
 846                         line.Append(' ').Append(ToHexString(b));
 847                         char c = cast<char>(b);
 848                         if (!IsPrintable(c))
 849                         {
 850                             c = '.';
 851                         }
 852                         chars.Append(c);
 853                     }
 854                     else
 855                     {
 856                         line.Append("   ");
 857                         chars.Append(' ');
 858                     }
 859                 }
 860                 line.Append(' ');
 861                 line.Append(chars);
 862                 return line;
 863             }
 864             else if (format == Format.wydes)
 865             {
 866                 for (int j = 0; j < numBytesInRow / 2; ++j;)
 867                 {
 868                     if (j == numBytesInRow / 4)
 869                     {
 870                         line.Append(" -");
 871                     }
 872                     int x = GetWyde(addr + cast<ulong>(j * 2));
 873                     if (x != -1)
 874                     {
 875                         ushort w = cast<ushort>(x);
 876                         line.Append(' ').Append(ToHexString(w));
 877                     }
 878                     else
 879                     {
 880                         line.Append(' '4 + 1);
 881                     }
 882                 }
 883                 return line;
 884             }
 885             else if (format == Format.tetras)
 886             {
 887                 for (int j = 0; j < numBytesInRow / 4; ++j;)
 888                 {
 889                     if (j == numBytesInRow / 8)
 890                     {
 891                         line.Append(" -");
 892                     }
 893                     long x = GetTetra(addr + cast<ulong>(j * 4));
 894                     if (x != -1)
 895                     {
 896                         uint i = cast<uint>(x);
 897                         line.Append(' ').Append(ToHexString(i));
 898                     }
 899                     else
 900                     {
 901                         line.Append(' '8 + 1);
 902                     }
 903                 }
 904                 return line;
 905             }
 906             else if (format == Format.octas)
 907             {
 908                 for (int j = 0; j < numBytesInRow / 8; ++j;)
 909                 {
 910                     if (j == numBytesInRow / 16)
 911                     {
 912                         line.Append(" -");
 913                     }
 914                     Pair<ulongbool> x = GetOcta(addr + cast<ulong>(j * 8));
 915                     if (x.second)
 916                     {
 917                         line.Append(' ').Append(ToHexString(x.first));
 918                     }
 919                     else
 920                     {
 921                         line.Append(' '16 + 1);
 922                     }
 923                 }
 924                 return line;
 925             }
 926             else
 927             {
 928                 return string();
 929             }
 930         }
 931         private int GetByte(ulong addr)
 932         {
 933             bool fillBuf = false;
 934             if (bufferStartAddress == 0u)
 935             {
 936                 bufferStartAddress = start;
 937                 fillBuf = true;
 938             }
 939             while (bufferStartAddress >= start && addr < bufferStartAddress)
 940             {
 941                 bufferStartAddress = bufferStartAddress - cast<ulong>(buffer.Length());
 942                 fillBuf = true;
 943             }
 944             while (bufferStartAddress + cast<ulong>(buffer.Length()) < end && addr >= bufferStartAddress + cast<ulong>(buffer.Length()))
 945             {
 946                 bufferStartAddress = bufferStartAddress + cast<ulong>(buffer.Length());
 947                 fillBuf = true;
 948             }
 949             if (fillBuf)
 950             {
 951                 FillBuffer();
 952             }
 953             if (addr >= bufferStartAddress && addr < bufferStartAddress + cast<ulong>(buffer.Length()))
 954             {
 955                 return buffer[cast<long>(addr - bufferStartAddress)];
 956             }
 957             return -1;
 958         }
 959         private int GetWyde(ulong addr)
 960         {
 961             int b1 = GetByte(addr);
 962             int b2 = GetByte(addr + 1u);
 963             if (b1 != -1 && b2 != -1)
 964             {
 965                 return cast<ushort>(b1) << 8u | cast<ushort>(b2);
 966             }
 967             else
 968             {
 969                 return -1;
 970             }
 971         }
 972         private long GetTetra(ulong addr)
 973         {
 974             int b1 = GetByte(addr);
 975             int b2 = GetByte(addr + 1u);
 976             int b3 = GetByte(addr + 2u);
 977             int b4 = GetByte(addr + 3u);
 978             if (b1 != -1 && b2 != -1 && b3 != -1 && b4 != -1)
 979             {
 980                 return cast<uint>(b1) << 24u | cast<uint>(b2) << 16u | cast<uint>(b3) << 8u | cast<uint>(b4);
 981             }
 982             else
 983             {
 984                 return -1;
 985             }
 986         }
 987         private Pair<ulongbool> GetOcta(ulong addr)
 988         {
 989             int b1 = GetByte(addr);
 990             int b2 = GetByte(addr + 1u);
 991             int b3 = GetByte(addr + 2u);
 992             int b4 = GetByte(addr + 3u);
 993             int b5 = GetByte(addr + 4u);
 994             int b6 = GetByte(addr + 5u);
 995             int b7 = GetByte(addr + 6u);
 996             int b8 = GetByte(addr + 7u);
 997             if (b1 != -1 && b2 != -1 && b3 != -1 && b4 != -1 && b5 != -1 && b6 != -1 && b7 != -1 && b8 != -1)
 998             {
 999                 return MakePair(
1000                     cast<ulong>(b1) << 56u | cast<ulong>(b2) << 48u | cast<ulong>(b3) << 40u | cast<ulong>(b4) << 32u | cast<ulong>(b5) << 24u | cast<ulong>(b6) << 16u | cast<ulong>(b7) << 8u | cast<ulong>(b8)
1001                     true);
1002             }
1003             else
1004             {
1005                 return MakePair(cast<ulong>(0u)false);
1006             }
1007         }
1008         private void FillBuffer()
1009         {
1010             ulong size = Min(end - bufferStartAddresscast<ulong>(buffer.Length()));
1011             try
1012             {
1013                 cmsx.kernel.ReadProcessMemory(*debugger->machinedebugger->processbufferStartAddress&buffer[0]sizefalse);
1014             }
1015             catch (const Exception& ex)
1016             {
1017                 cmsx.machine.Panic("debugger: could not read process memory: " + ex.ToString());
1018             }
1019         }
1020         private HeaderLine header;
1021         private byte segmentIndex;
1022         private ulong start;
1023         private ulong end;
1024         private ulong topAddress;
1025         private byte[4096] buffer;
1026         private ulong bufferStartAddress;
1027         private int numBytesInRow;
1028         private bool init;
1029         private Format format;
1030     }
1031 
1032     public class Output : Window
1033     {
1034         public nothrow Output() : base("Output")
1035         {
1036             header.SetHeader("*ESC* Exit *F1* Help *F2* Enter Command *F3* Disassembly *F6* Memory *F8* Focus Next *C* Clear");
1037         }
1038         public void SetScreen(Screen* screen_)
1039         {
1040             screen = screen_;
1041             color = whiteOnCyan;
1042             top = screen->rows - screen->commandWindowHeight - screen->outputWindowHeight;
1043             left = 0;
1044             height = screen->outputWindowHeight;
1045             width = screen->cols - left;
1046             cursorRow = top + height - 2;
1047             cursorCol = left;
1048             topLineIndex = 0;
1049         }
1050         public override void Draw()
1051         {
1052             header.Draw(screen);
1053             DrawFrame();
1054             int n = Top() + Height() - 1;
1055             cursorCol = Left() + 1;
1056             RtAttrOn(RtColorPair(color));
1057             for (int i = Top() + 1; i < n; ++i;)
1058             {
1059                 int lineIndex = topLineIndex + i - (Top() + 1);
1060                 ustring line;
1061                 if (lineIndex >= 0 && lineIndex < lines.Count())
1062                 {
1063                     line = lines[lineIndex].first;
1064                 }
1065                 int m = Width() - 1;
1066                 for (int j = Left() + 1; j < m; ++j;)
1067                 {
1068                     screen->MoveCursorTo(ij);
1069                     int charIndex = j - (Left() + 1);
1070                     int ch = cast<int>(' ');
1071                     if (charIndex >= 0 && charIndex < line.Length())
1072                     {
1073                         uchar c = line[charIndex];
1074                         if (IsGraphic(c))
1075                         {
1076                             ch = cast<int>(c);
1077                         }
1078                     }
1079                     RtAddCh(ch);
1080                 }
1081             }
1082             RtAttrOff(RtColorPair(color));
1083             if (screen->focusedWindow == this)
1084             {
1085                 screen->MoveCursorTo(cursorRowcursorCol);
1086             }
1087         }
1088         public override CommandResult HandleKey(int key)
1089         {
1090             switch (key)
1091             {
1092                 case keyEnter:
1093                 {
1094                     int lineIndex = topLineIndex + cursorRow - (Top() + 1);
1095                     if (lineIndex >= 0 && lineIndex < lines.Count())
1096                     {
1097                         ulong address = lines[lineIndex].second;
1098                         if (address != 0u)
1099                         {
1100                             debugger->ShowAddress(address);
1101                             return CommandResult.update;
1102                         }
1103                     }
1104                     break;
1105                 }
1106                 case keyUp:
1107                 {
1108                     if (cursorRow > Top() + 1)
1109                     {
1110                         --cursorRow;
1111                         return CommandResult.update;
1112                     }
1113                     else if (topLineIndex > 0)
1114                     {
1115                         topLineIndex = topLineIndex - 1;
1116                         return CommandResult.update;
1117                     }
1118                     break;
1119                 }
1120                 case keyDown:
1121                 {
1122                     if (cursorRow < Top() + Height() - 2)
1123                     {
1124                         ++cursorRow;
1125                         return CommandResult.update;
1126                     }
1127                     else
1128                     {
1129                         int n = Height() - 2;
1130                         if (topLineIndex < lines.Count() - n)
1131                         {
1132                             topLineIndex = topLineIndex + 1;
1133                             return CommandResult.update;
1134                         }
1135                     }
1136                     break;
1137                 }
1138                 case cast<int>('c'):
1139                 {
1140                     lines.Clear();
1141                     int n = Height() - 2;
1142                     topLineIndex = cast<int>(lines.Count() - n);
1143                     cursorRow = Top() + Height() - 2;
1144                     return CommandResult.update;
1145                 }
1146             }
1147             return CommandResult.cont;
1148         }
1149         public void AddChar(uchar culong address)
1150         {
1151             if (lines.IsEmpty())
1152             {
1153                 lines.Add(MakePair(ustring()cast<ulong>(0u)));
1154             }
1155             if (IsGraphic(c))
1156             {
1157                 lines.Back().first.Append(c);
1158                 lines.Back().second = address;
1159             }
1160             else
1161             {
1162                 if (c == '\n')
1163                 {
1164                     lines.Add(MakePair(ustring()cast<ulong>(0u)));
1165                 }
1166                 else if (cast<int>(c) < 128)
1167                 {
1168                     lines.Back().first.Append(ToUtf32(MakeCharLiteral(cast<char>(c))));
1169                     lines.Back().second = address;
1170                 }
1171             }
1172         }
1173         public void AddLine(const ustring& lineulong address)
1174         {
1175             for (uchar c : line)
1176             {
1177                 AddChar(caddress);
1178             }
1179             if (!lines.IsEmpty())
1180             {
1181                 if (!lines.Back().first.IsEmpty())
1182                 {
1183                     lines.Add(MakePair(ustring()cast<ulong>(0u)));
1184                 }
1185             }
1186             int n = Height() - 2;
1187             topLineIndex = cast<int>(lines.Count() - n);
1188             cursorRow = Top() + Height() - 2;
1189         }
1190         private HeaderLine header;
1191         private List<Pair<ustringulong>> lines;
1192         private int topLineIndex;
1193     }
1194 
1195     public class CommandWindow : Window
1196     {
1197         public nothrow CommandWindow() : base("Command")
1198         {
1199             header.SetHeader("*ESC* Exit *F1* Help *F3* Disassembly *F4* Output *F6* Memory *F8* Focus Next");
1200         }
1201         public void SetScreen(Screen* screen_)
1202         {
1203             screen = screen_;
1204             color = blackOnWhite;
1205             top = screen->rows - screen->commandWindowHeight;
1206             left = 0;
1207             height = screen->commandWindowHeight;
1208             width = screen->cols - left;
1209             cursorRow = top + height - 2;
1210             cursorCol = left + 2;
1211             pos = 0;
1212             prevWasTab = false;
1213         }
1214         public override void Draw()
1215         {
1216             header.Draw(screen);
1217             DrawFrame();
1218             RtAttrOn(RtColorPair(color));
1219             int n = Top() + Height() - 1;
1220             for (int i = Top() + 1; i < n; ++i;)
1221             {
1222                 for (int j = Left() + 1; j < Left() + Width() - Left() - 1; ++j;)
1223                 {
1224                     screen->MoveCursorTo(ij);
1225                     int index = j - (Left() + 2);
1226                     int ch = cast<int>(' ');
1227                     if (i == Top() + 1 && index >= 0 && index < line.Length())
1228                     {
1229                         ch = cast<int>(line[index]);
1230                     }
1231                     RtAddCh(ch);
1232                 }
1233             }
1234             if (!matches.IsEmpty())
1235             {
1236                 string m = " " + ToString(matchIndex + 1) + "/" + ToString(matches.Count()) + " ";
1237                 screen->MoveCursorTo(ncast<int>(Width() - 2 - m.Length()));
1238                 for (char c : m)
1239                 {
1240                     RtAddCh(cast<int>(c));
1241                 }
1242             }
1243             if (screen->focusedWindow == this)
1244             {
1245                 screen->MoveCursorTo(cursorRowcursorCol);
1246             }
1247             RtAttrOff(RtColorPair(color));
1248         }
1249         public void ClearMatches()
1250         {
1251             prevWasTab = false;
1252             matches.Clear();
1253             matchIndex = 0;
1254         }
1255         public override CommandResult HandleKey(int key)
1256         {
1257             switch (key)
1258             {
1259                 case keyEnter:
1260                 {
1261                     ClearMatches();
1262                     Evaluate(debuggerline);
1263                     history.Add(line);
1264                     historyIndex = cast<int>(history.Count());
1265                     line.Clear();
1266                     pos = 0;
1267                     cursorCol = Left() + 2;
1268                     return CommandResult.update;
1269                 }
1270                 case keyTab:
1271                 {
1272                     if (!prevWasTab)
1273                     {
1274                         debugger->FindSymbolsMatchingPrefix(linematches);
1275                         matchIndex = 0;
1276                     }
1277                     else if (!matches.IsEmpty())
1278                     {
1279                         matchIndex = cast<int>((matchIndex + 1) % matches.Count());
1280                     }
1281                     if (matchIndex >= 0 && matchIndex < matches.Count())
1282                     {
1283                         line = matches[matchIndex];
1284                     }
1285                     pos = cast<int>(line.Length());
1286                     cursorCol = Left() + 2 + pos;
1287                     prevWasTab = true;
1288                     return CommandResult.update;
1289                 }
1290                 case keyBackspace:
1291                 {
1292                     ClearMatches();
1293                     if (pos > 0)
1294                     {
1295                         line = line.Substring(0pos - 1) + line.Substring(pos);
1296                         --pos;
1297                         cursorCol = cursorCol - 1;
1298                         return CommandResult.update;
1299                     }
1300                     break;
1301                 }
1302                 case keyDel:
1303                 {
1304                     ClearMatches();
1305                     if (pos < line.Length())
1306                     {
1307                         ++pos;
1308                         cursorCol = cursorCol + 1;
1309                         line = line.Substring(0pos - 1) + line.Substring(pos);
1310                         --pos;
1311                         cursorCol = cursorCol - 1;
1312                         return CommandResult.update;
1313                     }
1314                     break;
1315                 }
1316                 case keyHome:
1317                 {
1318                     ClearMatches();
1319                     pos = 0;
1320                     cursorCol = Left() + 2;
1321                     return CommandResult.update;
1322                 }
1323                 case keyEnd:
1324                 {
1325                     prevWasTab = false;
1326                     pos = cast<int>(line.Length());
1327                     cursorCol = Left() + 2 + pos;
1328                     return CommandResult.update;
1329                 }
1330                 case keyLeft:
1331                 {
1332                     ClearMatches();
1333                     if (pos > 0)
1334                     {
1335                         --pos;
1336                         cursorCol = cursorCol - 1;
1337                         return CommandResult.update;
1338                     }
1339                     break;
1340                 }
1341                 case keyRight:
1342                 {
1343                     ClearMatches();
1344                     if (pos < line.Length())
1345                     {
1346                         ++pos;
1347                         cursorCol = cursorCol + 1;
1348                         return CommandResult.update;
1349                     }
1350                     break;
1351                 }
1352                 case keyUp:
1353                 {
1354                     ClearMatches();
1355                     if (historyIndex > 0)
1356                     {
1357                         --historyIndex;
1358                         if (historyIndex >= 0 && historyIndex < history.Count())
1359                         {
1360                             line = history[historyIndex];
1361                             pos = cast<int>(line.Length());
1362                             cursorCol = Left() + 2 + pos;
1363                             return CommandResult.update;
1364                         }
1365                     }
1366                     break;
1367                 }
1368                 case keyDown:
1369                 {
1370                     ClearMatches();
1371                     if (historyIndex < history.Count())
1372                     {
1373                         ++historyIndex;
1374                         if (historyIndex >= 0 && historyIndex < history.Count())
1375                         {
1376                             line = history[historyIndex];
1377                             pos = cast<int>(line.Length());
1378                             cursorCol = Left() + 2 + pos;
1379                             return CommandResult.update;
1380                         }
1381                     }
1382                     line = ustring();
1383                     pos = 0;
1384                     cursorCol = Left() + 2;
1385                     return CommandResult.update;
1386                 }
1387                 default:
1388                 {
1389                     ClearMatches();
1390                     uchar c = cast<uchar>(key);
1391                     if (IsGraphic(c))
1392                     {
1393                         if (pos < line.Length())
1394                         {
1395                             line = line.Substring(0pos) + ustring(c1) + line.Substring(pos);
1396                         }
1397                         else
1398                         {
1399                             line.Append(c);
1400                         }
1401                         cursorCol = cursorCol + 1;
1402                         ++pos;
1403                         return CommandResult.update;
1404                     }
1405                     break;
1406                 }
1407             }
1408             return CommandResult.cont;
1409         }
1410         private HeaderLine header;
1411         private List<ustring> history;
1412         private ustring line;
1413         private int pos;
1414         private int historyIndex;
1415         private bool prevWasTab;
1416         private List<ustring> matches;
1417         private int matchIndex;
1418     }
1419 
1420     public class InputWindow : Window
1421     {
1422         public nothrow InputWindow() : base("Input")
1423         {
1424             header.SetHeader("*ESC* Exit");
1425         }
1426         public void SetScreen(Screen* screen_)
1427         {
1428             screen = screen_;
1429             color = blackOnWhite;
1430             top = screen->rows - screen->commandWindowHeight;
1431             left = 0;
1432             height = screen->commandWindowHeight;
1433             width = screen->cols - left;
1434             cursorRow = top + height - 2;
1435             cursorCol = left + 2;
1436             pos = 0;
1437         }
1438         public override void Draw()
1439         {
1440             header.Draw(screen);
1441             DrawFrame();
1442             RtAttrOn(RtColorPair(color));
1443             int n = Top() + Height() - 1;
1444             for (int i = Top() + 1; i < n; ++i;)
1445             {
1446                 for (int j = Left() + 1; j < Left() + Width() - Left() - 1; ++j;)
1447                 {
1448                     screen->MoveCursorTo(ij);
1449                     int index = j - (Left() + 2);
1450                     int ch = cast<int>(' ');
1451                     if (i == Top() + 1 && index >= 0 && index < line.Length())
1452                     {
1453                         ch = cast<int>(line[index]);
1454                     }
1455                     RtAddCh(ch);
1456                 }
1457             }
1458             if (screen->focusedWindow == this)
1459             {
1460                 screen->MoveCursorTo(cursorRowcursorCol);
1461             }
1462             RtAttrOff(RtColorPair(color));
1463         }
1464         public override CommandResult HandleKey(int key)
1465         {
1466             switch (key)
1467             {
1468                 case keyEnter:
1469                 {
1470                     resultLine = line;
1471                     line.Clear();
1472                     pos = 0;
1473                     cursorCol = Left() + 2;
1474                     return CommandResult.ret;
1475                 }
1476                 case keyBackspace:
1477                 {
1478                     if (pos > 0)
1479                     {
1480                         line = line.Substring(0pos - 1) + line.Substring(pos);
1481                         --pos;
1482                         cursorCol = cursorCol - 1;
1483                         return CommandResult.update;
1484                     }
1485                     break;
1486                 }
1487                 case keyDel:
1488                 {
1489                     if (pos < line.Length())
1490                     {
1491                         ++pos;
1492                         cursorCol = cursorCol + 1;
1493                         line = line.Substring(0pos - 1) + line.Substring(pos);
1494                         --pos;
1495                         cursorCol = cursorCol - 1;
1496                         return CommandResult.update;
1497                     }
1498                     break;
1499                 }
1500                 case keyHome:
1501                 {
1502                     pos = 0;
1503                     cursorCol = Left() + 2;
1504                     return CommandResult.update;
1505                 }
1506                 case keyEnd:
1507                 {
1508                     pos = cast<int>(line.Length());
1509                     cursorCol = Left() + 2 + pos;
1510                     return CommandResult.update;
1511                 }
1512                 case keyLeft:
1513                 {
1514                     if (pos > 0)
1515                     {
1516                         --pos;
1517                         cursorCol = cursorCol - 1;
1518                         return CommandResult.update;
1519                     }
1520                     break;
1521                 }
1522                 case keyRight:
1523                 {
1524                     if (pos < line.Length())
1525                     {
1526                         ++pos;
1527                         cursorCol = cursorCol + 1;
1528                         return CommandResult.update;
1529                     }
1530                     break;
1531                 }
1532                 default:
1533                 {
1534                     uchar c = cast<uchar>(key);
1535                     if (IsGraphic(c))
1536                     {
1537                         if (pos < line.Length())
1538                         {
1539                             line = line.Substring(0pos) + ustring(c1) + line.Substring(pos);
1540                         }
1541                         else
1542                         {
1543                             line.Append(c);
1544                         }
1545                         cursorCol = cursorCol + 1;
1546                         ++pos;
1547                         return CommandResult.update;
1548                     }
1549                     break;
1550                 }
1551             }
1552             return CommandResult.cont;
1553         }
1554         private HeaderLine header;
1555         private ustring line;
1556         private int pos;
1557         public ustring resultLine;
1558     }
1559 
1560     public class Debugger : cmsx.kernel.Debugger
1561     {
1562         public nothrow Debugger() : screen()symbolTable(null)breakpoints()disassembly(&breakpoints)output()commandWindow()inputWindow()
1563         {
1564         }
1565         public override void Init(Process* process)
1566         {
1567             screen.Reset(new Screen());
1568             cmsx.kernel.Kernel& kernel = cmsx.kernel.Kernel.Instance();
1569             cmsx.object.ExecutableFile* executable = kernel.Executable();
1570             symbolTable = &executable->GetSymbolTable();
1571             disassembly.SetSymbolTable(symbolTable);
1572             disassembly.SetBreakpoints(&breakpoints);
1573             disassembly.SetScreen(screen.Get());
1574             memory.SetScreen(screen.Get());
1575             output.SetScreen(screen.Get());
1576             commandWindow.SetScreen(screen.Get());
1577             inputWindow.SetScreen(screen.Get());
1578             programEntryPoint = process->entryPoint;
1579             disassembly.SetEntryPointAddress(programEntryPoint);
1580             disassembly.SetInstructionEndAddress(programEntryPoint + executable->GetCodeSection()->dataLength);
1581             uint entryPointInst = ReadInst(processprogramEntryPoint);
1582             stepBreakpoints.Add(Breakpoint(Breakpoint.Kind.stepprogramEntryPointentryPointInst));
1583             WriteInst(processprogramEntryPointdebugBreakInst);
1584             disassembly.SetDebugger(this);
1585             disassembly.visible = true;
1586             disassembly.next = &memory;
1587             memory.SetDebugger(this);
1588             memory.visible = false;
1589             memory.next = &output;
1590             output.SetDebugger(this);
1591             output.visible = true;
1592             output.next = &commandWindow;
1593             commandWindow.SetDebugger(this);
1594             commandWindow.visible = true;
1595             commandWindow.next = &disassembly;
1596             inputWindow.visible = false;
1597             inputWindow.next = &inputWindow;
1598             screen->focusedWindow = &disassembly;
1599             state = State.running;
1600         }
1601         public override void Run(Process* process)
1602         {
1603             this->process = process;
1604             machine = &cmsx.machine.GetMachine();
1605             inst = -1;
1606             cmsx.machine.Registers& regs = machine->GetRegisters();
1607             if (state == State.running)
1608             {
1609                 pc = regs.GetSpecial(cmsx.machine.Registers.rW);
1610                 if (SkipStepBreakpoint(this->pcregs.Get(cmsx.machine.regFP)*machine))
1611                 {
1612                     return;
1613                 }
1614                 inst = RemoveStepBreakpoints(processpc);
1615                 Breakpoint* bp = breakpoints.GetBreakpoint(pc);
1616                 if (bp != null)
1617                 {
1618                     if (inst == -1)
1619                     {
1620                         inst = bp->inst;
1621                     }
1622                 }
1623                 machine->GetProcessor().ClearBreak();
1624                 middle = pc;
1625                 screen->Update();
1626                 int ch = RtGetCh();
1627                 while (ch != keyEscape)
1628                 {
1629                     ulong prevMiddle = middle;
1630                     numInstsInWindow = cast<ulong>(disassembly.Height() - 2);
1631                     start = middle - 4u * (numInstsInWindow / 2u);
1632                     if (ch == keyResize)
1633                     {
1634                         screen->GetDimensions();
1635                         screen->Update();
1636                     }
1637                     else if (ch == keyF2)
1638                     {
1639                         commandWindow.visible = true;
1640                         screen->focusedWindow = &commandWindow;
1641                         screen->Update();
1642                     }
1643                     else if (ch == keyF3)
1644                     {
1645                         disassembly.visible = true;
1646                         memory.visible = false;
1647                         screen->focusedWindow = &disassembly;
1648                         screen->Update();
1649                     }
1650                     else if (ch == keyF4)
1651                     {
1652                         output.visible = true;
1653                         screen->focusedWindow = &output;
1654                         screen->Update();
1655                     }
1656                     else if (ch == keyF6)
1657                     {
1658                         disassembly.visible = false;
1659                         memory.visible = true;
1660                         screen->focusedWindow = &memory;
1661                         screen->Update();
1662                     }
1663                     else if (ch == keyF8)
1664                     {
1665                         Window* next = screen->focusedWindow->next;
1666                         while (!next->visible)
1667                         {
1668                             next = next->next;
1669                         }
1670                         screen->focusedWindow = next;
1671                         screen->Update();
1672                     }
1673                     else
1674                     {
1675                         CommandResult result = screen->focusedWindow->HandleKey(ch);
1676                         if (result == CommandResult.ret)
1677                         {
1678                             return;
1679                         }
1680                         else if (result == CommandResult.update)
1681                         {
1682                             screen->Update();
1683                         }
1684                     }
1685                     ch = RtGetCh();
1686                 }
1687             }
1688             else if (state == State.exit)
1689             {
1690                 int ch = RtGetCh();
1691                 while (ch != keyEscape)
1692                 {
1693                     ch = RtGetCh();
1694                 }
1695             }
1696         }
1697         public override void Done()
1698         {
1699             screen.Reset();
1700         }
1701         public override void Exit(Process* process)
1702         {
1703             state = State.exit;
1704         }
1705         public override void WriteOutput(byte* bufferlong count)
1706         {
1707             string s(cast<const char*>(cast<void*>(buffer))count);
1708             ustring u(ToUtf32(s));
1709             for (uchar c : u)
1710             {
1711                 output.AddChar(c0u);
1712             }
1713         }
1714         public override bool Eof() const
1715         {
1716             return eof;
1717         }
1718         public override void ResetEof()
1719         {
1720             eof = false;
1721         }
1722         public override string ReadInputLine()
1723         {
1724             if (eof)
1725             {
1726                 return string();
1727             }
1728             Window* prevFocusedWindow = screen->focusedWindow;
1729             commandWindow.visible = false;
1730             inputWindow.visible = true;
1731             screen->focusedWindow = &inputWindow;
1732             screen->Update();
1733             int ch = RtGetCh();
1734             string resultLine;
1735             while (true)
1736             {
1737                 if (ch == keyEscape)
1738                 {
1739                     resultLine.Clear();
1740                     eof = true;
1741                     break;
1742                 }
1743                 else if (ch == keyControlD)
1744                 {
1745                     eof = true;
1746                     break;
1747                 }
1748                 else
1749                 {
1750                     CommandResult result = screen->focusedWindow->HandleKey(ch);
1751                     if (result == CommandResult.ret)
1752                     {
1753                         resultLine = ToUtf8(inputWindow.resultLine) + "\n";
1754                         break;
1755                     }
1756                     else if (result == CommandResult.update)
1757                     {
1758                         screen->Update();
1759                     }
1760                 }
1761                 ch = RtGetCh();
1762             }
1763             commandWindow.visible = true;
1764             inputWindow.visible = false;
1765             screen->focusedWindow = prevFocusedWindow;
1766             return resultLine;
1767         }
1768         private bool SkipStepBreakpoint(ulong addressulong fpcmsx.machine.Machine& machine)
1769         {
1770             for (const Breakpoint& stepBp : stepBreakpoints)
1771             {
1772                 if (stepBp.address == address)
1773                 {
1774                     if (stepBp.fp != 0u)
1775                     {
1776                         if (stepBp.fp != fp)
1777                         {
1778                             machine.GetRegisters().SetSpecial(cmsx.machine.Registers.rXXstepBp.inst);
1779                             return true;
1780                         }
1781                     }
1782                 }
1783             }
1784             return false;
1785         }
1786         private long RemoveStepBreakpoints(Process* processulong address)
1787         {
1788             long inst = -1;
1789             for (const Breakpoint& stepBp : stepBreakpoints)
1790             {
1791                 if (address == stepBp.address)
1792                 {
1793                     inst = stepBp.inst;
1794                 }
1795                 WriteInst(processstepBp.addressstepBp.inst);
1796             }
1797             stepBreakpoints.Clear();
1798             return inst;
1799         }
1800         private uint GetInst(Process* processulong pclong inst)
1801         {
1802             if (inst != -1)
1803             {
1804                 return cast<uint>(inst);
1805             }
1806             else
1807             {
1808                 Breakpoint* bp = breakpoints.GetBreakpoint(pc);
1809                 if (bp != null)
1810                 {
1811                     return bp->inst;
1812                 }
1813             }
1814             return ReadInst(processpc);
1815         }
1816         public void AddOutputLine(const ustring& lineulong address)
1817         {
1818             output.AddLine(lineaddress);
1819             screen->Update();
1820         }
1821         public void ToggleBreakpoint(ulong address)
1822         {
1823             Breakpoint* bp = breakpoints.GetBreakpoint(address);
1824             if (bp != null)
1825             {
1826                 WriteInst(processaddressbp->inst);
1827                 breakpoints.RemoveBreakpoint(address);
1828                 screen->Update();
1829             }
1830             else
1831             {
1832                 uint inst = GetInst(processaddress-1);
1833                 Breakpoint bp(Breakpoint.Kind.hardaddressinst);
1834                 breakpoints.SetBreakpoint(bp);
1835                 WriteInst(processaddressdebugBreakInst);
1836                 screen->Update();
1837             }
1838         }
1839         public void Run()
1840         {
1841             uint i = GetInst(processpcinst);
1842             machine->GetRegisters().SetSpecial(cmsx.machine.Registers.rXXi);
1843         }
1844         public void StepInto()
1845         {
1846             uint i = GetInst(processpcinst);
1847             WriteInst(processpci);
1848             Breakpoint* bp = breakpoints.GetBreakpoint(pc);
1849             if (bp != null)
1850             {
1851                 machine->GetProcessor().SetBreak(bp->addressdebugBreakInst);
1852             }
1853             byte opCode = cast<byte>(i >> 24u);
1854             byte x = cast<byte>(i >> 16u);
1855             byte y = cast<byte>(i >> 8u);
1856             byte z = cast<byte>(i);
1857             cmsx.machine.Instruction* instruction = machine->GetInst(opCode);
1858             ulong prevRV = machine->GetRegisters().GetSpecial(cmsx.machine.Registers.rV);
1859             MemoryTable& memoryTable = process->memoryTable;
1860             machine->GetRegisters().SetSpecial(cmsx.machine.Registers.rVmemoryTable.virtualTranslationRegisterValue);
1861             List<ulong> targetAddresses = instruction->GetTargetAddresses(pcmachine->GetRegisters()machine->GetMemory()xyz);
1862             machine->GetRegisters().SetSpecial(cmsx.machine.Registers.rVprevRV);
1863             for (ulong address : targetAddresses)
1864             {
1865                 Breakpoint bp(Breakpoint.Kind.stepaddressGetInst(processaddress-1));
1866                 stepBreakpoints.Add(bp);
1867                 WriteInst(processaddressdebugBreakInst);
1868             }
1869             machine->GetRegisters().SetSpecial(cmsx.machine.Registers.rXXi);
1870             if (instruction->IsJumpInst() || i == 0u)
1871             {
1872                 machine->GetRegisters().SetPC(pc);
1873             }
1874         }
1875         public void StepOver()
1876         {
1877             uint i = GetInst(processpcinst);
1878             byte opCode = cast<byte>(i >> 24u);
1879             if (opCode == cmsx.machine.CALL || opCode == cmsx.machine.CALLI)
1880             {
1881                 Breakpoint bp(Breakpoint.Kind.steppc + 4uGetInst(processpc + 4u-1));
1882                 bp.fp = machine->GetRegisters().Get(cmsx.machine.regFP);
1883                 stepBreakpoints.Add(bp);
1884                 WriteInst(processpc + 4udebugBreakInst);
1885                 machine->GetRegisters().SetSpecial(cmsx.machine.Registers.rXXi);
1886                 machine->GetRegisters().SetPC(pc);
1887             }
1888             else
1889             {
1890                 StepInto();
1891             }
1892         }
1893         public void StepOut()
1894         {
1895             uint i = GetInst(processpcinst);
1896             ulong retAddress = 0u;
1897             if (InProlog(i))
1898             {
1899                 ulong sp = machine->GetRegisters().Get(cmsx.machine.regSP);
1900                 try
1901                 {
1902                     ReadProcessMemory(*machineprocesssp - 8uretAddress8ufalse);
1903                 }
1904                 catch (const Exception& ex)
1905                 {
1906                     cmsx.machine.Panic("debugger: could not read process memory: " + ex.ToString());
1907                 }
1908             }
1909             else if (InEpilog(i))
1910             {
1911                 StepInto();
1912             }
1913             else
1914             {
1915                 ulong fp = machine->GetRegisters().Get(cmsx.machine.regFP);
1916                 try
1917                 {
1918                     ReadProcessMemory(*machineprocessfp - 8uretAddress8ufalse);
1919                 }
1920                 catch (const Exception& ex)
1921                 {
1922                     cmsx.machine.Panic("debugger: could not read process memory: " + ex.ToString());
1923                 }
1924             }
1925             Breakpoint bp(Breakpoint.Kind.stepretAddressGetInst(processretAddress-1));
1926             stepBreakpoints.Add(bp);
1927             WriteInst(processretAddressdebugBreakInst);
1928         }
1929         public ulong GetSymbolValue(const string& id)
1930         {
1931             cmsx.object.Symbol* symbol = symbolTable->GetSymbol(id);
1932             if (symbol != null)
1933             {
1934                 if (symbol->value.GetFlag(cmsx.object.Value.Flag.register))
1935                 {
1936                     return GetRegisterValue(cast<byte>(symbol->value.value));
1937                 }
1938                 SegmentDescriptor* segmentDescriptor = null;
1939                 switch (symbol->segment)
1940                 {
1941                     case cmsx.object.Segment.text: segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.textSegmentIndex]; break;
1942                     case cmsx.object.Segment.data: segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.dataSegmentIndex]; break;
1943                     case cmsx.object.Segment.pool: segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.poolSegmentIndex]; break;
1944                     case cmsx.object.Segment.stack: segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.stackSegmentIndex]; break;
1945                 }
1946                 if (segmentDescriptor != null)
1947                 {
1948                     return segmentDescriptor->baseAddress + segmentDescriptor->startAddress + symbol->value.value;
1949                 }
1950                 return symbol->value.value;
1951             }
1952             else
1953             {
1954                 throw Exception("unknown symbol '" + id + "'");
1955             }
1956         }
1957         public void FindSymbolsMatchingPrefix(const ustring& lineList<ustring>& matches)
1958         {
1959             matches.Clear();
1960             ustring prefix;
1961             long start = 0u;
1962             for (start = line.Length() - 1; start >= 0; --start;)
1963             {
1964                 if (line[start] == ' ')
1965                 {
1966                     break;
1967                 }
1968             }
1969             start = start + 1;
1970             prefix = line.Substring(start);
1971             string prefixStr = ToUtf8(prefix);
1972             if (!prefixStr.IsEmpty())
1973             {
1974                 for (const UniquePtr<cmsx.object.Symbol>& symbol : symbolTable->Symbols())
1975                 {
1976                     if (symbol->name.StartsWith(prefixStr))
1977                     {
1978                         matches.Add(TrimAll(line.Substring(0start) + u" " + ToUtf32(symbol->name)));
1979                     }
1980                 }
1981             }
1982         }
1983         public ulong GetRegisterValue(byte regNumber)
1984         {
1985             return machine->GetRegisters().Get(regNumber);
1986         }
1987         public ustring ReadStringFromMemory(ulong address)
1988         {
1989             string s;
1990             byte x = cast<byte>(ReadMemoryContent(address1u));
1991             while (x != 0u)
1992             {
1993                 s.Append(cast<char>(x));
1994                 ++address;
1995                 x = cast<byte>(ReadMemoryContent(address1u));
1996             }
1997             return ToUtf32(s);
1998         }
1999         public ulong ReadMemoryContent(ulong addressbyte size)
2000         {
2001             SegmentDescriptor* segmentDescriptor = null;
2002             if (address >= cmsx.machine.textSegmentBaseAddress && address < cmsx.machine.dataSegmentBaseAddress)
2003             {
2004                 segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.textSegmentIndex];
2005             }
2006             else if (address >= cmsx.machine.dataSegmentBaseAddress && address < cmsx.machine.poolSegmentBaseAddress)
2007             {
2008                 segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.dataSegmentIndex];
2009             }
2010             else if (address >= cmsx.machine.poolSegmentBaseAddress && address < cmsx.machine.stackSegmentBaseAddress)
2011             {
2012                 segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.poolSegmentIndex];
2013             }
2014             else if (address >= cmsx.machine.stackSegmentBaseAddress && address < cmsx.machine.kernelBaseAddress)
2015             {
2016                 segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.stackSegmentIndex];
2017             }
2018             if (segmentDescriptor == null)
2019             {
2020                 throw Exception("invalid access to virtual address #" + ToHexString(address));
2021             }
2022             if (address >= segmentDescriptor->baseAddress + segmentDescriptor->startAddress && address <= segmentDescriptor->baseAddress + segmentDescriptor->startAddress + segmentDescriptor->length)
2023             {
2024                 ulong value = 0u;
2025                 try
2026                 {
2027                     cmsx.kernel.ReadProcessMemory(*machineprocessaddressvaluesizefalse);
2028                     return value;
2029                 }
2030                 catch (const Exception& ex)
2031                 {
2032                     throw Exception("could not read process memory from virtual address #" + ToHexString(address) + ": " + ex.Message());
2033                 }
2034             }
2035             else
2036             {
2037                 throw Exception("invalid access to virtual address #" + ToHexString(address));
2038             }
2039             return 0u;
2040         }
2041         public void ShowAddress(ulong address)
2042         {
2043             SegmentDescriptor* segmentDescriptor = null;
2044             byte segmentIndex = cmsx.machine.numSegments;
2045             if (address >= cmsx.machine.textSegmentBaseAddress && address < cmsx.machine.dataSegmentBaseAddress)
2046             {
2047                 segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.textSegmentIndex];
2048                 segmentIndex = cmsx.machine.textSegmentIndex;
2049             }
2050             else if (address >= cmsx.machine.dataSegmentBaseAddress && address < cmsx.machine.poolSegmentBaseAddress)
2051             {
2052                 segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.dataSegmentIndex];
2053                 segmentIndex = cmsx.machine.dataSegmentIndex;
2054             }
2055             else if (address >= cmsx.machine.poolSegmentBaseAddress && address < cmsx.machine.stackSegmentBaseAddress)
2056             {
2057                 segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.poolSegmentIndex];
2058                 segmentIndex = cmsx.machine.poolSegmentIndex;
2059             }
2060             else if (address >= cmsx.machine.stackSegmentBaseAddress && address < cmsx.machine.kernelBaseAddress)
2061             {
2062                 segmentDescriptor = process->memoryTable.segmentDescriptors[cmsx.machine.stackSegmentIndex];
2063                 segmentIndex = cmsx.machine.stackSegmentIndex;
2064             }
2065             if (address >= segmentDescriptor->baseAddress + segmentDescriptor->startAddress && address <= segmentDescriptor->baseAddress + segmentDescriptor->startAddress + segmentDescriptor->length)
2066             {
2067                 switch (segmentIndex)
2068                 {
2069                     case cmsx.machine.textSegmentIndex:
2070                     {
2071                         disassembly.visible = true;
2072                         memory.visible = false;
2073                         middle = address;
2074                         break;
2075                     }
2076                     case cmsx.machine.dataSegmentIndex: case cmsx.machine.poolSegmentIndex: case cmsx.machine.stackSegmentIndex:
2077                     {
2078                         memory.visible = true;
2079                         disassembly.visible = false;
2080                         memory.ShowAddress(segmentIndexaddress);
2081                         break;
2082                     }
2083                 }
2084             }
2085         }
2086         public void Trace(ulong count)
2087         {
2088             List<ulong> addresses;
2089             addresses.Add(pc);
2090             ulong sp = machine->GetRegisters().Get(cmsx.machine.regSP);
2091             ulong fp = machine->GetRegisters().Get(cmsx.machine.regFP);
2092             ulong address = pc;
2093             ulong prevFP = pc;
2094             ulong retAddress = 0u;
2095             ulong frame = 0u;
2096             while (frame < count && prevFP != 0u)
2097             {
2098                 uint inst = ReadInst(processaddress);
2099                 if (InProlog(inst))
2100                 {
2101                     try
2102                     {
2103                         ReadProcessMemory(*machineprocesssp - 8uretAddress8ufalse);
2104                     }
2105                     catch (const Exception& ex)
2106                     {
2107                         cmsx.machine.Panic("debugger: could not read process memory: " + ex.ToString());
2108                     }
2109                     ++frame;
2110                     address = retAddress;
2111                     if (address != 0u)
2112                     {
2113                         addresses.Add(address);
2114                     }
2115                 }
2116                 try
2117                 {
2118                     ReadProcessMemory(*machineprocessfp - 8uretAddress8ufalse);
2119                     ReadProcessMemory(*machineprocessfpprevFP8ufalse);
2120                 }
2121                 catch (const Exception& ex)
2122                 {
2123                     cmsx.machine.Panic("debugger: could not read process memory: " + ex.ToString());
2124                 }
2125                 ++frame;
2126                 address = retAddress;
2127                 if (address != 0u)
2128                 {
2129                     addresses.Add(address);
2130                 }
2131                 fp = prevFP;
2132             }
2133             List<cmsx.object.Symbol*> functionSymbols;
2134             for (const UniquePtr<cmsx.object.Symbol>& symbol : symbolTable->Symbols())
2135             {
2136                 if (symbol->value.GetFlag(cmsx.object.Value.Flag.function))
2137                 {
2138                     functionSymbols.Add(symbol.Get());
2139                 }
2140             }
2141             Sort(functionSymbolsByStart());
2142             for (long i = addresses.Count() - 1; i >= 0; --i;)
2143             {
2144                 ulong address = addresses[i];
2145                 cmsx.object.Symbol s;
2146                 s.start = address;
2147                 List<cmsx.object.Symbol*>.ConstIterator it = LowerBound(functionSymbols.CBegin()functionSymbols.CEnd()&sByStart());
2148                 string functionName;
2149                 if (it == functionSymbols.CEnd())
2150                 {
2151                     --it;
2152                 }
2153                 cmsx.object.Symbol* found = *it;
2154                 if (found->start > address && it != functionSymbols.CBegin())
2155                 {
2156                     --it;
2157                     found = *it;
2158                 }
2159                 if (address >= found->start && address < found->start + found->length)
2160                 {
2161                     functionName = found->name;
2162                 }
2163                 output.AddLine(ToUtf32(Format(ToString(i)3FormatJustify.right)) + u": #" + ToUtf32(ToHexString(address)) + u" : " + ToUtf32(functionName)address);
2164             }
2165         }
2166         public cmsx.machine.Machine* machine;
2167         public cmsx.kernel.Process* process;
2168         public long inst;
2169         public ulong pc;
2170         public ulong middle;
2171         public ulong start;
2172         public ulong numInstsInWindow;
2173         private State state;
2174         private UniquePtr<Screen> screen;
2175         private cmsx.object.SymbolTable* symbolTable;
2176         private Breakpoints breakpoints;
2177         private List<Breakpoint> stepBreakpoints;
2178         private Disassembly disassembly;
2179         private Memory memory;
2180         private Output output;
2181         private CommandWindow commandWindow;
2182         private InputWindow inputWindow;
2183         private ulong programEntryPoint;
2184         private bool eof;
2185     }
2186 }