diff options
| author | Richard Henderson <richard.henderson@linaro.org> | 2026-05-30 12:20:08 -0700 |
|---|---|---|
| committer | Richard Henderson <richard.henderson@linaro.org> | 2026-07-10 14:39:58 -0700 |
| commit | 544f4c5b68d5ec9d26f7ccceeff9766546e3b2bf (patch) | |
| tree | cbcdd089c89a218ad692a55fe1d938f10a4e31e3 /common-user | |
| parent | 259de598b3565a1d0e97df65d9b07adef2add0a1 (diff) | |
| download | qemu-544f4c5b68d5ec9d26f7ccceeff9766546e3b2bf.tar.gz qemu-544f4c5b68d5ec9d26f7ccceeff9766546e3b2bf.zip | |
common-user: Move selfmap from util
This interface is only used for user-only. It's more usefully
placed within common-user than util. Temporarily add stub
implementation for bsd-user.
Reviewed-by: Helge Deller <deller@gmx.de>
Reviewed-by: Warner Losh <imp@bsdimp.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'common-user')
| -rw-r--r-- | common-user/meson.build | 1 | ||||
| -rw-r--r-- | common-user/selfmap.c | 113 |
2 files changed, 114 insertions, 0 deletions
diff --git a/common-user/meson.build b/common-user/meson.build index f9e2e83f9a..831a7273fb 100644 --- a/common-user/meson.build +++ b/common-user/meson.build @@ -8,4 +8,5 @@ user_ss.add(files( 'mmap-min-addr.c', 'safe-syscall.S', 'safe-syscall-error.c', + 'selfmap.c', )) diff --git a/common-user/selfmap.c b/common-user/selfmap.c new file mode 100644 index 0000000000..a1b88dee66 --- /dev/null +++ b/common-user/selfmap.c @@ -0,0 +1,113 @@ +/* + * Utility function to get QEMU's own process map + * + * Copyright (c) 2020 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "user/selfmap.h" + +IntervalTreeRoot *read_self_maps(void) +{ +#ifdef __linux__ + IntervalTreeRoot *root; + gchar *maps, **lines; + guint i, nlines; + + if (!g_file_get_contents("/proc/self/maps", &maps, NULL, NULL)) { + return NULL; + } + + root = g_new0(IntervalTreeRoot, 1); + lines = g_strsplit(maps, "\n", 0); + nlines = g_strv_length(lines); + + for (i = 0; i < nlines; i++) { + gchar **fields = g_strsplit(lines[i], " ", 6); + guint nfields = g_strv_length(fields); + + if (nfields > 4) { + uint64_t start, end, offset, inode; + unsigned dev_maj, dev_min; + int errors = 0; + const char *p; + + errors |= qemu_strtou64(fields[0], &p, 16, &start); + errors |= qemu_strtou64(p + 1, NULL, 16, &end); + errors |= qemu_strtou64(fields[2], NULL, 16, &offset); + errors |= qemu_strtoui(fields[3], &p, 16, &dev_maj); + errors |= qemu_strtoui(p + 1, NULL, 16, &dev_min); + errors |= qemu_strtou64(fields[4], NULL, 10, &inode); + + if (!errors) { + size_t path_len; + MapInfo *e; + + if (nfields == 6) { + p = fields[5]; + p += strspn(p, " "); + path_len = strlen(p) + 1; + } else { + p = NULL; + path_len = 0; + } + + e = g_malloc0(sizeof(*e) + path_len); + + e->itree.start = start; + e->itree.last = end - 1; + e->offset = offset; + e->dev = makedev(dev_maj, dev_min); + e->inode = inode; + + e->is_read = fields[1][0] == 'r'; + e->is_write = fields[1][1] == 'w'; + e->is_exec = fields[1][2] == 'x'; + e->is_priv = fields[1][3] == 'p'; + + if (path_len) { + e->path = memcpy(e + 1, p, path_len); + } + + interval_tree_insert(&e->itree, root); + } + } + g_strfreev(fields); + } + g_strfreev(lines); + g_free(maps); + + return root; +#else + return NULL; +#endif +} + +/** + * free_self_maps: + * @root: an interval tree + * + * Free a tree of MapInfo structures. + * Since we allocated each MapInfo in one chunk, we need not consider the + * contents and can simply free each RBNode. + */ + +static void free_rbnode(RBNode *n) +{ + if (n) { + free_rbnode(n->rb_left); + free_rbnode(n->rb_right); + g_free(n); + } +} + +void free_self_maps(IntervalTreeRoot *root) +{ + if (root) { + free_rbnode(root->rb_root.rb_node); + g_free(root); + } +} |
