Sync with NetBSD.
[dragonfly/vkernel-mp.git] / test / debug / ncptrace.c
blobf3142a292b532b9fd7f8c49291da23d8f96022a2
1 /*
2 * NCPTRACE.C
4 * cc -I/usr/src/sys ncptrace.c -o /usr/local/bin/ncptrace -lkvm
6 * ncptrace
7 * ncptrace [path]
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.
13 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
15 * This code is derived from software contributed to The DragonFly Project
16 * by Matthew Dillon <dillon@backplane.com>
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in
26 * the documentation and/or other materials provided with the
27 * distribution.
28 * 3. Neither the name of The DragonFly Project nor the names of its
29 * contributors may be used to endorse or promote products derived
30 * from this software without specific, prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
36 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
37 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
38 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
40 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
45 * $DragonFly: src/test/debug/ncptrace.c,v 1.6 2005/03/24 21:15:11 dillon Exp $
48 #define _KERNEL_STRUCTURES
49 #include <sys/param.h>
50 #include <sys/user.h>
51 #include <sys/malloc.h>
52 #include <sys/signalvar.h>
53 #include <sys/vnode.h>
54 #include <sys/namecache.h>
56 #include <vm/vm.h>
57 #include <vm/vm_page.h>
58 #include <vm/vm_kern.h>
59 #include <vm/swap_pager.h>
60 #include <vm/vnode_pager.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <fcntl.h>
66 #include <kvm.h>
67 #include <nlist.h>
68 #include <getopt.h>
70 struct nlist Nl[] = {
71 { "_rootncp" },
72 { NULL }
75 void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
76 void dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path);
78 main(int ac, char **av)
80 struct namecache *ncptr;
81 kvm_t *kd;
82 const char *corefile = NULL;
83 const char *sysfile = NULL;
84 int ch;
85 int i;
87 while ((ch = getopt(ac, av, "M:N:")) != -1) {
88 switch(ch) {
89 case 'M':
90 corefile = optarg;
91 break;
92 case 'N':
93 sysfile = optarg;
94 break;
95 default:
96 fprintf(stderr, "%s [-M core] [-N system]\n", av[0]);
97 exit(1);
100 ac -= optind;
101 av += optind;
103 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) {
104 perror("kvm_open");
105 exit(1);
107 if (kvm_nlist(kd, Nl) != 0) {
108 perror("kvm_nlist");
109 exit(1);
111 kkread(kd, Nl[0].n_value, &ncptr, sizeof(ncptr));
112 if (ac == 0) {
113 dumpncp(kd, 0, ncptr, NULL);
114 } else {
115 for (i = 0; i < ac; ++i) {
116 if (av[i][0] != '/')
117 fprintf(stderr, "%s: path must start at the root\n", av[i]);
118 dumpncp(kd, 0, ncptr, av[i]);
123 void
124 dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path)
126 struct namecache ncp;
127 struct namecache *ncscan;
128 const char *ptr;
129 int haschildren;
130 char name[256];
132 kkread(kd, (u_long)ncptr, &ncp, sizeof(ncp));
133 if (ncp.nc_nlen < sizeof(name)) {
134 kkread(kd, (u_long)ncp.nc_name, name, ncp.nc_nlen);
135 name[ncp.nc_nlen] = 0;
136 } else {
137 name[0] = 0;
139 if (tab == 0) {
140 strcpy(name, "ROOT");
141 if (path)
142 ++path;
143 } else if (ncp.nc_flag & NCF_MOUNTPT) {
144 strcpy(name, "MOUNTGLUE");
145 } else if (name[0] == 0) {
146 strcpy(name, "?");
147 if (path)
148 return;
149 } else if (path) {
150 if ((ptr = strchr(path, '/')) == NULL)
151 ptr = path + strlen(path);
152 if (strlen(name) != ptr - path ||
153 bcmp(name, path, ptr - path) != 0
155 return;
157 path = ptr;
158 if (*path == '/')
159 ++path;
160 if (*path == 0)
161 path = NULL;
164 if (ncp.nc_list.tqh_first)
165 haschildren = 1;
166 else
167 haschildren = 0;
169 if (path)
170 printf("ELM ");
171 else
172 printf("%*.*s%s ", tab, tab, "", name);
173 printf("[ncp=%p par=%p %04x vp=%p",
174 ncptr, ncp.nc_parent, ncp.nc_flag, ncp.nc_vp);
175 if (ncp.nc_timeout)
176 printf(" timo=%d", ncp.nc_timeout);
177 if (ncp.nc_refs)
178 printf(" refs=%d", ncp.nc_refs);
179 if ((ncp.nc_flag & NCF_UNRESOLVED) == 0 && ncp.nc_error)
180 printf(" error=%d", ncp.nc_error);
181 if (ncp.nc_exlocks)
182 printf(" LOCKED(%d,td=%p)", ncp.nc_exlocks, ncp.nc_locktd);
183 printf("]");
185 if (path) {
186 printf(" %s\n", name);
187 } else {
188 printf("%s\n", haschildren ? " {" : "");
190 for (ncscan = ncp.nc_list.tqh_first; ncscan; ncscan = ncp.nc_entry.tqe_next) {
191 kkread(kd, (u_long)ncscan, &ncp, sizeof(ncp));
192 dumpncp(kd, (path ? (tab ? tab : 4) : tab + 4), ncscan, path);
194 if (haschildren && path == NULL)
195 printf("%*.*s}\n", tab, tab, "");
198 void
199 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
201 if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
202 perror("kvm_read");
203 exit(1);