- add ability for openocd to communicate to gdb using pipes (stdin/stdout).
- this is enabled by new command line option option --pipe. git-svn-id: svn://svn.berlios.de/openocd/trunk@1242 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
parent
459d03e3bb
commit
47d0449347
|
@ -15,7 +15,7 @@
|
|||
|
||||
@itemize @bullet
|
||||
@item Copyright @copyright{} 2008 The OpenOCD Project
|
||||
@item Copyright @copyright{} 2007-2008 Spen @email{spen@@spen-soft.co.uk}
|
||||
@item Copyright @copyright{} 2007-2008 Spencer Oliver @email{spen@@spen-soft.co.uk}
|
||||
@item Copyright @copyright{} 2008 Oyvind Harboe @email{oyvind.harboe@@zylin.com}
|
||||
@item Copyright @copyright{} 2008 Duane Ellis @email{openocd@@duaneellis.com}
|
||||
@end itemize
|
||||
|
@ -411,9 +411,10 @@ 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
|
||||
|
||||
By default openocd reads the file configuration file ``openocd.cfg''
|
||||
By default OpenOCD reads the file configuration file ``openocd.cfg''
|
||||
in the current directory. To specify a different (or multiple)
|
||||
configuration file, you can use the ``-f'' option. For example:
|
||||
|
||||
|
@ -445,6 +446,9 @@ Search paths for config/script files can be added to OpenOCD by using
|
|||
the @option{-s <search>} switch. The current directory and the OpenOCD
|
||||
target library is in the search path by default.
|
||||
|
||||
For details on the @option{-p} option. @xref{Connecting to GDB}.
|
||||
Option @option{-p} is not currently supported under native win32.
|
||||
|
||||
Note! OpenOCD will launch the GDB & telnet server even if it can not
|
||||
establish a connection with the target. In general, it is possible for
|
||||
the JTAG controller to be unresponsive until the target is set up
|
||||
|
@ -455,7 +459,7 @@ correctly via e.g. GDB monitor commands in a GDB init script.
|
|||
@cindex configuration
|
||||
|
||||
@section Outline
|
||||
There are 4 basic ways of ``configurating'' openocd to run, they are:
|
||||
There are 4 basic ways of ``configurating'' OpenOCD to run, they are:
|
||||
|
||||
@enumerate
|
||||
@item A small openocd.cfg file which ``sources'' other configuration files
|
||||
|
@ -671,7 +675,7 @@ tap identifier dotted name.
|
|||
every chip. If the @t{-expected-id} is nonzero, OpenOCD attempts
|
||||
to verify the tap id number verses configuration file and may issue an
|
||||
error or warning like this. The hope is this will help pin point
|
||||
problem openocd configurations.
|
||||
problem OpenOCD configurations.
|
||||
|
||||
@example
|
||||
Info: JTAG tap: sam7x256.cpu tap/device found: 0x3f0f0f0f (Manufacturer: 0x787, Part: 0xf0f0, Version: 0x3)
|
||||
|
@ -904,7 +908,7 @@ command interpretor today (28/nov/2008) is a mixture of (newer)
|
|||
JIM-Tcl commands, and (older) the orginal command interpretor.
|
||||
|
||||
@item @b{Commands}
|
||||
@* At the openocd telnet command line (or via the GDB mon command) one
|
||||
@* At the OpenOCD telnet command line (or via the GDB mon command) one
|
||||
can type a Tcl for() loop, set variables, etc.
|
||||
|
||||
@item @b{Historical Note}
|
||||
|
@ -1145,7 +1149,7 @@ if compiled with FTD2XX support.
|
|||
@b{TODO:} Confirm the following: On windows the name needs to end with
|
||||
a ``space A''? Or not? It has to do with the FTD2xx driver. When must
|
||||
this be added and when must it not be added? Why can't the code in the
|
||||
interface or in openocd automatically add this if needed? -- Duane.
|
||||
interface or in OpenOCD automatically add this if needed? -- Duane.
|
||||
|
||||
@item @b{ft2232_serial} <@var{serial-number}>
|
||||
@cindex ft2232_serial
|
||||
|
@ -1527,7 +1531,7 @@ then ``bypass'' the tap, the tap is completely removed from the
|
|||
circuit and skipped.
|
||||
|
||||
|
||||
From OpenOCDs view point, a JTAG TAP is in one of 3 states:
|
||||
From OpenOCD's view point, a JTAG TAP is in one of 3 states:
|
||||
|
||||
@itemize @bullet
|
||||
@item @b{Enabled - Not In ByPass} and has a variable bit length
|
||||
|
@ -1640,7 +1644,7 @@ configure it like this:
|
|||
puts [format "The button is %s" $x]
|
||||
@end example
|
||||
|
||||
In OpenOCDs terms, the ``target'' is an object just like a Tcl/Tk
|
||||
In OpenOCD's terms, the ``target'' is an object just like a Tcl/Tk
|
||||
button. Commands avaialble as a ``target object'' are:
|
||||
|
||||
@comment START targetobj commands.
|
||||
|
@ -1841,7 +1845,7 @@ via the configure option or to query the target via cget.
|
|||
@item @b{-work-area-size [ADDRESS]} specify/set the work area
|
||||
@item @b{-work-area-backup [0|1]} does the work area get backed up
|
||||
@item @b{-endian [big|little]}
|
||||
@item @b{-variant [NAME]} some chips have varients openocd needs to know about
|
||||
@item @b{-variant [NAME]} some chips have varients OpenOCD needs to know about
|
||||
@item @b{-chain-position DOTTED.NAME} the tap name this target refers to.
|
||||
@end itemize
|
||||
Example:
|
||||
|
@ -1870,7 +1874,7 @@ cores.
|
|||
@* None (this is also used as the ARM946)
|
||||
@item @b{cortex_m3}
|
||||
@* use variant <@var{-variant lm3s}> when debugging luminary lm3s targets. This will cause
|
||||
openocd to use a software reset rather than asserting SRST to avoid a issue with clearing
|
||||
OpenOCD to use a software reset rather than asserting SRST to avoid a issue with clearing
|
||||
the debug registers. This is fixed in Fury Rev B, DustDevil Rev B, Tempest, these revisions will
|
||||
be detected and the normal reset behaviour used.
|
||||
@item @b{xscale}
|
||||
|
@ -1880,9 +1884,9 @@ be detected and the normal reset behaviour used.
|
|||
@item @b{mips_m4k}
|
||||
@* Use variant @option{ejtag_srst} when debugging targets that do not
|
||||
provide a functional SRST line on the EJTAG connector. This causes
|
||||
openocd to instead use an EJTAG software reset command to reset the
|
||||
OpenOCD to instead use an EJTAG software reset command to reset the
|
||||
processor. You still need to enable @option{srst} on the reset
|
||||
configuration command to enable openocd hardware reset functionality.
|
||||
configuration command to enable OpenOCD hardware reset functionality.
|
||||
@comment END varients
|
||||
@end itemize
|
||||
@section working_area - Command Removed
|
||||
|
@ -2004,7 +2008,7 @@ to a <@var{file}>.
|
|||
@end itemize
|
||||
|
||||
@section flash bank command
|
||||
The @b{flash bank} command is used to configure one or more flash chips (or banks in openocd terms)
|
||||
The @b{flash bank} command is used to configure one or more flash chips (or banks in OpenOCD terms)
|
||||
|
||||
@example
|
||||
@b{flash bank} <@var{driver}> <@var{base}> <@var{size}> <@var{chip_width}>
|
||||
|
@ -2170,7 +2174,7 @@ erase the device.
|
|||
@end itemize
|
||||
|
||||
Note: Before using the str9xpec driver here is some background info to help
|
||||
you better understand how the drivers works. Openocd has two flash drivers for
|
||||
you better understand how the drivers works. OpenOCD has two flash drivers for
|
||||
the str9.
|
||||
@enumerate
|
||||
@item
|
||||
|
@ -2793,41 +2797,52 @@ openocd -f interface/parport.cfg -f target/at91r40008.cfg -c init -c reset
|
|||
OpenOCD complies with the remote gdbserver protocol, and as such can be used
|
||||
to debug remote targets.
|
||||
|
||||
@section Connecting to gdb
|
||||
@cindex Connecting to gdb
|
||||
@section Connecting to GDB
|
||||
@cindex Connecting to GDB
|
||||
@anchor{Connecting to GDB}
|
||||
Use GDB 6.7 or newer with OpenOCD if you run into trouble. For
|
||||
instance 6.3 has a known bug where it produces bogus memory access
|
||||
errors, which has since been fixed: look up 1836 in
|
||||
@url{http://sourceware.org/cgi-bin/gnatsweb.pl?database=gdb}
|
||||
|
||||
|
||||
A connection is typically started as follows:
|
||||
@*OpenOCD can communicate with GDB in two ways:
|
||||
@enumerate
|
||||
@item
|
||||
A socket (tcp) connection is typically started as follows:
|
||||
@example
|
||||
target remote localhost:3333
|
||||
@end example
|
||||
This would cause gdb to connect to the gdbserver on the local pc using port 3333.
|
||||
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
|
||||
@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 debug session.
|
||||
@end enumerate
|
||||
|
||||
To see a list of available OpenOCD commands type @option{monitor help} on the
|
||||
gdb commandline.
|
||||
@*To see a list of available OpenOCD commands type @option{monitor help} on the
|
||||
GDB commandline.
|
||||
|
||||
OpenOCD supports the gdb @option{qSupported} packet, this enables information
|
||||
to be sent by the gdb server (openocd) to gdb. Typical information includes
|
||||
to be sent by the gdb server (OpenOCD) to GDB. Typical information includes
|
||||
packet size and device memory map.
|
||||
|
||||
Previous versions of OpenOCD required the following gdb options to increase
|
||||
the packet size and speed up gdb communication.
|
||||
Previous versions of OpenOCD required the following GDB options to increase
|
||||
the packet size and speed up GDB communication.
|
||||
@example
|
||||
set remote memory-write-packet-size 1024
|
||||
set remote memory-write-packet-size fixed
|
||||
set remote memory-read-packet-size 1024
|
||||
set remote memory-read-packet-size fixed
|
||||
@end example
|
||||
This is now handled in the @option{qSupported} PacketSize.
|
||||
This is now handled in the @option{qSupported} PacketSize and should not be required.
|
||||
|
||||
@section Programming using gdb
|
||||
@cindex Programming using gdb
|
||||
@section Programming using GDB
|
||||
@cindex Programming using GDB
|
||||
|
||||
By default the target memory map is sent to gdb, this can be disabled by
|
||||
By default the target memory map is sent to GDB, this can be disabled by
|
||||
the following OpenOCD config option:
|
||||
@example
|
||||
gdb_memory_map disable
|
||||
|
@ -2836,34 +2851,34 @@ For this to function correctly a valid flash config must also be configured
|
|||
in OpenOCD. For faster performance you should also configure a valid
|
||||
working area.
|
||||
|
||||
Informing gdb of the memory map of the target will enable gdb to protect any
|
||||
Informing GDB of the memory map of the target will enable GDB to protect any
|
||||
flash area of the target and use hardware breakpoints by default. This means
|
||||
that the OpenOCD option @option{gdb_breakpoint_override} is not required when
|
||||
using a memory map. @xref{gdb_breakpoint_override}.
|
||||
|
||||
To view the configured memory map in gdb, use the gdb command @option{info mem}
|
||||
All other unasigned addresses within gdb are treated as RAM.
|
||||
To view the configured memory map in GDB, use the gdb command @option{info mem}
|
||||
All other unasigned addresses within GDB are treated as RAM.
|
||||
|
||||
GDB 6.8 and higher set any memory area not in the memory map as inaccessible,
|
||||
this can be changed to the old behaviour by using the following gdb command.
|
||||
this can be changed to the old behaviour by using the following GDB command.
|
||||
@example
|
||||
set mem inaccessible-by-default off
|
||||
@end example
|
||||
|
||||
If @option{gdb_flash_program enable} is also used, gdb will be able to
|
||||
If @option{gdb_flash_program enable} is also used, GDB will be able to
|
||||
program any flash memory using the vFlash interface.
|
||||
|
||||
gdb will look at the target memory map when a load command is given, if any
|
||||
GDB will look at the target memory map when a load command is given, if any
|
||||
areas to be programmed lie within the target flash area the vFlash packets
|
||||
will be used.
|
||||
|
||||
If the target needs configuring before gdb programming, an event
|
||||
If the target needs configuring before GDB programming, an event
|
||||
script can be executed.
|
||||
@example
|
||||
$_TARGETNAME configure -event EVENTNAME BODY
|
||||
@end example
|
||||
|
||||
To verify any flash programming the gdb command @option{compare-sections}
|
||||
To verify any flash programming the GDB command @option{compare-sections}
|
||||
can be used.
|
||||
|
||||
@node TCL scripting API
|
||||
|
@ -3598,7 +3613,7 @@ foreach who @{A B C D E@}
|
|||
OpenOCD comes with a target configuration script library. These scripts can be
|
||||
used as-is or serve as a starting point.
|
||||
|
||||
The target library is published together with the openocd executable and
|
||||
The target library is published together with the OpenOCD executable and
|
||||
the path to the target library is in the OpenOCD script search path.
|
||||
Similarly there are example scripts for configuring the JTAG interface.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
INCLUDES = -I$(top_srcdir)/src $(all_includes) -I$(top_srcdir)/src/target
|
||||
INCLUDES = -I$(top_srcdir)/src $(all_includes) -I$(top_srcdir)/src/target -I$(top_srcdir)/src/server
|
||||
METASOURCES = AUTO
|
||||
AM_CPPFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" -DPKGLIBDIR=\"$(pkglibdir)\" @CPPFLAGS@
|
||||
noinst_LIBRARIES = libhelper.a
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "configuration.h"
|
||||
#include "time_support.h"
|
||||
#include "command.h"
|
||||
#include "server.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -108,9 +109,11 @@ static void log_puts(enum log_levels level, const char *file, int line, const ch
|
|||
#endif
|
||||
string);
|
||||
}
|
||||
else
|
||||
else if(server_use_pipes == 0)
|
||||
{
|
||||
if (strcmp(string, "\n")!=0)
|
||||
/* if we are using gdb through pipes then we do not want any output
|
||||
* to the pipe otherwise we get repeated strings */
|
||||
if (strcmp(string, "\n") != 0)
|
||||
{
|
||||
/* print human readable output - but skip empty lines */
|
||||
fprintf(log_output, "%s%s",
|
||||
|
@ -203,6 +206,18 @@ int handle_debug_level_command(struct command_context_s *cmd_ctx, char *cmd, cha
|
|||
if (debug_level > 3)
|
||||
debug_level = 3;
|
||||
|
||||
if (debug_level >= LOG_LVL_DEBUG && server_use_pipes == 1)
|
||||
{
|
||||
/* if we are enabling debug info then we need to write to a log file
|
||||
* otherwise the pipe will get full and cause issues with gdb */
|
||||
FILE* file = fopen("openocd.log", "w");
|
||||
if (file)
|
||||
{
|
||||
log_output = file;
|
||||
LOG_WARNING("enabling log output as we are using pipes");
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,10 +24,13 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "replacements.h"
|
||||
|
||||
#include "types.h"
|
||||
#include "command.h"
|
||||
#include "configuration.h"
|
||||
#include "log.h"
|
||||
#include "server.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -43,8 +46,9 @@ static struct option long_options[] =
|
|||
{"debug", optional_argument, 0, 'd'},
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"search", required_argument, 0, 's'},
|
||||
{"log_output", required_argument, 0, 'l'},
|
||||
{"log_output", required_argument, 0, 'l'},
|
||||
{"command", required_argument, 0, 'c'},
|
||||
{"pipe", no_argument, 0, 'p'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -95,7 +99,7 @@ int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[]
|
|||
/* getopt_long stores the option index here. */
|
||||
int option_index = 0;
|
||||
|
||||
c = getopt_long(argc, argv, "hvd::l:f:s:c:", long_options, &option_index);
|
||||
c = getopt_long(argc, argv, "hvd::l:f:s:c:p", long_options, &option_index);
|
||||
|
||||
/* Detect the end of the options. */
|
||||
if (c == -1)
|
||||
|
@ -140,7 +144,20 @@ int parse_cmdline_args(struct command_context_s *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
|
||||
#ifdef IS_MINGW
|
||||
/* pipes currently unsupported on win32 */
|
||||
LOG_WARNING("pipes currently unsupported on win32");
|
||||
exit(1);
|
||||
#else
|
||||
server_use_pipes = 1;
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,6 +171,7 @@ int parse_cmdline_args(struct command_context_s *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);
|
||||
}
|
||||
|
||||
|
@ -161,7 +179,7 @@ int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[]
|
|||
{
|
||||
/* Nothing to do, version gets printed automatically. */
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -169,10 +169,18 @@ int gdb_get_char(connection_t *connection, int* next_char)
|
|||
|
||||
for (;;)
|
||||
{
|
||||
retval=check_pending(connection, 1, NULL);
|
||||
if (retval!=ERROR_OK)
|
||||
return retval;
|
||||
gdb_con->buf_cnt = read_socket(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE);
|
||||
if (connection->service->type == CONNECTION_PIPE)
|
||||
{
|
||||
gdb_con->buf_cnt = read(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = check_pending(connection, 1, NULL);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
gdb_con->buf_cnt = read_socket(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
if (gdb_con->buf_cnt > 0)
|
||||
{
|
||||
break;
|
||||
|
@ -268,10 +276,21 @@ int gdb_write(connection_t *connection, void *data, int len)
|
|||
gdb_connection_t *gdb_con = connection->priv;
|
||||
if (gdb_con->closed)
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
|
||||
if (write_socket(connection->fd, data, len) == len)
|
||||
|
||||
if (connection->service->type == CONNECTION_PIPE)
|
||||
{
|
||||
return ERROR_OK;
|
||||
/* write to stdout */
|
||||
if (write(STDOUT_FILENO, data, len) == len)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (write_socket(connection->fd, data, len) == len)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
}
|
||||
gdb_con->closed = 1;
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
|
@ -2158,7 +2177,7 @@ int gdb_input(connection_t *connection)
|
|||
if (retval == ERROR_SERVER_REMOTE_CLOSED)
|
||||
return retval;
|
||||
|
||||
/* logging does not propagate the error, yet can set th gdb_con->closed flag */
|
||||
/* logging does not propagate the error, yet can set the gdb_con->closed flag */
|
||||
if (gdb_con->closed)
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
|
||||
|
@ -2177,34 +2196,37 @@ int gdb_init(void)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
if (gdb_port == 0)
|
||||
if (gdb_port == 0 && server_use_pipes == 0)
|
||||
{
|
||||
LOG_WARNING("no gdb port specified, using default port 3333");
|
||||
gdb_port = 3333;
|
||||
}
|
||||
|
||||
while (target)
|
||||
if (server_use_pipes)
|
||||
{
|
||||
char service_name[8];
|
||||
|
||||
snprintf(service_name, 8, "gdb-%2.2i", target->target_number);
|
||||
|
||||
/* only a single gdb connection when using a pipe */
|
||||
|
||||
gdb_service = malloc(sizeof(gdb_service_t));
|
||||
gdb_service->target = target;
|
||||
|
||||
add_service("gdb", CONNECTION_GDB,
|
||||
gdb_port + target->target_number,
|
||||
1, gdb_new_connection, gdb_input,
|
||||
gdb_connection_closed,
|
||||
gdb_service);
|
||||
add_service("gdb", CONNECTION_PIPE, 0, 1, gdb_new_connection, gdb_input, gdb_connection_closed, gdb_service);
|
||||
|
||||
LOG_DEBUG("gdb service for target %s at port %i",
|
||||
target->type->name,
|
||||
gdb_port + target->target_number);
|
||||
|
||||
target = target->next;
|
||||
LOG_DEBUG("gdb service for target %s using pipes", target->type->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (target)
|
||||
{
|
||||
gdb_service = malloc(sizeof(gdb_service_t));
|
||||
gdb_service->target = target;
|
||||
|
||||
add_service("gdb", CONNECTION_TCP, gdb_port + target->target_number, 1, gdb_new_connection, gdb_input, gdb_connection_closed, gdb_service);
|
||||
|
||||
LOG_DEBUG("gdb service for target %s at port %i", target->type->name, gdb_port + target->target_number);
|
||||
target = target->next;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ service_t *services = NULL;
|
|||
static int shutdown_openocd = 0;
|
||||
int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
|
||||
/* set when using pipes rather than tcp */
|
||||
int server_use_pipes = 0;
|
||||
|
||||
int add_connection(service_t *service, command_context_t *cmd_ctx)
|
||||
{
|
||||
unsigned int address_size;
|
||||
|
@ -69,28 +72,44 @@ int add_connection(service_t *service, command_context_t *cmd_ctx)
|
|||
c->priv = NULL;
|
||||
c->next = NULL;
|
||||
|
||||
address_size = sizeof(c->sin);
|
||||
|
||||
c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
|
||||
|
||||
/* This increases performance dramatically for e.g. GDB load which
|
||||
* does not have a sliding window protocol. */
|
||||
retval=setsockopt(c->fd, /* socket affected */
|
||||
IPPROTO_TCP, /* set option at TCP level */
|
||||
TCP_NODELAY, /* name of option */
|
||||
(char *)&flag, /* the cast is historical cruft */
|
||||
sizeof(int)); /* length of option value */
|
||||
if (service->type == CONNECTION_TCP)
|
||||
{
|
||||
address_size = sizeof(c->sin);
|
||||
|
||||
LOG_INFO("accepting '%s' connection from %i", service->name, c->sin.sin_port);
|
||||
if ((retval = service->new_connection(c)) == ERROR_OK)
|
||||
{
|
||||
c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
|
||||
|
||||
/* This increases performance dramatically for e.g. GDB load which
|
||||
* does not have a sliding window protocol. */
|
||||
retval=setsockopt(c->fd, /* socket affected */
|
||||
IPPROTO_TCP, /* set option at TCP level */
|
||||
TCP_NODELAY, /* name of option */
|
||||
(char *)&flag, /* the cast is historical cruft */
|
||||
sizeof(int)); /* length of option value */
|
||||
|
||||
LOG_INFO("accepting '%s' connection from %i", service->name, c->sin.sin_port);
|
||||
if ((retval = service->new_connection(c)) != ERROR_OK)
|
||||
{
|
||||
close_socket(c->fd);
|
||||
LOG_ERROR("attempted '%s' connection rejected", service->name);
|
||||
free(c);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (service->type == CONNECTION_PIPE)
|
||||
{
|
||||
close_socket(c->fd);
|
||||
LOG_ERROR("attempted '%s' connection rejected", service->name);
|
||||
free(c);
|
||||
return retval;
|
||||
#ifndef _WIN32
|
||||
c->fd = service->fd;
|
||||
|
||||
/* do not check for new connections again on stdin */
|
||||
service->fd = -1;
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* add to the end of linked list */
|
||||
|
@ -113,7 +132,8 @@ int remove_connection(service_t *service, connection_t *connection)
|
|||
if (c->fd == connection->fd)
|
||||
{
|
||||
service->connection_closed(c);
|
||||
close_socket(c->fd);
|
||||
if (service->type == CONNECTION_TCP)
|
||||
close_socket(c->fd);
|
||||
command_done(c->cmd_ctx);
|
||||
|
||||
/* delete connection */
|
||||
|
@ -150,44 +170,67 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
|
|||
c->priv = priv;
|
||||
c->next = NULL;
|
||||
|
||||
if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
if (type == CONNECTION_TCP)
|
||||
{
|
||||
LOG_ERROR("error creating socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));
|
||||
|
||||
socket_nonblock(c->fd);
|
||||
|
||||
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);
|
||||
|
||||
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1)
|
||||
{
|
||||
LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
LOG_ERROR("error creating socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));
|
||||
|
||||
socket_nonblock(c->fd);
|
||||
|
||||
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);
|
||||
|
||||
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1)
|
||||
{
|
||||
LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
int segsize=65536;
|
||||
setsockopt(c->fd, IPPROTO_TCP, TCP_MAXSEG, &segsize, sizeof(int));
|
||||
int segsize=65536;
|
||||
setsockopt(c->fd, IPPROTO_TCP, TCP_MAXSEG, &segsize, sizeof(int));
|
||||
#endif
|
||||
int window_size = 128 * 1024;
|
||||
|
||||
/* These setsockopt()s must happen before the listen() */
|
||||
int window_size = 128 * 1024;
|
||||
|
||||
setsockopt(c->fd, SOL_SOCKET, SO_SNDBUF,
|
||||
(char *)&window_size, sizeof(window_size));
|
||||
setsockopt(c->fd, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *)&window_size, sizeof(window_size));
|
||||
|
||||
if (listen(c->fd, 1) == -1)
|
||||
/* These setsockopt()s must happen before the listen() */
|
||||
|
||||
setsockopt(c->fd, SOL_SOCKET, SO_SNDBUF,
|
||||
(char *)&window_size, sizeof(window_size));
|
||||
setsockopt(c->fd, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *)&window_size, sizeof(window_size));
|
||||
|
||||
if (listen(c->fd, 1) == -1)
|
||||
{
|
||||
LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
else if (type == CONNECTION_PIPE)
|
||||
{
|
||||
LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
/* use stdin */
|
||||
c->fd = STDIN_FILENO;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* for win32 set stdin/stdout to binary mode */
|
||||
if (_setmode(_fileno(stdout), _O_BINARY) < 0)
|
||||
LOG_WARNING("cannot change stdout mode to binary");
|
||||
if (_setmode(_fileno(stdin), _O_BINARY) < 0)
|
||||
LOG_WARNING("cannot change stdin mode to binary");
|
||||
#else
|
||||
socket_nonblock(c->fd);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("unknown connection type: %d", type);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* add to the end of linked list */
|
||||
|
@ -310,14 +353,18 @@ int server_loop(command_context_t *command_context)
|
|||
|
||||
#ifndef _WIN32
|
||||
#if BUILD_ECOSBOARD == 0
|
||||
/* add STDIN to read_fds */
|
||||
FD_SET(fileno(stdin), &read_fds);
|
||||
if (server_use_pipes == 0)
|
||||
{
|
||||
/* add STDIN to read_fds */
|
||||
FD_SET(fileno(stdin), &read_fds);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
openocd_sleep_prelude();
|
||||
kept_alive();
|
||||
// Only while we're sleeping we'll let others run
|
||||
|
||||
/* Only while we're sleeping we'll let others run */
|
||||
retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
|
||||
openocd_sleep_postlude();
|
||||
|
||||
|
@ -371,11 +418,14 @@ int server_loop(command_context_t *command_context)
|
|||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
unsigned int address_size = sizeof(sin);
|
||||
int tmp_fd;
|
||||
tmp_fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
|
||||
close_socket(tmp_fd);
|
||||
if (service->type != CONNECTION_PIPE)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
unsigned int address_size = sizeof(sin);
|
||||
int tmp_fd;
|
||||
tmp_fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
|
||||
close_socket(tmp_fd);
|
||||
}
|
||||
LOG_INFO("rejected '%s' connection, no more connections allowed", service->name);
|
||||
}
|
||||
}
|
||||
|
@ -389,11 +439,16 @@ int server_loop(command_context_t *command_context)
|
|||
{
|
||||
if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending)
|
||||
{
|
||||
if (service->input(c) != ERROR_OK)
|
||||
if ((retval = service->input(c)) != ERROR_OK)
|
||||
{
|
||||
connection_t *next = c->next;
|
||||
if (service->type == CONNECTION_PIPE)
|
||||
{
|
||||
/* if connection uses a pipe then shutdown openocd on error */
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
remove_connection(service, c);
|
||||
LOG_INFO("dropped '%s' connection", service->name);
|
||||
LOG_INFO("dropped '%s' connection - error %d", service->name, retval);
|
||||
c = next;
|
||||
continue;
|
||||
}
|
||||
|
@ -405,11 +460,15 @@ int server_loop(command_context_t *command_context)
|
|||
|
||||
#ifndef _WIN32
|
||||
#if BUILD_ECOSBOARD == 0
|
||||
if (FD_ISSET(fileno(stdin), &read_fds))
|
||||
/* check for data on stdin if not using pipes */
|
||||
if (server_use_pipes == 0)
|
||||
{
|
||||
if (getc(stdin) == 'x')
|
||||
if (FD_ISSET(fileno(stdin), &read_fds))
|
||||
{
|
||||
shutdown_openocd = 1;
|
||||
if (getc(stdin) == 'x')
|
||||
{
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -459,7 +518,6 @@ int server_init(void)
|
|||
signal(SIGBREAK, sig_handler);
|
||||
signal(SIGABRT, sig_handler);
|
||||
#endif
|
||||
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -34,9 +34,8 @@
|
|||
|
||||
enum connection_type
|
||||
{
|
||||
CONNECTION_GDB,
|
||||
CONNECTION_TELNET,
|
||||
CONNECTION_TCL,
|
||||
CONNECTION_TCP,
|
||||
CONNECTION_PIPE
|
||||
};
|
||||
|
||||
typedef struct connection_s
|
||||
|
@ -76,6 +75,8 @@ extern int server_quit(void);
|
|||
extern int server_loop(command_context_t *command_context);
|
||||
extern int server_register_commands(command_context_t *context);
|
||||
|
||||
extern int server_use_pipes;
|
||||
|
||||
#define ERROR_SERVER_REMOTE_CLOSED (-400)
|
||||
#define ERROR_CONNECTION_REJECTED (-401)
|
||||
|
||||
|
|
|
@ -179,7 +179,7 @@ int tcl_init(void)
|
|||
tcl_port = 6666;
|
||||
}
|
||||
|
||||
retval = add_service("tcl", CONNECTION_TCL, tcl_port, 1, tcl_new_connection, tcl_input, tcl_closed, NULL);
|
||||
retval = add_service("tcl", CONNECTION_TCP, tcl_port, 1, tcl_new_connection, tcl_input, tcl_closed, NULL);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
@ -615,7 +615,7 @@ int telnet_init(char *banner)
|
|||
|
||||
telnet_service->banner = banner;
|
||||
|
||||
add_service("telnet", CONNECTION_TELNET, telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service);
|
||||
add_service("telnet", CONNECTION_TCP, telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -232,7 +232,6 @@ const Jim_Nvp nvp_target_debug_reason [] = {
|
|||
{ .name = NULL, .value = -1 },
|
||||
};
|
||||
|
||||
|
||||
const Jim_Nvp nvp_target_endian[] = {
|
||||
{ .name = "big", .value = TARGET_BIG_ENDIAN },
|
||||
{ .name = "little", .value = TARGET_LITTLE_ENDIAN },
|
||||
|
@ -249,8 +248,7 @@ const Jim_Nvp nvp_reset_modes[] = {
|
|||
{ .name = NULL , .value = -1 },
|
||||
};
|
||||
|
||||
static int
|
||||
max_target_number( void )
|
||||
static int max_target_number(void)
|
||||
{
|
||||
target_t *t;
|
||||
int x;
|
||||
|
@ -267,8 +265,7 @@ max_target_number( void )
|
|||
}
|
||||
|
||||
/* determine the number of the new target */
|
||||
static int
|
||||
new_target_number( void )
|
||||
static int new_target_number(void)
|
||||
{
|
||||
target_t *t;
|
||||
int x;
|
||||
|
|
Loading…
Reference in New Issue