diff options
author | Daniel Jacobowitz <dan@debian.org> | 2006-09-21 13:54:03 +0000 |
---|---|---|
committer | Daniel Jacobowitz <dan@debian.org> | 2006-09-21 13:54:03 +0000 |
commit | 0db1deea44f24680af47168d22114a3d3c91bd7f (patch) | |
tree | eadf9391ef39e78b94b3cea7f2b098fdc44f7290 /gdb/memory-map.c | |
parent | cdbf4cd48d4c74ddb4859dd2bb7dda31cbf465f1 (diff) | |
download | gdb-0db1deea44f24680af47168d22114a3d3c91bd7f.tar.gz |
gdb/
2006-09-21 Vladimir Prus <vladimir@codesourcery.com>
Daniel Jacobowitz <dan@codesourcery.com>
Nathan Sidwell <nathan@codesourcery.com>
* Makefile.in (SFILES): Add memory-map.c and xml-support.c.
(memory_map_h, xml_support_h): New.
(target_h): Add vec_h dependency.
(COMMON_OBS): Add memory-map.o and xml-support.o.
(memory-map.o, xml-support.o): New rules.
(remote.o): Update.
* exceptions.h (enum errors): Add XML_PARSE_ERROR.
* infcmd.c (run_command_1, attach_command): Call target_pre_inferior.
* memattr.c (default_mem_attrib): Initialize blocksize.
(target_mem_region_list, mem_use_target)
(target_mem_regions_valid, mem_region_cmp, mem_region_init)
(require_user_regions, require_target_regions)
(invalidate_target_mem_regions): New.
(create_mem_region): Use mem_region_init.
(mem_clear): Move higher.
(lookup_mem_region): Use require_target_regions.
(mem_command): Implement "mem auto".
(mem_info_command): Handle target-supplied regions and flash
attributes.
(mem_enable_command, mem_disable_command, mem_delete_command): Use
require_user_regions.
(_initialize_mem): Mention "mem auto" in help.
* memattr.h (enum mem_access_mode): Add MEM_FLASH.
(struct mem_attrib): Add blocksize.
(invalidate_target_mem_regions, mem_region_init, mem_region_cmp): New
prototypes.
* remote.c: Include "memory-map.h".
(PACKET_qXfer_memory_map): New enum value.
(remote_protocol_features): Add qXfer:memory-map:read.
(remote_xfer_partial): Handle memory maps.
(remote_memory_map): New.
(init_remote_ops, init_remote_async_ops): Set to_memory_map.
(_initialize_remote): Register qXfer:memory-map:read.
* target.c (update_current_target): Mention to_memory_map.
(target_memory_map, target_pre_inferior): New.
(target_preopen): Call target_pre_inferior.
* target.h: Include "vec.h".
(enum target_object): Add TARGET_OBJECT_MEMORY_MAP.
(struct target_ops): Add to_memory_map.
(target_memory_map, target_pre_inferior): New prototypes.
* memory-map.c, memory-map.h, xml-support.c, xml-support.h: New files.
gdb/doc/
2006-09-21 Vladimir Prus <vladimir@codesourcery.com>
Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (Memory Region Attributes): Mention target-supplied
memory regions and "mem auto".
Diffstat (limited to 'gdb/memory-map.c')
-rw-r--r-- | gdb/memory-map.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/gdb/memory-map.c b/gdb/memory-map.c new file mode 100644 index 00000000000..01171c10fd0 --- /dev/null +++ b/gdb/memory-map.c @@ -0,0 +1,273 @@ +/* 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 "gdb_string.h" + +#if !defined(HAVE_LIBEXPAT) + +VEC(mem_region_s) * +parse_memory_map (const char *memory_map) +{ + static int have_warned; + + if (!have_warned) + { + have_warned = 1; + warning (_("Can not parse XML memory map; XML support was disabled " + "at compile time")); + } + + return NULL; +} + +#else /* HAVE_LIBEXPAT */ + +#include "xml-support.h" +#include <expat.h> + +/* Internal parsing data passed to all Expat callbacks. */ +struct memory_map_parsing_data + { + VEC(mem_region_s) **memory_map; + struct mem_region *currently_parsing; + 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); +} + +/* 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 a new memory region and initializes it + from attributes. Sets DATA_.currently_parsing 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) +{ + static const XML_Char *type_names[] = {"ram", "rom", "flash", 0}; + static int type_values[] = { MEM_RW, MEM_RO, MEM_FLASH }; + struct memory_map_parsing_data *data = data_; + struct gdb_exception ex; + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + if (strcmp (name, "memory") == 0) + { + struct mem_region *r; + + r = VEC_safe_push (mem_region_s, *data->memory_map, NULL); + mem_region_init (r); + + r->lo = xml_get_integer_attribute (attrs, "start"); + r->hi = r->lo + xml_get_integer_attribute (attrs, "length"); + r->attrib.mode = xml_get_enum_value (attrs, "type", type_names, + type_values); + r->attrib.blocksize = -1; + + data->currently_parsing = r; + } + else if (strcmp (name, "property") == 0) + { + if (!data->currently_parsing) + throw_error (XML_PARSE_ERROR, + _("memory map: found 'property' element outside 'memory'")); + + data->capture_text = 1; + + data->property_name = xml_get_required_attribute (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 a pointer + to our memory_map_parsing_data. NAME is the name of the element. + + This function handles the following elements: + - 'property' -- check that the property name is 'blocksize' and + sets DATA->currently_parsing->attrib.blocksize + - '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_PARSE_ERROR, + _("Empty content of 'property' element")); + char *end = NULL; + data->currently_parsing->attrib.blocksize + = strtoul (data->character_data, &end, 0); + if (*end != '\0') + throw_error (XML_PARSE_ERROR, + _("Invalid content of the 'blocksize' property")); + } + else + throw_error (XML_PARSE_ERROR, + _("Unknown memory region property: %s"), name); + + data->capture_text = 0; + } + else if (strcmp (name, "memory") == 0) + { + if (data->currently_parsing->attrib.mode == MEM_FLASH + && data->currently_parsing->attrib.blocksize == -1) + throw_error (XML_PARSE_ERROR, + _("Flash block size is not set")); + + data->currently_parsing = 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(mem_region_s) **result = p; + VEC_free (mem_region_s, *result); + *result = NULL; +} + +VEC(mem_region_s) * +parse_memory_map (const char *memory_map) +{ + VEC(mem_region_s) *result = NULL; + 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_free_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_PARSE_ERROR, "%s", XML_ErrorString (err)); + } + } + if (ex.reason != GDB_NO_ERROR) + { + if (ex.error == XML_PARSE_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 the result. */ + discard_cleanups (before_deleting_result); + + out: + do_cleanups (back_to); + return result; +} + +#endif /* HAVE_LIBEXPAT */ |