Use the correct thread for memory accesses. (#459)
* Deal with vlenb being unreadable. Instead of exiting during examine(), spit out a warning, and don't expose the vector data registers. We do provide access to the vector CSRs, because maybe they do work? It's just that we have no idea what the size of the data registers is. Change-Id: I6e9ffeb242e2e22fc62cb1b50782c2efb4ace0bd * WIP Change-Id: I46292eefe537aeaf72bdd44e4aa58298b5120b00 * Use the correct thread for memory accesses. Previously, OpenOCD would perform RTOS memory accesses through the first thread in the RTOS. This doesn't work if different threads have a different memory view. For instance if `-rtos hwthread` is used, each configured core could have address translation configured differently. Change-Id: I61328c8f50065ecba5ce1797dbeaee482812f799regcache
parent
5b2426a4b2
commit
60eccb2967
|
@ -151,6 +151,7 @@ extern int debug_level;
|
||||||
#define ERROR_WAIT (-5)
|
#define ERROR_WAIT (-5)
|
||||||
/* ERROR_TIMEOUT is already taken by winerror.h. */
|
/* ERROR_TIMEOUT is already taken by winerror.h. */
|
||||||
#define ERROR_TIMEOUT_REACHED (-6)
|
#define ERROR_TIMEOUT_REACHED (-6)
|
||||||
|
#define ERROR_NOT_IMPLEMENTED (-7)
|
||||||
|
|
||||||
|
|
||||||
#endif /* OPENOCD_HELPER_LOG_H */
|
#endif /* OPENOCD_HELPER_LOG_H */
|
||||||
|
|
|
@ -39,6 +39,10 @@ static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]
|
||||||
static int hwthread_smp_init(struct target *target);
|
static int hwthread_smp_init(struct target *target);
|
||||||
int hwthread_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value);
|
int hwthread_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value);
|
||||||
bool hwthread_needs_fake_step(struct target *target, int64_t thread_id);
|
bool hwthread_needs_fake_step(struct target *target, int64_t thread_id);
|
||||||
|
int hwthread_read_buffer(struct rtos *rtos, target_addr_t address,
|
||||||
|
uint32_t size, uint8_t *buffer);
|
||||||
|
int hwthread_write_buffer(struct rtos *rtos, target_addr_t address,
|
||||||
|
uint32_t size, const uint8_t *buffer);
|
||||||
|
|
||||||
#define HW_THREAD_NAME_STR_SIZE (32)
|
#define HW_THREAD_NAME_STR_SIZE (32)
|
||||||
|
|
||||||
|
@ -59,7 +63,9 @@ const struct rtos_type hwthread_rtos = {
|
||||||
.get_symbol_list_to_lookup = hwthread_get_symbol_list_to_lookup,
|
.get_symbol_list_to_lookup = hwthread_get_symbol_list_to_lookup,
|
||||||
.smp_init = hwthread_smp_init,
|
.smp_init = hwthread_smp_init,
|
||||||
.set_reg = hwthread_set_reg,
|
.set_reg = hwthread_set_reg,
|
||||||
.needs_fake_step = hwthread_needs_fake_step
|
.needs_fake_step = hwthread_needs_fake_step,
|
||||||
|
.read_buffer = hwthread_read_buffer,
|
||||||
|
.write_buffer = hwthread_write_buffer,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hwthread_params {
|
struct hwthread_params {
|
||||||
|
@ -393,3 +399,33 @@ bool hwthread_needs_fake_step(struct target *target, int64_t thread_id)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hwthread_read_buffer(struct rtos *rtos, target_addr_t address,
|
||||||
|
uint32_t size, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
if (rtos == NULL)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct target *target = rtos->target;
|
||||||
|
|
||||||
|
struct target *curr = find_thread(target, rtos->current_thread);
|
||||||
|
if (curr == NULL)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
return target_read_buffer(curr, address, size, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hwthread_write_buffer(struct rtos *rtos, target_addr_t address,
|
||||||
|
uint32_t size, const uint8_t *buffer)
|
||||||
|
{
|
||||||
|
if (rtos == NULL)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct target *target = rtos->target;
|
||||||
|
|
||||||
|
struct target *curr = find_thread(target, rtos->current_thread);
|
||||||
|
if (curr == NULL)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
return target_write_buffer(curr, address, size, buffer);
|
||||||
|
}
|
||||||
|
|
|
@ -680,3 +680,19 @@ bool rtos_needs_fake_step(struct target *target, int64_t thread_id)
|
||||||
return target->rtos->type->needs_fake_step(target, thread_id);
|
return target->rtos->type->needs_fake_step(target, thread_id);
|
||||||
return target->rtos->current_thread != thread_id;
|
return target->rtos->current_thread != thread_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rtos_read_buffer(struct target *target, target_addr_t address,
|
||||||
|
uint32_t size, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
if (target->rtos->type->read_buffer)
|
||||||
|
return target->rtos->type->read_buffer(target->rtos, address, size, buffer);
|
||||||
|
return ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtos_write_buffer(struct target *target, target_addr_t address,
|
||||||
|
uint32_t size, const uint8_t *buffer)
|
||||||
|
{
|
||||||
|
if (target->rtos->type->write_buffer)
|
||||||
|
return target->rtos->type->write_buffer(target->rtos, address, size, buffer);
|
||||||
|
return ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
|
@ -90,6 +90,13 @@ struct rtos_type {
|
||||||
* target running a multi-threading OS. If an RTOS can do this, override
|
* target running a multi-threading OS. If an RTOS can do this, override
|
||||||
* needs_fake_step(). */
|
* needs_fake_step(). */
|
||||||
bool (*needs_fake_step)(struct target *target, int64_t thread_id);
|
bool (*needs_fake_step)(struct target *target, int64_t thread_id);
|
||||||
|
/* Implement these if different threads in the RTOS can see memory
|
||||||
|
* differently (for instance because address translation might be different
|
||||||
|
* for each thread). */
|
||||||
|
int (*read_buffer)(struct rtos *rtos, target_addr_t address, uint32_t size,
|
||||||
|
uint8_t *buffer);
|
||||||
|
int (*write_buffer)(struct rtos *rtos, target_addr_t address, uint32_t size,
|
||||||
|
const uint8_t *buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stack_register_offset {
|
struct stack_register_offset {
|
||||||
|
@ -136,5 +143,9 @@ int rtos_smp_init(struct target *target);
|
||||||
/* function for handling symbol access */
|
/* function for handling symbol access */
|
||||||
int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size);
|
int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size);
|
||||||
bool rtos_needs_fake_step(struct target *target, int64_t thread_id);
|
bool rtos_needs_fake_step(struct target *target, int64_t thread_id);
|
||||||
|
int rtos_read_buffer(struct target *target, target_addr_t address,
|
||||||
|
uint32_t size, uint8_t *buffer);
|
||||||
|
int rtos_write_buffer(struct target *target, target_addr_t address,
|
||||||
|
uint32_t size, const uint8_t *buffer);
|
||||||
|
|
||||||
#endif /* OPENOCD_RTOS_RTOS_H */
|
#endif /* OPENOCD_RTOS_RTOS_H */
|
||||||
|
|
|
@ -1425,7 +1425,7 @@ static int gdb_read_memory_packet(struct connection *connection,
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
char *hex_buffer;
|
char *hex_buffer;
|
||||||
|
|
||||||
int retval = ERROR_OK;
|
int retval;
|
||||||
|
|
||||||
/* skip command character */
|
/* skip command character */
|
||||||
packet++;
|
packet++;
|
||||||
|
@ -1449,7 +1449,11 @@ static int gdb_read_memory_packet(struct connection *connection,
|
||||||
|
|
||||||
LOG_DEBUG("addr: 0x%16.16" PRIx64 ", 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);
|
retval = ERROR_NOT_IMPLEMENTED;
|
||||||
|
if (target->rtos != NULL)
|
||||||
|
retval = rtos_read_buffer(target, addr, len, buffer);
|
||||||
|
if (retval == ERROR_NOT_IMPLEMENTED)
|
||||||
|
retval = target_read_buffer(target, addr, len, buffer);
|
||||||
|
|
||||||
if ((retval != ERROR_OK) && !gdb_report_data_abort) {
|
if ((retval != ERROR_OK) && !gdb_report_data_abort) {
|
||||||
/* TODO : Here we have to lie and send back all zero's lest stack traces won't work.
|
/* TODO : Here we have to lie and send back all zero's lest stack traces won't work.
|
||||||
|
@ -1520,7 +1524,11 @@ static int gdb_write_memory_packet(struct connection *connection,
|
||||||
if (unhexify(buffer, separator, len) != len)
|
if (unhexify(buffer, separator, len) != len)
|
||||||
LOG_ERROR("unable to decode memory packet");
|
LOG_ERROR("unable to decode memory packet");
|
||||||
|
|
||||||
retval = target_write_buffer(target, addr, len, buffer);
|
retval = ERROR_NOT_IMPLEMENTED;
|
||||||
|
if (target->rtos != NULL)
|
||||||
|
retval = rtos_write_buffer(target, addr, len, buffer);
|
||||||
|
if (retval == ERROR_NOT_IMPLEMENTED)
|
||||||
|
retval = target_write_buffer(target, addr, len, buffer);
|
||||||
|
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
gdb_put_packet(connection, "OK", 2);
|
gdb_put_packet(connection, "OK", 2);
|
||||||
|
@ -1589,7 +1597,12 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
|
||||||
if (len) {
|
if (len) {
|
||||||
LOG_DEBUG("addr: 0x%" PRIx64 ", 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);
|
retval = ERROR_NOT_IMPLEMENTED;
|
||||||
|
if (target->rtos != NULL)
|
||||||
|
retval = rtos_write_buffer(target, addr, len, (uint8_t *)separator);
|
||||||
|
if (retval == ERROR_NOT_IMPLEMENTED)
|
||||||
|
retval = target_write_buffer(target, addr, len, (uint8_t *)separator);
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
gdb_connection->mem_write_error = true;
|
gdb_connection->mem_write_error = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue