X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fserver%2Fgdb_server.c;h=ef8d7f22900dfd45b80fd21df0354a2044b52045;hb=cb4a475f6c26ff197cd9d601b0b9f86653d961a2;hp=21dc24c9e1c74b2a51033b1bb0e4338a30242591;hpb=410fab9ea8c6632da2e4967d960f66eecc7821ec;p=openocd.git diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 21dc24c9e1..ef8d7f2290 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -34,7 +34,7 @@ #include "flash.h" #include "gdb_server.h" #include "image.h" -#include "jtag.h" +#include #if 0 @@ -53,7 +53,7 @@ static const char *DIGITS = "0123456789abcdef"; static void gdb_log_callback(void *priv, const char *file, unsigned line, const char *function, const char *string); -/* number of gdb connections, mainly to supress gdb related debugging spam +/* number of gdb connections, mainly to suppress gdb related debugging spam * in helper/log.c when no gdb connections are actually active */ int gdb_actual_connections; @@ -568,7 +568,7 @@ int gdb_get_packet_inner(struct connection *connection, char *buffer, int *len) break; case '+': /* gdb sends a dummy ack '+' at every remote connect - see remote_start_remote (remote.c) - * incase anyone tries to debug why they receive this warning every time */ + * in case anyone tries to debug why they receive this warning every time */ LOG_WARNING("acknowledgment received, but no packet pending"); break; case '-': @@ -774,7 +774,7 @@ int gdb_new_connection(struct connection *connection) gdb_actual_connections++; LOG_DEBUG("New GDB Connection: %d, Target %s, state: %s", gdb_actual_connections, - gdb_service->target->cmd_name, + target_name(gdb_service->target), target_state_name(gdb_service->target)); return ERROR_OK; @@ -792,7 +792,7 @@ int gdb_connection_closed(struct connection *connection) gdb_actual_connections--; LOG_DEBUG("GDB Close, Target: %s, state: %s, gdb_actual_connections=%d", - gdb_service->target->cmd_name, + target_name(gdb_service->target), target_state_name(gdb_service->target), gdb_actual_connections); @@ -859,7 +859,7 @@ static int gdb_reg_pos(struct target *target, int pos, int len) * register might be non-divisible by 8(a byte), in which * case an entire byte is shown. * - * NB! the format on the wire is the target endianess + * NB! the format on the wire is the target endianness * * The format of reg->value is little endian * @@ -2138,10 +2138,10 @@ int gdb_input_inner(struct connection *connection) watchpoint_clear_target(gdb_service->target); command_run_linef(connection->cmd_ctx, "ocd_gdb_restart %s", - target->cmd_name); + target_name(target)); break; default: - /* ignore unkown packets */ + /* ignore unknown packets */ LOG_DEBUG("ignoring 0x%2.2x packet", packet[0]); gdb_put_packet(connection, NULL, 0); break; @@ -2189,55 +2189,68 @@ int gdb_input(struct connection *connection) return ERROR_OK; } -int gdb_init(void) +static int gdb_target_start(struct target *target, uint16_t port) { - struct gdb_service *gdb_service; - struct target *target = all_targets; + bool use_pipes = 0 == port; + struct gdb_service *gdb_service = malloc(sizeof(struct gdb_service)); + if (NULL == gdb_service) + return -ENOMEM; - if (!target) - { - LOG_WARNING("no gdb ports allocated as no target has been specified"); - return ERROR_OK; - } + gdb_service->target = target; + add_service("gdb", use_pipes ? CONNECTION_PIPE : CONNECTION_TCP, + 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; +} + +int gdb_target_add_one(struct target *target) +{ if (gdb_port == 0 && server_use_pipes == 0) { LOG_INFO("gdb port disabled"); return ERROR_OK; } - if (server_use_pipes) + bool use_pipes = server_use_pipes; + static bool server_started_with_pipes = false; + if (server_started_with_pipes) { - /* only a single gdb connection when using a pipe */ + LOG_WARNING("gdb service permits one target when using pipes"); + if (0 == gdb_port) + return ERROR_OK; + + use_pipes = false; + } - gdb_service = malloc(sizeof(struct gdb_service)); - gdb_service->target = target; + int e = gdb_target_start(target, use_pipes ? 0 : gdb_port++); + if (ERROR_OK == e) + server_started_with_pipes |= use_pipes; - add_service("gdb", CONNECTION_PIPE, 0, 1, gdb_new_connection, gdb_input, gdb_connection_closed, gdb_service); + return e; +} - LOG_DEBUG("gdb service for target %s using pipes", - target_get_name(target)); +int gdb_target_add_all(struct target *target) +{ + if (NULL == target) + { + LOG_WARNING("gdb services need one or more targets defined"); + return ERROR_OK; } - else + + while (NULL != target) { - unsigned short port = gdb_port; + int retval = gdb_target_add_one(target); + if (ERROR_OK != retval) + return retval; - while (target) - { - gdb_service = malloc(sizeof(struct gdb_service)); - gdb_service->target = target; - - add_service("gdb", CONNECTION_TCP, - port, 1, - gdb_new_connection, gdb_input, - gdb_connection_closed, gdb_service); - - LOG_DEBUG("gdb service for target %s at TCP port %i", - target_get_name(target), - port); - target = target->next; - port++; - } + target = target->next; } return ERROR_OK; @@ -2320,33 +2333,61 @@ COMMAND_HANDLER(handle_gdb_breakpoint_override_command) LOG_USER("force %s breakpoints", (gdb_breakpoint_override_type == BKPT_HARD)?"hard":"soft"); } else { - LOG_USER("breakpoint type is not overriden"); + LOG_USER("breakpoint type is not overridden"); } return ERROR_OK; } -int gdb_register_commands(struct command_context *command_context) +static const struct command_registration gdb_command_handlers[] = { + { + .name = "gdb_sync", + .handler = &handle_gdb_sync_command, + .mode = COMMAND_ANY, + .help = "next stepi will return immediately allowing " + "GDB to fetch register state without affecting " + "target state", + }, + { + .name = "gdb_port", + .handler = &handle_gdb_port_command, + .mode = COMMAND_ANY, + .help = "daemon configuration command gdb_port", + .usage = "", + }, + { + .name = "gdb_memory_map", + .handler = &handle_gdb_memory_map_command, + .mode = COMMAND_CONFIG, + .help = "enable or disable memory map", + .usage = "enable|disable" + }, + { + .name = "gdb_flash_program", + .handler = &handle_gdb_flash_program_command, + .mode = COMMAND_CONFIG, + .help = "enable or disable flash program", + .usage = "enable|disable" + }, + { + .name = "gdb_report_data_abort", + .handler = &handle_gdb_report_data_abort_command, + .mode = COMMAND_CONFIG, + .help = "enable or disable reporting data aborts", + .usage = "enable|disable" + }, + { + .name = "gdb_breakpoint_override", + .handler = &handle_gdb_breakpoint_override_command, + .mode = COMMAND_EXEC, + .help = "force type of breakpoint " + "used by gdb 'break' commands.", + .usage = "hard|soft|disable", + }, + COMMAND_REGISTRATION_DONE +}; + +int gdb_register_commands(struct command_context *cmd_ctx) { - register_command(command_context, NULL, "gdb_sync", - handle_gdb_sync_command, COMMAND_ANY, - "next stepi will return immediately allowing GDB to " - "fetch register state without affecting target state"); - register_command(command_context, NULL, "gdb_port", - handle_gdb_port_command, COMMAND_ANY, - "daemon configuration command gdb_port"); - register_command(command_context, NULL, "gdb_memory_map", - handle_gdb_memory_map_command, COMMAND_CONFIG, - "enable or disable memory map"); - register_command(command_context, NULL, "gdb_flash_program", - handle_gdb_flash_program_command, COMMAND_CONFIG, - "enable or disable flash program"); - register_command(command_context, NULL, "gdb_report_data_abort", - handle_gdb_report_data_abort_command, COMMAND_CONFIG, - "enable or disable reporting data aborts"); - register_command(command_context, NULL, "gdb_breakpoint_override", - handle_gdb_breakpoint_override_command, COMMAND_EXEC, - "hard/soft/disable - force type of breakpoint " - "used by gdb 'break' commands."); - return ERROR_OK; + return register_commands(cmd_ctx, NULL, gdb_command_handlers); }