aboutsummaryrefslogtreecommitdiff
path: root/gdb/nbsd-nat.c
diff options
context:
space:
mode:
authorKamil Rytarowski <n54@gmx.com>2020-04-12 02:00:14 +0200
committerKamil Rytarowski <n54@gmx.com>2020-04-12 13:06:08 +0200
commit54b8cbd0e4063846349634aefa8ed1a3c0ac62ca (patch)
tree3deec11e19aac2982654f8c2550d10680527ca7f /gdb/nbsd-nat.c
parent0b07a199018c928f12ddfb8d5f75baf466de389d (diff)
downloadgdb-54b8cbd0e4063846349634aefa8ed1a3c0ac62ca.zip
gdb-54b8cbd0e4063846349634aefa8ed1a3c0ac62ca.tar.gz
gdb-54b8cbd0e4063846349634aefa8ed1a3c0ac62ca.tar.bz2
Implement "info proc mappings" for NetBSD
Define nbsd_nat_target::find_memory_regions and nbsd_nat_target::info_proc. info_proc handles as of now only the "mappings" command. Define a local static function kinfo_get_vmmap() that reads the process memory layout of a specified process. kinfo_get_vmmap() wraps the sysctl(3) call. nbsd-tdep.c defines now utility functions for printing the process memory layout: * nbsd_info_proc_mappings_header() * nbsd_vm_map_entry_flags() * nbsd_info_proc_mappings_entry() gdb/ChangeLog: * nbsd-nat.c; Include "nbsd-tdep.h" and "gdbarch.h". * nbsd-nat.c (nbsd_nat_target::find_memory_regions) (nbsd_nat_target::info_proc): New functions. * nbsd-nat.c (kinfo_get_vmmap): New function. * nbsd-nat.c (nbsd_nat_target::info_proc) Use nbsd_info_proc_mappings_header and nbsd_info_proc_mappings_entry. * nbsd-tdep.c (nbsd_info_proc_mappings_header) (nbsd_info_proc_mappings_entry, nbsd_vm_map_entry_flags): New functions. * nbsd-tdep.c (KINFO_VME_PROT_READ, KINFO_VME_PROT_WRITE) (KINFO_VME_PROT_EXEC, KINFO_VME_FLAG_COW) (KINFO_VME_FLAG_NEEDS_COPY, KINFO_VME_FLAG_NOCOREDUMP) (KINFO_VME_FLAG_PAGEABLE, KINFO_VME_FLAG_GROWS_UP) (KINFO_VME_FLAG_GROWS_DOWN): New.
Diffstat (limited to 'gdb/nbsd-nat.c')
-rw-r--r--gdb/nbsd-nat.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c
index 4423e19..2420153 100644
--- a/gdb/nbsd-nat.c
+++ b/gdb/nbsd-nat.c
@@ -21,7 +21,9 @@
#include "nbsd-nat.h"
#include "gdbthread.h"
+#include "nbsd-tdep.h"
#include "inferior.h"
+#include "gdbarch.h"
#include <sys/types.h>
#include <sys/ptrace.h>
@@ -199,3 +201,150 @@ nbsd_nat_target::pid_to_str (ptid_t ptid)
return normal_pid_to_str (ptid);
}
+
+/* Retrieve all the memory regions in the specified process. */
+
+static gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]>
+nbsd_kinfo_get_vmmap (pid_t pid, size_t *size)
+{
+ int mib[5] = {CTL_VM, VM_PROC, VM_PROC_MAP, pid,
+ sizeof (struct kinfo_vmentry)};
+
+ size_t length = 0;
+ if (sysctl (mib, ARRAY_SIZE (mib), NULL, &length, NULL, 0))
+ {
+ *size = 0;
+ return NULL;
+ }
+
+ /* Prereserve more space. The length argument is volatile and can change
+ between the sysctl(3) calls as this function can be called against a
+ running process. */
+ length = length * 5 / 3;
+
+ gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> kiv
+ (XNEWVAR (kinfo_vmentry, length));
+
+ if (sysctl (mib, ARRAY_SIZE (mib), kiv.get (), &length, NULL, 0))
+ {
+ *size = 0;
+ return NULL;
+ }
+
+ *size = length / sizeof (struct kinfo_vmentry);
+ return kiv;
+}
+
+/* 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
+nbsd_nat_target::find_memory_regions (find_memory_region_ftype func,
+ void *data)
+{
+ pid_t pid = inferior_ptid.pid ();
+
+ size_t nitems;
+ gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> vmentl
+ = nbsd_kinfo_get_vmmap (pid, &nitems);
+ if (vmentl == NULL)
+ perror_with_name (_("Couldn't fetch VM map entries."));
+
+ for (size_t i = 0; i < nitems; i++)
+ {
+ struct kinfo_vmentry *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. */
+ switch (kve->kve_type)
+ {
+ case KVME_TYPE_VNODE:
+ case KVME_TYPE_ANON:
+ case KVME_TYPE_SUBMAP:
+ case KVME_TYPE_OBJECT:
+ break;
+ default:
+ continue;
+ }
+
+ size_t 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, data);
+ }
+ return 0;
+}
+
+/* Implement the "info_proc" target_ops method. */
+
+bool
+nbsd_nat_target::info_proc (const char *args, enum info_proc_what what)
+{
+ pid_t pid;
+ bool do_mappings = false;
+
+ switch (what)
+ {
+ case IP_MAPPINGS:
+ do_mappings = true;
+ break;
+ default:
+ error (_("Not supported on this target."));
+ }
+
+ gdb_argv built_argv (args);
+ if (built_argv.count () == 0)
+ {
+ pid = inferior_ptid.pid ();
+ if (pid == 0)
+ error (_("No current process: you must name one."));
+ }
+ else if (built_argv.count () == 1 && isdigit (built_argv[0][0]))
+ pid = strtol (built_argv[0], NULL, 10);
+ else
+ error (_("Invalid arguments."));
+
+ printf_filtered (_("process %d\n"), pid);
+
+ if (do_mappings)
+ {
+ size_t nvment;
+ gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> vmentl
+ = nbsd_kinfo_get_vmmap (pid, &nvment);
+
+ if (vmentl != nullptr)
+ {
+ int addr_bit = TARGET_CHAR_BIT * sizeof (void *);
+ nbsd_info_proc_mappings_header (addr_bit);
+
+ struct kinfo_vmentry *kve = vmentl.get ();
+ for (int i = 0; i < nvment; i++, kve++)
+ nbsd_info_proc_mappings_entry (addr_bit, kve->kve_start,
+ kve->kve_end, kve->kve_offset,
+ kve->kve_flags, kve->kve_protection,
+ kve->kve_path);
+ }
+ else
+ warning (_("unable to fetch virtual memory map"));
+ }
+
+ return true;
+}