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