[Top][All Lists]
[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);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [dotgnu-pnet-commits] pnet ChangeLog engine/debugger.c engine/debugge...,
Radek Polak <=