diff --git a/libs/libc/gdbstub/lib_gdbstub.c b/libs/libc/gdbstub/lib_gdbstub.c index 32cda12c8b1..4d78e1baf9c 100644 --- a/libs/libc/gdbstub/lib_gdbstub.c +++ b/libs/libc/gdbstub/lib_gdbstub.c @@ -25,6 +25,7 @@ ****************************************************************************/ #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include /**************************************************************************** * Pre-processor Definitions @@ -68,6 +70,7 @@ struct gdb_state_s size_t pkt_len; /* Packet send and receive length */ uint8_t running_regs[XCPTCONTEXT_SIZE]; /* Registers of running thread */ size_t size; /* Size of registers */ + FAR struct memory_region_s *range; /* Memory regions */ uintptr_t registers[0]; /* Registers of other threads */ }; @@ -633,6 +636,7 @@ static ssize_t gdb_hex2bin(FAR void *buf, size_t buf_len, in[pos], in[pos + 1], 0 }; + set_errno(0); out[pos / 2] = strtoul(ch, NULL, 16); /* Decode high nibble */ if (out[pos / 2] == 0 && get_errno()) { @@ -703,6 +707,40 @@ static ssize_t gdb_bin2bin(FAR void *buf, size_t buf_len, return out_pos; } +/**************************************************************************** + * Name: gdb_is_valid_region + * Description: + * Check if the address is in the memory region. + * + ****************************************************************************/ + +static bool gdb_is_valid_region(FAR struct gdb_state_s *state, + uintptr_t addr, size_t len, uint32_t flags) +{ + FAR struct memory_region_s *region = state->range; + + if (state->range == NULL) + { + /* No memory region, so allow all access */ + + return true; + } + + while (region->start < region->end) + { + if (addr >= region->start && + addr <= region->end - len && + (region->flags & flags) == flags) + { + return true; + } + + region++; + } + + return false; +} + /**************************************************************************** * Command Functions ****************************************************************************/ @@ -732,7 +770,14 @@ static ssize_t gdb_get_memory(FAR struct gdb_state_s *state, uintptr_t addr, size_t len, gdb_format_func_t format) { - return format(buf, buf_len, (FAR const void *)addr, len); + ssize_t ret = -EINVAL; + + if (gdb_is_valid_region(state, addr, len, PF_R)) + { + return format(buf, buf_len, (FAR const void *)addr, len); + } + + return ret; } /**************************************************************************** @@ -760,7 +805,14 @@ static ssize_t gdb_put_memory(FAR struct gdb_state_s *state, uintptr_t addr, size_t len, gdb_format_func_t format) { - return format((FAR void *)addr, len, buf, buf_len); + ssize_t ret = -EINVAL; + + if (gdb_is_valid_region(state, addr, len, PF_W)) + { + return format((FAR void *)addr, len, buf, buf_len); + } + + return ret; } /**************************************************************************** @@ -1786,6 +1838,16 @@ FAR struct gdb_state_s *gdb_state_init(gdb_send_func_t send, state->priv = priv; state->monitor = monitor; + if (CONFIG_BOARD_MEMORY_RANGE[0] != '\0') + { + state->range = alloc_memory_region(CONFIG_BOARD_MEMORY_RANGE); + if (state->range == NULL) + { + lib_free(state); + return NULL; + } + } + return state; } @@ -1804,6 +1866,11 @@ void gdb_state_uninit(FAR struct gdb_state_s *state) { if (state != NULL) { + if (state->range != NULL) + { + free_memory_region(state->range); + } + lib_free(state); } } diff --git a/sched/misc/coredump.c b/sched/misc/coredump.c index 253e31d25dd..8866768af48 100644 --- a/sched/misc/coredump.c +++ b/sched/misc/coredump.c @@ -212,7 +212,7 @@ int coredump_add_memory_region(FAR const void *ptr, size_t size) { region = (FAR struct memory_region_s *)g_regions; - while (region->start != 0) + while (region->start < region->end) { if ((uintptr_t)ptr >= region->start && (uintptr_t)ptr + size < region->end)