selfmap.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*
  2. * Utility function to get QEMU's own process map
  3. *
  4. * Copyright (c) 2020 Linaro Ltd
  5. *
  6. * SPDX-License-Identifier: GPL-2.0-or-later
  7. */
  8. #include "qemu/osdep.h"
  9. #include "qemu/cutils.h"
  10. #include "qemu/selfmap.h"
  11. IntervalTreeRoot *read_self_maps(void)
  12. {
  13. IntervalTreeRoot *root;
  14. gchar *maps, **lines;
  15. guint i, nlines;
  16. if (!g_file_get_contents("/proc/self/maps", &maps, NULL, NULL)) {
  17. return NULL;
  18. }
  19. root = g_new0(IntervalTreeRoot, 1);
  20. lines = g_strsplit(maps, "\n", 0);
  21. nlines = g_strv_length(lines);
  22. for (i = 0; i < nlines; i++) {
  23. gchar **fields = g_strsplit(lines[i], " ", 6);
  24. guint nfields = g_strv_length(fields);
  25. if (nfields > 4) {
  26. uint64_t start, end, offset, inode;
  27. unsigned dev_maj, dev_min;
  28. int errors = 0;
  29. const char *p;
  30. errors |= qemu_strtou64(fields[0], &p, 16, &start);
  31. errors |= qemu_strtou64(p + 1, NULL, 16, &end);
  32. errors |= qemu_strtou64(fields[2], NULL, 16, &offset);
  33. errors |= qemu_strtoui(fields[3], &p, 16, &dev_maj);
  34. errors |= qemu_strtoui(p + 1, NULL, 16, &dev_min);
  35. errors |= qemu_strtou64(fields[4], NULL, 10, &inode);
  36. if (!errors) {
  37. size_t path_len;
  38. MapInfo *e;
  39. if (nfields == 6) {
  40. p = fields[5];
  41. p += strspn(p, " ");
  42. path_len = strlen(p) + 1;
  43. } else {
  44. p = NULL;
  45. path_len = 0;
  46. }
  47. e = g_malloc0(sizeof(*e) + path_len);
  48. e->itree.start = start;
  49. e->itree.last = end - 1;
  50. e->offset = offset;
  51. e->dev = makedev(dev_maj, dev_min);
  52. e->inode = inode;
  53. e->is_read = fields[1][0] == 'r';
  54. e->is_write = fields[1][1] == 'w';
  55. e->is_exec = fields[1][2] == 'x';
  56. e->is_priv = fields[1][3] == 'p';
  57. if (path_len) {
  58. e->path = memcpy(e + 1, p, path_len);
  59. }
  60. interval_tree_insert(&e->itree, root);
  61. }
  62. }
  63. g_strfreev(fields);
  64. }
  65. g_strfreev(lines);
  66. g_free(maps);
  67. return root;
  68. }
  69. /**
  70. * free_self_maps:
  71. * @root: an interval tree
  72. *
  73. * Free a tree of MapInfo structures.
  74. * Since we allocated each MapInfo in one chunk, we need not consider the
  75. * contents and can simply free each RBNode.
  76. */
  77. static void free_rbnode(RBNode *n)
  78. {
  79. if (n) {
  80. free_rbnode(n->rb_left);
  81. free_rbnode(n->rb_right);
  82. g_free(n);
  83. }
  84. }
  85. void free_self_maps(IntervalTreeRoot *root)
  86. {
  87. if (root) {
  88. free_rbnode(root->rb_root.rb_node);
  89. g_free(root);
  90. }
  91. }