1 /* $NetBSD: exec_elf32.c,v 1.13 2003/07/26 20:34:12 salo Exp $ */
4 * Copyright (c) 1997, 1998 Christopher G. Demetriou
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the
18 * NetBSD Project. See http://www.NetBSD.org/ for
19 * information about NetBSD.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
37 #include <sys/cdefs.h>
39 __RCSID("$NetBSD: exec_elf32.c,v 1.13 2003/07/26 20:34:12 salo Exp $");
46 #include <sys/types.h>
57 #if (defined(NLIST_ELF32) && (ELFSIZE == 32)) || \
58 (defined(NLIST_ELF64) && (ELFSIZE == 64))
60 #include <sys/exec_elf.h>
63 struct listelem
*next
;
70 xreadatoff(int fd
, void *buf
, off_t off
, size_t size
, const char *fn
)
74 if (lseek(fd
, off
, SEEK_SET
) != off
) {
78 if ((size_t)(rv
= read(fd
, buf
, size
)) != size
) {
79 fprintf(stderr
, "%s: read error: %s\n", fn
,
80 rv
== -1 ? strerror(errno
) : "short read");
87 xwriteatoff(int fd
, void *buf
, off_t off
, size_t size
, const char *fn
)
91 if (lseek(fd
, off
, SEEK_SET
) != off
) {
95 if ((size_t)(rv
= write(fd
, buf
, size
)) != size
) {
96 fprintf(stderr
, "%s: write error: %s\n", fn
,
97 rv
== -1 ? strerror(errno
) : "short write");
104 xmalloc(size_t size
, const char *fn
, const char *use
)
110 fprintf(stderr
, "%s: out of memory (allocating for %s)\n",
116 xrealloc(void *ptr
, size_t size
, const char *fn
, const char *use
)
120 rv
= realloc(ptr
, size
);
123 fprintf(stderr
, "%s: out of memory (reallocating for %s)\n",
130 ELFNAMEEND(check
)(int fd
, const char *fn
)
136 * Check the header to maek sure it's an ELF file (of the
139 if (fstat(fd
, &sb
) == -1)
141 if (sb
.st_size
< (off_t
)(sizeof eh
))
143 if (read(fd
, &eh
, sizeof eh
) != sizeof eh
)
146 if (memcmp(eh
.e_ident
, ELFMAG
, SELFMAG
) != 0 ||
147 eh
.e_ident
[EI_CLASS
] != ELFCLASS
)
150 switch (eh
.e_machine
) {
151 ELFDEFNNAME(MACHDEP_ID_CASES
)
161 * This function 'hides' (some of) ELF executable file's symbols.
162 * It hides them by renaming them to "_$$hide$$ <filename> <symbolname>".
163 * Symbols in the global keep list, or which are marked as being undefined,
166 * An old version of this code shuffled various tables around, turning
167 * global symbols to be hidden into local symbols. That lost on the
168 * mips, because CALL16 relocs must reference global symbols, and, if
169 * those symbols were being hidden, they were no longer global.
171 * The new renaming behaviour doesn't take global symbols out of the
172 * namespace. However, it's ... unlikely that there will ever be
173 * any collisions in practice because of the new method.
176 ELFNAMEEND(hide
)(int fd
, const char *fn
)
179 Elf_Shdr
*shdrp
= NULL
;
180 int symtabsnum
, strtabsnum
;
181 Elf_Sym
*symtabp
= NULL
;
182 char *strtabp
= NULL
, *nstrtabp
= NULL
;
184 Elf_Off stroff
, maxoff
;
185 const char *weirdreason
;
187 size_t nstrtab_size
, nstrtab_nextoff
, fn_size
;
191 if (xreadatoff(fd
, &ehdr
, 0, sizeof ehdr
, fn
) != sizeof ehdr
)
194 shdrsize
= ehdr
.e_shnum
* ehdr
.e_shentsize
;
195 if ((shdrp
= xmalloc(shdrsize
, fn
, "section header table")) == NULL
)
197 if (xreadatoff(fd
, shdrp
, ehdr
.e_shoff
, shdrsize
, fn
) != shdrsize
)
200 symtabsnum
= strtabsnum
= -1;
204 for (i
= 0; i
< ehdr
.e_shnum
; i
++) {
205 if (shdrp
[i
].sh_offset
> maxoff
) {
206 maxoff
= shdrp
[i
].sh_offset
;
208 switch (shdrp
[i
].sh_type
) {
210 if (!weird
&& symtabsnum
!= -1) {
212 weirdreason
= "multiple symbol tables";
215 strtabsnum
= shdrp
[i
].sh_link
;
216 stroff
= shdrp
[strtabsnum
].sh_offset
;
217 if (!weird
&& strtabsnum
!= (ehdr
.e_shnum
- 1)) {
219 weirdreason
= "string table not last section";
224 if (symtabsnum
== -1)
226 if (!weird
&& strtabsnum
== -1) {
228 weirdreason
= "no string table found";
230 if (!weird
&& stroff
!= maxoff
) {
232 weirdreason
= "string table section not last in file";
235 fprintf(stderr
, "%s: weird executable (%s); unsupported\n", fn
,
241 * load up everything we need
245 if ((symtabp
= xmalloc(shdrp
[symtabsnum
].sh_size
, fn
, "symbol table"))
248 if ((size_t)xreadatoff(fd
, symtabp
, shdrp
[symtabsnum
].sh_offset
,
249 shdrp
[symtabsnum
].sh_size
, fn
) != shdrp
[symtabsnum
].sh_size
)
253 if ((strtabp
= xmalloc(shdrp
[strtabsnum
].sh_size
, fn
, "string table"))
256 if ((size_t)xreadatoff(fd
, strtabp
, shdrp
[strtabsnum
].sh_offset
,
257 shdrp
[strtabsnum
].sh_size
, fn
) != shdrp
[strtabsnum
].sh_size
)
260 nsyms
= shdrp
[symtabsnum
].sh_size
/ shdrp
[symtabsnum
].sh_entsize
;
263 nstrtabp
= xmalloc(nstrtab_size
, fn
, "new string table");
264 if (nstrtabp
== NULL
)
268 fn_size
= strlen(fn
);
270 for (j
= 0; j
< nsyms
; j
++) {
271 Elf_Sym
*sp
= &symtabp
[j
];
272 const char *symname
= strtabp
+ sp
->st_name
;
276 * make sure there's size for the next entry, even if it's
277 * as large as it can be.
279 * "_$$hide$$ <filename> <symname><NUL>" ->
280 * 9 + 3 + sizes of fn and sym name
282 while ((nstrtab_size
- nstrtab_nextoff
) <
283 strlen(symname
) + fn_size
+ 12) {
285 nstrtabp
= xrealloc(nstrtabp
, nstrtab_size
, fn
,
287 if (nstrtabp
== NULL
)
291 sp
->st_name
= nstrtab_nextoff
;
293 /* if it's a keeper or is undefined, don't rename it. */
294 if (in_keep_list(symname
) ||
295 sp
->st_shndx
== SHN_UNDEF
) {
296 newent_len
= sprintf(nstrtabp
+ nstrtab_nextoff
,
299 newent_len
= sprintf(nstrtabp
+ nstrtab_nextoff
,
300 "_$$hide$$ %s %s", fn
, symname
) + 1;
302 nstrtab_nextoff
+= newent_len
;
304 shdrp
[strtabsnum
].sh_size
= nstrtab_nextoff
;
307 * write new tables to the file
309 if (xwriteatoff(fd
, shdrp
, ehdr
.e_shoff
, shdrsize
, fn
) != shdrsize
)
311 if ((size_t)xwriteatoff(fd
, symtabp
, shdrp
[symtabsnum
].sh_offset
,
312 shdrp
[symtabsnum
].sh_size
, fn
) != shdrp
[symtabsnum
].sh_size
)
314 if ((size_t)xwriteatoff(fd
, nstrtabp
, shdrp
[strtabsnum
].sh_offset
,
315 shdrp
[strtabsnum
].sh_size
, fn
) != shdrp
[strtabsnum
].sh_size
)
325 if (nstrtabp
!= NULL
)
334 #endif /* include this size of ELF */