openbsd-ports/sysutils/lsof/patches/patch-dialects_n+obsd_dproc_c
sthen 63b61837cd fix with vmmap, originally from ariane@
(recommitting the right diff..)
2012-03-15 21:39:53 +00:00

178 lines
4.3 KiB
Plaintext

$OpenBSD: patch-dialects_n+obsd_dproc_c,v 1.2 2012/03/15 21:39:53 sthen Exp $
--- dialects/n+obsd/dproc.c.orig Wed May 11 14:54:00 2005
+++ dialects/n+obsd/dproc.c Sun Jan 8 20:40:43 2012
@@ -172,7 +172,10 @@ gather_proc_info()
static int pofb = 0;
#endif /* defined(HASFSTRUCT) */
-#if defined(HASKVMGETPROC2)
+#if defined(HASKVMGETPROCS)
+ struct kinfo_proc *p;
+#define KVMPROCSZ sizeof(struct kinfo_proc)
+#elif defined(HASKVMGETPROC2)
struct kinfo_proc2 *p;
#define KVMPROCSZ2 sizeof(struct kinfo_proc2)
#else /* !defined(HASKVMGETPROC2) */
@@ -183,11 +186,13 @@ gather_proc_info()
* Read the process table.
*/
-#if defined(HASKVMGETPROC2)
+#if defined(HASKVMGETPROCS)
+ P = kvm_getprocs(Kd, KERN_PROC_ALL, 0, KVMPROCSZ, &Np);
+#elif defined(HASKVMGETPROC2)
P = kvm_getproc2(Kd, KERN_PROC_ALL, 0, KVMPROCSZ2, &Np);
#else /* !defined(HASKVMGETPROC2) */
P = kvm_getprocs(Kd, KERN_PROC_ALL, 0, &Np);
-#endif /* defined(HASKVMGETPROC2) &/
+#endif /* defined(HASKVMGETPROC2) */
if (!P) {
(void) fprintf(stderr, "%s: can't read process table: %s\n",
@@ -503,19 +508,98 @@ kread(addr, buf, len)
return((br == len) ? 0 : 1);
}
+/*
+ * Download vmmap_entries from the kernel into our address space.
+ * We fix up the addr tree while downloading.
+ *
+ * Returns: the size of the tree on success, or -1 on failure.
+ * On failure, *rptr needs to be passed to unload_vmmap_entries to free
+ * the lot.
+ */
+ssize_t
+load_vmmap_entries(KA_T kptr, struct vm_map_entry **rptr,
+ struct vm_map_entry *parent)
+{
+ struct vm_map_entry *entry;
+ KA_T left_kptr, right_kptr;
+ ssize_t left_sz;
+ ssize_t right_sz;
+ if (kptr == 0)
+ return 0;
+
+ /* Need space. */
+ entry = malloc(sizeof(*entry));
+ if (entry == NULL)
+ return -1;
+
+ /* Download entry at kptr. */
+ if (!kread(kptr, (char *)entry, sizeof(*entry))) {
+ free(entry);
+ return -1;
+ }
+
+ /*
+ * Update addr pointers to have sane values in this address space.
+ * We save the kernel pointers in {left,right}_kptr, so we have them
+ * available to download children.
+ */
+ left_kptr = (KA_T) RB_LEFT(entry, daddrs.addr_entry);
+ right_kptr = (KA_T) RB_RIGHT(entry, daddrs.addr_entry);
+ RB_LEFT(entry, daddrs.addr_entry) =
+ RB_RIGHT(entry, daddrs.addr_entry) = NULL;
+ /* Fill in parent pointer. */
+ RB_PARENT(entry, daddrs.addr_entry) = parent;
+
+ /*
+ * Consistent state reached, fill in *rptr.
+ */
+ *rptr = entry;
+
+ /*
+ * Download left, right.
+ * On failure, our map is in a state that can be handled by
+ * unload_vmmap_entries.
+ */
+ left_sz = load_vmmap_entries(left_kptr,
+ &RB_LEFT(entry, daddrs.addr_entry), entry);
+ if (left_sz == -1)
+ return -1;
+ right_sz = load_vmmap_entries(right_kptr,
+ &RB_RIGHT(entry, daddrs.addr_entry), entry);
+ if (right_sz == -1)
+ return -1;
+
+ return 1 + left_sz + right_sz;
+}
+
/*
+ * Free the vmmap entries in the given tree.
+ */
+void
+unload_vmmap_entries(struct vm_map_entry *entry)
+{
+ if (entry == NULL)
+ return;
+
+ unload_vmmap_entries(RB_LEFT(entry, daddrs.addr_entry));
+ unload_vmmap_entries(RB_RIGHT(entry, daddrs.addr_entry));
+ free(entry);
+}
+
+/*
* process_text() - process text information
*/
void
process_text(vm)
KA_T vm; /* kernel vm space pointer */
{
- int i, j;
+ int j;
KA_T ka;
int n = 0;
struct vm_map_entry vmme, *e;
struct vmspace vmsp;
+ struct uvm_map_addr root;
#if !defined(UVM)
struct pager_struct pg;
@@ -536,20 +620,12 @@ process_text(vm)
return;
#endif /* !defined(UVM) */
- for (i = 0; i < vmsp.vm_map.nentries; i++) {
+ RB_INIT(&root);
+ if (load_vmmap_entries((KA_T) RB_ROOT(&vmsp.vm_map.addr),
+ &RB_ROOT(&root), NULL) == -1)
+ goto do_unload;
- /*
- * Read the next vm_map_entry.
- */
- if (!i)
- e = &vmsp.vm_map.header;
- else {
- if (!(ka = (KA_T)e->next))
- return;
- e = &vmme;
- if (kread(ka, (char *)e, sizeof(vmme)))
- return;
- }
+ RB_FOREACH(e, uvm_map_addr, &root) {
#if defined(UVM)
/*
@@ -581,4 +657,19 @@ process_text(vm)
#endif /* defined(UVM) */
}
+
+do_unload:
+ unload_vmmap_entries(RB_ROOT(&root));
}
+
+/*
+ * Don't implement address comparison.
+ */
+static __inline int
+no_impl(void *p, void *q)
+{
+ abort(); /* Should not be called. */
+ return 0;
+}
+
+RB_GENERATE(uvm_map_addr, vm_map_entry, daddrs.addr_entry, no_impl);