On Sat, May 30, 2026 at 3:13 PM Richard Henderson <
[email protected]> wrote:

> Use kinfo_getvmmap from -luser.
>
> Signed-off-by: Richard Henderson <[email protected]>
> ---
>  common-user/selfmap.c   | 41 ++++++++++++++++++++++++++++++++++++++++-
>  common-user/meson.build |  5 +++++
>  2 files changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/common-user/selfmap.c b/common-user/selfmap.c
> index a1b88dee66..151d066801 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 <libutil.h>
> +#include <sys/user.h>
> +#endif
>
>  IntervalTreeRoot *read_self_maps(void)
>  {
> @@ -80,9 +84,44 @@ IntervalTreeRoot *read_self_maps(void)
>      g_strfreev(lines);
>      g_free(maps);
>
> +    return root;
> +#elif defined(__FreeBSD__)
> +    int n = 0;
> +    struct kinfo_vmentry *entries = kinfo_getvmmap(getpid(), &n);
> +    IntervalTreeRoot *root;
> +
> +    if (!entries) {
> +        return NULL;
> +    }
> +    root = g_new0(IntervalTreeRoot, 1);
> +
> +    for (int i = 0; i < n; ++i) {
> +        struct kinfo_vmentry *k = &entries[i];
> +        size_t path_len = strnlen(k->kve_path, sizeof(k->kve_path)) + 1;
> +        MapInfo *e = g_malloc0(sizeof(*e) + path_len);
> +
> +        e->itree.start = k->kve_start;
> +        e->itree.last = k->kve_end - 1;
> +
> +        /* ??? The rest of these fields are only used in linux-user. */
> +        e->dev = k->kve_vn_fsid_freebsd11;
> +        e->inode = k->kve_vn_fileid;
> +        e->offset = k->kve_offset;
> +        e->is_read = k->kve_protection & KVME_PROT_READ;
> +        e->is_write = k->kve_protection & KVME_PROT_WRITE;
> +        e->is_exec = k->kve_protection & KVME_PROT_EXEC;
> +        e->is_priv = k->kve_flags & KVME_FLAG_COW;
> +        if (path_len) {
> +            e->path = memcpy(e + 1, k->kve_path, path_len);
> +        }
> +
> +        interval_tree_insert(&e->itree, root);
> +    }
> +
> +    free(entries);
>      return root;
>  #else
> -    return NULL;
> +# error
>  #endif
>  }
>
> diff --git a/common-user/meson.build b/common-user/meson.build
> index 831a7273fb..5e041de55e 100644
> --- a/common-user/meson.build
> +++ b/common-user/meson.build
> @@ -10,3 +10,8 @@ user_ss.add(files(
>    'safe-syscall-error.c',
>    'selfmap.c',
>  ))
> +
> +if host_os == 'freebsd'
> +  libutil = cc.find_library('util', required: true)
> +  user_ss.add(libutil)
> +endif
>

I have an implementation of this in bltiz. I'll compare the two. Do you want
me to send that to the list, or can you look at
https://github.com/qemu-bsd-user/qemu-bsd-user/commit/a19b96e7719d570d9a8b605f2e89d59750110990
and
https://github.com/qemu-bsd-user/qemu-bsd-user/commit/f6708d9cd0ee6e3d950ce2adc9a36ecd9b3eb7cc
to see what I've done. It works, and I think it's right. I used the sysctl
interface directly rather than the
kinfo_getvmmap to avoid the libutil dependency, but maybe that's not a big
concern.

I'll go over the rest of this series in a bit. This one caught my eye when
catching up on email.

Warner

Reply via email to