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.
This commit is contained in:
parent
0b07a19901
commit
54b8cbd0e4
|
@ -1,3 +1,20 @@
|
||||||
|
2020-04-11 Kamil Rytarowski <n54@gmx.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2020-04-10 Artur Shepilko <nomadbyte@gmail.com>
|
2020-04-10 Artur Shepilko <nomadbyte@gmail.com>
|
||||||
|
|
||||||
* utils.c (copy_bitwise): Use unsigned 0 constant as operand of
|
* utils.c (copy_bitwise): Use unsigned 0 constant as operand of
|
||||||
|
|
149
gdb/nbsd-nat.c
149
gdb/nbsd-nat.c
|
@ -21,7 +21,9 @@
|
||||||
|
|
||||||
#include "nbsd-nat.h"
|
#include "nbsd-nat.h"
|
||||||
#include "gdbthread.h"
|
#include "gdbthread.h"
|
||||||
|
#include "nbsd-tdep.h"
|
||||||
#include "inferior.h"
|
#include "inferior.h"
|
||||||
|
#include "gdbarch.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
@ -199,3 +201,150 @@ nbsd_nat_target::pid_to_str (ptid_t ptid)
|
||||||
|
|
||||||
return normal_pid_to_str (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;
|
||||||
|
}
|
||||||
|
|
|
@ -35,6 +35,9 @@ struct nbsd_nat_target : public inf_ptrace_target
|
||||||
void post_attach (int pid) override;
|
void post_attach (int pid) override;
|
||||||
void update_thread_list () override;
|
void update_thread_list () override;
|
||||||
std::string pid_to_str (ptid_t ptid) override;
|
std::string pid_to_str (ptid_t ptid) override;
|
||||||
|
|
||||||
|
int find_memory_regions (find_memory_region_ftype func, void *data) override;
|
||||||
|
bool info_proc (const char *, enum info_proc_what) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* nbsd-nat.h */
|
#endif /* nbsd-nat.h */
|
||||||
|
|
|
@ -26,6 +26,23 @@
|
||||||
#include "gdbarch.h"
|
#include "gdbarch.h"
|
||||||
#include "objfiles.h"
|
#include "objfiles.h"
|
||||||
|
|
||||||
|
/* Flags in the 'kve_protection' field in struct kinfo_vmentry. These
|
||||||
|
match the KVME_PROT_* constants in <sys/sysctl.h>. */
|
||||||
|
|
||||||
|
#define KINFO_VME_PROT_READ 0x00000001
|
||||||
|
#define KINFO_VME_PROT_WRITE 0x00000002
|
||||||
|
#define KINFO_VME_PROT_EXEC 0x00000004
|
||||||
|
|
||||||
|
/* Flags in the 'kve_flags' field in struct kinfo_vmentry. These
|
||||||
|
match the KVME_FLAG_* constants in <sys/sysctl.h>. */
|
||||||
|
|
||||||
|
#define KINFO_VME_FLAG_COW 0x00000001
|
||||||
|
#define KINFO_VME_FLAG_NEEDS_COPY 0x00000002
|
||||||
|
#define KINFO_VME_FLAG_NOCOREDUMP 0x00000004
|
||||||
|
#define KINFO_VME_FLAG_PAGEABLE 0x00000008
|
||||||
|
#define KINFO_VME_FLAG_GROWS_UP 0x00000010
|
||||||
|
#define KINFO_VME_FLAG_GROWS_DOWN 0x00000020
|
||||||
|
|
||||||
/* FIXME: kettenis/20060115: We should really eliminate the next two
|
/* FIXME: kettenis/20060115: We should really eliminate the next two
|
||||||
functions completely. */
|
functions completely. */
|
||||||
|
|
||||||
|
@ -357,6 +374,78 @@ nbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
|
||||||
|
|
||||||
/* See nbsd-tdep.h. */
|
/* See nbsd-tdep.h. */
|
||||||
|
|
||||||
|
void
|
||||||
|
nbsd_info_proc_mappings_header (int addr_bit)
|
||||||
|
{
|
||||||
|
printf_filtered (_("Mapped address spaces:\n\n"));
|
||||||
|
if (addr_bit == 64)
|
||||||
|
{
|
||||||
|
printf_filtered (" %18s %18s %10s %10s %9s %s\n",
|
||||||
|
"Start Addr",
|
||||||
|
" End Addr",
|
||||||
|
" Size", " Offset", "Flags ", "File");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf_filtered ("\t%10s %10s %10s %10s %9s %s\n",
|
||||||
|
"Start Addr",
|
||||||
|
" End Addr",
|
||||||
|
" Size", " Offset", "Flags ", "File");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper function to generate mappings flags for a single VM map
|
||||||
|
entry in 'info proc mappings'. */
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
nbsd_vm_map_entry_flags (int kve_flags, int kve_protection)
|
||||||
|
{
|
||||||
|
static char vm_flags[9];
|
||||||
|
|
||||||
|
vm_flags[0] = (kve_protection & KINFO_VME_PROT_READ) ? 'r' : '-';
|
||||||
|
vm_flags[1] = (kve_protection & KINFO_VME_PROT_WRITE) ? 'w' : '-';
|
||||||
|
vm_flags[2] = (kve_protection & KINFO_VME_PROT_EXEC) ? 'x' : '-';
|
||||||
|
vm_flags[3] = ' ';
|
||||||
|
vm_flags[4] = (kve_flags & KINFO_VME_FLAG_COW) ? 'C' : '-';
|
||||||
|
vm_flags[5] = (kve_flags & KINFO_VME_FLAG_NEEDS_COPY) ? 'N' : '-';
|
||||||
|
vm_flags[6] = (kve_flags & KINFO_VME_FLAG_PAGEABLE) ? 'P' : '-';
|
||||||
|
vm_flags[7] = (kve_flags & KINFO_VME_FLAG_GROWS_UP) ? 'U'
|
||||||
|
: (kve_flags & KINFO_VME_FLAG_GROWS_DOWN) ? 'D' : '-';
|
||||||
|
vm_flags[8] = '\0';
|
||||||
|
|
||||||
|
return vm_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nbsd_info_proc_mappings_entry (int addr_bit, ULONGEST kve_start,
|
||||||
|
ULONGEST kve_end, ULONGEST kve_offset,
|
||||||
|
int kve_flags, int kve_protection,
|
||||||
|
const char *kve_path)
|
||||||
|
{
|
||||||
|
if (addr_bit == 64)
|
||||||
|
{
|
||||||
|
printf_filtered (" %18s %18s %10s %10s %9s %s\n",
|
||||||
|
hex_string (kve_start),
|
||||||
|
hex_string (kve_end),
|
||||||
|
hex_string (kve_end - kve_start),
|
||||||
|
hex_string (kve_offset),
|
||||||
|
nbsd_vm_map_entry_flags (kve_flags, kve_protection),
|
||||||
|
kve_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf_filtered ("\t%10s %10s %10s %10s %9s %s\n",
|
||||||
|
hex_string (kve_start),
|
||||||
|
hex_string (kve_end),
|
||||||
|
hex_string (kve_end - kve_start),
|
||||||
|
hex_string (kve_offset),
|
||||||
|
nbsd_vm_map_entry_flags (kve_flags, kve_protection),
|
||||||
|
kve_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See nbsd-tdep.h. */
|
||||||
|
|
||||||
void
|
void
|
||||||
nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,4 +29,22 @@ int nbsd_pc_in_sigtramp (CORE_ADDR, const char *);
|
||||||
|
|
||||||
void nbsd_init_abi (struct gdbarch_info, struct gdbarch *);
|
void nbsd_init_abi (struct gdbarch_info, struct gdbarch *);
|
||||||
|
|
||||||
|
/* Output the header for "info proc mappings". ADDR_BIT is the size
|
||||||
|
of a virtual address in bits. */
|
||||||
|
|
||||||
|
extern void nbsd_info_proc_mappings_header (int addr_bit);
|
||||||
|
|
||||||
|
/* Output description of a single memory range for "info proc
|
||||||
|
mappings". ADDR_BIT is the size of a virtual address in bits. The
|
||||||
|
KVE_START, KVE_END, KVE_OFFSET, KVE_FLAGS, and KVE_PROTECTION
|
||||||
|
parameters should contain the value of the corresponding fields in
|
||||||
|
a 'struct kinfo_vmentry'. The KVE_PATH parameter should contain a
|
||||||
|
pointer to the 'kve_path' field in a 'struct kinfo_vmentry'. */
|
||||||
|
|
||||||
|
extern void nbsd_info_proc_mappings_entry (int addr_bit, ULONGEST kve_start,
|
||||||
|
ULONGEST kve_end,
|
||||||
|
ULONGEST kve_offset,
|
||||||
|
int kve_flags, int kve_protection,
|
||||||
|
const char *kve_path);
|
||||||
|
|
||||||
#endif /* NBSD_TDEP_H */
|
#endif /* NBSD_TDEP_H */
|
||||||
|
|
Loading…
Reference in New Issue