static 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; }
prmap_t * proc_name2map(struct proc_handle *p, const char *name) { size_t i; int cnt; prmap_t *map; char tmppath[MAXPATHLEN]; struct kinfo_vmentry *kves, *kve; rd_loadobj_t *rdl; /* * If we haven't iterated over the list of loaded objects, * librtld_db isn't yet initialized and it's very likely * that librtld_db called us. We need to do the heavy * lifting here to find the symbol librtld_db is looking for. */ if (p->nobjs == 0) { if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL) return (NULL); for (i = 0; i < (size_t)cnt; i++) { kve = kves + i; basename_r(kve->kve_path, tmppath); if (strcmp(tmppath, name) == 0) { map = proc_addr2map(p, kve->kve_start); free(kves); return (map); } } free(kves); return (NULL); } if (name == NULL || strcmp(name, "a.out") == 0) { map = proc_addr2map(p, p->rdobjs[0].rdl_saddr); return (map); } for (i = 0; i < p->nobjs; i++) { rdl = &p->rdobjs[i]; basename_r(rdl->rdl_path, tmppath); if (strcmp(tmppath, name) == 0) { if ((map = malloc(sizeof(*map))) == NULL) return (NULL); proc_rdl2prmap(rdl, map); return (map); } } return (NULL); }
prmap_t * proc_addr2map(struct proc_handle *p, uintptr_t addr) { size_t i; int cnt, lastvn = 0; prmap_t *map; rd_loadobj_t *rdl; struct kinfo_vmentry *kves, *kve; /* * If we don't have a cache of listed objects, we need to query * it ourselves. */ if (p->nobjs == 0) { if ((kves = kinfo_getvmmap(p->pid, &cnt)) == NULL) return (NULL); for (i = 0; i < (size_t)cnt; i++) { kve = kves + i; if (kve->kve_type == KVME_TYPE_VNODE) lastvn = i; if (addr >= kve->kve_start && addr <= kve->kve_end) { if ((map = malloc(sizeof(*map))) == NULL) { free(kves); return (NULL); } map->pr_vaddr = kve->kve_start; map->pr_size = kve->kve_end - kve->kve_start; map->pr_offset = kve->kve_offset; map->pr_mflags = 0; if (kve->kve_protection & KVME_PROT_READ) map->pr_mflags |= MA_READ; if (kve->kve_protection & KVME_PROT_WRITE) map->pr_mflags |= MA_WRITE; if (kve->kve_protection & KVME_PROT_EXEC) map->pr_mflags |= MA_EXEC; if (kve->kve_flags & KVME_FLAG_COW) map->pr_mflags |= MA_COW; if (kve->kve_flags & KVME_FLAG_NEEDS_COPY) map->pr_mflags |= MA_NEEDS_COPY; if (kve->kve_flags & KVME_FLAG_NOCOREDUMP) map->pr_mflags |= MA_NOCOREDUMP; strlcpy(map->pr_mapname, kves[lastvn].kve_path, sizeof(map->pr_mapname)); free(kves); return (map); } } free(kves); return (NULL); } for (i = 0; i < p->nobjs; i++) { rdl = &p->rdobjs[i]; if (addr >= rdl->rdl_saddr && addr <= rdl->rdl_eaddr) { if ((map = malloc(sizeof(*map))) == NULL) return (NULL); proc_rdl2prmap(rdl, map); return (map); } } return (NULL); }
void procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp) { struct kinfo_vmentry *freep, *kve; int ptrwidth; unsigned int i, cnt; const char *str; #ifdef __x86_64__ ptrwidth = 14; #else ptrwidth = 2*sizeof(void *) + 2; #endif fprintf(stderr, "%*s %*s %3s %4s %4s %3s %3s %4s %-2s %-s\n", ptrwidth, "START", ptrwidth, "END", "PRT", "RES", "PRES", "REF", "SHD", "FL", "TP", "PATH"); #ifdef HAVE_PROCSTAT_GETVMMAP freep = procstat_getvmmap(procstat, kipp, &cnt); #else freep = kinfo_getvmmap(kipp->ki_pid, &cnt); #endif if (freep == NULL) return; for (i = 0; i < cnt; i++) { kve = &freep[i]; fprintf(stderr, "%#*jx ", ptrwidth, (uintmax_t)kve->kve_start); fprintf(stderr, "%#*jx ", ptrwidth, (uintmax_t)kve->kve_end); fprintf(stderr, "%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-"); fprintf(stderr, "%s", kve->kve_protection & KVME_PROT_WRITE ? "w" : "-"); fprintf(stderr, "%s ", kve->kve_protection & KVME_PROT_EXEC ? "x" : "-"); fprintf(stderr, "%4d ", kve->kve_resident); fprintf(stderr, "%4d ", kve->kve_private_resident); fprintf(stderr, "%3d ", kve->kve_ref_count); fprintf(stderr, "%3d ", kve->kve_shadow_count); fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_COW ? "C" : "-"); fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_NEEDS_COPY ? "N" : "-"); fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_SUPER ? "S" : "-"); fprintf(stderr, "%-1s ", kve->kve_flags & KVME_FLAG_GROWS_UP ? "U" : kve->kve_flags & KVME_FLAG_GROWS_DOWN ? "D" : "-"); switch (kve->kve_type) { case KVME_TYPE_NONE: str = "--"; break; case KVME_TYPE_DEFAULT: str = "df"; break; case KVME_TYPE_VNODE: str = "vn"; break; case KVME_TYPE_SWAP: str = "sw"; break; case KVME_TYPE_DEVICE: str = "dv"; break; case KVME_TYPE_PHYS: str = "ph"; break; case KVME_TYPE_DEAD: str = "dd"; break; case KVME_TYPE_SG: str = "sg"; break; case KVME_TYPE_MGTDEVICE: str = "md"; break; case KVME_TYPE_UNKNOWN: default: str = "??"; break; } fprintf(stderr, "%-2s ", str); fprintf(stderr, "%-s\n", kve->kve_path); } free(freep); }
PyObject * psutil_proc_memory_maps(PyObject *self, PyObject *args) { // Return a list of tuples for every process memory maps. //'procstat' cmdline utility has been used as an example. long pid; int ptrwidth; int i, cnt; char addr[1000]; char perms[4]; const char *path; struct kinfo_proc kp; struct kinfo_vmentry *freep = NULL; struct kinfo_vmentry *kve; ptrwidth = 2 * sizeof(void *); PyObject *py_tuple = NULL; PyObject *py_retlist = PyList_New(0); if (py_retlist == NULL) return NULL; if (! PyArg_ParseTuple(args, "l", &pid)) goto error; if (psutil_kinfo_proc(pid, &kp) == -1) goto error; freep = kinfo_getvmmap(pid, &cnt); if (freep == NULL) { psutil_raise_ad_or_nsp(pid); goto error; } for (i = 0; i < cnt; i++) { py_tuple = NULL; kve = &freep[i]; addr[0] = '\0'; perms[0] = '\0'; sprintf(addr, "%#*jx-%#*jx", ptrwidth, (uintmax_t)kve->kve_start, ptrwidth, (uintmax_t)kve->kve_end); psutil_remove_spaces(addr); strlcat(perms, kve->kve_protection & KVME_PROT_READ ? "r" : "-", sizeof(perms)); strlcat(perms, kve->kve_protection & KVME_PROT_WRITE ? "w" : "-", sizeof(perms)); strlcat(perms, kve->kve_protection & KVME_PROT_EXEC ? "x" : "-", sizeof(perms)); if (strlen(kve->kve_path) == 0) { switch (kve->kve_type) { case KVME_TYPE_NONE: path = "[none]"; break; case KVME_TYPE_DEFAULT: path = "[default]"; break; case KVME_TYPE_VNODE: path = "[vnode]"; break; case KVME_TYPE_SWAP: path = "[swap]"; break; case KVME_TYPE_DEVICE: path = "[device]"; break; case KVME_TYPE_PHYS: path = "[phys]"; break; case KVME_TYPE_DEAD: path = "[dead]"; break; case KVME_TYPE_SG: path = "[sg]"; break; case KVME_TYPE_UNKNOWN: path = "[unknown]"; break; default: path = "[?]"; break; } } else { path = kve->kve_path; } py_tuple = Py_BuildValue("sssiiii", addr, // "start-end" address perms, // "rwx" permissions path, // path kve->kve_resident, // rss kve->kve_private_resident, // private kve->kve_ref_count, // ref count kve->kve_shadow_count); // shadow count if (!py_tuple) goto error; if (PyList_Append(py_retlist, py_tuple)) goto error; Py_DECREF(py_tuple); } free(freep); return py_retlist; error: Py_XDECREF(py_tuple); Py_DECREF(py_retlist); if (freep != NULL) free(freep); return NULL; }
/* * Return a list of tuples for every process memory maps. * 'procstat' cmdline utility has been used as an example. */ static PyObject* get_process_memory_maps(PyObject* self, PyObject* args) { long pid; int ptrwidth; int i, cnt; char addr[30]; char perms[10]; const char *path; PyObject* retlist = PyList_New(0); // FIXME - read /usr/src/usr.sbin/procmap #if 0 struct kinfo_proc kp; struct kinfo_vmentry *freep, *kve; PyObject* pytuple = NULL; ptrwidth = 2*sizeof(void *); // NOTE: Get the PID from args. if (! PyArg_ParseTuple(args, "l", &pid)) { return NULL; } if (get_kinfo_proc(pid, &kp) == -1) { return NULL; } // NOTE: Get the VM Map for this process. freep = kinfo_getvmmap(pid, &cnt); if (freep == NULL) { PyErr_SetString(PyExc_RuntimeError, "kinfo_getvmmap() failed"); return NULL; } for (i = 0; i < cnt; i++) { kve = &freep[i]; addr[0] = '\0'; perms[0] = '\0'; sprintf(addr, "%#*jx-%#*jx", ptrwidth, (uintmax_t)kve->kve_start, ptrwidth, (uintmax_t)kve->kve_end); strlcat(perms, kve->kve_protection & KVME_PROT_READ ? "r" : "-", sizeof(perms)); strlcat(perms, kve->kve_protection & KVME_PROT_WRITE ? "w" : "-", sizeof(perms)); strlcat(perms, kve->kve_protection & KVME_PROT_EXEC ? "x" : "-", sizeof(perms)); if (strlen(kve->kve_path) == 0) { switch (kve->kve_type) { case KVME_TYPE_NONE: path = "[none]"; break; case KVME_TYPE_DEFAULT: path = "[default]"; break; case KVME_TYPE_VNODE: path = "[vnode]"; break; case KVME_TYPE_SWAP: path = "[swap]"; break; case KVME_TYPE_DEVICE: path = "[device]"; break; case KVME_TYPE_PHYS: path = "[phys]"; break; case KVME_TYPE_DEAD: path = "[dead]"; break; case KVME_TYPE_SG: path = "[sg]"; break; case KVME_TYPE_UNKNOWN: path = "[unknown]"; break; default: path = "[?]"; break; } } else { path = kve->kve_path; } pytuple = Py_BuildValue("sssiiii", addr, // "start-end" address perms, // "rwx" permissions path, // path kve->kve_resident, // rss kve->kve_private_resident, // private kve->kve_ref_count, // ref count kve->kve_shadow_count // shadow count ); PyList_Append(retlist, pytuple); Py_XDECREF(pytuple); } free(freep); #endif return retlist; }
bool fbsd_nat_target::info_proc (const char *args, enum info_proc_what what) { #ifdef HAVE_KINFO_GETFILE gdb::unique_xmalloc_ptr<struct kinfo_file> fdtbl; int nfd = 0; #endif struct kinfo_proc kp; char *tmp; pid_t pid; bool do_cmdline = false; bool do_cwd = false; bool do_exe = false; #ifdef HAVE_KINFO_GETVMMAP bool do_mappings = false; #endif bool do_status = false; switch (what) { case IP_MINIMAL: do_cmdline = true; do_cwd = true; do_exe = true; break; #ifdef HAVE_KINFO_GETVMMAP case IP_MAPPINGS: do_mappings = true; break; #endif case IP_STATUS: case IP_STAT: do_status = 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; #ifdef HAVE_KINFO_GETVMMAP do_mappings = true; #endif do_status = 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); #ifdef HAVE_KINFO_GETFILE if (do_cwd || do_exe) fdtbl.reset (kinfo_getfile (pid, &nfd)); #endif if (do_cmdline) { gdb::unique_xmalloc_ptr<char> cmdline = fbsd_fetch_cmdline (pid); if (cmdline != nullptr) printf_filtered ("cmdline = '%s'\n", cmdline.get ()); else warning (_("unable to fetch command line")); } if (do_cwd) { const char *cwd = NULL; #ifdef HAVE_KINFO_GETFILE struct kinfo_file *kf = fdtbl.get (); for (int i = 0; i < nfd; i++, kf++) { if (kf->kf_type == KF_TYPE_VNODE && kf->kf_fd == KF_FD_TYPE_CWD) { cwd = kf->kf_path; break; } } #endif if (cwd != NULL) printf_filtered ("cwd = '%s'\n", cwd); else warning (_("unable to fetch current working directory")); } if (do_exe) { const char *exe = NULL; #ifdef HAVE_KINFO_GETFILE struct kinfo_file *kf = fdtbl.get (); for (int i = 0; i < nfd; i++, kf++) { if (kf->kf_type == KF_TYPE_VNODE && kf->kf_fd == KF_FD_TYPE_TEXT) { exe = kf->kf_path; break; } } #endif if (exe == NULL) exe = pid_to_exec_file (pid); if (exe != NULL) printf_filtered ("exe = '%s'\n", exe); else warning (_("unable to fetch executable path name")); } #ifdef HAVE_KINFO_GETVMMAP if (do_mappings) { int nvment; gdb::unique_xmalloc_ptr<struct kinfo_vmentry> vmentl (kinfo_getvmmap (pid, &nvment)); if (vmentl != nullptr) { printf_filtered (_("Mapped address spaces:\n\n")); #ifdef __LP64__ 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"); #endif struct kinfo_vmentry *kve = vmentl.get (); for (int i = 0; i < nvment; i++, kve++) { ULONGEST start, end; start = kve->kve_start; end = kve->kve_end; #ifdef __LP64__ printf_filtered (" %18s %18s %10s %10s %9s %s\n", hex_string (start), hex_string (end), hex_string (end - start), hex_string (kve->kve_offset), fbsd_vm_map_entry_flags (kve->kve_flags, kve->kve_protection), kve->kve_path); #else printf_filtered ("\t%10s %10s %10s %10s %9s %s\n", hex_string (start), hex_string (end), hex_string (end - start), hex_string (kve->kve_offset), fbsd_vm_map_entry_flags (kve->kve_flags, kve->kve_protection), kve->kve_path); #endif } } else warning (_("unable to fetch virtual memory map")); } #endif if (do_status) { if (!fbsd_fetch_kinfo_proc (pid, &kp)) warning (_("Failed to fetch process information")); else { const char *state; int pgtok; printf_filtered ("Name: %s\n", kp.ki_comm); switch (kp.ki_stat) { case SIDL: state = "I (idle)"; break; case SRUN: state = "R (running)"; break; case SSTOP: state = "T (stopped)"; break; case SZOMB: state = "Z (zombie)"; break; case SSLEEP: state = "S (sleeping)"; break; case SWAIT: state = "W (interrupt wait)"; break; case SLOCK: state = "L (blocked on lock)"; break; default: state = "? (unknown)"; break; } printf_filtered ("State: %s\n", state); printf_filtered ("Parent process: %d\n", kp.ki_ppid); printf_filtered ("Process group: %d\n", kp.ki_pgid); printf_filtered ("Session id: %d\n", kp.ki_sid); printf_filtered ("TTY: %ju\n", (uintmax_t) kp.ki_tdev); printf_filtered ("TTY owner process group: %d\n", kp.ki_tpgid); printf_filtered ("User IDs (real, effective, saved): %d %d %d\n", kp.ki_ruid, kp.ki_uid, kp.ki_svuid); printf_filtered ("Group IDs (real, effective, saved): %d %d %d\n", kp.ki_rgid, kp.ki_groups[0], kp.ki_svgid); printf_filtered ("Groups: "); for (int i = 0; i < kp.ki_ngroups; i++) printf_filtered ("%d ", kp.ki_groups[i]); printf_filtered ("\n"); printf_filtered ("Minor faults (no memory page): %ld\n", kp.ki_rusage.ru_minflt); printf_filtered ("Minor faults, children: %ld\n", kp.ki_rusage_ch.ru_minflt); printf_filtered ("Major faults (memory page faults): %ld\n", kp.ki_rusage.ru_majflt); printf_filtered ("Major faults, children: %ld\n", kp.ki_rusage_ch.ru_majflt); printf_filtered ("utime: %jd.%06ld\n", (intmax_t) kp.ki_rusage.ru_utime.tv_sec, kp.ki_rusage.ru_utime.tv_usec); printf_filtered ("stime: %jd.%06ld\n", (intmax_t) kp.ki_rusage.ru_stime.tv_sec, kp.ki_rusage.ru_stime.tv_usec); printf_filtered ("utime, children: %jd.%06ld\n", (intmax_t) kp.ki_rusage_ch.ru_utime.tv_sec, kp.ki_rusage_ch.ru_utime.tv_usec); printf_filtered ("stime, children: %jd.%06ld\n", (intmax_t) kp.ki_rusage_ch.ru_stime.tv_sec, kp.ki_rusage_ch.ru_stime.tv_usec); printf_filtered ("'nice' value: %d\n", kp.ki_nice); printf_filtered ("Start time: %jd.%06ld\n", kp.ki_start.tv_sec, kp.ki_start.tv_usec); pgtok = getpagesize () / 1024; printf_filtered ("Virtual memory size: %ju kB\n", (uintmax_t) kp.ki_size / 1024); printf_filtered ("Data size: %ju kB\n", (uintmax_t) kp.ki_dsize * pgtok); printf_filtered ("Stack size: %ju kB\n", (uintmax_t) kp.ki_ssize * pgtok); printf_filtered ("Text size: %ju kB\n", (uintmax_t) kp.ki_tsize * pgtok); printf_filtered ("Resident set size: %ju kB\n", (uintmax_t) kp.ki_rssize * pgtok); printf_filtered ("Maximum RSS: %ju kB\n", (uintmax_t) kp.ki_rusage.ru_maxrss); printf_filtered ("Pending Signals: "); for (int i = 0; i < _SIG_WORDS; i++) printf_filtered ("%08x ", kp.ki_siglist.__bits[i]); printf_filtered ("\n"); printf_filtered ("Ignored Signals: "); for (int i = 0; i < _SIG_WORDS; i++) printf_filtered ("%08x ", kp.ki_sigignore.__bits[i]); printf_filtered ("\n"); printf_filtered ("Caught Signals: "); for (int i = 0; i < _SIG_WORDS; i++) printf_filtered ("%08x ", kp.ki_sigcatch.__bits[i]); printf_filtered ("\n"); } } return true; }
static bool read_lib_info(struct ps_prochandle* ph) { #if defined(__FreeBSD__) && __FreeBSD_version >= 701000 struct kinfo_vmentry *freep, *kve; int i, cnt; freep = kinfo_getvmmap(ph->pid, &cnt); if (freep == NULL) { print_debug("can't get vm map for pid\n", ph->pid); return false; } for (i = 0; i < cnt; i++) { kve = &freep[i]; if ((kve->kve_flags & KVME_FLAG_COW) && kve->kve_path != NULL && strlen(kve->kve_path) > 0) { if (find_lib(ph, kve->kve_path) == false) { lib_info* lib; if ((lib = add_lib_info(ph, kve->kve_path, (uintptr_t) kve->kve_start)) == NULL) continue; // ignore, add_lib_info prints error // we don't need to keep the library open, symtab is already // built. Only for core dump we need to keep the fd open. close(lib->fd); lib->fd = -1; } } } free(freep); return true; #else char *l_name; struct link_map *lmap; uintptr_t lmap_addr; if ((l_name = malloc(BUF_SIZE)) == NULL) return false; if ((lmap = malloc(sizeof(*lmap))) == NULL) { free(l_name); return false; } lmap_addr = linkmap_addr(ph); if (lmap_addr == 0) { free(l_name); free(lmap); return false; } do { if (process_read_data(ph, lmap_addr, (char *)lmap, sizeof(*lmap)) != true) { print_debug("process_read_data failed for lmap_addr %p\n", lmap_addr); free (l_name); free (lmap); return false; } if (process_read_data(ph, (uintptr_t)lmap->l_name, l_name, BUF_SIZE) != true) { print_debug("process_read_data failed for lmap->l_name %p\n", lmap->l_name); free (l_name); free (lmap); return false; } if (find_lib(ph, l_name) == false) { lib_info* lib; if ((lib = add_lib_info(ph, l_name, (uintptr_t) lmap->l_addr)) == NULL) continue; // ignore, add_lib_info prints error // we don't need to keep the library open, symtab is already // built. Only for core dump we need to keep the fd open. close(lib->fd); lib->fd = -1; } lmap_addr = (uintptr_t)lmap->l_next; } while (lmap->l_next != NULL); free (l_name); free (lmap); return true; #endif }