]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/kvm_mkdb/nlist.c
Don't chain makes with &&; apparently this is evil for parallelism.
[FreeBSD/FreeBSD.git] / usr.sbin / kvm_mkdb / nlist.c
1 /*-
2  * Copyright (c) 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
20  *
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
31  * SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 #if 0
36 static char sccsid[] = "@(#)from: nlist.c       8.1 (Berkeley) 6/6/93";
37 #endif
38 static const char rcsid[] =
39         "$Id: nlist.c,v 1.8 1997/09/24 06:44:10 charnier Exp $";
40 #endif /* not lint */
41
42 #include <sys/param.h>
43 #include <sys/mman.h>
44 #include <sys/stat.h>
45
46 #include <vm/vm.h>
47 #include <vm/vm_param.h>
48
49 #include <a.out.h>
50 #include <db.h>
51 #include <err.h>
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <kvm.h>
55 #include <limits.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <unistd.h>
60
61 #include "extern.h"
62
63 #ifdef DO_ELF
64 #include <elf.h>
65 #endif
66
67 typedef struct nlist NLIST;
68 #define _strx   n_un.n_strx
69 #define _name   n_un.n_name
70
71 #define badfmt(str)     errx(1, "%s: %s: %s", kfile, str, strerror(EFTYPE))
72 static char *kfile;
73
74 #if defined(DO_AOUT)
75
76 int
77 __aout_knlist(name, db)
78         char *name;
79         DB *db;
80 {
81         register int nsyms;
82         struct exec *ebuf;
83         NLIST *nbuf;
84         DBT data, key;
85         int fd;
86         char *strtab;
87         u_char *filep;
88         char *vp;
89         struct stat sst;
90         long cur_off, voff;
91
92         kfile = name;
93         if ((fd = open(name, O_RDONLY, 0)) < 0)
94                 err(1, "%s", name);
95
96         fstat(fd,&sst);
97
98         filep = (u_char*)mmap(0, sst.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
99
100         if (filep == (u_char*)MAP_FAILED)
101                 err(1, "mmap failed");
102
103         /* Read in exec structure. */
104         ebuf = (struct exec *) filep;
105
106         /* Check magic number and symbol count. */
107         if (N_BADMAG(*ebuf))
108                 badfmt("bad magic number");
109         if (!ebuf->a_syms)
110                 badfmt("stripped");
111
112         strtab = filep + N_STROFF(*ebuf) + sizeof (int);
113
114         /* Seek to symbol table. */
115         cur_off = N_SYMOFF(*ebuf);
116
117         /* Read each symbol and enter it into the database. */
118         nsyms = ebuf->a_syms / sizeof(struct nlist);
119         while (nsyms--) {
120
121                 nbuf = (NLIST *)(filep + cur_off);
122                 cur_off += sizeof(NLIST);
123
124                 if (!nbuf->_strx || nbuf->n_type&N_STAB)
125                         continue;
126
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");
133
134                 if (1 && strcmp((char *)key.data, VRS_SYM) == 0) {
135 #ifndef KERNTEXTOFF
136 /*
137  * XXX
138  * The FreeBSD bootloader loads the kernel at the a_entry address, meaning
139  * that this is where the kernel starts.  (not at KERNBASE)
140  *
141  * This may be introducing an i386 dependency.
142  */
143 #if defined(__FreeBSD__)
144 #define KERNTEXTOFF ebuf->a_entry
145 #else
146 #define KERNTEXTOFF KERNBASE
147 #endif
148 #endif
149                         /*
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.
154                          */
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);
158                         else
159                                 voff += N_DATOFF(*ebuf) - N_DATADDR(*ebuf);
160
161                         vp = filep + voff;
162
163                         key.data = (u_char *)VRS_KEY;
164                         key.size = sizeof(VRS_KEY) - 1;
165                         data.data = vp;
166                         data.size = strchr(vp, '\n') - vp + 1;
167
168                         if (db->put(db, &key, &data, 0))
169                                 err(1, "record enter");
170
171                         /* Restore to original values. */
172                         data.size = sizeof(NLIST);
173                 }
174         }
175         return(0);
176 }
177
178
179 #endif /* DO_AOUT */
180
181 #ifdef DO_ELF
182
183 int
184 __elf_knlist(name, db)
185         char *name;
186         DB *db;
187 {
188         register caddr_t strtab;
189         register off_t symstroff, symoff;
190         register u_long symsize;
191         register u_long kernvma, kernoffs;
192         register int i;
193         Elf_Sym *sbuf;
194         size_t symstrsize;
195         char *shstr, buf[1024];
196         Elf_Ehdr *eh;
197         Elf_Shdr *sh = NULL;
198         DBT data, key;
199         NLIST nbuf;
200         int fd;
201         u_char *filep;
202         struct stat sst;
203
204         kfile = name;
205         if ((fd = open(name, O_RDONLY, 0)) < 0)
206                 err(1, "%s", name);
207
208         fstat(fd, &sst);
209
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");
214         }
215         filep = (u_char*)mmap(0, sst.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
216
217         if (filep == (u_char*)MAP_FAILED)
218                 err(1, "mmap failed");
219
220         /* Read in exec structure. */
221         eh = (Elf_Ehdr *) filep;
222
223         if (!IS_ELF(*eh))
224                 return(-1);
225
226         sh = (Elf_Shdr *)&filep[eh->e_shoff];
227
228         shstr = (char *)&filep[sh[eh->e_shstrndx].sh_offset];
229
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;
234                 }
235                 else if (strcmp (shstr + sh[i].sh_name, ".symtab") == 0) {
236                         symoff = sh[i].sh_offset;
237                         symsize = sh[i].sh_size;
238                 }
239                 else if (strcmp (shstr + sh[i].sh_name, ".text") == 0) {
240                         kernvma = sh[i].sh_addr;
241                         kernoffs = sh[i].sh_offset;
242                 }
243         }
244
245         strtab = (char *)&filep[symstroff];
246
247         data.data = (u_char *)&nbuf;
248         data.size = sizeof(NLIST);
249
250         /* Read each symbol and enter it into the database. */
251         for (i = 0; symsize > 0; i++, symsize -= sizeof(Elf_Sym)) {
252
253                 sbuf = (Elf_Sym *)&filep[symoff + i * sizeof(*sbuf)];
254                 if (!sbuf->st_name)
255                         continue;
256
257                 nbuf.n_value = sbuf->st_value;
258
259                 /*XXX type conversion is pretty rude... */
260                 switch (ELF_ST_TYPE(sbuf->st_info)) {
261                 case STT_NOTYPE:
262                         nbuf.n_type = N_UNDF;
263                         break;
264                 case STT_FUNC:
265                         nbuf.n_type = N_TEXT;
266                         break;
267                 case STT_OBJECT:
268                         nbuf.n_type = N_DATA;
269                         break;
270                 }
271                 if (ELF_ST_BIND(sbuf->st_info) == STB_LOCAL)
272                         nbuf.n_type = N_EXT;
273
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");
278
279                 /* also put in name prefixed with _ */
280                 *buf = '_';
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");
286
287                 /* Special processing for "_version" (depends on above) */
288                 if (strcmp((char *)key.data, VRS_SYM) == 0) {
289                         char *vp;
290
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)
299                                 *vp = '\0';
300                         data.size = strlen((char *)data.data);
301
302                         if (db->put(db, &key, &data, 0))
303                                 err(1, "record enter");
304
305                         /* Restore to original values. */
306                         data.data = (u_char *)&nbuf;
307                         data.size = sizeof(NLIST);
308                 }
309         }
310         munmap(filep, sst.st_size);
311         (void)close(fd);
312         return(0);
313 }
314 #endif /* DO_ELF */
315
316 static struct knlist_handlers {
317         int     (*fn) __P((char *name, DB *db));
318 } nlist_fn[] = {
319 #ifdef DO_ELF
320         { __elf_knlist },
321 #endif
322 #ifdef DO_AOUT
323         { __aout_knlist },
324 #endif
325 };
326
327 void
328 create_knlist(name, db)
329         char *name;
330         DB *db;
331 {
332         int n, i;
333
334         for (i = 0; i < sizeof(nlist_fn)/sizeof(nlist_fn[0]); i++) {
335                 n = (nlist_fn[i].fn)(name, db);
336                 if (n != -1)
337                         break;
338         }
339 }