| /****************************************************************************** |
| * 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]); |
| } |