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