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.6 2005/03/24 20:15:11 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 { "_rootncp" }, 72 { NULL } 73 }; 74 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); 77 78 main(int ac, char **av) 79 { 80 struct namecache *ncptr; 81 kvm_t *kd; 82 const char *corefile = NULL; 83 const char *sysfile = NULL; 84 int ch; 85 int i; 86 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); 98 } 99 } 100 ac -= optind; 101 av += optind; 102 103 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { 104 perror("kvm_open"); 105 exit(1); 106 } 107 if (kvm_nlist(kd, Nl) != 0) { 108 perror("kvm_nlist"); 109 exit(1); 110 } 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]); 119 } 120 } 121 } 122 123 void 124 dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path) 125 { 126 struct namecache ncp; 127 struct namecache *ncscan; 128 const char *ptr; 129 int haschildren; 130 char name[256]; 131 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; 138 } 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 154 ) { 155 return; 156 } 157 path = ptr; 158 if (*path == '/') 159 ++path; 160 if (*path == 0) 161 path = NULL; 162 } 163 164 if (ncp.nc_list.tqh_first) 165 haschildren = 1; 166 else 167 haschildren = 0; 168 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("]"); 184 185 if (path) { 186 printf(" %s\n", name); 187 } else { 188 printf("%s\n", haschildren ? " {" : ""); 189 } 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); 193 } 194 if (haschildren && path == NULL) 195 printf("%*.*s}\n", tab, tab, ""); 196 } 197 198 void 199 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes) 200 { 201 if (kvm_read(kd, addr, buf, nbytes) != nbytes) { 202 perror("kvm_read"); 203 exit(1); 204 } 205 } 206 207