1 /* Routines for handling XML memory maps provided by target. 2 3 Copyright (C) 2006-2016 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 23 #if !defined(HAVE_LIBEXPAT) 24 25 VEC(mem_region_s) * 26 parse_memory_map (const char *memory_map) 27 { 28 static int have_warned; 29 30 if (!have_warned) 31 { 32 have_warned = 1; 33 warning (_("Can not parse XML memory map; XML support was disabled " 34 "at compile time")); 35 } 36 37 return NULL; 38 } 39 40 #else /* HAVE_LIBEXPAT */ 41 42 #include "xml-support.h" 43 44 /* Internal parsing data passed to all XML callbacks. */ 45 struct memory_map_parsing_data 46 { 47 VEC(mem_region_s) **memory_map; 48 char property_name[32]; 49 }; 50 51 /* Handle the start of a <memory> element. */ 52 53 static void 54 memory_map_start_memory (struct gdb_xml_parser *parser, 55 const struct gdb_xml_element *element, 56 void *user_data, VEC(gdb_xml_value_s) *attributes) 57 { 58 struct memory_map_parsing_data *data 59 = (struct memory_map_parsing_data *) user_data; 60 struct mem_region *r = VEC_safe_push (mem_region_s, *data->memory_map, NULL); 61 ULONGEST *start_p, *length_p, *type_p; 62 63 start_p 64 = (ULONGEST *) xml_find_attribute (attributes, "start")->value; 65 length_p 66 = (ULONGEST *) xml_find_attribute (attributes, "length")->value; 67 type_p 68 = (ULONGEST *) 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 = (enum mem_access_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 86 = (struct memory_map_parsing_data *) user_data; 87 struct mem_region *r = VEC_last (mem_region_s, *data->memory_map); 88 89 if (r->attrib.mode == MEM_FLASH && r->attrib.blocksize == -1) 90 gdb_xml_error (parser, _("Flash block size is not set")); 91 } 92 93 /* Handle the start of a <property> element by saving the name 94 attribute for later. */ 95 96 static void 97 memory_map_start_property (struct gdb_xml_parser *parser, 98 const struct gdb_xml_element *element, 99 void *user_data, VEC(gdb_xml_value_s) *attributes) 100 { 101 struct memory_map_parsing_data *data 102 = (struct memory_map_parsing_data *) user_data; 103 char *name; 104 105 name = (char *) xml_find_attribute (attributes, "name")->value; 106 snprintf (data->property_name, sizeof (data->property_name), "%s", name); 107 } 108 109 /* Handle the end of a <property> element and its value. */ 110 111 static void 112 memory_map_end_property (struct gdb_xml_parser *parser, 113 const struct gdb_xml_element *element, 114 void *user_data, const char *body_text) 115 { 116 struct memory_map_parsing_data *data 117 = (struct memory_map_parsing_data *) user_data; 118 char *name = data->property_name; 119 120 if (strcmp (name, "blocksize") == 0) 121 { 122 struct mem_region *r = VEC_last (mem_region_s, *data->memory_map); 123 124 r->attrib.blocksize = gdb_xml_parse_ulongest (parser, body_text); 125 } 126 else 127 gdb_xml_debug (parser, _("Unknown property \"%s\""), name); 128 } 129 130 /* Discard the constructed memory map (if an error occurs). */ 131 132 static void 133 clear_result (void *p) 134 { 135 VEC(mem_region_s) **result = (VEC(mem_region_s) **) p; 136 VEC_free (mem_region_s, *result); 137 *result = NULL; 138 } 139 140 /* The allowed elements and attributes for an XML memory map. */ 141 142 const struct gdb_xml_attribute property_attributes[] = { 143 { "name", GDB_XML_AF_NONE, NULL, NULL }, 144 { NULL, GDB_XML_AF_NONE, NULL, NULL } 145 }; 146 147 const struct gdb_xml_element memory_children[] = { 148 { "property", property_attributes, NULL, 149 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, 150 memory_map_start_property, memory_map_end_property }, 151 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 152 }; 153 154 const struct gdb_xml_enum memory_type_enum[] = { 155 { "ram", MEM_RW }, 156 { "rom", MEM_RO }, 157 { "flash", MEM_FLASH }, 158 { NULL, 0 } 159 }; 160 161 const struct gdb_xml_attribute memory_attributes[] = { 162 { "start", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 163 { "length", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 164 { "type", GDB_XML_AF_NONE, gdb_xml_parse_attr_enum, &memory_type_enum }, 165 { NULL, GDB_XML_AF_NONE, NULL, NULL } 166 }; 167 168 const struct gdb_xml_element memory_map_children[] = { 169 { "memory", memory_attributes, memory_children, GDB_XML_EF_REPEATABLE, 170 memory_map_start_memory, memory_map_end_memory }, 171 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 172 }; 173 174 const struct gdb_xml_element memory_map_elements[] = { 175 { "memory-map", NULL, memory_map_children, GDB_XML_EF_NONE, 176 NULL, NULL }, 177 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 178 }; 179 180 VEC(mem_region_s) * 181 parse_memory_map (const char *memory_map) 182 { 183 VEC(mem_region_s) *result = NULL; 184 struct cleanup *back_to; 185 struct memory_map_parsing_data data = { NULL }; 186 187 data.memory_map = &result; 188 back_to = make_cleanup (clear_result, &result); 189 if (gdb_xml_parse_quick (_("target memory map"), NULL, memory_map_elements, 190 memory_map, &data) == 0) 191 { 192 /* Parsed successfully, keep the result. */ 193 discard_cleanups (back_to); 194 return result; 195 } 196 197 do_cleanups (back_to); 198 return NULL; 199 } 200 201 #endif /* HAVE_LIBEXPAT */ 202