]> git.saurik.com Git - apple/libc.git/blame - gen/nlist.c
Libc-262.tar.gz
[apple/libc.git] / gen / nlist.c
CommitLineData
e9ce8d39
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 *
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
27 * are met:
28 * 1. Redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer.
30 * 2. Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in the
32 * documentation and/or other materials provided with the distribution.
33 * 3. All advertising materials mentioning features or use of this software
34 * must display the following acknowledgement:
35 * This product includes software developed by the University of
36 * California, Berkeley and its contributors.
37 * 4. Neither the name of the University nor the names of its contributors
38 * may be used to endorse or promote products derived from this software
39 * without specific prior written permission.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 */
53
54
55#include <stdlib.h>
56#include <sys/types.h>
57#include <sys/file.h>
58#include <fcntl.h>
59#include <string.h>
60#include <unistd.h>
61
62/* Stuff lifted from <a.out.h> and <sys/exec.h> since they are gone */
63/*
64 * Header prepended to each a.out file.
65 */
66struct exec {
67unsigned short a_machtype; /* machine type */
68unsigned short a_magic; /* magic number */
69unsigned long a_text; /* size of text segment */
70unsigned long a_data; /* size of initialized data */
71unsigned long a_bss; /* size of uninitialized data */
72unsigned long a_syms; /* size of symbol table */
73unsigned long a_entry; /* entry point */
74unsigned long a_trsize; /* size of text relocation */
75unsigned long a_drsize; /* size of data relocation */
76};
77
78#define OMAGIC 0407 /* old impure format */
79#define NMAGIC 0410 /* read-only text */
80#define ZMAGIC 0413 /* demand load format */
81
82#define N_BADMAG(x) \
83 (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC)
84#define N_TXTOFF(x) \
85 ((x).a_magic==ZMAGIC ? 0 : sizeof (struct exec))
86#define N_SYMOFF(x) \
87 (N_TXTOFF(x) + (x).a_text+(x).a_data + (x).a_trsize+(x).a_drsize)
88
89#include <mach/mach.h>
90#include <mach-o/nlist.h>
91#include <stdio.h>
92#include <mach-o/loader.h>
93#include <mach-o/fat.h>
94
95/*
96 * CPUSUBTYPE_SUPPORT should be changed to non-zero once the
97 * cpusubtype_* routines are available in libc.
98 */
99#define CPUSUBTYPE_SUPPORT 0
100
101/*
102 * nlist - retreive attributes from name list (string table version)
103 */
104
105int
106nlist(name, list)
107 const char *name;
108 struct nlist *list;
109{
110 int fd, n;
111
112 fd = open(name, O_RDONLY, 0);
113 if (fd < 0)
114 return (-1);
115 n = __fdnlist(fd, list);
116 (void)close(fd);
117 return (n);
118}
119
120/* Note: __fdnlist() is called from kvm_nlist in libkvm's kvm.c */
121
122int
123__fdnlist(fd, list)
124 int fd;
125 struct nlist *list;
126{
127 register struct nlist *p, *q;
128 register char *s1, *s2;
129 register n, m;
130 int maxlen, nreq;
131 off_t sa; /* symbol address */
132 off_t ss; /* start of strings */
133 struct exec buf;
134 struct nlist space[BUFSIZ/sizeof (struct nlist)];
135 unsigned arch_offset = 0;
136
137 maxlen = 0;
138 for (q = list, nreq = 0; q->n_un.n_name && q->n_un.n_name[0]; q++, nreq++) {
139 q->n_type = 0;
140 q->n_value = 0;
141 q->n_desc = 0;
142 q->n_sect = 0;
143 n = strlen(q->n_un.n_name);
144 if (n > maxlen)
145 maxlen = n;
146 }
147 if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf) ||
148 (N_BADMAG(buf) && *((long *)&buf) != MH_MAGIC &&
149 NXSwapBigLongToHost(*((long *)&buf)) != FAT_MAGIC)) {
150 return (-1);
151 }
152
153 /* Deal with fat file if necessary */
154 if (NXSwapBigLongToHost(*((long *)&buf)) == FAT_MAGIC) {
155 struct host_basic_info hbi;
156 struct fat_header fh;
157 struct fat_arch *fat_archs, *fap;
158 unsigned i;
5b2abdfb 159 host_t host;
e9ce8d39
A
160
161 /* Get our host info */
5b2abdfb 162 host = mach_host_self();
e9ce8d39 163 i = HOST_BASIC_INFO_COUNT;
5b2abdfb 164 if (host_info(host, HOST_BASIC_INFO,
e9ce8d39
A
165 (host_info_t)(&hbi), &i) != KERN_SUCCESS) {
166 return (-1);
167 }
5b2abdfb 168 mach_port_deallocate(mach_task_self(), host);
e9ce8d39
A
169
170 /* Read in the fat header */
171 lseek(fd, 0, SEEK_SET);
172 if (read(fd, (char *)&fh, sizeof(fh)) != sizeof(fh)) {
173 return (-1);
174 }
175
176 /* Convert fat_narchs to host byte order */
177 fh.nfat_arch = NXSwapBigLongToHost(fh.nfat_arch);
178
179 /* Read in the fat archs */
180 fat_archs = (struct fat_arch *)malloc(fh.nfat_arch *
181 sizeof(struct fat_arch));
182 if (fat_archs == NULL) {
183 return (-1);
184 }
185 if (read(fd, (char *)fat_archs,
186 sizeof(struct fat_arch) * fh.nfat_arch) !=
187 sizeof(struct fat_arch) * fh.nfat_arch) {
188 free(fat_archs);
189 return (-1);
190 }
191
192 /*
193 * Convert archs to host byte ordering (a constraint of
194 * cpusubtype_getbestarch()
195 */
196 for (i = 0; i < fh.nfat_arch; i++) {
197 fat_archs[i].cputype =
198 NXSwapBigLongToHost(fat_archs[i].cputype);
199 fat_archs[i].cpusubtype =
200 NXSwapBigLongToHost(fat_archs[i].cpusubtype);
201 fat_archs[i].offset =
202 NXSwapBigLongToHost(fat_archs[i].offset);
203 fat_archs[i].size =
204 NXSwapBigLongToHost(fat_archs[i].size);
205 fat_archs[i].align =
206 NXSwapBigLongToHost(fat_archs[i].align);
207 }
208
209#if CPUSUBTYPE_SUPPORT
210 fap = cpusubtype_getbestarch(hbi.cpu_type, hbi.cpu_subtype,
211 fat_archs, fh.nfat_arch);
212#else CPUSUBTYPE_SUPPORT
213#warning Use the cpusubtype functions!!!
214 fap = NULL;
215 for (i = 0; i < fh.nfat_arch; i++) {
216 if (fat_archs[i].cputype == hbi.cpu_type) {
217 fap = &fat_archs[i];
218 break;
219 }
220 }
221#endif CPUSUBTYPE_SUPPORT
222 if (!fap) {
223 free(fat_archs);
224 return (-1);
225 }
226 arch_offset = fap->offset;
227 free(fat_archs);
228
229 /* Read in the beginning of the architecture-specific file */
230 lseek(fd, arch_offset, SEEK_SET);
231 if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf)) {
232 return (-1);
233 }
234 }
235
236 if (*((long *)&buf) == MH_MAGIC) {
237 struct mach_header mh;
238 struct load_command *load_commands, *lcp;
239 struct symtab_command *stp;
240 long i;
241
242 lseek(fd, arch_offset, SEEK_SET);
243 if (read(fd, (char *)&mh, sizeof(mh)) != sizeof(mh)) {
244 return (-1);
245 }
246 load_commands = (struct load_command *)malloc(mh.sizeofcmds);
247 if (load_commands == NULL) {
248 return (-1);
249 }
250 if (read(fd, (char *)load_commands, mh.sizeofcmds) !=
251 mh.sizeofcmds) {
252 free(load_commands);
253 return (-1);
254 }
255 stp = NULL;
256 lcp = load_commands;
257 for (i = 0; i < mh.ncmds; i++) {
258 if (lcp->cmdsize % sizeof(long) != 0 ||
259 lcp->cmdsize <= 0 ||
260 (char *)lcp + lcp->cmdsize >
261 (char *)load_commands + mh.sizeofcmds) {
262 free(load_commands);
263 return (-1);
264 }
265 if (lcp->cmd == LC_SYMTAB) {
266 if (lcp->cmdsize !=
267 sizeof(struct symtab_command)) {
268 free(load_commands);
269 return (-1);
270 }
271 stp = (struct symtab_command *)lcp;
272 break;
273 }
274 lcp = (struct load_command *)
275 ((char *)lcp + lcp->cmdsize);
276 }
277 if (stp == NULL) {
278 free(load_commands);
279 return (-1);
280 }
281 sa = stp->symoff + arch_offset;
282 ss = stp->stroff + arch_offset;
283 n = stp->nsyms * sizeof(struct nlist);
284 free(load_commands);
285 }
286 else {
287 sa = N_SYMOFF(buf) + arch_offset;
288 ss = sa + buf.a_syms + arch_offset;
289 n = buf.a_syms;
290 }
291
292 lseek(fd, sa, SEEK_SET);
293 while (n) {
294 long savpos;
295
296 m = sizeof (space);
297 if (n < m)
298 m = n;
299 if (read(fd, (char *)space, m) != m)
300 break;
301 n -= m;
302 savpos = lseek(fd, 0, SEEK_CUR);
303 for (q = space; (m -= sizeof(struct nlist)) >= 0; q++) {
304 char nambuf[BUFSIZ];
305
306 if (q->n_un.n_strx == 0 || q->n_type & N_STAB)
307 continue;
308 lseek(fd, ss+q->n_un.n_strx, SEEK_SET);
309 read(fd, nambuf, maxlen+1);
310 for (p = list; p->n_un.n_name && p->n_un.n_name[0]; p++) {
311 s1 = p->n_un.n_name;
312 s2 = nambuf;
313 while (*s1) {
314 if (*s1++ != *s2++)
315 goto cont;
316 }
317 if (*s2)
318 goto cont;
319 p->n_value = q->n_value;
320 p->n_type = q->n_type;
321 p->n_desc = q->n_desc;
322 p->n_sect = q->n_sect;
323 if (--nreq == 0)
324 return (nreq);
325 break;
326 cont: ;
327 }
328 }
329 lseek(fd, savpos, SEEK_SET);
330 }
331 return (nreq);
332}