1 /* Routines for handling XML memory maps provided by target. 2 3 Copyright (C) 2006-2012 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "memory-map.h" 22 #include "gdb_assert.h" 23 #include "exceptions.h" 24 25 #include "gdb_string.h" 26 27 #if !defined(HAVE_LIBEXPAT) 28 29 VEC(mem_region_s) * 30 parse_memory_map (const char *memory_map) 31 { 32 static int have_warned; 33 34 if (!have_warned) 35 { 36 have_warned = 1; 37 warning (_("Can not parse XML memory map; XML support was disabled " 38 "at compile time")); 39 } 40 41 return NULL; 42 } 43 44 #else /* HAVE_LIBEXPAT */ 45 46 #include "xml-support.h" 47 48 /* Internal parsing data passed to all XML callbacks. */ 49 struct memory_map_parsing_data 50 { 51 VEC(mem_region_s) **memory_map; 52 char property_name[32]; 53 }; 54 55 /* Handle the start of a <memory> element. */ 56 57 static void 58 memory_map_start_memory (struct gdb_xml_parser *parser, 59 const struct gdb_xml_element *element, 60 void *user_data, VEC(gdb_xml_value_s) *attributes) 61 { 62 struct memory_map_parsing_data *data = user_data; 63 struct mem_region *r = VEC_safe_push (mem_region_s, *data->memory_map, NULL); 64 ULONGEST *start_p, *length_p, *type_p; 65 66 start_p = xml_find_attribute (attributes, "start")->value; 67 length_p = xml_find_attribute (attributes, "length")->value; 68 type_p = xml_find_attribute (attributes, "type")->value; 69 70 mem_region_init (r); 71 r->lo = *start_p; 72 r->hi = r->lo + *length_p; 73 r->attrib.mode = *type_p; 74 r->attrib.blocksize = -1; 75 } 76 77 /* Handle the end of a <memory> element. Verify that any necessary 78 children were present. */ 79 80 static void 81 memory_map_end_memory (struct gdb_xml_parser *parser, 82 const struct gdb_xml_element *element, 83 void *user_data, const char *body_text) 84 { 85 struct memory_map_parsing_data *data = user_data; 86 struct mem_region *r = VEC_last (mem_region_s, *data->memory_map); 87 88 if (r->attrib.mode == MEM_FLASH && r->attrib.blocksize == -1) 89 gdb_xml_error (parser, _("Flash block size is not set")); 90 } 91 92 /* Handle the start of a <property> element by saving the name 93 attribute for later. */ 94 95 static void 96 memory_map_start_property (struct gdb_xml_parser *parser, 97 const struct gdb_xml_element *element, 98 void *user_data, VEC(gdb_xml_value_s) *attributes) 99 { 100 struct memory_map_parsing_data *data = user_data; 101 char *name; 102 103 name = xml_find_attribute (attributes, "name")->value; 104 snprintf (data->property_name, sizeof (data->property_name), "%s", name); 105 } 106 107 /* Handle the end of a <property> element and its value. */ 108 109 static void 110 memory_map_end_property (struct gdb_xml_parser *parser, 111 const struct gdb_xml_element *element, 112 void *user_data, const char *body_text) 113 { 114 struct memory_map_parsing_data *data = user_data; 115 char *name = data->property_name; 116 117 if (strcmp (name, "blocksize") == 0) 118 { 119 struct mem_region *r = VEC_last (mem_region_s, *data->memory_map); 120 121 r->attrib.blocksize = gdb_xml_parse_ulongest (parser, body_text); 122 } 123 else 124 gdb_xml_debug (parser, _("Unknown property \"%s\""), name); 125 } 126 127 /* Discard the constructed memory map (if an error occurs). */ 128 129 static void 130 clear_result (void *p) 131 { 132 VEC(mem_region_s) **result = p; 133 VEC_free (mem_region_s, *result); 134 *result = NULL; 135 } 136 137 /* The allowed elements and attributes for an XML memory map. */ 138 139 const struct gdb_xml_attribute property_attributes[] = { 140 { "name", GDB_XML_AF_NONE, NULL, NULL }, 141 { NULL, GDB_XML_AF_NONE, NULL, NULL } 142 }; 143 144 const struct gdb_xml_element memory_children[] = { 145 { "property", property_attributes, NULL, 146 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, 147 memory_map_start_property, memory_map_end_property }, 148 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 149 }; 150 151 const struct gdb_xml_enum memory_type_enum[] = { 152 { "ram", MEM_RW }, 153 { "rom", MEM_RO }, 154 { "flash", MEM_FLASH }, 155 { NULL, 0 } 156 }; 157 158 const struct gdb_xml_attribute memory_attributes[] = { 159 { "start", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 160 { "length", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 161 { "type", GDB_XML_AF_NONE, gdb_xml_parse_attr_enum, &memory_type_enum }, 162 { NULL, GDB_XML_AF_NONE, NULL, NULL } 163 }; 164 165 const struct gdb_xml_element memory_map_children[] = { 166 { "memory", memory_attributes, memory_children, GDB_XML_EF_REPEATABLE, 167 memory_map_start_memory, memory_map_end_memory }, 168 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 169 }; 170 171 const struct gdb_xml_element memory_map_elements[] = { 172 { "memory-map", NULL, memory_map_children, GDB_XML_EF_NONE, 173 NULL, NULL }, 174 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 175 }; 176 177 VEC(mem_region_s) * 178 parse_memory_map (const char *memory_map) 179 { 180 VEC(mem_region_s) *result = NULL; 181 struct cleanup *back_to; 182 struct memory_map_parsing_data data = { NULL }; 183 184 data.memory_map = &result; 185 back_to = make_cleanup (clear_result, &result); 186 if (gdb_xml_parse_quick (_("target memory map"), NULL, memory_map_elements, 187 memory_map, &data) == 0) 188 { 189 /* Parsed successfully, keep the result. */ 190 discard_cleanups (back_to); 191 return result; 192 } 193 194 do_cleanups (back_to); 195 return NULL; 196 } 197 198 #endif /* HAVE_LIBEXPAT */ 199