xref: /openbsd-src/sys/dev/ksyms.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
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