1 /* $OpenBSD: ksyms.c,v 1.8 2001/06/08 08:09:36 art Exp $ */ 2 /* 3 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> 4 * Copyright (c) 2001 Artur Grabowski <art@openbsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the authors may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/buf.h> 32 #include <sys/exec.h> 33 #include <sys/systm.h> 34 #include <sys/uio.h> 35 #include <sys/malloc.h> 36 #include <sys/fcntl.h> 37 38 #ifdef _NLIST_DO_ELF 39 #include <sys/exec_elf.h> 40 #endif 41 42 #include <machine/cpu.h> 43 44 #include <vm/vm.h> 45 46 extern char *esym; /* end of symbol table */ 47 extern long end; /* end of kernel */ 48 49 static caddr_t ksym_head; 50 static caddr_t ksym_syms; 51 static size_t ksym_head_size; 52 static size_t ksym_syms_size; 53 54 void ksymsattach __P((int)); 55 int ksymsopen __P((dev_t, int, int)); 56 int ksymsclose __P((dev_t, int, int)); 57 int ksymsread __P((dev_t, struct uio *, int)); 58 59 /* 60 * We assume __LDPGSZ is a multiple of PAGE_SIZE (it is) 61 */ 62 63 /*ARGSUSED*/ 64 void 65 ksymsattach(num) 66 int num; 67 { 68 69 if (esym <= (char *)&end) { 70 printf("/dev/ksyms: Symbol table not valid.\n"); 71 return; 72 } 73 74 #ifdef _NLIST_DO_ELF 75 do { 76 caddr_t symtab = (caddr_t)&end; 77 Elf_Ehdr *elf; 78 Elf_Shdr *shdr; 79 int i; 80 81 elf = (Elf_Ehdr *)symtab; 82 if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 || 83 elf->e_ident[EI_CLASS] != ELFCLASS || 84 elf->e_machine != ELF_TARG_MACH) 85 break; 86 87 shdr = (Elf_Shdr *)&symtab[elf->e_shoff]; 88 for (i = 0; i < elf->e_shnum; i++) { 89 if (shdr[i].sh_type == SHT_SYMTAB) { 90 break; 91 } 92 } 93 94 /* 95 * No symbol table found. 96 */ 97 if (i == elf->e_shnum) 98 break; 99 100 /* 101 * No additional header. 102 */ 103 ksym_head_size = 0; 104 ksym_syms = symtab; 105 ksym_syms_size = (size_t)(esym - symtab); 106 107 return; 108 } while (0); 109 #endif 110 111 #ifdef _NLIST_DO_AOUT 112 { 113 /* 114 * a.out header. 115 * Fake up a struct exec. 116 * We only fill in the following non-zero entries: 117 * a_text - fake text segment (struct exec only) 118 * a_syms - size of symbol table 119 */ 120 caddr_t symtab = (char *)(&end + 1); 121 struct exec *k1; 122 123 ksym_head_size = __LDPGSZ; 124 ksym_head = malloc(ksym_head_size, M_DEVBUF, M_NOWAIT); 125 if (ksym_head == NULL) { 126 printf("failed to allocate memory for /dev/ksyms\n"); 127 return; 128 } 129 bzero(ksym_head, ksym_head_size); 130 131 k1 = (struct exec *)ksym_head; 132 133 N_SETMAGIC(*k1, ZMAGIC, MID_MACHINE, 0); 134 k1->a_text = __LDPGSZ; 135 k1->a_syms = end; 136 137 ksym_syms = symtab; 138 ksym_syms_size = (size_t)(esym - symtab); 139 } 140 #endif 141 } 142 143 /*ARGSUSED*/ 144 int 145 ksymsopen(dev, flag, mode) 146 dev_t dev; 147 int flag, mode; 148 { 149 150 /* There are no non-zero minor devices */ 151 if (minor(dev) != 0) 152 return (ENXIO); 153 154 /* This device is read-only */ 155 if ((flag & FWRITE)) 156 return (EPERM); 157 158 /* ksym_syms must be initialized */ 159 if (ksym_syms == NULL) 160 return (ENXIO); 161 162 return (0); 163 } 164 165 /*ARGSUSED*/ 166 int 167 ksymsclose(dev, flag, mode) 168 dev_t dev; 169 int flag, mode; 170 { 171 172 return (0); 173 } 174 175 /*ARGSUSED*/ 176 int 177 ksymsread(dev, uio, flags) 178 dev_t dev; 179 struct uio *uio; 180 int flags; 181 { 182 int error; 183 size_t len; 184 caddr_t v; 185 size_t off; 186 187 while (uio->uio_resid > 0) { 188 if (uio->uio_offset >= ksym_head_size + ksym_syms_size) 189 break; 190 191 if (uio->uio_offset < ksym_head_size) { 192 v = ksym_head + uio->uio_offset; 193 len = ksym_head_size - uio->uio_offset; 194 } else { 195 off = uio->uio_offset - ksym_head_size; 196 v = ksym_syms + off; 197 len = ksym_syms_size - off; 198 } 199 200 if (len > uio->uio_resid) 201 len = uio->uio_resid; 202 203 if ((error = uiomove(v, len, uio)) != 0) 204 return (error); 205 } 206 207 return (0); 208 } 209 210 /* XXX - not yet */ 211 #if 0 212 int 213 ksymsmmap(dev, off, prot) 214 dev_t dev; 215 int off, prot; 216 { 217 vaddr_t va; 218 paddr_t pa; 219 220 if (off < 0) 221 return (-1); 222 if (off >= ksym_head_size + ksym_syms_size) 223 return (-1); 224 225 if ((vaddr_t)off < ksym_head_size) { 226 va = (vaddr_t)ksym_head + off; 227 } else { 228 va = (vaddr_t)ksym_syms + off; 229 } 230 231 if (pmap_extract(pmap_kernel, va, &pa) == FALSE) 232 panic("ksymsmmap: unmapped page"); 233 234 return atop(pa); 235 } 236 #endif 237