Merge branch 'remotes/openocd/master' into riscv64

Merged 1025be363e

Conflicts:
	src/flash/nor/Makefile.am
	src/rtos/Makefile.am
	src/rtos/rtos.c
	src/target/Makefile.am
	src/target/target.c
	src/target/target_type.h

Doesn't build yet, but I fixed the conflicts that git pointed out.
This commit is contained in:
Tim Newsome
2017-06-13 11:52:50 -07:00
303 changed files with 17138 additions and 10591 deletions
+14 -18
View File
@@ -1,23 +1,19 @@
include $(top_srcdir)/common.mk
noinst_LTLIBRARIES += %D%/libserver.la
%C%_libserver_la_SOURCES = \
%D%/server.c \
%D%/telnet_server.c \
%D%/gdb_server.c \
%D%/server.h \
%D%/telnet_server.h \
%D%/gdb_server.h \
%D%/server_stubs.c \
%D%/tcl_server.c \
%D%/tcl_server.h
METASOURCES = AUTO
noinst_LTLIBRARIES = libserver.la
noinst_HEADERS = server.h telnet_server.h gdb_server.h
libserver_la_SOURCES = server.c telnet_server.c gdb_server.c
libserver_la_SOURCES += server_stubs.c
libserver_la_CFLAGS =
%C%_libserver_la_CFLAGS = $(AM_CFLAGS)
if IS_MINGW
# FD_* macros are sloppy with their signs on MinGW32 platform
libserver_la_CFLAGS += -Wno-sign-compare
%C%_libserver_la_CFLAGS += -Wno-sign-compare
endif
# tcl server addons
noinst_HEADERS += tcl_server.h
libserver_la_SOURCES += tcl_server.c
EXTRA_DIST = \
startup.tcl
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
STARTUP_TCL_SRCS += %D%/startup.tcl
+179 -33
View File
@@ -90,6 +90,8 @@ struct gdb_connection {
bool attached;
/* temporarily used for target description support */
struct target_desc_format target_desc;
/* temporarily used for thread list support */
char *thread_list;
};
#if 0
@@ -695,7 +697,8 @@ static int gdb_output_con(struct connection *connection, const char *line)
return ERROR_GDB_BUFFER_TOO_SMALL;
hex_buffer[0] = 'O';
int pkt_len = hexify(hex_buffer + 1, line, bin_size, bin_size * 2 + 1);
size_t pkt_len = hexify(hex_buffer + 1, (const uint8_t *)line, bin_size,
bin_size * 2 + 1);
int retval = gdb_put_packet(connection, hex_buffer, pkt_len + 1);
free(hex_buffer);
@@ -732,22 +735,22 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio
stop_reason[0] = '\0';
if (target->debug_reason == DBG_REASON_WATCHPOINT) {
enum watchpoint_rw hit_wp_type;
uint32_t hit_wp_address;
target_addr_t hit_wp_address;
if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) {
switch (hit_wp_type) {
case WPT_WRITE:
snprintf(stop_reason, sizeof(stop_reason),
"watch:%08" PRIx32 ";", hit_wp_address);
"watch:%08" TARGET_PRIxADDR ";", hit_wp_address);
break;
case WPT_READ:
snprintf(stop_reason, sizeof(stop_reason),
"rwatch:%08" PRIx32 ";", hit_wp_address);
"rwatch:%08" TARGET_PRIxADDR ";", hit_wp_address);
break;
case WPT_ACCESS:
snprintf(stop_reason, sizeof(stop_reason),
"awatch:%08" PRIx32 ";", hit_wp_address);
"awatch:%08" TARGET_PRIxADDR ";", hit_wp_address);
break;
default:
break;
@@ -934,6 +937,7 @@ static int gdb_new_connection(struct connection *connection)
gdb_connection->attached = true;
gdb_connection->target_desc.tdesc = NULL;
gdb_connection->target_desc.tdesc_length = 0;
gdb_connection->thread_list = NULL;
/* send ACK to GDB for debug request */
gdb_write(connection, "+", 1);
@@ -1376,7 +1380,7 @@ static int gdb_read_memory_packet(struct connection *connection,
{
struct target *target = get_target_from_connection(connection);
char *separator;
uint32_t addr = 0;
uint64_t addr = 0;
uint32_t len = 0;
uint8_t *buffer;
@@ -1387,7 +1391,7 @@ static int gdb_read_memory_packet(struct connection *connection,
/* skip command character */
packet++;
addr = strtoul(packet, &separator, 16);
addr = strtoull(packet, &separator, 16);
if (*separator != ',') {
LOG_ERROR("incomplete read memory packet received, dropping connection");
@@ -1404,7 +1408,7 @@ static int gdb_read_memory_packet(struct connection *connection,
buffer = malloc(len);
LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
LOG_DEBUG("addr: 0x%16.16" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len);
retval = target_read_buffer(target, addr, len, buffer);
@@ -1429,7 +1433,7 @@ static int gdb_read_memory_packet(struct connection *connection,
if (retval == ERROR_OK) {
hex_buffer = malloc(len * 2 + 1);
int pkt_len = hexify(hex_buffer, (char *)buffer, len, len * 2 + 1);
size_t pkt_len = hexify(hex_buffer, buffer, len, len * 2 + 1);
gdb_put_packet(connection, hex_buffer, pkt_len);
@@ -1447,7 +1451,7 @@ static int gdb_write_memory_packet(struct connection *connection,
{
struct target *target = get_target_from_connection(connection);
char *separator;
uint32_t addr = 0;
uint64_t addr = 0;
uint32_t len = 0;
uint8_t *buffer;
@@ -1456,7 +1460,7 @@ static int gdb_write_memory_packet(struct connection *connection,
/* skip command character */
packet++;
addr = strtoul(packet, &separator, 16);
addr = strtoull(packet, &separator, 16);
if (*separator != ',') {
LOG_ERROR("incomplete write memory packet received, dropping connection");
@@ -1472,9 +1476,9 @@ static int gdb_write_memory_packet(struct connection *connection,
buffer = malloc(len);
LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len);
if (unhexify((char *)buffer, separator, len) != (int)len)
if (unhexify(buffer, separator, len) != len)
LOG_ERROR("unable to decode memory packet");
retval = target_write_buffer(target, addr, len, buffer);
@@ -1494,15 +1498,19 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
{
struct target *target = get_target_from_connection(connection);
char *separator;
uint32_t addr = 0;
uint64_t addr = 0;
uint32_t len = 0;
int retval = ERROR_OK;
/* Packets larger than fast_limit bytes will be acknowledged instantly on
* the assumption that we're in a download and it's important to go as fast
* as possible. */
uint32_t fast_limit = 8;
/* skip command character */
packet++;
addr = strtoul(packet, &separator, 16);
addr = strtoull(packet, &separator, 16);
if (*separator != ',') {
LOG_ERROR("incomplete write memory binary packet received, dropping connection");
@@ -1518,31 +1526,44 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
struct gdb_connection *gdb_connection = connection->priv;
if (gdb_connection->mem_write_error) {
if (gdb_connection->mem_write_error)
retval = ERROR_FAIL;
if (retval == ERROR_OK) {
if (len >= fast_limit) {
/* By replying the packet *immediately* GDB will send us a new packet
* while we write the last one to the target.
* We only do this for larger writes, so that users who do something like:
* p *((int*)0xdeadbeef)=8675309
* will get immediate feedback that that write failed.
*/
gdb_put_packet(connection, "OK", 2);
}
} else {
retval = gdb_error(connection, retval);
/* now that we have reported the memory write error, we can clear the condition */
gdb_connection->mem_write_error = false;
}
/* By replying the packet *immediately* GDB will send us a new packet
* while we write the last one to the target.
*/
if (retval == ERROR_OK)
gdb_put_packet(connection, "OK", 2);
else {
retval = gdb_error(connection, retval);
if (retval != ERROR_OK)
return retval;
}
if (len) {
LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len);
retval = target_write_buffer(target, addr, len, (uint8_t *)separator);
if (retval != ERROR_OK)
gdb_connection->mem_write_error = true;
}
if (len < fast_limit) {
if (retval != ERROR_OK) {
gdb_error(connection, retval);
gdb_connection->mem_write_error = false;
} else {
gdb_put_packet(connection, "OK", 2);
}
}
return ERROR_OK;
}
@@ -1551,13 +1572,13 @@ static int gdb_step_continue_packet(struct connection *connection,
{
struct target *target = get_target_from_connection(connection);
int current = 0;
uint32_t address = 0x0;
uint64_t address = 0x0;
int retval = ERROR_OK;
LOG_DEBUG("-");
if (packet_size > 1)
address = strtoul(packet + 1, NULL, 16);
address = strtoull(packet + 1, NULL, 16);
else
current = 1;
@@ -1581,7 +1602,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
int type;
enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */;
enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */;
uint32_t address;
uint64_t address;
uint32_t size;
char *separator;
int retval;
@@ -1613,7 +1634,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
return ERROR_SERVER_REMOTE_CLOSED;
}
address = strtoul(separator + 1, &separator, 16);
address = strtoull(separator + 1, &separator, 16);
if (*separator != ',') {
LOG_ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
@@ -2291,6 +2312,95 @@ error:
return retval;
}
static int gdb_generate_thread_list(struct target *target, char **thread_list_out)
{
struct rtos *rtos = target->rtos;
int retval = ERROR_OK;
char *thread_list = NULL;
int pos = 0;
int size = 0;
xml_printf(&retval, &thread_list, &pos, &size,
"<?xml version=\"1.0\"?>\n"
"<threads>\n");
if (rtos != NULL) {
for (int i = 0; i < rtos->thread_count; i++) {
struct thread_detail *thread_detail = &rtos->thread_details[i];
if (!thread_detail->exists)
continue;
xml_printf(&retval, &thread_list, &pos, &size,
"<thread id=\"%" PRIx64 "\">", thread_detail->threadid);
if (thread_detail->thread_name_str != NULL)
xml_printf(&retval, &thread_list, &pos, &size,
"Name: %s", thread_detail->thread_name_str);
if (thread_detail->extra_info_str != NULL) {
if (thread_detail->thread_name_str != NULL)
xml_printf(&retval, &thread_list, &pos, &size,
", ");
xml_printf(&retval, &thread_list, &pos, &size,
thread_detail->extra_info_str);
}
xml_printf(&retval, &thread_list, &pos, &size,
"</thread>\n");
}
}
xml_printf(&retval, &thread_list, &pos, &size,
"</threads>\n");
if (retval == ERROR_OK)
*thread_list_out = thread_list;
else
free(thread_list);
return retval;
}
static int gdb_get_thread_list_chunk(struct target *target, char **thread_list,
char **chunk, int32_t offset, uint32_t length)
{
if (*thread_list == NULL) {
int retval = gdb_generate_thread_list(target, thread_list);
if (retval != ERROR_OK) {
LOG_ERROR("Unable to Generate Thread List");
return ERROR_FAIL;
}
}
size_t thread_list_length = strlen(*thread_list);
char transfer_type;
length = MIN(length, thread_list_length - offset);
if (length < (thread_list_length - offset))
transfer_type = 'm';
else
transfer_type = 'l';
*chunk = malloc(length + 2);
if (*chunk == NULL) {
LOG_ERROR("Unable to allocate memory");
return ERROR_FAIL;
}
(*chunk)[0] = transfer_type;
strncpy((*chunk) + 1, (*thread_list) + offset, length);
(*chunk)[1 + length] = '\0';
/* After gdb-server sends out last chunk, invalidate thread list. */
if (transfer_type == 'l') {
free(*thread_list);
*thread_list = NULL;
}
return ERROR_OK;
}
static int gdb_query_packet(struct connection *connection,
char const *packet, int packet_size)
{
@@ -2302,7 +2412,7 @@ static int gdb_query_packet(struct connection *connection,
if (packet_size > 6) {
char *cmd;
cmd = malloc((packet_size - 6) / 2 + 1);
int len = unhexify(cmd, packet + 6, (packet_size - 6) / 2);
size_t len = unhexify((uint8_t *)cmd, packet + 6, (packet_size - 6) / 2);
cmd[len] = 0;
/* We want to print all debug output to GDB connection */
@@ -2380,7 +2490,7 @@ static int gdb_query_packet(struct connection *connection,
&buffer,
&pos,
&size,
"PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;QStartNoAckMode+",
"PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;qXfer:threads:read+;QStartNoAckMode+",
(GDB_BUFFER_SIZE - 1),
((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-',
(gdb_target_desc_supported == 1) ? '+' : '-');
@@ -2426,6 +2536,37 @@ static int gdb_query_packet(struct connection *connection,
gdb_put_packet(connection, xml, strlen(xml));
free(xml);
return ERROR_OK;
} else if (strncmp(packet, "qXfer:threads:read:", 19) == 0) {
char *xml = NULL;
int retval = ERROR_OK;
int offset;
unsigned int length;
/* skip command character */
packet += 19;
if (decode_xfer_read(packet, NULL, &offset, &length) < 0) {
gdb_send_error(connection, 01);
return ERROR_OK;
}
/* Target should prepare correct thread list for annex.
* The first character of returned xml is 'm' or 'l'. 'm' for
* there are *more* chunks to transfer. 'l' for it is the *last*
* chunk of target description.
*/
retval = gdb_get_thread_list_chunk(target, &gdb_connection->thread_list,
&xml, offset, length);
if (retval != ERROR_OK) {
gdb_error(connection, retval);
return retval;
}
gdb_put_packet(connection, xml, strlen(xml));
free(xml);
return ERROR_OK;
} else if (strncmp(packet, "QStartNoAckMode", 15) == 0) {
@@ -2953,6 +3094,11 @@ static int gdb_target_start(struct target *target, const char *port)
static int gdb_target_add_one(struct target *target)
{
if (strcmp(gdb_port, "disabled") == 0) {
LOG_INFO("gdb port disabled");
return ERROR_OK;
}
/* one gdb instance per smp list */
if ((target->smp) && (target->gdb_service))
return ERROR_OK;
@@ -3146,7 +3292,7 @@ static const struct command_registration gdb_command_handlers[] = {
"server listens for the next port number after the "
"base port number specified. "
"No arguments reports GDB port. \"pipe\" means listen to stdin "
"output to stdout, an integer is base port number, \"disable\" disables "
"output to stdout, an integer is base port number, \"disabled\" disables "
"port. Any other string is are interpreted as named pipe to listen to. "
"Output pipe is the same name as input pipe, but with 'o' appended.",
.usage = "[port_num]",
+38 -13
View File
@@ -132,7 +132,9 @@ static int add_connection(struct service *service, struct command_context *cmd_c
free(out_file);
if (c->fd_out == -1) {
LOG_ERROR("could not open %s", service->port);
exit(1);
command_done(c->cmd_ctx);
free(c);
return ERROR_FAIL;
}
LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port);
@@ -191,7 +193,13 @@ static int remove_connection(struct service *service, struct connection *connect
return ERROR_OK;
}
/* FIX! make service return error instead of invoking exit() */
static void free_service(struct service *c)
{
free(c->name);
free(c->port);
free(c);
}
int add_service(char *name,
const char *port,
int max_connections,
@@ -235,7 +243,8 @@ int add_service(char *name,
c->fd = socket(AF_INET, SOCK_STREAM, 0);
if (c->fd == -1) {
LOG_ERROR("error creating socket: %s", strerror(errno));
exit(-1);
free_service(c);
return ERROR_FAIL;
}
setsockopt(c->fd,
@@ -255,7 +264,9 @@ int add_service(char *name,
hp = gethostbyname(bindto_name);
if (hp == NULL) {
LOG_ERROR("couldn't resolve bindto address: %s", bindto_name);
exit(-1);
close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
}
memcpy(&c->sin.sin_addr, hp->h_addr_list[0], hp->h_length);
}
@@ -263,7 +274,9 @@ int add_service(char *name,
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) {
LOG_ERROR("couldn't bind %s to socket: %s", name, strerror(errno));
exit(-1);
close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
}
#ifndef _WIN32
@@ -281,7 +294,9 @@ int add_service(char *name,
if (listen(c->fd, 1) == -1) {
LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
exit(-1);
close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
}
} else if (c->type == CONNECTION_STDINOUT) {
c->fd = fileno(stdin);
@@ -302,13 +317,15 @@ int add_service(char *name,
/* we currenty do not support named pipes under win32
* so exit openocd for now */
LOG_ERROR("Named pipes currently not supported under this os");
exit(1);
free_service(c);
return ERROR_FAIL;
#else
/* 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);
free_service(c);
return ERROR_FAIL;
}
#endif
}
@@ -425,7 +442,7 @@ int server_loop(struct command_context *command_context)
FD_ZERO(&read_fds);
else {
LOG_ERROR("error during select: %s", strerror(errno));
exit(-1);
return ERROR_FAIL;
}
#else
@@ -433,7 +450,7 @@ int server_loop(struct command_context *command_context)
FD_ZERO(&read_fds);
else {
LOG_ERROR("error during select: %s", strerror(errno));
exit(-1);
return ERROR_FAIL;
}
#endif
}
@@ -552,7 +569,7 @@ int server_preinit(void)
if (WSAStartup(wVersionRequested, &wsaData) != 0) {
LOG_ERROR("Failed to Open Winsock");
exit(-1);
return ERROR_FAIL;
}
/* register ctrl-c handler */
@@ -570,10 +587,18 @@ int server_preinit(void)
int server_init(struct command_context *cmd_ctx)
{
int ret = tcl_init();
if (ERROR_OK != ret)
if (ret != ERROR_OK)
return ret;
return telnet_init("Open On-Chip Debugger");
ret = telnet_init("Open On-Chip Debugger");
if (ret != ERROR_OK) {
remove_services();
return ret;
}
return ERROR_OK;
}
int server_quit(void)
+1 -1
View File
@@ -105,7 +105,7 @@ static int tcl_target_callback_trace_handler(struct target *target,
if (tclc->tc_trace) {
hex = malloc(hex_len);
buf = malloc(max_len);
hexify(hex, (const char *)data, len, hex_len);
hexify(hex, data, len, hex_len);
snprintf(buf, max_len, "%s%s%s", header, hex, trailer);
tcl_output(connection, buf, strlen(buf));
free(hex);
+12 -10
View File
@@ -573,7 +573,7 @@ static int telnet_input(struct connection *connection)
break;
default:
LOG_ERROR("unknown telnet state");
exit(-1);
return ERROR_FAIL;
}
bytes_read--;
@@ -624,9 +624,8 @@ int telnet_init(char *banner)
return ERROR_OK;
}
struct telnet_service *telnet_service;
telnet_service = malloc(sizeof(struct telnet_service));
struct telnet_service *telnet_service =
malloc(sizeof(struct telnet_service));
if (!telnet_service) {
LOG_ERROR("Failed to allocate telnet service.");
@@ -635,13 +634,16 @@ int telnet_init(char *banner)
telnet_service->banner = banner;
return add_service("telnet",
telnet_port,
CONNECTION_LIMIT_UNLIMITED,
telnet_new_connection,
telnet_input,
telnet_connection_closed,
int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED,
telnet_new_connection, telnet_input, telnet_connection_closed,
telnet_service);
if (ret != ERROR_OK) {
free(telnet_service);
return ret;
}
return ERROR_OK;
}
/* daemon configuration command telnet_port */