1 /* Functions that provide the mechanism to parse a syscall XML file 2 and get its values. 3 4 Copyright (C) 2009-2012 Free Software Foundation, Inc. 5 6 This file is part of GDB. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 #include "defs.h" 22 #include "gdbtypes.h" 23 #include "xml-support.h" 24 #include "xml-syscall.h" 25 26 /* For the struct syscall definition. */ 27 #include "target.h" 28 29 #include "filenames.h" 30 31 #include "gdb_assert.h" 32 33 #ifndef HAVE_LIBEXPAT 34 35 /* Dummy functions to indicate that there's no support for fetching 36 syscalls information. */ 37 38 static void 39 syscall_warn_user (void) 40 { 41 static int have_warned = 0; 42 if (!have_warned) 43 { 44 have_warned = 1; 45 warning (_("Can not parse XML syscalls information; XML support was " 46 "disabled at compile time.")); 47 } 48 } 49 50 void 51 set_xml_syscall_file_name (const char *name) 52 { 53 return; 54 } 55 56 void 57 get_syscall_by_number (int syscall_number, 58 struct syscall *s) 59 { 60 syscall_warn_user (); 61 s->number = syscall_number; 62 s->name = NULL; 63 } 64 65 void 66 get_syscall_by_name (const char *syscall_name, 67 struct syscall *s) 68 { 69 syscall_warn_user (); 70 s->number = UNKNOWN_SYSCALL; 71 s->name = syscall_name; 72 } 73 74 const char ** 75 get_syscall_names (void) 76 { 77 syscall_warn_user (); 78 return NULL; 79 } 80 81 #else /* ! HAVE_LIBEXPAT */ 82 83 /* Variable that will hold the last known data-directory. This is useful to 84 know whether we should re-read the XML info for the target. */ 85 static char *my_gdb_datadir = NULL; 86 87 /* Structure which describes a syscall. */ 88 typedef struct syscall_desc 89 { 90 /* The syscall number. */ 91 92 int number; 93 94 /* The syscall name. */ 95 96 char *name; 97 } *syscall_desc_p; 98 DEF_VEC_P(syscall_desc_p); 99 100 /* Structure that represents syscalls information. */ 101 struct syscalls_info 102 { 103 /* The syscalls. */ 104 105 VEC(syscall_desc_p) *syscalls; 106 }; 107 108 /* Callback data for syscall information parsing. */ 109 struct syscall_parsing_data 110 { 111 /* The syscalls_info we are building. */ 112 113 struct syscalls_info *sysinfo; 114 }; 115 116 /* Structure used to store information about the available syscalls in 117 the system. */ 118 static const struct syscalls_info *sysinfo = NULL; 119 120 /* A flag to tell if we already initialized the structure above. */ 121 static int have_initialized_sysinfo = 0; 122 123 /* The filename of the syscall's XML. */ 124 static const char *xml_syscall_file = NULL; 125 126 static struct syscalls_info * 127 allocate_syscalls_info (void) 128 { 129 return XZALLOC (struct syscalls_info); 130 } 131 132 static void 133 sysinfo_free_syscalls_desc (struct syscall_desc *sd) 134 { 135 xfree (sd->name); 136 } 137 138 static void 139 free_syscalls_info (void *arg) 140 { 141 struct syscalls_info *sysinfo = arg; 142 struct syscall_desc *sysdesc; 143 int i; 144 145 for (i = 0; 146 VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc); 147 i++) 148 sysinfo_free_syscalls_desc (sysdesc); 149 VEC_free (syscall_desc_p, sysinfo->syscalls); 150 151 xfree (sysinfo); 152 } 153 154 struct cleanup * 155 make_cleanup_free_syscalls_info (struct syscalls_info *sysinfo) 156 { 157 return make_cleanup (free_syscalls_info, sysinfo); 158 } 159 160 static void 161 syscall_create_syscall_desc (struct syscalls_info *sysinfo, 162 const char *name, int number) 163 { 164 struct syscall_desc *sysdesc = XZALLOC (struct syscall_desc); 165 166 sysdesc->name = xstrdup (name); 167 sysdesc->number = number; 168 169 VEC_safe_push (syscall_desc_p, sysinfo->syscalls, sysdesc); 170 } 171 172 /* Handle the start of a <syscall> element. */ 173 static void 174 syscall_start_syscall (struct gdb_xml_parser *parser, 175 const struct gdb_xml_element *element, 176 void *user_data, VEC(gdb_xml_value_s) *attributes) 177 { 178 struct syscall_parsing_data *data = user_data; 179 struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes); 180 int len, i; 181 /* syscall info. */ 182 char *name = NULL; 183 int number = 0; 184 185 len = VEC_length (gdb_xml_value_s, attributes); 186 187 for (i = 0; i < len; i++) 188 { 189 if (strcmp (attrs[i].name, "name") == 0) 190 name = attrs[i].value; 191 else if (strcmp (attrs[i].name, "number") == 0) 192 number = * (ULONGEST *) attrs[i].value; 193 else 194 internal_error (__FILE__, __LINE__, 195 _("Unknown attribute name '%s'."), attrs[i].name); 196 } 197 198 gdb_assert (name); 199 syscall_create_syscall_desc (data->sysinfo, name, number); 200 } 201 202 203 /* The elements and attributes of an XML syscall document. */ 204 static const struct gdb_xml_attribute syscall_attr[] = { 205 { "number", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 206 { "name", GDB_XML_AF_NONE, NULL, NULL }, 207 { NULL, GDB_XML_AF_NONE, NULL, NULL } 208 }; 209 210 static const struct gdb_xml_element syscalls_info_children[] = { 211 { "syscall", syscall_attr, NULL, 212 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, 213 syscall_start_syscall, NULL }, 214 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 215 }; 216 217 static const struct gdb_xml_element syselements[] = { 218 { "syscalls_info", NULL, syscalls_info_children, 219 GDB_XML_EF_NONE, NULL, NULL }, 220 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 221 }; 222 223 static struct syscalls_info * 224 syscall_parse_xml (const char *document, xml_fetch_another fetcher, 225 void *fetcher_baton) 226 { 227 struct cleanup *result_cleanup; 228 struct syscall_parsing_data data; 229 230 data.sysinfo = allocate_syscalls_info (); 231 result_cleanup = make_cleanup_free_syscalls_info (data.sysinfo); 232 233 if (gdb_xml_parse_quick (_("syscalls info"), NULL, 234 syselements, document, &data) == 0) 235 { 236 /* Parsed successfully. */ 237 discard_cleanups (result_cleanup); 238 return data.sysinfo; 239 } 240 else 241 { 242 warning (_("Could not load XML syscalls info; ignoring")); 243 do_cleanups (result_cleanup); 244 return NULL; 245 } 246 } 247 248 /* Function responsible for initializing the information 249 about the syscalls. It reads the XML file and fills the 250 struct syscalls_info with the values. 251 252 Returns the struct syscalls_info if the file is valid, NULL otherwise. */ 253 static const struct syscalls_info * 254 xml_init_syscalls_info (const char *filename) 255 { 256 char *full_file; 257 char *dirname; 258 struct syscalls_info *sysinfo; 259 struct cleanup *back_to; 260 261 full_file = xml_fetch_content_from_file (filename, gdb_datadir); 262 if (full_file == NULL) 263 return NULL; 264 265 back_to = make_cleanup (xfree, full_file); 266 267 dirname = ldirname (filename); 268 if (dirname != NULL) 269 make_cleanup (xfree, dirname); 270 271 sysinfo = syscall_parse_xml (full_file, 272 xml_fetch_content_from_file, dirname); 273 do_cleanups (back_to); 274 275 return sysinfo; 276 } 277 278 /* Initializes the syscalls_info structure according to the 279 architecture. */ 280 static void 281 init_sysinfo (void) 282 { 283 /* Should we re-read the XML info for this target? */ 284 if (my_gdb_datadir && filename_cmp (my_gdb_datadir, gdb_datadir) != 0) 285 { 286 /* The data-directory changed from the last time we used it. 287 It means that we have to re-read the XML info. */ 288 have_initialized_sysinfo = 0; 289 xfree (my_gdb_datadir); 290 my_gdb_datadir = NULL; 291 if (sysinfo) 292 free_syscalls_info ((void *) sysinfo); 293 } 294 295 /* Did we already try to initialize the structure? */ 296 if (have_initialized_sysinfo) 297 return; 298 299 sysinfo = xml_init_syscalls_info (xml_syscall_file); 300 301 have_initialized_sysinfo = 1; 302 303 if (sysinfo == NULL) 304 { 305 if (xml_syscall_file) 306 warning (_("Could not load the syscall XML file `%s/%s'."), 307 gdb_datadir, xml_syscall_file); 308 else 309 warning (_("There is no XML file to open.")); 310 311 warning (_("GDB will not be able to display " 312 "syscall names nor to verify if\n" 313 "any provided syscall numbers are valid.")); 314 } 315 316 /* Saving the data-directory used to read this XML info. */ 317 my_gdb_datadir = xstrdup (gdb_datadir); 318 } 319 320 static int 321 xml_get_syscall_number (const struct syscalls_info *sysinfo, 322 const char *syscall_name) 323 { 324 struct syscall_desc *sysdesc; 325 int i; 326 327 if (sysinfo == NULL 328 || syscall_name == NULL) 329 return UNKNOWN_SYSCALL; 330 331 for (i = 0; 332 VEC_iterate(syscall_desc_p, sysinfo->syscalls, i, sysdesc); 333 i++) 334 if (strcmp (sysdesc->name, syscall_name) == 0) 335 return sysdesc->number; 336 337 return UNKNOWN_SYSCALL; 338 } 339 340 static const char * 341 xml_get_syscall_name (const struct syscalls_info *sysinfo, 342 int syscall_number) 343 { 344 struct syscall_desc *sysdesc; 345 int i; 346 347 if (sysinfo == NULL 348 || syscall_number < 0) 349 return NULL; 350 351 for (i = 0; 352 VEC_iterate(syscall_desc_p, sysinfo->syscalls, i, sysdesc); 353 i++) 354 if (sysdesc->number == syscall_number) 355 return sysdesc->name; 356 357 return NULL; 358 } 359 360 static const char ** 361 xml_list_of_syscalls (const struct syscalls_info *sysinfo) 362 { 363 struct syscall_desc *sysdesc; 364 const char **names = NULL; 365 int nsyscalls; 366 int i; 367 368 if (sysinfo == NULL) 369 return NULL; 370 371 nsyscalls = VEC_length (syscall_desc_p, sysinfo->syscalls); 372 names = xmalloc ((nsyscalls + 1) * sizeof (char *)); 373 374 for (i = 0; 375 VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc); 376 i++) 377 names[i] = sysdesc->name; 378 379 names[i] = NULL; 380 381 return names; 382 } 383 384 void 385 set_xml_syscall_file_name (const char *name) 386 { 387 xml_syscall_file = name; 388 } 389 390 void 391 get_syscall_by_number (int syscall_number, 392 struct syscall *s) 393 { 394 init_sysinfo (); 395 396 s->number = syscall_number; 397 s->name = xml_get_syscall_name (sysinfo, syscall_number); 398 } 399 400 void 401 get_syscall_by_name (const char *syscall_name, 402 struct syscall *s) 403 { 404 init_sysinfo (); 405 406 s->number = xml_get_syscall_number (sysinfo, syscall_name); 407 s->name = syscall_name; 408 } 409 410 const char ** 411 get_syscall_names (void) 412 { 413 init_sysinfo (); 414 415 return xml_list_of_syscalls (sysinfo); 416 } 417 418 #endif /* ! HAVE_LIBEXPAT */ 419