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); > So I had the following to use the sysctl interface. The extra bit is paranoia for the general case where we're multi-threaded. I'm not entirely sure it's needed, but it won't hurt since we free this memory at the end anyway. It's up to you to see if you think the -lutil addition is better or this slightly longer code is better. int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; size_t len; char *buf, *p; if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) { return NULL; } /* Add some slack in case mappings change between calls. */ len = len * 4 / 3; buf = g_malloc(len); if (sysctl(mib, 4, buf, &len, NULL, 0) < 0) { g_free(buf); return NULL; } > + 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; > This is shorter than what I had in blitz. > + MapInfo *e = g_malloc0(sizeof(*e) + path_len); > > My version did the following only if if (kve->kve_type != KVME_TYPE_GUARD && kve->kve_type != KVME_TYPE_DEAD) { though now I see my version would have been better with the contrapositive and continue. > + 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); > I had g_free() here, but I am a 'cargo cult' glib user... > 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 > This dependency is likely fine, but as I said in my other mail using the sysctl obviates the need for this. And thank you so much for writing this, even though there's a small collision here. I do very much appreciate it. Warner > -- > 2.43.0 > >
