12ec21a68SJordan K. Hubbard /* 22ec21a68SJordan K. Hubbard * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. 32ec21a68SJordan K. Hubbard * 42ec21a68SJordan K. Hubbard * Redistribution and use in source and binary forms, with or without 52ec21a68SJordan K. Hubbard * modification, are permitted provided that the following conditions 62ec21a68SJordan K. Hubbard * are met: 72ec21a68SJordan K. Hubbard * 1. Redistributions of source code must retain the above copyright 82ec21a68SJordan K. Hubbard * notice, this list of conditions and the following disclaimer. 92ec21a68SJordan K. Hubbard * 2. Redistributions in binary form must reproduce the above copyright 102ec21a68SJordan K. Hubbard * notice, this list of conditions and the following disclaimer in the 112ec21a68SJordan K. Hubbard * documentation and/or other materials provided with the distribution. 122ec21a68SJordan K. Hubbard * 3. All advertising materials mentioning features or use of this software 132ec21a68SJordan K. Hubbard * must display the following acknowledgement: 142ec21a68SJordan K. Hubbard * This product includes software developed by Christopher G. Demetriou 152ec21a68SJordan K. Hubbard * for the NetBSD Project. 162ec21a68SJordan K. Hubbard * 4. The name of the author may not be used to endorse or promote products 172ec21a68SJordan K. Hubbard * derived from this software without specific prior written permission 182ec21a68SJordan K. Hubbard * 192ec21a68SJordan K. Hubbard * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 202ec21a68SJordan K. Hubbard * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 212ec21a68SJordan K. Hubbard * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 222ec21a68SJordan K. Hubbard * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 232ec21a68SJordan K. Hubbard * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 242ec21a68SJordan K. Hubbard * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 252ec21a68SJordan K. Hubbard * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 262ec21a68SJordan K. Hubbard * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 272ec21a68SJordan K. Hubbard * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 282ec21a68SJordan K. Hubbard * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 292ec21a68SJordan K. Hubbard */ 302ec21a68SJordan K. Hubbard 312ec21a68SJordan K. Hubbard #include <sys/cdefs.h> 322ec21a68SJordan K. Hubbard #ifndef lint 335e6220d9SDavid E. O'Brien #if 0 342ec21a68SJordan K. Hubbard __RCSID("$NetBSD: exec_elf32.c,v 1.4 1997/08/12 06:07:24 mikel Exp $"); 352ec21a68SJordan K. Hubbard #endif 365e6220d9SDavid E. O'Brien #endif 3790b77cf3SDavid E. O'Brien __FBSDID("$FreeBSD$"); 382ec21a68SJordan K. Hubbard 392ec21a68SJordan K. Hubbard #ifndef ELFSIZE 402ec21a68SJordan K. Hubbard #define ELFSIZE 32 412ec21a68SJordan K. Hubbard #endif 422ec21a68SJordan K. Hubbard 432ec21a68SJordan K. Hubbard #include <sys/types.h> 442d57da02SDavid E. O'Brien #include <sys/endian.h> 452ec21a68SJordan K. Hubbard #include <sys/stat.h> 462ec21a68SJordan K. Hubbard 472ec21a68SJordan K. Hubbard #include <errno.h> 482ec21a68SJordan K. Hubbard #include <stdio.h> 492ec21a68SJordan K. Hubbard #include <stdlib.h> 502ec21a68SJordan K. Hubbard #include <string.h> 512ec21a68SJordan K. Hubbard #include <unistd.h> 522ec21a68SJordan K. Hubbard 532ec21a68SJordan K. Hubbard #include "extern.h" 542ec21a68SJordan K. Hubbard 552ec21a68SJordan K. Hubbard #if (defined(NLIST_ELF32) && (ELFSIZE == 32)) || \ 562ec21a68SJordan K. Hubbard (defined(NLIST_ELF64) && (ELFSIZE == 64)) 572ec21a68SJordan K. Hubbard 5864b06e78SRuslan Ermilov #define __ELF_WORD_SIZE ELFSIZE 5964b06e78SRuslan Ermilov #if (ELFSIZE == 32) 6064b06e78SRuslan Ermilov #include <sys/elf32.h> 61d8d97708SRuslan Ermilov #define xewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 6282c7cf31SRuslan Ermilov #define htoxew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 6364b06e78SRuslan Ermilov #elif (ELFSIZE == 64) 6464b06e78SRuslan Ermilov #include <sys/elf64.h> 65d8d97708SRuslan Ermilov #define xewtoh(x) ((data == ELFDATA2MSB) ? be64toh(x) : le64toh(x)) 6682c7cf31SRuslan Ermilov #define htoxew(x) ((data == ELFDATA2MSB) ? htobe64(x) : htole64(x)) 6764b06e78SRuslan Ermilov #endif 6864b06e78SRuslan Ermilov #include <sys/elf_generic.h> 692ec21a68SJordan K. Hubbard 702ec21a68SJordan K. Hubbard #define CONCAT(x,y) __CONCAT(x,y) 712ec21a68SJordan K. Hubbard #define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) 722ec21a68SJordan K. Hubbard #define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y)))) 732ec21a68SJordan K. Hubbard #define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE)) 742ec21a68SJordan K. Hubbard #define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) 752ec21a68SJordan K. Hubbard 76d8d97708SRuslan Ermilov #define xe16toh(x) ((data == ELFDATA2MSB) ? be16toh(x) : le16toh(x)) 77d8d97708SRuslan Ermilov #define xe32toh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 78d8d97708SRuslan Ermilov #define htoxe32(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 79d8d97708SRuslan Ermilov 802ec21a68SJordan K. Hubbard struct listelem { 812ec21a68SJordan K. Hubbard struct listelem *next; 822ec21a68SJordan K. Hubbard void *mem; 832ec21a68SJordan K. Hubbard off_t file; 842ec21a68SJordan K. Hubbard size_t size; 852ec21a68SJordan K. Hubbard }; 862ec21a68SJordan K. Hubbard 872ec21a68SJordan K. Hubbard static ssize_t 882ec21a68SJordan K. Hubbard xreadatoff(int fd, void *buf, off_t off, size_t size, const char *fn) 892ec21a68SJordan K. Hubbard { 902ec21a68SJordan K. Hubbard ssize_t rv; 912ec21a68SJordan K. Hubbard 922ec21a68SJordan K. Hubbard if (lseek(fd, off, SEEK_SET) != off) { 932ec21a68SJordan K. Hubbard perror(fn); 942ec21a68SJordan K. Hubbard return -1; 952ec21a68SJordan K. Hubbard } 962ec21a68SJordan K. Hubbard if ((rv = read(fd, buf, size)) != size) { 972ec21a68SJordan K. Hubbard fprintf(stderr, "%s: read error: %s\n", fn, 982ec21a68SJordan K. Hubbard rv == -1 ? strerror(errno) : "short read"); 992ec21a68SJordan K. Hubbard return -1; 1002ec21a68SJordan K. Hubbard } 1012ec21a68SJordan K. Hubbard return size; 1022ec21a68SJordan K. Hubbard } 1032ec21a68SJordan K. Hubbard 1042ec21a68SJordan K. Hubbard static ssize_t 1052ec21a68SJordan K. Hubbard xwriteatoff(int fd, void *buf, off_t off, size_t size, const char *fn) 1062ec21a68SJordan K. Hubbard { 1072ec21a68SJordan K. Hubbard ssize_t rv; 1082ec21a68SJordan K. Hubbard 1092ec21a68SJordan K. Hubbard if (lseek(fd, off, SEEK_SET) != off) { 1102ec21a68SJordan K. Hubbard perror(fn); 1112ec21a68SJordan K. Hubbard return -1; 1122ec21a68SJordan K. Hubbard } 1132ec21a68SJordan K. Hubbard if ((rv = write(fd, buf, size)) != size) { 1142ec21a68SJordan K. Hubbard fprintf(stderr, "%s: write error: %s\n", fn, 1152ec21a68SJordan K. Hubbard rv == -1 ? strerror(errno) : "short write"); 1162ec21a68SJordan K. Hubbard return -1; 1172ec21a68SJordan K. Hubbard } 1182ec21a68SJordan K. Hubbard return size; 1192ec21a68SJordan K. Hubbard } 1202ec21a68SJordan K. Hubbard 1212ec21a68SJordan K. Hubbard static void * 1222ec21a68SJordan K. Hubbard xmalloc(size_t size, const char *fn, const char *use) 1232ec21a68SJordan K. Hubbard { 1242ec21a68SJordan K. Hubbard void *rv; 1252ec21a68SJordan K. Hubbard 1262ec21a68SJordan K. Hubbard rv = malloc(size); 1272ec21a68SJordan K. Hubbard if (rv == NULL) 1282ec21a68SJordan K. Hubbard fprintf(stderr, "%s: out of memory (allocating for %s)\n", 1292ec21a68SJordan K. Hubbard fn, use); 1302ec21a68SJordan K. Hubbard return (rv); 1312ec21a68SJordan K. Hubbard } 1322ec21a68SJordan K. Hubbard 1332ec21a68SJordan K. Hubbard int 1342ec21a68SJordan K. Hubbard ELFNAMEEND(check)(int fd, const char *fn) 1352ec21a68SJordan K. Hubbard { 1362ec21a68SJordan K. Hubbard Elf_Ehdr eh; 1372ec21a68SJordan K. Hubbard struct stat sb; 138d8d97708SRuslan Ermilov unsigned char data; 1392ec21a68SJordan K. Hubbard 1402ec21a68SJordan K. Hubbard /* 1412ec21a68SJordan K. Hubbard * Check the header to maek sure it's an ELF file (of the 1422ec21a68SJordan K. Hubbard * appropriate size). 1432ec21a68SJordan K. Hubbard */ 1442ec21a68SJordan K. Hubbard if (fstat(fd, &sb) == -1) 1452ec21a68SJordan K. Hubbard return 0; 1462ec21a68SJordan K. Hubbard if (sb.st_size < sizeof eh) 1472ec21a68SJordan K. Hubbard return 0; 1482ec21a68SJordan K. Hubbard if (read(fd, &eh, sizeof eh) != sizeof eh) 1492ec21a68SJordan K. Hubbard return 0; 1502ec21a68SJordan K. Hubbard 1512ec21a68SJordan K. Hubbard if (IS_ELF(eh) == 0) 1522ec21a68SJordan K. Hubbard return 0; 1532ec21a68SJordan K. Hubbard 154d8d97708SRuslan Ermilov data = eh.e_ident[EI_DATA]; 155d8d97708SRuslan Ermilov 156d8d97708SRuslan Ermilov switch (xe16toh(eh.e_machine)) { 1572ec21a68SJordan K. Hubbard case EM_386: break; 1582ec21a68SJordan K. Hubbard case EM_ALPHA: break; 1594192cfffSRuslan Ermilov #ifndef EM_IA_64 1604192cfffSRuslan Ermilov #define EM_IA_64 50 1614192cfffSRuslan Ermilov #endif 16266c795d4SRuslan Ermilov case EM_IA_64: break; 163930d8c70SDavid E. O'Brien #ifndef EM_PPC 164930d8c70SDavid E. O'Brien #define EM_PPC 20 165930d8c70SDavid E. O'Brien #endif 166930d8c70SDavid E. O'Brien case EM_PPC: break; 1674192cfffSRuslan Ermilov #ifndef EM_SPARCV9 1684192cfffSRuslan Ermilov #define EM_SPARCV9 43 1694192cfffSRuslan Ermilov #endif 17066c795d4SRuslan Ermilov case EM_SPARCV9: break; 1718e81109eSPeter Wemm #ifndef EM_X86_64 1728e81109eSPeter Wemm #define EM_X86_64 62 1738e81109eSPeter Wemm #endif 1748e81109eSPeter Wemm case EM_X86_64: break; 1752ec21a68SJordan K. Hubbard /* ELFDEFNNAME(MACHDEP_ID_CASES) */ 1762ec21a68SJordan K. Hubbard 1772ec21a68SJordan K. Hubbard default: 1782ec21a68SJordan K. Hubbard return 0; 1792ec21a68SJordan K. Hubbard } 1802ec21a68SJordan K. Hubbard 1812ec21a68SJordan K. Hubbard return 1; 1822ec21a68SJordan K. Hubbard } 1832ec21a68SJordan K. Hubbard 1842ec21a68SJordan K. Hubbard int 1852ec21a68SJordan K. Hubbard ELFNAMEEND(hide)(int fd, const char *fn) 1862ec21a68SJordan K. Hubbard { 1872ec21a68SJordan K. Hubbard Elf_Ehdr ehdr; 1882ec21a68SJordan K. Hubbard Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr; 1892ec21a68SJordan K. Hubbard Elf_Sym *symtabp = NULL; 1902ec21a68SJordan K. Hubbard char *strtabp = NULL; 1912ec21a68SJordan K. Hubbard Elf_Word *symfwmap = NULL, *symrvmap = NULL, nsyms, nlocalsyms, ewi; 1922ec21a68SJordan K. Hubbard struct listelem *relalist = NULL, *rellist = NULL, *tmpl; 1932ec21a68SJordan K. Hubbard ssize_t shdrsize; 1942ec21a68SJordan K. Hubbard int rv, i, weird; 195d8d97708SRuslan Ermilov unsigned char data; 1962ec21a68SJordan K. Hubbard 1972ec21a68SJordan K. Hubbard rv = 0; 1982ec21a68SJordan K. Hubbard if (xreadatoff(fd, &ehdr, 0, sizeof ehdr, fn) != sizeof ehdr) 1992ec21a68SJordan K. Hubbard goto bad; 2002ec21a68SJordan K. Hubbard 201d8d97708SRuslan Ermilov data = ehdr.e_ident[EI_DATA]; 202d8d97708SRuslan Ermilov 203d8d97708SRuslan Ermilov shdrsize = xe16toh(ehdr.e_shnum) * xe16toh(ehdr.e_shentsize); 2042ec21a68SJordan K. Hubbard if ((shdrp = xmalloc(shdrsize, fn, "section header table")) == NULL) 2052ec21a68SJordan K. Hubbard goto bad; 206d8d97708SRuslan Ermilov if (xreadatoff(fd, shdrp, xewtoh(ehdr.e_shoff), shdrsize, fn) != 207d8d97708SRuslan Ermilov shdrsize) 2082ec21a68SJordan K. Hubbard goto bad; 2092ec21a68SJordan K. Hubbard 2102ec21a68SJordan K. Hubbard symtabshdr = strtabshdr = NULL; 2112ec21a68SJordan K. Hubbard weird = 0; 212d8d97708SRuslan Ermilov for (i = 0; i < xe16toh(ehdr.e_shnum); i++) { 213d8d97708SRuslan Ermilov switch (xe32toh(shdrp[i].sh_type)) { 2142ec21a68SJordan K. Hubbard case SHT_SYMTAB: 2152ec21a68SJordan K. Hubbard if (symtabshdr != NULL) 2162ec21a68SJordan K. Hubbard weird = 1; 2172ec21a68SJordan K. Hubbard symtabshdr = &shdrp[i]; 218d8d97708SRuslan Ermilov strtabshdr = &shdrp[xe32toh(shdrp[i].sh_link)]; 2192ec21a68SJordan K. Hubbard break; 2202ec21a68SJordan K. Hubbard case SHT_RELA: 2212ec21a68SJordan K. Hubbard tmpl = xmalloc(sizeof *tmpl, fn, "rela list element"); 2222ec21a68SJordan K. Hubbard if (tmpl == NULL) 2232ec21a68SJordan K. Hubbard goto bad; 2242ec21a68SJordan K. Hubbard tmpl->mem = NULL; 2252ec21a68SJordan K. Hubbard tmpl->file = shdrp[i].sh_offset; 2262ec21a68SJordan K. Hubbard tmpl->size = shdrp[i].sh_size; 2272ec21a68SJordan K. Hubbard tmpl->next = relalist; 2282ec21a68SJordan K. Hubbard relalist = tmpl; 2292ec21a68SJordan K. Hubbard break; 2302ec21a68SJordan K. Hubbard case SHT_REL: 2312ec21a68SJordan K. Hubbard tmpl = xmalloc(sizeof *tmpl, fn, "rel list element"); 2322ec21a68SJordan K. Hubbard if (tmpl == NULL) 2332ec21a68SJordan K. Hubbard goto bad; 2342ec21a68SJordan K. Hubbard tmpl->mem = NULL; 2352ec21a68SJordan K. Hubbard tmpl->file = shdrp[i].sh_offset; 2362ec21a68SJordan K. Hubbard tmpl->size = shdrp[i].sh_size; 2372ec21a68SJordan K. Hubbard tmpl->next = rellist; 2382ec21a68SJordan K. Hubbard rellist = tmpl; 2392ec21a68SJordan K. Hubbard break; 2402ec21a68SJordan K. Hubbard } 2412ec21a68SJordan K. Hubbard } 2422ec21a68SJordan K. Hubbard if (symtabshdr == NULL) 2432ec21a68SJordan K. Hubbard goto out; 2442ec21a68SJordan K. Hubbard if (strtabshdr == NULL) 2452ec21a68SJordan K. Hubbard weird = 1; 2462ec21a68SJordan K. Hubbard if (weird) { 2472ec21a68SJordan K. Hubbard fprintf(stderr, "%s: weird executable (unsupported)\n", fn); 2482ec21a68SJordan K. Hubbard goto bad; 2492ec21a68SJordan K. Hubbard } 2502ec21a68SJordan K. Hubbard 2512ec21a68SJordan K. Hubbard /* 2522ec21a68SJordan K. Hubbard * load up everything we need 2532ec21a68SJordan K. Hubbard */ 2542ec21a68SJordan K. Hubbard 2552ec21a68SJordan K. Hubbard /* symbol table */ 256d8d97708SRuslan Ermilov if ((symtabp = xmalloc(xewtoh(symtabshdr->sh_size), fn, "symbol table")) 2572ec21a68SJordan K. Hubbard == NULL) 2582ec21a68SJordan K. Hubbard goto bad; 259d8d97708SRuslan Ermilov if (xreadatoff(fd, symtabp, xewtoh(symtabshdr->sh_offset), 260d8d97708SRuslan Ermilov xewtoh(symtabshdr->sh_size), fn) != xewtoh(symtabshdr->sh_size)) 2612ec21a68SJordan K. Hubbard goto bad; 2622ec21a68SJordan K. Hubbard 2632ec21a68SJordan K. Hubbard /* string table */ 264d8d97708SRuslan Ermilov if ((strtabp = xmalloc(xewtoh(strtabshdr->sh_size), fn, "string table")) 2652ec21a68SJordan K. Hubbard == NULL) 2662ec21a68SJordan K. Hubbard goto bad; 267d8d97708SRuslan Ermilov if (xreadatoff(fd, strtabp, xewtoh(strtabshdr->sh_offset), 268d8d97708SRuslan Ermilov xewtoh(strtabshdr->sh_size), fn) != xewtoh(strtabshdr->sh_size)) 2692ec21a68SJordan K. Hubbard goto bad; 2702ec21a68SJordan K. Hubbard 2712ec21a68SJordan K. Hubbard /* any rela tables */ 2722ec21a68SJordan K. Hubbard for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) { 273d8d97708SRuslan Ermilov if ((tmpl->mem = xmalloc(xewtoh(tmpl->size), fn, "rela table")) 2742ec21a68SJordan K. Hubbard == NULL) 2752ec21a68SJordan K. Hubbard goto bad; 276d8d97708SRuslan Ermilov if (xreadatoff(fd, tmpl->mem, xewtoh(tmpl->file), 277d8d97708SRuslan Ermilov xewtoh(tmpl->size), fn) != xewtoh(tmpl->size)) 2782ec21a68SJordan K. Hubbard goto bad; 2792ec21a68SJordan K. Hubbard } 2802ec21a68SJordan K. Hubbard 2812ec21a68SJordan K. Hubbard /* any rel tables */ 2822ec21a68SJordan K. Hubbard for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) { 283d8d97708SRuslan Ermilov if ((tmpl->mem = xmalloc(xewtoh(tmpl->size), fn, "rel table")) 2842ec21a68SJordan K. Hubbard == NULL) 2852ec21a68SJordan K. Hubbard goto bad; 286d8d97708SRuslan Ermilov if (xreadatoff(fd, tmpl->mem, xewtoh(tmpl->file), 287d8d97708SRuslan Ermilov xewtoh(tmpl->size), fn) != xewtoh(tmpl->size)) 2882ec21a68SJordan K. Hubbard goto bad; 2892ec21a68SJordan K. Hubbard } 2902ec21a68SJordan K. Hubbard 2912ec21a68SJordan K. Hubbard /* Prepare data structures for symbol movement. */ 292d8d97708SRuslan Ermilov nsyms = xewtoh(symtabshdr->sh_size) / xewtoh(symtabshdr->sh_entsize); 293d8d97708SRuslan Ermilov nlocalsyms = xe32toh(symtabshdr->sh_info); 2942ec21a68SJordan K. Hubbard if ((symfwmap = xmalloc(nsyms * sizeof (Elf_Word), fn, 2952ec21a68SJordan K. Hubbard "symbol forward mapping table")) == NULL) 2962ec21a68SJordan K. Hubbard goto bad; 2972ec21a68SJordan K. Hubbard if ((symrvmap = xmalloc(nsyms * sizeof (Elf_Word), fn, 2982ec21a68SJordan K. Hubbard "symbol reverse mapping table")) == NULL) 2992ec21a68SJordan K. Hubbard goto bad; 3002ec21a68SJordan K. Hubbard 3012ec21a68SJordan K. Hubbard /* init location -> symbol # table */ 3022ec21a68SJordan K. Hubbard for (ewi = 0; ewi < nsyms; ewi++) 3032ec21a68SJordan K. Hubbard symrvmap[ewi] = ewi; 3042ec21a68SJordan K. Hubbard 3052ec21a68SJordan K. Hubbard /* move symbols, making them local */ 3062ec21a68SJordan K. Hubbard for (ewi = nlocalsyms; ewi < nsyms; ewi++) { 3072ec21a68SJordan K. Hubbard Elf_Sym *sp, symswap; 3082ec21a68SJordan K. Hubbard Elf_Word mapswap; 3092ec21a68SJordan K. Hubbard 3102ec21a68SJordan K. Hubbard sp = &symtabp[ewi]; 3112ec21a68SJordan K. Hubbard 3122ec21a68SJordan K. Hubbard /* if it's on our keep list, don't move it */ 313d8d97708SRuslan Ermilov if (in_keep_list(strtabp + xe32toh(sp->st_name))) 3142ec21a68SJordan K. Hubbard continue; 3152ec21a68SJordan K. Hubbard 3162ec21a68SJordan K. Hubbard /* if it's an undefined symbol, keep it */ 317d8d97708SRuslan Ermilov if (xe16toh(sp->st_shndx) == SHN_UNDEF) 3182ec21a68SJordan K. Hubbard continue; 3192ec21a68SJordan K. Hubbard 3202ec21a68SJordan K. Hubbard /* adjust the symbol so that it's local */ 3212ec21a68SJordan K. Hubbard sp->st_info = 3222ec21a68SJordan K. Hubbard ELF_ST_INFO(STB_LOCAL, sp->st_info); 3232ec21a68SJordan K. Hubbard /* (STB_LOCAL << 4) | ELF_SYM_TYPE(sp->st_info); *//* XXX */ 3242ec21a68SJordan K. Hubbard 3252ec21a68SJordan K. Hubbard /* 3262ec21a68SJordan K. Hubbard * move the symbol to its new location 3272ec21a68SJordan K. Hubbard */ 3282ec21a68SJordan K. Hubbard 3292ec21a68SJordan K. Hubbard /* note that symbols in those locations have been swapped */ 3302ec21a68SJordan K. Hubbard mapswap = symrvmap[ewi]; 3312ec21a68SJordan K. Hubbard symrvmap[ewi] = symrvmap[nlocalsyms]; 3322ec21a68SJordan K. Hubbard symrvmap[nlocalsyms] = mapswap; 3332ec21a68SJordan K. Hubbard 3342ec21a68SJordan K. Hubbard /* and swap the symbols */ 3352ec21a68SJordan K. Hubbard symswap = *sp; 3362ec21a68SJordan K. Hubbard *sp = symtabp[nlocalsyms]; 3372ec21a68SJordan K. Hubbard symtabp[nlocalsyms] = symswap; 3382ec21a68SJordan K. Hubbard 3392ec21a68SJordan K. Hubbard nlocalsyms++; /* note new local sym */ 3402ec21a68SJordan K. Hubbard } 341d8d97708SRuslan Ermilov symtabshdr->sh_info = htoxe32(nlocalsyms); 3422ec21a68SJordan K. Hubbard 3432ec21a68SJordan K. Hubbard /* set up symbol # -> location mapping table */ 3442ec21a68SJordan K. Hubbard for (ewi = 0; ewi < nsyms; ewi++) 3452ec21a68SJordan K. Hubbard symfwmap[symrvmap[ewi]] = ewi; 3462ec21a68SJordan K. Hubbard 3472ec21a68SJordan K. Hubbard /* any rela tables */ 3482ec21a68SJordan K. Hubbard for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) { 3492ec21a68SJordan K. Hubbard Elf_Rela *relap = tmpl->mem; 3502ec21a68SJordan K. Hubbard 351d8d97708SRuslan Ermilov for (ewi = 0; ewi < xewtoh(tmpl->size) / sizeof(*relap); ewi++) { 35282c7cf31SRuslan Ermilov relap[ewi].r_info = htoxew(ELF_R_INFO( 35382c7cf31SRuslan Ermilov symfwmap[ELF_R_SYM(xewtoh(relap[ewi].r_info))], 35482c7cf31SRuslan Ermilov ELF_R_TYPE(xewtoh(relap[ewi].r_info)) 35582c7cf31SRuslan Ermilov )); 3562ec21a68SJordan K. Hubbard } 3572ec21a68SJordan K. Hubbard } 3582ec21a68SJordan K. Hubbard 3592ec21a68SJordan K. Hubbard /* any rel tables */ 3602ec21a68SJordan K. Hubbard for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) { 3612ec21a68SJordan K. Hubbard Elf_Rel *relp = tmpl->mem; 3622ec21a68SJordan K. Hubbard 363d8d97708SRuslan Ermilov for (ewi = 0; ewi < xewtoh(tmpl->size) / sizeof *relp; ewi++) { 36482c7cf31SRuslan Ermilov relp[ewi].r_info = htoxew(ELF_R_INFO( 36582c7cf31SRuslan Ermilov symfwmap[ELF_R_SYM(xewtoh(relp[ewi].r_info))], 36682c7cf31SRuslan Ermilov ELF_R_TYPE(xewtoh(relp[ewi].r_info)) 36782c7cf31SRuslan Ermilov )); 3682ec21a68SJordan K. Hubbard } 3692ec21a68SJordan K. Hubbard } 3702ec21a68SJordan K. Hubbard 3712ec21a68SJordan K. Hubbard /* 3722ec21a68SJordan K. Hubbard * write new tables to the file 3732ec21a68SJordan K. Hubbard */ 374d8d97708SRuslan Ermilov if (xwriteatoff(fd, shdrp, xewtoh(ehdr.e_shoff), shdrsize, fn) != 375d8d97708SRuslan Ermilov shdrsize) 3762ec21a68SJordan K. Hubbard goto bad; 377d8d97708SRuslan Ermilov if (xwriteatoff(fd, symtabp, xewtoh(symtabshdr->sh_offset), 378d8d97708SRuslan Ermilov xewtoh(symtabshdr->sh_size), fn) != xewtoh(symtabshdr->sh_size)) 3792ec21a68SJordan K. Hubbard goto bad; 3802ec21a68SJordan K. Hubbard for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) { 381d8d97708SRuslan Ermilov if (xwriteatoff(fd, tmpl->mem, xewtoh(tmpl->file), 382d8d97708SRuslan Ermilov xewtoh(tmpl->size), fn) != xewtoh(tmpl->size)) 3832ec21a68SJordan K. Hubbard goto bad; 3842ec21a68SJordan K. Hubbard } 3852ec21a68SJordan K. Hubbard for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) { 386d8d97708SRuslan Ermilov if (xwriteatoff(fd, tmpl->mem, xewtoh(tmpl->file), 387d8d97708SRuslan Ermilov xewtoh(tmpl->size), fn) != xewtoh(tmpl->size)) 3882ec21a68SJordan K. Hubbard goto bad; 3892ec21a68SJordan K. Hubbard } 3902ec21a68SJordan K. Hubbard 3912ec21a68SJordan K. Hubbard out: 3922ec21a68SJordan K. Hubbard if (shdrp != NULL) 3932ec21a68SJordan K. Hubbard free(shdrp); 3942ec21a68SJordan K. Hubbard if (symtabp != NULL) 3952ec21a68SJordan K. Hubbard free(symtabp); 3962ec21a68SJordan K. Hubbard if (strtabp != NULL) 3972ec21a68SJordan K. Hubbard free(strtabp); 3982ec21a68SJordan K. Hubbard if (symfwmap != NULL) 3992ec21a68SJordan K. Hubbard free(symfwmap); 4002ec21a68SJordan K. Hubbard if (symrvmap != NULL) 4012ec21a68SJordan K. Hubbard free(symrvmap); 4022ec21a68SJordan K. Hubbard while ((tmpl = relalist) != NULL) { 4032ec21a68SJordan K. Hubbard relalist = tmpl->next; 4042ec21a68SJordan K. Hubbard if (tmpl->mem != NULL) 4052ec21a68SJordan K. Hubbard free(tmpl->mem); 4062ec21a68SJordan K. Hubbard free(tmpl); 4072ec21a68SJordan K. Hubbard } 4082ec21a68SJordan K. Hubbard while ((tmpl = rellist) != NULL) { 4092ec21a68SJordan K. Hubbard rellist = tmpl->next; 4102ec21a68SJordan K. Hubbard if (tmpl->mem != NULL) 4112ec21a68SJordan K. Hubbard free(tmpl->mem); 4122ec21a68SJordan K. Hubbard free(tmpl); 4132ec21a68SJordan K. Hubbard } 4142ec21a68SJordan K. Hubbard return (rv); 4152ec21a68SJordan K. Hubbard 4162ec21a68SJordan K. Hubbard bad: 4172ec21a68SJordan K. Hubbard rv = 1; 4182ec21a68SJordan K. Hubbard goto out; 4192ec21a68SJordan K. Hubbard } 4202ec21a68SJordan K. Hubbard 4212ec21a68SJordan K. Hubbard #endif /* include this size of ELF */ 422