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 * 13 * Copyright (c) 2004 The DragonFly Project. All rights reserved. 14 * 15 * This code is derived from software contributed to The DragonFly Project 16 * by Matthew Dillon <dillon@backplane.com> 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 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. 31 * 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. 44 * 45 * $DragonFly: src/test/debug/ncptrace.c,v 1.5 2004/10/08 18:32:58 dillon Exp $ 46 */ 47 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> 55 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> 61 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> 69 70 struct nlist Nl[] = { 71 #ifdef CINV_PARENT 72 { "_rootncp" }, 73 #else 74 { "_rootnamecache" }, 75 #endif 76 { NULL } 77 }; 78 79 void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes); 80 void dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path); 81 82 main(int ac, char **av) 83 { 84 struct namecache *ncptr; 85 kvm_t *kd; 86 const char *corefile = NULL; 87 const char *sysfile = NULL; 88 int ch; 89 int i; 90 91 while ((ch = getopt(ac, av, "M:N:")) != -1) { 92 switch(ch) { 93 case 'M': 94 corefile = optarg; 95 break; 96 case 'N': 97 sysfile = optarg; 98 break; 99 default: 100 fprintf(stderr, "%s [-M core] [-N system]\n", av[0]); 101 exit(1); 102 } 103 } 104 ac -= optind; 105 av += optind; 106 107 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { 108 perror("kvm_open"); 109 exit(1); 110 } 111 if (kvm_nlist(kd, Nl) != 0) { 112 perror("kvm_nlist"); 113 exit(1); 114 } 115 #ifdef CINV_PARENT 116 kkread(kd, Nl[0].n_value, &ncptr, sizeof(ncptr)); 117 #else 118 ncptr = (void *)Nl[0].n_value; 119 #endif 120 if (ac == 0) { 121 dumpncp(kd, 0, ncptr, NULL); 122 } else { 123 for (i = 0; i < ac; ++i) { 124 if (av[i][0] != '/') 125 fprintf(stderr, "%s: path must start at the root\n", av[i]); 126 dumpncp(kd, 0, ncptr, av[i]); 127 } 128 } 129 } 130 131 void 132 dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path) 133 { 134 struct namecache ncp; 135 struct namecache *ncscan; 136 const char *ptr; 137 int haschildren; 138 char name[256]; 139 140 kkread(kd, (u_long)ncptr, &ncp, sizeof(ncp)); 141 if (ncp.nc_nlen < sizeof(name)) { 142 kkread(kd, (u_long)ncp.nc_name, name, ncp.nc_nlen); 143 name[ncp.nc_nlen] = 0; 144 } else { 145 name[0] = 0; 146 } 147 if (tab == 0) { 148 strcpy(name, "ROOT"); 149 if (path) 150 ++path; 151 } else if (ncp.nc_flag & NCF_MOUNTPT) { 152 strcpy(name, "MOUNTGLUE"); 153 } else if (name[0] == 0) { 154 strcpy(name, "?"); 155 if (path) 156 return; 157 } else if (path) { 158 if ((ptr = strchr(path, '/')) == NULL) 159 ptr = path + strlen(path); 160 if (strlen(name) != ptr - path || 161 bcmp(name, path, ptr - path) != 0 162 ) { 163 return; 164 } 165 path = ptr; 166 if (*path == '/') 167 ++path; 168 if (*path == 0) 169 path = NULL; 170 } 171 172 if (ncp.nc_list.tqh_first) 173 haschildren = 1; 174 else 175 haschildren = 0; 176 177 if (path) 178 printf("ELM "); 179 else 180 printf("%*.*s%s ", tab, tab, "", name); 181 printf("[ncp=%p par=%p %04x vp=%p", 182 ncptr, ncp.nc_parent, ncp.nc_flag, ncp.nc_vp); 183 if (ncp.nc_timeout) 184 printf(" timo=%d", ncp.nc_timeout); 185 if (ncp.nc_refs) 186 printf(" refs=%d", ncp.nc_refs); 187 if ((ncp.nc_flag & NCF_UNRESOLVED) == 0 && ncp.nc_error) 188 printf(" error=%d", ncp.nc_error); 189 if (ncp.nc_exlocks) 190 printf(" LOCKED(%d,td=%p)", ncp.nc_exlocks, ncp.nc_locktd); 191 printf("]"); 192 193 if (path) { 194 printf(" %s\n", name); 195 } else { 196 printf("%s\n", haschildren ? " {" : ""); 197 } 198 for (ncscan = ncp.nc_list.tqh_first; ncscan; ncscan = ncp.nc_entry.tqe_next) { 199 kkread(kd, (u_long)ncscan, &ncp, sizeof(ncp)); 200 dumpncp(kd, (path ? (tab ? tab : 4) : tab + 4), ncscan, path); 201 } 202 if (haschildren && path == NULL) 203 printf("%*.*s}\n", tab, tab, ""); 204 } 205 206 void 207 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes) 208 { 209 if (kvm_read(kd, addr, buf, nbytes) != nbytes) { 210 perror("kvm_read"); 211 exit(1); 212 } 213 } 214 215