1 /* Routines for handling XML memory maps provided by target. 2 3 Copyright (C) 2006-2015 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 = user_data; 59 struct mem_region *r = VEC_safe_push (mem_region_s, *data->memory_map, NULL); 60 ULONGEST *start_p, *length_p, *type_p; 61 62 start_p = xml_find_attribute (attributes, "start")->value; 63 length_p = xml_find_attribute (attributes, "length")->value; 64 type_p = xml_find_attribute (attributes, "type")->value; 65 66 mem_region_init (r); 67 r->lo = *start_p; 68 r->hi = r->lo + *length_p; 69 r->attrib.mode = *type_p; 70 r->attrib.blocksize = -1; 71 } 72 73 /* Handle the end of a <memory> element. Verify that any necessary 74 children were present. */ 75 76 static void 77 memory_map_end_memory (struct gdb_xml_parser *parser, 78 const struct gdb_xml_element *element, 79 void *user_data, const char *body_text) 80 { 81 struct memory_map_parsing_data *data = user_data; 82 struct mem_region *r = VEC_last (mem_region_s, *data->memory_map); 83 84 if (r->attrib.mode == MEM_FLASH && r->attrib.blocksize == -1) 85 gdb_xml_error (parser, _("Flash block size is not set")); 86 } 87 88 /* Handle the start of a <property> element by saving the name 89 attribute for later. */ 90 91 static void 92 memory_map_start_property (struct gdb_xml_parser *parser, 93 const struct gdb_xml_element *element, 94 void *user_data, VEC(gdb_xml_value_s) *attributes) 95 { 96 struct memory_map_parsing_data *data = user_data; 97 char *name; 98 99 name = xml_find_attribute (attributes, "name")->value; 100 snprintf (data->property_name, sizeof (data->property_name), "%s", name); 101 } 102 103 /* Handle the end of a <property> element and its value. */ 104 105 static void 106 memory_map_end_property (struct gdb_xml_parser *parser, 107 const struct gdb_xml_element *element, 108 void *user_data, const char *body_text) 109 { 110 struct memory_map_parsing_data *data = user_data; 111 char *name = data->property_name; 112 113 if (strcmp (name, "blocksize") == 0) 114 { 115 struct mem_region *r = VEC_last (mem_region_s, *data->memory_map); 116 117 r->attrib.blocksize = gdb_xml_parse_ulongest (parser, body_text); 118 } 119 else 120 gdb_xml_debug (parser, _("Unknown property \"%s\""), name); 121 } 122 123 /* Discard the constructed memory map (if an error occurs). */ 124 125 static void 126 clear_result (void *p) 127 { 128 VEC(mem_region_s) **result = p; 129 VEC_free (mem_region_s, *result); 130 *result = NULL; 131 } 132 133 /* The allowed elements and attributes for an XML memory map. */ 134 135 const struct gdb_xml_attribute property_attributes[] = { 136 { "name", GDB_XML_AF_NONE, NULL, NULL }, 137 { NULL, GDB_XML_AF_NONE, NULL, NULL } 138 }; 139 140 const struct gdb_xml_element memory_children[] = { 141 { "property", property_attributes, NULL, 142 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, 143 memory_map_start_property, memory_map_end_property }, 144 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 145 }; 146 147 const struct gdb_xml_enum memory_type_enum[] = { 148 { "ram", MEM_RW }, 149 { "rom", MEM_RO }, 150 { "flash", MEM_FLASH }, 151 { NULL, 0 } 152 }; 153 154 const struct gdb_xml_attribute memory_attributes[] = { 155 { "start", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 156 { "length", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 157 { "type", GDB_XML_AF_NONE, gdb_xml_parse_attr_enum, &memory_type_enum }, 158 { NULL, GDB_XML_AF_NONE, NULL, NULL } 159 }; 160 161 const struct gdb_xml_element memory_map_children[] = { 162 { "memory", memory_attributes, memory_children, GDB_XML_EF_REPEATABLE, 163 memory_map_start_memory, memory_map_end_memory }, 164 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 165 }; 166 167 const struct gdb_xml_element memory_map_elements[] = { 168 { "memory-map", NULL, memory_map_children, GDB_XML_EF_NONE, 169 NULL, NULL }, 170 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 171 }; 172 173 VEC(mem_region_s) * 174 parse_memory_map (const char *memory_map) 175 { 176 VEC(mem_region_s) *result = NULL; 177 struct cleanup *back_to; 178 struct memory_map_parsing_data data = { NULL }; 179 180 data.memory_map = &result; 181 back_to = make_cleanup (clear_result, &result); 182 if (gdb_xml_parse_quick (_("target memory map"), NULL, memory_map_elements, 183 memory_map, &data) == 0) 184 { 185 /* Parsed successfully, keep the result. */ 186 discard_cleanups (back_to); 187 return result; 188 } 189 190 do_cleanups (back_to); 191 return NULL; 192 } 193 194 #endif /* HAVE_LIBEXPAT */ 195