blob: 7d252edefb15612370fcab0e5f06c5924c3b102b [file]
/******************************************************************************
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "sdm.h"
#include "dbg.h"
#include "dbg_proxy.h"
#include "session.h"
#include "proxy.h"
#include "proxy_event.h"
#include "bitset.h"
#include "handler.h"
/*
* The TIMEOUT determines how often the debugger polls progress routines.
* Too often and it uses too much CPU, too few and things will slow down...
*/
#define CLIENT_TIMEOUT 50000
#define SERVER_TIMEOUT 50000
static sdm_idset tmp_idset;
static bitset * tmp_bitset;
sdm_idset
bitset_to_idset(bitset *b)
{
int bit;
sdm_set_clear(tmp_idset);
for (bit = 0; bit < bitset_size(b); bit++) {
if (bitset_test(b, bit)) {
sdm_set_add_element(tmp_idset, bit);
}
}
return tmp_idset;
}
bitset *
idset_to_bitset(sdm_idset ids)
{
sdm_id id;
bitset_clear(tmp_bitset);
for (id = sdm_set_first(ids); !sdm_set_done(ids); id = sdm_set_next(ids)) {
bitset_set(tmp_bitset, id);
}
return tmp_bitset;
}
static int
session_event_handler(sdm_message msg, void *data)
{
int len;
unsigned char * buf;
dbg_event * ev;
proxy_msg * pmsg;
session * s = (session *)data;
sdm_message_get_payload(msg, &buf, &len);
if (proxy_deserialize_msg(buf, len, &pmsg) < 0) {
fprintf(stderr, "could not deserialize message");
sdm_message_free(msg);
return -1;
}
if (DbgDeserializeEvent(pmsg->msg_id, pmsg->num_args, pmsg->args, &ev) < 0) {
fprintf(stderr, "bad conversion to debug event");
sdm_message_free(msg);
return -1;
}
ev->procs = idset_to_bitset(sdm_message_get_source(msg));
if (s->sess_event_handler != NULL) {
s->sess_event_handler(ev, s->sess_event_data);
}
sdm_message_free(msg);
return 0;
}
static int
send_command(bitset *procs, int timeout, unsigned char *cmd, int len, void *cbdata)
{
sdm_message msg;
sdm_idset dest = bitset_to_idset(procs);
msg = sdm_message_new(cmd, len);
sdm_aggregate_set_value(sdm_message_get_aggregate(msg), SDM_AGGREGATE_TIMEOUT, timeout);
sdm_set_union(sdm_message_get_destination(msg), dest);
sdm_aggregate_message(msg, SDM_AGGREGATE_DOWNSTREAM);
sdm_message_set_send_callback(msg, sdm_message_free);
sdm_message_send(msg);
return 0;
}
/*
* Session initialization
*/
int
DbgInit(session **sess, int argc, char *argv[])
{
session * s;
*sess = s = (session *)malloc(sizeof(session));
if (sdm_init(argc, argv) < 0) {
return -1;
}
s->sess_procs = sdm_route_get_size() - 1;
tmp_idset = sdm_set_new();
tmp_bitset = bitset_new(s->sess_procs);
sdm_aggregate_set_completion_callback(session_event_handler, (void *)s);
return 0;
}
int
DbgConnect(session *s)
{
return proxy_clnt_connect(s->sess_proxy);
}
int
DbgCreate(session *s)
{
return proxy_clnt_create(s->sess_proxy);
}
int
DbgStartSession(session *s, char *exe, char *path, char *args)
{
int res;
int len;
unsigned char * buf;
bitset * procs = bitset_new(s->sess_procs);
proxy_msg * msg = new_proxy_msg(DBG_STARTSESSION_CMD, 0);
proxy_msg_add_int(msg, SERVER_TIMEOUT);
proxy_msg_add_string(msg, exe);
proxy_msg_add_string(msg, path);
proxy_msg_add_string(msg, args);
proxy_serialize_msg(msg, &buf, &len);
/*
* Create a bitset containing all processes
*/
bitset_invert(procs);
res = send_command(procs, DBG_EV_WAITALL, buf, len, NULL);
free_proxy_msg(msg);
bitset_free(procs);
return res;
}
/*
* Breakpoint operations
*/
int
DbgSetLineBreakpoint(session *s, bitset *set, int bpid, char *file, int line)
{
int res;
int len;
unsigned char * buf;
proxy_msg * msg = new_proxy_msg(DBG_SETLINEBREAKPOINT_CMD, 0);
proxy_msg_add_int(msg, bpid);
proxy_msg_add_string(msg, file);
proxy_msg_add_int(msg, line);
proxy_serialize_msg(msg, &buf, &len);
res = send_command(set, DBG_EV_WAITALL, buf, len, NULL);
free_proxy_msg(msg);
return res;
}
int
DbgSetFuncBreakpoint(session *s, bitset *set, int bpid, char *file, char *func)
{
proxy_msg * msg = new_proxy_msg(DBG_SETFUNCBREAKPOINT_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, bpid);
proxy_msg_add_string(msg, file);
proxy_msg_add_string(msg, func);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgDeleteBreakpoint(session *s, bitset *set, int bpid)
{
proxy_msg * msg = new_proxy_msg(DBG_DELETEBREAKPOINT_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, bpid);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgEnableBreakpoint(session *s, bitset *set, int bpid)
{
proxy_msg * msg = new_proxy_msg(DBG_ENABLEBREAKPOINT_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, bpid);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgDisableBreakpoint(session *s, bitset *set, int bpid)
{
proxy_msg * msg = new_proxy_msg(DBG_DISABLEBREAKPOINT_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, bpid);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgConditionBreakpoint(session *s, bitset *set, int bpid, char *expr)
{
proxy_msg * msg = new_proxy_msg(DBG_CONDITIONBREAKPOINT_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, bpid);
proxy_msg_add_string(msg, expr);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgBreakpointAfter(session *s, bitset *set, int bpid, int icount)
{
proxy_msg * msg = new_proxy_msg(DBG_BREAKPOINTAFTER_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, bpid);
proxy_msg_add_int(msg, icount);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgSetWatchpoint(session *s, bitset *set, int bpid, char *expr, int access, int read, char *condition, int icount)
{
proxy_msg * msg = new_proxy_msg(DBG_SETWATCHPOINT_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, bpid);
proxy_msg_add_string(msg, expr);
proxy_msg_add_int(msg, access);
proxy_msg_add_int(msg, read);
proxy_msg_add_string(msg, condition);
proxy_msg_add_int(msg, icount);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
/*
* Process control operations
*/
int
DbgGo(session *s, bitset *set)
{
int res;
int len;
unsigned char * buf;
proxy_msg * msg = new_proxy_msg(DBG_GO_CMD, 0);
proxy_serialize_msg(msg, &buf, &len);
res = send_command(set, DBG_EV_WAITSOME, buf, len, NULL);
free_proxy_msg(msg);
return res;
}
int
DbgStep(session *s, bitset *set, int count, int type)
{
int res;
int len;
unsigned char * buf;
proxy_msg * msg = new_proxy_msg(DBG_STEP_CMD, 0);
proxy_msg_add_int(msg, count);
proxy_msg_add_int(msg, type);
proxy_serialize_msg(msg, &buf, &len);
res = send_command(set, DBG_EV_WAITSOME, buf, len, NULL);
free_proxy_msg(msg);
return res;
}
int
DbgTerminate(session *s, bitset *set)
{
proxy_msg * msg = new_proxy_msg(DBG_TERMINATE_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgSuspend(session *s, bitset *set)
{
proxy_msg * msg = new_proxy_msg(DBG_SUSPEND_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
/*
* Stack frame operations
*/
int
DbgListStackframes(session *s, bitset *set, int low, int depth)
{
int res;
int len;
unsigned char * buf;
proxy_msg * msg = new_proxy_msg(DBG_LISTSTACKFRAMES_CMD, 0);
proxy_msg_add_int(msg, low);
proxy_msg_add_int(msg, depth);
proxy_serialize_msg(msg, &buf, &len);
res = send_command(set, DBG_EV_WAITALL, buf, len, NULL);
return 0;
}
int
DbgSetCurrentStackframe(session *s, bitset *set, int level)
{
proxy_msg * msg = new_proxy_msg(DBG_SETCURRENTSTACKFRAME_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, level);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
/*
* Expression/variable operations
*/
int
DbgEvaluateExpression(session *s, bitset *set, char *exp)
{
int res;
int len;
unsigned char * buf;
proxy_msg * msg = new_proxy_msg(DBG_EVALUATEEXPRESSION_CMD, 0);
proxy_msg_add_string(msg, exp);
proxy_serialize_msg(msg, &buf, &len);
res = send_command(set, DBG_EV_WAITSOME, buf, len, NULL);
free_proxy_msg(msg);
return res;
}
int
DbgGetType(session *s, bitset *set, char *exp)
{
proxy_msg * msg = new_proxy_msg(DBG_GETTYPE_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_string(msg, exp);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgListLocalVariables(session *s, bitset *set)
{
proxy_msg * msg = new_proxy_msg(DBG_LISTLOCALVARIABLES_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgListArguments(session *s, bitset *set, int low, int high)
{
proxy_msg * msg = new_proxy_msg(DBG_LISTARGUMENTS_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, low);
proxy_msg_add_int(msg, high);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgListGlobalVariables(session *s, bitset *set)
{
proxy_msg * msg = new_proxy_msg(DBG_LISTGLOBALVARIABLES_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgListInfoThreads(session *s, bitset *set)
{
proxy_msg * msg = new_proxy_msg(DBG_LISTINFOTHREADS_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgSetThreadSelect(session *s, bitset *set, int threadNum)
{
proxy_msg * msg = new_proxy_msg(DBG_SETTHREADSELECT_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, threadNum);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgStackInfoDepth(session *s, bitset *set)
{
proxy_msg * msg = new_proxy_msg(DBG_STACKINFODEPTH_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgDataReadMemory(session *s, bitset *set, long offset, char *address, char *format, int wordSize, int rows, int cols, char *asChar)
{
proxy_msg * msg = new_proxy_msg(DBG_DATAREADMEMORY_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, offset);
proxy_msg_add_string(msg, address);
proxy_msg_add_string(msg, format);
proxy_msg_add_int(msg, wordSize);
proxy_msg_add_int(msg, rows);
proxy_msg_add_int(msg, cols);
proxy_msg_add_string(msg, asChar);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgDataWriteMemory(session *s, bitset *set, long offset, char *address, char *format, int wordSize, char *value)
{
proxy_msg * msg = new_proxy_msg(DBG_DATAWRITEMEMORY_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_int(msg, offset);
proxy_msg_add_string(msg, address);
proxy_msg_add_string(msg, format);
proxy_msg_add_int(msg, wordSize);
proxy_msg_add_string(msg, value);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgListSignals(session *s, bitset *set, char *name)
{
proxy_msg * msg = new_proxy_msg(DBG_LISTSIGNALS_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_string(msg, name);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgCLIHandle(session *s, bitset *set, char *arg)
{
proxy_msg * msg = new_proxy_msg(DBG_CLIHANDLE_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_string(msg, arg);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgQuit(session *s)
{
int res;
int len;
unsigned char * buf;
bitset * procs = bitset_new(s->sess_procs);
proxy_msg * msg = new_proxy_msg(DBG_QUIT_CMD, 0);
proxy_serialize_msg(msg, &buf, &len);
bitset_invert(procs);
res = send_command(procs, DBG_EV_WAITALL, buf, len, NULL);
free_proxy_msg(msg);
bitset_free(procs);
return res;
}
int
DbgEvaluatePartialExpression(session *s, bitset *set, char *name, char *key, int listChildren, int express)
{
proxy_msg * msg = new_proxy_msg(DBG_EVALUATEPARTIALEXPRESSION_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_string(msg, name);
proxy_msg_add_string(msg, key);
proxy_msg_add_int(msg, listChildren);
proxy_msg_add_int(msg, express);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
int
DbgDeletePartialExpression(session *s, bitset *set, char *arg)
{
proxy_msg * msg = new_proxy_msg(DBG_DELETEPARTIALEXPRESSION_CMD, 0);
proxy_msg_add_bitset(msg, set);
proxy_msg_add_string(msg, arg);
proxy_clnt_queue_msg(s->sess_proxy, msg);
free_proxy_msg(msg);
return 0;
}
/*
* Event handling
*/
int
DbgProgress(session *s)
{
return sdm_progress();
}
void
DbgRegisterEventHandler(session *s, void (*event_callback)(dbg_event *, void *), void *data)
{
s->sess_event_handler = event_callback;
s->sess_event_data = data;
}
/**
* Unregister file descriptor handler
*/
void
DbgUnregisterEventHandler(session *s, void (*event_callback)(dbg_event *, void *))
{
s->sess_event_handler = NULL;
}
/**
* Register a handler for file descriptor events.
*/
void
DbgRegisterReadFileHandler(session *s, int fd, int (*file_handler)(int, void *), void *data)
{
RegisterFileHandler(fd, READ_FILE_HANDLER, file_handler, data);
}
void
DbgRegisterWriteFileHandler(session *s, int fd, int (*file_handler)(int, void *), void *data)
{
RegisterFileHandler(fd, WRITE_FILE_HANDLER, file_handler, data);
}
void
DbgRegisterExceptFileHandler(session *s, int fd, int (*file_handler)(int, void *), void *data)
{
RegisterFileHandler(fd, EXCEPT_FILE_HANDLER, file_handler, data);
}
/**
* Unregister file descriptor handler
*/
void
DbgUnregisterFileHandler(session *s, int fd)
{
UnregisterFileHandler(fd);
}