Skip to content

Commit 90bc731

Browse files
dgloeckgalak
authored andcommitted
rtos/Zephyr: read registers from correct location
Almost all architectures store the stack pointer in the _callee_saved structure and we know which other registers are stored there as well. The rest of the general registers should have been stored to the stack of the thread. The only exception is x86-64, which is not yet in a usable state and eventually has to store the stack pointer somewhere. For ARM Cortex-M we must also skip the floating point registers on the stack if they have been stored by the cpu and undo the stack pointer realignment to 8 bytes. It is not possible to return the floating point registers to GDB with the current OpenOCD RTOS API. Fixes #4 Signed-off-by: Daniel Glöckner <[email protected]>
1 parent b00a609 commit 90bc731

File tree

1 file changed

+100
-6
lines changed

1 file changed

+100
-6
lines changed

src/rtos/Zephyr.c

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "rtos_standard_stackings.h"
2929
#include "target/target.h"
3030
#include "target/target_type.h"
31+
#include "target/armv7m.h"
3132

3233
struct Zephyr_thread {
3334
uint32_t ptr, next_ptr;
@@ -56,14 +57,83 @@ struct Zephyr_params {
5657
uint8_t size_width;
5758
uint8_t pointer_width;
5859
uint32_t offsets[OFFSET_MAX];
59-
const struct rtos_register_stacking *reg_stacking;
60+
const struct rtos_register_stacking *callee_saved_stacking;
61+
const struct rtos_register_stacking *cpu_saved_nofp_stacking;
62+
const struct rtos_register_stacking *cpu_saved_fp_stacking;
63+
};
64+
65+
static const struct stack_register_offset arm_callee_saved[] = {
66+
{ ARMV7M_R13, 32, 32 },
67+
{ 4, 0, 32 },
68+
{ 5, 4, 32 },
69+
{ 6, 8, 32 },
70+
{ 7, 12, 32 },
71+
{ 8, 16, 32 },
72+
{ 9, 20, 32 },
73+
{ 10, 24, 32 },
74+
{ 11, 28, 32 },
75+
};
76+
77+
static const struct rtos_register_stacking arm_callee_saved_stacking = {
78+
.stack_registers_size = 36,
79+
.stack_growth_direction = -1,
80+
.num_output_registers = ARRAY_SIZE(arm_callee_saved),
81+
.register_offsets = arm_callee_saved,
82+
};
83+
84+
static const struct stack_register_offset arm_cpu_saved[] = {
85+
{ ARMV7M_R0, 0, 32 },
86+
{ ARMV7M_R1, 4, 32 },
87+
{ ARMV7M_R2, 8, 32 },
88+
{ ARMV7M_R3, 12, 32 },
89+
{ ARMV7M_R4, -1, 32 },
90+
{ ARMV7M_R5, -1, 32 },
91+
{ ARMV7M_R6, -1, 32 },
92+
{ ARMV7M_R7, -1, 32 },
93+
{ ARMV7M_R8, -1, 32 },
94+
{ ARMV7M_R9, -1, 32 },
95+
{ ARMV7M_R10, -1, 32 },
96+
{ ARMV7M_R11, -1, 32 },
97+
{ ARMV7M_R12, 16, 32 },
98+
{ ARMV7M_R13, -2, 32 },
99+
{ ARMV7M_R14, 20, 32 },
100+
{ ARMV7M_PC, 24, 32 },
101+
{ ARMV7M_xPSR, 28, 32 },
102+
};
103+
104+
static int64_t Zephyr_Cortex_M_stack_align(struct target *target,
105+
const uint8_t *stack_data,
106+
const struct rtos_register_stacking *stacking,
107+
int64_t stack_ptr)
108+
{
109+
const int XPSR_OFFSET = 28;
110+
return rtos_Cortex_M_stack_align(target, stack_data, stacking, stack_ptr,
111+
XPSR_OFFSET);
112+
}
113+
114+
static const struct rtos_register_stacking arm_cpu_saved_nofp_stacking = {
115+
.stack_registers_size = 32,
116+
.stack_growth_direction = -1,
117+
.num_output_registers = ARRAY_SIZE(arm_cpu_saved),
118+
.calculate_process_stack = Zephyr_Cortex_M_stack_align,
119+
.register_offsets = arm_cpu_saved,
120+
};
121+
122+
static const struct rtos_register_stacking arm_cpu_saved_fp_stacking = {
123+
.stack_registers_size = 32 + 18 * 4,
124+
.stack_growth_direction = -1,
125+
.num_output_registers = ARRAY_SIZE(arm_cpu_saved),
126+
.calculate_process_stack = Zephyr_Cortex_M_stack_align,
127+
.register_offsets = arm_cpu_saved,
60128
};
61129

62130
static struct Zephyr_params Zephyr_params_list[] = {
63131
{
64132
.target_name = "cortex_m",
65133
.pointer_width = 4,
66-
.reg_stacking = &rtos_standard_Cortex_M4F_FPU_stacking,
134+
.callee_saved_stacking = &arm_callee_saved_stacking,
135+
.cpu_saved_nofp_stacking = &arm_cpu_saved_nofp_stacking,
136+
.cpu_saved_fp_stacking = &arm_cpu_saved_fp_stacking,
67137
},
68138
{
69139
.target_name = NULL
@@ -339,8 +409,11 @@ static int Zephyr_update_threads(struct rtos *rtos)
339409
static int Zephyr_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
340410
struct rtos_reg **reg_list, int *num_regs)
341411
{
342-
struct Zephyr_thread thr;
343412
struct Zephyr_params *params;
413+
const struct rtos_register_stacking *stacking;
414+
struct rtos_reg *callee_saved_reg_list;
415+
int num_callee_saved_regs;
416+
int64_t addr;
344417
int retval;
345418

346419
LOG_INFO("Getting thread %" PRId64 " reg list", thread_id);
@@ -355,12 +428,33 @@ static int Zephyr_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
355428
if (params == NULL)
356429
return ERROR_FAIL;
357430

358-
retval = Zephyr_fetch_thread(rtos, &thr, thread_id);
431+
addr = thread_id + params->offsets[OFFSET_T_STACK_POINTER]
432+
- params->callee_saved_stacking->register_offsets[0].offset;
433+
retval = rtos_generic_stack_read(rtos->target,
434+
params->callee_saved_stacking,
435+
addr, &callee_saved_reg_list,
436+
&num_callee_saved_regs);
359437
if (retval < 0)
360438
return retval;
361439

362-
return rtos_generic_stack_read(rtos->target, params->reg_stacking,
363-
thr.stack_pointer, reg_list, num_regs);
440+
addr = target_buffer_get_u32(rtos->target,
441+
callee_saved_reg_list[0].value);
442+
if (params->offsets[OFFSET_T_PREEMPT_FLOAT] != UNIMPLEMENTED)
443+
stacking = params->cpu_saved_fp_stacking;
444+
else
445+
stacking = params->cpu_saved_nofp_stacking;
446+
retval = rtos_generic_stack_read(rtos->target, stacking, addr, reg_list,
447+
num_regs);
448+
449+
if (retval >= 0)
450+
for (int i = 1; i < num_callee_saved_regs; i++)
451+
buf_cpy(callee_saved_reg_list[i].value,
452+
(*reg_list)[callee_saved_reg_list[i].number].value,
453+
callee_saved_reg_list[i].size);
454+
455+
free(callee_saved_reg_list);
456+
457+
return retval;
364458
}
365459

366460
static int Zephyr_get_symbol_list_to_lookup(symbol_table_elem_t **symbol_list)

0 commit comments

Comments
 (0)