nlist_ecoff.c revision 1.19 1 1.19 christos /* $NetBSD: nlist_ecoff.c,v 1.19 2012/03/18 14:34:28 christos Exp $ */
2 1.1 cgd
3 1.1 cgd /*
4 1.13 cgd * Copyright (c) 1996 Christopher G. Demetriou
5 1.13 cgd * All rights reserved.
6 1.13 cgd *
7 1.1 cgd * Redistribution and use in source and binary forms, with or without
8 1.1 cgd * modification, are permitted provided that the following conditions
9 1.1 cgd * are met:
10 1.1 cgd * 1. Redistributions of source code must retain the above copyright
11 1.1 cgd * notice, this list of conditions and the following disclaimer.
12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 cgd * notice, this list of conditions and the following disclaimer in the
14 1.1 cgd * documentation and/or other materials provided with the distribution.
15 1.1 cgd * 3. All advertising materials mentioning features or use of this software
16 1.1 cgd * must display the following acknowledgement:
17 1.13 cgd * This product includes software developed for the
18 1.14 salo * NetBSD Project. See http://www.NetBSD.org/ for
19 1.13 cgd * information about NetBSD.
20 1.3 cgd * 4. The name of the author may not be used to endorse or promote products
21 1.13 cgd * derived from this software without specific prior written permission.
22 1.13 cgd *
23 1.3 cgd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 1.3 cgd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 1.3 cgd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 1.3 cgd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 1.3 cgd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 1.3 cgd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 1.3 cgd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 1.3 cgd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 1.3 cgd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 1.3 cgd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 1.13 cgd *
34 1.13 cgd * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
35 1.1 cgd */
36 1.1 cgd
37 1.4 christos #include <sys/cdefs.h>
38 1.1 cgd #if defined(LIBC_SCCS) && !defined(lint)
39 1.19 christos __RCSID("$NetBSD: nlist_ecoff.c,v 1.19 2012/03/18 14:34:28 christos Exp $");
40 1.1 cgd #endif /* LIBC_SCCS and not lint */
41 1.1 cgd
42 1.7 kleink #include "namespace.h"
43 1.1 cgd #include <sys/param.h>
44 1.1 cgd #include <sys/mman.h>
45 1.1 cgd #include <sys/stat.h>
46 1.1 cgd #include <sys/file.h>
47 1.1 cgd
48 1.9 lukem #include <assert.h>
49 1.1 cgd #include <errno.h>
50 1.1 cgd #include <stdio.h>
51 1.1 cgd #include <string.h>
52 1.1 cgd #include <unistd.h>
53 1.18 he #include <nlist.h>
54 1.1 cgd
55 1.1 cgd #include "nlist_private.h"
56 1.1 cgd #ifdef NLIST_ECOFF
57 1.1 cgd #include <sys/exec_ecoff.h>
58 1.1 cgd #endif
59 1.1 cgd
60 1.1 cgd #ifdef NLIST_ECOFF
61 1.1 cgd #define check(off, size) ((off < 0) || (off + size > mappedsize))
62 1.1 cgd
63 1.1 cgd int
64 1.1 cgd __fdnlist_ecoff(fd, list)
65 1.6 perry int fd;
66 1.6 perry struct nlist *list;
67 1.1 cgd {
68 1.1 cgd struct nlist *p;
69 1.1 cgd struct ecoff_exechdr *exechdrp;
70 1.1 cgd struct ecoff_symhdr *symhdrp;
71 1.1 cgd struct ecoff_extsym *esyms;
72 1.1 cgd struct stat st;
73 1.19 christos void *mappedfile;
74 1.1 cgd size_t mappedsize;
75 1.1 cgd u_long symhdroff, extstroff;
76 1.1 cgd u_int symhdrsize;
77 1.1 cgd int rv, nent;
78 1.1 cgd long i, nesyms;
79 1.9 lukem
80 1.9 lukem _DIAGASSERT(fd != -1);
81 1.9 lukem _DIAGASSERT(list != NULL);
82 1.1 cgd
83 1.3 cgd rv = -1;
84 1.1 cgd
85 1.3 cgd /*
86 1.3 cgd * If we can't fstat() the file, something bad is going on.
87 1.3 cgd */
88 1.1 cgd if (fstat(fd, &st) < 0)
89 1.19 christos goto out;
90 1.3 cgd
91 1.3 cgd /*
92 1.3 cgd * Map the file in its entirety.
93 1.3 cgd */
94 1.17 lukem if ((uintmax_t)st.st_size > (uintmax_t)SIZE_T_MAX) {
95 1.1 cgd errno = EFBIG;
96 1.19 christos goto out;
97 1.1 cgd }
98 1.19 christos mappedsize = (size_t)st.st_size;
99 1.8 thorpej mappedfile = mmap(NULL, mappedsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
100 1.5 mrg fd, 0);
101 1.19 christos if (mappedfile == MAP_FAILED)
102 1.19 christos goto out;
103 1.1 cgd
104 1.3 cgd /*
105 1.3 cgd * Make sure we can access the executable's header
106 1.3 cgd * directly, and make sure the recognize the executable
107 1.3 cgd * as an ECOFF binary.
108 1.3 cgd */
109 1.1 cgd if (check(0, sizeof *exechdrp))
110 1.19 christos goto unmap;
111 1.19 christos exechdrp = mappedfile;
112 1.1 cgd
113 1.1 cgd if (ECOFF_BADMAG(exechdrp))
114 1.19 christos goto unmap;
115 1.1 cgd
116 1.3 cgd /*
117 1.3 cgd * Find the symbol list.
118 1.3 cgd */
119 1.1 cgd symhdroff = exechdrp->f.f_symptr;
120 1.1 cgd symhdrsize = exechdrp->f.f_nsyms;
121 1.1 cgd
122 1.15 he if ((symhdroff + sizeof *symhdrp) > mappedsize ||
123 1.1 cgd sizeof *symhdrp != symhdrsize)
124 1.19 christos goto unmap;
125 1.19 christos symhdrp = (void *)((char *)mappedfile + symhdroff);
126 1.1 cgd
127 1.1 cgd nesyms = symhdrp->esymMax;
128 1.1 cgd if (check(symhdrp->cbExtOffset, nesyms * sizeof *esyms))
129 1.19 christos goto unmap;
130 1.19 christos esyms = (void *)((char *)mappedfile + symhdrp->cbExtOffset);
131 1.1 cgd extstroff = symhdrp->cbSsExtOffset;
132 1.1 cgd
133 1.1 cgd /*
134 1.3 cgd * Clean out any left-over information for all valid entries.
135 1.3 cgd * Type and value are defined to be 0 if not found; historical
136 1.1 cgd * versions cleared other and desc as well.
137 1.1 cgd *
138 1.3 cgd * XXX Clearing anything other than n_type and n_value violates
139 1.1 cgd * the semantics given in the man page.
140 1.1 cgd */
141 1.1 cgd nent = 0;
142 1.1 cgd for (p = list; !ISLAST(p); ++p) {
143 1.1 cgd p->n_type = 0;
144 1.1 cgd p->n_other = 0;
145 1.1 cgd p->n_desc = 0;
146 1.1 cgd p->n_value = 0;
147 1.1 cgd ++nent;
148 1.1 cgd }
149 1.1 cgd
150 1.1 cgd for (i = 0; i < nesyms; i++) {
151 1.1 cgd for (p = list; !ISLAST(p); p++) {
152 1.18 he const char *nlistname;
153 1.1 cgd char *symtabname;
154 1.1 cgd
155 1.1 cgd /* This may be incorrect */
156 1.18 he nlistname = N_NAME(p);
157 1.1 cgd if (*nlistname == '_')
158 1.1 cgd nlistname++;
159 1.1 cgd
160 1.1 cgd symtabname =
161 1.1 cgd &mappedfile[extstroff + esyms[i].es_strindex];
162 1.1 cgd
163 1.1 cgd if (!strcmp(symtabname, nlistname)) {
164 1.3 cgd /*
165 1.3 cgd * Translate (roughly) from ECOFF to nlist
166 1.3 cgd */
167 1.1 cgd p->n_value = esyms[i].es_value;
168 1.1 cgd p->n_type = N_EXT; /* XXX */
169 1.1 cgd p->n_desc = 0; /* XXX */
170 1.1 cgd p->n_other = 0; /* XXX */
171 1.3 cgd
172 1.1 cgd if (--nent <= 0)
173 1.3 cgd goto done;
174 1.3 cgd break; /* into next run of outer loop */
175 1.1 cgd }
176 1.1 cgd }
177 1.1 cgd }
178 1.3 cgd
179 1.3 cgd done:
180 1.1 cgd rv = nent;
181 1.1 cgd unmap:
182 1.1 cgd munmap(mappedfile, mappedsize);
183 1.1 cgd out:
184 1.19 christos return rv;
185 1.1 cgd }
186 1.1 cgd
187 1.1 cgd #endif /* NLIST_ECOFF */
188