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