Fix the -N and M options for ncptrace.
[dragonfly.git] / test / debug / ncptrace.c
1 /*
2  * NCPTRACE.C
3  *
4  * cc -I/usr/src/sys ncptrace.c -o /usr/local/bin/ncptrace -lkvm
5  *
6  * ncptrace
7  * ncptrace [path]
8  *
9  * Trace and dump the kernel namecache hierarchy.  If a path is specified
10  * the trace begins there, otherwise the trace begins at the root.
11  *
12  * $DragonFly: src/test/debug/ncptrace.c,v 1.4 2004/10/07 10:15:06 dillon Exp $
13  */
14
15 #define _KERNEL_STRUCTURES_
16 #include <sys/param.h>
17 #include <sys/user.h>
18 #include <sys/malloc.h>
19 #include <sys/signalvar.h>
20 #include <sys/vnode.h>
21 #include <sys/namecache.h>
22
23 #include <vm/vm.h>
24 #include <vm/vm_page.h>
25 #include <vm/vm_kern.h>
26 #include <vm/swap_pager.h>
27 #include <vm/vnode_pager.h>
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <kvm.h>
34 #include <nlist.h>
35 #include <getopt.h>
36
37 struct nlist Nl[] = {
38 #ifdef CINV_PARENT
39     { "_rootncp" },
40 #else
41     { "_rootnamecache" },
42 #endif
43     { NULL }
44 };
45
46 void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
47 void dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path);
48
49 main(int ac, char **av)
50 {
51     struct namecache *ncptr;
52     kvm_t *kd;
53     const char *corefile = NULL;
54     const char *sysfile = NULL;
55     int ch;
56     int i;
57
58     while ((ch = getopt(ac, av, "M:N:")) != -1) {
59         switch(ch) {
60         case 'M':
61             corefile = optarg;
62             break;
63         case 'N':
64             sysfile = optarg;
65             break;
66         default:
67             fprintf(stderr, "%s [-M core] [-N system]\n", av[0]);
68             exit(1);
69         }
70     }
71     ac -= optind;
72     av += optind;
73
74     if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) {
75         perror("kvm_open");
76         exit(1);
77     }
78     if (kvm_nlist(kd, Nl) != 0) {
79         perror("kvm_nlist");
80         exit(1);
81     }
82 #ifdef CINV_PARENT
83     kkread(kd, Nl[0].n_value, &ncptr, sizeof(ncptr));
84 #else
85     ncptr = (void *)Nl[0].n_value;
86 #endif
87     if (ac == 0) {
88         dumpncp(kd, 0, ncptr, NULL);
89     } else {
90         for (i = 0; i < ac; ++i) {
91             if (av[i][0] != '/')
92                 fprintf(stderr, "%s: path must start at the root\n", av[i]);
93             dumpncp(kd, 0, ncptr, av[i]);
94         }
95     }
96 }
97
98 void
99 dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path)
100 {
101     struct namecache ncp;
102     struct namecache *ncscan;
103     const char *ptr;
104     int haschildren;
105     char name[256];
106
107     kkread(kd, (u_long)ncptr, &ncp, sizeof(ncp));
108     if (ncp.nc_nlen < sizeof(name)) {
109         kkread(kd, (u_long)ncp.nc_name, name, ncp.nc_nlen);
110         name[ncp.nc_nlen] = 0;
111     } else {
112         name[0] = 0;
113     }
114     if (tab == 0) {
115         strcpy(name, "ROOT");
116         if (path)
117             ++path;
118     } else if (ncp.nc_flag & NCF_MOUNTPT) {
119         strcpy(name, "MOUNTGLUE");
120     } else if (name[0] == 0) {
121         strcpy(name, "?");
122         if (path)
123             return;
124     } else if (path) {
125         if ((ptr = strchr(path, '/')) == NULL)
126             ptr = path + strlen(path);
127         if (strlen(name) != ptr - path ||
128             bcmp(name, path, ptr - path) != 0
129         ) {
130             return;
131         }
132         path = ptr;
133         if (*path == '/')
134             ++path;
135         if (*path == 0)
136             path = NULL;
137     }
138
139     if (ncp.nc_list.tqh_first)
140         haschildren = 1;
141     else
142         haschildren = 0;
143
144     if (path)
145         printf("ELM ");
146     else
147         printf("%*.*s%s ", tab, tab, "", name);
148     printf("[ncp=%p par=%p %04x vp=%p", 
149             ncptr, ncp.nc_parent, ncp.nc_flag, ncp.nc_vp);
150     if (ncp.nc_timeout)
151         printf(" timo=%d", ncp.nc_timeout);
152     if (ncp.nc_refs)
153         printf(" refs=%d", ncp.nc_refs);
154     if ((ncp.nc_flag & NCF_UNRESOLVED) == 0 && ncp.nc_error)
155         printf(" error=%d", ncp.nc_error);
156     if (ncp.nc_exlocks)
157         printf(" LOCKED(%d,td=%p)", ncp.nc_exlocks, ncp.nc_locktd);
158     printf("]");
159
160     if (path) {
161         printf(" %s\n", name);
162     } else {
163         printf("%s\n", haschildren ? " {" : "");
164     }
165     for (ncscan = ncp.nc_list.tqh_first; ncscan; ncscan = ncp.nc_entry.tqe_next) {
166         kkread(kd, (u_long)ncscan, &ncp, sizeof(ncp));
167         dumpncp(kd, (path ? (tab ? tab : 4) : tab + 4), ncscan, path);
168     }
169     if (haschildren && path == NULL)
170         printf("%*.*s}\n", tab, tab, "");
171 }
172
173 void
174 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
175 {
176     if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
177         perror("kvm_read");
178         exit(1);
179     }
180 }
181