dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] pnet ChangeLog engine/debugger.c engine/debugge...


From: Radek Polak
Subject: [dotgnu-pnet-commits] pnet ChangeLog engine/debugger.c engine/debugge...
Date: Fri, 09 Mar 2007 17:43:11 +0000

CVSROOT:        /sources/dotgnu-pnet
Module name:    pnet
Changes by:     Radek Polak <radekp>    07/03/09 17:43:11

Modified files:
        .              : ChangeLog 
        engine         : debugger.c debugger.h engine.h ilrun.c jitc.c 
                         process.c thread.c 
        include        : il_debugger.h 

Log message:
        new debugger stuff

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/pnet/ChangeLog?cvsroot=dotgnu-pnet&r1=1.3432&r2=1.3433
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/debugger.c?cvsroot=dotgnu-pnet&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/debugger.h?cvsroot=dotgnu-pnet&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/engine.h?cvsroot=dotgnu-pnet&r1=1.118&r2=1.119
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/ilrun.c?cvsroot=dotgnu-pnet&r1=1.57&r2=1.58
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc.c?cvsroot=dotgnu-pnet&r1=1.68&r2=1.69
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/process.c?cvsroot=dotgnu-pnet&r1=1.70&r2=1.71
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/thread.c?cvsroot=dotgnu-pnet&r1=1.44&r2=1.45
http://cvs.savannah.gnu.org/viewcvs/pnet/include/il_debugger.h?cvsroot=dotgnu-pnet&r1=1.3&r2=1.4

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/ChangeLog,v
retrieving revision 1.3432
retrieving revision 1.3433
diff -u -b -r1.3432 -r1.3433
--- ChangeLog   7 Mar 2007 20:19:38 -0000       1.3432
+++ ChangeLog   9 Mar 2007 17:43:11 -0000       1.3433
@@ -1,3 +1,36 @@
+2007-03-09  Radek Polak  <address@hidden>
+
+       * engine/debugger.c: Fix problem when response from debugger was not
+       correctly terminated with 0. Functions for dumping common errors. Use 
wait
+       handles instead of suspending/resuming stopped threads. Execute 
commands in
+       current exec thread instead of command loop - this enables us to 
correctly
+       call managed methods from debugger. Implemented new commands add_watch,
+       remove_watch, remove_all_watches, is_stopped_in_watched_assembly,
+       show_watches for watching locals, static class members and their 
members.
+       Implemented quit command, that aborts debugged process. Rename
+       commandThread to ioThread which is more appropriate. Added public 
function
+       ILDebuggerRequestTerminate() for the debugged process to notify debugger
+       user that process is terminating and to stop IO thread. Debugger now
+       counts with having DebuggerHelper class in corlib.
+
+       * engine/debugger.h: Added function ILDebuggerIsThreadUnbreakable() 
which
+       is used by the coder to determine if debug hook should be processed. If
+       true is returned, then coder must avoid calling debug hook. Added event
+       handle used to wakup stopped thread to execute command. Added even
+       handle in debugger used for waiting until command is finnished.
+
+       * engine/engine.h, engine/thread.c: Rename ILWatch to ILLocalWatch.
+
+       * engine/ilrun.c: Notify debugger, that the process is terminating.
+
+       * engine/jitc.c: Prevent calling debug hook for unbreakable thread. 
Rename
+       ILWatch to ILLocalWatch.
+
+       * engine/process.c: Destroy attached debugger.
+
+       * include/il_debugger.h: Rename ILWatch to ILLocalWatch, prototype for
+       ILDebuggerRequestTerminate().
+
 2007-03-07  Klaus Treichel  <address@hidden>
 
        * engine/Makefile.am: Add jitc_gen.h to the jit coder includes so that 
the

Index: engine/debugger.c
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/debugger.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- engine/debugger.c   11 Feb 2007 14:48:54 -0000      1.13
+++ engine/debugger.c   9 Mar 2007 17:43:11 -0000       1.14
@@ -78,13 +78,18 @@
 
 /*
  * Return contents of stream from start to current position
- * as text allocated with ILMalloc(). Return 0 on error.
+ * as text allocated with ILMalloc() terminated with 0.
+ * Returns 0 on error.
  */
 static char *ReadStream(FILE *stream)
 {
        int len;
        char *result;
 
+       /* Terminate the stream with 0 */
+       putc(0, stream);
+
+       /* Allocate the string and read the stream into it */
        len = (int) ftell(stream);
        result = (char *) ILMalloc(len);
        if(result == 0)
@@ -373,6 +378,22 @@
 }
 
 /*
+ * Dump "out of memory" error.
+ */
+static void DumpOutOfMemoryError(FILE *stream)
+{
+       DumpError("out of memory", stream);
+}
+
+/*
+ * Dump "parameter missing" error.
+ */
+static void DumpParamMissingError(FILE *stream)
+{
+       DumpError("parameter missing", stream);
+}
+
+/*
  * Dump message to outgoing buffer.
  */
 static void DumpMessage(const char *message, FILE *stream)
@@ -575,7 +596,15 @@
                ILDbOutOfMemory();
        }
        memset(result, 0, sizeof(ILDebuggerThreadInfo));
-       result->runType = IL_DEBUGGER_RUN_TYPE_STOPPED;
+
+       /* Initialize handle for recieving events from IO thread */
+       result->event = ILWaitEventCreate(0, 0);
+       if(result->event == 0)
+       {
+               ILDbOutOfMemory();
+       }
+
+       result->runType = IL_DEBUGGER_RUN_TYPE_CONTINUE;
        return result;
 }
 
@@ -595,6 +624,10 @@
                        jit_stack_trace_free(info->jitStackTrace);
                }
 #endif
+               if(info->event)
+               {
+                       ILWaitHandleClose(info->event);
+               }
                ILFree(info);
                info = next;
        }
@@ -867,7 +900,7 @@
        /* Validate and parse arguments */
        if(debugger->argCount < 2)
        {
-               DumpError("Parameter missing", stream);
+               DumpParamMissingError(stream);
                return;
        }
        reqLine = atoi(debugger->args[1]);
@@ -964,39 +997,99 @@
 }
 
 /*
- * show_locals command.
+ * Call DebuggerHelper.ExpressionToString() method for given expression.
+ * Returns result as GC allocated string.
  */
-void ShowLocals(ILDebugger *debugger, FILE *stream)
+char *DebuggerHelper_ExpressionToString(ILExecThread *thread, const char 
*expression)
 {
-#ifdef IL_USE_CVM
-       CVMWord *p;
-       ILExecThread *thread = debugger->dbthread->execThread;
-       fputs("<LocalVariables>\n",stream);
-       for(p = thread->frame; p < thread->stackTop; p++)
+       ILString *str;
+       char *result;
+
+       str = ILStringCreateUTF8(thread, expression);
+       if(!str)
        {
-               fprintf(stream, "  <LocalVariable Value=\"%d\" />\n", 
p->intValue);
+               return 0;
        }
-       fputs("</LocalVariables>",stream);
-#endif
 
+       ILExecThreadCallNamed(thread, "System.Private.DebuggerHelper",
+                                       "ExpressionToString", 
"(oSystem.String;)oSystem.String;",
+                                       &str, str);
+
+       result = ILStringToUTF8(thread, str);
+       return result;
+}
+
+/*
+ * Call DebuggerHelper.ClearLocals() method.
+ */
+void DebuggerHelper_ClearLocals(ILExecThread *thread)
+{
+       ILExecThreadCallNamed(thread, "System.Private.DebuggerHelper",
+                                       "ClearLocals", "()V", (void *)0);
+}
+
+/*
+ * Call DebuggerHelper.AddLocal() method.
+ */
+void DebuggerHelper_AddLocal(ILExecThread *thread, const char *name,
+                                                        ILType *type, void 
*ptr)
+{
+       ILString *str;
+       ILObject *obj;
+       ILObject *clrType;
+
+       str = ILStringCreateUTF8(thread, name);
+
+       if(ILType_IsPrimitive(type) || ILType_IsValueType(type)) 
+       {
+               obj = ILExecThreadBox(thread, type, ptr);
+       }
+       else
+       {
+               obj = *(ILObject **)(ptr);
+       }
+
+       clrType = _ILGetClrTypeForILType(thread, type);
+
+       ILExecThreadCallNamed(thread, "System.Private.DebuggerHelper",
+                                       "AddLocal", 
"(oSystem.String;oSystem.Type;oSystem.Object;)V",
+                                       (void *)0, str, clrType, obj);
+
+}
+
+/*
+ * Call DebuggerHelper.ShowLocals() method.
+ * Returns result as GC allocated string.
+ */
+char *DebuggerHelper_ShowLocals(ILExecThread *thread)
+{
+       char *result;
+       ILString *str;
+
+       ILExecThreadCallNamed(thread, "System.Private.DebuggerHelper",
+                                       "ShowLocals", "()oSystem.String;",
+                                       &str);
+
+       result = ILStringToUTF8(thread, str);
+       return result;
+}
+
+/*
+ * Update locals in DebuggerHelper class.
+ */
+static void UpdateLocals(FILE *stream, ILExecThread *thread, ILMethod *method)
+{
 #ifdef IL_USE_JIT
-       ILExecThread *thread;
-       ILMethod *method;
        ILMethodCode code;
        ILType *signature;
        ILUInt32 num;
        ILUInt32 current;
        ILUInt32 i;
-       ILWatch *watch;
+       ILLocalWatch *local;
        ILType *type;
-       char *str;
-       char ch[8];
-       int len;
-       int j;
 
-       /* Current thread and method */
-       thread = debugger->dbthread->execThread;
-       method = debugger->dbthread->method;
+       /* Clear locals in helper class */
+       DebuggerHelper_ClearLocals(thread);
 
        /* Get local variables info */
        if(!ILMethodGetCode(method, &code))
@@ -1015,125 +1108,210 @@
                num = 0;
        }
 
-       fputs("<LocalVariables>\n", stream);
-
-       /* Dump local variables in current frame */
+       /* Add local variables in current frame */
        current = 0;
        for(i = 0; i < thread->numWatches && num > 0; i++)
        {
-               watch = &(thread->watchStack[i]);
-               if(watch->frame != thread->frame)
+               local = &(thread->watchStack[i]);
+
+               /* Skip variables that are not in current frame */
+               if(local->frame != thread->frame)
                {
-                       continue;       /* Skip if variable is not in current 
frame */
+                       continue;
                }
+               type = ILTypeGetLocal(signature, current);
 
-               /* TODO: dump local variable name */
-               fprintf(stream, "<LocalVariable Name=\"var%d\" Value=\"", i);
+               /* TODO: local variable name */
+               DebuggerHelper_AddLocal(thread, 0, type, local->addr);
 
-               type = ILTypeGetLocal(signature, current);
+               current++;
+               num--;
+       }
+#endif
+}
 
-               switch((unsigned long)type)
+/*
+ * show_locals command.
+ */
+void ShowLocals(ILDebugger *debugger, FILE *stream)
+{
+#ifdef IL_USE_CVM
+       CVMWord *p;
+       ILExecThread *thread = debugger->dbthread->execThread;
+       fputs("<LocalVariables>\n", stream);
+       for(p = thread->frame; p < thread->stackTop; p++)
                {
-                       case (unsigned long)ILType_Boolean:
+               fprintf(stream, "  <LocalVariable Value=\"%d\" />\n", 
p->intValue);
+       }
+       fputs("</LocalVariables>",stream);
+#endif
+
+#ifdef IL_USE_JIT
+       char *str;
+
+       /* Update locals in DebuggerHelper class */
+       UpdateLocals(stream, debugger->dbthread->execThread,
+                                                                               
                debugger->dbthread->method);
+
+       str = DebuggerHelper_ShowLocals(debugger->dbthread->execThread);
+       if(str)
                        {
-                               if(*((ILBool *)(watch->addr)) != 0)
+               if(*str == '<')
                                {
-                                       fputs("true", stream);
+                       fputs(str, stream);
                                }
                                else
                                {
-                                       fputs("false", stream);
+                       DumpError(str, stream);
                                }
                        }
-                       break;
-                       case (unsigned long)ILType_Int8:
+       else
                        {
-                               fprintf(stream, "%d", *((ILInt8 
*)(watch->addr)));
+               DumpOutOfMemoryError(stream);
                        }
-                       break;
-                       case (unsigned long)ILType_UInt8:
+#endif  // IL_USE_JIT
+}
+
+/*
+ * add_watch command.
+ */
+void AddWatch(ILDebugger *debugger, FILE *stream)
+{
+       ILDebuggerWatch *watch;
+       ILDebuggerWatch *tail;
+
+       if(debugger->argCount < 1)
                        {
-                               fprintf(stream, "%u", *((ILUInt8 
*)(watch->addr)));
+               DumpParamMissingError(stream);
+               return;
                        }
-                       break;
-                       case (unsigned long)ILType_Int16:
+       
+       /* Allocate new watch */
+       if((watch = (ILDebuggerWatch *)ILMalloc(sizeof(ILDebuggerWatch))) == 0)
                        {
-                               fprintf(stream, "%hd", *((ILInt16 
*)(watch->addr)));
+               DumpOutOfMemoryError(stream);
+               return;
                        }
-                       break;
-                       case (unsigned long)ILType_UInt16:
+
+       /* Append the watch to the end of the list */
+       tail = debugger->watches;
+       if(tail != 0)
                        {
-                               fprintf(stream, "%hu", *((ILUInt16 
*)(watch->addr)));
-                       }
-                       break;
-                       case (unsigned long)ILType_Int32:
+               while(tail->next != 0)
                        {
-                               fprintf(stream, "%d", *((ILInt32 
*)(watch->addr)));
+                       tail = tail->next;
                        }
-                       break;
-                       case (unsigned long)ILType_UInt32:
-                       {
-                               fprintf(stream, "%u", *((ILUInt32 
*)(watch->addr)));
+               tail->next = watch;
                        }
-                       break;
-                       case (unsigned long)ILType_Int64:
-                       {
-                               fprintf(stream, "%lld", *((ILInt64 
*)(watch->addr)));
-                       }
-                       break;
-                       case (unsigned long)ILType_UInt64:
+       else
                        {
-                               fprintf(stream, "%llu", *((ILUInt64 
*)(watch->addr)));
+               debugger->watches = watch;
                        }
-                       break;
-                       case (unsigned long)ILType_Float32:
+       
+       watch->expression = ILDupString(debugger->args[0]);
+       watch->next = 0;
+
+       DumpMessage("ok", stream);
+}
+
+/*
+ * remove_watch command.
+ */
+void RemoveWatch(ILDebugger *debugger, FILE *stream)
+{
+       ILDebuggerWatch *watch;
+       ILDebuggerWatch *prev;
+
+       if(debugger->argCount < 1)
                        {
-                               fprintf(stream, "%f", *((ILFloat 
*)(watch->addr)));
+               DumpParamMissingError(stream);
+               return;
                        }
-                       break;
-                       case (unsigned long)ILType_Float64:
+       
+       /* Search the watch list for watch with given name */
+       prev = 0;
+       watch = debugger->watches;
+       while(watch != 0)
                        {
-                               fprintf(stream, "%f", *((ILDouble 
*)(watch->addr)));
-                       }
-                       break;
-                       case (unsigned long)ILType_Char:
+               if(ILStrICmp(watch->expression, debugger->args[0]) == 0)
                        {
-                               len = ILUTF8WriteChar(ch, *((ILUInt16 
*)(watch->addr)));
-                               for(j = 0; j < len; j++)
+                       if(prev != 0)
                                {
-                                       putc(ch[j], stream);
-                               }
-                       }
-                       break;
-                       default:
-                       {
-                               if(ILTypeIsStringClass(type))
-                               {
-                                       str = ILStringToUTF8(thread, 
*((ILString **)(watch->addr)));
-                                       DumpString(str, stream);
+                               prev->next = watch->next;
                                }
                                else
                                {
-                                       fprintf(stream, "%p", *((void 
**)(watch->addr)));
+                               debugger->watches = watch->next;
                                }
+                       ILFree(watch->expression);
+                       ILFree(watch);
+                       DumpMessage("ok", stream);
+                       return;
                        }
-                       break;
+               prev = watch;
+               watch = watch->next;
                }
-               fputs("\" >", stream);
 
-               str = ILTypeToName(type);
-               fputs("<Type Name=\"", stream);
-               DumpString(str, stream);
-               fputs("\" /></LocalVariable>\n", stream);
-               ILFree(str);
+       DumpMessage("watch not found", stream);
+}
 
-               current++;
-               num--;
+/*
+ * Destroy the watch list.
+ */
+static void DestroyWatchList(ILDebuggerWatch *watch)
+{
+       ILDebuggerWatch *next;
+       while(watch)
+       {
+               next = watch->next;
+               ILFree(watch->expression);
+               ILFree(watch);
+               watch = next;
        }
+}
 
-       fputs("</LocalVariables>",stream);
+/*
+ * remove_all_watches command.
+ */
+void RemoveAllWatches(ILDebugger *debugger, FILE *stream)
+{
+       DestroyWatchList(debugger->watches);
+       debugger->watches = 0;
+       DumpMessage("ok", stream);
+}
 
-#endif
+/*
+ * show_watches command.
+ */
+void ShowWatches(ILDebugger *debugger, FILE *stream)
+{
+       ILDebuggerWatch *watch;
+       char *value;
+
+       /* Update locals in DebuggerHelper class */
+       UpdateLocals(stream, debugger->dbthread->execThread,
+                                                                               
                debugger->dbthread->method);
+
+       fputs("<Watches>\n", stream);
+
+       /* Iterate all watches and dump their values */
+       watch = debugger->watches;
+       while(watch != 0)
+       {
+               fputs("  <Watch Expression=\"", stream);
+               DumpString(watch->expression, stream);
+               fputs("\" Value=\"", stream);
+               value = DebuggerHelper_ExpressionToString(
+                                               debugger->dbthread->execThread, 
watch->expression);
+               if(value)
+               {
+                       DumpString(value, stream);
+               }
+               fputs("\"/>\n", stream);
+               watch = watch->next;
+       }
+
+       fputs("</Watches>", stream);
 }
 
 /*
@@ -1197,7 +1375,7 @@
        else if((frame = _ILAllocCallFrame(thread)) == 0)
        {
                /* We ran out of memory trying to push the frame */
-               DumpError("out of memory while getting stack trace", stream);
+               DumpOutOfMemoryError(stream);
                return;
        }
        frame->method = thread->method;
@@ -1297,7 +1475,7 @@
 
        if(debugger->argCount < 1)
        {
-               DumpError("Parameter missing", stream);
+               DumpParamMissingError(stream);
                return;
        }
 
@@ -1334,7 +1512,7 @@
        /* Add the image to the watch list in the thread safe way */
        if((watch = (ILAssemblyWatch *)ILMalloc(sizeof(ILAssemblyWatch))) == 0)
        {
-               DumpError("out of memory", stream);
+               DumpOutOfMemoryError(stream);
                return;
        }
 
@@ -1356,35 +1534,6 @@
 }
 
 /*
- * suspend_all command.
- */
-void SuspendAll(ILDebugger *debugger, FILE *stream)
-{
-       ILExecThread *thread = debugger->process->firstThread;
-       while(thread)
-       {
-               _ILExecThreadSuspendThread(thread, thread->supportThread);
-               thread = thread->nextThread;
-       }
-       
-       /* Report ok and continue execution */
-       DumpMessage("ok", stream);
-}
-
-void ResumeAll(ILDebugger *debugger, FILE *stream)
-{
-       ILExecThread *thread = debugger->process->firstThread;
-       while(thread)
-       {
-               _ILExecThreadResumeThread(thread, thread->supportThread);
-               thread = thread->nextThread;
-       }
-
-       /* Report ok and continue execution */
-       DumpMessage("ok", stream);
-}
-
-/*
  * show_threads command.
  */
 void ShowThreads(ILDebugger *debugger, FILE *stream)
@@ -1528,7 +1677,7 @@
                                                        StringFreeFunc);
        if(table == 0)
        {
-               DumpError("Out of memory", stream);
+               DumpOutOfMemoryError(stream);
                return;
        }
 
@@ -1662,12 +1811,8 @@
                                info->runType = IL_DEBUGGER_RUN_TYPE_CONTINUE;
                        }
        
-                       /* Resume exec thread if it was suspended */
-                       if(debugger->commandThread)
-                       {
-                               _ILExecThreadResumeThread(info->execThread,
-                                                                               
        info->execThread->supportThread);
-                       }
+                       /* Signal thread to continue */
+                       ILWaitEventSet(info->event);
                }
                info = info->next;
        } while(info);
@@ -1717,6 +1862,22 @@
 }
 
 /*
+ * is_stopped_in_watched_assembly command.
+ */
+void IsStoppedInWatchedAssembly(ILDebugger *debugger, FILE *stream)
+{
+       if(debugger->dbthread->runType == IL_DEBUGGER_RUN_TYPE_STOPPED &&
+                       ILDebuggerIsAssemblyWatched(debugger, 
debugger->dbthread->method))
+       {
+               DumpMessage("yes", stream);
+       }
+       else
+       {
+               DumpMessage("no", stream);
+       }
+}
+
+/*
  * show_dasm command.
  */
 void ShowDasm(ILDebugger *debugger, FILE *stream)
@@ -1744,7 +1905,7 @@
 
        if(!str)
        {
-               DumpError("Out of memory", stream);
+               DumpOutOfMemoryError(stream);
                return;
        }
 
@@ -1781,7 +1942,7 @@
 
        if(!str)
        {
-               DumpError("Out of memory", stream);
+               DumpOutOfMemoryError(stream);
                return;
        }
 
@@ -1795,6 +1956,15 @@
 }
 
 /*
+ * quit command.
+ */
+void Quit(ILDebugger *debugger, FILE *stream)
+{
+       debugger->abort = 1;
+       DumpMessage("ok", stream);
+}
+
+/*
  * Table of commands.
  */
 typedef struct
@@ -1840,6 +2010,24 @@
                "Toggle breakpoint."
        },
 
+       { "add_watch",                                  9,      1,      
AddWatch,
+               "add_watch [expression]",
+               "Add new watch.",
+               "Add new watch. Specify variable, field, property or function 
call e.g. i, this.x, this.X, this.ToString"
+       },
+
+       { "remove_watch",                               12,     1,      
RemoveWatch,
+               "remove_watch [expression]",
+               "Remove watch.",
+               "Remove watch with given id."
+       },
+
+       { "remove_all_watches",                 18,     1,      
RemoveAllWatches,
+               "remove_all_watches",
+               "Remove all watches.",
+               "Remove all watches."
+       },
+
        { "break",                                              5,      0,      
Break,
                "break",
                "Break execution.",
@@ -1876,6 +2064,12 @@
                "Execution is stopped e.g when breakpoint is reached or break 
command is issued."
        },
 
+       { "is_stopped_in_watched_assembly",     30,     0,      
IsStoppedInWatchedAssembly,
+               "is_stopped_in_watched_assembly",
+               "Is execution stopped in assembly that we watch?",
+               "This function is useful after initial break. We usually do 
step command to get to assembly that is user watching."
+       },      
+
        { "show_threads",                               12,     0,      
ShowThreads,
                "show_threads",
                "List threads stopped in debugger.",
@@ -1889,9 +2083,15 @@
        },
 
        { "show_locals",                                11,     0,      
ShowLocals,
-               "print_locals",
-               "Print local variables.",
-               "Print local variables."
+               "show_locals",
+               "Show local variables.",
+               "Show local variables."
+       },
+
+       { "show_watches",                               12,     0,      
ShowWatches,
+               "show_watches",
+               "Show all watches.",
+               "Show all watches defined with add_watch command."
        },
 
        { "show_position",                              13,     0,      
ShowPosition,
@@ -1924,6 +2124,12 @@
                "Dissassemble current function in IL."
        },
 
+       { "quit",                                               4,      0,      
Quit,
+               "quit",
+               "Abort debugged program.",
+               "Abort debugged program."
+       },
+
        { "help",                                               4,      0,      
Help,
                "help [command]",
                "Display this information or command help.",
@@ -1934,6 +2140,63 @@
 #define        num_commands    (sizeof(commands) / sizeof(commands[0]))
 
 /*
+ * Help command.
+ */
+static void Help(ILDebugger *debugger, FILE *stream)
+{
+       int i;
+       char *msg;
+       int size, maxSize; 
+
+       /* Print the help header */
+       fputs("Usage: command [arguments]\n", stream);
+       fputs("Commands:\n", stream);
+
+       /* Scan the command table to determine the width of the tab column */
+       maxSize = 0;
+       for(i = 0; i < num_commands; ++i)
+       {
+               msg = commands[i].helpName;
+               if(!msg)
+               {
+                       continue;
+               }
+               size = strlen(msg);
+               if(size > maxSize)
+               {
+                       maxSize = size;
+               }
+       }
+
+       /* Dump the help messages in the command table */
+       for(i = 0; i < num_commands; ++i)
+       {
+               if(i > 0)
+               {
+                       putc('\n', stream);
+               }
+               msg = commands[i].helpName;
+               if(!msg)
+               {
+                       continue;
+               }
+               msg = msg;
+               size = 0;
+               fputs(msg, stream);
+               size = strlen(msg);
+               while(size < maxSize)
+               {
+                       putc(' ', stream);
+                       ++size;
+               }
+               putc(' ', stream);
+               putc(' ', stream);
+               msg = commands[i].helpMsg;
+               fputs(msg, stream);
+       }
+}
+
+/*
  * Check if commands are ok.
  */
 static int CheckCommands()
@@ -2026,12 +2289,27 @@
 }
 
 /*
- * Parse command from input text and call command function.
+ * Parse, execute and free current debugger command.
+ * Returns:
+ *   1 if next command is expected 
+ *   0 to continue execution (e.g. after step command)
  */
-void ParseAndExecuteCommand(ILDebugger *debugger, char *text, int textLen,
-                                                                               
                                        FILE *outputStream)
+static void ParseAndExecuteCurrentCommand(ILDebugger *debugger)
 {
-       int cmdIndex = ParseCommand(debugger, text, textLen);
+       int cmdIndex;
+       FILE *outputStream = debugger->io->output;
+
+       /* Handle aborting */
+       if(debugger->abort)
+       {
+               DumpMessage("process is aborting", outputStream);
+       }
+       else
+       {
+               /* Parse command */
+               cmdIndex = ParseCommand(debugger, debugger->currentCommand,
+                                                                               
                strlen(debugger->currentCommand));
+
        if(cmdIndex >= 0)
        {
                /* Execute command */
@@ -2048,13 +2326,18 @@
        }
  }
 
+       /* Free command text, since it was allocated on heap */
+       ILFree(debugger->currentCommand);
+       debugger->currentCommand = 0;
+ }
+
 /*
  * Run command loop.
  */
 static void CommandLoop(ILDebugger *debugger)
 {
-       char *cmd;
        int nextCommand;
+
        do
        {
                /* Recieve command */
@@ -2065,8 +2348,8 @@
                }
 
                /* Read command text from input stream */
-               cmd = ReadStream(debugger->io->input);
-               if(cmd == 0)
+               debugger->currentCommand = ReadStream(debugger->io->input);
+               if(debugger->currentCommand == 0)
                {
                        debugger->abort = 1;
                        break;
@@ -2075,100 +2358,50 @@
                /* Dump response header */
                fputs("<DebuggerResponse>\n", debugger->io->output);
 
-               /* Lock down the debugger */
+               /* Lock down the debugger for executing command */
                LockDebugger(debugger);
                
-               /* Execute command */
-               ParseAndExecuteCommand(debugger, cmd, strlen(cmd),
-                                                                               
                                debugger->io->output);
+               /* Determine which thread should execute the command */
+               if(debugger->dbthread->runType == IL_DEBUGGER_RUN_TYPE_STOPPED 
&&
+                                                                               
                debugger->ioThread != 0)
+               {
+                       /* Wake up current thread to execute the command */
+                       ILWaitEventSet(debugger->dbthread->event);
 
-               /* Next command flag - true until debugger is stopped */
-               nextCommand =
-                               (debugger->dbthread->runType == 
IL_DEBUGGER_RUN_TYPE_STOPPED);
+                       /* Wait until the command is processed */
+                       ILWaitOne(debugger->event, -1);
+               }
+               else
+               {
+                       /* Handle command from this thread */
+                       ParseAndExecuteCurrentCommand(debugger);
+               }
 
-               /* Unlock the debugger */
                UnlockDebugger(debugger);
 
                /* Dump response footer */
                fputs("\n</DebuggerResponse>\n", debugger->io->output);
 
-               /* Free command text, since it was allocated on head */
-               ILFree(cmd);
-
                /* Send response to client */
                if(!(debugger->io->send(debugger->io)))
                {
                        debugger->abort = 1;
                        break;
                }
-       }
-       while(nextCommand);
-}
 
-/*
- * Help command.
- */
-static void Help(ILDebugger *debugger, FILE *stream)
-{
-       int i;
-       char *msg;
-       int size, maxSize; 
-
-       /* Print the help header */
-       fputs("Usage: command [arguments]\n", stream);
-       fputs("Commands:\n", stream);
-
-       /* Scan the command table to determine the width of the tab column */
-       maxSize = 0;
-       for(i = 0; i < num_commands; ++i)
-       {
-               msg = commands[i].helpName;
-               if(!msg)
-               {
-                       continue;
-               }
-               size = strlen(msg);
-               if(size > maxSize)
-               {
-                       maxSize = size;
-               }
-       }
-
-       /* Dump the help messages in the command table */
-       for(i = 0; i < num_commands; ++i)
-       {
-               if(i > 0)
-               {
-                       putc('\n', stream);
-               }
-               msg = commands[i].helpName;
-               if(!msg)
-               {
-                       continue;
-               }
-               msg = msg;
-               size = 0;
-               fputs(msg, stream);
-               size = strlen(msg);
-               while(size < maxSize)
-               {
-                       putc(' ', stream);
-                       ++size;
-               }
-               putc(' ', stream);
-               putc(' ', stream);
-               msg = commands[i].helpMsg;
-               fputs(msg, stream);
+               /* Is next command expected?*/
+               nextCommand = debugger->dbthread->runType == 
IL_DEBUGGER_RUN_TYPE_STOPPED;
        }
+       while(nextCommand && debugger->abort == 0);
 }
 
 /*
  * Do CommandLoop() until abort is requested.
- * This function executing in command thread.
- * When abort requested, all thread have to
+ * This function is executing in IO thread.
+ * When abort is requested, all thread have to
  * be resumed, so that they can terminate.
  */
-static void CommandThreadFn(void *arg)
+static void IOThreadFn(void *arg)
 {
        ILDebugger *debugger = (ILDebugger *) arg;
        do
@@ -2185,7 +2418,7 @@
 /*
  * Start command-loop in separate thread.
  */
-int StartCommandThread(ILDebugger *debugger)
+int StartIOThread(ILDebugger *debugger)
 {
        if(!ILHasThreads())
        {
@@ -2193,19 +2426,19 @@
        }
 
        /* Create command loop thread  */
-       debugger->commandThread = ILThreadCreate(CommandThreadFn,
+       debugger->ioThread = ILThreadCreate(IOThreadFn,
                                                                                
                                (void *) debugger);
 
-       if(debugger->commandThread == 0)
+       if(debugger->ioThread == 0)
        {
                return 0;
        }
 
        /* Start command loop thread */
-       if(!ILThreadStart(debugger->commandThread))
+       if(!ILThreadStart(debugger->ioThread))
        {
-               ILThreadDestroy(debugger->commandThread);
-               debugger->commandThread = 0;
+               ILThreadDestroy(debugger->ioThread);
+               debugger->ioThread = 0;
                return 0;
        }
 
@@ -2256,7 +2489,7 @@
        /* Get or create debugger info about thread */
        info = GetDbThreadInfo(debugger, thread);
 
-       //fprintf(stderr, " run type %d\n", info->runType);
+       /* fprintf(stderr, " runType=%d breakAll=%d\n", info->runType, 
debugger->breakAll); */
 
        if(debugger->breakAll)
        {
@@ -2361,10 +2594,21 @@
        UnlockDebugger(debugger);
 
        /* Check command loop thread */
-       if(debugger->commandThread || StartCommandThread(debugger))
+       if(debugger->ioThread || StartIOThread(debugger))
+       {
+               while(info->runType == IL_DEBUGGER_RUN_TYPE_STOPPED)
+               {
+                       /* Wait for command or for resuming */
+                       ILWaitOne(info->event, -1);
+
+                       /* Check if we were resumed for executing current 
command */
+                       if(debugger->currentCommand != 0 && info == 
debugger->dbthread)
        {
-               /* Suspend until resumed by continue, step or similar command */
-               _ILExecThreadSuspendThread(thread, thread->supportThread);
+                               /* Execute and signal that the command was 
handled */
+                               ParseAndExecuteCurrentCommand(debugger);
+                               ILWaitEventSet(debugger->event);
+                       }
+               }
        }
        else
        {
@@ -2452,12 +2696,22 @@
        return process->debugger;
 }
 
+void ILDebuggerRequestTerminate(ILDebugger *debugger)
+{
+       /* Notify IO thread to abort */
+       debugger->abort = 1;
+}
+
 void ILDebuggerDestroy(ILDebugger *debugger)
 {
        /* Destroy initialized members */
-       if(debugger->commandThread)
+       if(debugger->ioThread)
+       {
+               ILThreadDestroy(debugger->ioThread);
+       }
+       if(debugger->event)
        {
-               ILThreadDestroy(debugger->commandThread);
+               ILWaitHandleClose(debugger->event);
        }
        if(debugger->lock)
        {
@@ -2470,6 +2724,9 @@
        /* Destroy assembly watch list */
        DestroyAssemblyWatches(debugger);
 
+       /* Destroy watch list */
+       DestroyWatchList(debugger->watches);
+
        if(debugger->io)
        {
                ILDebuggerIODestroy(debugger->io);
@@ -2518,6 +2775,9 @@
        /* Assembly watch list */
        debugger->assemblyWatches = 0;
 
+       /* Watch list */
+       debugger->watches = 0;
+
        /* Default thread info */
        debugger->dbthread = ILDebuggerThreadInfo_Create();
        debugger->dbthread->runType = IL_DEBUGGER_RUN_TYPE_STEP;
@@ -2529,13 +2789,22 @@
        debugger->breakpoint = ILBreakpoint_Create();
 
        /* Initialize command thread */
-       debugger->commandThread = 0;
+       debugger->ioThread = 0;
+
+       /* Initialize handle for synchronizing command execution */
+       debugger->event = ILWaitEventCreate(0, 0);
+       if(!(debugger->event))
+       {
+               fprintf(stderr, "il_debugger: failed to create wait handle\n");
+               ILDebuggerDestroy(debugger);
+               return 0;
+       }
 
        /* Register debug hook function */
        if(ILExecProcessDebugHook(process, DebugHook, 0) == 0)
        {
-               ILDebuggerDestroy(debugger);
                fprintf(stderr, "il_debugger: the runtime engine does not 
support debugging.\n");
+               ILDebuggerDestroy(debugger);
                return 0;
        }
 

Index: engine/debugger.h
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/debugger.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- engine/debugger.h   23 Jan 2007 19:49:02 -0000      1.4
+++ engine/debugger.h   9 Mar 2007 17:43:11 -0000       1.5
@@ -45,6 +45,20 @@
 
 #define IL_DEBUGGER_COMMAND_MAX_ARG_COUNT      3
 
+/*
+ * Determine if thread is unbreakable and untouchable in coder's debug hook.
+ *
+ * Such thread has stopped in debug hook and is now calling managed method
+ * e.g. ToString() for displaying watch.
+ * 
+ * The engine must prevent calling debug hook and changing debugger related
+ * stuff of such thread. Otherwise it leads to deadlock or other disfunctions.
+ * For example if thread->frame gets changed this affects show_locals command
+ * which relies on this value.
+ */
+#define ILDebuggerIsThreadUnbreakable(thread) \
+       (thread->process->debugger->dbthread->runType == 
IL_DEBUGGER_RUN_TYPE_STOPPED && \
+        thread->process->debugger->dbthread->execThread == thread)
 
 /*
  * Check whether debugger is watching method's assembly.
@@ -67,6 +81,9 @@
        ILInt32 offset;
        int type;
 
+       /* Wakeups the thread to execute command or continue execution */
+       ILWaitHandle *event;
+
        /* Current location in source file */
        const char *sourceFile;
        ILUInt32 line;
@@ -112,6 +129,18 @@
 };
 
 /*
+ * Watch info for local variable, field, property or function call.
+ */
+struct _tagILDebuggerWatch
+{
+       /* Expression to watch */
+       char *expression;
+
+       /* Next watch in this linked list */
+       ILDebuggerWatch *next;
+};
+
+/*
  * Structure of a debugger instance.
  */
 struct _tagILDebugger
@@ -119,14 +148,21 @@
        /* Lock to serialize access to this object */
        ILMutex *lock;
 
-       /* Refernce to current exec process */
+       /* Reference to current exec process */
        ILExecProcess *process;
 
        /* Debugger client stream */
        ILDebuggerIO *io;
 
-       /* Thread with command loop or 0 if debugging runs in single thread */
-       ILThread *commandThread;
+       /* Current command */
+       char *currentCommand;
+
+       /* Used to signal that command execution finnished */
+       ILWaitHandle *event;
+
+       /* Thread that is recieving, sending and sometimes executing commands.
+          Can be 0 if debugging runs in single thread. */
+       ILThread *ioThread;
 
        /* Currently debugged thread followed by other stopped threads */
        ILDebuggerThreadInfo * volatile dbthread;
@@ -134,6 +170,10 @@
        /* Linked list of watched assemblies or NULL to watch all */
        ILAssemblyWatch *assemblyWatches;
        
+       /* Linked list of watched local variables, fields, properties or 
function
+          calls */
+       ILDebuggerWatch *watches;
+       
        /* Linked list of user breakpoints */
        ILBreakpoint *breakpoint;
 

Index: engine/engine.h
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/engine.h,v
retrieving revision 1.118
retrieving revision 1.119
diff -u -b -r1.118 -r1.119
--- engine/engine.h     23 Jan 2007 19:49:02 -0000      1.118
+++ engine/engine.h     9 Mar 2007 17:43:11 -0000       1.119
@@ -339,13 +339,13 @@
 /*
  * Information about local variable or function parameter.
  */
-typedef struct _tagILWatch
+typedef struct _tagILLocalWatch
 {
        void           *addr;                   /* Address of variable */
        int                             flag;
        void               *frame;                      /* Frame pointer */
 
-} ILWatch;
+} ILLocalWatch;
 #endif
 
 /*
@@ -424,7 +424,7 @@
 
 #ifdef IL_CONFIG_DEBUGGER
        /* Stack for watching local variables and function params */
-       ILWatch        *watchStack;
+       ILLocalWatch   *watchStack;
        ILUInt32                numWatches;
        ILUInt32                maxWatches;
 #endif
@@ -902,7 +902,7 @@
  * Reallocate the watches for a given thread in order
  * to provide more space.  Returns NULL if out of memory.
  */
-ILWatch *_ILAllocWatch(ILExecThread *thread);
+ILLocalWatch *_ILAllocLocalWatch(ILExecThread *thread);
 #endif
 
 /*

Index: engine/ilrun.c
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/ilrun.c,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -b -r1.57 -r1.58
--- engine/ilrun.c      17 Feb 2007 14:44:21 -0000      1.57
+++ engine/ilrun.c      9 Mar 2007 17:43:11 -0000       1.58
@@ -192,7 +192,7 @@
 #endif
 #ifdef IL_CONFIG_DEBUGGER
        char *debuggerConnectionString = 0;
-       ILDebugger *debugger;
+       ILDebugger *debugger = 0;
 #endif
 
        /* Initialize the locale routines */
@@ -436,6 +436,7 @@
                        {
                                /* Connect failed - destroy debugger and print 
error */
                                ILDebuggerDestroy(debugger);
+                               debugger = 0;
                                fprintf(stderr, "%s: debugger connection failed 
on %s\n",
                                                                                
        progname,
                                                                                
        debuggerConnectionString);
@@ -588,6 +589,14 @@
                ILExecThreadPrintException(thread);
        }
 
+#ifdef IL_CONFIG_DEBUGGER
+       /* Notify debugger client that the process is terminating */
+       if(debugger)
+       {
+               ILDebuggerRequestTerminate(debugger);
+       }
+#endif
+
        /* Wait for all foreground threads to finish */
        ILThreadWaitForForegroundThreads(-1);
  

Index: engine/jitc.c
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/jitc.c,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -b -r1.68 -r1.69
--- engine/jitc.c       11 Feb 2007 14:34:32 -0000      1.68
+++ engine/jitc.c       9 Mar 2007 17:43:11 -0000       1.69
@@ -2574,7 +2574,7 @@
 {
        void *frame;
        ILUInt32 i;
-       ILWatch *watch;
+       ILLocalWatch *watch;
 
        /* Mark all watches invalid */
        for(i = 0; i < thread->numWatches; i++)
@@ -2628,11 +2628,17 @@
 static void JitDebuggerHook(jit_function_t func, jit_nint data1, jit_nint 
data2)
 {
        ILExecThread *thread;
-       ILWatch *watch;
+       ILLocalWatch *watch;
        void *frame;
 
        thread = ILExecThreadCurrent();
 
+       /* Prevent debug hook call for thread executing from debugger */
+       if(ILDebuggerIsThreadUnbreakable(thread))
+       {
+               return;
+       }
+
        switch(data1)
        {
                case JIT_DEBUGGER_DATA1_METHOD_ENTER:
@@ -2649,7 +2655,7 @@
                        {
                                watch = 
&(thread->watchStack[(thread->numWatches)]);
                        }
-                       else if((watch = _ILAllocWatch(thread)) == 0)
+                       else if((watch = _ILAllocLocalWatch(thread)) == 0)
                        {
                                /* We ran out of memory trying to push the 
watch */
                                thread->numWatches = 0;
@@ -2659,7 +2665,7 @@
                        /* Two frames above us should be frame for current 
method */
                        watch->frame = jit_get_frame_address(2);
 
-                       /* Assign index of local variable. Type and address 
will follow */
+                       /* Address is in data2 */
                        watch->addr = (void *) data2;
 
                        thread->numWatches++;

Index: engine/process.c
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/process.c,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -b -r1.70 -r1.71
--- engine/process.c    4 Nov 2006 10:53:18 -0000       1.70
+++ engine/process.c    9 Mar 2007 17:43:11 -0000       1.71
@@ -444,6 +444,14 @@
                _ILExecThreadDestroy(process->finalizerThread);
        }
 
+#ifdef IL_CONFIG_DEBUGGER
+       /* Destroy the debugger */
+       if(process->debugger)
+       {
+               ILDebuggerDestroy(process->debugger);
+       }
+#endif
+
        /* Destroy the CVM coder instance */
        if (process->coder)
        {

Index: engine/thread.c
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/thread.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -b -r1.44 -r1.45
--- engine/thread.c     23 Jan 2007 19:49:02 -0000      1.44
+++ engine/thread.c     9 Mar 2007 17:43:11 -0000       1.45
@@ -784,10 +784,10 @@
 
 #ifdef IL_CONFIG_DEBUGGER
 
-ILWatch *_ILAllocWatch(ILExecThread *thread)
+ILLocalWatch *_ILAllocLocalWatch(ILExecThread *thread)
 {
        ILUInt32 newsize;
-       ILWatch *watches;
+       ILLocalWatch *watches;
 
        /* Calculate watch stack size */
        if(thread->maxWatches)
@@ -800,8 +800,8 @@
        }
 
        /* Allocate new watches */
-       if((watches = (ILWatch *)ILGCAllocPersistent
-                               (sizeof(ILWatch) * newsize)) == 0)
+       if((watches = (ILLocalWatch *)ILGCAllocPersistent
+                               (sizeof(ILLocalWatch) * newsize)) == 0)
        {
            thread->thrownException = thread->process->outOfMemoryObject;
                return 0;
@@ -811,7 +811,7 @@
        if(thread->maxWatches)
        {
                ILMemCpy(watches, thread->watchStack,
-                               sizeof(ILWatch) * thread->maxWatches);
+                               sizeof(ILLocalWatch) * thread->maxWatches);
 
                /* Free the old watches */
                ILGCFreePersistent(thread->watchStack);

Index: include/il_debugger.h
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/include/il_debugger.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- include/il_debugger.h       23 Jan 2007 19:49:02 -0000      1.3
+++ include/il_debugger.h       9 Mar 2007 17:43:11 -0000       1.4
@@ -37,6 +37,7 @@
 typedef struct _tagILBreakpoint                ILBreakpoint;
 typedef struct _tagILDebuggerThreadInfo                ILDebuggerThreadInfo;
 typedef struct _tagILAssemblyWatch             ILAssemblyWatch;
+typedef struct _tagILDebuggerWatch             ILDebuggerWatch;
 typedef struct _tagILDebuggerIO                        ILDebuggerIO;
 
 /*
@@ -119,6 +120,12 @@
 int ILDebuggerConnect(ILDebugger *debugger, char *connectionString);
 
 /*
+ * Notify debugger that the process is terminating.
+ * This will notify client and terminate IO thread.
+ */
+void ILDebuggerRequestTerminate(ILDebugger *debugger);
+
+/*
  * Destroy debugger and IO connection to debugger client.
  */
 void ILDebuggerDestroy(ILDebugger *debugger);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]