| /****************************************************************************** |
| * Copyright (c) 2005 The Regents of the University of California. |
| * This material was produced under U.S. Government contract W-7405-ENG-36 |
| * for Los Alamos National Laboratory, which is operated by the University |
| * of California for the U.S. Department of Energy. The U.S. Government has |
| * rights to use, reproduce, and distribute this software. NEITHER THE |
| * GOVERNMENT NOR THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR |
| * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified |
| * to produce derivative works, such modified software should be clearly |
| * marked, so as not to confuse it with the version available from LANL. |
| * |
| * Additionally, this program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * LA-CC 04-115 |
| ******************************************************************************/ |
| |
| #ifdef __gnu_linux__ |
| #define _GNU_SOURCE |
| #endif /* __gnu_linux__ */ |
| |
| #include "config.h" |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/wait.h> |
| |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| |
| #include "dbg.h" |
| #include "dbg_event.h" |
| #include "backend.h" |
| #include "list.h" |
| |
| static dbg_event * LastEvent; |
| static void (*EventCallback)(dbg_event *); |
| static int ServerExit; |
| static int Started; |
| |
| static int TestInit(void (*)(dbg_event *)); |
| static int TestProgress(void); |
| static int TestInterrupt(void); |
| static int TestStartSession(char *, char *, char *, char *, char **, char **, long); |
| static int TestSetLineBreakpoint(int, int, int, char *, int, char*, int, int); |
| static int TestSetFuncBreakpoint(int, int, int, char *, char *, char*, int, int); |
| static int TestDeleteBreakpoint(int); |
| static int TestEnableBreakpoint(int); |
| static int TestDisableBreakpoint(int); |
| static int TestConditionBreakpoint(int, char *expr); |
| static int TestBreakpointAfter(int, int icount); |
| static int TestWatchpoint(int, char *, int, int, char *, int); |
| static int TestGo(void); |
| static int TestStep(int, int); |
| static int TestTerminate(void); |
| static int TestListStackframes(int, int); |
| static int TestSetCurrentStackframe(int); |
| static int TestEvaluateExpression(char *); |
| static int TestGetNativeType(char *); |
| static int TestGetLocalVariables(void); |
| static int TestListArguments(int, int); |
| static int TestGetInfoThread(void); |
| static int TestSetThreadSelect(int); |
| static int TestStackInfoDepth(void); |
| static int TestDataReadMemory(long, char*, char*, int, int, int, char*); |
| static int TestDataWriteMemory(long, char*, char*, int, char*); |
| static int TestGetGlobalVariables(void); |
| static int TestListSignals(char*); |
| static int TestSignalInfo(char*); |
| static int TestHandle(char*); |
| static int TestQuit(void); |
| static int TestDataEvaluateExpression(char*); |
| static int TestGetPartialAIF(char *, char *, int, int); |
| static int TestVarDelete(char*); |
| |
| static int SetAndCheckBreak(int, int, int, char *, char *, int, int); |
| |
| dbg_backend_funcs TestBackend = |
| { |
| TestInit, |
| TestProgress, |
| TestInterrupt, |
| TestStartSession, |
| TestSetLineBreakpoint, |
| TestSetFuncBreakpoint, |
| TestDeleteBreakpoint, |
| TestEnableBreakpoint, |
| TestDisableBreakpoint, |
| TestConditionBreakpoint, |
| TestBreakpointAfter, |
| TestWatchpoint, |
| TestGo, |
| TestStep, |
| TestTerminate, |
| TestListStackframes, |
| TestSetCurrentStackframe, |
| TestEvaluateExpression, |
| TestGetNativeType, |
| TestGetLocalVariables, |
| TestListArguments, |
| TestGetGlobalVariables, |
| TestGetInfoThread, |
| TestSetThreadSelect, |
| TestStackInfoDepth, |
| TestDataReadMemory, |
| TestDataWriteMemory, |
| TestListSignals, |
| TestSignalInfo, |
| TestHandle, |
| TestDataEvaluateExpression, |
| TestGetPartialAIF, |
| TestVarDelete, |
| TestQuit |
| }; |
| |
| static void |
| SaveEvent(dbg_event *e) |
| { |
| if (LastEvent != NULL) |
| FreeDbgEvent(LastEvent); |
| |
| LastEvent = e; |
| } |
| |
| /* |
| * Initialize Test |
| */ |
| static int |
| TestInit(void (*event_callback)(dbg_event *)) |
| { |
| EventCallback = event_callback; |
| LastEvent = NULL; |
| ServerExit = 0; |
| |
| signal(SIGTERM, SIG_IGN); |
| signal(SIGHUP, SIG_IGN); |
| signal(SIGINT, SIG_IGN); |
| |
| return DBGRES_OK; |
| } |
| |
| /* |
| * Start Test session |
| */ |
| static int |
| TestStartSession(char *test_path, char *prog, char *path, char *work_dir, char **args, char **env, long timeout) |
| { |
| Started = 0; |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| * Progress test commands. |
| * |
| * TODO: Deal with errors |
| * |
| * @return -1 server shutdown |
| * 1 event callback |
| * 0 completed operation |
| */ |
| static int |
| TestProgress(void) |
| { |
| int res = 0; |
| |
| /* |
| * Check for existing events |
| */ |
| if (LastEvent != NULL) { |
| if (EventCallback != NULL) { |
| EventCallback(LastEvent); |
| res = 1; |
| } |
| |
| if (ServerExit && LastEvent->event_id == DBGEV_OK) { |
| res = -1; |
| } |
| |
| FreeDbgEvent(LastEvent); |
| LastEvent = NULL; |
| return res; |
| } |
| |
| return 0; |
| } |
| |
| /* |
| ** Set breakpoint at specified line. |
| */ |
| static int |
| TestSetLineBreakpoint(int bpid, int isTemp, int isHard, char *file, int line, char *condition, int ignoreCount, int tid) |
| { |
| int res; |
| char* where = NULL; |
| res = SetAndCheckBreak(bpid, isTemp, isHard, where, condition, ignoreCount, tid); |
| return res; |
| } |
| |
| /* |
| ** Set breakpoint at start of specified function. |
| */ |
| static int |
| TestSetFuncBreakpoint(int bpid, int isTemp, int isHard, char *file, char *func, char *condition, int ignoreCount, int tid) |
| { |
| int res; |
| char* where = NULL; |
| res = SetAndCheckBreak(bpid, isTemp, isHard, where, condition, ignoreCount, tid); |
| return res; |
| } |
| |
| /* |
| ** Check that breakpoint command has succeded and |
| ** extract appropriate information. Returns breakpoint |
| ** id in bid. Adds to breakpoint list if necessary. |
| */ |
| static int |
| SetAndCheckBreak(int bpid, int isTemp, int isHard, char *where, char *condition, int ignoreCount, int tid) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_BPSET); |
| e->dbg_event_u.bpset_event.bpid = bpid; |
| e->dbg_event_u.bpset_event.bp = MIBreakpointNew(); |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** Delete a breakpoint. |
| */ |
| static int |
| TestDeleteBreakpoint(int bpid) |
| { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** Enable a breakpoint. |
| */ |
| static int |
| TestEnableBreakpoint(int bpid) |
| { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** Disable a breakpoint. |
| */ |
| static int |
| TestDisableBreakpoint(int bpid) |
| { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** Condition a breakpoint. |
| */ |
| static int |
| TestConditionBreakpoint(int bpid, char *expr) |
| { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** breakpoint after. |
| */ |
| static int |
| TestBreakpointAfter(int bpid, int icount) |
| { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| * Set watch point |
| */ |
| static int |
| TestWatchpoint(int bpid, char *expr, int isAccess, int isRead, char *condition, int ignoreCount) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_BPSET); |
| e->dbg_event_u.bpset_event.bpid = bpid; |
| e->dbg_event_u.bpset_event.bp = MIBreakpointNew(); |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** Start/continue executing program. |
| */ |
| static int |
| TestGo(void) |
| { |
| //SendCommandWait(DebugSession, cmd); |
| return DBGRES_OK; |
| } |
| |
| /* |
| * Execute count statements. |
| * |
| * type step kind |
| * 0 enter function calls |
| * 1 do not enter function calls |
| * 2 step out of function (count ignored) |
| */ |
| static int |
| TestStep(int count, int type) |
| { |
| //SendCommandWait(DebugSession, cmd); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** Terminate program execution. |
| */ |
| static int |
| TestTerminate(void) |
| { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** Interrupt an executing program. |
| */ |
| static int |
| TestInterrupt(void) |
| { |
| //SendCommandWait(DebugSession, cmd); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** Move up or down count stack frames. |
| */ |
| static int |
| TestSetCurrentStackframe(int level) |
| { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** List current or all stack frames. |
| */ |
| static int |
| TestListStackframes(int low, int high) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_FRAMES); |
| e->dbg_event_u.list = frames; |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** List local variables. |
| */ |
| static int |
| TestGetLocalVariables(void) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_VARS); |
| e->dbg_event_u.list = NewList(); |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** List arguments. |
| */ |
| static int |
| TestListArguments(int low, int high) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_ARGS); |
| e->dbg_event_u.list = NewList(); |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** List global variables. |
| */ |
| static int |
| TestGetGlobalVariables(void) |
| { |
| DbgSetError(DBGERR_NOTIMP, NULL); |
| return DBGRES_ERR; |
| } |
| |
| /* |
| ** Quit debugger. |
| */ |
| static int |
| TestQuit(void) |
| { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| ServerExit++; |
| return DBGRES_OK; |
| } |
| |
| static int |
| TestGetInfoThread(void) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_THREADS); |
| e->dbg_event_u.threads_event.thread_id = info->current_thread_id; |
| e->dbg_event_u.threads_event.list = NewList(); |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| static int |
| TestSetThreadSelect(int threadNum) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_THREAD_SELECT); |
| e->dbg_event_u.thread_select_event.thread_id = info->current_thread_id; |
| e->dbg_event_u.thread_select_event.frame = s; |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| static int |
| TestStackInfoDepth() |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_STACK_DEPTH); |
| e->dbg_event_u.stack_depth = depth; |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| static int |
| TestDataReadMemory(long offset, char* address, char* format, int wordSize, int rows, int cols, char* asChar) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_DATAR_MEM); |
| e->dbg_event_u.meminfo = meminfo; |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| static int |
| TestDataWriteMemory(long offset, char* address, char* format, int wordSize, char* value) |
| { |
| //TODO |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| static int |
| TestListSignals(char* name) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_SIGNALS); |
| e->dbg_event_u.list = signals; |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| static int |
| TestSignalInfo(char* arg) |
| { |
| //SendCommandWait(DebugSession, cmd); |
| return DBGRES_OK; |
| } |
| |
| static int |
| TestHandle(char *arg) |
| { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| static int |
| TestDataEvaluateExpression(char *arg) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_DATA_EVA_EX); |
| e->dbg_event_u.data_expression = res; |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /* |
| ** Evaluate the expression exp. |
| */ |
| static int |
| TestEvaluateExpression(char *exp) |
| { |
| AIF *a; |
| if (strcmp(exp, "long_string") == 0) { |
| a = StringToAIF("testing start from 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 end 200"); |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_DATA); |
| e->dbg_event_u.data_event.data = a; |
| e->dbg_event_u.data_event.type_desc = "string"; |
| SaveEvent(e); |
| } |
| else if (strcmp(exp, "long_long_string") == 0) { |
| a = StringToAIF("testing start from \ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\ |
| end 5000"); |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_DATA); |
| e->dbg_event_u.data_event.data = a; |
| e->dbg_event_u.data_event.type_desc = "string"; |
| SaveEvent(e); |
| } |
| else { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| } |
| return DBGRES_OK; |
| } |
| /* |
| ** Find native type of variable. |
| */ |
| static int |
| TestGetNativeType(char *var) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_TYPE); |
| e->dbg_event_u.type_desc = type; |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| /*************************** PARTIAL AIF ***************************/ |
| static int |
| TestGetPartialAIF(char* name, char* key, int listChildren, int express) |
| { |
| /* |
| dbg_event * e; |
| e = NewDbgEvent(DBGEV_PARTIAL_AIF); |
| e->dbg_event_u.partial_aif_event.data = a; |
| e->dbg_event_u.partial_aif_event.type_desc = strdup(mivar->type); |
| e->dbg_event_u.partial_aif_event.name = strdup(mivar->name); |
| SaveEvent(e); |
| */ |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |
| |
| static int |
| TestVarDelete(char *name) |
| { |
| SaveEvent(NewDbgEvent(DBGEV_OK)); |
| return DBGRES_OK; |
| } |