gdb_server -- subroutinize memory map logic
Put the memory map logic into its own subroutine. This will make it a bit easier to package bugfixes, and simplifies the query packet handling. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
This commit is contained in:
parent
bf1e9a83c8
commit
44aaba3d08
|
@ -1647,8 +1647,120 @@ static int compare_bank (const void * a, const void * b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gdb_query_packet(struct connection *connection,
|
static int gdb_memory_map(struct connection *connection,
|
||||||
struct target *target, char *packet, int packet_size)
|
struct target *target, char *packet, int packet_size)
|
||||||
|
{
|
||||||
|
/* We get away with only specifying flash here. Regions that are not
|
||||||
|
* specified are treated as if we provided no memory map(if not we
|
||||||
|
* could detect the holes and mark them as RAM).
|
||||||
|
* Normally we only execute this code once, but no big deal if we
|
||||||
|
* have to regenerate it a couple of times.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct flash_bank *p;
|
||||||
|
char *xml = NULL;
|
||||||
|
int size = 0;
|
||||||
|
int pos = 0;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
struct flash_bank **banks;
|
||||||
|
int offset;
|
||||||
|
int length;
|
||||||
|
char *separator;
|
||||||
|
int blocksize;
|
||||||
|
uint32_t ram_start = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* skip command character */
|
||||||
|
packet += 23;
|
||||||
|
|
||||||
|
offset = strtoul(packet, &separator, 16);
|
||||||
|
length = strtoul(separator + 1, &separator, 16);
|
||||||
|
|
||||||
|
xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
|
||||||
|
|
||||||
|
/* Sort banks in ascending order. We need to report non-flash
|
||||||
|
* memory as ram (or rather read/write) by default for GDB, since
|
||||||
|
* it has no concept of non-cacheable read/write memory (i/o etc).
|
||||||
|
*
|
||||||
|
* FIXME Most non-flash addresses are *NOT* RAM! Don't lie.
|
||||||
|
*/
|
||||||
|
banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
|
||||||
|
|
||||||
|
for (i = 0; i < flash_get_bank_count(); i++) {
|
||||||
|
p = get_flash_bank_by_num(i);
|
||||||
|
if (p == NULL) {
|
||||||
|
free(banks);
|
||||||
|
retval = ERROR_FAIL;
|
||||||
|
gdb_send_error(connection, retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
banks[i] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(banks, flash_get_bank_count(), sizeof(struct flash_bank *),
|
||||||
|
compare_bank);
|
||||||
|
|
||||||
|
for (i = 0; i < flash_get_bank_count(); i++) {
|
||||||
|
p = banks[i];
|
||||||
|
|
||||||
|
if (ram_start < p->base)
|
||||||
|
xml_printf(&retval, &xml, &pos, &size,
|
||||||
|
"<memory type=\"ram\" start=\"0x%x\" "
|
||||||
|
"length=\"0x%x\"/>\n",
|
||||||
|
ram_start, p->base-ram_start);
|
||||||
|
|
||||||
|
/* If device has uneven sector sizes, eg. str7, lpc
|
||||||
|
* we pass the smallest sector size to gdb memory map
|
||||||
|
*
|
||||||
|
* FIXME Don't lie about flash regions with different
|
||||||
|
* sector sizes; just tell GDB about each region as
|
||||||
|
* if it were a separate flash device.
|
||||||
|
*/
|
||||||
|
blocksize = gdb_calc_blocksize(p);
|
||||||
|
|
||||||
|
xml_printf(&retval, &xml, &pos, &size,
|
||||||
|
"<memory type=\"flash\" start=\"0x%x\" "
|
||||||
|
"length=\"0x%x\">\n" \
|
||||||
|
"<property name=\"blocksize\">0x%x</property>\n" \
|
||||||
|
"</memory>\n", \
|
||||||
|
p->base, p->size, blocksize);
|
||||||
|
ram_start = p->base + p->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ram_start != 0)
|
||||||
|
xml_printf(&retval, &xml, &pos, &size,
|
||||||
|
"<memory type=\"ram\" start=\"0x%x\" "
|
||||||
|
"length=\"0x%x\"/>\n",
|
||||||
|
ram_start, 0-ram_start);
|
||||||
|
/* ELSE a flash chip could be at the very end of the 32 bit address
|
||||||
|
* space, in which case ram_start will be precisely 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
free(banks);
|
||||||
|
banks = NULL;
|
||||||
|
|
||||||
|
xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
|
||||||
|
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
gdb_send_error(connection, retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset + length > pos)
|
||||||
|
length = pos - offset;
|
||||||
|
|
||||||
|
char *t = malloc(length + 1);
|
||||||
|
t[0] = 'l';
|
||||||
|
memcpy(t + 1, xml + offset, length);
|
||||||
|
gdb_put_packet(connection, t, length + 1);
|
||||||
|
|
||||||
|
free(t);
|
||||||
|
free(xml);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gdb_query_packet(struct connection *connection,
|
||||||
|
struct target *target, char *packet, int packet_size)
|
||||||
{
|
{
|
||||||
struct command_context *cmd_ctx = connection->cmd_ctx;
|
struct command_context *cmd_ctx = connection->cmd_ctx;
|
||||||
struct gdb_connection *gdb_connection = connection->priv;
|
struct gdb_connection *gdb_connection = connection->priv;
|
||||||
|
@ -1747,112 +1859,9 @@ static int gdb_query_packet(struct connection *connection,
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
else if (strstr(packet, "qXfer:memory-map:read::") && (flash_get_bank_count() > 0))
|
else if (strstr(packet, "qXfer:memory-map:read::")
|
||||||
{
|
&& (flash_get_bank_count() > 0))
|
||||||
/* We get away with only specifying flash here. Regions that are not
|
return gdb_memory_map(connection, target, packet, packet_size);
|
||||||
* specified are treated as if we provided no memory map(if not we
|
|
||||||
* could detect the holes and mark them as RAM).
|
|
||||||
* Normally we only execute this code once, but no big deal if we
|
|
||||||
* have to regenerate it a couple of times. */
|
|
||||||
|
|
||||||
struct flash_bank *p;
|
|
||||||
char *xml = NULL;
|
|
||||||
int size = 0;
|
|
||||||
int pos = 0;
|
|
||||||
int retval = ERROR_OK;
|
|
||||||
|
|
||||||
int offset;
|
|
||||||
int length;
|
|
||||||
char *separator;
|
|
||||||
int blocksize;
|
|
||||||
|
|
||||||
/* skip command character */
|
|
||||||
packet += 23;
|
|
||||||
|
|
||||||
offset = strtoul(packet, &separator, 16);
|
|
||||||
length = strtoul(separator + 1, &separator, 16);
|
|
||||||
|
|
||||||
xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
|
|
||||||
|
|
||||||
/*
|
|
||||||
sort banks in ascending order, we need to make non-flash memory be ram(or rather
|
|
||||||
read/write) by default for GDB.
|
|
||||||
GDB does not have a concept of non-cacheable read/write memory.
|
|
||||||
*/
|
|
||||||
struct flash_bank **banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < flash_get_bank_count(); i++)
|
|
||||||
{
|
|
||||||
p = get_flash_bank_by_num(i);
|
|
||||||
if (p == NULL)
|
|
||||||
{
|
|
||||||
free(banks);
|
|
||||||
retval = ERROR_FAIL;
|
|
||||||
gdb_send_error(connection, retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
banks[i]=p;
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(banks, flash_get_bank_count(), sizeof(struct flash_bank *), compare_bank);
|
|
||||||
|
|
||||||
uint32_t ram_start = 0;
|
|
||||||
for (i = 0; i < flash_get_bank_count(); i++)
|
|
||||||
{
|
|
||||||
p = banks[i];
|
|
||||||
|
|
||||||
if (ram_start < p->base)
|
|
||||||
{
|
|
||||||
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" length=\"0x%x\"/>\n",
|
|
||||||
ram_start, p->base-ram_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if device has uneven sector sizes, eg. str7, lpc
|
|
||||||
* we pass the smallest sector size to gdb memory map */
|
|
||||||
blocksize = gdb_calc_blocksize(p);
|
|
||||||
|
|
||||||
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
|
|
||||||
"<property name=\"blocksize\">0x%x</property>\n" \
|
|
||||||
"</memory>\n", \
|
|
||||||
p->base, p->size, blocksize);
|
|
||||||
ram_start = p->base + p->size;
|
|
||||||
}
|
|
||||||
if (ram_start != 0)
|
|
||||||
{
|
|
||||||
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" length=\"0x%x\"/>\n",
|
|
||||||
ram_start, 0-ram_start);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
/* a flash chip could be at the very end of the 32 bit address space, in which case
|
|
||||||
ram_start will be precisely 0 */
|
|
||||||
}
|
|
||||||
|
|
||||||
free(banks);
|
|
||||||
banks = NULL;
|
|
||||||
|
|
||||||
xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
|
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
|
||||||
{
|
|
||||||
gdb_send_error(connection, retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset + length > pos)
|
|
||||||
{
|
|
||||||
length = pos - offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *t = malloc(length + 1);
|
|
||||||
t[0] = 'l';
|
|
||||||
memcpy(t + 1, xml + offset, length);
|
|
||||||
gdb_put_packet(connection, t, length + 1);
|
|
||||||
|
|
||||||
free(t);
|
|
||||||
free(xml);
|
|
||||||
return ERROR_OK;
|
|
||||||
}
|
|
||||||
else if (strstr(packet, "qXfer:features:read:"))
|
else if (strstr(packet, "qXfer:features:read:"))
|
||||||
{
|
{
|
||||||
char *xml = NULL;
|
char *xml = NULL;
|
||||||
|
|
Loading…
Reference in New Issue