nlist_ecoff.c revision 1.18 1 1.18 he /* $NetBSD: nlist_ecoff.c,v 1.18 2009/08/21 08:42:02 he 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.18 he __RCSID("$NetBSD: nlist_ecoff.c,v 1.18 2009/08/21 08:42:02 he 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.11 simonb #define BAD do { rv = -1; goto out; } while (/*CONSTCOND*/0)
63 1.11 simonb #define BADUNMAP do { rv = -1; goto unmap; } while (/*CONSTCOND*/0)
64 1.1 cgd
65 1.1 cgd int
66 1.1 cgd __fdnlist_ecoff(fd, list)
67 1.6 perry int fd;
68 1.6 perry struct nlist *list;
69 1.1 cgd {
70 1.1 cgd struct nlist *p;
71 1.1 cgd struct ecoff_exechdr *exechdrp;
72 1.1 cgd struct ecoff_symhdr *symhdrp;
73 1.1 cgd struct ecoff_extsym *esyms;
74 1.1 cgd struct stat st;
75 1.1 cgd char *mappedfile;
76 1.1 cgd size_t mappedsize;
77 1.1 cgd u_long symhdroff, extstroff;
78 1.1 cgd u_int symhdrsize;
79 1.1 cgd int rv, nent;
80 1.1 cgd long i, nesyms;
81 1.9 lukem
82 1.9 lukem _DIAGASSERT(fd != -1);
83 1.9 lukem _DIAGASSERT(list != NULL);
84 1.1 cgd
85 1.3 cgd rv = -1;
86 1.1 cgd
87 1.3 cgd /*
88 1.3 cgd * If we can't fstat() the file, something bad is going on.
89 1.3 cgd */
90 1.1 cgd if (fstat(fd, &st) < 0)
91 1.1 cgd BAD;
92 1.3 cgd
93 1.3 cgd /*
94 1.3 cgd * Map the file in its entirety.
95 1.3 cgd */
96 1.17 lukem if ((uintmax_t)st.st_size > (uintmax_t)SIZE_T_MAX) {
97 1.1 cgd errno = EFBIG;
98 1.1 cgd BAD;
99 1.1 cgd }
100 1.1 cgd mappedsize = st.st_size;
101 1.8 thorpej mappedfile = mmap(NULL, mappedsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
102 1.5 mrg fd, 0);
103 1.1 cgd if (mappedfile == (char *)-1)
104 1.1 cgd BAD;
105 1.1 cgd
106 1.3 cgd /*
107 1.3 cgd * Make sure we can access the executable's header
108 1.3 cgd * directly, and make sure the recognize the executable
109 1.3 cgd * as an ECOFF binary.
110 1.3 cgd */
111 1.1 cgd if (check(0, sizeof *exechdrp))
112 1.1 cgd BADUNMAP;
113 1.1 cgd exechdrp = (struct ecoff_exechdr *)&mappedfile[0];
114 1.1 cgd
115 1.1 cgd if (ECOFF_BADMAG(exechdrp))
116 1.1 cgd BADUNMAP;
117 1.1 cgd
118 1.3 cgd /*
119 1.3 cgd * Find the symbol list.
120 1.3 cgd */
121 1.1 cgd symhdroff = exechdrp->f.f_symptr;
122 1.1 cgd symhdrsize = exechdrp->f.f_nsyms;
123 1.1 cgd
124 1.15 he if ((symhdroff + sizeof *symhdrp) > mappedsize ||
125 1.1 cgd sizeof *symhdrp != symhdrsize)
126 1.1 cgd BADUNMAP;
127 1.1 cgd symhdrp = (struct ecoff_symhdr *)&mappedfile[symhdroff];
128 1.1 cgd
129 1.1 cgd nesyms = symhdrp->esymMax;
130 1.1 cgd if (check(symhdrp->cbExtOffset, nesyms * sizeof *esyms))
131 1.1 cgd BADUNMAP;
132 1.1 cgd esyms = (struct ecoff_extsym *)&mappedfile[symhdrp->cbExtOffset];
133 1.1 cgd extstroff = symhdrp->cbSsExtOffset;
134 1.1 cgd
135 1.1 cgd /*
136 1.3 cgd * Clean out any left-over information for all valid entries.
137 1.3 cgd * Type and value are defined to be 0 if not found; historical
138 1.1 cgd * versions cleared other and desc as well.
139 1.1 cgd *
140 1.3 cgd * XXX Clearing anything other than n_type and n_value violates
141 1.1 cgd * the semantics given in the man page.
142 1.1 cgd */
143 1.1 cgd nent = 0;
144 1.1 cgd for (p = list; !ISLAST(p); ++p) {
145 1.1 cgd p->n_type = 0;
146 1.1 cgd p->n_other = 0;
147 1.1 cgd p->n_desc = 0;
148 1.1 cgd p->n_value = 0;
149 1.1 cgd ++nent;
150 1.1 cgd }
151 1.1 cgd
152 1.1 cgd for (i = 0; i < nesyms; i++) {
153 1.1 cgd for (p = list; !ISLAST(p); p++) {
154 1.18 he const char *nlistname;
155 1.1 cgd char *symtabname;
156 1.1 cgd
157 1.1 cgd /* This may be incorrect */
158 1.18 he nlistname = N_NAME(p);
159 1.1 cgd if (*nlistname == '_')
160 1.1 cgd nlistname++;
161 1.1 cgd
162 1.1 cgd symtabname =
163 1.1 cgd &mappedfile[extstroff + esyms[i].es_strindex];
164 1.1 cgd
165 1.1 cgd if (!strcmp(symtabname, nlistname)) {
166 1.3 cgd /*
167 1.3 cgd * Translate (roughly) from ECOFF to nlist
168 1.3 cgd */
169 1.1 cgd p->n_value = esyms[i].es_value;
170 1.1 cgd p->n_type = N_EXT; /* XXX */
171 1.1 cgd p->n_desc = 0; /* XXX */
172 1.1 cgd p->n_other = 0; /* XXX */
173 1.3 cgd
174 1.1 cgd if (--nent <= 0)
175 1.3 cgd goto done;
176 1.3 cgd break; /* into next run of outer loop */
177 1.1 cgd }
178 1.1 cgd }
179 1.1 cgd }
180 1.3 cgd
181 1.3 cgd done:
182 1.1 cgd rv = nent;
183 1.1 cgd unmap:
184 1.1 cgd munmap(mappedfile, mappedsize);
185 1.1 cgd out:
186 1.1 cgd return (rv);
187 1.1 cgd }
188 1.1 cgd
189 1.1 cgd #endif /* NLIST_ECOFF */
190