2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 static char sccsid[] = "@(#)from: nlist.c 8.1 (Berkeley) 6/6/93";
38 static const char rcsid[] =
39 "$Id: nlist.c,v 1.8 1997/09/24 06:44:10 charnier Exp $";
42 #include <sys/param.h>
47 #include <vm/vm_param.h>
67 typedef struct nlist NLIST;
68 #define _strx n_un.n_strx
69 #define _name n_un.n_name
71 #define badfmt(str) errx(1, "%s: %s: %s", kfile, str, strerror(EFTYPE))
77 __aout_knlist(name, db)
93 if ((fd = open(name, O_RDONLY, 0)) < 0)
98 filep = (u_char*)mmap(0, sst.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
100 if (filep == (u_char*)MAP_FAILED)
101 err(1, "mmap failed");
103 /* Read in exec structure. */
104 ebuf = (struct exec *) filep;
106 /* Check magic number and symbol count. */
108 badfmt("bad magic number");
112 strtab = filep + N_STROFF(*ebuf) + sizeof (int);
114 /* Seek to symbol table. */
115 cur_off = N_SYMOFF(*ebuf);
117 /* Read each symbol and enter it into the database. */
118 nsyms = ebuf->a_syms / sizeof(struct nlist);
121 nbuf = (NLIST *)(filep + cur_off);
122 cur_off += sizeof(NLIST);
124 if (!nbuf->_strx || nbuf->n_type&N_STAB)
127 key.data = (u_char *)strtab + nbuf->_strx - sizeof(long);
128 key.size = strlen((char *)key.data);
129 data.data = (u_char *)nbuf;
130 data.size = sizeof(NLIST);
131 if (db->put(db, &key, &data, 0))
132 err(1, "record enter");
134 if (1 && strcmp((char *)key.data, VRS_SYM) == 0) {
138 * The FreeBSD bootloader loads the kernel at the a_entry address, meaning
139 * that this is where the kernel starts. (not at KERNBASE)
141 * This may be introducing an i386 dependency.
143 #if defined(__FreeBSD__)
144 #define KERNTEXTOFF ebuf->a_entry
146 #define KERNTEXTOFF KERNBASE
150 * Calculate offset relative to a normal (non-kernel)
151 * a.out. KERNTEXTOFF is where the kernel is really
152 * loaded; N_TXTADDR is where a normal file is loaded.
153 * From there, locate file offset in text or data.
155 voff = nbuf->n_value - KERNTEXTOFF + N_TXTADDR(*ebuf);
156 if ((nbuf->n_type & N_TYPE) == N_TEXT)
157 voff += N_TXTOFF(*ebuf) - N_TXTADDR(*ebuf);
159 voff += N_DATOFF(*ebuf) - N_DATADDR(*ebuf);
163 key.data = (u_char *)VRS_KEY;
164 key.size = sizeof(VRS_KEY) - 1;
166 data.size = strchr(vp, '\n') - vp + 1;
168 if (db->put(db, &key, &data, 0))
169 err(1, "record enter");
171 /* Restore to original values. */
172 data.size = sizeof(NLIST);
184 __elf_knlist(name, db)
188 register caddr_t strtab;
189 register off_t symstroff, symoff;
190 register u_long symsize;
191 register u_long kernvma, kernoffs;
195 char *shstr, buf[1024];
205 if ((fd = open(name, O_RDONLY, 0)) < 0)
210 /* Check for files too large to mmap. */
211 /* XXX is this really possible? */
212 if (sst.st_size > SIZE_T_MAX) {
213 badfmt("corrupt file");
215 filep = (u_char*)mmap(0, sst.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
217 if (filep == (u_char*)MAP_FAILED)
218 err(1, "mmap failed");
220 /* Read in exec structure. */
221 eh = (Elf_Ehdr *) filep;
226 sh = (Elf_Shdr *)&filep[eh->e_shoff];
228 shstr = (char *)&filep[sh[eh->e_shstrndx].sh_offset];
230 for (i = 0; i < eh->e_shnum; i++) {
231 if (strcmp (shstr + sh[i].sh_name, ".strtab") == 0) {
232 symstroff = sh[i].sh_offset;
233 symstrsize = sh[i].sh_size;
235 else if (strcmp (shstr + sh[i].sh_name, ".symtab") == 0) {
236 symoff = sh[i].sh_offset;
237 symsize = sh[i].sh_size;
239 else if (strcmp (shstr + sh[i].sh_name, ".text") == 0) {
240 kernvma = sh[i].sh_addr;
241 kernoffs = sh[i].sh_offset;
245 strtab = (char *)&filep[symstroff];
247 data.data = (u_char *)&nbuf;
248 data.size = sizeof(NLIST);
250 /* Read each symbol and enter it into the database. */
251 for (i = 0; symsize > 0; i++, symsize -= sizeof(Elf_Sym)) {
253 sbuf = (Elf_Sym *)&filep[symoff + i * sizeof(*sbuf)];
257 nbuf.n_value = sbuf->st_value;
259 /*XXX type conversion is pretty rude... */
260 switch (ELF_ST_TYPE(sbuf->st_info)) {
262 nbuf.n_type = N_UNDF;
265 nbuf.n_type = N_TEXT;
268 nbuf.n_type = N_DATA;
271 if (ELF_ST_BIND(sbuf->st_info) == STB_LOCAL)
274 key.data = (u_char *)(strtab + sbuf->st_name);
275 key.size = strlen((char *)key.data);
276 if (db->put(db, &key, &data, 0))
277 err(1, "record enter");
279 /* also put in name prefixed with _ */
281 strcpy(buf + 1, strtab + sbuf->st_name);
282 key.data = (u_char *)buf;
283 key.size = strlen((char *)key.data);
284 if (db->put(db, &key, &data, 0))
285 err(1, "record enter");
287 /* Special processing for "_version" (depends on above) */
288 if (strcmp((char *)key.data, VRS_SYM) == 0) {
291 key.data = (u_char *)VRS_KEY;
292 key.size = sizeof(VRS_KEY) - 1;
293 /* Find the version string, relative to its section */
294 data.data = strdup(&filep[nbuf.n_value -
295 sh[sbuf->st_shndx].sh_addr +
296 sh[sbuf->st_shndx].sh_offset]);
297 /* assumes newline terminates version. */
298 if ((vp = strchr(data.data, '\n')) != NULL)
300 data.size = strlen((char *)data.data);
302 if (db->put(db, &key, &data, 0))
303 err(1, "record enter");
305 /* Restore to original values. */
306 data.data = (u_char *)&nbuf;
307 data.size = sizeof(NLIST);
310 munmap(filep, sst.st_size);
316 static struct knlist_handlers {
317 int (*fn) __P((char *name, DB *db));
328 create_knlist(name, db)
334 for (i = 0; i < sizeof(nlist_fn)/sizeof(nlist_fn[0]); i++) {
335 n = (nlist_fn[i].fn)(name, db);