| /****************************************************************************** | |
| * 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 | |
| ******************************************************************************/ | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <errno.h> | |
| #include <stdio.h> | |
| #include "compat.h" | |
| #include "args.h" | |
| #include "dbg.h" | |
| #include "dbg_event.h" | |
| #include "dbg_proxy.h" | |
| #include "backend.h" | |
| #define SVR_RUNNING 0 | |
| #define SVR_SHUTDOWN_STARTED 1 | |
| #define SVR_SHUTDOWN_COMPLETED 2 | |
| typedef int (*svr_cmd)(dbg_backend *, int, char **); | |
| static int svr_cmd_start_session(dbg_backend *, int, char **); | |
| static int svr_cmd_setlinebreakpoint(dbg_backend *, int, char **); | |
| static int svr_cmd_setfuncbreakpoint(dbg_backend *, int, char **); | |
| static int svr_cmd_deletebreakpoint(dbg_backend *, int, char **); | |
| static int svr_cmd_enablebreakpoint(dbg_backend *, int, char **); | |
| static int svr_cmd_disablebreakpoint(dbg_backend *, int, char **); | |
| static int svr_cmd_conditionbreakpoint(dbg_backend *, int, char **); | |
| static int svr_cmd_breakpointafter(dbg_backend *, int, char **); | |
| static int svr_cmd_setwatchpoint(dbg_backend *, int, char **); | |
| static int svr_cmd_go(dbg_backend *, int, char **); | |
| static int svr_cmd_step(dbg_backend *, int, char **); | |
| static int svr_cmd_terminate(dbg_backend *, int, char **); | |
| static int svr_cmd_suspend(dbg_backend *, int, char **); | |
| static int svr_cmd_liststackframes(dbg_backend *, int, char **); | |
| static int svr_cmd_setcurrentstackframe(dbg_backend *, int, char **); | |
| static int svr_cmd_evaluateexpression(dbg_backend *, int, char **); | |
| static int svr_cmd_gettype(dbg_backend *, int, char **); | |
| static int svr_cmd_listlocalvariables(dbg_backend *, int, char **); | |
| static int svr_cmd_listarguments(dbg_backend *, int, char **); | |
| static int svr_cmd_listglobalvariables(dbg_backend *, int, char **); | |
| static int svr_cmd_listinfothreads(dbg_backend *, int, char **); | |
| static int svr_cmd_setthreadselect(dbg_backend *, int, char **); | |
| static int svr_cmd_stackinfodepth(dbg_backend *, int, char **); | |
| static int svr_cmd_datareadmemory(dbg_backend *, int, char **); | |
| static int svr_cmd_datawritememory(dbg_backend *, int, char **); | |
| static int svr_cmd_listsignals(dbg_backend *, int, char **); | |
| static int svr_cmd_clihandle(dbg_backend *, int, char **); | |
| static int svr_cmd_quit(dbg_backend *, int, char **); | |
| static int svr_cmd_evaluatepartialexpression(dbg_backend *, int, char **); | |
| static int svr_cmd_deletepartialexpression(dbg_backend *, int, char **); | |
| static svr_cmd svr_cmd_tab[] = | |
| { | |
| /* DBG_QUIT_CMD */ svr_cmd_quit, | |
| /* DBG_STARTSESSION_CMD */ svr_cmd_start_session, | |
| /* DBG_SETLINEBREAKPOINT_CMD */ svr_cmd_setlinebreakpoint, | |
| /* DBG_SETFUNCBREAKPOINT_CMD */ svr_cmd_setfuncbreakpoint, | |
| /* DBG_DELETEBREAKPOINT_CMD */ svr_cmd_deletebreakpoint, | |
| /* DBG_ENABLEBREAKPOINT_CMD */ svr_cmd_enablebreakpoint, | |
| /* DBG_DISABLEBREAKPOINT_CMD */ svr_cmd_disablebreakpoint, | |
| /* DBG_CONDITIONBREAKPOINT_CMD */ svr_cmd_conditionbreakpoint, | |
| /* DBG_BREAKPOINTAFTER_CMD */ svr_cmd_breakpointafter, | |
| /* DBG_SETWATCHPOINT_CMD */ svr_cmd_setwatchpoint, | |
| /* DBG_GO_CMD */ svr_cmd_go, | |
| /* DBG_STEP_CMD */ svr_cmd_step, | |
| /* DBG_TERMINATE_CMD */ svr_cmd_terminate, | |
| /* DBG_SUSPEND_CMD */ svr_cmd_suspend, | |
| /* DBG_LISTSTACKFRAMES_CMD */ svr_cmd_liststackframes, | |
| /* DBG_SETCURRENTSTACKFRAME_CMD */ svr_cmd_setcurrentstackframe, | |
| /* DBG_EVALUATEEXPRESSION_CMD */ svr_cmd_evaluateexpression, | |
| /* DBG_GETTYPE_CMD */ svr_cmd_gettype, | |
| /* DBG_LISTLOCALVARIABLES_CMD */ svr_cmd_listlocalvariables, | |
| /* DBG_LISTARGUMENTS_CMD */ svr_cmd_listarguments, | |
| /* DBG_LISTGLOBALVARIABLES_CMD */ svr_cmd_listglobalvariables, | |
| /* DBG_LISTINFOTHREADS_CMD */ svr_cmd_listinfothreads, | |
| /* DBG_SETTHREADSELECT_CMD */ svr_cmd_setthreadselect, | |
| /* DBG_STACKINFODEPTH_CMD */ svr_cmd_stackinfodepth, | |
| /* DBG_DATAREADMEMORY_CMD */ svr_cmd_datareadmemory, | |
| /* DBG_DATAWRITEMEMORY_CMD */ svr_cmd_datawritememory, | |
| /* DBG_LISTSIGNALS_CMD */ svr_cmd_listsignals, | |
| /* DBG_SIGNALINFO_CMD */ NULL, | |
| /* DBG_CLIHANDLE_CMD */ svr_cmd_clihandle, | |
| /* DBG_DATAEVALUATEEXPRESSION_CMD */ NULL, | |
| /* DBG_EVALUATEPARTIALEXPRESSION_CMD */ svr_cmd_evaluatepartialexpression, | |
| /* DBG_DELETEPARTIALEXPRESSION_CMD */ svr_cmd_deletepartialexpression, | |
| }; | |
| static int svr_res; | |
| static void (*event_callback)(dbg_event *, int); | |
| static int event_data; | |
| static char ** svr_env; | |
| static int svr_last_tid; | |
| static int svr_state; | |
| static void | |
| svr_event_callback(dbg_event *e) | |
| { | |
| e->trans_id = svr_last_tid; | |
| event_callback(e, event_data); | |
| } | |
| int | |
| svr_isshutdown(void) | |
| { | |
| if (svr_state == SVR_SHUTDOWN_STARTED) { | |
| svr_state = SVR_SHUTDOWN_COMPLETED; | |
| return 0; | |
| } | |
| return (svr_state == SVR_SHUTDOWN_COMPLETED) ? 1 : 0; | |
| } | |
| int | |
| svr_init(dbg_backend *db, void (*cb)(dbg_event *, int)) | |
| { | |
| event_callback = cb; | |
| svr_env = NULL; | |
| svr_last_tid = 0; | |
| svr_state = SVR_RUNNING; | |
| return db->db_funcs->init(svr_event_callback); | |
| } | |
| int | |
| svr_shutdown(dbg_backend *db) | |
| { | |
| if (svr_state == SVR_RUNNING) { | |
| svr_state = SVR_SHUTDOWN_STARTED; | |
| return db->db_funcs->quit(); | |
| } | |
| return 0; | |
| } | |
| int | |
| svr_dispatch(dbg_backend *db, unsigned char *buf, int len, int data) | |
| { | |
| int idx; | |
| proxy_msg * msg; | |
| svr_cmd cmd; | |
| event_data = data; | |
| if (proxy_deserialize_msg(buf, len, &msg) < 0) { | |
| svr_res = DBGRES_ERR; | |
| DbgSetError(DBGERR_DEBUGGER, "bad debug message format"); | |
| return 0; | |
| } | |
| idx = msg->msg_id - DBG_CMD_BASE; | |
| if (idx >= 0 && idx < sizeof(svr_cmd_tab)/sizeof(svr_cmd)) { | |
| svr_last_tid = msg->trans_id; | |
| cmd = svr_cmd_tab[idx]; | |
| if (cmd != NULL) { | |
| svr_res = cmd(db, msg->num_args, msg->args); | |
| } | |
| } else { | |
| svr_res = DBGRES_ERR; | |
| DbgSetError(DBGERR_DEBUGGER, "Unknown command"); | |
| } | |
| free_proxy_msg(msg); | |
| return 0; | |
| } | |
| int | |
| svr_progress(dbg_backend *db) | |
| { | |
| dbg_event * e; | |
| if (svr_res != DBGRES_OK) { | |
| e = DbgErrorEvent(DbgGetError(), DbgGetErrorStr()); | |
| svr_event_callback(e); | |
| FreeDbgEvent(e); | |
| svr_res = DBGRES_OK; | |
| return 0; | |
| } | |
| db->db_funcs->progress(); | |
| return 0; | |
| } | |
| int | |
| svr_cmd_suspend(dbg_backend *db, int nargs, char **args) | |
| { | |
| return db->db_funcs->interrupt(); | |
| } | |
| static int | |
| svr_cmd_start_session(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 4) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->start_session(db->db_exe_path, args[1], args[2], args[3], &args[4], svr_env, strtol(args[0], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_setlinebreakpoint(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 8) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->setlinebreakpoint((int)strtol(args[0], NULL, 10), (int)strtol(args[1], NULL, 10), (int)strtol(args[2], NULL, 10), args[3], (int)strtol(args[4], NULL, 10), args[5], (int)strtol(args[6], NULL, 10), (int)strtol(args[7], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_setfuncbreakpoint(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 8) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->setfuncbreakpoint((int)strtol(args[0], NULL, 10), (int)strtol(args[1], NULL, 10), (int)strtol(args[2], NULL, 10), args[3], args[4], args[5], (int)strtol(args[6], NULL, 10), (int)strtol(args[7], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_deletebreakpoint(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->deletebreakpoint((int)strtol(args[0], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_enablebreakpoint(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->enablebreakpoint((int)strtol(args[0], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_disablebreakpoint(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->disablebreakpoint((int)strtol(args[0], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_conditionbreakpoint(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 2) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->conditionbreakpoint((int)strtol(args[0], NULL, 10), args[1]); | |
| } | |
| static int | |
| svr_cmd_breakpointafter(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 2) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->breakpointafter((int)strtol(args[0], NULL, 10), (int)strtol(args[1], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_setwatchpoint(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 6) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->setwatchpoint((int)strtol(args[0], NULL, 10), args[1], (int)strtol(args[2], NULL, 10), (int)strtol(args[3], NULL, 10), args[4], (int)strtol(args[5], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_go(dbg_backend *db, int nargs, char **args) | |
| { | |
| return db->db_funcs->go(); | |
| } | |
| static int | |
| svr_cmd_step(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 2) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->step((int)strtol(args[0], NULL, 10), (int)strtol(args[1], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_terminate(dbg_backend *db, int nargs, char **args) | |
| { | |
| return db->db_funcs->terminate(); | |
| } | |
| static int | |
| svr_cmd_liststackframes(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 2) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->liststackframes((int)strtol(args[0], NULL, 10), (int)strtol(args[1], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_setcurrentstackframe(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->setcurrentstackframe((int)strtol(args[0], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_evaluateexpression(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->evaluateexpression(args[0]); | |
| } | |
| static int | |
| svr_cmd_gettype(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->gettype(args[0]); | |
| } | |
| static int | |
| svr_cmd_listlocalvariables(dbg_backend *db, int nargs, char **args) | |
| { | |
| return db->db_funcs->listlocalvariables(); | |
| } | |
| static int | |
| svr_cmd_listarguments(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 2) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->listarguments((int)strtol(args[0], NULL, 10), (int)strtol(args[1], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_listglobalvariables(dbg_backend *db, int nargs, char **args) | |
| { | |
| return db->db_funcs->listglobalvariables(); | |
| } | |
| static int | |
| svr_cmd_listinfothreads(dbg_backend *db, int nargs, char **args) | |
| { | |
| return db->db_funcs->listinfothreads(); | |
| } | |
| static int | |
| svr_cmd_setthreadselect(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->setthreadselect((int)strtol(args[0], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_stackinfodepth(dbg_backend *db, int nargs, char **args) { | |
| return db->db_funcs->stackinfodepth(); | |
| } | |
| static int | |
| svr_cmd_datareadmemory(dbg_backend *db, int nargs, char **args) { | |
| if (nargs < 7) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->datareadmemory(strtol(args[0], NULL, 10), args[1], args[2], (int)strtol(args[3], NULL, 10), (int)strtol(args[4], NULL, 10), (int)strtol(args[5], NULL, 10), args[6]); | |
| } | |
| static int | |
| svr_cmd_datawritememory(dbg_backend *db, int nargs, char **args) { | |
| if (nargs < 5) { | |
| } | |
| return db->db_funcs->datawritememory(strtol(args[0], NULL, 10), args[1], args[2], (int)strtol(args[3], NULL, 10), args[4]); | |
| } | |
| static int | |
| svr_cmd_listsignals(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| } | |
| return db->db_funcs->listsignals(args[0]); | |
| } | |
| #if 0 | |
| static int | |
| svr_cmd_signalinfo(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->signalinfo(args[0]); | |
| } | |
| #endif | |
| static int | |
| svr_cmd_clihandle(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->clihandle(args[0]); | |
| } | |
| static int | |
| svr_cmd_quit(dbg_backend *db, int nargs, char **args) | |
| { | |
| return svr_shutdown(db); | |
| } | |
| static int | |
| svr_cmd_evaluatepartialexpression(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 4) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->evaluatepartialexpression(args[0], args[1], (int)strtol(args[2], NULL, 10), (int)strtol(args[3], NULL, 10)); | |
| } | |
| static int | |
| svr_cmd_deletepartialexpression(dbg_backend *db, int nargs, char **args) | |
| { | |
| if (nargs < 1) { | |
| DbgSetError(DBGERR_DEBUGGER, "not enough arguments for debug cmd"); | |
| return DBGRES_ERR; | |
| } | |
| return db->db_funcs->deletepartialexpression(args[0]); | |
| } |