Skip to content

Commit 6d764f5

Browse files
timsifivetom-van
authored andcommitted
rtos: Dynamically allocate memory for RTOS registers
Imported from riscv-collab/riscv-openocd#647 FreeRTOS part of patch dropped as it depends on other riscv-collab specific changes. This makes things work on RISC-V cores with large vector registers (which can be up to kilobytes in size). Change-Id: Ie53cb43a88e2a475f695cd5c1e28605569926817 Signed-off-by: Tim Newsome <[email protected]> Signed-off-by: Tomas Vanek <[email protected]> Reviewed-on: https://review.openocd.org/c/openocd/+/9123 Tested-by: jenkins Reviewed-by: Evgeniy Naydanov <[email protected]>
1 parent 6127077 commit 6d764f5

File tree

3 files changed

+42
-17
lines changed

3 files changed

+42
-17
lines changed

src/rtos/hwthread.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
static bool hwthread_detect_rtos(struct target *target);
1818
static int hwthread_create(struct target *target);
1919
static int hwthread_update_threads(struct rtos *rtos);
20-
static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id,
21-
uint32_t reg_num, struct rtos_reg *rtos_reg);
20+
static int hwthread_get_thread_reg_value(struct rtos *rtos, int64_t thread_id,
21+
uint32_t reg_num, uint32_t *size, uint8_t **value);
2222
static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
2323
struct rtos_reg **reg_list, int *num_regs);
2424
static int hwthread_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
@@ -53,7 +53,7 @@ const struct rtos_type hwthread_rtos = {
5353
.create = hwthread_create,
5454
.update_threads = hwthread_update_threads,
5555
.get_thread_reg_list = hwthread_get_thread_reg_list,
56-
.get_thread_reg = hwthread_get_thread_reg,
56+
.get_thread_reg_value = hwthread_get_thread_reg_value,
5757
.get_symbol_list_to_lookup = hwthread_get_symbol_list_to_lookup,
5858
.smp_init = hwthread_smp_init,
5959
.set_reg = hwthread_set_reg,
@@ -291,8 +291,8 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
291291
return ERROR_OK;
292292
}
293293

294-
static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id,
295-
uint32_t reg_num, struct rtos_reg *rtos_reg)
294+
static int hwthread_get_thread_reg_value(struct rtos *rtos, int64_t thread_id,
295+
uint32_t reg_num, uint32_t *size, uint8_t **value)
296296
{
297297
if (!rtos)
298298
return ERROR_FAIL;
@@ -321,11 +321,14 @@ static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id,
321321
if (reg->type->get(reg) != ERROR_OK)
322322
return ERROR_FAIL;
323323

324-
rtos_reg->number = reg->number;
325-
rtos_reg->size = reg->size;
326-
unsigned int bytes = (reg->size + 7) / 8;
327-
assert(bytes <= sizeof(rtos_reg->value));
328-
memcpy(rtos_reg->value, reg->value, bytes);
324+
*size = reg->size;
325+
unsigned int bytes = DIV_ROUND_UP(reg->size, 8);
326+
*value = malloc(bytes);
327+
if (!*value) {
328+
LOG_ERROR("Failed to allocate memory for %d-bit register.", reg->size);
329+
return ERROR_FAIL;
330+
}
331+
memcpy(*value, reg->value, bytes);
329332

330333
return ERROR_OK;
331334
}

src/rtos/rtos.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -545,15 +545,33 @@ int rtos_get_gdb_reg(struct connection *connection, int reg_num)
545545
target->rtos->current_thread);
546546

547547
int retval;
548-
if (target->rtos->type->get_thread_reg) {
549-
reg_list = calloc(1, sizeof(*reg_list));
550-
num_regs = 1;
551-
retval = target->rtos->type->get_thread_reg(target->rtos,
552-
current_threadid, reg_num, &reg_list[0]);
548+
if (target->rtos->type->get_thread_reg_value) {
549+
uint32_t reg_size;
550+
uint8_t *reg_value;
551+
retval = target->rtos->type->get_thread_reg_value(target->rtos,
552+
current_threadid, reg_num, &reg_size, &reg_value);
553553
if (retval != ERROR_OK) {
554554
LOG_ERROR("RTOS: failed to get register %d", reg_num);
555555
return retval;
556556
}
557+
558+
/* Create a reg_list with one register that can
559+
* accommodate the full size of the one we just got the
560+
* value for. To do that we allocate extra space off the
561+
* end of the struct, relying on the fact that
562+
* rtos_reg.value is the last element in the struct. */
563+
reg_list = calloc(1, sizeof(*reg_list) + DIV_ROUND_UP(reg_size, 8));
564+
if (!reg_list) {
565+
free(reg_value);
566+
LOG_ERROR("Failed to allocated reg_list for %d-byte register.",
567+
reg_size);
568+
return ERROR_FAIL;
569+
}
570+
reg_list[0].number = reg_num;
571+
reg_list[0].size = reg_size;
572+
memcpy(&reg_list[0].value, reg_value, DIV_ROUND_UP(reg_size, 8));
573+
free(reg_value);
574+
num_regs = 1;
557575
} else {
558576
retval = target->rtos->type->get_thread_reg_list(target->rtos,
559577
current_threadid,

src/rtos/rtos.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ struct rtos_reg {
5353
uint32_t number;
5454
uint32_t size;
5555
uint8_t value[16];
56+
/* WARNING: rtos_get_gdb_reg() relies on the fact that value is the last
57+
* element of this struct. Any new fields should be added *before* value. */
5658
};
5759

5860
struct rtos_type {
@@ -64,8 +66,10 @@ struct rtos_type {
6466
/** Return a list of general registers, with their values filled out. */
6567
int (*get_thread_reg_list)(struct rtos *rtos, int64_t thread_id,
6668
struct rtos_reg **reg_list, int *num_regs);
67-
int (*get_thread_reg)(struct rtos *rtos, int64_t thread_id,
68-
uint32_t reg_num, struct rtos_reg *reg);
69+
/** Return the size and value of the specified reg_num. The value is
70+
* allocated by the callee and freed by the caller. */
71+
int (*get_thread_reg_value)(struct rtos *rtos, threadid_t thread_id,
72+
uint32_t reg_num, uint32_t *size, uint8_t **value);
6973
int (*get_symbol_list_to_lookup)(struct symbol_table_elem *symbol_list[]);
7074
int (*clean)(struct target *target);
7175
char * (*ps_command)(struct target *target);

0 commit comments

Comments
 (0)