nlist_elf32.c revision 1.1 1 /* $NetBSD: nlist_elf32.c,v 1.1 1996/09/27 22:23:06 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #if defined(LIBC_SCCS) && !defined(lint)
38 #if 0
39 static char sccsid[] = "@(#)nlist.c 8.1 (Berkeley) 6/4/93";
40 #else
41 static char rcsid[] = "$NetBSD: nlist_elf32.c,v 1.1 1996/09/27 22:23:06 cgd Exp $";
42 #endif
43 #endif /* LIBC_SCCS and not lint */
44
45 /* If not included by nlist_elf64.c, ELFSIZE won't be defined. */
46 #ifndef ELFSIZE
47 #define ELFSIZE 32
48 #endif
49
50 #include <sys/param.h>
51 #include <sys/mman.h>
52 #include <sys/stat.h>
53 #include <sys/file.h>
54
55 #include <errno.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <unistd.h>
59 #include <a.out.h> /* for 'struct nlist' declaration */
60
61 #include "nlist_private.h"
62 #if defined(NLIST_ELF32) || defined(NLIST_ELF64)
63 #include <sys/exec_elf.h>
64 #endif
65
66 #if (defined(NLIST_ELF32) && (ELFSIZE == 32)) || \
67 (defined(NLIST_ELF64) && (ELFSIZE == 64))
68
69 #define CONCAT(x,y) __CONCAT(x,y)
70 #define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
71 #define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
72 #define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE))
73 #define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
74
75 int
76 ELFNAMEEND(__fdnlist_is)(fd)
77 int fd;
78 {
79 Elf_Ehdr ehdr;
80
81 if (lseek(fd, (off_t)0, SEEK_SET) == -1 ||
82 read(fd, &ehdr, sizeof(Elf_Ehdr)) != sizeof(Elf_Ehdr))
83 return (-1);
84
85 if (bcmp(ehdr.e_ident, Elf_e_ident, Elf_e_siz))
86 return (-1);
87
88 switch (ehdr.e_machine) {
89 ELFDEFNNAME(MACHDEP_ID_CASES)
90
91 default:
92 return (-1);
93 }
94
95 return (0);
96 }
97
98 int
99 ELFNAMEEND(__fdnlist)(fd, list)
100 register int fd;
101 register struct nlist *list;
102 {
103 register struct nlist *p;
104 register caddr_t strtab;
105 #if (ELFSIZE == 32)
106 register Elf32_Word symsize, symstrsize;
107 register Elf32_Off symoff = 0, symstroff;
108 #elif (ELFSIZE == 64)
109 register Elf64_Word symsize, symstrsize;
110 register Elf64_Off symoff = 0, symstroff;
111 #endif
112 register long nent, cc, i;
113 Elf_Sym sbuf[1024];
114 Elf_Sym *s;
115 Elf_Ehdr ehdr;
116 Elf_Shdr *shdr = NULL;
117 Elf_Word shdr_size;
118 struct stat st;
119
120 /* Make sure obj is OK */
121 if (lseek(fd, (off_t)0, SEEK_SET) == -1 ||
122 read(fd, &ehdr, sizeof(Elf_Ehdr)) != sizeof(Elf_Ehdr) ||
123 fstat(fd, &st) < 0)
124 return (-1);
125
126 /* calculate section header table size */
127 shdr_size = ehdr.e_shentsize * ehdr.e_shnum;
128
129 /* Make sure it's not too big to mmap */
130 if (shdr_size > SIZE_T_MAX) {
131 errno = EFBIG;
132 return (-1);
133 }
134
135 /* mmap section header table */
136 shdr = (Elf_Shdr *)mmap(NULL, (size_t)shdr_size,
137 PROT_READ, 0, fd, ehdr.e_shoff);
138 if (shdr == (Elf_Shdr *)-1)
139 return (-1);
140
141 /*
142 * Find the symbol table entry and it's corresponding
143 * string table entry. Version 1.1 of the ABI states
144 * that there is only one symbol table but that this
145 * could change in the future.
146 */
147 for (i = 0; i < ehdr.e_shnum; i++) {
148 if (shdr[i].sh_type == Elf_sht_symtab) {
149 symoff = shdr[i].sh_offset;
150 symsize = shdr[i].sh_size;
151 symstroff = shdr[shdr[i].sh_link].sh_offset;
152 symstrsize = shdr[shdr[i].sh_link].sh_size;
153 break;
154 }
155 }
156
157 /* Flush the section header table */
158 munmap((caddr_t)shdr, shdr_size);
159
160 /* Check for files too large to mmap. */
161 /* XXX is this really possible? */
162 if (symstrsize > SIZE_T_MAX) {
163 errno = EFBIG;
164 return (-1);
165 }
166 /*
167 * Map string table into our address space. This gives us
168 * an easy way to randomly access all the strings, without
169 * making the memory allocation permanent as with malloc/free
170 * (i.e., munmap will return it to the system).
171 */
172 strtab = mmap(NULL, (size_t)symstrsize, PROT_READ, 0, fd, symstroff);
173 if (strtab == (char *)-1)
174 return (-1);
175 /*
176 * clean out any left-over information for all valid entries.
177 * Type and value defined to be 0 if not found; historical
178 * versions cleared other and desc as well. Also figure out
179 * the largest string length so don't read any more of the
180 * string table than we have to.
181 *
182 * XXX clearing anything other than n_type and n_value violates
183 * the semantics given in the man page.
184 */
185 nent = 0;
186 for (p = list; !ISLAST(p); ++p) {
187 p->n_type = 0;
188 p->n_other = 0;
189 p->n_desc = 0;
190 p->n_value = 0;
191 ++nent;
192 }
193
194 /* Don't process any further if object is stripped. */
195 /* ELFism - dunno if stripped by looking at header */
196 if (symoff == 0)
197 goto done;
198
199 if (lseek(fd, symoff, SEEK_SET) == -1) {
200 nent = -1;
201 goto done;
202 }
203
204 while (symsize > 0) {
205 cc = MIN(symsize, sizeof(sbuf));
206 if (read(fd, sbuf, cc) != cc)
207 break;
208 symsize -= cc;
209 for (s = sbuf; cc > 0; ++s, cc -= sizeof(*s)) {
210 register int soff = s->st_name;
211
212 if (soff == 0)
213 continue;
214
215 for (p = list; !ISLAST(p); p++) {
216 char *nlistname;
217
218 nlistname = p->n_un.n_name;
219 if (*nlistname == '_')
220 nlistname++;
221
222 if (!strcmp(&strtab[soff], nlistname)) {
223 p->n_value = s->st_value;
224
225 /* XXX - type conversion */
226 /* is pretty rude. */
227 switch(ELF_SYM_TYPE(s->st_info)) {
228 case Elf_estt_notype:
229 p->n_type = N_UNDF;
230 break;
231 case Elf_estt_object:
232 p->n_type = N_DATA;
233 break;
234 case Elf_estt_func:
235 p->n_type = N_TEXT;
236 break;
237 case Elf_estt_file:
238 p->n_type = N_FN;
239 break;
240 }
241 if (ELF_SYM_BIND(s->st_info) !=
242 Elf_estb_local)
243 p->n_type |= N_EXT;
244 p->n_desc = 0;
245 p->n_other = 0;
246 if (--nent <= 0)
247 break;
248 }
249 }
250 }
251 }
252 done:
253 munmap(strtab, symstrsize);
254
255 return (nent);
256 }
257
258 #endif
259