X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fnbsd-nat.c;h=5eaf9dec8afc2c6528cb23d101edb5ab975d42e5;hb=1085dfd4e1242fab231b26093882f4e2526d14d0;hp=4423e19428d3405e5f3c8ed537f1cde7e6c843d6;hpb=05f00e223d56927bfb03e3272a4827276ed67372;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c index 4423e19428..5eaf9dec8a 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 #include @@ -42,6 +44,47 @@ nbsd_nat_target::pid_to_exec_file (int pid) return buf; } +/* Return the current directory for the process identified by PID. */ + +static std::string +nbsd_pid_to_cwd (int pid) +{ + char buf[PATH_MAX]; + size_t buflen; + int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD}; + buflen = sizeof (buf); + if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0)) + return ""; + return buf; +} + +/* Return the command line for the process identified by PID. */ + +static gdb::unique_xmalloc_ptr +nbsd_pid_to_cmdline (int pid) +{ + int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV}; + + size_t size = 0; + if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0) + return nullptr; + + gdb::unique_xmalloc_ptr args (XNEWVAR (char, size)); + + if (sysctl (mib, ARRAY_SIZE (mib), args.get (), &size, NULL, 0) == -1 + || size == 0) + return nullptr; + + /* Arguments are returned as a flattened string with NUL separators. + Join the arguments with spaces to form a single string. */ + for (size_t i = 0; i < size - 1; i++) + if (args[i] == '\0') + args[i] = ' '; + args[size - 1] = '\0'; + + return args; +} + /* Generic thread (LWP) lister within a specified process. The callback parameters is a C++ function that is called for each detected thread. */ @@ -199,3 +242,197 @@ 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 +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 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 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_cmdline = false; + bool do_cwd = false; + bool do_exe = false; + bool do_mappings = false; + + switch (what) + { + case IP_MINIMAL: + do_cmdline = true; + do_cwd = true; + do_exe = true; + break; + case IP_MAPPINGS: + do_mappings = true; + break; + case IP_CMDLINE: + do_cmdline = true; + break; + case IP_EXE: + do_exe = true; + break; + case IP_CWD: + do_cwd = true; + break; + case IP_ALL: + do_cmdline = true; + do_cwd = true; + do_exe = true; + 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_cmdline) + { + gdb::unique_xmalloc_ptr cmdline = nbsd_pid_to_cmdline (pid); + if (cmdline != nullptr) + printf_filtered ("cmdline = '%s'\n", cmdline.get ()); + else + warning (_("unable to fetch command line")); + } + if (do_cwd) + { + std::string cwd = nbsd_pid_to_cwd (pid); + if (cwd != "") + printf_filtered ("cwd = '%s'\n", cwd.c_str ()); + else + warning (_("unable to fetch current working directory")); + } + if (do_exe) + { + const char *exe = pid_to_exec_file (pid); + if (exe != nullptr) + printf_filtered ("exe = '%s'\n", exe); + else + warning (_("unable to fetch executable path name")); + } + if (do_mappings) + { + size_t nvment; + gdb::unique_xmalloc_ptr 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; +}