libdebugger/target: Add support for backend code writters

The call lets backends support special methods of writing code.

Updates #5098
This commit is contained in:
Chris Johns
2024-08-07 05:09:38 +00:00
parent 6a367f4689
commit 53a62631ac
2 changed files with 92 additions and 57 deletions
+72 -47
View File
@@ -217,22 +217,31 @@ rtems_debugger_target_swbreak_control(bool insert, uintptr_t addr, DB_UINT kind)
if (loc == swbreaks[i].address) {
size_t remaining;
if (!insert) {
if (target->breakpoint_size > 4)
memcpy(loc, swbreaks[i].contents, target->breakpoint_size);
else {
switch (target->breakpoint_size) {
case 4:
loc[3] = swbreaks[i].contents[3];
case 3:
loc[2] = swbreaks[i].contents[2];
case 2:
loc[1] = swbreaks[i].contents[1];
case 1:
loc[0] = swbreaks[i].contents[0];
break;
if (target->code_writer != NULL) {
r = target->code_writer(loc,
&swbreaks[i].contents[0],
target->breakpoint_size);
if (r < 0) {
return r;
}
} else {
if (target->breakpoint_size > 4) {
memcpy(loc, &swbreaks[i].contents[0], target->breakpoint_size);
} else {
switch (target->breakpoint_size) {
case 4:
loc[3] = swbreaks[i].contents[3];
case 3:
loc[2] = swbreaks[i].contents[2];
case 2:
loc[1] = swbreaks[i].contents[1];
case 1:
loc[0] = swbreaks[i].contents[0];
break;
}
}
rtems_debugger_target_cache_sync(&swbreaks[i]);
}
rtems_debugger_target_cache_sync(&swbreaks[i]);
--target->swbreaks.level;
remaining = (target->swbreaks.level - i) * swbreak_size;
memmove(&swbreaks[i], &swbreaks[i + 1], remaining);
@@ -287,27 +296,36 @@ rtems_debugger_target_swbreak_insert(void)
uint8_t* loc = swbreaks[i].address;
if (rtems_debugger_verbose())
rtems_debugger_printf("rtems-db: bp: in: %p\n", swbreaks[i].address);
if (target->breakpoint_size > 4)
memcpy(loc, &target->breakpoint[0], target->breakpoint_size);
else {
if (rtems_debugger_verbose())
rtems_debugger_printf("rtems-db: bp: in: %p %p %d %d %d\n",
loc, &target->breakpoint[0],
(int) target->breakpoint_size,
(int) i, (int) target->swbreaks.level);
switch (target->breakpoint_size) {
case 4:
loc[3] = target->breakpoint[3];
case 3:
loc[2] = target->breakpoint[2];
case 2:
loc[1] = target->breakpoint[1];
case 1:
loc[0] = target->breakpoint[0];
break;
if (target->code_writer != NULL) {
r = target->code_writer(loc,
&target->breakpoint[0],
target->breakpoint_size);
if (r < 0) {
return r;
}
} else {
if (target->breakpoint_size > 4) {
memcpy(loc, &target->breakpoint[0], target->breakpoint_size);
} else {
if (rtems_debugger_verbose())
rtems_debugger_printf("rtems-db: bp: in: %p %p %d %d %d\n",
loc, &target->breakpoint[0],
(int) target->breakpoint_size,
(int) i, (int) target->swbreaks.level);
switch (target->breakpoint_size) {
case 4:
loc[3] = target->breakpoint[3];
case 3:
loc[2] = target->breakpoint[2];
case 2:
loc[1] = target->breakpoint[1];
case 1:
loc[0] = target->breakpoint[0];
break;
}
}
r = rtems_debugger_target_cache_sync(&swbreaks[i]);
}
r = rtems_debugger_target_cache_sync(&swbreaks[i]);
}
}
return r;
@@ -328,22 +346,29 @@ rtems_debugger_target_swbreak_remove(void)
uint8_t* contents = &swbreaks[i].contents[0];
if (rtems_debugger_verbose())
rtems_debugger_printf("rtems-db: bp: out: %p\n", swbreaks[i].address);
if (target->breakpoint_size > 4)
memcpy(loc, contents, target->breakpoint_size);
else {
switch (target->breakpoint_size) {
case 4:
loc[3] = contents[3];
case 3:
loc[2] = contents[2];
case 2:
loc[1] = contents[1];
case 1:
loc[0] = contents[0];
break;
if (target->code_writer != NULL) {
r = target->code_writer(loc, contents, target->breakpoint_size);
if (r < 0) {
return r;
}
} else {
if (target->breakpoint_size > 4) {
memcpy(loc, contents, target->breakpoint_size);
} else {
switch (target->breakpoint_size) {
case 4:
loc[3] = contents[3];
case 3:
loc[2] = contents[2];
case 2:
loc[1] = contents[1];
case 1:
loc[0] = contents[0];
break;
}
}
r = rtems_debugger_target_cache_sync(&swbreaks[i]);
}
r = rtems_debugger_target_cache_sync(&swbreaks[i]);
}
}
return r;
+20 -10
View File
@@ -91,6 +91,15 @@ typedef struct rtems_debugger_target_swbreak {
uint8_t contents[RTEMS_DEBUGGER_TARGET_SWBREAK_MAX_SIZE];
} rtems_debugger_target_swbreak;
/**
* Target memory update handler. If set this is called to modify
* the executable memory. It may not be possible to make it
* read/write.
*/
typedef int (*rtems_debugger_target_code_writer)(void* address,
const void* data,
size_t size);
/**
* The target data.
*
@@ -99,16 +108,17 @@ typedef struct rtems_debugger_target_swbreak {
* the last entry is the size of the register table.
*/
typedef struct rtems_debugger_target {
int capabilities; /*<< The capabilities to report. */
size_t reg_num; /*<< The number of registers. */
const size_t* reg_offset; /*<< The reg offsettable, len = reg_num + 1. */
const uint8_t* breakpoint; /*<< The breakpoint instruction(s). */
size_t breakpoint_size; /*<< The breakpoint size. */
rtems_debugger_block swbreaks; /*<< The software breakpoint block. */
bool memory_access; /*<< Accessing target memory. */
jmp_buf access_return; /*<< Return from an access fault. */
uintptr_t step_bp_address; /*<< Stepping break point address */
rtems_id step_tid; /*<< Stepping task id */
int capabilities; /*<< The capabilities to report. */
size_t reg_num; /*<< The number of registers. */
const size_t* reg_offset; /*<< The reg offsettable, len = reg_num + 1. */
const uint8_t* breakpoint; /*<< The breakpoint instruction(s). */
size_t breakpoint_size; /*<< The breakpoint size. */
rtems_debugger_block swbreaks; /*<< The software breakpoint block. */
rtems_debugger_target_code_writer code_writer; /*<< If set use to write to code memory */
bool memory_access; /*<< Accessing target memory. */
jmp_buf access_return; /*<< Return from an access fault. */
uintptr_t step_bp_address; /*<< Stepping break point address */
rtems_id step_tid; /*<< Stepping task id */
} rtems_debugger_target;