2 * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Christopher G. Demetriou
15 * for the NetBSD Project.
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: exec_elf32.c,v 1.4 1997/08/12 06:07:24 mikel Exp $");
36 static const char rcsid[] =
37 "$FreeBSD: src/usr.sbin/crunch/crunchide/exec_elf32.c,v 1.1.6.2 2002/07/25 09:33:17 ru Exp $";
44 #include <sys/types.h>
55 #if (defined(NLIST_ELF32) && (ELFSIZE == 32)) || \
56 (defined(NLIST_ELF64) && (ELFSIZE == 64))
58 #define __ELF_WORD_SIZE ELFSIZE
60 #include <sys/elf32.h>
62 #include <sys/elf64.h>
64 #include <sys/elf_generic.h>
66 #define CONCAT(x,y) __CONCAT(x,y)
67 #define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
68 #define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
69 #define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE))
70 #define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
73 struct listelem *next;
80 xreadatoff(int fd, void *buf, off_t off, size_t size, const char *fn)
84 if (lseek(fd, off, SEEK_SET) != off) {
88 if ((rv = read(fd, buf, size)) != size) {
89 fprintf(stderr, "%s: read error: %s\n", fn,
90 rv == -1 ? strerror(errno) : "short read");
97 xwriteatoff(int fd, void *buf, off_t off, size_t size, const char *fn)
101 if (lseek(fd, off, SEEK_SET) != off) {
105 if ((rv = write(fd, buf, size)) != size) {
106 fprintf(stderr, "%s: write error: %s\n", fn,
107 rv == -1 ? strerror(errno) : "short write");
114 xmalloc(size_t size, const char *fn, const char *use)
120 fprintf(stderr, "%s: out of memory (allocating for %s)\n",
126 ELFNAMEEND(check)(int fd, const char *fn)
132 * Check the header to maek sure it's an ELF file (of the
135 if (fstat(fd, &sb) == -1)
137 if (sb.st_size < sizeof eh)
139 if (read(fd, &eh, sizeof eh) != sizeof eh)
145 switch (eh.e_machine) {
147 case EM_ALPHA: break;
148 /* ELFDEFNNAME(MACHDEP_ID_CASES) */
158 ELFNAMEEND(hide)(int fd, const char *fn)
161 Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr;
162 Elf_Sym *symtabp = NULL;
163 char *strtabp = NULL;
164 Elf_Word *symfwmap = NULL, *symrvmap = NULL, nsyms, nlocalsyms, ewi;
165 struct listelem *relalist = NULL, *rellist = NULL, *tmpl;
170 if (xreadatoff(fd, &ehdr, 0, sizeof ehdr, fn) != sizeof ehdr)
173 shdrsize = ehdr.e_shnum * ehdr.e_shentsize;
174 if ((shdrp = xmalloc(shdrsize, fn, "section header table")) == NULL)
176 if (xreadatoff(fd, shdrp, ehdr.e_shoff, shdrsize, fn) != shdrsize)
179 symtabshdr = strtabshdr = NULL;
181 for (i = 0; i < ehdr.e_shnum; i++) {
182 switch (shdrp[i].sh_type) {
184 if (symtabshdr != NULL)
186 symtabshdr = &shdrp[i];
187 strtabshdr = &shdrp[shdrp[i].sh_link];
190 tmpl = xmalloc(sizeof *tmpl, fn, "rela list element");
194 tmpl->file = shdrp[i].sh_offset;
195 tmpl->size = shdrp[i].sh_size;
196 tmpl->next = relalist;
200 tmpl = xmalloc(sizeof *tmpl, fn, "rel list element");
204 tmpl->file = shdrp[i].sh_offset;
205 tmpl->size = shdrp[i].sh_size;
206 tmpl->next = rellist;
211 if (symtabshdr == NULL)
213 if (strtabshdr == NULL)
216 fprintf(stderr, "%s: weird executable (unsupported)\n", fn);
221 * load up everything we need
225 if ((symtabp = xmalloc(symtabshdr->sh_size, fn, "symbol table"))
228 if (xreadatoff(fd, symtabp, symtabshdr->sh_offset, symtabshdr->sh_size,
229 fn) != symtabshdr->sh_size)
233 if ((strtabp = xmalloc(strtabshdr->sh_size, fn, "string table"))
236 if (xreadatoff(fd, strtabp, strtabshdr->sh_offset, strtabshdr->sh_size,
237 fn) != strtabshdr->sh_size)
240 /* any rela tables */
241 for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
242 if ((tmpl->mem = xmalloc(tmpl->size, fn, "rela table"))
245 if (xreadatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
251 for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
252 if ((tmpl->mem = xmalloc(tmpl->size, fn, "rel table"))
255 if (xreadatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
260 /* Prepare data structures for symbol movement. */
261 nsyms = symtabshdr->sh_size / symtabshdr->sh_entsize;
262 nlocalsyms = symtabshdr->sh_info;
263 if ((symfwmap = xmalloc(nsyms * sizeof (Elf_Word), fn,
264 "symbol forward mapping table")) == NULL)
266 if ((symrvmap = xmalloc(nsyms * sizeof (Elf_Word), fn,
267 "symbol reverse mapping table")) == NULL)
270 /* init location -> symbol # table */
271 for (ewi = 0; ewi < nsyms; ewi++)
274 /* move symbols, making them local */
275 for (ewi = nlocalsyms; ewi < nsyms; ewi++) {
276 Elf_Sym *sp, symswap;
281 /* if it's on our keep list, don't move it */
282 if (in_keep_list(strtabp + sp->st_name))
285 /* if it's an undefined symbol, keep it */
286 if (sp->st_shndx == SHN_UNDEF)
289 /* adjust the symbol so that it's local */
291 ELF_ST_INFO(STB_LOCAL, sp->st_info);
292 /* (STB_LOCAL << 4) | ELF_SYM_TYPE(sp->st_info); *//* XXX */
295 * move the symbol to its new location
298 /* note that symbols in those locations have been swapped */
299 mapswap = symrvmap[ewi];
300 symrvmap[ewi] = symrvmap[nlocalsyms];
301 symrvmap[nlocalsyms] = mapswap;
303 /* and swap the symbols */
305 *sp = symtabp[nlocalsyms];
306 symtabp[nlocalsyms] = symswap;
308 nlocalsyms++; /* note new local sym */
310 symtabshdr->sh_info = nlocalsyms;
312 /* set up symbol # -> location mapping table */
313 for (ewi = 0; ewi < nsyms; ewi++)
314 symfwmap[symrvmap[ewi]] = ewi;
316 /* any rela tables */
317 for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
318 Elf_Rela *relap = tmpl->mem;
320 for (ewi = 0; ewi < tmpl->size / sizeof(*relap); ewi++) {
322 #if (ELFSIZE == 32) /* XXX */
323 symfwmap[ELF_R_SYM(relap[ewi].r_info)] << 8 |
324 ELF_R_TYPE(relap[ewi].r_info);
325 #elif (ELFSIZE == 64) /* XXX */
326 symfwmap[ELF_R_SYM(relap[ewi].r_info)] << 32 |
327 ELF_R_TYPE(relap[ewi].r_info);
333 for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
334 Elf_Rel *relp = tmpl->mem;
336 for (ewi = 0; ewi < tmpl->size / sizeof *relp; ewi++) {
338 #if (ELFSIZE == 32) /* XXX */
339 symfwmap[ELF_R_SYM(relp[ewi].r_info)] << 8 |
340 ELF_R_TYPE(relp[ewi].r_info);
341 #elif (ELFSIZE == 64) /* XXX */
342 symfwmap[ELF_R_SYM(relp[ewi].r_info)] << 32 |
343 ELF_R_TYPE(relp[ewi].r_info);
349 * write new tables to the file
351 if (xwriteatoff(fd, shdrp, ehdr.e_shoff, shdrsize, fn) != shdrsize)
353 if (xwriteatoff(fd, symtabp, symtabshdr->sh_offset,
354 symtabshdr->sh_size, fn) != symtabshdr->sh_size)
356 for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
357 if (xwriteatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
361 for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
362 if (xwriteatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
374 if (symfwmap != NULL)
376 if (symrvmap != NULL)
378 while ((tmpl = relalist) != NULL) {
379 relalist = tmpl->next;
380 if (tmpl->mem != NULL)
384 while ((tmpl = rellist) != NULL) {
385 rellist = tmpl->next;
386 if (tmpl->mem != NULL)
397 #endif /* include this size of ELF */