server: add support for pipes
-p/--pipe is now deprecated. Use '-c "gdb_port pipe;log_output openocd.log"' instead. Warning logged. Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
This commit is contained in:
parent
6c137a2fc0
commit
50d5441e2a
|
@ -574,7 +574,6 @@ bash$ openocd --help
|
|||
--debug | -d set debug level <0-3>
|
||||
--log_output | -l redirect log output to file <name>
|
||||
--command | -c run <command>
|
||||
--pipe | -p use pipes when talking to gdb
|
||||
@end verbatim
|
||||
|
||||
If you don't give any @option{-f} or @option{-c} options,
|
||||
|
@ -7052,11 +7051,12 @@ This would cause GDB to connect to the gdbserver on the local pc using port 3333
|
|||
@item
|
||||
A pipe connection is typically started as follows:
|
||||
@example
|
||||
target remote | openocd --pipe
|
||||
target remote | openocd -c "gdb_port pipe; log_output openocd.log"
|
||||
@end example
|
||||
This would cause GDB to run OpenOCD and communicate using pipes (stdin/stdout).
|
||||
Using this method has the advantage of GDB starting/stopping OpenOCD for the debug
|
||||
session.
|
||||
session. log_output sends the log output to a file to ensure that the pipe is
|
||||
not saturated when using higher debug level outputs.
|
||||
@end enumerate
|
||||
|
||||
To list the available OpenOCD commands type @command{monitor help} on the
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007-2010 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
@ -177,13 +177,9 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
|
|||
add_config_command(optarg);
|
||||
}
|
||||
break;
|
||||
case 'p': /* --pipe | -p */
|
||||
#if BUILD_ECOSBOARD == 1
|
||||
/* pipes unsupported on hosted platforms */
|
||||
LOG_WARNING("pipes not supported on this platform");
|
||||
#else
|
||||
server_use_pipes = 1;
|
||||
#endif
|
||||
case 'p':
|
||||
LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; log_output openocd.log\"' instead.");
|
||||
add_config_command("gdb_port pipe; log_output openocd.log");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +194,6 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
|
|||
LOG_OUTPUT("--debug | -d\tset debug level <0-3>\n");
|
||||
LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
|
||||
LOG_OUTPUT("--command | -c\trun <command>\n");
|
||||
LOG_OUTPUT("--pipe | -p\tuse pipes for gdb communication\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
|
|
@ -2387,42 +2387,22 @@ static int gdb_input(struct connection *connection)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int gdb_target_start(struct target *target, uint16_t port)
|
||||
static int gdb_target_start(struct target *target, const char *port)
|
||||
{
|
||||
bool use_pipes = 0 == port;
|
||||
struct gdb_service *gdb_service = malloc(sizeof(struct gdb_service));
|
||||
if (NULL == gdb_service)
|
||||
return -ENOMEM;
|
||||
|
||||
gdb_service->target = target;
|
||||
|
||||
add_service("gdb", use_pipes ? CONNECTION_PIPE : CONNECTION_TCP,
|
||||
return add_service("gdb",
|
||||
port, 1, &gdb_new_connection, &gdb_input,
|
||||
&gdb_connection_closed, gdb_service);
|
||||
|
||||
const char *name = target_name(target);
|
||||
if (use_pipes)
|
||||
LOG_DEBUG("gdb service for target '%s' using pipes", name);
|
||||
else
|
||||
LOG_DEBUG("gdb service for target '%s' on TCP port %u", name, port);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int gdb_target_add_one(struct target *target)
|
||||
{
|
||||
long portnumber_parsed;
|
||||
/* If we can parse the port number
|
||||
* then we increment the port number for the next target.
|
||||
*/
|
||||
char *end_parse;
|
||||
portnumber_parsed = strtol(gdb_port_next, &end_parse, 0);
|
||||
if (!*end_parse)
|
||||
{
|
||||
LOG_ERROR("Illegal port number");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
int retval = gdb_target_start(target, portnumber_parsed);
|
||||
int retval = gdb_target_start(target, gdb_port_next);
|
||||
if (retval == ERROR_OK)
|
||||
{
|
||||
long portnumber;
|
||||
|
|
|
@ -45,9 +45,6 @@ static struct service *services = NULL;
|
|||
/* shutdown_openocd == 1: exit the main event loop, and quit the debugger */
|
||||
static int shutdown_openocd = 0;
|
||||
|
||||
/* set when using pipes rather than tcp */
|
||||
int server_use_pipes = 0;
|
||||
|
||||
static int add_connection(struct service *service, struct command_context *cmd_ctx)
|
||||
{
|
||||
socklen_t address_size;
|
||||
|
@ -80,7 +77,7 @@ static int add_connection(struct service *service, struct command_context *cmd_c
|
|||
(char *)&flag, /* the cast is historical cruft */
|
||||
sizeof(int)); /* length of option value */
|
||||
|
||||
LOG_INFO("accepting '%s' connection from %i", service->name, service->port);
|
||||
LOG_INFO("accepting '%s' connection from %s", service->name, service->port);
|
||||
if ((retval = service->new_connection(c)) != ERROR_OK)
|
||||
{
|
||||
close_socket(c->fd);
|
||||
|
@ -88,8 +85,7 @@ static int add_connection(struct service *service, struct command_context *cmd_c
|
|||
free(c);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
else if (service->type == CONNECTION_PIPE)
|
||||
} else if (service->type == CONNECTION_STDINOUT)
|
||||
{
|
||||
c->fd = service->fd;
|
||||
c->fd_out = fileno(stdout);
|
||||
|
@ -97,10 +93,29 @@ static int add_connection(struct service *service, struct command_context *cmd_c
|
|||
/* do not check for new connections again on stdin */
|
||||
service->fd = -1;
|
||||
|
||||
LOG_INFO("accepting '%s' connection from pipe", service->name);
|
||||
if ((retval = service->new_connection(c)) != ERROR_OK)
|
||||
{
|
||||
LOG_ERROR("attempted '%s' connection rejected", service->name);
|
||||
free(c);
|
||||
return retval;
|
||||
}
|
||||
} else if (service->type == CONNECTION_PIPE)
|
||||
{
|
||||
c->fd = service->fd;
|
||||
/* do not check for new connections again on stdin */
|
||||
service->fd = -1;
|
||||
|
||||
LOG_INFO("accepting '%s' connection from pipe", service->name);
|
||||
char * out_file = alloc_printf("%so", service->port);
|
||||
c->fd_out = open(out_file, O_WRONLY);
|
||||
free(out_file);
|
||||
if (c->fd_out == -1)
|
||||
{
|
||||
LOG_ERROR("could not open %s", service->port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port);
|
||||
if ((retval = service->new_connection(c)) != ERROR_OK)
|
||||
{
|
||||
LOG_ERROR("attempted '%s' connection rejected", service->name);
|
||||
|
@ -130,7 +145,14 @@ static int remove_connection(struct service *service, struct connection *connect
|
|||
{
|
||||
service->connection_closed(c);
|
||||
if (service->type == CONNECTION_TCP)
|
||||
{
|
||||
close_socket(c->fd);
|
||||
} else if (service->type == CONNECTION_PIPE)
|
||||
{
|
||||
/* The service will listen to the pipe again */
|
||||
c->service->fd = c->fd;
|
||||
}
|
||||
|
||||
command_done(c->cmd_ctx);
|
||||
|
||||
/* delete connection */
|
||||
|
@ -148,7 +170,8 @@ static int remove_connection(struct service *service, struct connection *connect
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int add_service(char *name, enum connection_type type, unsigned short port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv)
|
||||
/* FIX! make service return error instead of invoking exit() */
|
||||
int add_service(char *name, const char *port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv)
|
||||
{
|
||||
struct service *c, **p;
|
||||
int so_reuseaddr_option = 1;
|
||||
|
@ -156,9 +179,8 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
|
|||
c = malloc(sizeof(struct service));
|
||||
|
||||
c->name = strdup(name);
|
||||
c->type = type;
|
||||
c->port = port;
|
||||
c->max_connections = max_connections;
|
||||
c->port = strdup(port);
|
||||
c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */
|
||||
c->fd = -1;
|
||||
c->connections = NULL;
|
||||
c->new_connection = new_connection_handler;
|
||||
|
@ -166,9 +188,28 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
|
|||
c->connection_closed = connection_closed_handler;
|
||||
c->priv = priv;
|
||||
c->next = NULL;
|
||||
|
||||
if (type == CONNECTION_TCP)
|
||||
long portnumber;
|
||||
if (strcmp(c->port, "pipe") == 0)
|
||||
{
|
||||
c->type = CONNECTION_STDINOUT;
|
||||
} else
|
||||
{
|
||||
char *end;
|
||||
strtol(c->port, &end, 0);
|
||||
if (!*end && (parse_long(c->port, &portnumber) == ERROR_OK))
|
||||
{
|
||||
c->portnumber = portnumber;
|
||||
c->type = CONNECTION_TCP;
|
||||
} else
|
||||
{
|
||||
c->type = CONNECTION_PIPE;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->type == CONNECTION_TCP)
|
||||
{
|
||||
c->max_connections = max_connections;
|
||||
|
||||
if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
LOG_ERROR("error creating socket: %s", strerror(errno));
|
||||
|
@ -182,7 +223,7 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
|
|||
memset(&c->sin, 0, sizeof(c->sin));
|
||||
c->sin.sin_family = AF_INET;
|
||||
c->sin.sin_addr.s_addr = INADDR_ANY;
|
||||
c->sin.sin_port = htons(port);
|
||||
c->sin.sin_port = htons(c->portnumber);
|
||||
|
||||
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1)
|
||||
{
|
||||
|
@ -209,7 +250,7 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
|
|||
exit(-1);
|
||||
}
|
||||
}
|
||||
else if (type == CONNECTION_PIPE)
|
||||
else if (c->type == CONNECTION_STDINOUT)
|
||||
{
|
||||
c->fd = fileno(stdin);
|
||||
|
||||
|
@ -225,10 +266,15 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
|
|||
socket_nonblock(c->fd);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
else if (c->type == CONNECTION_PIPE)
|
||||
{
|
||||
LOG_ERROR("unknown connection type: %d", type);
|
||||
exit(1);
|
||||
/* Pipe we're reading from */
|
||||
c->fd = open(c->port, O_RDONLY | O_NONBLOCK);
|
||||
if (c->fd == -1)
|
||||
{
|
||||
LOG_ERROR("could not open %s", c->port);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* add to the end of linked list */
|
||||
|
@ -238,29 +284,6 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int add_service_pipe(char *name, const char *port, int max_connections,
|
||||
new_connection_handler_t new_connection_handler, input_handler_t input_handler,
|
||||
connection_closed_handler_t connection_closed_handler, void *priv)
|
||||
{
|
||||
enum connection_type type = CONNECTION_TCP;
|
||||
long portnumber;
|
||||
char *end;
|
||||
strtol(port, &end, 0);
|
||||
if (!*end)
|
||||
{
|
||||
if ((parse_long(port, &portnumber) == ERROR_OK) && (portnumber == 0))
|
||||
{
|
||||
type = CONNECTION_PIPE;
|
||||
}
|
||||
} else
|
||||
{
|
||||
LOG_ERROR("Illegal port number %s", port);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return add_service(name, type, portnumber, max_connections, new_connection_handler,
|
||||
input_handler, connection_closed_handler, priv);
|
||||
}
|
||||
|
||||
static int remove_services(void)
|
||||
{
|
||||
struct service *c = services;
|
||||
|
@ -278,6 +301,8 @@ static int remove_services(void)
|
|||
if (c->fd != -1)
|
||||
close(c->fd);
|
||||
}
|
||||
if (c->port)
|
||||
free((void *)c->port);
|
||||
|
||||
if (c->priv)
|
||||
free(c->priv);
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
enum connection_type
|
||||
{
|
||||
CONNECTION_TCP,
|
||||
CONNECTION_PIPE
|
||||
CONNECTION_PIPE,
|
||||
CONNECTION_STDINOUT
|
||||
};
|
||||
|
||||
struct connection
|
||||
|
@ -58,7 +59,8 @@ struct service
|
|||
{
|
||||
char *name;
|
||||
enum connection_type type;
|
||||
unsigned short port;
|
||||
const char *port;
|
||||
unsigned short portnumber;
|
||||
int fd;
|
||||
struct sockaddr_in sin;
|
||||
int max_connections;
|
||||
|
@ -70,12 +72,7 @@ struct service
|
|||
struct service *next;
|
||||
};
|
||||
|
||||
int add_service(char *name, enum connection_type type, unsigned short port,
|
||||
int max_connections, new_connection_handler_t new_connection_handler,
|
||||
input_handler_t in_handler, connection_closed_handler_t close_handler,
|
||||
void *priv);
|
||||
|
||||
int add_service_pipe(char *name, const char *port,
|
||||
int add_service(char *name, const char *port,
|
||||
int max_connections, new_connection_handler_t new_connection_handler,
|
||||
input_handler_t in_handler, connection_closed_handler_t close_handler,
|
||||
void *priv);
|
||||
|
@ -115,8 +112,6 @@ SERVER_PIPE_COMMAND();
|
|||
|
||||
SERVER_PORT_COMMAND();
|
||||
|
||||
extern int server_use_pipes;
|
||||
|
||||
#define ERROR_SERVER_REMOTE_CLOSED (-400)
|
||||
#define ERROR_CONNECTION_REJECTED (-401)
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ int tcl_init(void)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
return add_service_pipe("tcl", tcl_port, 1,
|
||||
return add_service("tcl", tcl_port, 1,
|
||||
&tcl_new_connection, &tcl_input,
|
||||
&tcl_closed, NULL);
|
||||
}
|
||||
|
|
|
@ -592,9 +592,7 @@ int telnet_init(char *banner)
|
|||
|
||||
telnet_service->banner = banner;
|
||||
|
||||
add_service_pipe("telnet", telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service);
|
||||
|
||||
return ERROR_OK;
|
||||
return add_service("telnet", telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service);
|
||||
}
|
||||
|
||||
/* daemon configuration command telnet_port */
|
||||
|
|
Loading…
Reference in New Issue