This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] Use kinfo_getvmmap () on FreeBSD to enumerate memory regions.
- From: John Baldwin <jhb at freebsd dot org>
- To: Pedro Alves <palves at redhat dot com>
- Cc: gdb-patches at sourceware dot org
- Date: Fri, 13 Mar 2015 08:02:42 -0400
- Subject: Re: [PATCH] Use kinfo_getvmmap () on FreeBSD to enumerate memory regions.
- Authentication-results: sourceware.org; auth=none
- References: <1611123 dot gixn7rQRH9 at ralph dot baldwin dot cx> <1897208 dot OU0R2xD82y at ralph dot baldwin dot cx> <54FA2D0F dot 7000108 at redhat dot com>
On Friday, March 06, 2015 10:41:19 PM Pedro Alves wrote:
> On 03/06/2015 09:06 PM, John Baldwin wrote:
> > On Friday, March 06, 2015 07:49:23 PM Pedro Alves wrote:
> >>> +# On FreeBSD we may need libutil for kinfo_getvmmap (used by fbsd-nat.c).
> >>> +AC_CHECK_LIB(util, kinfo_getvmmap,
> >>> + [AC_DEFINE(HAVE_KINFO_GETVMMAP, 1,
> >>> + [Define to 1 if your system has the kinfo_getvmmap function.
> >>> ])]) +
> >>
> >> Isn't
> >>
> >> AC_SEARCH_LIBS(kinfo_getvmmap, [util])
> >>
> >> pretty much the same?
> >
> > Might be, I wasn't sure from reading the autoconf docs that this would add the
> > appropriate define. I'll certainly try it and if it works I'm happier to use
> > the simpler form.
I ended up needing to include AC_DEFINE() still, but AC_SEARCH_LIBS() worked
fine.
Updated patch:
Use kinfo_getvmmap from libutil on FreeBSD to enumerate memory
regions in a running process instead of /proc/<pid>/map. FreeBSD systems
do not mount procfs by default, but kinfo_getvmmap uses a sysctl that
is always available.
Skip memory regions for devices as well as regions an application has
requested to not be dumped via the MAP_NOCORE flag to mmap or
MADV_NOCORE advice to madvise.
gdb/ChangeLog:
* configure.ac: AC_CHECK_LIB(util, kinfo_getvmmap).
* configure: Regenerate.
* config.in: Regenerate.
* fbsd-nat.c [!HAVE_KINFO_GETVMMAP] (fbsd_read_mapping): Don't
define.
(fbsd_find_memory_regions): Use kinfo_getvmmap to
enumerate memory regions if present.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 4a0b6a3..38747e8 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -537,6 +537,11 @@ AM_ZLIB
# On HP/UX we may need libxpdl for dlgetmodinfo (used by solib-pa64.c).
AC_SEARCH_LIBS(dlgetmodinfo, [dl xpdl])
+# On FreeBSD we may need libutil for kinfo_getvmmap (used by fbsd-nat.c).
+AC_SEARCH_LIBS(kinfo_getvmmap, util,
+ [AC_DEFINE(HAVE_KINFO_GETVMMAP, 1,
+ [Define to 1 if your system has the kinfo_getvmmap function. ])])
+
AM_ICONV
# GDB may fork/exec the iconv program to get the list of supported character
diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c
index 062eede..1ce197d 100644
--- a/gdb/fbsd-nat.c
+++ b/gdb/fbsd-nat.c
@@ -26,6 +26,10 @@
#include <sys/types.h>
#include <sys/procfs.h>
#include <sys/sysctl.h>
+#ifdef HAVE_KINFO_GETVMMAP
+#include <sys/user.h>
+#include <libutil.h>
+#endif
#include "elf-bfd.h"
#include "fbsd-nat.h"
@@ -62,6 +66,64 @@ fbsd_pid_to_exec_file (struct target_ops *self, int pid)
return NULL;
}
+#ifdef HAVE_KINFO_GETVMMAP
+/* Iterate over all the memory regions in the current inferior,
+ calling FUNC for each memory region. OBFD is passed as the last
+ argument to FUNC. */
+
+int
+fbsd_find_memory_regions (struct target_ops *self,
+ find_memory_region_ftype func, void *obfd)
+{
+ pid_t pid = ptid_get_pid (inferior_ptid);
+ struct kinfo_vmentry *vmentl, *kve;
+ uint64_t size;
+ struct cleanup *cleanup;
+ int i, nitems;
+
+ vmentl = kinfo_getvmmap (pid, &nitems);
+ if (vmentl == NULL)
+ perror_with_name (_("Couldn't fetch VM map entries."));
+ cleanup = make_cleanup (free, vmentl);
+
+ for (i = 0; i < nitems; i++)
+ {
+ kve = &vmentl[i];
+
+ /* Skip unreadable segments and those where MAP_NOCORE has been set. */
+ if (!(kve->kve_protection & KVME_PROT_READ)
+ || kve->kve_flags & KVME_FLAG_NOCOREDUMP)
+ continue;
+
+ /* Skip segments with an invalid type. */
+ if (kve->kve_type != KVME_TYPE_DEFAULT
+ && kve->kve_type != KVME_TYPE_VNODE
+ && kve->kve_type != KVME_TYPE_SWAP
+ && kve->kve_type != KVME_TYPE_PHYS)
+ continue;
+
+ size = kve->kve_end - kve->kve_start;
+ if (info_verbose)
+ {
+ fprintf_filtered (gdb_stdout,
+ "Save segment, %ld bytes at %s (%c%c%c)\n",
+ (long) size,
+ paddress (target_gdbarch (), kve->kve_start),
+ kve->kve_protection & KVME_PROT_READ ? 'r' : '-',
+ kve->kve_protection & KVME_PROT_WRITE ? 'w' : '-',
+ kve->kve_protection & KVME_PROT_EXEC ? 'x' : '-');
+ }
+
+ /* Invoke the callback function to create the corefile segment.
+ Pass MODIFIED as true, we do not know the real modification state. */
+ func (kve->kve_start, size, kve->kve_protection & KVME_PROT_READ,
+ kve->kve_protection & KVME_PROT_WRITE,
+ kve->kve_protection & KVME_PROT_EXEC, 1, obfd);
+ }
+ do_cleanups (cleanup);
+ return 0;
+}
+#else
static int
fbsd_read_mapping (FILE *mapfile, unsigned long *start, unsigned long *end,
char *protection)
@@ -137,3 +199,4 @@ fbsd_find_memory_regions (struct target_ops *self,
do_cleanups (cleanup);
return 0;
}
+#endif
--
2.2.1