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 $");
37 __FBSDID("$FreeBSD$");
43 #include <sys/types.h>
44 #include <sys/endian.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>
61 #define xewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x))
62 #define htoxew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x))
64 #include <sys/elf64.h>
65 #define xewtoh(x) ((data == ELFDATA2MSB) ? be64toh(x) : le64toh(x))
66 #define htoxew(x) ((data == ELFDATA2MSB) ? htobe64(x) : htole64(x))
68 #include <sys/elf_generic.h>
70 #define CONCAT(x,y) __CONCAT(x,y)
71 #define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
72 #define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
73 #define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE))
74 #define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
76 #define xe16toh(x) ((data == ELFDATA2MSB) ? be16toh(x) : le16toh(x))
77 #define xe32toh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x))
78 #define htoxe32(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x))
81 struct listelem
*next
;
88 xreadatoff(int fd
, void *buf
, off_t off
, size_t size
, const char *fn
)
92 if (lseek(fd
, off
, SEEK_SET
) != off
) {
96 if ((rv
= read(fd
, buf
, size
)) != size
) {
97 fprintf(stderr
, "%s: read error: %s\n", fn
,
98 rv
== -1 ? strerror(errno
) : "short read");
105 xwriteatoff(int fd
, void *buf
, off_t off
, size_t size
, const char *fn
)
109 if (lseek(fd
, off
, SEEK_SET
) != off
) {
113 if ((rv
= write(fd
, buf
, size
)) != size
) {
114 fprintf(stderr
, "%s: write error: %s\n", fn
,
115 rv
== -1 ? strerror(errno
) : "short write");
122 xmalloc(size_t size
, const char *fn
, const char *use
)
128 fprintf(stderr
, "%s: out of memory (allocating for %s)\n",
134 ELFNAMEEND(check
)(int fd
, const char *fn
)
141 * Check the header to maek sure it's an ELF file (of the
144 if (fstat(fd
, &sb
) == -1)
146 if (sb
.st_size
< sizeof eh
)
148 if (read(fd
, &eh
, sizeof eh
) != sizeof eh
)
154 data
= eh
.e_ident
[EI_DATA
];
156 switch (xe16toh(eh
.e_machine
)) {
158 case EM_ALPHA
: break;
166 #ifndef EM_MIPS_RS4_BE /* same as EM_MIPS_RS3_LE */
167 #define EM_MIPS_RS4_BE 10
170 case /* EM_MIPS_RS3_LE */ EM_MIPS_RS4_BE
: break;
174 case EM_IA_64
: break;
180 #define EM_SPARCV9 43
182 case EM_SPARCV9
: break;
186 case EM_X86_64
: break;
187 /* ELFDEFNNAME(MACHDEP_ID_CASES) */
197 ELFNAMEEND(hide
)(int fd
, const char *fn
)
200 Elf_Shdr
*shdrp
= NULL
, *symtabshdr
, *strtabshdr
;
201 Elf_Sym
*symtabp
= NULL
;
202 char *strtabp
= NULL
;
203 Elf_Size
*symfwmap
= NULL
, *symrvmap
= NULL
, nsyms
, nlocalsyms
, ewi
;
204 struct listelem
*relalist
= NULL
, *rellist
= NULL
, *tmpl
;
210 if (xreadatoff(fd
, &ehdr
, 0, sizeof ehdr
, fn
) != sizeof ehdr
)
213 data
= ehdr
.e_ident
[EI_DATA
];
215 shdrsize
= xe16toh(ehdr
.e_shnum
) * xe16toh(ehdr
.e_shentsize
);
216 if ((shdrp
= xmalloc(shdrsize
, fn
, "section header table")) == NULL
)
218 if (xreadatoff(fd
, shdrp
, xewtoh(ehdr
.e_shoff
), shdrsize
, fn
) !=
222 symtabshdr
= strtabshdr
= NULL
;
224 for (i
= 0; i
< xe16toh(ehdr
.e_shnum
); i
++) {
225 switch (xe32toh(shdrp
[i
].sh_type
)) {
227 if (symtabshdr
!= NULL
)
229 symtabshdr
= &shdrp
[i
];
230 strtabshdr
= &shdrp
[xe32toh(shdrp
[i
].sh_link
)];
233 tmpl
= xmalloc(sizeof *tmpl
, fn
, "rela list element");
237 tmpl
->file
= xewtoh(shdrp
[i
].sh_offset
);
238 tmpl
->size
= xewtoh(shdrp
[i
].sh_size
);
239 tmpl
->next
= relalist
;
243 tmpl
= xmalloc(sizeof *tmpl
, fn
, "rel list element");
247 tmpl
->file
= xewtoh(shdrp
[i
].sh_offset
);
248 tmpl
->size
= xewtoh(shdrp
[i
].sh_size
);
249 tmpl
->next
= rellist
;
254 if (symtabshdr
== NULL
)
256 if (strtabshdr
== NULL
)
259 fprintf(stderr
, "%s: weird executable (unsupported)\n", fn
);
264 * load up everything we need
268 if ((symtabp
= xmalloc(xewtoh(symtabshdr
->sh_size
), fn
, "symbol table"))
271 if (xreadatoff(fd
, symtabp
, xewtoh(symtabshdr
->sh_offset
),
272 xewtoh(symtabshdr
->sh_size
), fn
) != xewtoh(symtabshdr
->sh_size
))
276 if ((strtabp
= xmalloc(xewtoh(strtabshdr
->sh_size
), fn
, "string table"))
279 if (xreadatoff(fd
, strtabp
, xewtoh(strtabshdr
->sh_offset
),
280 xewtoh(strtabshdr
->sh_size
), fn
) != xewtoh(strtabshdr
->sh_size
))
283 /* any rela tables */
284 for (tmpl
= relalist
; tmpl
!= NULL
; tmpl
= tmpl
->next
) {
285 if ((tmpl
->mem
= xmalloc(tmpl
->size
, fn
, "rela table"))
288 if (xreadatoff(fd
, tmpl
->mem
, tmpl
->file
,
289 tmpl
->size
, fn
) != tmpl
->size
)
294 for (tmpl
= rellist
; tmpl
!= NULL
; tmpl
= tmpl
->next
) {
295 if ((tmpl
->mem
= xmalloc(tmpl
->size
, fn
, "rel table"))
298 if (xreadatoff(fd
, tmpl
->mem
, tmpl
->file
,
299 tmpl
->size
, fn
) != tmpl
->size
)
303 /* Prepare data structures for symbol movement. */
304 nsyms
= xewtoh(symtabshdr
->sh_size
) / xewtoh(symtabshdr
->sh_entsize
);
305 nlocalsyms
= xe32toh(symtabshdr
->sh_info
);
306 if ((symfwmap
= xmalloc(nsyms
* sizeof (Elf_Size
), fn
,
307 "symbol forward mapping table")) == NULL
)
309 if ((symrvmap
= xmalloc(nsyms
* sizeof (Elf_Size
), fn
,
310 "symbol reverse mapping table")) == NULL
)
313 /* init location -> symbol # table */
314 for (ewi
= 0; ewi
< nsyms
; ewi
++)
317 /* move symbols, making them local */
318 for (ewi
= nlocalsyms
; ewi
< nsyms
; ewi
++) {
319 Elf_Sym
*sp
, symswap
;
324 /* if it's on our keep list, don't move it */
325 if (in_keep_list(strtabp
+ xe32toh(sp
->st_name
)))
328 /* if it's an undefined symbol, keep it */
329 if (xe16toh(sp
->st_shndx
) == SHN_UNDEF
)
332 /* adjust the symbol so that it's local */
334 ELF_ST_INFO(STB_LOCAL
, sp
->st_info
);
335 /* (STB_LOCAL << 4) | ELF_SYM_TYPE(sp->st_info); *//* XXX */
338 * move the symbol to its new location
341 /* note that symbols in those locations have been swapped */
342 mapswap
= symrvmap
[ewi
];
343 symrvmap
[ewi
] = symrvmap
[nlocalsyms
];
344 symrvmap
[nlocalsyms
] = mapswap
;
346 /* and swap the symbols */
348 *sp
= symtabp
[nlocalsyms
];
349 symtabp
[nlocalsyms
] = symswap
;
351 nlocalsyms
++; /* note new local sym */
353 symtabshdr
->sh_info
= htoxe32(nlocalsyms
);
355 /* set up symbol # -> location mapping table */
356 for (ewi
= 0; ewi
< nsyms
; ewi
++)
357 symfwmap
[symrvmap
[ewi
]] = ewi
;
359 /* any rela tables */
360 for (tmpl
= relalist
; tmpl
!= NULL
; tmpl
= tmpl
->next
) {
361 Elf_Rela
*relap
= tmpl
->mem
;
363 for (ewi
= 0; ewi
< tmpl
->size
/ sizeof(*relap
); ewi
++) {
364 relap
[ewi
].r_info
= htoxew(ELF_R_INFO(
365 symfwmap
[ELF_R_SYM(xewtoh(relap
[ewi
].r_info
))],
366 ELF_R_TYPE(xewtoh(relap
[ewi
].r_info
))
372 for (tmpl
= rellist
; tmpl
!= NULL
; tmpl
= tmpl
->next
) {
373 Elf_Rel
*relp
= tmpl
->mem
;
375 for (ewi
= 0; ewi
< tmpl
->size
/ sizeof *relp
; ewi
++) {
376 relp
[ewi
].r_info
= htoxew(ELF_R_INFO(
377 symfwmap
[ELF_R_SYM(xewtoh(relp
[ewi
].r_info
))],
378 ELF_R_TYPE(xewtoh(relp
[ewi
].r_info
))
384 * write new tables to the file
386 if (xwriteatoff(fd
, shdrp
, xewtoh(ehdr
.e_shoff
), shdrsize
, fn
) !=
389 if (xwriteatoff(fd
, symtabp
, xewtoh(symtabshdr
->sh_offset
),
390 xewtoh(symtabshdr
->sh_size
), fn
) != xewtoh(symtabshdr
->sh_size
))
392 for (tmpl
= relalist
; tmpl
!= NULL
; tmpl
= tmpl
->next
) {
393 if (xwriteatoff(fd
, tmpl
->mem
, tmpl
->file
,
394 tmpl
->size
, fn
) != tmpl
->size
)
397 for (tmpl
= rellist
; tmpl
!= NULL
; tmpl
= tmpl
->next
) {
398 if (xwriteatoff(fd
, tmpl
->mem
, tmpl
->file
,
399 tmpl
->size
, fn
) != tmpl
->size
)
410 if (symfwmap
!= NULL
)
412 if (symrvmap
!= NULL
)
414 while ((tmpl
= relalist
) != NULL
) {
415 relalist
= tmpl
->next
;
416 if (tmpl
->mem
!= NULL
)
420 while ((tmpl
= rellist
) != NULL
) {
421 rellist
= tmpl
->next
;
422 if (tmpl
->mem
!= NULL
)
433 #endif /* include this size of ELF */