ide, debugger; fixed breakpoints issues when using run to cursor together with breakp...
[sdk] / ide / src / debugger / Debugger.ec
index 7191268..0e9e984 100644 (file)
@@ -10,6 +10,7 @@ import "debugTools"
 extern char * strrchr(const char * s, int c);
 
 #define uint _uint
+#define strlen _strlen
 #include <stdarg.h>
 #include <unistd.h>
 
@@ -22,7 +23,7 @@ extern char * strrchr(const char * s, int c);
 #include <sys/time.h> // Required on Apple...
 #endif
 #undef uint
-
+#undef strlen
 
 public char * StripQuotes2(char * string, char * output)
 {
@@ -305,7 +306,7 @@ char progFifoDir[MAX_LOCATION];
 enum DebuggerState { none, prompt, loaded, running, stopped, terminated };
 enum DebuggerEvent { none, hit, breakEvent, signal, stepEnd, functionEnd, exit };
 enum DebuggerAction { none, internal, restart, stop, selectFrame }; //, bpValidation
-enum BreakpointType { none, internalMain, internalWinMain, internalModulesLoaded, user, runToCursor };
+enum BreakpointType { none, internalMain, internalWinMain, internalModulesLoaded, user, runToCursor, internalModuleLoad };
 enum DebuggerEvaluationError { none, symbolNotFound, memoryCantBeRead, unknown };
 
 FileDialog debuggerFileDialog { type = selectDir };
@@ -363,6 +364,7 @@ class Debugger
 
    CompilerConfig currentCompiler;
    ProjectConfig prjConfig;
+   int bitDepth;
 
    CodeEditor codeEditor;
 
@@ -395,7 +397,7 @@ class Debugger
          {
             case restart:
                breakType = none;
-               Restart(currentCompiler, prjConfig);
+               Restart(currentCompiler, prjConfig, bitDepth);
                break;
             case stop:
                breakType = none;
@@ -456,7 +458,8 @@ class Debugger
                   bpHit = bp;
                   
                   if(!(!userBreakOnInternBreak && 
-                        bp && (bp.type == internalMain || bp.type == internalWinMain || bp.type == internalModulesLoaded)))
+                        bp && (bp.type == internalMain || bp.type == internalWinMain ||
+                        bp.type == internalModulesLoaded || bp.type == internalModuleLoad)))
                      monitor = true;
                   hitThread = stopItem.threadid;
                }
@@ -607,7 +610,7 @@ class Debugger
       sysBPs.Add(Breakpoint { type = internalWinMain, enabled = true, level = -1 });
 #endif
       sysBPs.Add(Breakpoint { type = internalModulesLoaded, enabled = true, level = -1 });
-      
+      sysBPs.Add(Breakpoint { type = internalModuleLoad, enabled = true, level = -1 });
    }
 
    ~Debugger()
@@ -655,7 +658,7 @@ class Debugger
       }
    }
 
-   void Restart(CompilerConfig compiler, ProjectConfig config)
+   void Restart(CompilerConfig compiler, ProjectConfig config, int bitDepth)
    {
       switch(state)
       {
@@ -670,7 +673,7 @@ class Debugger
             GdbAbortExec();
          case none:
          case terminated:
-            if(!GdbInit(compiler, config))
+            if(!GdbInit(compiler, config, bitDepth))
                break;
          case loaded:
             GdbExecRun();
@@ -684,7 +687,7 @@ class Debugger
       codloc = CodeLocation::ParseCodeLocation(location);
       if(codloc)
       {
-         CodeEditor editor = (CodeEditor)ide.OpenFile(codloc.absoluteFile, normal, true, null, no, normal);
+         CodeEditor editor = (CodeEditor)ide.OpenFile(codloc.absoluteFile, normal, true, null, no, normal, false);
          if(editor)
          {
             EditBox editBox = editor.editBox;
@@ -729,7 +732,7 @@ class Debugger
                }
             }
             if(frame.absoluteFile)
-               editor = (CodeEditor)ide.OpenFile(frame.absoluteFile, normal, true, null, no, normal);
+               editor = (CodeEditor)ide.OpenFile(frame.absoluteFile, normal, true, null, no, normal, false);
             ide.Update(null);
             if(editor && frame.line)
             {
@@ -845,14 +848,14 @@ class Debugger
       ide.Update(null);
    }
       
-   void Start(CompilerConfig compiler, ProjectConfig config)
+   void Start(CompilerConfig compiler, ProjectConfig config, int bitDepth)
    {
       ide.outputView.debugBox.Clear();
       switch(state)
       {
          case none:
          case terminated:
-            if(!GdbInit(compiler, config))
+            if(!GdbInit(compiler, config, bitDepth))
                break;
          case loaded:
             GdbExecRun();
@@ -860,13 +863,13 @@ class Debugger
       }
    }
 
-   void StepInto(CompilerConfig compiler, ProjectConfig config)
+   void StepInto(CompilerConfig compiler, ProjectConfig config, int bitDepth)
    {
       switch(state)
       {
          case none:
          case terminated:
-            if(!GdbInit(compiler, config)) 
+            if(!GdbInit(compiler, config, bitDepth)) 
                break;
          case loaded:
             ide.outputView.ShowClearSelectTab(debug);
@@ -880,13 +883,13 @@ class Debugger
       }
    }
 
-   void StepOver(CompilerConfig compiler, ProjectConfig config, bool ignoreBkpts)
+   void StepOver(CompilerConfig compiler, ProjectConfig config, int bitDepth, bool ignoreBkpts)
    {
       switch(state)
       {
          case none:
          case terminated:
-            if(!GdbInit(compiler, config)) 
+            if(!GdbInit(compiler, config, bitDepth)) 
                break;
          case loaded:
             ide.outputView.ShowClearSelectTab(debug);
@@ -915,7 +918,7 @@ class Debugger
       }
    }
 
-   void RunToCursor(CompilerConfig compiler, ProjectConfig config, char * absoluteFilePath, int lineNumber, bool ignoreBkpts)
+   void RunToCursor(CompilerConfig compiler, ProjectConfig config, int bitDepth, char * absoluteFilePath, int lineNumber, bool ignoreBkpts, bool atSameLevel)
    {
       char relativeFilePath[MAX_LOCATION];
       DebuggerState oldState = state;
@@ -926,7 +929,7 @@ class Debugger
       {
          case none:
          case terminated:
-            Start(compiler, config);
+            Start(compiler, config, bitDepth);
          case stopped:
          case loaded:
             if(symbols)
@@ -936,7 +939,7 @@ class Debugger
                   ide.outputView.ShowClearSelectTab(debug);
                   ide.outputView.debugBox.Logf($"Starting debug mode\n");
                }
-               RunToCursorPrepare(absoluteFilePath, relativeFilePath, lineNumber);
+               RunToCursorPrepare(absoluteFilePath, relativeFilePath, lineNumber, atSameLevel);
                sentBreakInsert = true;
                GdbCommand(false, "-break-insert %s:%d", relativeFilePath, lineNumber);
                bpRunToCursor.bp = bpItem;
@@ -973,7 +976,7 @@ class Debugger
       else
       {
          *error = signalOn && activeThread == signalThread;
-         *lineCursor = activeFrameLevel + 1;
+         *lineCursor = activeFrameLevel - ((frameCount > 192 && activeFrameLevel > 191) ? frameCount - 192 - 1 : 0) + 1;
          *lineTopFrame = activeFrameLevel ? 1 : 0;
       }
    }
@@ -1041,7 +1044,7 @@ class Debugger
       else if(expression)
       {
          wh = Watch { };
-         row.tag = (int)wh;
+         row.tag = (int64)wh;
          ide.workspace.watches.Add(wh);
          wh.row = row;
          wh.expression = CopyString(expression);
@@ -1416,7 +1419,7 @@ class Debugger
       if(gdbHandle)
       {
          // TODO: Improve this limit
-         static char string[MAX_F_STRING*3];
+         static char string[MAX_F_STRING*4];
          va_list args;
          va_start(args, format);
          vsnprintf(string, sizeof(string), format, args);
@@ -1478,13 +1481,13 @@ class Debugger
       return true;
    }
 
-   static void GdbInsertInternalBreakpoint()
+   static void GdbInsertInternalBreakpoints()
    {
       if(symbols)
       {
          //if(!breakpointsInserted)
          {
-            DirExpression objDir = ide.project.GetObjDir(currentCompiler, prjConfig);
+            DirExpression objDir = ide.project.GetObjDir(currentCompiler, prjConfig, bitDepth);
             for(bp : sysBPs)
             {
                if(!bp.inserted)
@@ -1551,11 +1554,40 @@ class Debugger
                            bp.bp = bpItem;
                            bpItem = null;
                            bp.inserted = (bp.bp && bp.bp.number != 0);
-                           ValidateBreakpoint(bp);
                         }
                         delete f;
                      }
-                     break;
+                  }
+                  else if(bp.type == internalModuleLoad && modules)
+                  {
+                     Project ecerePrj = null;
+                     for(p : ide.workspace.projects)
+                     {
+                        if(!strcmp(p.topNode.name, "ecere.epj"))
+                        {
+                           ecerePrj = p;
+                           break;
+                        }
+                     }
+                     if(ecerePrj)
+                     {
+                        ProjectNode node = ecerePrj.topNode.Find("instance.c", false);
+                        if(node)
+                        {
+                           char path[MAX_LOCATION];
+                           char relative[MAX_LOCATION];
+                           node.GetFullFilePath(path);
+                           bp.absoluteFilePath = CopyString(path);
+                           MakePathRelative(path, ecerePrj.topNode.path, relative);
+                           delete bp.relativeFilePath;
+                           bp.relativeFilePath = CopyString(relative);
+                           sentBreakInsert = true;
+                           GdbCommand(false, "-break-insert %s:InternalModuleLoadBreakpoint", bp.relativeFilePath);
+                           bp.bp = bpItem;
+                           bpItem = null;
+                           bp.inserted = (bp.bp && bp.bp.number != 0);
+                        }
+                     }
                   }
                }
             }
@@ -1625,6 +1657,15 @@ class Debugger
       //breakpointsInserted = false;
       if(symbols)
       {
+         for(bp : sysBPs)
+         {
+            if(bp.bp)
+               GdbCommand(false, "-break-delete %d", bp.bp.number);
+            bp.inserted = false;
+            bp.bp = bpItem;
+            //check here (reply form -break-delete, returns bpitem?)
+            bpItem = null;
+         }
          for(bp : ide.workspace.breakpoints)
          {
             if(bp.bp)
@@ -1688,7 +1729,7 @@ class Debugger
             GdbCommand(false, "-environment-directory \"%s\"", dir);
             //GdbCommand(false, ""); // why this empty GDB command
          }
-         GdbInsertInternalBreakpoint();
+         GdbInsertInternalBreakpoints();
          targeted = true;
       }
       return true;
@@ -1762,6 +1803,7 @@ class Debugger
    void GdbExecCommon()
    {
       ClearBreakDisplay();
+      GdbInsertInternalBreakpoints();
       GdbBreakpointsInsert();
    }
 
@@ -1812,14 +1854,14 @@ class Debugger
       return true;
    }
 
-   bool GdbInit(CompilerConfig compiler, ProjectConfig config)
+   bool GdbInit(CompilerConfig compiler, ProjectConfig config, int bitDepth)
    {
       bool result = true;
       char oldDirectory[MAX_LOCATION];
       char tempPath[MAX_LOCATION];
       char command[MAX_LOCATION];
       Project project = ide.project;
-      DirExpression targetDirExp = project.GetTargetDir(compiler, config);
+      DirExpression targetDirExp = project.GetTargetDir(compiler, config, bitDepth);
       PathBackup pathBackup { };
 
       if(currentCompiler != compiler)
@@ -1829,6 +1871,7 @@ class Debugger
          incref currentCompiler;
       }
       prjConfig = config;
+      this.bitDepth = bitDepth;
 
       ChangeState(loaded);
       sentKill = false;
@@ -1868,7 +1911,7 @@ class Debugger
       else
          ChangeWorkingDir(ide.workspace.projectDir);
       
-      ide.SetPath(true, compiler, config);
+      ide.SetPath(true, compiler, config, bitDepth);
 
       // TODO: This pollutes the environment, but at least it works
       // It shouldn't really affect the IDE as the PATH gets restored and other variables set for testing will unlikely cause problems
@@ -1879,7 +1922,11 @@ class Debugger
          SetEnvironment(e.name, e.string);
       }
 
-      strcpy(command, "gdb -n -silent --interpreter=mi2"); //-async //\"%s\"
+      strcpy(command,
+         (compiler.targetPlatform == win32 && bitDepth == 64) ? "x86_64-w64-mingw32-gdb" :
+         (compiler.targetPlatform == win32 && bitDepth == 32) ? "i686-w64-mingw32-gdb" :
+         "gdb");
+      strcat(command, " -n -silent --interpreter=mi2"); //-async //\"%s\"
       gdbTimer.Start();
       gdbHandle = DualPipeOpen(PipeOpenMode { output = 1, error = 2, input = 1 }, command);
       if(!gdbHandle)
@@ -2035,14 +2082,14 @@ class Debugger
       
       strcpy(path, ide.workspace.projectDir);
       PathCat(path, tempPath);
-      codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no);
+      codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no, normal, false);
       if(!codeEditor)
       {
          for(srcDir : ide.workspace.sourceDirs)
          {
             strcpy(path, srcDir);
             PathCat(path, tempPath);
-            codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no);
+            codeEditor = (CodeEditor)ide.OpenFile(path, Normal, false, null, no, normal, false);
             if(codeEditor) break;
          }
       }
@@ -2053,7 +2100,7 @@ class Debugger
       if(!activeFrame || !activeFrame.absoluteFile)
          codeEditor = null;
       else
-         codeEditor = (CodeEditor)ide.OpenFile(activeFrame.absoluteFile, normal, false, null, no, normal);
+         codeEditor = (CodeEditor)ide.OpenFile(activeFrame.absoluteFile, normal, false, null, no, normal, false);
       if(codeEditor)
       {
          codeEditor.inUseDebug = true;
@@ -2283,7 +2330,7 @@ class Debugger
                            {
                               char string[256] = "";
                               Symbol classSym;
-                              PrintType(type, string, false, true);
+                              PrintTypeNoConst(type, string, false, true);
                               classSym = FindClass(string);
                               _class = classSym ? classSym.registered : null;
                            }
@@ -2327,7 +2374,7 @@ class Debugger
 
                         if(exp.expType.kind != arrayType || exp.hasAddress)
                         {
-                           uint address;
+                           uint64 address;
                            char * string;
                            char value[4196];
                            int len;
@@ -2340,9 +2387,15 @@ class Debugger
                               sprintf(temp, "(char*)%s", exp.constant);*/
 
                            //evaluation = Debugger::EvaluateExpression(temp, &evalError);
-                           address = strtoul(exp.constant, null, 0);
+                           // address = strtoul(exp.constant, null, 0);
+                           address = _strtoui64(exp.constant, null, 0);
                            //printf("%x\n", address);
-                           snprintf(value, sizeof(value), "0x%08x ", address);
+                           // snprintf(value, sizeof(value), "0x%08x ", address);
+
+                           if(address > 0xFFFFFFFFLL)
+                              snprintf(value, sizeof(value), (GetRuntimePlatform() == win32) ? "0x%016I64x " : "0x%016llx ", address);
+                           else
+                              snprintf(value, sizeof(value), (GetRuntimePlatform() == win32) ? "0x%08I64x " : "0x%08llx ", address);
                            value[sizeof(value)-1] = 0;
                            
                            if(!address)
@@ -2446,7 +2499,7 @@ class Debugger
                            }
                            else
                            {
-                              value = strtoul(exp.constant, null, 0);
+                              value = (uint)strtoul(exp.constant, null, 0);
                               signedValue = (int)value;
                            }
                         }
@@ -2485,7 +2538,7 @@ class Debugger
                   default:
                      if(exp.hasAddress)
                      {
-                        wh.value = PrintHexUInt(exp.address);
+                        wh.value = PrintHexUInt64(exp.address);
                         result = (bool)exp.address;
                      }
                      else
@@ -2539,7 +2592,7 @@ class Debugger
    }
 
    // to be removed... use GdbReadMemory that returns a byte array instead
-   char * ::GdbReadMemoryString(uint address, int size, char format, int rows, int cols)
+   char * ::GdbReadMemoryString(uint64 address, int size, char format, int rows, int cols)
    {
       eval.active = true;
       eval.error = none;
@@ -2547,17 +2600,25 @@ class Debugger
       if(!size)
          printf("GdbReadMemoryString called with size = 0!\n");
 #endif
-      GdbCommand(false, "-data-read-memory 0x%08x %c, %d, %d, %d", address, format, size, rows, cols);
+      // GdbCommand(false, "-data-read-memory 0x%08x %c, %d, %d, %d", address, format, size, rows, cols);
+      if(GetRuntimePlatform() == win32)
+         GdbCommand(false, "-data-read-memory 0x%016I64x %c, %d, %d, %d", address, format, size, rows, cols);
+      else
+         GdbCommand(false, "-data-read-memory 0x%016llx %c, %d, %d, %d", address, format, size, rows, cols);
       if(eval.active)
          ide.outputView.debugBox.Logf("Debugger Error: GdbReadMemoryString\n");
       return eval.result;
    }
 
-   byte * ::GdbReadMemory(uint address, int bytes)
+   byte * ::GdbReadMemory(uint64 address, int bytes)
    {
       eval.active = true;
       eval.error = none;
-      GdbCommand(false, "-data-read-memory 0x%08x %c, 1, 1, %d", address, 'u', bytes);
+      //GdbCommand(false, "-data-read-memory 0x%08x %c, 1, 1, %d", address, 'u', bytes);
+      if(GetRuntimePlatform() == win32)
+         GdbCommand(false, "-data-read-memory 0x%016I64x %c, 1, 1, %d", address, 'u', bytes);
+      else
+         GdbCommand(false, "-data-read-memory 0x%016llx %c, 1, 1, %d", address, 'u', bytes);
 #ifdef _DEBUG
       if(!bytes)
          printf("GdbReadMemory called with bytes = 0!\n");
@@ -2593,11 +2654,7 @@ class Debugger
       Breakpoint bp = bpHit;
 
       if(!bp && bpRunToCursor)
-      {
          bp = bpRunToCursor;
-         if(symbols)
-            GdbCommand(false, "-break-delete %d", bp.bp.number);
-      }
       
       if(bp)
       {
@@ -2627,6 +2684,11 @@ class Debugger
                break;
             case internalModulesLoaded:
                modules = true;
+               GdbInsertInternalBreakpoints();
+               GdbBreakpointsInsert();
+               GdbExecContinue(false);
+               break;
+            case internalModuleLoad:
                GdbBreakpointsInsert();
                GdbExecContinue(false);
                break;
@@ -2646,11 +2708,6 @@ class Debugger
                      GoToStackFrameLine(activeFrameLevel, true);
                      ideMainFrame.Activate();   // TOFIX: ide.Activate() is not reliable (app inactive)
                      ide.Update(null);
-                     if(bp.type == BreakpointType::runToCursor)
-                     {
-                        delete bpRunToCursor;
-                        bpRunToCursor = null;
-                     }
                   }
                   else
                   {
@@ -2666,6 +2723,13 @@ class Debugger
       }
       else
          ide.outputView.debugBox.Logf("Debugger Error: Breakpoint hit could not match breakpoint instance\n");
+
+      if(bpRunToCursor)
+      {
+         if(symbols && bpRunToCursor.inserted)
+            GdbCommand(false, "-break-delete %d", bpRunToCursor.bp.number);
+         delete bpRunToCursor;
+      }
    }
 
    void GdbThreadExit()
@@ -2976,7 +3040,7 @@ class Debugger
                            else if(!strcmp(item.name, "next-row"))
                            {
                               StripQuotes(item.value, item.value);
-                              eval.nextBlockAddress = strtoul(item.value, null, 0);
+                              eval.nextBlockAddress = _strtoui64(item.value, null, 0);
                            }
                            else if(!strcmp(item.name, "memory"))
                            {
@@ -3417,7 +3481,7 @@ class Debugger
       delete item2;
    }
 
-   void RunToCursorPrepare(char * absoluteFilePath, char * relativeFilePath, int lineNumber)
+   void RunToCursorPrepare(char * absoluteFilePath, char * relativeFilePath, int lineNumber, bool atSameLevel)
    {
       if(bpRunToCursor)
       {
@@ -3436,7 +3500,7 @@ class Debugger
       bpRunToCursor.enabled = true;
       bpRunToCursor.condition = null;
       bpRunToCursor.ignore = 0;
-      bpRunToCursor.level = -1;
+      bpRunToCursor.level = atSameLevel ? frameCount - activeFrameLevel -1 : -1;
    }
 
    ExpressionType ::DebugEvalExpTypeError(char * result)
@@ -3469,7 +3533,7 @@ class Debugger
       return result;
    }
 
-   char * ::ReadMemory(uint address, int size, char format, ExpressionType * error)
+   char * ::ReadMemory(uint64 address, int size, char format, ExpressionType * error)
    {
       // check for state
       char * result = GdbReadMemoryString(address, size, format, 1, 1);
@@ -3614,7 +3678,7 @@ class ProgramThread : Thread
          selectResult = select(fd + 1, &rs, null, null, &time);
          if(FD_ISSET(fd, &rs))
          {
-            int result = read(fd, output, sizeof(output)-1);
+            int result = (int)read(fd, output, sizeof(output)-1);
             if(!result || (result < 0 && errno != EAGAIN))
                break;
             if(result > 0)
@@ -3879,7 +3943,7 @@ struct DebugEvaluationData
    bool active;
    char * result;
    int bytes;
-   uint nextBlockAddress;
+   uint64 nextBlockAddress;
 
    DebuggerEvaluationError error;
 };