139172Sjkh/* 239172Sjkh * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. 339172Sjkh * 439172Sjkh * Redistribution and use in source and binary forms, with or without 539172Sjkh * modification, are permitted provided that the following conditions 639172Sjkh * are met: 739172Sjkh * 1. Redistributions of source code must retain the above copyright 839172Sjkh * notice, this list of conditions and the following disclaimer. 939172Sjkh * 2. Redistributions in binary form must reproduce the above copyright 1039172Sjkh * notice, this list of conditions and the following disclaimer in the 1139172Sjkh * documentation and/or other materials provided with the distribution. 1239172Sjkh * 3. All advertising materials mentioning features or use of this software 1339172Sjkh * must display the following acknowledgement: 1439172Sjkh * This product includes software developed by Christopher G. Demetriou 1539172Sjkh * for the NetBSD Project. 1639172Sjkh * 4. The name of the author may not be used to endorse or promote products 1739172Sjkh * derived from this software without specific prior written permission 1839172Sjkh * 1939172Sjkh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2039172Sjkh * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2139172Sjkh * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2239172Sjkh * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2339172Sjkh * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2439172Sjkh * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2539172Sjkh * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2639172Sjkh * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2739172Sjkh * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2839172Sjkh * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2939172Sjkh */ 3039172Sjkh 3139172Sjkh#include <sys/cdefs.h> 3239172Sjkh#ifndef lint 3376224Sobrien#if 0 34246256Spfg__RCSID("$NetBSD: exec_elf32.c,v 1.6 1999/09/20 04:12:16 christos Exp $"); 3539172Sjkh#endif 3676224Sobrien#endif 37108440Sobrien__FBSDID("$FreeBSD: stable/10/usr.sbin/crunch/crunchide/exec_elf32.c 309077 2016-11-24 00:46:34Z emaste $"); 38308804Semaste 3939172Sjkh#ifndef ELFSIZE 4039172Sjkh#define ELFSIZE 32 4139172Sjkh#endif 4239172Sjkh 4339172Sjkh#include <sys/types.h> 44112767Sobrien#include <sys/endian.h> 4539172Sjkh#include <sys/stat.h> 4639172Sjkh 4739172Sjkh#include <errno.h> 48246296Spfg#include <limits.h> 49277557Semaste#include <stddef.h> 5039172Sjkh#include <stdio.h> 5139172Sjkh#include <stdlib.h> 5239172Sjkh#include <string.h> 5339172Sjkh#include <unistd.h> 5439172Sjkh 5539172Sjkh#include "extern.h" 5639172Sjkh 5739172Sjkh#if (defined(NLIST_ELF32) && (ELFSIZE == 32)) || \ 5839172Sjkh (defined(NLIST_ELF64) && (ELFSIZE == 64)) 5939172Sjkh 6095781Sru#define __ELF_WORD_SIZE ELFSIZE 6195781Sru#if (ELFSIZE == 32) 6295781Sru#include <sys/elf32.h> 6397226Sru#define xewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 64112192Sru#define htoxew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 65211222Sadrian#define wewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 66211222Sadrian#define htowew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 6795781Sru#elif (ELFSIZE == 64) 6895781Sru#include <sys/elf64.h> 6997226Sru#define xewtoh(x) ((data == ELFDATA2MSB) ? be64toh(x) : le64toh(x)) 70112192Sru#define htoxew(x) ((data == ELFDATA2MSB) ? htobe64(x) : htole64(x)) 71211222Sadrian/* elf64 Elf64_Word are 32 bits */ 72211222Sadrian#define wewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 73211222Sadrian#define htowew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 7495781Sru#endif 7595781Sru#include <sys/elf_generic.h> 7639172Sjkh 7739172Sjkh#define CONCAT(x,y) __CONCAT(x,y) 7839172Sjkh#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) 7939172Sjkh#define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y)))) 8039172Sjkh#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE)) 8139172Sjkh#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) 82292423Semaste#ifndef ELFCLASS 83292423Semaste#define ELFCLASS CONCAT(ELFCLASS,ELFSIZE) 84292423Semaste#endif 8539172Sjkh 8697226Sru#define xe16toh(x) ((data == ELFDATA2MSB) ? be16toh(x) : le16toh(x)) 8797226Sru#define xe32toh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 8897226Sru#define htoxe32(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 8997226Sru 90246296Spfgstruct shlayout { 91246296Spfg Elf_Shdr *shdr; 92246296Spfg void *bufp; 9339172Sjkh}; 9439172Sjkh 9539172Sjkhstatic ssize_t 9639172Sjkhxreadatoff(int fd, void *buf, off_t off, size_t size, const char *fn) 9739172Sjkh{ 9839172Sjkh ssize_t rv; 9939172Sjkh 10039172Sjkh if (lseek(fd, off, SEEK_SET) != off) { 10139172Sjkh perror(fn); 10239172Sjkh return -1; 10339172Sjkh } 104246256Spfg if ((size_t)(rv = read(fd, buf, size)) != size) { 10539172Sjkh fprintf(stderr, "%s: read error: %s\n", fn, 10639172Sjkh rv == -1 ? strerror(errno) : "short read"); 10739172Sjkh return -1; 10839172Sjkh } 10939172Sjkh return size; 11039172Sjkh} 11139172Sjkh 11239172Sjkhstatic ssize_t 11339172Sjkhxwriteatoff(int fd, void *buf, off_t off, size_t size, const char *fn) 11439172Sjkh{ 11539172Sjkh ssize_t rv; 11639172Sjkh 11739172Sjkh if (lseek(fd, off, SEEK_SET) != off) { 11839172Sjkh perror(fn); 11939172Sjkh return -1; 12039172Sjkh } 121246256Spfg if ((size_t)(rv = write(fd, buf, size)) != size) { 12239172Sjkh fprintf(stderr, "%s: write error: %s\n", fn, 12339172Sjkh rv == -1 ? strerror(errno) : "short write"); 12439172Sjkh return -1; 12539172Sjkh } 12639172Sjkh return size; 12739172Sjkh} 12839172Sjkh 12939172Sjkhstatic void * 13039172Sjkhxmalloc(size_t size, const char *fn, const char *use) 13139172Sjkh{ 13239172Sjkh void *rv; 13339172Sjkh 13439172Sjkh rv = malloc(size); 13539172Sjkh if (rv == NULL) 13639172Sjkh fprintf(stderr, "%s: out of memory (allocating for %s)\n", 13739172Sjkh fn, use); 13839172Sjkh return (rv); 13939172Sjkh} 14039172Sjkh 141211137Sadrianstatic void * 142211137Sadrianxrealloc(void *ptr, size_t size, const char *fn, const char *use) 143211137Sadrian{ 144211137Sadrian void *rv; 145308804Semaste 146211137Sadrian rv = realloc(ptr, size); 147211137Sadrian if (rv == NULL) { 148211137Sadrian free(ptr); 149211137Sadrian fprintf(stderr, "%s: out of memory (reallocating for %s)\n", 150211137Sadrian fn, use); 151211137Sadrian } 152211137Sadrian return (rv); 153308804Semaste} 154211137Sadrian 15539172Sjkhint 15639172SjkhELFNAMEEND(check)(int fd, const char *fn) 15739172Sjkh{ 15839172Sjkh Elf_Ehdr eh; 15939172Sjkh struct stat sb; 16097226Sru unsigned char data; 16139172Sjkh 16239172Sjkh /* 16339172Sjkh * Check the header to maek sure it's an ELF file (of the 16439172Sjkh * appropriate size). 16539172Sjkh */ 16639172Sjkh if (fstat(fd, &sb) == -1) 16739172Sjkh return 0; 168246256Spfg if (sb.st_size < (off_t)(sizeof eh)) 16939172Sjkh return 0; 17039172Sjkh if (read(fd, &eh, sizeof eh) != sizeof eh) 17139172Sjkh return 0; 17239172Sjkh 173292423Semaste if (IS_ELF(eh) == 0 || eh.e_ident[EI_CLASS] != ELFCLASS) 17439172Sjkh return 0; 17539172Sjkh 17697226Sru data = eh.e_ident[EI_DATA]; 17797226Sru 17897226Sru switch (xe16toh(eh.e_machine)) { 17939172Sjkh case EM_386: break; 18039172Sjkh case EM_ALPHA: break; 181292421Semaste#ifndef EM_AARCH64 182292421Semaste#define EM_AARCH64 183 183130155Scognet#endif 184292421Semaste case EM_AARCH64: break; 185130155Scognet case EM_ARM: break; 186292885Semaste case EM_IA_64: break; 187182725Sobrien case EM_MIPS: break; 188182725Sobrien case /* EM_MIPS_RS3_LE */ EM_MIPS_RS4_BE: break; 189117857Sobrien case EM_PPC: break; 190209889Snwhitehorn case EM_PPC64: break; 191292421Semaste#ifndef EM_RISCV 192292421Semaste#define EM_RISCV 243 193106848Sru#endif 194292421Semaste case EM_RISCV: break; 19597068Sru case EM_SPARCV9: break; 196115757Speter case EM_X86_64: break; 19739172Sjkh/* ELFDEFNNAME(MACHDEP_ID_CASES) */ 19839172Sjkh 19939172Sjkh default: 20039172Sjkh return 0; 20139172Sjkh } 20239172Sjkh 20339172Sjkh return 1; 20439172Sjkh} 20539172Sjkh 206211137Sadrian/* 207211137Sadrian * This function 'hides' (some of) ELF executable file's symbols. 208211137Sadrian * It hides them by renaming them to "_$$hide$$ <filename> <symbolname>". 209211137Sadrian * Symbols in the global keep list, or which are marked as being undefined, 210211137Sadrian * are left alone. 211211137Sadrian * 212211137Sadrian * An old version of this code shuffled various tables around, turning 213211137Sadrian * global symbols to be hidden into local symbols. That lost on the 214211137Sadrian * mips, because CALL16 relocs must reference global symbols, and, if 215211137Sadrian * those symbols were being hidden, they were no longer global. 216211137Sadrian * 217211137Sadrian * The new renaming behaviour doesn't take global symbols out of the 218211137Sadrian * namespace. However, it's ... unlikely that there will ever be 219211137Sadrian * any collisions in practice because of the new method. 220211137Sadrian */ 22139172Sjkhint 22239172SjkhELFNAMEEND(hide)(int fd, const char *fn) 22339172Sjkh{ 22439172Sjkh Elf_Ehdr ehdr; 225246296Spfg struct shlayout *layoutp = NULL; 226246296Spfg Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr, *shstrtabshdr; 227246296Spfg Elf_Shdr shdrshdr; 22839172Sjkh Elf_Sym *symtabp = NULL; 229246296Spfg char *shstrtabp = NULL, *strtabp = NULL; 230246296Spfg Elf_Size nsyms, ewi; 231246296Spfg Elf_Off off; 23239172Sjkh ssize_t shdrsize; 233246296Spfg int rv, i, weird, l, m, r, strtabidx; 234246296Spfg size_t nstrtab_size, nstrtab_nextoff, fn_size, size; 235211137Sadrian char *nstrtabp = NULL; 23697226Sru unsigned char data; 237211137Sadrian const char *weirdreason = NULL; 238246296Spfg void *buf; 239246298Spfg Elf_Half shnum; 24039172Sjkh 24139172Sjkh rv = 0; 24239172Sjkh if (xreadatoff(fd, &ehdr, 0, sizeof ehdr, fn) != sizeof ehdr) 24339172Sjkh goto bad; 24439172Sjkh 24597226Sru data = ehdr.e_ident[EI_DATA]; 246246298Spfg shnum = xe16toh(ehdr.e_shnum); 24797226Sru 248246298Spfg shdrsize = shnum * xe16toh(ehdr.e_shentsize); 24939172Sjkh if ((shdrp = xmalloc(shdrsize, fn, "section header table")) == NULL) 25039172Sjkh goto bad; 25197226Sru if (xreadatoff(fd, shdrp, xewtoh(ehdr.e_shoff), shdrsize, fn) != 25297226Sru shdrsize) 25339172Sjkh goto bad; 25439172Sjkh 255246296Spfg symtabshdr = strtabshdr = shstrtabshdr = NULL; 25639172Sjkh weird = 0; 257246298Spfg for (i = 0; i < shnum; i++) { 25897226Sru switch (xe32toh(shdrp[i].sh_type)) { 25939172Sjkh case SHT_SYMTAB: 260246296Spfg if (symtabshdr != NULL) { 26139172Sjkh weird = 1; 262246296Spfg weirdreason = "multiple symbol tables"; 263246296Spfg } 26439172Sjkh symtabshdr = &shdrp[i]; 26597226Sru strtabshdr = &shdrp[xe32toh(shdrp[i].sh_link)]; 26639172Sjkh break; 267246296Spfg case SHT_STRTAB: 268246296Spfg if (i == xe16toh(ehdr.e_shstrndx)) 269246296Spfg shstrtabshdr = &shdrp[i]; 270246296Spfg break; 27139172Sjkh } 27239172Sjkh } 27339172Sjkh if (symtabshdr == NULL) 27439172Sjkh goto out; 275246296Spfg if (strtabshdr == NULL) { 27639172Sjkh weird = 1; 277246296Spfg weirdreason = "string table does not exist"; 278246296Spfg } 279246296Spfg if (shstrtabshdr == NULL) { 280211137Sadrian weird = 1; 281246296Spfg weirdreason = "section header string table does not exist"; 282246296Spfg } 283309077Semaste if (strtabshdr == shstrtabshdr) { 284309077Semaste weird = 1; 285309077Semaste weirdreason = "combined strtab and shstrtab not supported"; 286309077Semaste } 287246296Spfg if (weirdreason == NULL) 288246296Spfg weirdreason = "unsupported"; 28939172Sjkh if (weird) { 290211137Sadrian fprintf(stderr, "%s: weird executable (%s)\n", fn, weirdreason); 29139172Sjkh goto bad; 29239172Sjkh } 29339172Sjkh 29439172Sjkh /* 295246296Spfg * sort section layout table by offset 296246296Spfg */ 297246298Spfg layoutp = xmalloc((shnum + 1) * sizeof(struct shlayout), 298246296Spfg fn, "layout table"); 299246296Spfg if (layoutp == NULL) 300246296Spfg goto bad; 301246296Spfg 302246296Spfg /* add a pseudo entry to represent the section header table */ 303246296Spfg shdrshdr.sh_offset = ehdr.e_shoff; 304246296Spfg shdrshdr.sh_size = htoxew(shdrsize); 305246296Spfg shdrshdr.sh_addralign = htoxew(ELFSIZE / 8); 306246298Spfg layoutp[shnum].shdr = &shdrshdr; 307246296Spfg 308246296Spfg /* insert and sort normal section headers */ 309246298Spfg for (i = shnum; i-- != 0;) { 310246296Spfg l = i + 1; 311246298Spfg r = shnum; 312246296Spfg while (l <= r) { 313246296Spfg m = ( l + r) / 2; 314246296Spfg if (xewtoh(shdrp[i].sh_offset) > 315246296Spfg xewtoh(layoutp[m].shdr->sh_offset)) 316246296Spfg l = m + 1; 317246296Spfg else 318246296Spfg r = m - 1; 319246296Spfg } 320246296Spfg 321246296Spfg if (r != i) { 322246296Spfg memmove(&layoutp[i], &layoutp[i + 1], 323246296Spfg sizeof(struct shlayout) * (r - i)); 324246296Spfg } 325246296Spfg 326246296Spfg layoutp[r].shdr = &shdrp[i]; 327246296Spfg layoutp[r].bufp = NULL; 328246296Spfg } 329246298Spfg ++shnum; 330246296Spfg 331246296Spfg /* 33239172Sjkh * load up everything we need 33339172Sjkh */ 33439172Sjkh 335246296Spfg /* load section string table for debug use */ 336283260Semaste if ((size = xewtoh(shstrtabshdr->sh_size)) == 0) 33739172Sjkh goto bad; 338283260Semaste if ((shstrtabp = xmalloc(size, fn, "section string table")) == NULL) 339283260Semaste goto bad; 340246296Spfg if ((size_t)xreadatoff(fd, shstrtabp, xewtoh(shstrtabshdr->sh_offset), 341283260Semaste size, fn) != size) 34239172Sjkh goto bad; 343283260Semaste if (shstrtabp[size - 1] != '\0') 344283260Semaste goto bad; 34539172Sjkh 346246296Spfg /* we need symtab, strtab, and everything behind strtab */ 347246296Spfg strtabidx = INT_MAX; 348246298Spfg for (i = 0; i < shnum; i++) { 349246296Spfg if (layoutp[i].shdr == &shdrshdr) { 350246296Spfg /* not load section header again */ 351246296Spfg layoutp[i].bufp = shdrp; 352246296Spfg continue; 353246296Spfg } 354246296Spfg if (layoutp[i].shdr == shstrtabshdr) { 355246296Spfg /* not load section string table again */ 356246296Spfg layoutp[i].bufp = shstrtabp; 357246296Spfg continue; 358246296Spfg } 35939172Sjkh 360246296Spfg if (layoutp[i].shdr == strtabshdr) 361246296Spfg strtabidx = i; 362246296Spfg if (layoutp[i].shdr == symtabshdr || i >= strtabidx) { 363246296Spfg off = xewtoh(layoutp[i].shdr->sh_offset); 364283260Semaste if ((size = xewtoh(layoutp[i].shdr->sh_size)) == 0) 365283260Semaste goto bad; 366246296Spfg layoutp[i].bufp = xmalloc(size, fn, 367246296Spfg shstrtabp + xewtoh(layoutp[i].shdr->sh_name)); 368246296Spfg if (layoutp[i].bufp == NULL) 369246296Spfg goto bad; 370246296Spfg if ((size_t)xreadatoff(fd, layoutp[i].bufp, off, size, fn) != 371246296Spfg size) 372246296Spfg goto bad; 373246296Spfg 374246296Spfg /* set symbol table and string table */ 375283260Semaste if (layoutp[i].shdr == symtabshdr) { 376246296Spfg symtabp = layoutp[i].bufp; 377283260Semaste } else if (layoutp[i].shdr == strtabshdr) { 378246296Spfg strtabp = layoutp[i].bufp; 379283260Semaste if (strtabp[size - 1] != '\0') 380283260Semaste goto bad; 381283260Semaste } 382246296Spfg } 383246296Spfg } 384246296Spfg 385211137Sadrian nstrtab_size = 256; 386211137Sadrian nstrtabp = xmalloc(nstrtab_size, fn, "new string table"); 387211137Sadrian if (nstrtabp == NULL) 388211137Sadrian goto bad; 389211137Sadrian nstrtab_nextoff = 0; 39039172Sjkh 391211137Sadrian fn_size = strlen(fn); 39239172Sjkh 39339172Sjkh /* Prepare data structures for symbol movement. */ 39497226Sru nsyms = xewtoh(symtabshdr->sh_size) / xewtoh(symtabshdr->sh_entsize); 39539172Sjkh 39639172Sjkh /* move symbols, making them local */ 397211137Sadrian for (ewi = 0; ewi < nsyms; ewi++) { 398211137Sadrian Elf_Sym *sp = &symtabp[ewi]; 399211137Sadrian const char *symname = strtabp + xe32toh(sp->st_name); 400211137Sadrian size_t newent_len; 40139172Sjkh /* 402211137Sadrian * make sure there's size for the next entry, even if it's 403211137Sadrian * as large as it can be. 404211137Sadrian * 405211137Sadrian * "_$$hide$$ <filename> <symname><NUL>" -> 406211137Sadrian * 9 + 3 + sizes of fn and sym name 40739172Sjkh */ 408211137Sadrian while ((nstrtab_size - nstrtab_nextoff) < 409211137Sadrian strlen(symname) + fn_size + 12) { 410211137Sadrian nstrtab_size *= 2; 411211137Sadrian nstrtabp = xrealloc(nstrtabp, nstrtab_size, fn, 412211137Sadrian "new string table"); 413211137Sadrian if (nstrtabp == NULL) 414211137Sadrian goto bad; 41539172Sjkh } 41639172Sjkh 417211222Sadrian sp->st_name = htowew(nstrtab_nextoff); 41839172Sjkh 419211137Sadrian /* if it's a keeper or is undefined, don't rename it. */ 420211137Sadrian if (in_keep_list(symname) || 421211137Sadrian (xe16toh(sp->st_shndx) == SHN_UNDEF)) { 422211137Sadrian newent_len = sprintf(nstrtabp + nstrtab_nextoff, 423211137Sadrian "%s", symname) + 1; 424211137Sadrian } else { 425211137Sadrian newent_len = sprintf(nstrtabp + nstrtab_nextoff, 426211137Sadrian "_$$hide$$ %s %s", fn, symname) + 1; 42739172Sjkh } 428211137Sadrian nstrtab_nextoff += newent_len; 42939172Sjkh } 430211137Sadrian strtabshdr->sh_size = htoxew(nstrtab_nextoff); 43139172Sjkh 43239172Sjkh /* 433246296Spfg * update section header table in ascending order of offset 43439172Sjkh */ 435246298Spfg for (i = strtabidx + 1; i < shnum; i++) { 436246296Spfg Elf_Off off, align; 437246296Spfg off = xewtoh(layoutp[i - 1].shdr->sh_offset) + 438246296Spfg xewtoh(layoutp[i - 1].shdr->sh_size); 439246296Spfg align = xewtoh(layoutp[i].shdr->sh_addralign); 440246296Spfg off = (off + (align - 1)) & ~(align - 1); 441246296Spfg layoutp[i].shdr->sh_offset = htoxew(off); 442246296Spfg } 44339172Sjkh 444246296Spfg /* 445246296Spfg * write data to the file in descending order of offset 446246296Spfg */ 447246298Spfg for (i = shnum; i-- != 0;) { 448246296Spfg if (layoutp[i].shdr == strtabshdr) { 449246296Spfg /* new string table */ 450246296Spfg buf = nstrtabp; 451246296Spfg } else 452246296Spfg buf = layoutp[i].bufp; 453246296Spfg 454246296Spfg if (layoutp[i].shdr == &shdrshdr || 455246296Spfg layoutp[i].shdr == symtabshdr || i >= strtabidx) { 456246296Spfg if (buf == NULL) 457246296Spfg goto bad; 458246296Spfg 459246296Spfg /* 460246296Spfg * update the offset of section header table in elf 461246296Spfg * header if needed. 462246296Spfg */ 463246296Spfg if (layoutp[i].shdr == &shdrshdr && 464246296Spfg ehdr.e_shoff != shdrshdr.sh_offset) { 465246296Spfg ehdr.e_shoff = shdrshdr.sh_offset; 466277557Semaste off = offsetof(Elf_Ehdr, e_shoff); 467246296Spfg size = sizeof(Elf_Off); 468246296Spfg if ((size_t)xwriteatoff(fd, &ehdr.e_shoff, off, size, 469246296Spfg fn) != size) 470246296Spfg goto bad; 471246296Spfg } 472246296Spfg 473246296Spfg off = xewtoh(layoutp[i].shdr->sh_offset); 474246296Spfg size = xewtoh(layoutp[i].shdr->sh_size); 475246296Spfg if ((size_t)xwriteatoff(fd, buf, off, size, fn) != size) 476246296Spfg goto bad; 477246296Spfg } 478246296Spfg } 479246296Spfg 48039172Sjkhout: 481246296Spfg if (layoutp != NULL) { 482246298Spfg for (i = 0; i < shnum; i++) { 483246296Spfg if (layoutp[i].bufp != NULL) 484246296Spfg free(layoutp[i].bufp); 485246296Spfg } 486246296Spfg free(layoutp); 487246296Spfg } 488246296Spfg free(nstrtabp); 48939172Sjkh return (rv); 49039172Sjkh 49139172Sjkhbad: 49239172Sjkh rv = 1; 49339172Sjkh goto out; 49439172Sjkh} 49539172Sjkh 49639172Sjkh#endif /* include this size of ELF */ 497