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