Re: Flash support part 1: memory maps

Vladimir Prus
2006-07-31T13:20:40Z

[-- Attachment #1: Type: text/plain, Size: 1059 bytes --]

On Monday 31 July 2006 17:00, Vladimir Prus wrote:
> On Friday 21 July 2006 19:20, Eli Zaretskii wrote:
> > > From: Vladimir Prus <vladimir@codesourcery.com>
> > > Date: Fri, 21 Jul 2006 15:35:29 +0400
> > > Cc: gdb-patches@sources.redhat.com
> > >
> > > > > + if (!data->character_data)
> > > > > + data->character_data = (char *)malloc (len + 1);
> > > > > + else
> > > > > + {
> > > > > + current_size = strlen (data->character_data);
> > > > > + data->character_data = (char *)realloc
> > > > > (data->character_data, +
> > > > > current_size + len + 1);
> > > >
> > > > Why do we need to cast the results of malloc and realloc?
> > >
> > > Ah, yea, we don't need this in C.
> >
> > In fact, I think you should replace these with xmalloc and xrealloc.
>
> Here's a patch that does exactly that, and is also based on the current
> mainline (and so uses target_read_stralloc).

Sorry, that patch included some extra changes and did not include some neede
ones. This one is correct.

- Volodya

[-- Attachment #2: memory_map__gdb.diff --]
[-- Type: text/x-diff, Size: 28448 bytes --]

=== gdb/target.c
==================================================================
--- gdb/target.c (/mirrors/gdb) (revision 326)
+++ gdb/target.c (/patches/memory_map/gdb) (revision 326)
@@ -456,6 +456,7 @@
INHERIT (to_make_corefile_notes, t);
INHERIT (to_get_thread_local_address, t);
INHERIT (to_magic, t);
+ /* Do not inherit to_memory_map. */
}
#undef INHERIT

@@ -1011,6 +1012,50 @@
return target_xfer_memory (memaddr, bytes, len, 1);
}

+
+VEC(memory_region) *
+target_memory_map (void)
+{
+ struct target_ops *t;
+
+ for (t = current_target.beneath; t != NULL; t = t->beneath)
+ if (t->to_memory_map != NULL)
+ {
+ VEC(memory_region) *result;
+ int i;
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog, "target_memory_map\n");
+
+ result = t->to_memory_map (t);
+
+ qsort (VEC_address (memory_region, result),
+ VEC_length (memory_region, result),
+ sizeof (memory_region),
+ compare_memory_region_starting_address);
+
+ /* Check that regions do not overlap. */
+ if (!VEC_empty (memory_region, result))
+ for (i = 0; i < VEC_length (memory_region, result) - 1; ++i)
+ {
+ memory_region *this_one = VEC_index (memory_region, result, i);
+ memory_region *next_one = VEC_index
+ (memory_region, result, i+1);
+
+ if (this_one->end > next_one->begin)
+ {
+ warning (_("Overlapping regions in memory map: ignoring"));
+ VEC_free (memory_region, result);
+ return 0;
+ }
+ }
+
+ return result;
+ }
+
+ tcomplain ();
+}
+
#ifndef target_stopped_data_address_p
int
target_stopped_data_address_p (struct target_ops *target)
=== gdb/remote.c
==================================================================
--- gdb/remote.c (/mirrors/gdb) (revision 326)
+++ gdb/remote.c (/patches/memory_map/gdb) (revision 326)
@@ -60,6 +60,8 @@

#include "remote-fileio.h"

+#include "memory-map.h"
+
/* The size to align memory write packets, when practical. The protocol
does not guarantee any alignment, and gdb will generate short
writes and unaligned writes, but even as a best-effort attempt this
@@ -233,6 +235,15 @@
a buffer in the stub), this will be set to that packet size.
Otherwise zero, meaning to use the guessed size. */
long explicit_packet_size;
+
+ /* The memory map we've obtained from remote. */
+ VEC(memory_region) *current_memory_map;
+
+ /* Tells if we've already fetched memory map. If non-zero,
+ we don't need to try again. Note that if we've tried to
+ fetch memory map but failed, this field will be non-zero,
+ while CURRENT_MEMORY_MAP will be NULL. */
+ int fetched_memory_map;
};

/* This data could be associated with a target, but we do not always
@@ -349,6 +360,9 @@
rs->buf = xrealloc (rs->buf, rs->buf_size);
}

+ rs->current_memory_map = NULL;
+ rs->fetched_memory_map = 0;
+
return rsa;
}

@@ -826,6 +840,7 @@
PACKET_Z3,
PACKET_Z4,
PACKET_qXfer_auxv,
+ PACKET_qXfer_memory_map,
PACKET_qGetTLSAddr,
PACKET_qSupported,
PACKET_MAX
@@ -2177,7 +2192,9 @@
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
- PACKET_qXfer_auxv }
+ PACKET_qXfer_auxv },
+ { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_memory_map }
};

static void
@@ -2373,6 +2390,11 @@
use_threadinfo_query = 1;
use_threadextra_query = 1;

+ /* After connect, memory map is not valid. */
+ rs->fetched_memory_map = 0;
+ VEC_free (memory_region, rs->current_memory_map);
+ rs->current_memory_map = NULL;
+
/* The first packet we send to the target is the optional "supported
packets" request. If the target can answer this, it will tell us
which later probes to skip. */
@@ -5312,6 +5334,11 @@
return remote_read_qxfer (ops, "auxv", annex, readbuf, offset, len,
&remote_protocol_packets[PACKET_qXfer_auxv]);

+ case TARGET_OBJECT_MEMORY_MAP:
+ gdb_assert (annex == NULL);
+ return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
+ &remote_protocol_packets[PACKET_qXfer_memory_map]);
+
default:
return -1;
}
@@ -5420,6 +5447,29 @@
}
}

+static VEC(memory_region) *
+remote_memory_map (struct target_ops *ops)
+{
+ struct cleanup *back_to = make_cleanup (null_cleanup, 0);
+ struct remote_state *rs = get_remote_state ();
+
+ if (!rs->fetched_memory_map)
+ {
+ char *text = target_read_stralloc (&current_target,
+ TARGET_OBJECT_MEMORY_MAP, NULL);
+ if (text)
+ {
+ make_cleanup (free_current_contents, &text);
+
+ rs->fetched_memory_map = 1;
+ rs->current_memory_map = parse_memory_map (text);
+ }
+ }
+
+ do_cleanups (back_to);
+ return rs->current_memory_map;
+}
+
static void
packet_command (char *args, int from_tty)
{
@@ -5692,6 +5742,7 @@
remote_ops.to_has_execution = 1;
remote_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */
remote_ops.to_magic = OPS_MAGIC;
+ remote_ops.to_memory_map = remote_memory_map;
}

/* Set up the extended remote vector by making a copy of the standard
@@ -5821,6 +5872,7 @@
remote_async_ops.to_async = remote_async;
remote_async_ops.to_async_mask_value = 1;
remote_async_ops.to_magic = OPS_MAGIC;
+ remote_async_ops.to_memory_map = remote_memory_map;
}

/* Set up the async extended remote vector by making a copy of the standard
@@ -6061,6 +6113,9 @@
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_auxv],
"qXfer:auxv:read", "read-aux-vector", 0);

+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map],
+ "qXfer:memory-map:read", "memory-map", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr],
"qGetTLSAddr", "get-thread-local-storage-address",
0);
=== gdb/target.h
==================================================================
--- gdb/target.h (/mirrors/gdb) (revision 326)
+++ gdb/target.h (/patches/memory_map/gdb) (revision 326)
@@ -55,6 +55,8 @@
#include "symtab.h"
#include "dcache.h"
#include "memattr.h"
+#include "vec.h"
+#include "memory-map.h"

enum strata
{
@@ -194,7 +196,9 @@
/* Transfer auxilliary vector. */
TARGET_OBJECT_AUXV,
/* StackGhost cookie. See "sparc-tdep.c". */
- TARGET_OBJECT_WCOOKIE
+ TARGET_OBJECT_WCOOKIE,
+ /* Target memory map in XML format. */
+ TARGET_OBJECT_MEMORY_MAP,

/* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC, ... */
};
@@ -437,6 +441,20 @@
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len);

+ /* Returns the memory map for the target. The return value of 0 means
+ that no memory map is available. If a memory address does not fall
+ within any returned regions, it's assumed to be RAM. The returned
+ memory regions should not overlap.
+
+ The order of regions does not matter, as target_memory_map will
+ sort regions by starting address anyway. For that reason, this
+ function should not be called directly, only via target_memory_map.
+
+ This method is expected to cache the data if fetching it is slow.
+ The higher-level code has no way of knowing when memory map
+ could change, and so can't do caching itself. */
+ VEC(memory_region) * (*to_memory_map) (struct target_ops *);
+
int to_magic;
/* Need sub-structure for target machine related rather than comm related?
*/
@@ -575,6 +593,12 @@
extern int target_write_memory_partial (CORE_ADDR addr, gdb_byte *buf,
int len, int *err);

+/* Calls the first non-null to_memory_map pointer in target_stack.
+ Sorts the result by starting address and returns it. Additionally
+ checks that memory regions do not overlap. If they do, issues
+ a warning and returns empty vector. */
+VEC(memory_region) *target_memory_map (void);
+
extern char *child_pid_to_exec_file (int);

extern char *child_core_file_to_sym_file (char *);
=== gdb/memory-map.c
==================================================================
--- gdb/memory-map.c (/mirrors/gdb) (revision 326)
+++ gdb/memory-map.c (/patches/memory_map/gdb) (revision 326)
@@ -0,0 +1,363 @@
+/* Routines for handling XML memory maps provided by target.
+
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#include "defs.h"
+#include "memory-map.h"
+#include "gdb_assert.h"
+#include "exceptions.h"
+
+#include <expat.h>
+
+#include "gdb_string.h"
+
+/* Internal parsing data passed to all Expat callbacks. */
+struct memory_map_parsing_data
+ {
+ VEC(memory_region) **memory_map;
+ memory_region *currently_parsed;
+ char *character_data;
+ const char* property_name;
+ int capture_text;
+ };
+
+static void
+free_memory_map_parsing_data (void *p_)
+{
+ struct memory_map_parsing_data *p = p_;
+
+ xfree (p->character_data);
+}
+
+
+/* Returns the value of attribute ATTR from expat attribute list ATTRS.
+ If not found, calls 'error'. */
+const XML_Char *xml_get_attribute_value(const XML_Char **attrs,
+ const XML_Char *attr)
+{
+ const XML_Char **p;
+ for (p = attrs; *p; p += 2)
+ {
+ const char *name = p[0];
+ const char *val = p[1];
+
+ if (strcmp (name, attr) == 0)
+ return val;
+ }
+ throw_error (XML_MEMORY_MAP_ERROR, _("Can't find attribute %s"), attr);
+ return 0;
+}
+
+/* Parse a field VALSTR that we expect to contain an integer value.
+ The integer is returned in *VALP.
+ The string is parsed with the strtoul rountine.
+
+ Returns 0 for success, -1 for error. */
+static int
+xml_parse_unsigned_integer (const char *valstr, unsigned long *valp)
+{
+ char *endptr;
+ unsigned result;
+
+ if (*valstr == '\0')
+ return -1;
+
+ result = strtoul (valstr, &endptr, 0);
+ if (*endptr != '\0')
+ return -1;
+
+ *valp = result;
+ return 0;
+}
+
+/* Gets the value of an integer attribute, if it's present.
+ If the attribute is not found, or can't be parsed as integer,
+ calls error. */
+static unsigned long
+xml_get_integer_attribute (const XML_Char **attrs,
+ const XML_Char *attr)
+{
+ unsigned long result;
+ const XML_Char *value = xml_get_attribute_value (attrs, attr);
+
+ if (xml_parse_unsigned_integer (value, &result) != 0)
+ {
+ throw_error (XML_MEMORY_MAP_ERROR,
+ _("Can't convert value of attribute %s, %s, to integer"),
+ attr, value);
+ }
+ return result;
+}
+
+/* Obtains a value of attribute with enumerated type. In XML, enumerated
+ attributes have string as a value, and in C, they are represented as
+ values of enumerated type. This function maps the attribute onto
+ an integer value that can be immediately converted into enumerated
+ type.
+
+ First, obtains the string value of ATTR in ATTRS.
+ Then, finds the index of that value in XML_NAMES, which is a zero-terminated
+ array of strings. If found, returns the element of VALUES with that index.
+ Otherwise throws. */
+static int
+xml_get_enum_value (const XML_Char **attrs,
+ const XML_Char *attr,
+ const XML_Char **xml_names,
+ int *values)
+{
+ const XML_Char *value = xml_get_attribute_value (attrs, attr);
+
+ int i;
+ for (i = 0; xml_names[i]; ++i)
+ {
+ if (strcmp (xml_names[i], value) == 0)
+ return values[i];
+ }
+ throw_error (XML_MEMORY_MAP_ERROR,
+ _("Invalid enumerated value in XML: %s"), value);
+}
+
+/* Callback called by Expat on start of element.
+ DATA_ is pointer to memory_map_parsing_data
+ NAME is the name of element
+ ATTRS is the zero-terminated array of attribute names and
+ attribute values.
+
+ This function handles the following elements:
+ - 'memory' -- creates new memory region and initializes it
+ from attributes. sets DATA_.CURRENTLY_PARSED to the new region.
+ - 'properties' -- sets DATA.CAPTURE_TEXT. */
+static void
+memory_map_start_element (void* data_, const XML_Char *name,
+ const XML_Char **attrs)
+{
+ struct memory_map_parsing_data *data = data_;
+ struct gdb_exception ex;
+
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (strcmp (name, "memory") == 0)
+ {
+ struct memory_region *r =
+ VEC_safe_push (memory_region, *data->memory_map, NULL);
+
+ r->begin = xml_get_integer_attribute (attrs, "start");
+ r->end = r->begin + xml_get_integer_attribute (attrs, "length");
+
+ {
+ static const XML_Char* names[] = {"ram", "rom", "flash", 0};
+ static int values[] = {TARGET_MEMORY_RAM, TARGET_MEMORY_ROM,
+ TARGET_MEMORY_FLASH};
+
+ r->memory_type = xml_get_enum_value (attrs, "type", names, values);
+ }
+ r->flash_block_size = (unsigned)-1;
+
+ data->currently_parsed = r;
+ }
+ else if (strcmp (name, "property") == 0)
+ {
+ if (!data->currently_parsed)
+ throw_error (XML_MEMORY_MAP_ERROR,
+ _("memory map: found 'property' element outside 'memory'"));
+
+ data->capture_text = 1;
+
+ data->property_name = xml_get_attribute_value (attrs, "name");
+ }
+ }
+ if (ex.reason < 0)
+ throw_error
+ (ex.error, _("while parsing element %s:\n%s"), name, ex.message);
+
+}
+
+/* Callback called by Expat on start of element.
+ DATA_ is pointer to memory_map_parsing_data
+ NAME is the name of element
+
+ This function handles the following elements:
+ - 'property' -- check that property name is 'blocksize' and
+ sets DATA->CURRENT_PARSED->FLASH_BLOCK_SIZE
+ - 'memory' verifies that flash block size is set. */
+static void
+memory_map_end_element (void* data_, const XML_Char *name)
+{
+ struct memory_map_parsing_data *data = data_;
+ struct gdb_exception ex;
+
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (strcmp (name, "property") == 0)
+ {
+ if (strcmp (data->property_name, "blocksize") == 0)
+ {
+ if (!data->character_data)
+ throw_error (XML_MEMORY_MAP_ERROR,
+ _("Empty content of 'property' element"));
+ char *end = 0;
+ data->currently_parsed->flash_block_size =
+ strtoul (data->character_data, &end, 0);
+ if (*end != '\0')
+ throw_error (XML_MEMORY_MAP_ERROR,
+ _("Invalid content of the 'blocksize' property"));
+ }
+ else
+ throw_error (XML_MEMORY_MAP_ERROR,
+ _("Unknown memory region property: %s"), name);
+
+ data->capture_text = 0;
+ }
+ else if (strcmp (name, "memory") == 0)
+ {
+ if (data->currently_parsed->memory_type == TARGET_MEMORY_FLASH
+ && data->currently_parsed->flash_block_size == (unsigned)-1)
+ throw_error (XML_MEMORY_MAP_ERROR,
+ _("Flash block size is not set"));
+
+ data->currently_parsed = 0;
+ data->character_data = 0;
+ }
+ }
+ if (ex.reason < 0)
+ throw_error
+ (ex.error, _("while parsing element %s: \n%s"), name, ex.message);
+}
+
+/* Callback called by expat for all character data blocks.
+ DATA_ is the pointer to memory_map_parsing_data.
+ S is the point to character data.
+ LEN is the length of data; the data is not zero-terminated.
+
+ If DATA_->CAPTURE_TEXT is 1, appends this block of characters
+ to DATA_->CHARACTER_DATA. */
+static void
+memory_map_character_data (void *data_, const XML_Char *s,
+ int len)
+{
+ struct memory_map_parsing_data *data = data_;
+ int current_size = 0;
+
+ if (!data->capture_text)
+ return;
+
+ /* Expat interface does not guarantee that a single call to
+ a handler will be made. Actually, one call for each line
+ will be made, and character data can possibly span several
+ lines.
+
+ Take care to realloc the data if needed. */
+ if (!data->character_data)
+ data->character_data = xmalloc (len + 1);
+ else
+ {
+ current_size = strlen (data->character_data);
+ data->character_data = xrealloc (data->character_data,
+ current_size + len + 1);
+ }
+
+ memcpy (data->character_data + current_size, s, len);
+ data->character_data[current_size + len] = '\0';
+}
+
+static void
+clear_result (void *p)
+{
+ VEC(memory_region) **result = p;
+ VEC_free (memory_region, *result);
+ *result = 0;
+}
+
+static void
+cleanup_XML_parser (void *p)
+{
+ XML_Parser parser = p;
+ XML_ParserFree (parser);
+}
+
+
+VEC(memory_region) *
+parse_memory_map (const char *memory_map)
+{
+ VEC(memory_region) *result = 0;
+ struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+ struct cleanup *before_deleting_result;
+ struct cleanup *saved;
+ volatile struct gdb_exception ex;
+ int ok = 0;
+
+ struct memory_map_parsing_data data = {};
+
+ XML_Parser parser = XML_ParserCreateNS (NULL, '!');
+ if (parser == NULL)
+ goto out;
+
+ make_cleanup (cleanup_XML_parser, parser);
+ make_cleanup (free_memory_map_parsing_data, &data);
+ /* Note: 'clear_result' will zero 'result'. */
+ before_deleting_result = make_cleanup (clear_result, &result);
+
+
+ XML_SetElementHandler (parser, memory_map_start_element,
+ memory_map_end_element);
+ XML_SetCharacterDataHandler (parser, memory_map_character_data);
+ XML_SetUserData (parser, &data);
+ data.memory_map = &result;
+
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (XML_Parse (parser, memory_map, strlen (memory_map), 1)
+ != XML_STATUS_OK)
+ {
+ enum XML_Error err = XML_GetErrorCode (parser);
+
+ throw_error (XML_MEMORY_MAP_ERROR, "%s", XML_ErrorString (err));
+ }
+ }
+ if (ex.reason != GDB_NO_ERROR)
+ {
+ if (ex.error == XML_MEMORY_MAP_ERROR)
+ {
+ /* Just report it. */
+ warning (_("Could not parse XML memory map: %s"), ex.message);
+ }
+ else
+ {
+ throw_exception (ex);
+ }
+ }
+ else
+ {
+ /* Parsed successfully, don't need to delete result. */
+ discard_cleanups (before_deleting_result);
+ }
+
+ out:
+ do_cleanups (back_to);
+ return result;
+}
+
+int compare_memory_region_starting_address (const void* a, const void *b)
+{
+ ULONGEST a_begin = ((memory_region *)a)->begin;
+ ULONGEST b_begin = ((memory_region *)b)->begin;
+ return a_begin - b_begin;
+}
=== gdb/memory-map.h
==================================================================
--- gdb/memory-map.h (/mirrors/gdb) (revision 326)
+++ gdb/memory-map.h (/patches/memory_map/gdb) (revision 326)
@@ -0,0 +1,142 @@
+/* Routines for handling XML memory maps provided by target.
+
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+
+#ifndef MEMORY_MAP_H
+#define MEMORY_MAP_H
+
+#include "vec.h"
+
+/* Describes various kinds of memory regions. */
+enum memory_region_type
+ {
+ /* Memory that can be freely written and read. */
+ TARGET_MEMORY_RAM,
+ /* Memory that can't be written at all. */
+ TARGET_MEMORY_ROM,
+ /* Memory that can be written only using special operations. */
+ TARGET_MEMORY_FLASH
+ };
+
+/* Describes properties of a memory range. */
+typedef struct memory_region
+ {
+ /* The first address of the region. */
+ ULONGEST begin;
+ /* The past-the-end address of the region. */
+ ULONGEST end;
+ /* Type of the memory in this region. */
+ enum memory_region_type memory_type;
+ /* The size of flash memory sector. Some flash chips have non-uniform
+ sector sizes, for example small sectors at beginning and end.
+ In this case gdb will have to have several memory_region objects each
+ one having uniform sector size.
+ This field is defined only of MEMORY_TYPE == TARGET_MEMORY_FLASH. */
+ unsigned flash_block_size;
+ } memory_region;
+
+DEF_VEC_O(memory_region);
+
+/* Casts both A and B to memory_region, compares they starting addresses
+ and returns value less than zero, equal to zero, or greater then zero
+ if A's starting address is less than B's starting address, equal to,
+ or greater then, respectively. This function is suitable for sorting
+ vector of memory_regions with the qsort function. */
+int compare_memory_region_starting_address (const void* a, const void *b);
+
+/* Parses XML memory map passed as argument and returns the memory
+ regions it describes. On any error, emits error message and
+ returns 0. Does not throw. Ownership of result is passed to the caller. */
+VEC(memory_region) *parse_memory_map (const char *memory_map);
+
+#endif
+/* Routines for handling XML memory maps provided by target.
+
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+
+#ifndef MEMORY_MAP_H
+#define MEMORY_MAP_H
+
+#include "vec.h"
+
+/* Describes various kinds of memory regions. */
+enum memory_region_type
+ {
+ /* Memory that can be freely written and read. */
+ TARGET_MEMORY_RAM,
+ /* Memory that can't be written at all. */
+ TARGET_MEMORY_ROM,
+ /* Memory that can be written only using special operations. */
+ TARGET_MEMORY_FLASH
+ };
+
+/* Describes properties of a memory range. */
+typedef struct memory_region
+ {
+ /* The first address of the region. */
+ ULONGEST begin;
+ /* The past-the-end address of the region. */
+ ULONGEST end;
+ /* Type of the memory in this region. */
+ enum memory_region_type memory_type;
+ /* The size of flash memory sector. Some flash chips have non-uniform
+ sector sizes, for example small sectors at beginning and end.
+ In this case gdb will have to have several memory_region objects each
+ one having uniform sector size.
+ This field is defined only of MEMORY_TYPE == TARGET_MEMORY_FLASH. */
+ unsigned flash_block_size;
+ } memory_region;
+
+DEF_VEC_O(memory_region);
+
+/* Casts both A and B to memory_region, compares they starting addresses
+ and returns value less than zero, equal to zero, or greater then zero
+ if A's starting address is less than B's starting address, equal to,
+ or greater then, respectively. This function is suitable for sorting
+ vector of memory_regions with the qsort function. */
+int compare_memory_region_starting_address (const void* a, const void *b);
+
+/* Parses XML memory map passed as argument and returns the memory
+ regions it describes. On any error, emits error message and
+ returns 0. Does not throw. Ownership of result is passed to the caller. */
+VEC(memory_region) *parse_memory_map (const char *memory_map);
+
+#endif
=== gdb/Makefile.in
==================================================================
--- gdb/Makefile.in (/mirrors/gdb) (revision 326)
+++ gdb/Makefile.in (/patches/memory_map/gdb) (revision 326)
@@ -535,7 +535,7 @@
language.c linespec.c \
m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c \
macrotab.c macroexp.c macrocmd.c macroscope.c main.c maint.c \
- mdebugread.c memattr.c mem-break.c minsyms.c mipsread.c \
+ mdebugread.c memattr.c mem-break.c minsyms.c mipsread.c memory-map.c \
nlmread.c \
objc-exp.y objc-lang.c \
objfiles.c osabi.c observer.c \
@@ -745,6 +745,7 @@
mips_mdebug_tdep_h = mips-mdebug-tdep.h
mipsnbsd_tdep_h = mipsnbsd-tdep.h
mips_tdep_h = mips-tdep.h
+memory_map_h = memory-map.h $(vec_h)
mn10300_tdep_h = mn10300-tdep.h
monitor_h = monitor.h
nbsd_tdep_h = nbsd-tdep.h
@@ -794,7 +795,8 @@
stack_h = stack.h
symfile_h = symfile.h
symtab_h = symtab.h
-target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h)
+target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h) $(vec_h) \
+ $(memory_map_h)
terminal_h = terminal.h
top_h = top.h
tracepoint_h = tracepoint.h
@@ -953,7 +955,7 @@
trad-frame.o \
tramp-frame.o \
solib.o solib-null.o \
- prologue-value.o
+ prologue-value.o vec.o memory-map.o

TSOBS = inflow.o

@@ -2359,6 +2361,8 @@
$(floatformat_h)
mipsv4-nat.o: mipsv4-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(target_h) \
$(regcache_h) $(gregset_h)
+memory-map.o: memory-map.c $(defs_h) $(memory_map_h) $(gdb_assert_h) \
+ $(exceptions_h) $(gdb_string_h)
mn10300-linux-tdep.o: mn10300-linux-tdep.c $(defs_h) $(gdbcore_h) \
$(gdb_string_h) $(regcache_h) $(mn10300_tdep_h) $(gdb_assert_h) \
$(bfd_h) $(elf_bfd_h) $(osabi_h) $(regset_h) $(solib_svr4_h) \
@@ -2487,7 +2491,7 @@
$(gdb_stabs_h) $(gdbthread_h) $(remote_h) $(regcache_h) $(value_h) \
$(gdb_assert_h) $(event_loop_h) $(event_top_h) $(inf_loop_h) \
$(serial_h) $(gdbcore_h) $(remote_fileio_h) $(solib_h) $(observer_h) \
- $(cli_decode_h) $(cli_setshow_h)
+ $(cli_decode_h) $(cli_setshow_h) $(memory_map_h)
remote-e7000.o: remote-e7000.c $(defs_h) $(gdbcore_h) $(gdbarch_h) \
$(inferior_h) $(target_h) $(value_h) $(command_h) $(gdb_string_h) \
$(exceptions_h) $(gdbcmd_h) $(serial_h) $(remote_utils_h) \
=== gdb/exceptions.h
==================================================================
--- gdb/exceptions.h (/mirrors/gdb) (revision 326)
+++ gdb/exceptions.h (/patches/memory_map/gdb) (revision 326)
@@ -71,6 +71,9 @@
more detail. */
TLS_GENERIC_ERROR,

+ /* Problem parsing XML memory map. */
+ XML_MEMORY_MAP_ERROR,