GDB (API)
|
00001 /* Functions that provide the mechanism to parse a syscall XML file 00002 and get its values. 00003 00004 Copyright (C) 2009-2013 Free Software Foundation, Inc. 00005 00006 This file is part of GDB. 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00020 00021 #include "defs.h" 00022 #include "gdbtypes.h" 00023 #include "xml-support.h" 00024 #include "xml-syscall.h" 00025 00026 /* For the struct syscall definition. */ 00027 #include "target.h" 00028 00029 #include "filenames.h" 00030 00031 #include "gdb_assert.h" 00032 00033 #ifndef HAVE_LIBEXPAT 00034 00035 /* Dummy functions to indicate that there's no support for fetching 00036 syscalls information. */ 00037 00038 static void 00039 syscall_warn_user (void) 00040 { 00041 static int have_warned = 0; 00042 if (!have_warned) 00043 { 00044 have_warned = 1; 00045 warning (_("Can not parse XML syscalls information; XML support was " 00046 "disabled at compile time.")); 00047 } 00048 } 00049 00050 void 00051 set_xml_syscall_file_name (const char *name) 00052 { 00053 return; 00054 } 00055 00056 void 00057 get_syscall_by_number (int syscall_number, 00058 struct syscall *s) 00059 { 00060 syscall_warn_user (); 00061 s->number = syscall_number; 00062 s->name = NULL; 00063 } 00064 00065 void 00066 get_syscall_by_name (const char *syscall_name, 00067 struct syscall *s) 00068 { 00069 syscall_warn_user (); 00070 s->number = UNKNOWN_SYSCALL; 00071 s->name = syscall_name; 00072 } 00073 00074 const char ** 00075 get_syscall_names (void) 00076 { 00077 syscall_warn_user (); 00078 return NULL; 00079 } 00080 00081 #else /* ! HAVE_LIBEXPAT */ 00082 00083 /* Variable that will hold the last known data-directory. This is useful to 00084 know whether we should re-read the XML info for the target. */ 00085 static char *my_gdb_datadir = NULL; 00086 00087 /* Structure which describes a syscall. */ 00088 typedef struct syscall_desc 00089 { 00090 /* The syscall number. */ 00091 00092 int number; 00093 00094 /* The syscall name. */ 00095 00096 char *name; 00097 } *syscall_desc_p; 00098 DEF_VEC_P(syscall_desc_p); 00099 00100 /* Structure that represents syscalls information. */ 00101 struct syscalls_info 00102 { 00103 /* The syscalls. */ 00104 00105 VEC(syscall_desc_p) *syscalls; 00106 }; 00107 00108 /* Callback data for syscall information parsing. */ 00109 struct syscall_parsing_data 00110 { 00111 /* The syscalls_info we are building. */ 00112 00113 struct syscalls_info *sysinfo; 00114 }; 00115 00116 /* Structure used to store information about the available syscalls in 00117 the system. */ 00118 static const struct syscalls_info *sysinfo = NULL; 00119 00120 /* A flag to tell if we already initialized the structure above. */ 00121 static int have_initialized_sysinfo = 0; 00122 00123 /* The filename of the syscall's XML. */ 00124 static const char *xml_syscall_file = NULL; 00125 00126 static struct syscalls_info * 00127 allocate_syscalls_info (void) 00128 { 00129 return XZALLOC (struct syscalls_info); 00130 } 00131 00132 static void 00133 sysinfo_free_syscalls_desc (struct syscall_desc *sd) 00134 { 00135 xfree (sd->name); 00136 } 00137 00138 static void 00139 free_syscalls_info (void *arg) 00140 { 00141 struct syscalls_info *sysinfo = arg; 00142 struct syscall_desc *sysdesc; 00143 int i; 00144 00145 for (i = 0; 00146 VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc); 00147 i++) 00148 sysinfo_free_syscalls_desc (sysdesc); 00149 VEC_free (syscall_desc_p, sysinfo->syscalls); 00150 00151 xfree (sysinfo); 00152 } 00153 00154 static struct cleanup * 00155 make_cleanup_free_syscalls_info (struct syscalls_info *sysinfo) 00156 { 00157 return make_cleanup (free_syscalls_info, sysinfo); 00158 } 00159 00160 static void 00161 syscall_create_syscall_desc (struct syscalls_info *sysinfo, 00162 const char *name, int number) 00163 { 00164 struct syscall_desc *sysdesc = XZALLOC (struct syscall_desc); 00165 00166 sysdesc->name = xstrdup (name); 00167 sysdesc->number = number; 00168 00169 VEC_safe_push (syscall_desc_p, sysinfo->syscalls, sysdesc); 00170 } 00171 00172 /* Handle the start of a <syscall> element. */ 00173 static void 00174 syscall_start_syscall (struct gdb_xml_parser *parser, 00175 const struct gdb_xml_element *element, 00176 void *user_data, VEC(gdb_xml_value_s) *attributes) 00177 { 00178 struct syscall_parsing_data *data = user_data; 00179 struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes); 00180 int len, i; 00181 /* syscall info. */ 00182 char *name = NULL; 00183 int number = 0; 00184 00185 len = VEC_length (gdb_xml_value_s, attributes); 00186 00187 for (i = 0; i < len; i++) 00188 { 00189 if (strcmp (attrs[i].name, "name") == 0) 00190 name = attrs[i].value; 00191 else if (strcmp (attrs[i].name, "number") == 0) 00192 number = * (ULONGEST *) attrs[i].value; 00193 else 00194 internal_error (__FILE__, __LINE__, 00195 _("Unknown attribute name '%s'."), attrs[i].name); 00196 } 00197 00198 gdb_assert (name); 00199 syscall_create_syscall_desc (data->sysinfo, name, number); 00200 } 00201 00202 00203 /* The elements and attributes of an XML syscall document. */ 00204 static const struct gdb_xml_attribute syscall_attr[] = { 00205 { "number", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 00206 { "name", GDB_XML_AF_NONE, NULL, NULL }, 00207 { NULL, GDB_XML_AF_NONE, NULL, NULL } 00208 }; 00209 00210 static const struct gdb_xml_element syscalls_info_children[] = { 00211 { "syscall", syscall_attr, NULL, 00212 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, 00213 syscall_start_syscall, NULL }, 00214 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 00215 }; 00216 00217 static const struct gdb_xml_element syselements[] = { 00218 { "syscalls_info", NULL, syscalls_info_children, 00219 GDB_XML_EF_NONE, NULL, NULL }, 00220 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 00221 }; 00222 00223 static struct syscalls_info * 00224 syscall_parse_xml (const char *document, xml_fetch_another fetcher, 00225 void *fetcher_baton) 00226 { 00227 struct cleanup *result_cleanup; 00228 struct syscall_parsing_data data; 00229 00230 data.sysinfo = allocate_syscalls_info (); 00231 result_cleanup = make_cleanup_free_syscalls_info (data.sysinfo); 00232 00233 if (gdb_xml_parse_quick (_("syscalls info"), NULL, 00234 syselements, document, &data) == 0) 00235 { 00236 /* Parsed successfully. */ 00237 discard_cleanups (result_cleanup); 00238 return data.sysinfo; 00239 } 00240 else 00241 { 00242 warning (_("Could not load XML syscalls info; ignoring")); 00243 do_cleanups (result_cleanup); 00244 return NULL; 00245 } 00246 } 00247 00248 /* Function responsible for initializing the information 00249 about the syscalls. It reads the XML file and fills the 00250 struct syscalls_info with the values. 00251 00252 Returns the struct syscalls_info if the file is valid, NULL otherwise. */ 00253 static const struct syscalls_info * 00254 xml_init_syscalls_info (const char *filename) 00255 { 00256 char *full_file; 00257 char *dirname; 00258 struct syscalls_info *sysinfo; 00259 struct cleanup *back_to; 00260 00261 full_file = xml_fetch_content_from_file (filename, gdb_datadir); 00262 if (full_file == NULL) 00263 return NULL; 00264 00265 back_to = make_cleanup (xfree, full_file); 00266 00267 dirname = ldirname (filename); 00268 if (dirname != NULL) 00269 make_cleanup (xfree, dirname); 00270 00271 sysinfo = syscall_parse_xml (full_file, 00272 xml_fetch_content_from_file, dirname); 00273 do_cleanups (back_to); 00274 00275 return sysinfo; 00276 } 00277 00278 /* Initializes the syscalls_info structure according to the 00279 architecture. */ 00280 static void 00281 init_sysinfo (void) 00282 { 00283 /* Should we re-read the XML info for this target? */ 00284 if (my_gdb_datadir && filename_cmp (my_gdb_datadir, gdb_datadir) != 0) 00285 { 00286 /* The data-directory changed from the last time we used it. 00287 It means that we have to re-read the XML info. */ 00288 have_initialized_sysinfo = 0; 00289 xfree (my_gdb_datadir); 00290 my_gdb_datadir = NULL; 00291 if (sysinfo) 00292 free_syscalls_info ((void *) sysinfo); 00293 } 00294 00295 /* Did we already try to initialize the structure? */ 00296 if (have_initialized_sysinfo) 00297 return; 00298 00299 sysinfo = xml_init_syscalls_info (xml_syscall_file); 00300 00301 have_initialized_sysinfo = 1; 00302 00303 if (sysinfo == NULL) 00304 { 00305 if (xml_syscall_file) 00306 warning (_("Could not load the syscall XML file `%s/%s'."), 00307 gdb_datadir, xml_syscall_file); 00308 else 00309 warning (_("There is no XML file to open.")); 00310 00311 warning (_("GDB will not be able to display " 00312 "syscall names nor to verify if\n" 00313 "any provided syscall numbers are valid.")); 00314 } 00315 00316 /* Saving the data-directory used to read this XML info. */ 00317 my_gdb_datadir = xstrdup (gdb_datadir); 00318 } 00319 00320 static int 00321 xml_get_syscall_number (const struct syscalls_info *sysinfo, 00322 const char *syscall_name) 00323 { 00324 struct syscall_desc *sysdesc; 00325 int i; 00326 00327 if (sysinfo == NULL 00328 || syscall_name == NULL) 00329 return UNKNOWN_SYSCALL; 00330 00331 for (i = 0; 00332 VEC_iterate(syscall_desc_p, sysinfo->syscalls, i, sysdesc); 00333 i++) 00334 if (strcmp (sysdesc->name, syscall_name) == 0) 00335 return sysdesc->number; 00336 00337 return UNKNOWN_SYSCALL; 00338 } 00339 00340 static const char * 00341 xml_get_syscall_name (const struct syscalls_info *sysinfo, 00342 int syscall_number) 00343 { 00344 struct syscall_desc *sysdesc; 00345 int i; 00346 00347 if (sysinfo == NULL 00348 || syscall_number < 0) 00349 return NULL; 00350 00351 for (i = 0; 00352 VEC_iterate(syscall_desc_p, sysinfo->syscalls, i, sysdesc); 00353 i++) 00354 if (sysdesc->number == syscall_number) 00355 return sysdesc->name; 00356 00357 return NULL; 00358 } 00359 00360 static const char ** 00361 xml_list_of_syscalls (const struct syscalls_info *sysinfo) 00362 { 00363 struct syscall_desc *sysdesc; 00364 const char **names = NULL; 00365 int nsyscalls; 00366 int i; 00367 00368 if (sysinfo == NULL) 00369 return NULL; 00370 00371 nsyscalls = VEC_length (syscall_desc_p, sysinfo->syscalls); 00372 names = xmalloc ((nsyscalls + 1) * sizeof (char *)); 00373 00374 for (i = 0; 00375 VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc); 00376 i++) 00377 names[i] = sysdesc->name; 00378 00379 names[i] = NULL; 00380 00381 return names; 00382 } 00383 00384 void 00385 set_xml_syscall_file_name (const char *name) 00386 { 00387 xml_syscall_file = name; 00388 } 00389 00390 void 00391 get_syscall_by_number (int syscall_number, 00392 struct syscall *s) 00393 { 00394 init_sysinfo (); 00395 00396 s->number = syscall_number; 00397 s->name = xml_get_syscall_name (sysinfo, syscall_number); 00398 } 00399 00400 void 00401 get_syscall_by_name (const char *syscall_name, 00402 struct syscall *s) 00403 { 00404 init_sysinfo (); 00405 00406 s->number = xml_get_syscall_number (sysinfo, syscall_name); 00407 s->name = syscall_name; 00408 } 00409 00410 const char ** 00411 get_syscall_names (void) 00412 { 00413 init_sysinfo (); 00414 00415 return xml_list_of_syscalls (sysinfo); 00416 } 00417 00418 #endif /* ! HAVE_LIBEXPAT */