X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fmemory-map.c;h=3eaddb18b9aa862cfcfd7195c3fd281501406651;hb=7b085b1c1c6896f2137f64e82992a208c66c9473;hp=e3f8a805d585b387223c13e1e85f783a9854ad46;hpb=f2d483c4477a03591f3b05a877560ce620990b7c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/memory-map.c b/gdb/memory-map.c index e3f8a805d5..3eaddb18b9 100644 --- a/gdb/memory-map.c +++ b/gdb/memory-map.c @@ -1,13 +1,12 @@ /* Routines for handling XML memory maps provided by target. - Copyright (C) 2006 - Free Software Foundation, Inc. + Copyright (C) 2006-2020 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -16,20 +15,14 @@ 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. */ + along with this program. If not, see . */ #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) * +std::vector parse_memory_map (const char *memory_map) { static int have_warned; @@ -41,238 +34,156 @@ parse_memory_map (const char *memory_map) "at compile time")); } - return NULL; + return std::vector (); } #else /* HAVE_LIBEXPAT */ #include "xml-support.h" -#include - -#ifndef XML_STATUS_OK -# define XML_STATUS_OK 1 -# define XML_STATUS_ERROR 0 -#endif -/* Internal parsing data passed to all Expat callbacks. */ +/* Internal parsing data passed to all XML 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_; + memory_map_parsing_data (std::vector *memory_map_) + : memory_map (memory_map_) + {} - xfree (p->character_data); -} + std::vector *memory_map; -/* 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. + std::string property_name; +}; - 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. */ +/* Handle the start of a element. */ static void -memory_map_start_element (void *data_, const XML_Char *name, - const XML_Char **attrs) +memory_map_start_memory (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, + void *user_data, + std::vector &attributes) { - 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); + struct memory_map_parsing_data *data + = (struct memory_map_parsing_data *) user_data; + ULONGEST *start_p, *length_p, *type_p; + + start_p + = (ULONGEST *) xml_find_attribute (attributes, "start")->value.get (); + length_p + = (ULONGEST *) xml_find_attribute (attributes, "length")->value.get (); + type_p + = (ULONGEST *) xml_find_attribute (attributes, "type")->value.get (); + + data->memory_map->emplace_back (*start_p, *start_p + *length_p, + (enum mem_access_mode) *type_p); } -/* 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. */ +/* Handle the end of a element. Verify that any necessary + children were present. */ static void -memory_map_end_element (void *data_, const XML_Char *name) +memory_map_end_memory (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, + void *user_data, const char *body_text) { - struct memory_map_parsing_data *data = data_; - struct gdb_exception ex; + struct memory_map_parsing_data *data + = (struct memory_map_parsing_data *) user_data; + const mem_region &r = data->memory_map->back (); - 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); + if (r.attrib.mode == MEM_FLASH && r.attrib.blocksize == -1) + gdb_xml_error (parser, _("Flash block size is not set")); } -/* 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. +/* Handle the start of a element by saving the name + attribute for later. */ - 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) +memory_map_start_property (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, + void *user_data, + std::vector &attributes) { - 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. + struct memory_map_parsing_data *data + = (struct memory_map_parsing_data *) user_data; + char *name; - 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'; + name = (char *) xml_find_attribute (attributes, "name")->value.get (); + data->property_name.assign (name); } +/* Handle the end of a element and its value. */ + static void -clear_result (void *p) +memory_map_end_property (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, + void *user_data, const char *body_text) { - VEC(mem_region_s) **result = p; - VEC_free (mem_region_s, *result); - *result = NULL; + struct memory_map_parsing_data *data + = (struct memory_map_parsing_data *) user_data; + + if (data->property_name == "blocksize") + { + mem_region &r = data->memory_map->back (); + + r.attrib.blocksize = gdb_xml_parse_ulongest (parser, body_text); + } + else + gdb_xml_debug (parser, _("Unknown property \"%s\""), + data->property_name.c_str ()); } -VEC(mem_region_s) * +/* The allowed elements and attributes for an XML memory map. */ + +const struct gdb_xml_attribute property_attributes[] = { + { "name", GDB_XML_AF_NONE, NULL, NULL }, + { NULL, GDB_XML_AF_NONE, NULL, NULL } +}; + +const struct gdb_xml_element memory_children[] = { + { "property", property_attributes, NULL, + GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, + memory_map_start_property, memory_map_end_property }, + { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } +}; + +const struct gdb_xml_enum memory_type_enum[] = { + { "ram", MEM_RW }, + { "rom", MEM_RO }, + { "flash", MEM_FLASH }, + { NULL, 0 } +}; + +const struct gdb_xml_attribute memory_attributes[] = { + { "start", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, + { "length", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, + { "type", GDB_XML_AF_NONE, gdb_xml_parse_attr_enum, &memory_type_enum }, + { NULL, GDB_XML_AF_NONE, NULL, NULL } +}; + +const struct gdb_xml_element memory_map_children[] = { + { "memory", memory_attributes, memory_children, GDB_XML_EF_REPEATABLE, + memory_map_start_memory, memory_map_end_memory }, + { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } +}; + +const struct gdb_xml_element memory_map_elements[] = { + { "memory-map", NULL, memory_map_children, GDB_XML_EF_NONE, + NULL, NULL }, + { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } +}; + +std::vector 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); + std::vector ret; + memory_map_parsing_data data (&ret); - throw_error (XML_PARSE_ERROR, "%s", XML_ErrorString (err)); - } - } - if (ex.reason != GDB_NO_ERROR) + if (gdb_xml_parse_quick (_("target memory map"), NULL, memory_map_elements, + memory_map, &data) == 0) { - if (ex.error == XML_PARSE_ERROR) - /* Just report it. */ - warning (_("Could not parse XML memory map: %s"), ex.message); - else - throw_exception (ex); + /* Parsed successfully, keep the result. */ + return ret; } - else - /* Parsed successfully, don't need to delete the result. */ - discard_cleanups (before_deleting_result); - out: - do_cleanups (back_to); - return result; + return std::vector (); } #endif /* HAVE_LIBEXPAT */