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 int errors = 0; 34 const char *p; 35 36 errors |= qemu_strtou64(fields[0], &p, 16, &start); 37 errors |= qemu_strtou64(p + 1, NULL, 16, &end); 38 errors |= qemu_strtou64(fields[2], NULL, 16, &offset); 39 errors |= qemu_strtou64(fields[4], NULL, 10, &inode); 40 41 if (!errors) { 42 size_t dev_len, path_len; 43 MapInfo *e; 44 45 dev_len = strlen(fields[3]) + 1; 46 if (nfields == 6) { 47 p = fields[5]; 48 p += strspn(p, " "); 49 path_len = strlen(p) + 1; 50 } else { 51 p = NULL; 52 path_len = 0; 53 } 54 55 e = g_malloc0(sizeof(*e) + dev_len + path_len); 56 57 e->itree.start = start; 58 e->itree.last = end - 1; 59 e->offset = offset; 60 e->inode = inode; 61 62 e->is_read = fields[1][0] == 'r'; 63 e->is_write = fields[1][1] == 'w'; 64 e->is_exec = fields[1][2] == 'x'; 65 e->is_priv = fields[1][3] == 'p'; 66 67 memcpy(e->dev, fields[3], dev_len); 68 if (path_len) { 69 e->path = memcpy(e->dev + dev_len, p, path_len); 70 } 71 72 interval_tree_insert(&e->itree, root); 73 } 74 } 75 g_strfreev(fields); 76 } 77 g_strfreev(lines); 78 g_free(maps); 79 80 return root; 81 } 82 83 /** 84 * free_self_maps: 85 * @root: an interval tree 86 * 87 * Free a tree of MapInfo structures. 88 * Since we allocated each MapInfo in one chunk, we need not consider the 89 * contents and can simply free each RBNode. 90 */ 91 92 static void free_rbnode(RBNode *n) 93 { 94 if (n) { 95 free_rbnode(n->rb_left); 96 free_rbnode(n->rb_right); 97 g_free(n); 98 } 99 } 100 101 void free_self_maps(IntervalTreeRoot *root) 102 { 103 if (root) { 104 free_rbnode(root->rb_root.rb_node); 105 g_free(root); 106 } 107 } 108