diff options
author | Kamil Rytarowski <n54@gmx.com> | 2020-04-12 02:00:14 +0200 |
---|---|---|
committer | Kamil Rytarowski <n54@gmx.com> | 2020-04-12 13:06:08 +0200 |
commit | 54b8cbd0e4063846349634aefa8ed1a3c0ac62ca (patch) | |
tree | 3deec11e19aac2982654f8c2550d10680527ca7f /gdb/nbsd-nat.c | |
parent | 0b07a199018c928f12ddfb8d5f75baf466de389d (diff) | |
download | gdb-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.c | 149 |
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; +} |