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:
David Brownell 2010-01-19 23:32:54 -08:00
parent bf1e9a83c8
commit 44aaba3d08
1 changed files with 116 additions and 107 deletions

View File

@ -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)
{
/* 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 gdb_connection *gdb_connection = connection->priv;
@ -1747,112 +1859,9 @@ static int gdb_query_packet(struct connection *connection,
return ERROR_OK;
}
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
* 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:memory-map:read::")
&& (flash_get_bank_count() > 0))
return gdb_memory_map(connection, target, packet, packet_size);
else if (strstr(packet, "qXfer:features:read:"))
{
char *xml = NULL;