17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57257d1b4Sraf  * Common Development and Distribution License (the "License").
67257d1b4Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate /*
237257d1b4Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277257d1b4Sraf /*	Copyright (c) 1988 AT&T	*/
287257d1b4Sraf /*	  All Rights Reserved  	*/
297257d1b4Sraf 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * This stuff used to live in cook.c, but was moved out to
327c478bd9Sstevel@tonic-gate  * facilitate dual (Elf32 and Elf64) compilation.  See block
337c478bd9Sstevel@tonic-gate  * comment in cook.c for more info.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <string.h>
377c478bd9Sstevel@tonic-gate #include <ar.h>
387c478bd9Sstevel@tonic-gate #include <stdlib.h>
397c478bd9Sstevel@tonic-gate #include <errno.h>
4098cadd32SRichard Lowe #include <sys/sysmacros.h>
417c478bd9Sstevel@tonic-gate #include "decl.h"
427c478bd9Sstevel@tonic-gate #include "member.h"
437c478bd9Sstevel@tonic-gate #include "msg.h"
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * This module is compiled twice, the second time having
477c478bd9Sstevel@tonic-gate  * -D_ELF64 defined.  The following set of macros, along
487c478bd9Sstevel@tonic-gate  * with machelf.h, represent the differences between the
497c478bd9Sstevel@tonic-gate  * two compilations.  Be careful *not* to add any class-
507c478bd9Sstevel@tonic-gate  * dependent code (anything that has elf32 or elf64 in the
517c478bd9Sstevel@tonic-gate  * name) to this code without hiding it behind a switch-
527c478bd9Sstevel@tonic-gate  * able macro like these.
537c478bd9Sstevel@tonic-gate  */
547c478bd9Sstevel@tonic-gate #if	defined(_ELF64)
557c478bd9Sstevel@tonic-gate #define	Snode		Snode64
567c478bd9Sstevel@tonic-gate #define	ELFCLASS	ELFCLASS64
577c478bd9Sstevel@tonic-gate #define	ElfField	Elf64
587c478bd9Sstevel@tonic-gate #define	_elf_snode_init	_elf64_snode_init
597c478bd9Sstevel@tonic-gate #define	_elf_prepscan	_elf64_prepscan
607c478bd9Sstevel@tonic-gate #define	_elf_cookscn	_elf64_cookscn
617c478bd9Sstevel@tonic-gate #define	_elf_mtype	_elf64_mtype
627c478bd9Sstevel@tonic-gate #define	_elf_msize	_elf64_msize
637c478bd9Sstevel@tonic-gate #define	elf_fsize	elf64_fsize
647c478bd9Sstevel@tonic-gate #define	_elf_snode	_elf64_snode
657c478bd9Sstevel@tonic-gate #define	_elf_ehdr	_elf64_ehdr
667c478bd9Sstevel@tonic-gate #define	elf_xlatetom	elf64_xlatetom
677c478bd9Sstevel@tonic-gate #define	_elf_phdr	_elf64_phdr
687c478bd9Sstevel@tonic-gate #define	_elf_shdr	_elf64_shdr
697c478bd9Sstevel@tonic-gate #define	_elf_prepscn	_elf64_prepscn
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate #else  /* Elf32 */
727c478bd9Sstevel@tonic-gate #define	Snode		Snode32
737c478bd9Sstevel@tonic-gate #define	ELFCLASS	ELFCLASS32
747c478bd9Sstevel@tonic-gate #define	ElfField	Elf32
757c478bd9Sstevel@tonic-gate #define	_elf_snode_init	_elf32_snode_init
767c478bd9Sstevel@tonic-gate #define	_elf_prepscan	_elf32_prepscan
777c478bd9Sstevel@tonic-gate #define	_elf_cookscn	_elf32_cookscn
787c478bd9Sstevel@tonic-gate #define	_elf_mtype	_elf32_mtype
797c478bd9Sstevel@tonic-gate #define	_elf_msize	_elf32_msize
807c478bd9Sstevel@tonic-gate #define	elf_fsize	elf32_fsize
817c478bd9Sstevel@tonic-gate #define	_elf_snode	_elf32_snode
827c478bd9Sstevel@tonic-gate #define	_elf_ehdr	_elf32_ehdr
837c478bd9Sstevel@tonic-gate #define	elf_xlatetom	elf32_xlatetom
847c478bd9Sstevel@tonic-gate #define	_elf_phdr	_elf32_phdr
857c478bd9Sstevel@tonic-gate #define	_elf_shdr	_elf32_shdr
867c478bd9Sstevel@tonic-gate #define	_elf_prepscn	_elf32_prepscn
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #endif /* _ELF64 */
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate static Okay
_elf_prepscn(Elf * elf,size_t cnt)927c478bd9Sstevel@tonic-gate _elf_prepscn(Elf *elf, size_t cnt)
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate 	Elf_Scn *	s;
957c478bd9Sstevel@tonic-gate 	Elf_Scn *	end;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	if (cnt == 0)
987c478bd9Sstevel@tonic-gate 		return (OK_YES);
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	if ((s = malloc(cnt * sizeof (Elf_Scn))) == 0) {
1017c478bd9Sstevel@tonic-gate 		_elf_seterr(EMEM_SCN, errno);
1027c478bd9Sstevel@tonic-gate 		return (OK_NO);
1037c478bd9Sstevel@tonic-gate 	}
1047c478bd9Sstevel@tonic-gate 	elf->ed_scntabsz = cnt;
1057c478bd9Sstevel@tonic-gate 	end = s + cnt;
1067c478bd9Sstevel@tonic-gate 	elf->ed_hdscn = s;
1077c478bd9Sstevel@tonic-gate 	do {
1087c478bd9Sstevel@tonic-gate 		*s = _elf_snode_init.sb_scn;
1097c478bd9Sstevel@tonic-gate 		s->s_elf = elf;
1107c478bd9Sstevel@tonic-gate 		s->s_next = s + 1;
1117c478bd9Sstevel@tonic-gate 		s->s_index = s - elf->ed_hdscn;
1127c478bd9Sstevel@tonic-gate 		s->s_shdr = (Shdr*)s->s_elf->ed_shdr + s->s_index;
1137c478bd9Sstevel@tonic-gate 		ELFMUTEXINIT(&s->s_mutex);
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 		/*
1167c478bd9Sstevel@tonic-gate 		 * Section has not yet been cooked!
1177c478bd9Sstevel@tonic-gate 		 *
1187c478bd9Sstevel@tonic-gate 		 * We don't cook a section until it's data is actually
1197c478bd9Sstevel@tonic-gate 		 * referenced.
1207c478bd9Sstevel@tonic-gate 		 */
1217c478bd9Sstevel@tonic-gate 		s->s_myflags = 0;
1227c478bd9Sstevel@tonic-gate 	} while (++s < end);
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	elf->ed_tlscn = --s;
1257c478bd9Sstevel@tonic-gate 	s->s_next = 0;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	/*
1287c478bd9Sstevel@tonic-gate 	 * Section index SHN_UNDEF (0) does not and cannot
1297c478bd9Sstevel@tonic-gate 	 * have a data buffer.  Fix it here.  Also mark the
1307c478bd9Sstevel@tonic-gate 	 * initial section as being allocated for the block
1317c478bd9Sstevel@tonic-gate 	 */
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	s = elf->ed_hdscn;
1347c478bd9Sstevel@tonic-gate 	s->s_myflags = SF_ALLOC;
1357c478bd9Sstevel@tonic-gate 	s->s_hdnode = 0;
1367c478bd9Sstevel@tonic-gate 	s->s_tlnode = 0;
1377c478bd9Sstevel@tonic-gate 	return (OK_YES);
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate Okay
_elf_cookscn(Elf_Scn * s)1427c478bd9Sstevel@tonic-gate _elf_cookscn(Elf_Scn * s)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate 	Elf *			elf;
1457c478bd9Sstevel@tonic-gate 	Shdr *			sh;
1467c478bd9Sstevel@tonic-gate 	register Dnode *	d = &s->s_dnode;
1477c478bd9Sstevel@tonic-gate 	size_t			fsz, msz;
1487c478bd9Sstevel@tonic-gate 	unsigned		work;
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	s->s_hdnode = s->s_tlnode = d;
1517c478bd9Sstevel@tonic-gate 	s->s_err = 0;
1527c478bd9Sstevel@tonic-gate 	s->s_shflags = 0;
1537c478bd9Sstevel@tonic-gate 	s->s_uflags = 0;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	/*
1577c478bd9Sstevel@tonic-gate 	 * Prepare d_data for inspection, but don't actually
1587c478bd9Sstevel@tonic-gate 	 * translate data until needed.  Leave the READY
1597c478bd9Sstevel@tonic-gate 	 * flag off.  NOBITS sections see zero size.
1607c478bd9Sstevel@tonic-gate 	 */
1617c478bd9Sstevel@tonic-gate 	elf = s->s_elf;
1627c478bd9Sstevel@tonic-gate 	sh = s->s_shdr;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	d->db_scn = s;
1657c478bd9Sstevel@tonic-gate 	d->db_off = sh->sh_offset;
1667c478bd9Sstevel@tonic-gate 	d->db_data.d_align = sh->sh_addralign;
1677c478bd9Sstevel@tonic-gate 	d->db_data.d_version = elf->ed_version;
1687c478bd9Sstevel@tonic-gate 	ELFACCESSDATA(work, _elf_work)
1697c478bd9Sstevel@tonic-gate 	d->db_data.d_type = _elf_mtype(elf, sh->sh_type, work);
1707c478bd9Sstevel@tonic-gate 	d->db_data.d_buf = 0;
1717c478bd9Sstevel@tonic-gate 	d->db_data.d_off = 0;
1727c478bd9Sstevel@tonic-gate 	fsz = elf_fsize(d->db_data.d_type, 1, elf->ed_version);
1737c478bd9Sstevel@tonic-gate 	msz = _elf_msize(d->db_data.d_type, elf->ed_version);
17498cadd32SRichard Lowe 	d->db_data.d_size = MAX(sh->sh_size, (sh->sh_size / fsz) * msz);
1757c478bd9Sstevel@tonic-gate 	d->db_shsz = sh->sh_size;
1767c478bd9Sstevel@tonic-gate 	d->db_raw = 0;
1777c478bd9Sstevel@tonic-gate 	d->db_buf = 0;
1787c478bd9Sstevel@tonic-gate 	d->db_uflags = 0;
1797c478bd9Sstevel@tonic-gate 	d->db_myflags = 0;
1807c478bd9Sstevel@tonic-gate 	d->db_next = 0;
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	if (sh->sh_type != SHT_NOBITS)
1837c478bd9Sstevel@tonic-gate 		d->db_fsz = sh->sh_size;
1847c478bd9Sstevel@tonic-gate 	else
1857c478bd9Sstevel@tonic-gate 		d->db_fsz = 0;
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	s->s_myflags |= SF_READY;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	return (OK_YES);
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate Snode *
_elf_snode()1957c478bd9Sstevel@tonic-gate _elf_snode()
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate 	register Snode	*s;
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	if ((s = malloc(sizeof (Snode))) == 0) {
2007c478bd9Sstevel@tonic-gate 		_elf_seterr(EMEM_SNODE, errno);
2017c478bd9Sstevel@tonic-gate 		return (0);
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 	*s = _elf_snode_init;
2047c478bd9Sstevel@tonic-gate 	ELFMUTEXINIT(&s->sb_scn.s_mutex);
2057c478bd9Sstevel@tonic-gate 	s->sb_scn.s_myflags = SF_ALLOC | SF_READY;
2067c478bd9Sstevel@tonic-gate 	s->sb_scn.s_shdr = &s->sb_shdr;
2077c478bd9Sstevel@tonic-gate 	return (s);
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate int
_elf_ehdr(Elf * elf,int inplace)2137c478bd9Sstevel@tonic-gate _elf_ehdr(Elf * elf, int inplace)
2147c478bd9Sstevel@tonic-gate {
2157c478bd9Sstevel@tonic-gate 	register size_t	fsz;		/* field size */
2167c478bd9Sstevel@tonic-gate 	Elf_Data	dst, src;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	fsz = elf_fsize(ELF_T_EHDR, 1, elf->ed_version);
2197c478bd9Sstevel@tonic-gate 	if (fsz > elf->ed_fsz) {
2207c478bd9Sstevel@tonic-gate 		_elf_seterr(EFMT_EHDRSZ, 0);
2217c478bd9Sstevel@tonic-gate 		return (-1);
2227c478bd9Sstevel@tonic-gate 	}
2237c478bd9Sstevel@tonic-gate 	if (inplace && (fsz >= sizeof (Ehdr))) {
2247c478bd9Sstevel@tonic-gate 		/*
2257c478bd9Sstevel@tonic-gate 		 * The translated Ehdr will fit over the original Ehdr.
2267c478bd9Sstevel@tonic-gate 		 */
2277c478bd9Sstevel@tonic-gate 		/* LINTED */
2287c478bd9Sstevel@tonic-gate 		elf->ed_ehdr = (Ehdr *)elf->ed_ident;
2297c478bd9Sstevel@tonic-gate 		elf->ed_status = ES_COOKED;
2307c478bd9Sstevel@tonic-gate 	} else {
2317c478bd9Sstevel@tonic-gate 		elf->ed_ehdr = malloc(sizeof (Ehdr));
2327c478bd9Sstevel@tonic-gate 		if (elf->ed_ehdr == 0) {
2337c478bd9Sstevel@tonic-gate 			_elf_seterr(EMEM_EHDR, errno);
2347c478bd9Sstevel@tonic-gate 			return (-1);
2357c478bd9Sstevel@tonic-gate 		}
2367c478bd9Sstevel@tonic-gate 		elf->ed_myflags |= EDF_EHALLOC;
2377c478bd9Sstevel@tonic-gate 	}
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	/*
2407c478bd9Sstevel@tonic-gate 	 * Memory size >= fsz, because otherwise the memory version
2417c478bd9Sstevel@tonic-gate 	 * loses information and cannot accurately implement the
2427c478bd9Sstevel@tonic-gate 	 * file.
2437c478bd9Sstevel@tonic-gate 	 */
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	src.d_buf = (Elf_Void *)elf->ed_ident;
2467c478bd9Sstevel@tonic-gate 	src.d_type = ELF_T_EHDR;
2477c478bd9Sstevel@tonic-gate 	src.d_size = fsz;
2487c478bd9Sstevel@tonic-gate 	src.d_version = elf->ed_version;
2497c478bd9Sstevel@tonic-gate 	dst.d_buf = (Elf_Void *)elf->ed_ehdr;
2507c478bd9Sstevel@tonic-gate 	dst.d_size = sizeof (Ehdr);
2517c478bd9Sstevel@tonic-gate 	dst.d_version = EV_CURRENT;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	if ((_elf_vm(elf, (size_t)0, fsz) != OK_YES) ||
2547c478bd9Sstevel@tonic-gate 	    (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
2557c478bd9Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_EHALLOC) {
2567c478bd9Sstevel@tonic-gate 			elf->ed_myflags &= ~EDF_EHALLOC;
2577c478bd9Sstevel@tonic-gate 			free(elf->ed_ehdr);
2587c478bd9Sstevel@tonic-gate 		}
2597c478bd9Sstevel@tonic-gate 		elf->ed_ehdr = 0;
2607c478bd9Sstevel@tonic-gate 		return (-1);
2617c478bd9Sstevel@tonic-gate 	}
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	if (((Ehdr*)elf->ed_ehdr)->e_ident[EI_CLASS] != ELFCLASS) {
2647c478bd9Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
2657c478bd9Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_EHALLOC) {
2667c478bd9Sstevel@tonic-gate 			elf->ed_myflags &= ~EDF_EHALLOC;
2677c478bd9Sstevel@tonic-gate 			free(elf->ed_ehdr);
2687c478bd9Sstevel@tonic-gate 		}
2697c478bd9Sstevel@tonic-gate 		elf->ed_ehdr = 0;
2707c478bd9Sstevel@tonic-gate 		return (-1);
2717c478bd9Sstevel@tonic-gate 	}
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	if (((Ehdr*)elf->ed_ehdr)->e_version != elf->ed_version) {
2747c478bd9Sstevel@tonic-gate 		_elf_seterr(EFMT_VER2, 0);
2757c478bd9Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_EHALLOC) {
2767c478bd9Sstevel@tonic-gate 			elf->ed_myflags &= ~EDF_EHALLOC;
2777c478bd9Sstevel@tonic-gate 			free(elf->ed_ehdr);
2787c478bd9Sstevel@tonic-gate 		}
2797c478bd9Sstevel@tonic-gate 		elf->ed_ehdr = 0;
2807c478bd9Sstevel@tonic-gate 		return (-1);
2817c478bd9Sstevel@tonic-gate 	}
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	return (0);
2847c478bd9Sstevel@tonic-gate }
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate int
_elf_phdr(Elf * elf,int inplace)2897c478bd9Sstevel@tonic-gate _elf_phdr(Elf * elf, int inplace)
2907c478bd9Sstevel@tonic-gate {
2917c478bd9Sstevel@tonic-gate 	register size_t		fsz, msz;
2927c478bd9Sstevel@tonic-gate 	Elf_Data		dst, src;
2937c478bd9Sstevel@tonic-gate 	Ehdr *			eh = elf->ed_ehdr;	/* must be present */
2947c478bd9Sstevel@tonic-gate 	unsigned		work;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	if (eh->e_phnum == 0)
2977c478bd9Sstevel@tonic-gate 		return (0);
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	fsz = elf_fsize(ELF_T_PHDR, 1, elf->ed_version);
3007c478bd9Sstevel@tonic-gate 	if (eh->e_phentsize != fsz) {
3017c478bd9Sstevel@tonic-gate 		_elf_seterr(EFMT_PHDRSZ, 0);
3027c478bd9Sstevel@tonic-gate 		return (-1);
3037c478bd9Sstevel@tonic-gate 	}
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	fsz *= eh->e_phnum;
3067c478bd9Sstevel@tonic-gate 	ELFACCESSDATA(work, _elf_work)
3077c478bd9Sstevel@tonic-gate 	msz = _elf_msize(ELF_T_PHDR, work) * eh->e_phnum;
3087c478bd9Sstevel@tonic-gate 	if ((eh->e_phoff == 0) ||
309*18059eaeSRichard Lowe 	    (elf->ed_fsz <= eh->e_phoff) ||
310*18059eaeSRichard Lowe 	    (elf->ed_fsz - eh->e_phoff < fsz)) {
3117c478bd9Sstevel@tonic-gate 		_elf_seterr(EFMT_PHTAB, 0);
3127c478bd9Sstevel@tonic-gate 		return (-1);
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	if (inplace && fsz >= msz && eh->e_phoff % sizeof (ElfField) == 0) {
3167c478bd9Sstevel@tonic-gate 		elf->ed_phdr = (Elf_Void *)(elf->ed_ident + eh->e_phoff);
3177c478bd9Sstevel@tonic-gate 		elf->ed_status = ES_COOKED;
3187c478bd9Sstevel@tonic-gate 	} else {
3197c478bd9Sstevel@tonic-gate 		if ((elf->ed_phdr = malloc(msz)) == 0) {
3207c478bd9Sstevel@tonic-gate 			_elf_seterr(EMEM_PHDR, errno);
3217c478bd9Sstevel@tonic-gate 			return (-1);
3227c478bd9Sstevel@tonic-gate 		}
3237c478bd9Sstevel@tonic-gate 		elf->ed_myflags |= EDF_PHALLOC;
3247c478bd9Sstevel@tonic-gate 	}
3257c478bd9Sstevel@tonic-gate 	src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_phoff);
3267c478bd9Sstevel@tonic-gate 	src.d_type = ELF_T_PHDR;
3277c478bd9Sstevel@tonic-gate 	src.d_size = fsz;
3287c478bd9Sstevel@tonic-gate 	src.d_version = elf->ed_version;
3297c478bd9Sstevel@tonic-gate 	dst.d_buf = elf->ed_phdr;
3307c478bd9Sstevel@tonic-gate 	dst.d_size = msz;
3317c478bd9Sstevel@tonic-gate 	dst.d_version = work;
3327c478bd9Sstevel@tonic-gate 	if ((_elf_vm(elf, (size_t)eh->e_phoff, fsz) != OK_YES) ||
3337c478bd9Sstevel@tonic-gate 	    (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
3347c478bd9Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_PHALLOC) {
3357c478bd9Sstevel@tonic-gate 			elf->ed_myflags &= ~EDF_PHALLOC;
3367c478bd9Sstevel@tonic-gate 			free(elf->ed_phdr);
3377c478bd9Sstevel@tonic-gate 		}
3387c478bd9Sstevel@tonic-gate 		elf->ed_phdr = 0;
3397c478bd9Sstevel@tonic-gate 		return (-1);
3407c478bd9Sstevel@tonic-gate 	}
3417c478bd9Sstevel@tonic-gate 	elf->ed_phdrsz = msz;
3427c478bd9Sstevel@tonic-gate 	return (0);
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate int
_elf_shdr(Elf * elf,int inplace)3487c478bd9Sstevel@tonic-gate _elf_shdr(Elf * elf, int inplace)
3497c478bd9Sstevel@tonic-gate {
3507c478bd9Sstevel@tonic-gate 	register size_t		fsz, msz;
3517c478bd9Sstevel@tonic-gate 	size_t			scncnt;
3527c478bd9Sstevel@tonic-gate 	Elf_Data		dst, src;
3537c478bd9Sstevel@tonic-gate 	register Ehdr		*eh = elf->ed_ehdr;	/* must be present */
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	if ((eh->e_shnum == 0) && (eh->e_shoff == 0))
3567c478bd9Sstevel@tonic-gate 		return (0);
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	fsz = elf_fsize(ELF_T_SHDR, 1, elf->ed_version);
3597c478bd9Sstevel@tonic-gate 	if (eh->e_shentsize != fsz) {
3607c478bd9Sstevel@tonic-gate 		_elf_seterr(EFMT_SHDRSZ, 0);
3617c478bd9Sstevel@tonic-gate 		return (-1);
3627c478bd9Sstevel@tonic-gate 	}
3637c478bd9Sstevel@tonic-gate 	/*
3647c478bd9Sstevel@tonic-gate 	 * If we are dealing with a file with 'extended section
3657c478bd9Sstevel@tonic-gate 	 * indexes' - then we need to load the first section
3667c478bd9Sstevel@tonic-gate 	 * header.  The actual section count is stored in
3677c478bd9Sstevel@tonic-gate 	 * Shdr[0].sh_size.
3687c478bd9Sstevel@tonic-gate 	 */
3697c478bd9Sstevel@tonic-gate 	if ((scncnt = eh->e_shnum) == 0) {
3707c478bd9Sstevel@tonic-gate 		Shdr	sh;
3717c478bd9Sstevel@tonic-gate 		if ((eh->e_shoff == 0) ||
3727c478bd9Sstevel@tonic-gate 		    (elf->ed_fsz <= eh->e_shoff) ||
3737c478bd9Sstevel@tonic-gate 		    (elf->ed_fsz - eh->e_shoff < fsz)) {
3747c478bd9Sstevel@tonic-gate 			_elf_seterr(EFMT_SHTAB, 0);
3757c478bd9Sstevel@tonic-gate 			return (-1);
3767c478bd9Sstevel@tonic-gate 		}
3777c478bd9Sstevel@tonic-gate 		src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff);
3787c478bd9Sstevel@tonic-gate 		src.d_type = ELF_T_SHDR;
3797c478bd9Sstevel@tonic-gate 		src.d_size = fsz;
3807c478bd9Sstevel@tonic-gate 		src.d_version = elf->ed_version;
3817c478bd9Sstevel@tonic-gate 		dst.d_buf = (Elf_Void *)&sh;
3827c478bd9Sstevel@tonic-gate 		dst.d_size = sizeof (Shdr);
3837c478bd9Sstevel@tonic-gate 		dst.d_version = EV_CURRENT;
3847c478bd9Sstevel@tonic-gate 		if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) ||
3857c478bd9Sstevel@tonic-gate 		    (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
3867c478bd9Sstevel@tonic-gate 			return (-1);
3877c478bd9Sstevel@tonic-gate 		}
3887c478bd9Sstevel@tonic-gate 		scncnt = sh.sh_size;
3897c478bd9Sstevel@tonic-gate 	}
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	fsz *= scncnt;
3927c478bd9Sstevel@tonic-gate 	msz = scncnt * sizeof (Shdr);
3937c478bd9Sstevel@tonic-gate 	if ((eh->e_shoff == 0) ||
3947c478bd9Sstevel@tonic-gate 	    (elf->ed_fsz <= eh->e_shoff) ||
3957c478bd9Sstevel@tonic-gate 	    (elf->ed_fsz - eh->e_shoff < fsz)) {
3967c478bd9Sstevel@tonic-gate 		_elf_seterr(EFMT_SHTAB, 0);
3977c478bd9Sstevel@tonic-gate 		return (-1);
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	if (inplace && (fsz >= msz) &&
4017c478bd9Sstevel@tonic-gate 	    ((eh->e_shoff % sizeof (ElfField)) == 0)) {
4027c478bd9Sstevel@tonic-gate 		/* LINTED */
4037c478bd9Sstevel@tonic-gate 		elf->ed_shdr = (Shdr *)(elf->ed_ident + eh->e_shoff);
4047c478bd9Sstevel@tonic-gate 		elf->ed_status = ES_COOKED;
4057c478bd9Sstevel@tonic-gate 	} else {
4067c478bd9Sstevel@tonic-gate 		if ((elf->ed_shdr = malloc(msz)) == 0) {
4077c478bd9Sstevel@tonic-gate 			_elf_seterr(EMEM_SHDR, errno);
4087c478bd9Sstevel@tonic-gate 			return (-1);
4097c478bd9Sstevel@tonic-gate 		}
4107c478bd9Sstevel@tonic-gate 		elf->ed_myflags |= EDF_SHALLOC;
4117c478bd9Sstevel@tonic-gate 	}
4127c478bd9Sstevel@tonic-gate 	src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff);
4137c478bd9Sstevel@tonic-gate 	src.d_type = ELF_T_SHDR;
4147c478bd9Sstevel@tonic-gate 	src.d_size = fsz;
4157c478bd9Sstevel@tonic-gate 	src.d_version = elf->ed_version;
4167c478bd9Sstevel@tonic-gate 	dst.d_buf = (Elf_Void *)elf->ed_shdr;
4177c478bd9Sstevel@tonic-gate 	dst.d_size = msz;
4187c478bd9Sstevel@tonic-gate 	dst.d_version = EV_CURRENT;
4197c478bd9Sstevel@tonic-gate 	if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) ||
4207c478bd9Sstevel@tonic-gate 	    (elf_xlatetom(&dst, &src, elf->ed_encode) == 0) ||
4217c478bd9Sstevel@tonic-gate 	    (_elf_prepscn(elf, scncnt) != OK_YES)) {
4227c478bd9Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_SHALLOC) {
4237c478bd9Sstevel@tonic-gate 			elf->ed_myflags &= ~EDF_SHALLOC;
4247c478bd9Sstevel@tonic-gate 			free(elf->ed_shdr);
4257c478bd9Sstevel@tonic-gate 		}
4267c478bd9Sstevel@tonic-gate 		elf->ed_shdr = 0;
4277c478bd9Sstevel@tonic-gate 		return (-1);
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 	return (0);
4307c478bd9Sstevel@tonic-gate }
431