xref: /onnv-gate/usr/src/cmd/sgs/libelf/common/gelf.c (revision 942:8cf53d6a7d2e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <string.h>
300Sstevel@tonic-gate #include "gelf.h"
310Sstevel@tonic-gate #include "decl.h"
320Sstevel@tonic-gate #include "msg.h"
330Sstevel@tonic-gate 
340Sstevel@tonic-gate 
350Sstevel@tonic-gate /*
360Sstevel@tonic-gate  * Find elf or it's class from a pointer to an Elf_Data struct.
370Sstevel@tonic-gate  * Warning:  this Assumes that the Elf_Data is part of a libelf
380Sstevel@tonic-gate  * Dnode structure, which is expected to be true for any Elf_Data
390Sstevel@tonic-gate  * passed into libelf *except* for the xlatetof() and xlatetom() functions.
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate #define	EDATA_CLASS(edata) \
420Sstevel@tonic-gate 	(((Dnode *)(edata))->db_scn->s_elf->ed_class)
430Sstevel@tonic-gate 
440Sstevel@tonic-gate #define	EDATA_ELF(edata) \
450Sstevel@tonic-gate 	(((Dnode *)(edata))->db_scn->s_elf)
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #define	EDATA_SCN(edata) \
480Sstevel@tonic-gate 	(((Dnode *)(edata))->db_scn)
490Sstevel@tonic-gate 
500Sstevel@tonic-gate #define	EDATA_READLOCKS(edata) \
510Sstevel@tonic-gate 	READLOCKS(EDATA_ELF((edata)), EDATA_SCN((edata)))
520Sstevel@tonic-gate 
530Sstevel@tonic-gate #define	EDATA_READUNLOCKS(edata) \
540Sstevel@tonic-gate 	READUNLOCKS(EDATA_ELF((edata)), EDATA_SCN((edata)))
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 
570Sstevel@tonic-gate size_t
580Sstevel@tonic-gate gelf_fsize(Elf * elf, Elf_Type type, size_t count, unsigned ver)
590Sstevel@tonic-gate {
600Sstevel@tonic-gate 	int class;
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	if (elf == NULL)
630Sstevel@tonic-gate 		return (0);
640Sstevel@tonic-gate 
650Sstevel@tonic-gate 	class = gelf_getclass(elf);
660Sstevel@tonic-gate 	if (class == ELFCLASS32)
670Sstevel@tonic-gate 		return (elf32_fsize(type, count, ver));
680Sstevel@tonic-gate 	else if (class == ELFCLASS64)
690Sstevel@tonic-gate 		return (elf64_fsize(type, count, ver));
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 	_elf_seterr(EREQ_CLASS, 0);
720Sstevel@tonic-gate 	return (0);
730Sstevel@tonic-gate }
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 
760Sstevel@tonic-gate int
770Sstevel@tonic-gate gelf_getclass(Elf *elf)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	if (elf == NULL)
800Sstevel@tonic-gate 		return (0);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	/*
830Sstevel@tonic-gate 	 * Don't rely on the idents, a new ehdr doesn't have it!
840Sstevel@tonic-gate 	 */
850Sstevel@tonic-gate 	return (elf->ed_class);
860Sstevel@tonic-gate }
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 
890Sstevel@tonic-gate GElf_Ehdr *
900Sstevel@tonic-gate gelf_getehdr(Elf *elf, GElf_Ehdr *dst)
910Sstevel@tonic-gate {
920Sstevel@tonic-gate 	int class;
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	if (elf == NULL)
950Sstevel@tonic-gate 		return (NULL);
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	class = gelf_getclass(elf);
980Sstevel@tonic-gate 	if (class == ELFCLASS32) {
990Sstevel@tonic-gate 		Elf32_Ehdr * e		= elf32_getehdr(elf);
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 		if (e == NULL)
1020Sstevel@tonic-gate 			return (NULL);
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 		ELFRLOCK(elf);
1050Sstevel@tonic-gate 		(void) memcpy(dst->e_ident, e->e_ident, EI_NIDENT);
1060Sstevel@tonic-gate 		dst->e_type		= e->e_type;
1070Sstevel@tonic-gate 		dst->e_machine		= e->e_machine;
1080Sstevel@tonic-gate 		dst->e_version		= e->e_version;
1090Sstevel@tonic-gate 		dst->e_entry		= (Elf64_Addr)e->e_entry;
1100Sstevel@tonic-gate 		dst->e_phoff		= (Elf64_Off)e->e_phoff;
1110Sstevel@tonic-gate 		dst->e_shoff		= (Elf64_Off)e->e_shoff;
1120Sstevel@tonic-gate 		dst->e_flags		= e->e_flags;
1130Sstevel@tonic-gate 		dst->e_ehsize		= e->e_ehsize;
1140Sstevel@tonic-gate 		dst->e_phentsize	= e->e_phentsize;
1150Sstevel@tonic-gate 		dst->e_phnum		= e->e_phnum;
1160Sstevel@tonic-gate 		dst->e_shentsize	= e->e_shentsize;
1170Sstevel@tonic-gate 		dst->e_shnum		= e->e_shnum;
1180Sstevel@tonic-gate 		dst->e_shstrndx		= e->e_shstrndx;
1190Sstevel@tonic-gate 		ELFUNLOCK(elf);
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 		return (dst);
1220Sstevel@tonic-gate 	} else if (class == ELFCLASS64) {
1230Sstevel@tonic-gate 		Elf64_Ehdr * e		= elf64_getehdr(elf);
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 		if (e == NULL)
1260Sstevel@tonic-gate 			return (NULL);
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 		ELFRLOCK(elf);
1290Sstevel@tonic-gate 		*dst			= *e;
1300Sstevel@tonic-gate 		ELFUNLOCK(elf);
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 		return (dst);
1330Sstevel@tonic-gate 	}
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	_elf_seterr(EREQ_CLASS, 0);
1360Sstevel@tonic-gate 	return (NULL);
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate int
1410Sstevel@tonic-gate gelf_update_ehdr(Elf *elf, GElf_Ehdr *src)
1420Sstevel@tonic-gate {
1430Sstevel@tonic-gate 	int class;
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	if (elf == NULL)
1460Sstevel@tonic-gate 		return (0);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	/*
1490Sstevel@tonic-gate 	 * In case elf isn't cooked.
1500Sstevel@tonic-gate 	 */
1510Sstevel@tonic-gate 	class = gelf_getclass(elf);
1520Sstevel@tonic-gate 	if (class == ELFCLASSNONE)
1530Sstevel@tonic-gate 		class = src->e_ident[EI_CLASS];
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	if (class == ELFCLASS32) {
1570Sstevel@tonic-gate 		Elf32_Ehdr * d	= elf32_getehdr(elf);
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 		if (d == NULL)
1600Sstevel@tonic-gate 			return (0);
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 		ELFWLOCK(elf);
1630Sstevel@tonic-gate 		(void) memcpy(d->e_ident, src->e_ident, EI_NIDENT);
1640Sstevel@tonic-gate 		d->e_type	= src->e_type;
1650Sstevel@tonic-gate 		d->e_machine	= src->e_machine;
1660Sstevel@tonic-gate 		d->e_version	= src->e_version;
1670Sstevel@tonic-gate 		/* LINTED */
1680Sstevel@tonic-gate 		d->e_entry	= (Elf32_Addr)src->e_entry;
1690Sstevel@tonic-gate 		/* LINTED */
1700Sstevel@tonic-gate 		d->e_phoff	= (Elf32_Off)src->e_phoff;
1710Sstevel@tonic-gate 		/* LINTED */
1720Sstevel@tonic-gate 		d->e_shoff	= (Elf32_Off)src->e_shoff;
1730Sstevel@tonic-gate 		/* could memcpy the rest of these... */
1740Sstevel@tonic-gate 		d->e_flags	= src->e_flags;
1750Sstevel@tonic-gate 		d->e_ehsize	= src->e_ehsize;
1760Sstevel@tonic-gate 		d->e_phentsize	= src->e_phentsize;
1770Sstevel@tonic-gate 		d->e_phnum	= src->e_phnum;
1780Sstevel@tonic-gate 		d->e_shentsize	= src->e_shentsize;
1790Sstevel@tonic-gate 		d->e_shnum	= src->e_shnum;
1800Sstevel@tonic-gate 		d->e_shstrndx	= src->e_shstrndx;
1810Sstevel@tonic-gate 		ELFUNLOCK(elf);
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 		return (1);
1840Sstevel@tonic-gate 	} else if (class == ELFCLASS64) {
1850Sstevel@tonic-gate 		Elf64_Ehdr * d	= elf64_getehdr(elf);
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 		if (d == NULL)
1880Sstevel@tonic-gate 			return (0);
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 		ELFWLOCK(elf);
1910Sstevel@tonic-gate 		*d		= *(Elf64_Ehdr *)src;
1920Sstevel@tonic-gate 		ELFUNLOCK(elf);
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 		return (1);
1950Sstevel@tonic-gate 	}
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	_elf_seterr(EREQ_CLASS, 0);
1980Sstevel@tonic-gate 	return (0);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate unsigned long
2030Sstevel@tonic-gate gelf_newehdr(Elf *elf, int class)
2040Sstevel@tonic-gate {
2050Sstevel@tonic-gate 	if (elf == NULL)
2060Sstevel@tonic-gate 		return (0);
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	if (class == ELFCLASS32)
2090Sstevel@tonic-gate 		return ((unsigned long)elf32_newehdr(elf));
2100Sstevel@tonic-gate 	else if (class == ELFCLASS64)
2110Sstevel@tonic-gate 		return ((unsigned long)elf64_newehdr(elf));
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	_elf_seterr(EREQ_CLASS, 0);
2140Sstevel@tonic-gate 	return (0);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate GElf_Phdr *
2190Sstevel@tonic-gate gelf_getphdr(Elf *elf, int ndx, GElf_Phdr *dst)
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate 	int		class;
222*942Sahl 	size_t		phnum;
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	if (elf == NULL)
2250Sstevel@tonic-gate 		return (NULL);
2260Sstevel@tonic-gate 
227*942Sahl 	if (elf_getphnum(elf, &phnum) == 0)
2280Sstevel@tonic-gate 		return (NULL);
2290Sstevel@tonic-gate 
230*942Sahl 	if (phnum <= ndx) {
2310Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
2320Sstevel@tonic-gate 		return (NULL);
2330Sstevel@tonic-gate 	}
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	class = gelf_getclass(elf);
2360Sstevel@tonic-gate 	if ((class != ELFCLASS32) && (class != ELFCLASS64)) {
2370Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
2380Sstevel@tonic-gate 		return (NULL);
2390Sstevel@tonic-gate 	}
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	if (class == ELFCLASS32) {
2420Sstevel@tonic-gate 		Elf32_Phdr *p	= &((Elf32_Phdr *)elf32_getphdr(elf))[ndx];
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 		ELFRLOCK(elf);
2450Sstevel@tonic-gate 		dst->p_type	= p->p_type;
2460Sstevel@tonic-gate 		dst->p_flags	= p->p_flags;
2470Sstevel@tonic-gate 		dst->p_offset	= (Elf64_Off)p->p_offset;
2480Sstevel@tonic-gate 		dst->p_vaddr	= (Elf64_Addr)p->p_vaddr;
2490Sstevel@tonic-gate 		dst->p_paddr	= (Elf64_Addr)p->p_paddr;
2500Sstevel@tonic-gate 		dst->p_filesz	= (Elf64_Xword)p->p_filesz;
2510Sstevel@tonic-gate 		dst->p_memsz	= (Elf64_Xword)p->p_memsz;
2520Sstevel@tonic-gate 		dst->p_align	= (Elf64_Xword)p->p_align;
2530Sstevel@tonic-gate 		ELFUNLOCK(elf);
2540Sstevel@tonic-gate 	} else if (class == ELFCLASS64) {
2550Sstevel@tonic-gate 		Elf64_Phdr *phdrs = elf64_getphdr(elf);
2560Sstevel@tonic-gate 		ELFRLOCK(elf);
2570Sstevel@tonic-gate 		*dst = ((GElf_Phdr *)phdrs)[ndx];
2580Sstevel@tonic-gate 		ELFUNLOCK(elf);
2590Sstevel@tonic-gate 	}
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	return (dst);
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate int
2660Sstevel@tonic-gate gelf_update_phdr(Elf *elf, int ndx, GElf_Phdr *src)
2670Sstevel@tonic-gate {
2680Sstevel@tonic-gate 	int		class;
269*942Sahl 	size_t		phnum;
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	if (elf == NULL)
2720Sstevel@tonic-gate 		return (0);
2730Sstevel@tonic-gate 
274*942Sahl 	if (elf_getphnum(elf, &phnum) == 0)
275*942Sahl 		return (NULL);
2760Sstevel@tonic-gate 
277*942Sahl 	if (phnum < ndx) {
2780Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
2790Sstevel@tonic-gate 		return (0);
2800Sstevel@tonic-gate 	}
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 	class = gelf_getclass(elf);
2830Sstevel@tonic-gate 	if (class == ELFCLASS32) {
2840Sstevel@tonic-gate 		Elf32_Phdr *dst	= &((Elf32_Phdr *)elf32_getphdr(elf))[ndx];
2850Sstevel@tonic-gate 		ELFWLOCK(elf);
2860Sstevel@tonic-gate 		dst->p_type	= src->p_type;
2870Sstevel@tonic-gate 		dst->p_flags	= src->p_flags;
2880Sstevel@tonic-gate 		/* LINTED */
2890Sstevel@tonic-gate 		dst->p_offset	= (Elf32_Off)src->p_offset;
2900Sstevel@tonic-gate 		/* LINTED */
2910Sstevel@tonic-gate 		dst->p_vaddr	= (Elf32_Addr)src->p_vaddr;
2920Sstevel@tonic-gate 		/* LINTED */
2930Sstevel@tonic-gate 		dst->p_paddr	= (Elf32_Addr)src->p_paddr;
2940Sstevel@tonic-gate 		/* LINTED */
2950Sstevel@tonic-gate 		dst->p_filesz	= (Elf32_Word)src->p_filesz;
2960Sstevel@tonic-gate 		/* LINTED */
2970Sstevel@tonic-gate 		dst->p_memsz	= (Elf32_Word)src->p_memsz;
2980Sstevel@tonic-gate 		/* LINTED */
2990Sstevel@tonic-gate 		dst->p_align	= (Elf32_Word)src->p_align;
3000Sstevel@tonic-gate 		ELFUNLOCK(elf);
3010Sstevel@tonic-gate 	} else if (class == ELFCLASS64) {
3020Sstevel@tonic-gate 		Elf64_Phdr *dst = elf64_getphdr(elf);
3030Sstevel@tonic-gate 		ELFWLOCK(elf);
3040Sstevel@tonic-gate 		dst[ndx] = *(GElf_Phdr *)src;
3050Sstevel@tonic-gate 		ELFUNLOCK(elf);
3060Sstevel@tonic-gate 	} else {
3070Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
3080Sstevel@tonic-gate 		return (0);
3090Sstevel@tonic-gate 	}
3100Sstevel@tonic-gate 	return (1);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate unsigned long
3150Sstevel@tonic-gate gelf_newphdr(Elf *elf, size_t phnum)
3160Sstevel@tonic-gate {
3170Sstevel@tonic-gate 	int class;
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	if (elf == NULL)
3200Sstevel@tonic-gate 		return (0);
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	class = gelf_getclass(elf);
3230Sstevel@tonic-gate 	if (class == ELFCLASS32)
3240Sstevel@tonic-gate 		return ((unsigned long)elf32_newphdr(elf, phnum));
3250Sstevel@tonic-gate 	else if (class == ELFCLASS64)
3260Sstevel@tonic-gate 		return ((unsigned long)elf64_newphdr(elf, phnum));
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	_elf_seterr(EREQ_CLASS, 0);
3290Sstevel@tonic-gate 	return (0);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate GElf_Shdr *
3340Sstevel@tonic-gate gelf_getshdr(Elf_Scn *scn,  GElf_Shdr *dst)
3350Sstevel@tonic-gate {
3360Sstevel@tonic-gate 	if (scn == NULL)
3370Sstevel@tonic-gate 		return (NULL);
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	if (scn->s_elf->ed_class == ELFCLASS32) {
3400Sstevel@tonic-gate 		Elf32_Shdr *s		= elf32_getshdr(scn);
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 		if (s == NULL)
3430Sstevel@tonic-gate 			return (NULL);
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 		READLOCKS(scn->s_elf, scn);
3460Sstevel@tonic-gate 		dst->sh_name		= s->sh_name;
3470Sstevel@tonic-gate 		dst->sh_type		= s->sh_type;
3480Sstevel@tonic-gate 		dst->sh_flags		= (Elf64_Xword)s->sh_flags;
3490Sstevel@tonic-gate 		dst->sh_addr		= (Elf64_Addr)s->sh_addr;
3500Sstevel@tonic-gate 		dst->sh_offset		= (Elf64_Off)s->sh_offset;
3510Sstevel@tonic-gate 		dst->sh_size		= (Elf64_Xword)s->sh_size;
3520Sstevel@tonic-gate 		dst->sh_link		= s->sh_link;
3530Sstevel@tonic-gate 		dst->sh_info		= s->sh_info;
3540Sstevel@tonic-gate 		dst->sh_addralign	= (Elf64_Xword)s->sh_addralign;
3550Sstevel@tonic-gate 		dst->sh_entsize		= (Elf64_Xword)s->sh_entsize;
3560Sstevel@tonic-gate 		READUNLOCKS(scn->s_elf, scn);
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 		return (dst);
3590Sstevel@tonic-gate 	} else if (scn->s_elf->ed_class == ELFCLASS64) {
3600Sstevel@tonic-gate 		Elf64_Shdr *s		= elf64_getshdr(scn);
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 		if (s == NULL)
3630Sstevel@tonic-gate 			return (NULL);
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 		READLOCKS(scn->s_elf, scn);
3660Sstevel@tonic-gate 		*dst			= *(Elf64_Shdr *)s;
3670Sstevel@tonic-gate 		READUNLOCKS(scn->s_elf, scn);
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 		return (dst);
3700Sstevel@tonic-gate 	}
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	_elf_seterr(EREQ_CLASS, 0);
3730Sstevel@tonic-gate 	return (NULL);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate int
3780Sstevel@tonic-gate gelf_update_shdr(Elf_Scn *scn, GElf_Shdr *src)
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate 	if (scn == NULL)
3810Sstevel@tonic-gate 		return (0);
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	if (scn->s_elf->ed_class == ELFCLASS32) {
3840Sstevel@tonic-gate 		Elf32_Shdr *dst	= elf32_getshdr(scn);
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 		if (dst == NULL)
3870Sstevel@tonic-gate 			return (0);
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 		ELFWLOCK(scn->s_elf);
3900Sstevel@tonic-gate 		dst->sh_name		= src->sh_name;
3910Sstevel@tonic-gate 		dst->sh_type		= src->sh_type;
3920Sstevel@tonic-gate 		/* LINTED */
3930Sstevel@tonic-gate 		dst->sh_flags		= (Elf32_Word)src->sh_flags;
3940Sstevel@tonic-gate 		/* LINTED */
3950Sstevel@tonic-gate 		dst->sh_addr		= (Elf32_Addr)src->sh_addr;
3960Sstevel@tonic-gate 		/* LINTED */
3970Sstevel@tonic-gate 		dst->sh_offset		= (Elf32_Off) src->sh_offset;
3980Sstevel@tonic-gate 		/* LINTED */
3990Sstevel@tonic-gate 		dst->sh_size		= (Elf32_Word)src->sh_size;
4000Sstevel@tonic-gate 		dst->sh_link		= src->sh_link;
4010Sstevel@tonic-gate 		dst->sh_info		= src->sh_info;
4020Sstevel@tonic-gate 		/* LINTED */
4030Sstevel@tonic-gate 		dst->sh_addralign	= (Elf32_Word)src->sh_addralign;
4040Sstevel@tonic-gate 		/* LINTED */
4050Sstevel@tonic-gate 		dst->sh_entsize		= (Elf32_Word)src->sh_entsize;
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 		ELFUNLOCK(scn->s_elf);
4080Sstevel@tonic-gate 		return (1);
4090Sstevel@tonic-gate 	} else if (scn->s_elf->ed_class == ELFCLASS64) {
4100Sstevel@tonic-gate 		Elf64_Shdr * dst	= elf64_getshdr(scn);
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 		if (dst == NULL)
4130Sstevel@tonic-gate 			return (0);
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 		ELFWLOCK(scn->s_elf);
4160Sstevel@tonic-gate 		*dst			= *(Elf64_Shdr *)src;
4170Sstevel@tonic-gate 		ELFUNLOCK(scn->s_elf);
4180Sstevel@tonic-gate 		return (1);
4190Sstevel@tonic-gate 	}
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	_elf_seterr(EREQ_CLASS, 0);
4220Sstevel@tonic-gate 	return (0);
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate /*
4270Sstevel@tonic-gate  * gelf_xlatetof/gelf_xlatetom use 'elf' to find the class
4280Sstevel@tonic-gate  * because these are the odd case where the Elf_Data structs
4290Sstevel@tonic-gate  * might not have been allocated by libelf (and therefore
4300Sstevel@tonic-gate  * don't have Dnode's associated with them).
4310Sstevel@tonic-gate  */
4320Sstevel@tonic-gate Elf_Data *
4330Sstevel@tonic-gate gelf_xlatetof(Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode)
4340Sstevel@tonic-gate {
4350Sstevel@tonic-gate 	int class;
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	if ((elf == NULL) || (dst == NULL) || (src == NULL))
4380Sstevel@tonic-gate 		return (NULL);
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	class = gelf_getclass(elf);
4410Sstevel@tonic-gate 	if (class == ELFCLASS32)
4420Sstevel@tonic-gate 		return (elf32_xlatetof(dst, src, encode));
4430Sstevel@tonic-gate 	else if (class == ELFCLASS64)
4440Sstevel@tonic-gate 		return (elf64_xlatetof(dst, src, encode));
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	_elf_seterr(EREQ_CLASS, 0);
4470Sstevel@tonic-gate 	return (NULL);
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate Elf_Data *
4520Sstevel@tonic-gate gelf_xlatetom(Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode)
4530Sstevel@tonic-gate {
4540Sstevel@tonic-gate 	int class;
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	if ((elf == NULL) || (dst == NULL) || (src == NULL))
4570Sstevel@tonic-gate 		return (NULL);
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	class = gelf_getclass(elf);
4600Sstevel@tonic-gate 	if (class == ELFCLASS32)
4610Sstevel@tonic-gate 		return (elf32_xlatetom(dst, src, encode));
4620Sstevel@tonic-gate 	else if (class == ELFCLASS64)
4630Sstevel@tonic-gate 		return (elf64_xlatetom(dst, src, encode));
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	_elf_seterr(EREQ_CLASS, 0);
4660Sstevel@tonic-gate 	return (NULL);
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate GElf_Sym *
4710Sstevel@tonic-gate gelf_getsym(Elf_Data * data, int ndx, GElf_Sym * dst)
4720Sstevel@tonic-gate {
4730Sstevel@tonic-gate 	int	class;
4740Sstevel@tonic-gate 	size_t	entsize;
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	if (data == NULL)
4770Sstevel@tonic-gate 		return (NULL);
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	class = EDATA_CLASS(data);
4800Sstevel@tonic-gate 	if (class == ELFCLASS32)
4810Sstevel@tonic-gate 		entsize = sizeof (Elf32_Sym);
4820Sstevel@tonic-gate 	else if (class == ELFCLASS64)
4830Sstevel@tonic-gate 		entsize = sizeof (GElf_Sym);
4840Sstevel@tonic-gate 	else {
4850Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
4860Sstevel@tonic-gate 		return (NULL);
4870Sstevel@tonic-gate 	}
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	EDATA_READLOCKS(data);
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	if ((entsize * ndx) > data->d_size) {
4920Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
4930Sstevel@tonic-gate 		dst = NULL;
4940Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
4950Sstevel@tonic-gate 		Elf32_Sym	*s;
4960Sstevel@tonic-gate 		s		= &(((Elf32_Sym *)data->d_buf)[ndx]);
4970Sstevel@tonic-gate 		dst->st_name	= s->st_name;
4980Sstevel@tonic-gate 		dst->st_value	= (Elf64_Addr)s->st_value;
4990Sstevel@tonic-gate 		dst->st_size	= (Elf64_Xword)s->st_size;
5000Sstevel@tonic-gate 		dst->st_info	= ELF64_ST_INFO(ELF32_ST_BIND(s->st_info),
5010Sstevel@tonic-gate 					ELF32_ST_TYPE(s->st_info));
5020Sstevel@tonic-gate 		dst->st_other	= s->st_other;
5030Sstevel@tonic-gate 		dst->st_shndx	= s->st_shndx;
5040Sstevel@tonic-gate 	} else
5050Sstevel@tonic-gate 		*dst = ((GElf_Sym *)data->d_buf)[ndx];
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 	EDATA_READUNLOCKS(data);
5080Sstevel@tonic-gate 	return (dst);
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate int
5130Sstevel@tonic-gate gelf_update_sym(Elf_Data *dst, int ndx, GElf_Sym *src)
5140Sstevel@tonic-gate {
5150Sstevel@tonic-gate 	int	class, rc = 1;
5160Sstevel@tonic-gate 	size_t	entsize;
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	if (dst == NULL)
5190Sstevel@tonic-gate 		return (0);
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	class = EDATA_CLASS(dst);
5220Sstevel@tonic-gate 	if (class == ELFCLASS32)
5230Sstevel@tonic-gate 		entsize = sizeof (Elf32_Sym);
5240Sstevel@tonic-gate 	else if (class == ELFCLASS64)
5250Sstevel@tonic-gate 		entsize = sizeof (GElf_Sym);
5260Sstevel@tonic-gate 	else {
5270Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
5280Sstevel@tonic-gate 		return (0);
5290Sstevel@tonic-gate 	}
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	ELFWLOCK(EDATA_ELF(dst));
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	if ((entsize * ndx) > dst->d_size) {
5340Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
5350Sstevel@tonic-gate 		rc = 0;
5360Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
5370Sstevel@tonic-gate 		Elf32_Sym * d;
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 		d		= &(((Elf32_Sym *)dst->d_buf)[ndx]);
5400Sstevel@tonic-gate 		d->st_name	= src->st_name;
5410Sstevel@tonic-gate 		/* LINTED */
5420Sstevel@tonic-gate 		d->st_value	= (Elf32_Addr)src->st_value;
5430Sstevel@tonic-gate 		/* LINTED */
5440Sstevel@tonic-gate 		d->st_size	= (Elf32_Word)src->st_size;
5450Sstevel@tonic-gate 		d->st_info	= ELF32_ST_INFO(ELF64_ST_BIND(src->st_info),
5460Sstevel@tonic-gate 					ELF64_ST_TYPE(src->st_info));
5470Sstevel@tonic-gate 		d->st_other	= src->st_other;
5480Sstevel@tonic-gate 		d->st_shndx	= src->st_shndx;
5490Sstevel@tonic-gate 	} else
5500Sstevel@tonic-gate 		((Elf64_Sym *)dst->d_buf)[ndx] = *((Elf64_Sym *)src);
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 	ELFUNLOCK(EDATA_ELF(dst));
5530Sstevel@tonic-gate 	return (rc);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate GElf_Syminfo *
5580Sstevel@tonic-gate gelf_getsyminfo(Elf_Data *data, int ndx, GElf_Syminfo *dst)
5590Sstevel@tonic-gate {
5600Sstevel@tonic-gate 	int	class;
5610Sstevel@tonic-gate 	size_t	entsize;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	if (data == NULL)
5640Sstevel@tonic-gate 		return (NULL);
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	class = EDATA_CLASS(data);
5670Sstevel@tonic-gate 	if (class == ELFCLASS32)
5680Sstevel@tonic-gate 		entsize = sizeof (Elf32_Syminfo);
5690Sstevel@tonic-gate 	else if (class == ELFCLASS64)
5700Sstevel@tonic-gate 		entsize = sizeof (GElf_Syminfo);
5710Sstevel@tonic-gate 	else {
5720Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
5730Sstevel@tonic-gate 		return (NULL);
5740Sstevel@tonic-gate 	}
5750Sstevel@tonic-gate 	EDATA_READLOCKS(data);
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	if ((entsize * ndx) > data->d_size) {
5780Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
5790Sstevel@tonic-gate 		dst = NULL;
5800Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
5810Sstevel@tonic-gate 		Elf32_Syminfo *	si;
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 		si		= &(((Elf32_Syminfo *)data->d_buf)[ndx]);
5840Sstevel@tonic-gate 		dst->si_boundto = si->si_boundto;
5850Sstevel@tonic-gate 		dst->si_flags	= si->si_flags;
5860Sstevel@tonic-gate 	} else
5870Sstevel@tonic-gate 		*dst		= ((GElf_Syminfo *)data->d_buf)[ndx];
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate 	EDATA_READUNLOCKS(data);
5900Sstevel@tonic-gate 	return (dst);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate int
5940Sstevel@tonic-gate gelf_update_syminfo(Elf_Data *dst, int ndx, GElf_Syminfo *src)
5950Sstevel@tonic-gate {
5960Sstevel@tonic-gate 	int	class, rc = 1;
5970Sstevel@tonic-gate 	size_t	entsize;
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	if (dst == NULL)
6000Sstevel@tonic-gate 		return (0);
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	class = EDATA_CLASS(dst);
6030Sstevel@tonic-gate 	if (class == ELFCLASS32)
6040Sstevel@tonic-gate 		entsize = sizeof (Elf32_Syminfo);
6050Sstevel@tonic-gate 	else if (class == ELFCLASS64)
6060Sstevel@tonic-gate 		entsize = sizeof (GElf_Syminfo);
6070Sstevel@tonic-gate 	else {
6080Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
6090Sstevel@tonic-gate 		return (0);
6100Sstevel@tonic-gate 	}
6110Sstevel@tonic-gate 	ELFWLOCK(EDATA_ELF(dst));
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 	if ((entsize * ndx) > dst->d_size) {
6140Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
6150Sstevel@tonic-gate 		rc = 0;
6160Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
6170Sstevel@tonic-gate 		Elf32_Syminfo * d	= &(((Elf32_Syminfo *)dst->d_buf)[ndx]);
6180Sstevel@tonic-gate 		d->si_boundto		= src->si_boundto;
6190Sstevel@tonic-gate 		d->si_flags		= src->si_flags;
6200Sstevel@tonic-gate 	} else
6210Sstevel@tonic-gate 		((Elf64_Syminfo *)dst->d_buf)[ndx] = *((Elf64_Syminfo *)src);
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	ELFUNLOCK(EDATA_ELF(dst));
6240Sstevel@tonic-gate 	return (rc);
6250Sstevel@tonic-gate }
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate GElf_Dyn *
6280Sstevel@tonic-gate gelf_getdyn(Elf_Data *data, int ndx, GElf_Dyn *dst)
6290Sstevel@tonic-gate {
6300Sstevel@tonic-gate 	int	class;
6310Sstevel@tonic-gate 	size_t	entsize;
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	if (data == NULL)
6340Sstevel@tonic-gate 		return (NULL);
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	class = EDATA_CLASS(data);
6370Sstevel@tonic-gate 	if (class == ELFCLASS32)
6380Sstevel@tonic-gate 		entsize = sizeof (Elf32_Dyn);
6390Sstevel@tonic-gate 	else if (class == ELFCLASS64)
6400Sstevel@tonic-gate 		entsize = sizeof (GElf_Dyn);
6410Sstevel@tonic-gate 	else {
6420Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
6430Sstevel@tonic-gate 		return (NULL);
6440Sstevel@tonic-gate 	}
6450Sstevel@tonic-gate 	EDATA_READLOCKS(data);
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 	if ((entsize * ndx) > data->d_size) {
6480Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
6490Sstevel@tonic-gate 		dst = NULL;
6500Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
6510Sstevel@tonic-gate 		Elf32_Dyn * d = &((Elf32_Dyn *)data->d_buf)[ndx];
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 		dst->d_tag	= (Elf32_Sword)d->d_tag;
6540Sstevel@tonic-gate 		dst->d_un.d_val	= (Elf32_Word) d->d_un.d_val;
6550Sstevel@tonic-gate 	} else
6560Sstevel@tonic-gate 		*dst = ((Elf64_Dyn *)data->d_buf)[ndx];
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 	EDATA_READUNLOCKS(data);
6590Sstevel@tonic-gate 	return (dst);
6600Sstevel@tonic-gate }
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate int
6640Sstevel@tonic-gate gelf_update_dyn(Elf_Data *dst, int ndx, GElf_Dyn *src)
6650Sstevel@tonic-gate {
6660Sstevel@tonic-gate 	int	class, rc = 1;
6670Sstevel@tonic-gate 	size_t	entsize;
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate 	if (dst == NULL)
6700Sstevel@tonic-gate 		return (0);
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 	class = EDATA_CLASS(dst);
6730Sstevel@tonic-gate 	if (class == ELFCLASS32)
6740Sstevel@tonic-gate 		entsize = sizeof (Elf32_Dyn);
6750Sstevel@tonic-gate 	else if (class == ELFCLASS64)
6760Sstevel@tonic-gate 		entsize = sizeof (GElf_Dyn);
6770Sstevel@tonic-gate 	else {
6780Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
6790Sstevel@tonic-gate 		return (0);
6800Sstevel@tonic-gate 	}
6810Sstevel@tonic-gate 	ELFWLOCK(EDATA_ELF(dst));
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 	if ((entsize * ndx) > dst->d_size) {
6840Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
6850Sstevel@tonic-gate 		rc = 0;
6860Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
6870Sstevel@tonic-gate 		Elf32_Dyn * d = &((Elf32_Dyn *)dst->d_buf)[ndx];
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 		/* LINTED */
6900Sstevel@tonic-gate 		d->d_tag	= (Elf32_Word)src->d_tag;
6910Sstevel@tonic-gate 		/* LINTED */
6920Sstevel@tonic-gate 		d->d_un.d_val	= (Elf32_Word)src->d_un.d_val;
6930Sstevel@tonic-gate 	} else
6940Sstevel@tonic-gate 		((Elf64_Dyn *)dst->d_buf)[ndx] = *(Elf64_Dyn*)src;
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	ELFUNLOCK(EDATA_ELF(dst));
6970Sstevel@tonic-gate 	return (rc);
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate GElf_Sym *
7030Sstevel@tonic-gate gelf_getsymshndx(Elf_Data *symdata, Elf_Data *shndxdata,
7040Sstevel@tonic-gate 	int ndx, GElf_Sym *symptr, Elf32_Word *xshndx)
7050Sstevel@tonic-gate {
7060Sstevel@tonic-gate 	if (gelf_getsym(symdata, ndx, symptr) == 0)
7070Sstevel@tonic-gate 		return (NULL);
7080Sstevel@tonic-gate 	if (shndxdata && xshndx) {
7090Sstevel@tonic-gate 		EDATA_READLOCKS(shndxdata);
7100Sstevel@tonic-gate 		if ((ndx * sizeof (Elf32_Word)) > shndxdata->d_size) {
7110Sstevel@tonic-gate 			_elf_seterr(EREQ_RAND, 0);
7120Sstevel@tonic-gate 			EDATA_READUNLOCKS(shndxdata);
7130Sstevel@tonic-gate 			return (NULL);
7140Sstevel@tonic-gate 		}
7150Sstevel@tonic-gate 		*xshndx = (((Elf32_Word *)shndxdata->d_buf)[ndx]);
7160Sstevel@tonic-gate 		EDATA_READUNLOCKS(shndxdata);
7170Sstevel@tonic-gate 	} else {
7180Sstevel@tonic-gate 		*xshndx = 0;
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 	return (symptr);
7210Sstevel@tonic-gate }
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate int
7240Sstevel@tonic-gate gelf_update_symshndx(Elf_Data *symdata, Elf_Data *shndxdata,
7250Sstevel@tonic-gate 	int ndx, GElf_Sym *symptr, Elf32_Word xshndx)
7260Sstevel@tonic-gate {
7270Sstevel@tonic-gate 	if (gelf_update_sym(symdata, ndx, symptr) == 0)
7280Sstevel@tonic-gate 		return (0);
7290Sstevel@tonic-gate 	if (shndxdata) {
7300Sstevel@tonic-gate 		ELFWLOCK(EDATA_ELF(shndxdata));
7310Sstevel@tonic-gate 		if ((ndx * sizeof (Elf32_Word)) > shndxdata->d_size) {
7320Sstevel@tonic-gate 			_elf_seterr(EREQ_RAND, 0);
7330Sstevel@tonic-gate 			ELFUNLOCK(EDATA_ELF(shndxdata));
7340Sstevel@tonic-gate 			return (0);
7350Sstevel@tonic-gate 		}
7360Sstevel@tonic-gate 		((Elf32_Word *)shndxdata->d_buf)[ndx] = xshndx;
7370Sstevel@tonic-gate 		ELFUNLOCK(EDATA_ELF(shndxdata));
7380Sstevel@tonic-gate 	}
7390Sstevel@tonic-gate 	return (1);
7400Sstevel@tonic-gate }
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate GElf_Move *
7440Sstevel@tonic-gate gelf_getmove(Elf_Data *src, int ndx, GElf_Move *dst)
7450Sstevel@tonic-gate {
7460Sstevel@tonic-gate 	int	class;
7470Sstevel@tonic-gate 	size_t	entsize;
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 	if (src == NULL)
7500Sstevel@tonic-gate 		return (NULL);
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 	class = EDATA_CLASS(src);
7530Sstevel@tonic-gate 	if (class == ELFCLASS32)
7540Sstevel@tonic-gate 		entsize = sizeof (Elf32_Move);
7550Sstevel@tonic-gate 	else if (class == ELFCLASS64)
7560Sstevel@tonic-gate 		entsize = sizeof (GElf_Move);
7570Sstevel@tonic-gate 	else {
7580Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
7590Sstevel@tonic-gate 		return (NULL);
7600Sstevel@tonic-gate 	}
7610Sstevel@tonic-gate 	EDATA_READLOCKS(src);
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate 	if ((entsize * ndx) > src->d_size) {
7640Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
7650Sstevel@tonic-gate 		dst = NULL;
7660Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
7670Sstevel@tonic-gate 		Elf32_Move * m = &((Elf32_Move *)src->d_buf)[ndx];
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 		dst->m_poffset = (Elf64_Word)m->m_poffset;
7700Sstevel@tonic-gate 		dst->m_repeat = (Elf64_Xword)m->m_repeat;
7710Sstevel@tonic-gate 		dst->m_stride = (Elf64_Half)m->m_stride;
7720Sstevel@tonic-gate 		dst->m_value = (Elf64_Xword)m->m_value;
7730Sstevel@tonic-gate 		dst->m_info = ELF64_M_INFO(
7740Sstevel@tonic-gate 			ELF32_M_SYM(m->m_info),
7750Sstevel@tonic-gate 			ELF32_M_SIZE(m->m_info));
7760Sstevel@tonic-gate 	} else
7770Sstevel@tonic-gate 		*dst = ((Elf64_Move *)src->d_buf)[ndx];
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 	EDATA_READUNLOCKS(src);
7800Sstevel@tonic-gate 	return (dst);
7810Sstevel@tonic-gate }
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate int
7840Sstevel@tonic-gate gelf_update_move(Elf_Data *dest, int ndx, GElf_Move *src)
7850Sstevel@tonic-gate {
7860Sstevel@tonic-gate 	int	class, rc = 1;
7870Sstevel@tonic-gate 	size_t	entsize;
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 	if (dest == NULL)
7900Sstevel@tonic-gate 		return (0);
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 	class = EDATA_CLASS(dest);
7930Sstevel@tonic-gate 	if (class == ELFCLASS32)
7940Sstevel@tonic-gate 		entsize = sizeof (Elf32_Move);
7950Sstevel@tonic-gate 	else if (class == ELFCLASS64)
7960Sstevel@tonic-gate 		entsize = sizeof (GElf_Move);
7970Sstevel@tonic-gate 	else {
7980Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
7990Sstevel@tonic-gate 		return (0);
8000Sstevel@tonic-gate 	}
8010Sstevel@tonic-gate 	ELFWLOCK(EDATA_ELF(dest));
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	if ((entsize * ndx) > dest->d_size) {
8040Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
8050Sstevel@tonic-gate 		rc = 0;
8060Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
8070Sstevel@tonic-gate 		Elf32_Move * m = &((Elf32_Move *)dest->d_buf)[ndx];
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 		m->m_poffset = (Elf32_Word)src->m_poffset;
8100Sstevel@tonic-gate 		m->m_repeat = (Elf32_Half)src->m_repeat;
8110Sstevel@tonic-gate 		m->m_stride = (Elf32_Half)src->m_stride;
8120Sstevel@tonic-gate 		m->m_value = (Elf32_Lword)src->m_value;
8130Sstevel@tonic-gate 		m->m_info = (Elf32_Word)ELF32_M_INFO(
8140Sstevel@tonic-gate 				ELF64_M_SYM(src->m_info),
8150Sstevel@tonic-gate 				ELF64_M_SIZE(src->m_info));
8160Sstevel@tonic-gate 	} else
8170Sstevel@tonic-gate 		((Elf64_Move *)dest->d_buf)[ndx] = *(Elf64_Move *)src;
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate 	ELFUNLOCK(EDATA_ELF(dest));
8200Sstevel@tonic-gate 	return (rc);
8210Sstevel@tonic-gate }
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate GElf_Rela *
8250Sstevel@tonic-gate gelf_getrela(Elf_Data *src, int ndx, GElf_Rela *dst)
8260Sstevel@tonic-gate {
8270Sstevel@tonic-gate 	int	class;
8280Sstevel@tonic-gate 	size_t	entsize;
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate 	if (src == NULL)
8310Sstevel@tonic-gate 		return (NULL);
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate 	class = EDATA_CLASS(src);
8340Sstevel@tonic-gate 	if (class == ELFCLASS32)
8350Sstevel@tonic-gate 		entsize = sizeof (Elf32_Rela);
8360Sstevel@tonic-gate 	else if (class == ELFCLASS64)
8370Sstevel@tonic-gate 		entsize = sizeof (GElf_Rela);
8380Sstevel@tonic-gate 	else {
8390Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
8400Sstevel@tonic-gate 		return (NULL);
8410Sstevel@tonic-gate 	}
8420Sstevel@tonic-gate 	EDATA_READLOCKS(src);
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 	if ((entsize * ndx) > src->d_size) {
8450Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
8460Sstevel@tonic-gate 		dst = NULL;
8470Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
8480Sstevel@tonic-gate 		Elf32_Rela * r = &((Elf32_Rela *)src->d_buf)[ndx];
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 		dst->r_offset	= (GElf_Addr)r->r_offset;
8510Sstevel@tonic-gate 		dst->r_addend	= (GElf_Addr)r->r_addend;
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 		/*
8540Sstevel@tonic-gate 		 * Elf32 will never have the extra data field that
8550Sstevel@tonic-gate 		 * Elf64's r_info field can have, so ignore it.
8560Sstevel@tonic-gate 		 */
8570Sstevel@tonic-gate 		/* LINTED */
8580Sstevel@tonic-gate 		dst->r_info	= ELF64_R_INFO(
8590Sstevel@tonic-gate 		    ELF32_R_SYM(r->r_info),
8600Sstevel@tonic-gate 		    ELF32_R_TYPE(r->r_info));
8610Sstevel@tonic-gate 	} else
8620Sstevel@tonic-gate 		*dst = ((Elf64_Rela *)src->d_buf)[ndx];
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate 	EDATA_READUNLOCKS(src);
8650Sstevel@tonic-gate 	return (dst);
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 
8690Sstevel@tonic-gate int
8700Sstevel@tonic-gate gelf_update_rela(Elf_Data *dst, int ndx, GElf_Rela *src)
8710Sstevel@tonic-gate {
8720Sstevel@tonic-gate 	int	class, rc = 1;
8730Sstevel@tonic-gate 	size_t	entsize;
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate 	if (dst == NULL)
8760Sstevel@tonic-gate 		return (0);
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 	class = EDATA_CLASS(dst);
8790Sstevel@tonic-gate 	if (class == ELFCLASS32)
8800Sstevel@tonic-gate 		entsize = sizeof (Elf32_Rela);
8810Sstevel@tonic-gate 	else if (class == ELFCLASS64)
8820Sstevel@tonic-gate 		entsize = sizeof (GElf_Rela);
8830Sstevel@tonic-gate 	else {
8840Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
8850Sstevel@tonic-gate 		return (0);
8860Sstevel@tonic-gate 	}
8870Sstevel@tonic-gate 	ELFWLOCK(EDATA_ELF(dst));
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate 	if ((entsize * ndx) > dst->d_size) {
8900Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
8910Sstevel@tonic-gate 		rc = 0;
8920Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
8930Sstevel@tonic-gate 		Elf32_Rela * r = &((Elf32_Rela *)dst->d_buf)[ndx];
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 		/* LINTED */
8960Sstevel@tonic-gate 		r->r_offset	= (Elf32_Addr) src->r_offset;
8970Sstevel@tonic-gate 		/* LINTED */
8980Sstevel@tonic-gate 		r->r_addend	= (Elf32_Sword)src->r_addend;
8990Sstevel@tonic-gate 
9000Sstevel@tonic-gate 		/*
9010Sstevel@tonic-gate 		 * Elf32 will never have the extra data field that
9020Sstevel@tonic-gate 		 * Elf64's r_info field can have, so ignore it.
9030Sstevel@tonic-gate 		 */
9040Sstevel@tonic-gate 		/* LINTED */
9050Sstevel@tonic-gate 		r->r_info	= ELF32_R_INFO(
9060Sstevel@tonic-gate 					ELF64_R_SYM(src->r_info),
9070Sstevel@tonic-gate 					ELF64_R_TYPE(src->r_info));
9080Sstevel@tonic-gate 	} else
9090Sstevel@tonic-gate 		((Elf64_Rela *)dst->d_buf)[ndx] = *(Elf64_Rela *)src;
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate 	ELFUNLOCK(EDATA_ELF(dst));
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	return (rc);
9140Sstevel@tonic-gate }
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate GElf_Rel *
9180Sstevel@tonic-gate gelf_getrel(Elf_Data *src, int ndx, GElf_Rel *dst)
9190Sstevel@tonic-gate {
9200Sstevel@tonic-gate 	int	class;
9210Sstevel@tonic-gate 	size_t	entsize;
9220Sstevel@tonic-gate 
9230Sstevel@tonic-gate 	if (src == NULL)
9240Sstevel@tonic-gate 		return (NULL);
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 	class = EDATA_CLASS(src);
9270Sstevel@tonic-gate 	if (class == ELFCLASS32)
9280Sstevel@tonic-gate 		entsize = sizeof (Elf32_Rel);
9290Sstevel@tonic-gate 	else if (class == ELFCLASS64)
9300Sstevel@tonic-gate 		entsize = sizeof (GElf_Rel);
9310Sstevel@tonic-gate 	else {
9320Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
9330Sstevel@tonic-gate 		return (NULL);
9340Sstevel@tonic-gate 	}
9350Sstevel@tonic-gate 	EDATA_READLOCKS(src);
9360Sstevel@tonic-gate 
9370Sstevel@tonic-gate 	if ((entsize * ndx) > src->d_size) {
9380Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
9390Sstevel@tonic-gate 		dst = NULL;
9400Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
9410Sstevel@tonic-gate 		Elf32_Rel * r = &((Elf32_Rel *)src->d_buf)[ndx];
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 		dst->r_offset	= (GElf_Addr)r->r_offset;
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 		/*
9460Sstevel@tonic-gate 		 * Elf32 will never have the extra data field that
9470Sstevel@tonic-gate 		 * Elf64's r_info field can have, so ignore it.
9480Sstevel@tonic-gate 		 */
9490Sstevel@tonic-gate 		/* LINTED */
9500Sstevel@tonic-gate 		dst->r_info	= ELF64_R_INFO(ELF32_R_SYM(r->r_info),
9510Sstevel@tonic-gate 					ELF32_R_TYPE(r->r_info));
9520Sstevel@tonic-gate 	} else
9530Sstevel@tonic-gate 		*dst = ((Elf64_Rel *)src->d_buf)[ndx];
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate 	EDATA_READUNLOCKS(src);
9560Sstevel@tonic-gate 	return (dst);
9570Sstevel@tonic-gate }
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 
9600Sstevel@tonic-gate int
9610Sstevel@tonic-gate gelf_update_rel(Elf_Data *dst, int ndx, GElf_Rel *src)
9620Sstevel@tonic-gate {
9630Sstevel@tonic-gate 	int	class, rc = 1;
9640Sstevel@tonic-gate 	size_t	entsize;
9650Sstevel@tonic-gate 
9660Sstevel@tonic-gate 	if (dst == NULL)
9670Sstevel@tonic-gate 		return (0);
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate 	class = EDATA_CLASS(dst);
9700Sstevel@tonic-gate 	if (class == ELFCLASS32)
9710Sstevel@tonic-gate 		entsize = sizeof (Elf32_Rel);
9720Sstevel@tonic-gate 	else if (class == ELFCLASS64)
9730Sstevel@tonic-gate 		entsize = sizeof (GElf_Rel);
9740Sstevel@tonic-gate 	else {
9750Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
9760Sstevel@tonic-gate 		return (0);
9770Sstevel@tonic-gate 	}
9780Sstevel@tonic-gate 	ELFWLOCK(EDATA_ELF(dst));
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate 	if ((entsize * ndx) > dst->d_size) {
9810Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
9820Sstevel@tonic-gate 		rc = 0;
9830Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
9840Sstevel@tonic-gate 		Elf32_Rel * r = &((Elf32_Rel *)dst->d_buf)[ndx];
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate 		/* LINTED */
9870Sstevel@tonic-gate 		r->r_offset	= (Elf32_Addr) src->r_offset;
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 		/*
9900Sstevel@tonic-gate 		 * Elf32 will never have the extra data field that
9910Sstevel@tonic-gate 		 * Elf64's r_info field can have, so ignore it.
9920Sstevel@tonic-gate 		 */
9930Sstevel@tonic-gate 		/* LINTED */
9940Sstevel@tonic-gate 		r->r_info	= ELF32_R_INFO(
9950Sstevel@tonic-gate 					ELF64_R_SYM(src->r_info),
9960Sstevel@tonic-gate 					ELF64_R_TYPE(src->r_info));
9970Sstevel@tonic-gate 
9980Sstevel@tonic-gate 	} else
9990Sstevel@tonic-gate 		((Elf64_Rel *)dst->d_buf)[ndx] = *(Elf64_Rel *)src;
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate 	ELFUNLOCK(EDATA_ELF(dst));
10020Sstevel@tonic-gate 	return (rc);
10030Sstevel@tonic-gate }
10040Sstevel@tonic-gate 
10050Sstevel@tonic-gate long
10060Sstevel@tonic-gate gelf_checksum(Elf *elf)
10070Sstevel@tonic-gate {
10080Sstevel@tonic-gate 	int class = gelf_getclass(elf);
10090Sstevel@tonic-gate 
10100Sstevel@tonic-gate 	if (class == ELFCLASS32)
10110Sstevel@tonic-gate 		return (elf32_checksum(elf));
10120Sstevel@tonic-gate 	else if (class == ELFCLASS64)
10130Sstevel@tonic-gate 		return (elf64_checksum(elf));
10140Sstevel@tonic-gate 
10150Sstevel@tonic-gate 	_elf_seterr(EREQ_CLASS, 0);
10160Sstevel@tonic-gate 	return (0);
10170Sstevel@tonic-gate }
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate GElf_Cap *
10200Sstevel@tonic-gate gelf_getcap(Elf_Data *data, int ndx, GElf_Cap *dst)
10210Sstevel@tonic-gate {
10220Sstevel@tonic-gate 	int	class;
10230Sstevel@tonic-gate 	size_t	entsize;
10240Sstevel@tonic-gate 
10250Sstevel@tonic-gate 	if (data == NULL)
10260Sstevel@tonic-gate 		return (NULL);
10270Sstevel@tonic-gate 
10280Sstevel@tonic-gate 	class = EDATA_CLASS(data);
10290Sstevel@tonic-gate 	if (class == ELFCLASS32)
10300Sstevel@tonic-gate 		entsize = sizeof (Elf32_Cap);
10310Sstevel@tonic-gate 	else if (class == ELFCLASS64)
10320Sstevel@tonic-gate 		entsize = sizeof (GElf_Cap);
10330Sstevel@tonic-gate 	else {
10340Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
10350Sstevel@tonic-gate 		return (NULL);
10360Sstevel@tonic-gate 	}
10370Sstevel@tonic-gate 
10380Sstevel@tonic-gate 	EDATA_READLOCKS(data);
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 	if ((entsize * ndx) > data->d_size) {
10410Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
10420Sstevel@tonic-gate 		dst = NULL;
10430Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
10440Sstevel@tonic-gate 		Elf32_Cap	*c = &(((Elf32_Cap *)data->d_buf)[ndx]);
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 		dst->c_tag = (Elf64_Xword)c->c_tag;
10470Sstevel@tonic-gate 		dst->c_un.c_val = (Elf64_Xword)c->c_un.c_val;
10480Sstevel@tonic-gate 	} else
10490Sstevel@tonic-gate 		*dst = ((GElf_Cap *)data->d_buf)[ndx];
10500Sstevel@tonic-gate 
10510Sstevel@tonic-gate 	EDATA_READUNLOCKS(data);
10520Sstevel@tonic-gate 	return (dst);
10530Sstevel@tonic-gate }
10540Sstevel@tonic-gate 
10550Sstevel@tonic-gate int
10560Sstevel@tonic-gate gelf_update_cap(Elf_Data *dst, int ndx, GElf_Cap *src)
10570Sstevel@tonic-gate {
10580Sstevel@tonic-gate 	int	class, rc = 1;
10590Sstevel@tonic-gate 	size_t	entsize;
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	if (dst == NULL)
10620Sstevel@tonic-gate 		return (0);
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate 	class = EDATA_CLASS(dst);
10650Sstevel@tonic-gate 	if (class == ELFCLASS32)
10660Sstevel@tonic-gate 		entsize = sizeof (Elf32_Cap);
10670Sstevel@tonic-gate 	else if (class == ELFCLASS64)
10680Sstevel@tonic-gate 		entsize = sizeof (GElf_Cap);
10690Sstevel@tonic-gate 	else {
10700Sstevel@tonic-gate 		_elf_seterr(EREQ_CLASS, 0);
10710Sstevel@tonic-gate 		return (0);
10720Sstevel@tonic-gate 	}
10730Sstevel@tonic-gate 
10740Sstevel@tonic-gate 	ELFWLOCK(EDATA_ELF(dst));
10750Sstevel@tonic-gate 
10760Sstevel@tonic-gate 	if ((entsize * ndx) > dst->d_size) {
10770Sstevel@tonic-gate 		_elf_seterr(EREQ_RAND, 0);
10780Sstevel@tonic-gate 		rc = 0;
10790Sstevel@tonic-gate 	} else if (class == ELFCLASS32) {
10800Sstevel@tonic-gate 		Elf32_Cap	*c = &(((Elf32_Cap *)dst->d_buf)[ndx]);
10810Sstevel@tonic-gate 
10820Sstevel@tonic-gate 		c->c_tag = (Elf32_Word)src->c_tag;
10830Sstevel@tonic-gate 		c->c_un.c_val = (Elf32_Word)src->c_un.c_val;
10840Sstevel@tonic-gate 	} else
10850Sstevel@tonic-gate 		((Elf64_Cap *)dst->d_buf)[ndx] = *((Elf64_Cap *)src);
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate 	ELFUNLOCK(EDATA_ELF(dst));
10880Sstevel@tonic-gate 	return (rc);
10890Sstevel@tonic-gate }
1090