This re-introduces the vnode-to-filename mapping code with adaptions to
the new namecache layout.

For example, running procmap -a 1 now prints the .text, .data, and
.rodata segments of init(1) as below, if /sbin/init is in the
name cache:

104ccb700000-104ccb73dfff 248k 00000 r-xp+ (rwx) 1/0/0 04:00 42 - /sbin/init 
[0xffffff043c977898]
104ccb83d000-104ccb847fff  44k 3d000 r--p+ (rwx) 1/0/0 04:00 42 - /sbin/init 
[0xffffff043c977898]
104ccbb48000-104ccbb48fff   4k 48000 rw-p+ (rwx) 1/0/0 04:00 42 - /sbin/init 
[0xffffff043c977898]

ok?

Index: usr.sbin/procmap/procmap.1
===================================================================
RCS file: /cvs/src/usr.sbin/procmap/procmap.1,v
retrieving revision 1.20
diff -u -p -r1.20 procmap.1
--- usr.sbin/procmap/procmap.1  13 Mar 2015 19:58:41 -0000      1.20
+++ usr.sbin/procmap/procmap.1  26 May 2016 08:02:58 -0000
@@ -90,6 +90,8 @@ dump the process's vm_map structure
 dump the vm_map.header structure
 .It Cm 8
 dump each vm_map_entry in its entirety
+.It Cm 16
+dump the namei cache as it is traversed
 .El
 .It Fl d
 Dumps the vm_map and vm_map_entry structures in a style similar to
Index: usr.sbin/procmap/procmap.c
===================================================================
RCS file: /cvs/src/usr.sbin/procmap/procmap.c,v
retrieving revision 1.61
diff -u -p -r1.61 procmap.c
--- usr.sbin/procmap/procmap.c  25 May 2016 15:45:53 -0000      1.61
+++ usr.sbin/procmap/procmap.c  26 May 2016 08:02:58 -0000
@@ -38,6 +38,7 @@
 #include <sys/vnode.h>
 #include <sys/mount.h>
 #include <sys/uio.h>
+#include <sys/namei.h>
 #include <sys/sysctl.h>
 
 /* XXX until uvm gets cleaned up */
@@ -79,6 +80,7 @@ typedef int boolean_t;
 #define PRINT_VM_MAP           0x00000002
 #define PRINT_VM_MAP_HEADER    0x00000004
 #define PRINT_VM_MAP_ENTRY     0x00000008
+#define DUMP_NAMEI_CACHE       0x00000010
 
 struct cache_entry {
        LIST_ENTRY(cache_entry) ce_next;
@@ -89,8 +91,10 @@ struct cache_entry {
 };
 
 LIST_HEAD(cache_head, cache_entry) lcache;
+TAILQ_HEAD(namecache_head, namecache) nclruhead;
+int namecache_loaded;
 void *uvm_vnodeops, *uvm_deviceops, *aobj_pager;
-u_long kernel_map_addr;
+u_long kernel_map_addr, nclruhead_addr;
 int debug, verbose;
 int print_all, print_map, print_maps, print_solaris, print_ddb, print_amap;
 int rwx = PROT_READ | PROT_WRITE | PROT_EXEC;
@@ -165,6 +169,8 @@ struct nlist nl[] = {
 #define NL_AOBJ_PAGER          3
        { "_kernel_map" },
 #define NL_KERNEL_MAP          4
+       { "_nclruhead" },
+#define NL_NCLRUHEAD           5
        { NULL }
 };
 
@@ -178,6 +184,8 @@ size_t dump_vm_map_entry(kvm_t *, struct
 char *findname(kvm_t *, struct kbit *, struct vm_map_entry *, struct kbit *,
     struct kbit *, struct kbit *);
 int search_cache(kvm_t *, struct kbit *, char **, char *, size_t);
+void load_name_cache(kvm_t *);
+void cache_enter(struct namecache *);
 static void __dead usage(void);
 static pid_t strtopid(const char *);
 void print_sum(struct sum *, struct sum *);
@@ -219,7 +227,7 @@ main(int argc, char *argv[])
                        print_ddb = 1;
                        break;
                case 'D':
-                       debug = strtonum(optarg, 0, 0xf, &errstr);
+                       debug = strtonum(optarg, 0, 0x1f, &errstr);
                        if (errstr)
                                errx(1, "invalid debug mask");
                        break;
@@ -524,6 +532,8 @@ load_symbols(kvm_t *kd)
        uvm_deviceops = (void*)nl[NL_UVM_DEVICEOPS].n_value;
        aobj_pager =    (void*)nl[NL_AOBJ_PAGER].n_value;
 
+       nclruhead_addr = nl[NL_NCLRUHEAD].n_value;
+
        _KDEREF(kd, nl[NL_MAXSSIZ].n_value, &maxssiz,
            sizeof(maxssiz));
        _KDEREF(kd, nl[NL_KERNEL_MAP].n_value, &kernel_map_addr,
@@ -889,6 +899,9 @@ search_cache(kvm_t *kd, struct kbit *vp,
        char *o, *e;
        u_long cid;
 
+       if (!namecache_loaded)
+               load_name_cache(kd);
+
        P(&svp) = P(vp);
        S(&svp) = sizeof(struct vnode);
        cid = D(vp, vnode)->v_id;
@@ -900,8 +913,11 @@ search_cache(kvm_t *kd, struct kbit *vp,
                        if (ce->ce_vp == P(&svp) && ce->ce_cid == cid)
                                break;
                if (ce && ce->ce_vp == P(&svp) && ce->ce_cid == cid) {
-                       if (o != e)
+                       if (o != e) {
+                               if (o <= buf)
+                                       break;
                                *(--o) = '/';
+                       }
                        if (o - ce->ce_nlen <= buf)
                                break;
                        o -= ce->ce_nlen;
@@ -919,6 +935,56 @@ search_cache(kvm_t *kd, struct kbit *vp,
 
        KDEREF(kd, &svp);
        return (D(&svp, vnode)->v_flag & VROOT);
+}
+
+void
+load_name_cache(kvm_t *kd)
+{
+       struct namecache n, *tmp;
+       struct namecache_head nchead;
+
+       LIST_INIT(&lcache);
+       _KDEREF(kd, nclruhead_addr, &nchead, sizeof(nchead));
+       tmp = TAILQ_FIRST(&nchead);
+       while (tmp != NULL) {
+               _KDEREF(kd, (u_long)tmp, &n, sizeof(n));
+
+               if (n.nc_nlen > 0) {
+                       if (n.nc_nlen > 2 ||
+                           n.nc_name[0] != '.' ||
+                           (n.nc_nlen != 1 && n.nc_name[1] != '.'))
+                               cache_enter(&n);
+               }
+               tmp = TAILQ_NEXT(&n, nc_lru);
+       }
+
+       namecache_loaded = 1;
+}
+
+void
+cache_enter(struct namecache *ncp)
+{
+       struct cache_entry *ce;
+
+       if (debug & DUMP_NAMEI_CACHE)
+               printf("ncp->nc_vp %10p, ncp->nc_dvp %10p, ncp->nc_nlen "
+                   "%3d [%.*s] (nc_dvpid=%lu, nc_vpid=%lu)\n",
+                   ncp->nc_vp, ncp->nc_dvp,
+                   ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name,
+                   ncp->nc_dvpid, ncp->nc_vpid);
+
+       ce = malloc(sizeof(struct cache_entry));
+       if (ce == NULL)
+               err(1, "cache_enter");
+
+       ce->ce_vp = ncp->nc_vp;
+       ce->ce_pvp = ncp->nc_dvp;
+       ce->ce_cid = ncp->nc_vpid;
+       ce->ce_pcid = ncp->nc_dvpid;
+       ce->ce_nlen = (unsigned)ncp->nc_nlen;
+       strlcpy(ce->ce_name, ncp->nc_name, sizeof(ce->ce_name));
+
+       LIST_INSERT_HEAD(&lcache, ce, ce_next);
 }
 
 static void __dead

Reply via email to