root/dev/ksyms.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ksymsattach
  2. ksymsopen
  3. ksymsclose
  4. ksymsread
  5. ksymsmmap

    1 /*      $OpenBSD: ksyms.c,v 1.17 2006/07/12 18:09:24 martin 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  *
   16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
   17  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
   18  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
   19  * THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/param.h>
   29 #include <sys/buf.h>
   30 #include <sys/exec.h>
   31 #include <sys/systm.h>
   32 #include <sys/uio.h>
   33 #include <sys/malloc.h>
   34 #include <sys/fcntl.h>
   35 #include <sys/conf.h>
   36 
   37 #include <uvm/uvm_extern.h>
   38 
   39 #ifdef _NLIST_DO_ELF
   40 #include <sys/exec_elf.h>
   41 #endif
   42 
   43 #include <machine/cpu.h>
   44 
   45 extern char *esym;                              /* end of symbol table */
   46 #if defined(__sparc64__) || defined(__mips__)
   47 extern char *ssym;                              /* end of kernel */
   48 #else
   49 extern long end;                                /* end of kernel */
   50 #endif
   51 
   52 static caddr_t ksym_head;
   53 static caddr_t ksym_syms;
   54 static size_t ksym_head_size;
   55 static size_t ksym_syms_size;
   56 
   57 void    ksymsattach(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 defined(__sparc64__) || defined(__mips__)
   70         if (esym <= ssym) {
   71                 printf("/dev/ksyms: Symbol table not valid.\n");
   72                 return;
   73         }
   74 #else
   75         if (esym <= (char *)&end) {
   76                 printf("/dev/ksyms: Symbol table not valid.\n");
   77                 return;
   78         }
   79 #endif
   80 
   81 #ifdef _NLIST_DO_ELF
   82         do {
   83 #if defined(__sparc64__) || defined(__mips__)
   84                 caddr_t symtab = ssym;
   85 #else
   86                 caddr_t symtab = (caddr_t)&end;
   87 #endif
   88                 Elf_Ehdr *elf;
   89                 Elf_Shdr *shdr;
   90                 int i;
   91 
   92                 elf = (Elf_Ehdr *)symtab;
   93                 if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
   94                     elf->e_ident[EI_CLASS] != ELFCLASS ||
   95                     elf->e_machine != ELF_TARG_MACH)
   96                         break;
   97 
   98                 shdr = (Elf_Shdr *)&symtab[elf->e_shoff];
   99                 for (i = 0; i < elf->e_shnum; i++) {
  100                         if (shdr[i].sh_type == SHT_SYMTAB) {
  101                                 break;
  102                         }
  103                 }
  104 
  105                 /*
  106                  * No symbol table found.
  107                  */
  108                 if (i == elf->e_shnum)
  109                         break;
  110 
  111                 /*
  112                  * No additional header.
  113                  */
  114                 ksym_head_size = 0;
  115                 ksym_syms = symtab;
  116                 ksym_syms_size = (size_t)(esym - symtab);
  117 
  118                 return;
  119         } while (0);
  120 #endif
  121 
  122 #ifdef _NLIST_DO_AOUT
  123         {
  124                 /*
  125                  * a.out header.
  126                  * Fake up a struct exec.
  127                  * We only fill in the following non-zero entries:
  128                  *      a_text - fake text segment (struct exec only)
  129                  *      a_syms - size of symbol table
  130                  */
  131                 caddr_t symtab = (char *)(&end + 1);
  132                 struct exec *k1;
  133 
  134                 ksym_head_size = __LDPGSZ;
  135                 ksym_head = malloc(ksym_head_size, M_DEVBUF, M_NOWAIT);
  136                 if (ksym_head == NULL) {
  137                         printf("failed to allocate memory for /dev/ksyms\n");
  138                         return;
  139                 }
  140                 bzero(ksym_head, ksym_head_size);
  141 
  142                 k1 = (struct exec *)ksym_head;
  143 
  144                 N_SETMAGIC(*k1, ZMAGIC, MID_MACHINE, 0);
  145                 k1->a_text = __LDPGSZ;
  146                 k1->a_syms = end;
  147 
  148                 ksym_syms = symtab;
  149                 ksym_syms_size = (size_t)(esym - symtab);
  150         }
  151 #endif
  152 }
  153 
  154 /*ARGSUSED*/
  155 int
  156 ksymsopen(dev, flag, mode, p)
  157         dev_t dev;
  158         int flag, mode;
  159         struct proc *p;
  160 {
  161 
  162         /* There are no non-zero minor devices */
  163         if (minor(dev) != 0)
  164                 return (ENXIO);
  165 
  166         /* This device is read-only */
  167         if ((flag & FWRITE))
  168                 return (EPERM);
  169 
  170         /* ksym_syms must be initialized */
  171         if (ksym_syms == NULL)
  172                 return (ENXIO);
  173 
  174         return (0);
  175 }
  176 
  177 /*ARGSUSED*/
  178 int
  179 ksymsclose(dev, flag, mode, p)
  180         dev_t dev;
  181         int flag, mode;
  182         struct proc *p;
  183 {
  184 
  185         return (0);
  186 }
  187 
  188 /*ARGSUSED*/
  189 int
  190 ksymsread(dev, uio, flags)
  191         dev_t dev;
  192         struct uio *uio;
  193         int flags;
  194 {
  195         int error;
  196         size_t len;
  197         caddr_t v;
  198         size_t off;
  199 
  200         while (uio->uio_resid > 0) {
  201                 if (uio->uio_offset >= ksym_head_size + ksym_syms_size)
  202                         break;
  203 
  204                 if (uio->uio_offset < ksym_head_size) {
  205                         v = ksym_head + uio->uio_offset;
  206                         len = ksym_head_size - uio->uio_offset;
  207                 } else {
  208                         off = uio->uio_offset - ksym_head_size;
  209                         v = ksym_syms + off;
  210                         len = ksym_syms_size - off;
  211                 }
  212 
  213                 if (len > uio->uio_resid)
  214                         len = uio->uio_resid;
  215 
  216                 if ((error = uiomove(v, len, uio)) != 0)
  217                         return (error);
  218         }
  219 
  220         return (0);
  221 }
  222 
  223 /* XXX - not yet */
  224 #if 0
  225 paddr_t
  226 ksymsmmap(dev, off, prot)
  227         dev_t dev;
  228         off_t off;
  229         int prot;
  230 {
  231         vaddr_t va;
  232         paddr_t pa;
  233 
  234         if (off < 0)
  235                 return (-1);
  236         if (off >= ksym_head_size + ksym_syms_size)
  237                 return (-1);
  238 
  239         if ((vaddr_t)off < ksym_head_size) {
  240                 va = (vaddr_t)ksym_head + off;
  241         } else {
  242                 va = (vaddr_t)ksym_syms + off;
  243         }
  244 
  245         if (pmap_extract(pmap_kernel, va, &pa) == FALSE)
  246                 panic("ksymsmmap: unmapped page");
  247 
  248         return atop(pa);
  249 }
  250 #endif

/* [<][>][^][v][top][bottom][index][help] */