11de7b4b8SPedro F. Giffuni /*- 21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause 31de7b4b8SPedro F. Giffuni * 42ec21a68SJordan K. Hubbard * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. 52ec21a68SJordan K. Hubbard * 62ec21a68SJordan K. Hubbard * Redistribution and use in source and binary forms, with or without 72ec21a68SJordan K. Hubbard * modification, are permitted provided that the following conditions 82ec21a68SJordan K. Hubbard * are met: 92ec21a68SJordan K. Hubbard * 1. Redistributions of source code must retain the above copyright 102ec21a68SJordan K. Hubbard * notice, this list of conditions and the following disclaimer. 112ec21a68SJordan K. Hubbard * 2. Redistributions in binary form must reproduce the above copyright 122ec21a68SJordan K. Hubbard * notice, this list of conditions and the following disclaimer in the 132ec21a68SJordan K. Hubbard * documentation and/or other materials provided with the distribution. 142ec21a68SJordan K. Hubbard * 3. All advertising materials mentioning features or use of this software 152ec21a68SJordan K. Hubbard * must display the following acknowledgement: 162ec21a68SJordan K. Hubbard * This product includes software developed by Christopher G. Demetriou 172ec21a68SJordan K. Hubbard * for the NetBSD Project. 182ec21a68SJordan K. Hubbard * 4. The name of the author may not be used to endorse or promote products 192ec21a68SJordan K. Hubbard * derived from this software without specific prior written permission 202ec21a68SJordan K. Hubbard * 212ec21a68SJordan K. Hubbard * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 222ec21a68SJordan K. Hubbard * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 232ec21a68SJordan K. Hubbard * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 242ec21a68SJordan K. Hubbard * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 252ec21a68SJordan K. Hubbard * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 262ec21a68SJordan K. Hubbard * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 272ec21a68SJordan K. Hubbard * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 282ec21a68SJordan K. Hubbard * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 292ec21a68SJordan K. Hubbard * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 302ec21a68SJordan K. Hubbard * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 312ec21a68SJordan K. Hubbard */ 322ec21a68SJordan K. Hubbard 332ec21a68SJordan K. Hubbard #include <sys/cdefs.h> 342ec21a68SJordan K. Hubbard #ifndef lint 355e6220d9SDavid E. O'Brien #if 0 3696acb2c4SPedro F. Giffuni __RCSID("$NetBSD: exec_elf32.c,v 1.6 1999/09/20 04:12:16 christos Exp $"); 372ec21a68SJordan K. Hubbard #endif 385e6220d9SDavid E. O'Brien #endif 3990b77cf3SDavid E. O'Brien __FBSDID("$FreeBSD$"); 402ec21a68SJordan K. Hubbard 412ec21a68SJordan K. Hubbard #ifndef ELFSIZE 422ec21a68SJordan K. Hubbard #define ELFSIZE 32 432ec21a68SJordan K. Hubbard #endif 442ec21a68SJordan K. Hubbard 452ec21a68SJordan K. Hubbard #include <sys/types.h> 462d57da02SDavid E. O'Brien #include <sys/endian.h> 472ec21a68SJordan K. Hubbard #include <sys/stat.h> 482ec21a68SJordan K. Hubbard 492ec21a68SJordan K. Hubbard #include <errno.h> 50b5782a47SPedro F. Giffuni #include <limits.h> 51b15dc003SEd Maste #include <stddef.h> 522ec21a68SJordan K. Hubbard #include <stdio.h> 532ec21a68SJordan K. Hubbard #include <stdlib.h> 542ec21a68SJordan K. Hubbard #include <string.h> 552ec21a68SJordan K. Hubbard #include <unistd.h> 562ec21a68SJordan K. Hubbard 572ec21a68SJordan K. Hubbard #include "extern.h" 582ec21a68SJordan K. Hubbard 592ec21a68SJordan K. Hubbard #if (defined(NLIST_ELF32) && (ELFSIZE == 32)) || \ 602ec21a68SJordan K. Hubbard (defined(NLIST_ELF64) && (ELFSIZE == 64)) 612ec21a68SJordan K. Hubbard 6264b06e78SRuslan Ermilov #define __ELF_WORD_SIZE ELFSIZE 6364b06e78SRuslan Ermilov #if (ELFSIZE == 32) 6464b06e78SRuslan Ermilov #include <sys/elf32.h> 65d8d97708SRuslan Ermilov #define xewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 6682c7cf31SRuslan Ermilov #define htoxew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 672c457547SAdrian Chadd #define wewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 682c457547SAdrian Chadd #define htowew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 6964b06e78SRuslan Ermilov #elif (ELFSIZE == 64) 7064b06e78SRuslan Ermilov #include <sys/elf64.h> 71d8d97708SRuslan Ermilov #define xewtoh(x) ((data == ELFDATA2MSB) ? be64toh(x) : le64toh(x)) 7282c7cf31SRuslan Ermilov #define htoxew(x) ((data == ELFDATA2MSB) ? htobe64(x) : htole64(x)) 732c457547SAdrian Chadd /* elf64 Elf64_Word are 32 bits */ 742c457547SAdrian Chadd #define wewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 752c457547SAdrian Chadd #define htowew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 7664b06e78SRuslan Ermilov #endif 7764b06e78SRuslan Ermilov #include <sys/elf_generic.h> 782ec21a68SJordan K. Hubbard 792ec21a68SJordan K. Hubbard #define CONCAT(x,y) __CONCAT(x,y) 802ec21a68SJordan K. Hubbard #define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) 812ec21a68SJordan K. Hubbard #define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y)))) 822ec21a68SJordan K. Hubbard #define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE)) 832ec21a68SJordan K. Hubbard #define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) 84070cadfcSEd Maste #ifndef ELFCLASS 85070cadfcSEd Maste #define ELFCLASS CONCAT(ELFCLASS,ELFSIZE) 86070cadfcSEd Maste #endif 872ec21a68SJordan K. Hubbard 88d8d97708SRuslan Ermilov #define xe16toh(x) ((data == ELFDATA2MSB) ? be16toh(x) : le16toh(x)) 89d8d97708SRuslan Ermilov #define xe32toh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 90d8d97708SRuslan Ermilov #define htoxe32(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 91d8d97708SRuslan Ermilov 92b5782a47SPedro F. Giffuni struct shlayout { 93b5782a47SPedro F. Giffuni Elf_Shdr *shdr; 94b5782a47SPedro F. Giffuni void *bufp; 952ec21a68SJordan K. Hubbard }; 962ec21a68SJordan K. Hubbard 972ec21a68SJordan K. Hubbard static ssize_t 982ec21a68SJordan K. Hubbard xreadatoff(int fd, void *buf, off_t off, size_t size, const char *fn) 992ec21a68SJordan K. Hubbard { 1002ec21a68SJordan K. Hubbard ssize_t rv; 1012ec21a68SJordan K. Hubbard 1022ec21a68SJordan K. Hubbard if (lseek(fd, off, SEEK_SET) != off) { 1032ec21a68SJordan K. Hubbard perror(fn); 1042ec21a68SJordan K. Hubbard return -1; 1052ec21a68SJordan K. Hubbard } 10696acb2c4SPedro F. Giffuni if ((size_t)(rv = read(fd, buf, size)) != size) { 1072ec21a68SJordan K. Hubbard fprintf(stderr, "%s: read error: %s\n", fn, 1082ec21a68SJordan K. Hubbard rv == -1 ? strerror(errno) : "short read"); 1092ec21a68SJordan K. Hubbard return -1; 1102ec21a68SJordan K. Hubbard } 1112ec21a68SJordan K. Hubbard return size; 1122ec21a68SJordan K. Hubbard } 1132ec21a68SJordan K. Hubbard 1142ec21a68SJordan K. Hubbard static ssize_t 1152ec21a68SJordan K. Hubbard xwriteatoff(int fd, void *buf, off_t off, size_t size, const char *fn) 1162ec21a68SJordan K. Hubbard { 1172ec21a68SJordan K. Hubbard ssize_t rv; 1182ec21a68SJordan K. Hubbard 1192ec21a68SJordan K. Hubbard if (lseek(fd, off, SEEK_SET) != off) { 1202ec21a68SJordan K. Hubbard perror(fn); 1212ec21a68SJordan K. Hubbard return -1; 1222ec21a68SJordan K. Hubbard } 12396acb2c4SPedro F. Giffuni if ((size_t)(rv = write(fd, buf, size)) != size) { 1242ec21a68SJordan K. Hubbard fprintf(stderr, "%s: write error: %s\n", fn, 1252ec21a68SJordan K. Hubbard rv == -1 ? strerror(errno) : "short write"); 1262ec21a68SJordan K. Hubbard return -1; 1272ec21a68SJordan K. Hubbard } 1282ec21a68SJordan K. Hubbard return size; 1292ec21a68SJordan K. Hubbard } 1302ec21a68SJordan K. Hubbard 1312ec21a68SJordan K. Hubbard static void * 1322ec21a68SJordan K. Hubbard xmalloc(size_t size, const char *fn, const char *use) 1332ec21a68SJordan K. Hubbard { 1342ec21a68SJordan K. Hubbard void *rv; 1352ec21a68SJordan K. Hubbard 1362ec21a68SJordan K. Hubbard rv = malloc(size); 1372ec21a68SJordan K. Hubbard if (rv == NULL) 1382ec21a68SJordan K. Hubbard fprintf(stderr, "%s: out of memory (allocating for %s)\n", 1392ec21a68SJordan K. Hubbard fn, use); 1402ec21a68SJordan K. Hubbard return (rv); 1412ec21a68SJordan K. Hubbard } 1422ec21a68SJordan K. Hubbard 1437420b323SAdrian Chadd static void * 1447420b323SAdrian Chadd xrealloc(void *ptr, size_t size, const char *fn, const char *use) 1457420b323SAdrian Chadd { 1467420b323SAdrian Chadd void *rv; 1477420b323SAdrian Chadd 1487420b323SAdrian Chadd rv = realloc(ptr, size); 1497420b323SAdrian Chadd if (rv == NULL) { 1507420b323SAdrian Chadd free(ptr); 1517420b323SAdrian Chadd fprintf(stderr, "%s: out of memory (reallocating for %s)\n", 1527420b323SAdrian Chadd fn, use); 1537420b323SAdrian Chadd } 1547420b323SAdrian Chadd return (rv); 1557420b323SAdrian Chadd } 1567420b323SAdrian Chadd 1572ec21a68SJordan K. Hubbard int 158dd7c7ff1SKyle Evans ELFNAMEEND(check)(int fd, const char *fn __unused) 1592ec21a68SJordan K. Hubbard { 1602ec21a68SJordan K. Hubbard Elf_Ehdr eh; 1612ec21a68SJordan K. Hubbard struct stat sb; 162d8d97708SRuslan Ermilov unsigned char data; 1632ec21a68SJordan K. Hubbard 1642ec21a68SJordan K. Hubbard /* 165*d34de8d3SGordon Bergling * Check the header to make sure it's an ELF file (of the 1662ec21a68SJordan K. Hubbard * appropriate size). 1672ec21a68SJordan K. Hubbard */ 1682ec21a68SJordan K. Hubbard if (fstat(fd, &sb) == -1) 1692ec21a68SJordan K. Hubbard return 0; 17096acb2c4SPedro F. Giffuni if (sb.st_size < (off_t)(sizeof eh)) 1712ec21a68SJordan K. Hubbard return 0; 1722ec21a68SJordan K. Hubbard if (read(fd, &eh, sizeof eh) != sizeof eh) 1732ec21a68SJordan K. Hubbard return 0; 1742ec21a68SJordan K. Hubbard 175070cadfcSEd Maste if (IS_ELF(eh) == 0 || eh.e_ident[EI_CLASS] != ELFCLASS) 1762ec21a68SJordan K. Hubbard return 0; 1772ec21a68SJordan K. Hubbard 178d8d97708SRuslan Ermilov data = eh.e_ident[EI_DATA]; 179d8d97708SRuslan Ermilov 180d8d97708SRuslan Ermilov switch (xe16toh(eh.e_machine)) { 1812ec21a68SJordan K. Hubbard case EM_386: break; 1822ec21a68SJordan K. Hubbard case EM_ALPHA: break; 18366137b66SEd Maste #ifndef EM_AARCH64 18466137b66SEd Maste #define EM_AARCH64 183 18566137b66SEd Maste #endif 1865667872eSAndrew Turner case EM_AARCH64: break; 187ed575be4SOlivier Houchard case EM_ARM: break; 18822407452SDavid E. O'Brien case EM_MIPS: break; 18922407452SDavid E. O'Brien case /* EM_MIPS_RS3_LE */ EM_MIPS_RS4_BE: break; 190930d8c70SDavid E. O'Brien case EM_PPC: break; 1918a10bad2SNathan Whitehorn case EM_PPC64: break; 192c8daf7a0SEd Maste #ifndef EM_RISCV 193c8daf7a0SEd Maste #define EM_RISCV 243 194c8daf7a0SEd Maste #endif 195c8daf7a0SEd Maste case EM_RISCV: break; 1964a6768e6SBjoern A. Zeeb case EM_S390: break; 19766c795d4SRuslan Ermilov case EM_SPARCV9: break; 1988e81109eSPeter Wemm case EM_X86_64: break; 1992ec21a68SJordan K. Hubbard /* ELFDEFNNAME(MACHDEP_ID_CASES) */ 2002ec21a68SJordan K. Hubbard 2012ec21a68SJordan K. Hubbard default: 2022ec21a68SJordan K. Hubbard return 0; 2032ec21a68SJordan K. Hubbard } 2042ec21a68SJordan K. Hubbard 2052ec21a68SJordan K. Hubbard return 1; 2062ec21a68SJordan K. Hubbard } 2072ec21a68SJordan K. Hubbard 2087420b323SAdrian Chadd /* 2097420b323SAdrian Chadd * This function 'hides' (some of) ELF executable file's symbols. 2107420b323SAdrian Chadd * It hides them by renaming them to "_$$hide$$ <filename> <symbolname>". 2117420b323SAdrian Chadd * Symbols in the global keep list, or which are marked as being undefined, 2127420b323SAdrian Chadd * are left alone. 2137420b323SAdrian Chadd * 2147420b323SAdrian Chadd * An old version of this code shuffled various tables around, turning 2157420b323SAdrian Chadd * global symbols to be hidden into local symbols. That lost on the 2167420b323SAdrian Chadd * mips, because CALL16 relocs must reference global symbols, and, if 2177420b323SAdrian Chadd * those symbols were being hidden, they were no longer global. 2187420b323SAdrian Chadd * 2197420b323SAdrian Chadd * The new renaming behaviour doesn't take global symbols out of the 2207420b323SAdrian Chadd * namespace. However, it's ... unlikely that there will ever be 2217420b323SAdrian Chadd * any collisions in practice because of the new method. 2227420b323SAdrian Chadd */ 2232ec21a68SJordan K. Hubbard int 2242ec21a68SJordan K. Hubbard ELFNAMEEND(hide)(int fd, const char *fn) 2252ec21a68SJordan K. Hubbard { 2262ec21a68SJordan K. Hubbard Elf_Ehdr ehdr; 227b5782a47SPedro F. Giffuni struct shlayout *layoutp = NULL; 228b5782a47SPedro F. Giffuni Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr, *shstrtabshdr; 229b5782a47SPedro F. Giffuni Elf_Shdr shdrshdr; 2302ec21a68SJordan K. Hubbard Elf_Sym *symtabp = NULL; 231b5782a47SPedro F. Giffuni char *shstrtabp = NULL, *strtabp = NULL; 2321d76342eSEitan Adler Elf_Size nsyms, ewi; 233b5782a47SPedro F. Giffuni Elf_Off off; 2342ec21a68SJordan K. Hubbard ssize_t shdrsize; 235b5782a47SPedro F. Giffuni int rv, i, weird, l, m, r, strtabidx; 236b5782a47SPedro F. Giffuni size_t nstrtab_size, nstrtab_nextoff, fn_size, size; 2377420b323SAdrian Chadd char *nstrtabp = NULL; 238d8d97708SRuslan Ermilov unsigned char data; 2397420b323SAdrian Chadd const char *weirdreason = NULL; 240b5782a47SPedro F. Giffuni void *buf; 241e8ee1a1eSPedro F. Giffuni Elf_Half shnum; 2422ec21a68SJordan K. Hubbard 2432ec21a68SJordan K. Hubbard rv = 0; 2442ec21a68SJordan K. Hubbard if (xreadatoff(fd, &ehdr, 0, sizeof ehdr, fn) != sizeof ehdr) 2452ec21a68SJordan K. Hubbard goto bad; 2462ec21a68SJordan K. Hubbard 247d8d97708SRuslan Ermilov data = ehdr.e_ident[EI_DATA]; 248e8ee1a1eSPedro F. Giffuni shnum = xe16toh(ehdr.e_shnum); 249d8d97708SRuslan Ermilov 250e8ee1a1eSPedro F. Giffuni shdrsize = shnum * xe16toh(ehdr.e_shentsize); 2512ec21a68SJordan K. Hubbard if ((shdrp = xmalloc(shdrsize, fn, "section header table")) == NULL) 2522ec21a68SJordan K. Hubbard goto bad; 253d8d97708SRuslan Ermilov if (xreadatoff(fd, shdrp, xewtoh(ehdr.e_shoff), shdrsize, fn) != 254d8d97708SRuslan Ermilov shdrsize) 2552ec21a68SJordan K. Hubbard goto bad; 2562ec21a68SJordan K. Hubbard 257b5782a47SPedro F. Giffuni symtabshdr = strtabshdr = shstrtabshdr = NULL; 2582ec21a68SJordan K. Hubbard weird = 0; 259e8ee1a1eSPedro F. Giffuni for (i = 0; i < shnum; i++) { 260d8d97708SRuslan Ermilov switch (xe32toh(shdrp[i].sh_type)) { 2612ec21a68SJordan K. Hubbard case SHT_SYMTAB: 262b5782a47SPedro F. Giffuni if (symtabshdr != NULL) { 2632ec21a68SJordan K. Hubbard weird = 1; 264b5782a47SPedro F. Giffuni weirdreason = "multiple symbol tables"; 265b5782a47SPedro F. Giffuni } 2662ec21a68SJordan K. Hubbard symtabshdr = &shdrp[i]; 267d8d97708SRuslan Ermilov strtabshdr = &shdrp[xe32toh(shdrp[i].sh_link)]; 268b5782a47SPedro F. Giffuni break; 269b5782a47SPedro F. Giffuni case SHT_STRTAB: 270b5782a47SPedro F. Giffuni if (i == xe16toh(ehdr.e_shstrndx)) 271b5782a47SPedro F. Giffuni shstrtabshdr = &shdrp[i]; 2722ec21a68SJordan K. Hubbard break; 2732ec21a68SJordan K. Hubbard } 2742ec21a68SJordan K. Hubbard } 2752ec21a68SJordan K. Hubbard if (symtabshdr == NULL) 2762ec21a68SJordan K. Hubbard goto out; 277b5782a47SPedro F. Giffuni if (strtabshdr == NULL) { 2782ec21a68SJordan K. Hubbard weird = 1; 279b5782a47SPedro F. Giffuni weirdreason = "string table does not exist"; 2807420b323SAdrian Chadd } 281b5782a47SPedro F. Giffuni if (shstrtabshdr == NULL) { 282b5782a47SPedro F. Giffuni weird = 1; 283b5782a47SPedro F. Giffuni weirdreason = "section header string table does not exist"; 284b5782a47SPedro F. Giffuni } 285f513dfd4SEd Maste if (strtabshdr == shstrtabshdr) { 286f513dfd4SEd Maste weird = 1; 287f513dfd4SEd Maste weirdreason = "combined strtab and shstrtab not supported"; 288f513dfd4SEd Maste } 289b5782a47SPedro F. Giffuni if (weirdreason == NULL) 290b5782a47SPedro F. Giffuni weirdreason = "unsupported"; 2912ec21a68SJordan K. Hubbard if (weird) { 2927420b323SAdrian Chadd fprintf(stderr, "%s: weird executable (%s)\n", fn, weirdreason); 2932ec21a68SJordan K. Hubbard goto bad; 2942ec21a68SJordan K. Hubbard } 2952ec21a68SJordan K. Hubbard 2962ec21a68SJordan K. Hubbard /* 297b5782a47SPedro F. Giffuni * sort section layout table by offset 298b5782a47SPedro F. Giffuni */ 299e8ee1a1eSPedro F. Giffuni layoutp = xmalloc((shnum + 1) * sizeof(struct shlayout), 300b5782a47SPedro F. Giffuni fn, "layout table"); 301b5782a47SPedro F. Giffuni if (layoutp == NULL) 302b5782a47SPedro F. Giffuni goto bad; 303b5782a47SPedro F. Giffuni 304b5782a47SPedro F. Giffuni /* add a pseudo entry to represent the section header table */ 305b5782a47SPedro F. Giffuni shdrshdr.sh_offset = ehdr.e_shoff; 306b5782a47SPedro F. Giffuni shdrshdr.sh_size = htoxew(shdrsize); 307b5782a47SPedro F. Giffuni shdrshdr.sh_addralign = htoxew(ELFSIZE / 8); 308e8ee1a1eSPedro F. Giffuni layoutp[shnum].shdr = &shdrshdr; 309b5782a47SPedro F. Giffuni 310b5782a47SPedro F. Giffuni /* insert and sort normal section headers */ 311e8ee1a1eSPedro F. Giffuni for (i = shnum; i-- != 0;) { 312b5782a47SPedro F. Giffuni l = i + 1; 313e8ee1a1eSPedro F. Giffuni r = shnum; 314b5782a47SPedro F. Giffuni while (l <= r) { 315b5782a47SPedro F. Giffuni m = ( l + r) / 2; 316b5782a47SPedro F. Giffuni if (xewtoh(shdrp[i].sh_offset) > 317b5782a47SPedro F. Giffuni xewtoh(layoutp[m].shdr->sh_offset)) 318b5782a47SPedro F. Giffuni l = m + 1; 319b5782a47SPedro F. Giffuni else 320b5782a47SPedro F. Giffuni r = m - 1; 321b5782a47SPedro F. Giffuni } 322b5782a47SPedro F. Giffuni 323b5782a47SPedro F. Giffuni if (r != i) { 324b5782a47SPedro F. Giffuni memmove(&layoutp[i], &layoutp[i + 1], 325b5782a47SPedro F. Giffuni sizeof(struct shlayout) * (r - i)); 326b5782a47SPedro F. Giffuni } 327b5782a47SPedro F. Giffuni 328b5782a47SPedro F. Giffuni layoutp[r].shdr = &shdrp[i]; 329b5782a47SPedro F. Giffuni layoutp[r].bufp = NULL; 330b5782a47SPedro F. Giffuni } 331e8ee1a1eSPedro F. Giffuni ++shnum; 332b5782a47SPedro F. Giffuni 333b5782a47SPedro F. Giffuni /* 3342ec21a68SJordan K. Hubbard * load up everything we need 3352ec21a68SJordan K. Hubbard */ 3362ec21a68SJordan K. Hubbard 337b5782a47SPedro F. Giffuni /* load section string table for debug use */ 338e52f9715SEd Maste if ((size = xewtoh(shstrtabshdr->sh_size)) == 0) 339e52f9715SEd Maste goto bad; 340e52f9715SEd Maste if ((shstrtabp = xmalloc(size, fn, "section string table")) == NULL) 3412ec21a68SJordan K. Hubbard goto bad; 342b5782a47SPedro F. Giffuni if ((size_t)xreadatoff(fd, shstrtabp, xewtoh(shstrtabshdr->sh_offset), 343e52f9715SEd Maste size, fn) != size) 344e52f9715SEd Maste goto bad; 345e52f9715SEd Maste if (shstrtabp[size - 1] != '\0') 3462ec21a68SJordan K. Hubbard goto bad; 3472ec21a68SJordan K. Hubbard 348b5782a47SPedro F. Giffuni /* we need symtab, strtab, and everything behind strtab */ 349b5782a47SPedro F. Giffuni strtabidx = INT_MAX; 350e8ee1a1eSPedro F. Giffuni for (i = 0; i < shnum; i++) { 351b5782a47SPedro F. Giffuni if (layoutp[i].shdr == &shdrshdr) { 352b5782a47SPedro F. Giffuni /* not load section header again */ 353b5782a47SPedro F. Giffuni layoutp[i].bufp = shdrp; 354b5782a47SPedro F. Giffuni continue; 355b5782a47SPedro F. Giffuni } 356b5782a47SPedro F. Giffuni if (layoutp[i].shdr == shstrtabshdr) { 357b5782a47SPedro F. Giffuni /* not load section string table again */ 358b5782a47SPedro F. Giffuni layoutp[i].bufp = shstrtabp; 359b5782a47SPedro F. Giffuni continue; 360b5782a47SPedro F. Giffuni } 361b5782a47SPedro F. Giffuni 362b5782a47SPedro F. Giffuni if (layoutp[i].shdr == strtabshdr) 363b5782a47SPedro F. Giffuni strtabidx = i; 364b5782a47SPedro F. Giffuni if (layoutp[i].shdr == symtabshdr || i >= strtabidx) { 365b5782a47SPedro F. Giffuni off = xewtoh(layoutp[i].shdr->sh_offset); 366e52f9715SEd Maste if ((size = xewtoh(layoutp[i].shdr->sh_size)) == 0) 367e52f9715SEd Maste goto bad; 368b5782a47SPedro F. Giffuni layoutp[i].bufp = xmalloc(size, fn, 369b5782a47SPedro F. Giffuni shstrtabp + xewtoh(layoutp[i].shdr->sh_name)); 370b5782a47SPedro F. Giffuni if (layoutp[i].bufp == NULL) 3712ec21a68SJordan K. Hubbard goto bad; 372b5782a47SPedro F. Giffuni if ((size_t)xreadatoff(fd, layoutp[i].bufp, off, size, fn) != 373b5782a47SPedro F. Giffuni size) 3742ec21a68SJordan K. Hubbard goto bad; 3752ec21a68SJordan K. Hubbard 376b5782a47SPedro F. Giffuni /* set symbol table and string table */ 377e52f9715SEd Maste if (layoutp[i].shdr == symtabshdr) { 378b5782a47SPedro F. Giffuni symtabp = layoutp[i].bufp; 379e52f9715SEd Maste } else if (layoutp[i].shdr == strtabshdr) { 380b5782a47SPedro F. Giffuni strtabp = layoutp[i].bufp; 381e52f9715SEd Maste if (strtabp[size - 1] != '\0') 382e52f9715SEd Maste goto bad; 383e52f9715SEd Maste } 384b5782a47SPedro F. Giffuni } 385b5782a47SPedro F. Giffuni } 386b5782a47SPedro F. Giffuni 3877420b323SAdrian Chadd nstrtab_size = 256; 3887420b323SAdrian Chadd nstrtabp = xmalloc(nstrtab_size, fn, "new string table"); 3897420b323SAdrian Chadd if (nstrtabp == NULL) 3902ec21a68SJordan K. Hubbard goto bad; 3917420b323SAdrian Chadd nstrtab_nextoff = 0; 3922ec21a68SJordan K. Hubbard 3937420b323SAdrian Chadd fn_size = strlen(fn); 3942ec21a68SJordan K. Hubbard 3952ec21a68SJordan K. Hubbard /* Prepare data structures for symbol movement. */ 396d8d97708SRuslan Ermilov nsyms = xewtoh(symtabshdr->sh_size) / xewtoh(symtabshdr->sh_entsize); 3972ec21a68SJordan K. Hubbard 3982ec21a68SJordan K. Hubbard /* move symbols, making them local */ 3997420b323SAdrian Chadd for (ewi = 0; ewi < nsyms; ewi++) { 4007420b323SAdrian Chadd Elf_Sym *sp = &symtabp[ewi]; 4017420b323SAdrian Chadd const char *symname = strtabp + xe32toh(sp->st_name); 4027420b323SAdrian Chadd size_t newent_len; 4032ec21a68SJordan K. Hubbard /* 4047420b323SAdrian Chadd * make sure there's size for the next entry, even if it's 4057420b323SAdrian Chadd * as large as it can be. 4067420b323SAdrian Chadd * 4077420b323SAdrian Chadd * "_$$hide$$ <filename> <symname><NUL>" -> 4087420b323SAdrian Chadd * 9 + 3 + sizes of fn and sym name 4092ec21a68SJordan K. Hubbard */ 4107420b323SAdrian Chadd while ((nstrtab_size - nstrtab_nextoff) < 4117420b323SAdrian Chadd strlen(symname) + fn_size + 12) { 4127420b323SAdrian Chadd nstrtab_size *= 2; 4137420b323SAdrian Chadd nstrtabp = xrealloc(nstrtabp, nstrtab_size, fn, 4147420b323SAdrian Chadd "new string table"); 4157420b323SAdrian Chadd if (nstrtabp == NULL) 4167420b323SAdrian Chadd goto bad; 4172ec21a68SJordan K. Hubbard } 4182ec21a68SJordan K. Hubbard 4192c457547SAdrian Chadd sp->st_name = htowew(nstrtab_nextoff); 4202ec21a68SJordan K. Hubbard 4217420b323SAdrian Chadd /* if it's a keeper or is undefined, don't rename it. */ 4227420b323SAdrian Chadd if (in_keep_list(symname) || 4237420b323SAdrian Chadd (xe16toh(sp->st_shndx) == SHN_UNDEF)) { 4247420b323SAdrian Chadd newent_len = sprintf(nstrtabp + nstrtab_nextoff, 4257420b323SAdrian Chadd "%s", symname) + 1; 4267420b323SAdrian Chadd } else { 4277420b323SAdrian Chadd newent_len = sprintf(nstrtabp + nstrtab_nextoff, 4287420b323SAdrian Chadd "_$$hide$$ %s %s", fn, symname) + 1; 4292ec21a68SJordan K. Hubbard } 4307420b323SAdrian Chadd nstrtab_nextoff += newent_len; 4312ec21a68SJordan K. Hubbard } 4327420b323SAdrian Chadd strtabshdr->sh_size = htoxew(nstrtab_nextoff); 4332ec21a68SJordan K. Hubbard 4342ec21a68SJordan K. Hubbard /* 435b5782a47SPedro F. Giffuni * update section header table in ascending order of offset 4362ec21a68SJordan K. Hubbard */ 437e8ee1a1eSPedro F. Giffuni for (i = strtabidx + 1; i < shnum; i++) { 438dd7c7ff1SKyle Evans Elf_Off soff, align; 439dd7c7ff1SKyle Evans soff = xewtoh(layoutp[i - 1].shdr->sh_offset) + 440b5782a47SPedro F. Giffuni xewtoh(layoutp[i - 1].shdr->sh_size); 441b5782a47SPedro F. Giffuni align = xewtoh(layoutp[i].shdr->sh_addralign); 442dd7c7ff1SKyle Evans soff = (soff + (align - 1)) & ~(align - 1); 443dd7c7ff1SKyle Evans layoutp[i].shdr->sh_offset = htoxew(soff); 444b5782a47SPedro F. Giffuni } 445b5782a47SPedro F. Giffuni 446b5782a47SPedro F. Giffuni /* 447b5782a47SPedro F. Giffuni * write data to the file in descending order of offset 448b5782a47SPedro F. Giffuni */ 449e8ee1a1eSPedro F. Giffuni for (i = shnum; i-- != 0;) { 450b5782a47SPedro F. Giffuni if (layoutp[i].shdr == strtabshdr) { 451b5782a47SPedro F. Giffuni /* new string table */ 452b5782a47SPedro F. Giffuni buf = nstrtabp; 453b5782a47SPedro F. Giffuni } else 454b5782a47SPedro F. Giffuni buf = layoutp[i].bufp; 455b5782a47SPedro F. Giffuni 456b5782a47SPedro F. Giffuni if (layoutp[i].shdr == &shdrshdr || 457b5782a47SPedro F. Giffuni layoutp[i].shdr == symtabshdr || i >= strtabidx) { 458b5782a47SPedro F. Giffuni if (buf == NULL) 4592ec21a68SJordan K. Hubbard goto bad; 4602ec21a68SJordan K. Hubbard 461b5782a47SPedro F. Giffuni /* 462b5782a47SPedro F. Giffuni * update the offset of section header table in elf 463b5782a47SPedro F. Giffuni * header if needed. 464b5782a47SPedro F. Giffuni */ 465b5782a47SPedro F. Giffuni if (layoutp[i].shdr == &shdrshdr && 466b5782a47SPedro F. Giffuni ehdr.e_shoff != shdrshdr.sh_offset) { 467b5782a47SPedro F. Giffuni ehdr.e_shoff = shdrshdr.sh_offset; 468b15dc003SEd Maste off = offsetof(Elf_Ehdr, e_shoff); 469b5782a47SPedro F. Giffuni size = sizeof(Elf_Off); 470b5782a47SPedro F. Giffuni if ((size_t)xwriteatoff(fd, &ehdr.e_shoff, off, size, 471b5782a47SPedro F. Giffuni fn) != size) 472b5782a47SPedro F. Giffuni goto bad; 473b5782a47SPedro F. Giffuni } 474b5782a47SPedro F. Giffuni 475b5782a47SPedro F. Giffuni off = xewtoh(layoutp[i].shdr->sh_offset); 476b5782a47SPedro F. Giffuni size = xewtoh(layoutp[i].shdr->sh_size); 477b5782a47SPedro F. Giffuni if ((size_t)xwriteatoff(fd, buf, off, size, fn) != size) 478b5782a47SPedro F. Giffuni goto bad; 479b5782a47SPedro F. Giffuni } 480b5782a47SPedro F. Giffuni } 481b5782a47SPedro F. Giffuni 4822ec21a68SJordan K. Hubbard out: 483b5782a47SPedro F. Giffuni if (layoutp != NULL) { 484e8ee1a1eSPedro F. Giffuni for (i = 0; i < shnum; i++) { 485b5782a47SPedro F. Giffuni if (layoutp[i].bufp != NULL) 486b5782a47SPedro F. Giffuni free(layoutp[i].bufp); 487b5782a47SPedro F. Giffuni } 488b5782a47SPedro F. Giffuni free(layoutp); 489b5782a47SPedro F. Giffuni } 49096acb2c4SPedro F. Giffuni free(nstrtabp); 4912ec21a68SJordan K. Hubbard return (rv); 4922ec21a68SJordan K. Hubbard 4932ec21a68SJordan K. Hubbard bad: 4942ec21a68SJordan K. Hubbard rv = 1; 4952ec21a68SJordan K. Hubbard goto out; 4962ec21a68SJordan K. Hubbard } 4972ec21a68SJordan K. Hubbard 4982ec21a68SJordan K. Hubbard #endif /* include this size of ELF */ 499