xml-syscall.c 14 KB

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