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 34246576Spfg__RCSID("$NetBSD: exec_elf32.c,v 1.6 1999/09/20 04:12:16 christos Exp $"); 3539172Sjkh#endif 3676224Sobrien#endif 37108440Sobrien__FBSDID("$FreeBSD$"); 3839172Sjkh 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> 48246895Spfg#include <limits.h> 4939172Sjkh#include <stdio.h> 5039172Sjkh#include <stdlib.h> 5139172Sjkh#include <string.h> 5239172Sjkh#include <unistd.h> 5339172Sjkh 5439172Sjkh#include "extern.h" 5539172Sjkh 5639172Sjkh#if (defined(NLIST_ELF32) && (ELFSIZE == 32)) || \ 5739172Sjkh (defined(NLIST_ELF64) && (ELFSIZE == 64)) 5839172Sjkh 5995781Sru#define __ELF_WORD_SIZE ELFSIZE 6095781Sru#if (ELFSIZE == 32) 6195781Sru#include <sys/elf32.h> 6297226Sru#define xewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 63112192Sru#define htoxew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 64211222Sadrian#define wewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 65211222Sadrian#define htowew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 6695781Sru#elif (ELFSIZE == 64) 6795781Sru#include <sys/elf64.h> 6897226Sru#define xewtoh(x) ((data == ELFDATA2MSB) ? be64toh(x) : le64toh(x)) 69112192Sru#define htoxew(x) ((data == ELFDATA2MSB) ? htobe64(x) : htole64(x)) 70211222Sadrian/* elf64 Elf64_Word are 32 bits */ 71211222Sadrian#define wewtoh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 72211222Sadrian#define htowew(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 7395781Sru#endif 7495781Sru#include <sys/elf_generic.h> 7539172Sjkh 7639172Sjkh#define CONCAT(x,y) __CONCAT(x,y) 7739172Sjkh#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) 7839172Sjkh#define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y)))) 7939172Sjkh#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE)) 8039172Sjkh#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) 8139172Sjkh 8297226Sru#define xe16toh(x) ((data == ELFDATA2MSB) ? be16toh(x) : le16toh(x)) 8397226Sru#define xe32toh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) 8497226Sru#define htoxe32(x) ((data == ELFDATA2MSB) ? htobe32(x) : htole32(x)) 8597226Sru 86246895Spfgstruct shlayout { 87246895Spfg Elf_Shdr *shdr; 88246895Spfg void *bufp; 8939172Sjkh}; 9039172Sjkh 9139172Sjkhstatic ssize_t 9239172Sjkhxreadatoff(int fd, void *buf, off_t off, size_t size, const char *fn) 9339172Sjkh{ 9439172Sjkh ssize_t rv; 9539172Sjkh 9639172Sjkh if (lseek(fd, off, SEEK_SET) != off) { 9739172Sjkh perror(fn); 9839172Sjkh return -1; 9939172Sjkh } 100246576Spfg if ((size_t)(rv = read(fd, buf, size)) != size) { 10139172Sjkh fprintf(stderr, "%s: read error: %s\n", fn, 10239172Sjkh rv == -1 ? strerror(errno) : "short read"); 10339172Sjkh return -1; 10439172Sjkh } 10539172Sjkh return size; 10639172Sjkh} 10739172Sjkh 10839172Sjkhstatic ssize_t 10939172Sjkhxwriteatoff(int fd, void *buf, off_t off, size_t size, const char *fn) 11039172Sjkh{ 11139172Sjkh ssize_t rv; 11239172Sjkh 11339172Sjkh if (lseek(fd, off, SEEK_SET) != off) { 11439172Sjkh perror(fn); 11539172Sjkh return -1; 11639172Sjkh } 117246576Spfg if ((size_t)(rv = write(fd, buf, size)) != size) { 11839172Sjkh fprintf(stderr, "%s: write error: %s\n", fn, 11939172Sjkh rv == -1 ? strerror(errno) : "short write"); 12039172Sjkh return -1; 12139172Sjkh } 12239172Sjkh return size; 12339172Sjkh} 12439172Sjkh 12539172Sjkhstatic void * 12639172Sjkhxmalloc(size_t size, const char *fn, const char *use) 12739172Sjkh{ 12839172Sjkh void *rv; 12939172Sjkh 13039172Sjkh rv = malloc(size); 13139172Sjkh if (rv == NULL) 13239172Sjkh fprintf(stderr, "%s: out of memory (allocating for %s)\n", 13339172Sjkh fn, use); 13439172Sjkh return (rv); 13539172Sjkh} 13639172Sjkh 137211137Sadrianstatic void * 138211137Sadrianxrealloc(void *ptr, size_t size, const char *fn, const char *use) 139211137Sadrian{ 140211137Sadrian void *rv; 141211137Sadrian 142211137Sadrian rv = realloc(ptr, size); 143211137Sadrian if (rv == NULL) { 144211137Sadrian free(ptr); 145211137Sadrian fprintf(stderr, "%s: out of memory (reallocating for %s)\n", 146211137Sadrian fn, use); 147211137Sadrian } 148211137Sadrian return (rv); 149211137Sadrian} 150211137Sadrian 15139172Sjkhint 15239172SjkhELFNAMEEND(check)(int fd, const char *fn) 15339172Sjkh{ 15439172Sjkh Elf_Ehdr eh; 15539172Sjkh struct stat sb; 15697226Sru unsigned char data; 15739172Sjkh 15839172Sjkh /* 15939172Sjkh * Check the header to maek sure it's an ELF file (of the 16039172Sjkh * appropriate size). 16139172Sjkh */ 16239172Sjkh if (fstat(fd, &sb) == -1) 16339172Sjkh return 0; 164246576Spfg if (sb.st_size < (off_t)(sizeof eh)) 16539172Sjkh return 0; 16639172Sjkh if (read(fd, &eh, sizeof eh) != sizeof eh) 16739172Sjkh return 0; 16839172Sjkh 16939172Sjkh if (IS_ELF(eh) == 0) 17039172Sjkh return 0; 17139172Sjkh 17297226Sru data = eh.e_ident[EI_DATA]; 17397226Sru 17497226Sru switch (xe16toh(eh.e_machine)) { 17539172Sjkh case EM_386: break; 17639172Sjkh case EM_ALPHA: break; 177130155Scognet#ifndef EM_ARM 178130155Scognet#define EM_ARM 40 179130155Scognet#endif 180130155Scognet case EM_ARM: break; 181182725Sobrien#ifndef EM_MIPS 182182725Sobrien#define EM_MIPS 8 183182725Sobrien#endif 184182725Sobrien#ifndef EM_MIPS_RS4_BE /* same as EM_MIPS_RS3_LE */ 185182725Sobrien#define EM_MIPS_RS4_BE 10 186182725Sobrien#endif 187182725Sobrien case EM_MIPS: break; 188182725Sobrien case /* EM_MIPS_RS3_LE */ EM_MIPS_RS4_BE: break; 189106848Sru#ifndef EM_IA_64 190106848Sru#define EM_IA_64 50 191106848Sru#endif 19297068Sru case EM_IA_64: break; 193117857Sobrien#ifndef EM_PPC 194117857Sobrien#define EM_PPC 20 195117857Sobrien#endif 196117857Sobrien case EM_PPC: break; 197209889Snwhitehorn#ifndef EM_PPC64 198209889Snwhitehorn#define EM_PPC64 21 199209889Snwhitehorn#endif 200209889Snwhitehorn case EM_PPC64: break; 201106848Sru#ifndef EM_SPARCV9 202106848Sru#define EM_SPARCV9 43 203106848Sru#endif 20497068Sru case EM_SPARCV9: break; 205115757Speter#ifndef EM_X86_64 206115757Speter#define EM_X86_64 62 207115757Speter#endif 208115757Speter case EM_X86_64: break; 20939172Sjkh/* ELFDEFNNAME(MACHDEP_ID_CASES) */ 21039172Sjkh 21139172Sjkh default: 21239172Sjkh return 0; 21339172Sjkh } 21439172Sjkh 21539172Sjkh return 1; 21639172Sjkh} 21739172Sjkh 218211137Sadrian/* 219211137Sadrian * This function 'hides' (some of) ELF executable file's symbols. 220211137Sadrian * It hides them by renaming them to "_$$hide$$ <filename> <symbolname>". 221211137Sadrian * Symbols in the global keep list, or which are marked as being undefined, 222211137Sadrian * are left alone. 223211137Sadrian * 224211137Sadrian * An old version of this code shuffled various tables around, turning 225211137Sadrian * global symbols to be hidden into local symbols. That lost on the 226211137Sadrian * mips, because CALL16 relocs must reference global symbols, and, if 227211137Sadrian * those symbols were being hidden, they were no longer global. 228211137Sadrian * 229211137Sadrian * The new renaming behaviour doesn't take global symbols out of the 230211137Sadrian * namespace. However, it's ... unlikely that there will ever be 231211137Sadrian * any collisions in practice because of the new method. 232211137Sadrian */ 23339172Sjkhint 23439172SjkhELFNAMEEND(hide)(int fd, const char *fn) 23539172Sjkh{ 23639172Sjkh Elf_Ehdr ehdr; 237246895Spfg struct shlayout *layoutp = NULL; 238246895Spfg Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr, *shstrtabshdr; 239246895Spfg Elf_Shdr shdrshdr; 24039172Sjkh Elf_Sym *symtabp = NULL; 241246895Spfg char *shstrtabp = NULL, *strtabp = NULL; 242246895Spfg Elf_Size nsyms, ewi; 243246895Spfg Elf_Off off; 24439172Sjkh ssize_t shdrsize; 245246895Spfg int rv, i, weird, l, m, r, strtabidx; 246246895Spfg size_t nstrtab_size, nstrtab_nextoff, fn_size, size; 247211137Sadrian char *nstrtabp = NULL; 24897226Sru unsigned char data; 249211137Sadrian const char *weirdreason = NULL; 250246895Spfg void *buf; 251246895Spfg Elf_Half shnum; 25239172Sjkh 25339172Sjkh rv = 0; 25439172Sjkh if (xreadatoff(fd, &ehdr, 0, sizeof ehdr, fn) != sizeof ehdr) 25539172Sjkh goto bad; 25639172Sjkh 25797226Sru data = ehdr.e_ident[EI_DATA]; 258246895Spfg shnum = xe16toh(ehdr.e_shnum); 25997226Sru 260246895Spfg shdrsize = shnum * xe16toh(ehdr.e_shentsize); 26139172Sjkh if ((shdrp = xmalloc(shdrsize, fn, "section header table")) == NULL) 26239172Sjkh goto bad; 26397226Sru if (xreadatoff(fd, shdrp, xewtoh(ehdr.e_shoff), shdrsize, fn) != 26497226Sru shdrsize) 26539172Sjkh goto bad; 26639172Sjkh 267246895Spfg symtabshdr = strtabshdr = shstrtabshdr = NULL; 26839172Sjkh weird = 0; 269246895Spfg for (i = 0; i < shnum; i++) { 27097226Sru switch (xe32toh(shdrp[i].sh_type)) { 27139172Sjkh case SHT_SYMTAB: 272246895Spfg if (symtabshdr != NULL) { 27339172Sjkh weird = 1; 274246895Spfg weirdreason = "multiple symbol tables"; 275246895Spfg } 27639172Sjkh symtabshdr = &shdrp[i]; 27797226Sru strtabshdr = &shdrp[xe32toh(shdrp[i].sh_link)]; 27839172Sjkh break; 279246895Spfg case SHT_STRTAB: 280246895Spfg if (i == xe16toh(ehdr.e_shstrndx)) 281246895Spfg shstrtabshdr = &shdrp[i]; 282246895Spfg break; 28339172Sjkh } 28439172Sjkh } 28539172Sjkh if (symtabshdr == NULL) 28639172Sjkh goto out; 287246895Spfg if (strtabshdr == NULL) { 28839172Sjkh weird = 1; 289246895Spfg weirdreason = "string table does not exist"; 290246895Spfg } 291246895Spfg if (shstrtabshdr == NULL) { 292211137Sadrian weird = 1; 293246895Spfg weirdreason = "section header string table does not exist"; 294246895Spfg } 295246895Spfg if (weirdreason == NULL) 296246895Spfg weirdreason = "unsupported"; 29739172Sjkh if (weird) { 298211137Sadrian fprintf(stderr, "%s: weird executable (%s)\n", fn, weirdreason); 29939172Sjkh goto bad; 30039172Sjkh } 30139172Sjkh 30239172Sjkh /* 303246895Spfg * sort section layout table by offset 304246895Spfg */ 305246895Spfg layoutp = xmalloc((shnum + 1) * sizeof(struct shlayout), 306246895Spfg fn, "layout table"); 307246895Spfg if (layoutp == NULL) 308246895Spfg goto bad; 309246895Spfg 310246895Spfg /* add a pseudo entry to represent the section header table */ 311246895Spfg shdrshdr.sh_offset = ehdr.e_shoff; 312246895Spfg shdrshdr.sh_size = htoxew(shdrsize); 313246895Spfg shdrshdr.sh_addralign = htoxew(ELFSIZE / 8); 314246895Spfg layoutp[shnum].shdr = &shdrshdr; 315246895Spfg 316246895Spfg /* insert and sort normal section headers */ 317246895Spfg for (i = shnum; i-- != 0;) { 318246895Spfg l = i + 1; 319246895Spfg r = shnum; 320246895Spfg while (l <= r) { 321246895Spfg m = ( l + r) / 2; 322246895Spfg if (xewtoh(shdrp[i].sh_offset) > 323246895Spfg xewtoh(layoutp[m].shdr->sh_offset)) 324246895Spfg l = m + 1; 325246895Spfg else 326246895Spfg r = m - 1; 327246895Spfg } 328246895Spfg 329246895Spfg if (r != i) { 330246895Spfg memmove(&layoutp[i], &layoutp[i + 1], 331246895Spfg sizeof(struct shlayout) * (r - i)); 332246895Spfg } 333246895Spfg 334246895Spfg layoutp[r].shdr = &shdrp[i]; 335246895Spfg layoutp[r].bufp = NULL; 336246895Spfg } 337246895Spfg ++shnum; 338246895Spfg 339246895Spfg /* 34039172Sjkh * load up everything we need 34139172Sjkh */ 34239172Sjkh 343246895Spfg /* load section string table for debug use */ 344246895Spfg if ((shstrtabp = xmalloc(xewtoh(shstrtabshdr->sh_size), fn, 345246895Spfg "section string table")) == NULL) 34639172Sjkh goto bad; 347246895Spfg if ((size_t)xreadatoff(fd, shstrtabp, xewtoh(shstrtabshdr->sh_offset), 348246895Spfg xewtoh(shstrtabshdr->sh_size), fn) != xewtoh(shstrtabshdr->sh_size)) 34939172Sjkh goto bad; 35039172Sjkh 351246895Spfg /* we need symtab, strtab, and everything behind strtab */ 352246895Spfg strtabidx = INT_MAX; 353246895Spfg for (i = 0; i < shnum; i++) { 354246895Spfg if (layoutp[i].shdr == &shdrshdr) { 355246895Spfg /* not load section header again */ 356246895Spfg layoutp[i].bufp = shdrp; 357246895Spfg continue; 358246895Spfg } 359246895Spfg if (layoutp[i].shdr == shstrtabshdr) { 360246895Spfg /* not load section string table again */ 361246895Spfg layoutp[i].bufp = shstrtabp; 362246895Spfg continue; 363246895Spfg } 36439172Sjkh 365246895Spfg if (layoutp[i].shdr == strtabshdr) 366246895Spfg strtabidx = i; 367246895Spfg if (layoutp[i].shdr == symtabshdr || i >= strtabidx) { 368246895Spfg off = xewtoh(layoutp[i].shdr->sh_offset); 369246895Spfg size = xewtoh(layoutp[i].shdr->sh_size); 370246895Spfg layoutp[i].bufp = xmalloc(size, fn, 371246895Spfg shstrtabp + xewtoh(layoutp[i].shdr->sh_name)); 372246895Spfg if (layoutp[i].bufp == NULL) 373246895Spfg goto bad; 374246895Spfg if ((size_t)xreadatoff(fd, layoutp[i].bufp, off, size, fn) != 375246895Spfg size) 376246895Spfg goto bad; 377246895Spfg 378246895Spfg /* set symbol table and string table */ 379246895Spfg if (layoutp[i].shdr == symtabshdr) 380246895Spfg symtabp = layoutp[i].bufp; 381246895Spfg else if (layoutp[i].shdr == strtabshdr) 382246895Spfg strtabp = layoutp[i].bufp; 383246895Spfg } 384246895Spfg } 385246895Spfg 386211137Sadrian nstrtab_size = 256; 387211137Sadrian nstrtabp = xmalloc(nstrtab_size, fn, "new string table"); 388211137Sadrian if (nstrtabp == NULL) 389211137Sadrian goto bad; 390211137Sadrian nstrtab_nextoff = 0; 39139172Sjkh 392211137Sadrian fn_size = strlen(fn); 39339172Sjkh 39439172Sjkh /* Prepare data structures for symbol movement. */ 39597226Sru nsyms = xewtoh(symtabshdr->sh_size) / xewtoh(symtabshdr->sh_entsize); 39639172Sjkh 39739172Sjkh /* move symbols, making them local */ 398211137Sadrian for (ewi = 0; ewi < nsyms; ewi++) { 399211137Sadrian Elf_Sym *sp = &symtabp[ewi]; 400211137Sadrian const char *symname = strtabp + xe32toh(sp->st_name); 401211137Sadrian size_t newent_len; 40239172Sjkh /* 403211137Sadrian * make sure there's size for the next entry, even if it's 404211137Sadrian * as large as it can be. 405211137Sadrian * 406211137Sadrian * "_$$hide$$ <filename> <symname><NUL>" -> 407211137Sadrian * 9 + 3 + sizes of fn and sym name 40839172Sjkh */ 409211137Sadrian while ((nstrtab_size - nstrtab_nextoff) < 410211137Sadrian strlen(symname) + fn_size + 12) { 411211137Sadrian nstrtab_size *= 2; 412211137Sadrian nstrtabp = xrealloc(nstrtabp, nstrtab_size, fn, 413211137Sadrian "new string table"); 414211137Sadrian if (nstrtabp == NULL) 415211137Sadrian goto bad; 41639172Sjkh } 41739172Sjkh 418211222Sadrian sp->st_name = htowew(nstrtab_nextoff); 41939172Sjkh 420211137Sadrian /* if it's a keeper or is undefined, don't rename it. */ 421211137Sadrian if (in_keep_list(symname) || 422211137Sadrian (xe16toh(sp->st_shndx) == SHN_UNDEF)) { 423211137Sadrian newent_len = sprintf(nstrtabp + nstrtab_nextoff, 424211137Sadrian "%s", symname) + 1; 425211137Sadrian } else { 426211137Sadrian newent_len = sprintf(nstrtabp + nstrtab_nextoff, 427211137Sadrian "_$$hide$$ %s %s", fn, symname) + 1; 42839172Sjkh } 429211137Sadrian nstrtab_nextoff += newent_len; 43039172Sjkh } 431211137Sadrian strtabshdr->sh_size = htoxew(nstrtab_nextoff); 43239172Sjkh 43339172Sjkh /* 434246895Spfg * update section header table in ascending order of offset 43539172Sjkh */ 436246895Spfg for (i = strtabidx + 1; i < shnum; i++) { 437246895Spfg Elf_Off off, align; 438246895Spfg off = xewtoh(layoutp[i - 1].shdr->sh_offset) + 439246895Spfg xewtoh(layoutp[i - 1].shdr->sh_size); 440246895Spfg align = xewtoh(layoutp[i].shdr->sh_addralign); 441246895Spfg off = (off + (align - 1)) & ~(align - 1); 442246895Spfg layoutp[i].shdr->sh_offset = htoxew(off); 443246895Spfg } 44439172Sjkh 445246895Spfg /* 446246895Spfg * write data to the file in descending order of offset 447246895Spfg */ 448246895Spfg for (i = shnum; i-- != 0;) { 449246895Spfg if (layoutp[i].shdr == strtabshdr) { 450246895Spfg /* new string table */ 451246895Spfg buf = nstrtabp; 452246895Spfg } else 453246895Spfg buf = layoutp[i].bufp; 454246895Spfg 455246895Spfg if (layoutp[i].shdr == &shdrshdr || 456246895Spfg layoutp[i].shdr == symtabshdr || i >= strtabidx) { 457246895Spfg if (buf == NULL) 458246895Spfg goto bad; 459246895Spfg 460246895Spfg /* 461246895Spfg * update the offset of section header table in elf 462246895Spfg * header if needed. 463246895Spfg */ 464246895Spfg if (layoutp[i].shdr == &shdrshdr && 465246895Spfg ehdr.e_shoff != shdrshdr.sh_offset) { 466246895Spfg ehdr.e_shoff = shdrshdr.sh_offset; 467246895Spfg off = (ELFSIZE == 32) ? 32 : 44; 468246895Spfg size = sizeof(Elf_Off); 469246895Spfg if ((size_t)xwriteatoff(fd, &ehdr.e_shoff, off, size, 470246895Spfg fn) != size) 471246895Spfg goto bad; 472246895Spfg } 473246895Spfg 474246895Spfg off = xewtoh(layoutp[i].shdr->sh_offset); 475246895Spfg size = xewtoh(layoutp[i].shdr->sh_size); 476246895Spfg if ((size_t)xwriteatoff(fd, buf, off, size, fn) != size) 477246895Spfg goto bad; 478246895Spfg } 479246895Spfg } 480246895Spfg 48139172Sjkhout: 482246895Spfg if (layoutp != NULL) { 483246895Spfg for (i = 0; i < shnum; i++) { 484246895Spfg if (layoutp[i].bufp != NULL) 485246895Spfg free(layoutp[i].bufp); 486246895Spfg } 487246895Spfg free(layoutp); 488246895Spfg } 489246895Spfg free(nstrtabp); 49039172Sjkh return (rv); 49139172Sjkh 49239172Sjkhbad: 49339172Sjkh rv = 1; 49439172Sjkh goto out; 49539172Sjkh} 49639172Sjkh 49739172Sjkh#endif /* include this size of ELF */ 498