Use sysctl to fetch the vm map of the current process.

Signed-off-by: Richard Henderson <[email protected]>
---
 common-user/selfmap.c | 45 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/common-user/selfmap.c b/common-user/selfmap.c
index a1b88dee66..139dae15e8 100644
--- a/common-user/selfmap.c
+++ b/common-user/selfmap.c
@@ -9,6 +9,10 @@
 #include "qemu/osdep.h"
 #include "qemu/cutils.h"
 #include "user/selfmap.h"
+#ifdef __FreeBSD__
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#endif
 
 IntervalTreeRoot *read_self_maps(void)
 {
@@ -80,9 +84,48 @@ IntervalTreeRoot *read_self_maps(void)
     g_strfreev(lines);
     g_free(maps);
 
+    return root;
+#elif defined(__FreeBSD__)
+    int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid() };
+    size_t len = 0;
+    g_autofree void *buf = NULL;
+    IntervalTreeRoot *root;
+
+    /* Probe for buffer size. */
+    if (sysctl(mib, ARRAY_SIZE(mib), NULL, &len, NULL, 0) < 0) {
+        return NULL;
+    }
+
+    buf = g_malloc(len);
+    if (sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) < 0) {
+        return NULL;
+    }
+
+    root = g_new0(IntervalTreeRoot, 1);
+
+    for (size_t i = 0; i < len; ) {
+        struct kinfo_vmentry *k = buf + i;
+        MapInfo *e = g_new0(MapInfo, 1);
+
+        e->itree.start = k->kve_start;
+        e->itree.last = k->kve_end - 1;
+
+        /*
+         * TODO: The rest of the fields in MapInfo are used by linux-user
+         * for the implementation of open_self_maps().  These fields are
+         * quite specific to the textual format of /proc/self/maps.
+         *
+         * We may need something different to emulate KERN_PROC_VMMAP
+         * in bsd-user, but so far they're unused -- leave them zeroed.
+         */
+
+        interval_tree_insert(&e->itree, root);
+        i += k->kve_structsize;
+    }
+
     return root;
 #else
-    return NULL;
+# error
 #endif
 }
 
-- 
2.43.0


Reply via email to