1*64eea40cSguenther /* $OpenBSD: ksyms.c,v 1.34 2022/01/08 22:54:49 guenther Exp $ */
2220b8306Smillert /*
3bf198cc6Smillert * Copyright (c) 1998 Todd C. Miller <millert@openbsd.org>
4587a3b59Sart * Copyright (c) 2001 Artur Grabowski <art@openbsd.org>
5220b8306Smillert * All rights reserved.
6220b8306Smillert *
7220b8306Smillert * Redistribution and use in source and binary forms, with or without
8220b8306Smillert * modification, are permitted provided that the following conditions
9220b8306Smillert * are met:
10220b8306Smillert * 1. Redistributions of source code must retain the above copyright
11220b8306Smillert * notice, this list of conditions and the following disclaimer.
12220b8306Smillert * 2. Redistributions in binary form must reproduce the above copyright
13220b8306Smillert * notice, this list of conditions and the following disclaimer in the
14220b8306Smillert * documentation and/or other materials provided with the distribution.
15220b8306Smillert *
16220b8306Smillert * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17220b8306Smillert * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18220b8306Smillert * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19587a3b59Sart * THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20220b8306Smillert * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21220b8306Smillert * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22220b8306Smillert * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23220b8306Smillert * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24220b8306Smillert * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25220b8306Smillert * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26220b8306Smillert */
27220b8306Smillert
28220b8306Smillert #include <sys/param.h>
29220b8306Smillert #include <sys/exec.h>
30220b8306Smillert #include <sys/systm.h>
31220b8306Smillert #include <sys/uio.h>
32220b8306Smillert #include <sys/malloc.h>
33220b8306Smillert #include <sys/fcntl.h>
340a78fa0fSmickey #include <sys/conf.h>
35587a3b59Sart #include <sys/exec_elf.h>
36587a3b59Sart
37220b8306Smillert extern char *esym; /* end of symbol table */
38414976a8Smlarkin #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \
39060e6ef1Skettenis defined(__i386__) || defined(__powerpc64__)
40dea2358bSjason extern char *ssym; /* end of kernel */
41dea2358bSjason #else
42220b8306Smillert extern long end; /* end of kernel */
43dea2358bSjason #endif
44220b8306Smillert
45587a3b59Sart static caddr_t ksym_head;
46587a3b59Sart static caddr_t ksym_syms;
47587a3b59Sart static size_t ksym_head_size;
48587a3b59Sart static size_t ksym_syms_size;
49220b8306Smillert
50c4071fd1Smillert void ksymsattach(int);
51220b8306Smillert
52220b8306Smillert void
ksymsattach(int num)53efbf6099Stedu ksymsattach(int num)
54220b8306Smillert {
55220b8306Smillert
56414976a8Smlarkin #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \
57060e6ef1Skettenis defined(__i386__) || defined(__powerpc64__)
58dea2358bSjason if (esym <= ssym) {
59dea2358bSjason printf("/dev/ksyms: Symbol table not valid.\n");
60dea2358bSjason return;
61dea2358bSjason }
62dea2358bSjason #else
63587a3b59Sart if (esym <= (char *)&end) {
64587a3b59Sart printf("/dev/ksyms: Symbol table not valid.\n");
65587a3b59Sart return;
66587a3b59Sart }
67dea2358bSjason #endif
68587a3b59Sart
69587a3b59Sart do {
70414976a8Smlarkin #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \
71060e6ef1Skettenis defined(__i386__) || defined(__powerpc64__)
72dea2358bSjason caddr_t symtab = ssym;
73dea2358bSjason #else
74587a3b59Sart caddr_t symtab = (caddr_t)&end;
75dea2358bSjason #endif
76587a3b59Sart Elf_Ehdr *elf;
77587a3b59Sart Elf_Shdr *shdr;
78587a3b59Sart int i;
79587a3b59Sart
80587a3b59Sart elf = (Elf_Ehdr *)symtab;
81587a3b59Sart if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
82587a3b59Sart elf->e_ident[EI_CLASS] != ELFCLASS ||
83587a3b59Sart elf->e_machine != ELF_TARG_MACH)
84587a3b59Sart break;
85587a3b59Sart
86587a3b59Sart shdr = (Elf_Shdr *)&symtab[elf->e_shoff];
87587a3b59Sart for (i = 0; i < elf->e_shnum; i++) {
88587a3b59Sart if (shdr[i].sh_type == SHT_SYMTAB) {
89587a3b59Sart break;
90587a3b59Sart }
91587a3b59Sart }
92587a3b59Sart
93220b8306Smillert /*
94587a3b59Sart * No symbol table found.
95587a3b59Sart */
96587a3b59Sart if (i == elf->e_shnum)
97587a3b59Sart break;
98587a3b59Sart
99587a3b59Sart /*
100587a3b59Sart * No additional header.
101587a3b59Sart */
102587a3b59Sart ksym_head_size = 0;
103587a3b59Sart ksym_syms = symtab;
104587a3b59Sart ksym_syms_size = (size_t)(esym - symtab);
105587a3b59Sart
106587a3b59Sart return;
107587a3b59Sart } while (0);
108220b8306Smillert }
109220b8306Smillert
110220b8306Smillert int
ksymsopen(dev_t dev,int flag,int mode,struct proc * p)111efbf6099Stedu ksymsopen(dev_t dev, int flag, int mode, struct proc *p)
112220b8306Smillert {
113220b8306Smillert
114220b8306Smillert /* There are no non-zero minor devices */
115220b8306Smillert if (minor(dev) != 0)
116220b8306Smillert return (ENXIO);
117220b8306Smillert
118220b8306Smillert /* This device is read-only */
119220b8306Smillert if ((flag & FWRITE))
120220b8306Smillert return (EPERM);
121220b8306Smillert
122587a3b59Sart /* ksym_syms must be initialized */
123587a3b59Sart if (ksym_syms == NULL)
124220b8306Smillert return (ENXIO);
125220b8306Smillert
126220b8306Smillert return (0);
127220b8306Smillert }
128220b8306Smillert
129220b8306Smillert int
ksymsclose(dev_t dev,int flag,int mode,struct proc * p)130efbf6099Stedu ksymsclose(dev_t dev, int flag, int mode, struct proc *p)
131220b8306Smillert {
132220b8306Smillert
133220b8306Smillert return (0);
134220b8306Smillert }
135220b8306Smillert
136220b8306Smillert int
ksymsread(dev_t dev,struct uio * uio,int flags)137efbf6099Stedu ksymsread(dev_t dev, struct uio *uio, int flags)
138220b8306Smillert {
139587a3b59Sart int error;
140587a3b59Sart size_t len;
141587a3b59Sart caddr_t v;
142587a3b59Sart size_t off;
143220b8306Smillert
144b7b85555Smatthew if (uio->uio_offset < 0)
145b7b85555Smatthew return (EINVAL);
146b7b85555Smatthew
147587a3b59Sart while (uio->uio_resid > 0) {
148587a3b59Sart if (uio->uio_offset >= ksym_head_size + ksym_syms_size)
149220b8306Smillert break;
150220b8306Smillert
151587a3b59Sart if (uio->uio_offset < ksym_head_size) {
152587a3b59Sart v = ksym_head + uio->uio_offset;
153587a3b59Sart len = ksym_head_size - uio->uio_offset;
154220b8306Smillert } else {
155587a3b59Sart off = uio->uio_offset - ksym_head_size;
156587a3b59Sart v = ksym_syms + off;
157587a3b59Sart len = ksym_syms_size - off;
158587a3b59Sart }
159220b8306Smillert
160587a3b59Sart if (len > uio->uio_resid)
161587a3b59Sart len = uio->uio_resid;
162587a3b59Sart
1635d723380Sstefan if ((error = uiomove(v, len, uio)) != 0)
164220b8306Smillert return (error);
165220b8306Smillert }
166220b8306Smillert
167587a3b59Sart return (0);
168587a3b59Sart }
169