Line data Source code
1 : /* $OpenBSD: ksyms.c,v 1.31 2016/01/11 17:29:43 stefan 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/exec.h>
30 : #include <sys/systm.h>
31 : #include <sys/uio.h>
32 : #include <sys/malloc.h>
33 : #include <sys/fcntl.h>
34 : #include <sys/conf.h>
35 : #include <sys/exec_elf.h>
36 :
37 : extern char *esym; /* end of symbol table */
38 : #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \
39 : defined(__i386__)
40 : extern char *ssym; /* end of kernel */
41 : #else
42 : extern long end; /* end of kernel */
43 : #endif
44 :
45 : static caddr_t ksym_head;
46 : static caddr_t ksym_syms;
47 : static size_t ksym_head_size;
48 : static size_t ksym_syms_size;
49 :
50 : void ksymsattach(int);
51 :
52 : /*
53 : * We assume __LDPGSZ is a multiple of PAGE_SIZE (it is)
54 : */
55 :
56 : void
57 0 : ksymsattach(int num)
58 : {
59 :
60 : #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \
61 : defined(__i386__)
62 0 : if (esym <= ssym) {
63 0 : printf("/dev/ksyms: Symbol table not valid.\n");
64 0 : return;
65 : }
66 : #else
67 : if (esym <= (char *)&end) {
68 : printf("/dev/ksyms: Symbol table not valid.\n");
69 : return;
70 : }
71 : #endif
72 :
73 : do {
74 : #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \
75 : defined(__i386__)
76 : caddr_t symtab = ssym;
77 : #else
78 : caddr_t symtab = (caddr_t)&end;
79 : #endif
80 : Elf_Ehdr *elf;
81 : Elf_Shdr *shdr;
82 : int i;
83 :
84 0 : elf = (Elf_Ehdr *)symtab;
85 0 : if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
86 0 : elf->e_ident[EI_CLASS] != ELFCLASS ||
87 0 : elf->e_machine != ELF_TARG_MACH)
88 0 : break;
89 :
90 0 : shdr = (Elf_Shdr *)&symtab[elf->e_shoff];
91 0 : for (i = 0; i < elf->e_shnum; i++) {
92 0 : if (shdr[i].sh_type == SHT_SYMTAB) {
93 : break;
94 : }
95 : }
96 :
97 : /*
98 : * No symbol table found.
99 : */
100 0 : if (i == elf->e_shnum)
101 0 : break;
102 :
103 : /*
104 : * No additional header.
105 : */
106 0 : ksym_head_size = 0;
107 0 : ksym_syms = symtab;
108 0 : ksym_syms_size = (size_t)(esym - symtab);
109 :
110 0 : return;
111 : } while (0);
112 0 : }
113 :
114 : int
115 0 : ksymsopen(dev_t dev, int flag, int mode, struct proc *p)
116 : {
117 :
118 : /* There are no non-zero minor devices */
119 0 : if (minor(dev) != 0)
120 0 : return (ENXIO);
121 :
122 : /* This device is read-only */
123 0 : if ((flag & FWRITE))
124 0 : return (EPERM);
125 :
126 : /* ksym_syms must be initialized */
127 0 : if (ksym_syms == NULL)
128 0 : return (ENXIO);
129 :
130 0 : return (0);
131 0 : }
132 :
133 : int
134 0 : ksymsclose(dev_t dev, int flag, int mode, struct proc *p)
135 : {
136 :
137 0 : return (0);
138 : }
139 :
140 : int
141 0 : ksymsread(dev_t dev, struct uio *uio, int flags)
142 : {
143 : int error;
144 : size_t len;
145 : caddr_t v;
146 : size_t off;
147 :
148 0 : if (uio->uio_offset < 0)
149 0 : return (EINVAL);
150 :
151 0 : while (uio->uio_resid > 0) {
152 0 : if (uio->uio_offset >= ksym_head_size + ksym_syms_size)
153 : break;
154 :
155 0 : if (uio->uio_offset < ksym_head_size) {
156 0 : v = ksym_head + uio->uio_offset;
157 0 : len = ksym_head_size - uio->uio_offset;
158 0 : } else {
159 0 : off = uio->uio_offset - ksym_head_size;
160 0 : v = ksym_syms + off;
161 0 : len = ksym_syms_size - off;
162 : }
163 :
164 0 : if (len > uio->uio_resid)
165 0 : len = uio->uio_resid;
166 :
167 0 : if ((error = uiomove(v, len, uio)) != 0)
168 0 : return (error);
169 : }
170 :
171 0 : return (0);
172 0 : }
|