Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <string.h>
     27 #include "_libelf.h"
     28 #include "decl.h"
     29 #include "msg.h"
     30 
     31 
     32 /*
     33  * Find elf or it's class from a pointer to an Elf_Data struct.
     34  * Warning:  this Assumes that the Elf_Data is part of a libelf
     35  * Dnode structure, which is expected to be true for any Elf_Data
     36  * passed into libelf *except* for the xlatetof() and xlatetom() functions.
     37  */
     38 #define	EDATA_CLASS(edata) \
     39 	(((Dnode *)(edata))->db_scn->s_elf->ed_class)
     40 
     41 #define	EDATA_ELF(edata) \
     42 	(((Dnode *)(edata))->db_scn->s_elf)
     43 
     44 #define	EDATA_SCN(edata) \
     45 	(((Dnode *)(edata))->db_scn)
     46 
     47 #define	EDATA_READLOCKS(edata) \
     48 	READLOCKS(EDATA_ELF((edata)), EDATA_SCN((edata)))
     49 
     50 #define	EDATA_READUNLOCKS(edata) \
     51 	READUNLOCKS(EDATA_ELF((edata)), EDATA_SCN((edata)))
     52 
     53 
     54 size_t
     55 gelf_fsize(Elf * elf, Elf_Type type, size_t count, unsigned ver)
     56 {
     57 	int class;
     58 
     59 	if (elf == NULL)
     60 		return (0);
     61 
     62 	class = gelf_getclass(elf);
     63 	if (class == ELFCLASS32)
     64 		return (elf32_fsize(type, count, ver));
     65 	else if (class == ELFCLASS64)
     66 		return (elf64_fsize(type, count, ver));
     67 
     68 	_elf_seterr(EREQ_CLASS, 0);
     69 	return (0);
     70 }
     71 
     72 
     73 int
     74 gelf_getclass(Elf *elf)
     75 {
     76 	if (elf == NULL)
     77 		return (0);
     78 
     79 	/*
     80 	 * Don't rely on the idents, a new ehdr doesn't have it!
     81 	 */
     82 	return (elf->ed_class);
     83 }
     84 
     85 
     86 GElf_Ehdr *
     87 gelf_getehdr(Elf *elf, GElf_Ehdr *dst)
     88 {
     89 	int class;
     90 
     91 	if (elf == NULL)
     92 		return (NULL);
     93 
     94 	class = gelf_getclass(elf);
     95 	if (class == ELFCLASS32) {
     96 		Elf32_Ehdr * e		= elf32_getehdr(elf);
     97 
     98 		if (e == NULL)
     99 			return (NULL);
    100 
    101 		ELFRLOCK(elf);
    102 		(void) memcpy(dst->e_ident, e->e_ident, EI_NIDENT);
    103 		dst->e_type		= e->e_type;
    104 		dst->e_machine		= e->e_machine;
    105 		dst->e_version		= e->e_version;
    106 		dst->e_entry		= (Elf64_Addr)e->e_entry;
    107 		dst->e_phoff		= (Elf64_Off)e->e_phoff;
    108 		dst->e_shoff		= (Elf64_Off)e->e_shoff;
    109 		dst->e_flags		= e->e_flags;
    110 		dst->e_ehsize		= e->e_ehsize;
    111 		dst->e_phentsize	= e->e_phentsize;
    112 		dst->e_phnum		= e->e_phnum;
    113 		dst->e_shentsize	= e->e_shentsize;
    114 		dst->e_shnum		= e->e_shnum;
    115 		dst->e_shstrndx		= e->e_shstrndx;
    116 		ELFUNLOCK(elf);
    117 
    118 		return (dst);
    119 	} else if (class == ELFCLASS64) {
    120 		Elf64_Ehdr * e		= elf64_getehdr(elf);
    121 
    122 		if (e == NULL)
    123 			return (NULL);
    124 
    125 		ELFRLOCK(elf);
    126 		*dst			= *e;
    127 		ELFUNLOCK(elf);
    128 
    129 		return (dst);
    130 	}
    131 
    132 	_elf_seterr(EREQ_CLASS, 0);
    133 	return (NULL);
    134 }
    135 
    136 
    137 int
    138 gelf_update_ehdr(Elf *elf, GElf_Ehdr *src)
    139 {
    140 	int class;
    141 
    142 	if (elf == NULL)
    143 		return (0);
    144 
    145 	/*
    146 	 * In case elf isn't cooked.
    147 	 */
    148 	class = gelf_getclass(elf);
    149 	if (class == ELFCLASSNONE)
    150 		class = src->e_ident[EI_CLASS];
    151 
    152 
    153 	if (class == ELFCLASS32) {
    154 		Elf32_Ehdr * d	= elf32_getehdr(elf);
    155 
    156 		if (d == NULL)
    157 			return (0);
    158 
    159 		ELFWLOCK(elf);
    160 		(void) memcpy(d->e_ident, src->e_ident, EI_NIDENT);
    161 		d->e_type	= src->e_type;
    162 		d->e_machine	= src->e_machine;
    163 		d->e_version	= src->e_version;
    164 		/* LINTED */
    165 		d->e_entry	= (Elf32_Addr)src->e_entry;
    166 		/* LINTED */
    167 		d->e_phoff	= (Elf32_Off)src->e_phoff;
    168 		/* LINTED */
    169 		d->e_shoff	= (Elf32_Off)src->e_shoff;
    170 		/* could memcpy the rest of these... */
    171 		d->e_flags	= src->e_flags;
    172 		d->e_ehsize	= src->e_ehsize;
    173 		d->e_phentsize	= src->e_phentsize;
    174 		d->e_phnum	= src->e_phnum;
    175 		d->e_shentsize	= src->e_shentsize;
    176 		d->e_shnum	= src->e_shnum;
    177 		d->e_shstrndx	= src->e_shstrndx;
    178 		ELFUNLOCK(elf);
    179 
    180 		return (1);
    181 	} else if (class == ELFCLASS64) {
    182 		Elf64_Ehdr * d	= elf64_getehdr(elf);
    183 
    184 		if (d == NULL)
    185 			return (0);
    186 
    187 		ELFWLOCK(elf);
    188 		*d		= *(Elf64_Ehdr *)src;
    189 		ELFUNLOCK(elf);
    190 
    191 		return (1);
    192 	}
    193 
    194 	_elf_seterr(EREQ_CLASS, 0);
    195 	return (0);
    196 }
    197 
    198 
    199 unsigned long
    200 gelf_newehdr(Elf *elf, int class)
    201 {
    202 	if (elf == NULL)
    203 		return (0);
    204 
    205 	if (class == ELFCLASS32)
    206 		return ((unsigned long)elf32_newehdr(elf));
    207 	else if (class == ELFCLASS64)
    208 		return ((unsigned long)elf64_newehdr(elf));
    209 
    210 	_elf_seterr(EREQ_CLASS, 0);
    211 	return (0);
    212 }
    213 
    214 
    215 GElf_Phdr *
    216 gelf_getphdr(Elf *elf, int ndx, GElf_Phdr *dst)
    217 {
    218 	int		class;
    219 	size_t		phnum;
    220 
    221 	if (elf == NULL)
    222 		return (NULL);
    223 
    224 	if (elf_getphdrnum(elf, &phnum) == -1)
    225 		return (NULL);
    226 
    227 	if (phnum <= ndx) {
    228 		_elf_seterr(EREQ_RAND, 0);
    229 		return (NULL);
    230 	}
    231 
    232 	class = gelf_getclass(elf);
    233 	if ((class != ELFCLASS32) && (class != ELFCLASS64)) {
    234 		_elf_seterr(EREQ_CLASS, 0);
    235 		return (NULL);
    236 	}
    237 
    238 	if (class == ELFCLASS32) {
    239 		Elf32_Phdr *p	= &((Elf32_Phdr *)elf32_getphdr(elf))[ndx];
    240 
    241 		ELFRLOCK(elf);
    242 		dst->p_type	= p->p_type;
    243 		dst->p_flags	= p->p_flags;
    244 		dst->p_offset	= (Elf64_Off)p->p_offset;
    245 		dst->p_vaddr	= (Elf64_Addr)p->p_vaddr;
    246 		dst->p_paddr	= (Elf64_Addr)p->p_paddr;
    247 		dst->p_filesz	= (Elf64_Xword)p->p_filesz;
    248 		dst->p_memsz	= (Elf64_Xword)p->p_memsz;
    249 		dst->p_align	= (Elf64_Xword)p->p_align;
    250 		ELFUNLOCK(elf);
    251 	} else if (class == ELFCLASS64) {
    252 		Elf64_Phdr *phdrs = elf64_getphdr(elf);
    253 		ELFRLOCK(elf);
    254 		*dst = ((GElf_Phdr *)phdrs)[ndx];
    255 		ELFUNLOCK(elf);
    256 	}
    257 
    258 	return (dst);
    259 }
    260 
    261 
    262 int
    263 gelf_update_phdr(Elf *elf, int ndx, GElf_Phdr *src)
    264 {
    265 	int		class;
    266 	size_t		phnum;
    267 
    268 	if (elf == NULL)
    269 		return (0);
    270 
    271 	if (elf_getphdrnum(elf, &phnum) == -1)
    272 		return (NULL);
    273 
    274 	if (phnum < ndx) {
    275 		_elf_seterr(EREQ_RAND, 0);
    276 		return (0);
    277 	}
    278 
    279 	class = gelf_getclass(elf);
    280 	if (class == ELFCLASS32) {
    281 		Elf32_Phdr *dst	= &((Elf32_Phdr *)elf32_getphdr(elf))[ndx];
    282 		ELFWLOCK(elf);
    283 		dst->p_type	= src->p_type;
    284 		dst->p_flags	= src->p_flags;
    285 		/* LINTED */
    286 		dst->p_offset	= (Elf32_Off)src->p_offset;
    287 		/* LINTED */
    288 		dst->p_vaddr	= (Elf32_Addr)src->p_vaddr;
    289 		/* LINTED */
    290 		dst->p_paddr	= (Elf32_Addr)src->p_paddr;
    291 		/* LINTED */
    292 		dst->p_filesz	= (Elf32_Word)src->p_filesz;
    293 		/* LINTED */
    294 		dst->p_memsz	= (Elf32_Word)src->p_memsz;
    295 		/* LINTED */
    296 		dst->p_align	= (Elf32_Word)src->p_align;
    297 		ELFUNLOCK(elf);
    298 	} else if (class == ELFCLASS64) {
    299 		Elf64_Phdr *dst = elf64_getphdr(elf);
    300 		ELFWLOCK(elf);
    301 		dst[ndx] = *(GElf_Phdr *)src;
    302 		ELFUNLOCK(elf);
    303 	} else {
    304 		_elf_seterr(EREQ_CLASS, 0);
    305 		return (0);
    306 	}
    307 	return (1);
    308 }
    309 
    310 
    311 unsigned long
    312 gelf_newphdr(Elf *elf, size_t phnum)
    313 {
    314 	int class;
    315 
    316 	if (elf == NULL)
    317 		return (0);
    318 
    319 	class = gelf_getclass(elf);
    320 	if (class == ELFCLASS32)
    321 		return ((unsigned long)elf32_newphdr(elf, phnum));
    322 	else if (class == ELFCLASS64)
    323 		return ((unsigned long)elf64_newphdr(elf, phnum));
    324 
    325 	_elf_seterr(EREQ_CLASS, 0);
    326 	return (0);
    327 }
    328 
    329 
    330 GElf_Shdr *
    331 gelf_getshdr(Elf_Scn *scn,  GElf_Shdr *dst)
    332 {
    333 	if (scn == NULL)
    334 		return (NULL);
    335 
    336 	if (scn->s_elf->ed_class == ELFCLASS32) {
    337 		Elf32_Shdr *s		= elf32_getshdr(scn);
    338 
    339 		if (s == NULL)
    340 			return (NULL);
    341 
    342 		READLOCKS(scn->s_elf, scn);
    343 		dst->sh_name		= s->sh_name;
    344 		dst->sh_type		= s->sh_type;
    345 		dst->sh_flags		= (Elf64_Xword)s->sh_flags;
    346 		dst->sh_addr		= (Elf64_Addr)s->sh_addr;
    347 		dst->sh_offset		= (Elf64_Off)s->sh_offset;
    348 		dst->sh_size		= (Elf64_Xword)s->sh_size;
    349 		dst->sh_link		= s->sh_link;
    350 		dst->sh_info		= s->sh_info;
    351 		dst->sh_addralign	= (Elf64_Xword)s->sh_addralign;
    352 		dst->sh_entsize		= (Elf64_Xword)s->sh_entsize;
    353 		READUNLOCKS(scn->s_elf, scn);
    354 
    355 		return (dst);
    356 	} else if (scn->s_elf->ed_class == ELFCLASS64) {
    357 		Elf64_Shdr *s		= elf64_getshdr(scn);
    358 
    359 		if (s == NULL)
    360 			return (NULL);
    361 
    362 		READLOCKS(scn->s_elf, scn);
    363 		*dst			= *(Elf64_Shdr *)s;
    364 		READUNLOCKS(scn->s_elf, scn);
    365 
    366 		return (dst);
    367 	}
    368 
    369 	_elf_seterr(EREQ_CLASS, 0);
    370 	return (NULL);
    371 }
    372 
    373 
    374 int
    375 gelf_update_shdr(Elf_Scn *scn, GElf_Shdr *src)
    376 {
    377 	if (scn == NULL)
    378 		return (0);
    379 
    380 	if (scn->s_elf->ed_class == ELFCLASS32) {
    381 		Elf32_Shdr *dst	= elf32_getshdr(scn);
    382 
    383 		if (dst == NULL)
    384 			return (0);
    385 
    386 		ELFWLOCK(scn->s_elf);
    387 		dst->sh_name		= src->sh_name;
    388 		dst->sh_type		= src->sh_type;
    389 		/* LINTED */
    390 		dst->sh_flags		= (Elf32_Word)src->sh_flags;
    391 		/* LINTED */
    392 		dst->sh_addr		= (Elf32_Addr)src->sh_addr;
    393 		/* LINTED */
    394 		dst->sh_offset		= (Elf32_Off) src->sh_offset;
    395 		/* LINTED */
    396 		dst->sh_size		= (Elf32_Word)src->sh_size;
    397 		dst->sh_link		= src->sh_link;
    398 		dst->sh_info		= src->sh_info;
    399 		/* LINTED */
    400 		dst->sh_addralign	= (Elf32_Word)src->sh_addralign;
    401 		/* LINTED */
    402 		dst->sh_entsize		= (Elf32_Word)src->sh_entsize;
    403 
    404 		ELFUNLOCK(scn->s_elf);
    405 		return (1);
    406 	} else if (scn->s_elf->ed_class == ELFCLASS64) {
    407 		Elf64_Shdr * dst	= elf64_getshdr(scn);
    408 
    409 		if (dst == NULL)
    410 			return (0);
    411 
    412 		ELFWLOCK(scn->s_elf);
    413 		*dst			= *(Elf64_Shdr *)src;
    414 		ELFUNLOCK(scn->s_elf);
    415 		return (1);
    416 	}
    417 
    418 	_elf_seterr(EREQ_CLASS, 0);
    419 	return (0);
    420 }
    421 
    422 
    423 /*
    424  * gelf_xlatetof/gelf_xlatetom use 'elf' to find the class
    425  * because these are the odd case where the Elf_Data structs
    426  * might not have been allocated by libelf (and therefore
    427  * don't have Dnode's associated with them).
    428  */
    429 Elf_Data *
    430 gelf_xlatetof(Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode)
    431 {
    432 	int class;
    433 
    434 	if ((elf == NULL) || (dst == NULL) || (src == NULL))
    435 		return (NULL);
    436 
    437 	class = gelf_getclass(elf);
    438 	if (class == ELFCLASS32)
    439 		return (elf32_xlatetof(dst, src, encode));
    440 	else if (class == ELFCLASS64)
    441 		return (elf64_xlatetof(dst, src, encode));
    442 
    443 	_elf_seterr(EREQ_CLASS, 0);
    444 	return (NULL);
    445 }
    446 
    447 
    448 Elf_Data *
    449 gelf_xlatetom(Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode)
    450 {
    451 	int class;
    452 
    453 	if ((elf == NULL) || (dst == NULL) || (src == NULL))
    454 		return (NULL);
    455 
    456 	class = gelf_getclass(elf);
    457 	if (class == ELFCLASS32)
    458 		return (elf32_xlatetom(dst, src, encode));
    459 	else if (class == ELFCLASS64)
    460 		return (elf64_xlatetom(dst, src, encode));
    461 
    462 	_elf_seterr(EREQ_CLASS, 0);
    463 	return (NULL);
    464 }
    465 
    466 
    467 GElf_Sym *
    468 gelf_getsym(Elf_Data * data, int ndx, GElf_Sym * dst)
    469 {
    470 	int	class;
    471 	size_t	entsize;
    472 
    473 	if (data == NULL)
    474 		return (NULL);
    475 
    476 	class = EDATA_CLASS(data);
    477 	if (class == ELFCLASS32)
    478 		entsize = sizeof (Elf32_Sym);
    479 	else if (class == ELFCLASS64)
    480 		entsize = sizeof (GElf_Sym);
    481 	else {
    482 		_elf_seterr(EREQ_CLASS, 0);
    483 		return (NULL);
    484 	}
    485 
    486 	EDATA_READLOCKS(data);
    487 
    488 	if ((entsize * ndx) >= data->d_size) {
    489 		_elf_seterr(EREQ_RAND, 0);
    490 		dst = NULL;
    491 	} else if (class == ELFCLASS32) {
    492 		Elf32_Sym	*s;
    493 		s		= &(((Elf32_Sym *)data->d_buf)[ndx]);
    494 		dst->st_name	= s->st_name;
    495 		dst->st_value	= (Elf64_Addr)s->st_value;
    496 		dst->st_size	= (Elf64_Xword)s->st_size;
    497 		dst->st_info	= ELF64_ST_INFO(ELF32_ST_BIND(s->st_info),
    498 		    ELF32_ST_TYPE(s->st_info));
    499 		dst->st_other	= s->st_other;
    500 		dst->st_shndx	= s->st_shndx;
    501 	} else
    502 		*dst = ((GElf_Sym *)data->d_buf)[ndx];
    503 
    504 	EDATA_READUNLOCKS(data);
    505 	return (dst);
    506 }
    507 
    508 
    509 int
    510 gelf_update_sym(Elf_Data *dst, int ndx, GElf_Sym *src)
    511 {
    512 	int	class, rc = 1;
    513 	size_t	entsize;
    514 
    515 	if (dst == NULL)
    516 		return (0);
    517 
    518 	class = EDATA_CLASS(dst);
    519 	if (class == ELFCLASS32)
    520 		entsize = sizeof (Elf32_Sym);
    521 	else if (class == ELFCLASS64)
    522 		entsize = sizeof (GElf_Sym);
    523 	else {
    524 		_elf_seterr(EREQ_CLASS, 0);
    525 		return (0);
    526 	}
    527 
    528 	ELFWLOCK(EDATA_ELF(dst));
    529 
    530 	if ((entsize * ndx) >= dst->d_size) {
    531 		_elf_seterr(EREQ_RAND, 0);
    532 		rc = 0;
    533 	} else if (class == ELFCLASS32) {
    534 		Elf32_Sym * d;
    535 
    536 		d		= &(((Elf32_Sym *)dst->d_buf)[ndx]);
    537 		d->st_name	= src->st_name;
    538 		/* LINTED */
    539 		d->st_value	= (Elf32_Addr)src->st_value;
    540 		/* LINTED */
    541 		d->st_size	= (Elf32_Word)src->st_size;
    542 		d->st_info	= ELF32_ST_INFO(ELF64_ST_BIND(src->st_info),
    543 		    ELF64_ST_TYPE(src->st_info));
    544 		d->st_other	= src->st_other;
    545 		d->st_shndx	= src->st_shndx;
    546 	} else
    547 		((Elf64_Sym *)dst->d_buf)[ndx] = *((Elf64_Sym *)src);
    548 
    549 	ELFUNLOCK(EDATA_ELF(dst));
    550 	return (rc);
    551 }
    552 
    553 
    554 GElf_Syminfo *
    555 gelf_getsyminfo(Elf_Data *data, int ndx, GElf_Syminfo *dst)
    556 {
    557 	int	class;
    558 	size_t	entsize;
    559 
    560 	if (data == NULL)
    561 		return (NULL);
    562 
    563 	class = EDATA_CLASS(data);
    564 	if (class == ELFCLASS32)
    565 		entsize = sizeof (Elf32_Syminfo);
    566 	else if (class == ELFCLASS64)
    567 		entsize = sizeof (GElf_Syminfo);
    568 	else {
    569 		_elf_seterr(EREQ_CLASS, 0);
    570 		return (NULL);
    571 	}
    572 	EDATA_READLOCKS(data);
    573 
    574 	if ((entsize * ndx) >= data->d_size) {
    575 		_elf_seterr(EREQ_RAND, 0);
    576 		dst = NULL;
    577 	} else if (class == ELFCLASS32) {
    578 		Elf32_Syminfo *	si;
    579 
    580 		si		= &(((Elf32_Syminfo *)data->d_buf)[ndx]);
    581 		dst->si_boundto = si->si_boundto;
    582 		dst->si_flags	= si->si_flags;
    583 	} else
    584 		*dst		= ((GElf_Syminfo *)data->d_buf)[ndx];
    585 
    586 	EDATA_READUNLOCKS(data);
    587 	return (dst);
    588 }
    589 
    590 int
    591 gelf_update_syminfo(Elf_Data *dst, int ndx, GElf_Syminfo *src)
    592 {
    593 	int	class, rc = 1;
    594 	size_t	entsize;
    595 
    596 	if (dst == NULL)
    597 		return (0);
    598 
    599 	class = EDATA_CLASS(dst);
    600 	if (class == ELFCLASS32)
    601 		entsize = sizeof (Elf32_Syminfo);
    602 	else if (class == ELFCLASS64)
    603 		entsize = sizeof (GElf_Syminfo);
    604 	else {
    605 		_elf_seterr(EREQ_CLASS, 0);
    606 		return (0);
    607 	}
    608 	ELFWLOCK(EDATA_ELF(dst));
    609 
    610 	if ((entsize * ndx) >= dst->d_size) {
    611 		_elf_seterr(EREQ_RAND, 0);
    612 		rc = 0;
    613 	} else if (class == ELFCLASS32) {
    614 		Elf32_Syminfo * d	= &(((Elf32_Syminfo *)dst->d_buf)[ndx]);
    615 		d->si_boundto		= src->si_boundto;
    616 		d->si_flags		= src->si_flags;
    617 	} else
    618 		((Elf64_Syminfo *)dst->d_buf)[ndx] = *((Elf64_Syminfo *)src);
    619 
    620 	ELFUNLOCK(EDATA_ELF(dst));
    621 	return (rc);
    622 }
    623 
    624 GElf_Dyn *
    625 gelf_getdyn(Elf_Data *data, int ndx, GElf_Dyn *dst)
    626 {
    627 	int	class;
    628 	size_t	entsize;
    629 
    630 	if (data == NULL)
    631 		return (NULL);
    632 
    633 	class = EDATA_CLASS(data);
    634 	if (class == ELFCLASS32)
    635 		entsize = sizeof (Elf32_Dyn);
    636 	else if (class == ELFCLASS64)
    637 		entsize = sizeof (GElf_Dyn);
    638 	else {
    639 		_elf_seterr(EREQ_CLASS, 0);
    640 		return (NULL);
    641 	}
    642 	EDATA_READLOCKS(data);
    643 
    644 	if ((entsize * ndx) >= data->d_size) {
    645 		_elf_seterr(EREQ_RAND, 0);
    646 		dst = NULL;
    647 	} else if (class == ELFCLASS32) {
    648 		Elf32_Dyn * d = &((Elf32_Dyn *)data->d_buf)[ndx];
    649 
    650 		dst->d_tag	= (Elf32_Sword)d->d_tag;
    651 		dst->d_un.d_val	= (Elf32_Word) d->d_un.d_val;
    652 	} else
    653 		*dst = ((Elf64_Dyn *)data->d_buf)[ndx];
    654 
    655 	EDATA_READUNLOCKS(data);
    656 	return (dst);
    657 }
    658 
    659 
    660 int
    661 gelf_update_dyn(Elf_Data *dst, int ndx, GElf_Dyn *src)
    662 {
    663 	int	class, rc = 1;
    664 	size_t	entsize;
    665 
    666 	if (dst == NULL)
    667 		return (0);
    668 
    669 	class = EDATA_CLASS(dst);
    670 	if (class == ELFCLASS32)
    671 		entsize = sizeof (Elf32_Dyn);
    672 	else if (class == ELFCLASS64)
    673 		entsize = sizeof (GElf_Dyn);
    674 	else {
    675 		_elf_seterr(EREQ_CLASS, 0);
    676 		return (0);
    677 	}
    678 	ELFWLOCK(EDATA_ELF(dst));
    679 
    680 	if ((entsize * ndx) >= dst->d_size) {
    681 		_elf_seterr(EREQ_RAND, 0);
    682 		rc = 0;
    683 	} else if (class == ELFCLASS32) {
    684 		Elf32_Dyn * d = &((Elf32_Dyn *)dst->d_buf)[ndx];
    685 
    686 		/* LINTED */
    687 		d->d_tag	= (Elf32_Word)src->d_tag;
    688 		/* LINTED */
    689 		d->d_un.d_val	= (Elf32_Word)src->d_un.d_val;
    690 	} else
    691 		((Elf64_Dyn *)dst->d_buf)[ndx] = *(Elf64_Dyn*)src;
    692 
    693 	ELFUNLOCK(EDATA_ELF(dst));
    694 	return (rc);
    695 }
    696 
    697 
    698 
    699 GElf_Sym *
    700 gelf_getsymshndx(Elf_Data *symdata, Elf_Data *shndxdata,
    701 	int ndx, GElf_Sym *symptr, Elf32_Word *xshndx)
    702 {
    703 	if (gelf_getsym(symdata, ndx, symptr) == 0)
    704 		return (NULL);
    705 	if (shndxdata && xshndx) {
    706 		EDATA_READLOCKS(shndxdata);
    707 		if ((ndx * sizeof (Elf32_Word)) >= shndxdata->d_size) {
    708 			_elf_seterr(EREQ_RAND, 0);
    709 			EDATA_READUNLOCKS(shndxdata);
    710 			return (NULL);
    711 		}
    712 		*xshndx = (((Elf32_Word *)shndxdata->d_buf)[ndx]);
    713 		EDATA_READUNLOCKS(shndxdata);
    714 	} else {
    715 		*xshndx = 0;
    716 	}
    717 	return (symptr);
    718 }
    719 
    720 int
    721 gelf_update_symshndx(Elf_Data *symdata, Elf_Data *shndxdata,
    722 	int ndx, GElf_Sym *symptr, Elf32_Word xshndx)
    723 {
    724 	if (gelf_update_sym(symdata, ndx, symptr) == 0)
    725 		return (0);
    726 	if (shndxdata) {
    727 		ELFWLOCK(EDATA_ELF(shndxdata));
    728 		if ((ndx * sizeof (Elf32_Word)) >= shndxdata->d_size) {
    729 			_elf_seterr(EREQ_RAND, 0);
    730 			ELFUNLOCK(EDATA_ELF(shndxdata));
    731 			return (0);
    732 		}
    733 		((Elf32_Word *)shndxdata->d_buf)[ndx] = xshndx;
    734 		ELFUNLOCK(EDATA_ELF(shndxdata));
    735 	}
    736 	return (1);
    737 }
    738 
    739 
    740 GElf_Move *
    741 gelf_getmove(Elf_Data *src, int ndx, GElf_Move *dst)
    742 {
    743 	int	class;
    744 	size_t	entsize;
    745 
    746 	if (src == NULL)
    747 		return (NULL);
    748 
    749 	class = EDATA_CLASS(src);
    750 	if (class == ELFCLASS32)
    751 		entsize = sizeof (Elf32_Move);
    752 	else if (class == ELFCLASS64)
    753 		entsize = sizeof (GElf_Move);
    754 	else {
    755 		_elf_seterr(EREQ_CLASS, 0);
    756 		return (NULL);
    757 	}
    758 	EDATA_READLOCKS(src);
    759 
    760 	if ((entsize * ndx) >= src->d_size) {
    761 		_elf_seterr(EREQ_RAND, 0);
    762 		dst = NULL;
    763 	} else if (class == ELFCLASS32) {
    764 		Elf32_Move * m = &((Elf32_Move *)src->d_buf)[ndx];
    765 
    766 		dst->m_poffset = (Elf64_Word)m->m_poffset;
    767 		dst->m_repeat = (Elf64_Xword)m->m_repeat;
    768 		dst->m_stride = (Elf64_Half)m->m_stride;
    769 		dst->m_value = (Elf64_Xword)m->m_value;
    770 		dst->m_info = ELF64_M_INFO(ELF32_M_SYM(m->m_info),
    771 		    ELF32_M_SIZE(m->m_info));
    772 	} else {
    773 		*dst = ((Elf64_Move *)src->d_buf)[ndx];
    774 	}
    775 
    776 	EDATA_READUNLOCKS(src);
    777 	return (dst);
    778 }
    779 
    780 int
    781 gelf_update_move(Elf_Data *dest, int ndx, GElf_Move *src)
    782 {
    783 	int	class, rc = 1;
    784 	size_t	entsize;
    785 
    786 	if (dest == NULL)
    787 		return (0);
    788 
    789 	class = EDATA_CLASS(dest);
    790 	if (class == ELFCLASS32)
    791 		entsize = sizeof (Elf32_Move);
    792 	else if (class == ELFCLASS64)
    793 		entsize = sizeof (GElf_Move);
    794 	else {
    795 		_elf_seterr(EREQ_CLASS, 0);
    796 		return (0);
    797 	}
    798 	ELFWLOCK(EDATA_ELF(dest));
    799 
    800 	if ((entsize * ndx) >= dest->d_size) {
    801 		_elf_seterr(EREQ_RAND, 0);
    802 		rc = 0;
    803 	} else if (class == ELFCLASS32) {
    804 		Elf32_Move * m = &((Elf32_Move *)dest->d_buf)[ndx];
    805 
    806 		m->m_poffset = (Elf32_Word)src->m_poffset;
    807 		m->m_repeat = (Elf32_Half)src->m_repeat;
    808 		m->m_stride = (Elf32_Half)src->m_stride;
    809 		m->m_value = (Elf32_Lword)src->m_value;
    810 		m->m_info = (Elf32_Word)ELF32_M_INFO(ELF64_M_SYM(src->m_info),
    811 		    ELF64_M_SIZE(src->m_info));
    812 	} else {
    813 		((Elf64_Move *)dest->d_buf)[ndx] = *(Elf64_Move *)src;
    814 	}
    815 
    816 	ELFUNLOCK(EDATA_ELF(dest));
    817 	return (rc);
    818 }
    819 
    820 
    821 GElf_Rela *
    822 gelf_getrela(Elf_Data *src, int ndx, GElf_Rela *dst)
    823 {
    824 	int	class;
    825 	size_t	entsize;
    826 
    827 	if (src == NULL)
    828 		return (NULL);
    829 
    830 	class = EDATA_CLASS(src);
    831 	if (class == ELFCLASS32)
    832 		entsize = sizeof (Elf32_Rela);
    833 	else if (class == ELFCLASS64)
    834 		entsize = sizeof (GElf_Rela);
    835 	else {
    836 		_elf_seterr(EREQ_CLASS, 0);
    837 		return (NULL);
    838 	}
    839 	EDATA_READLOCKS(src);
    840 
    841 	if ((entsize * ndx) >= src->d_size) {
    842 		_elf_seterr(EREQ_RAND, 0);
    843 		dst = NULL;
    844 	} else if (class == ELFCLASS32) {
    845 		Elf32_Rela * r = &((Elf32_Rela *)src->d_buf)[ndx];
    846 
    847 		dst->r_offset	= (GElf_Addr)r->r_offset;
    848 		dst->r_addend	= (GElf_Addr)r->r_addend;
    849 
    850 		/*
    851 		 * Elf32 will never have the extra data field that
    852 		 * Elf64's r_info field can have, so ignore it.
    853 		 */
    854 		/* LINTED */
    855 		dst->r_info	= ELF64_R_INFO(
    856 		    ELF32_R_SYM(r->r_info),
    857 		    ELF32_R_TYPE(r->r_info));
    858 	} else
    859 		*dst = ((Elf64_Rela *)src->d_buf)[ndx];
    860 
    861 	EDATA_READUNLOCKS(src);
    862 	return (dst);
    863 }
    864 
    865 
    866 int
    867 gelf_update_rela(Elf_Data *dst, int ndx, GElf_Rela *src)
    868 {
    869 	int	class, rc = 1;
    870 	size_t	entsize;
    871 
    872 	if (dst == NULL)
    873 		return (0);
    874 
    875 	class = EDATA_CLASS(dst);
    876 	if (class == ELFCLASS32)
    877 		entsize = sizeof (Elf32_Rela);
    878 	else if (class == ELFCLASS64)
    879 		entsize = sizeof (GElf_Rela);
    880 	else {
    881 		_elf_seterr(EREQ_CLASS, 0);
    882 		return (0);
    883 	}
    884 	ELFWLOCK(EDATA_ELF(dst));
    885 
    886 	if ((entsize * ndx) >= dst->d_size) {
    887 		_elf_seterr(EREQ_RAND, 0);
    888 		rc = 0;
    889 	} else if (class == ELFCLASS32) {
    890 		Elf32_Rela * r = &((Elf32_Rela *)dst->d_buf)[ndx];
    891 
    892 		/* LINTED */
    893 		r->r_offset	= (Elf32_Addr) src->r_offset;
    894 		/* LINTED */
    895 		r->r_addend	= (Elf32_Sword)src->r_addend;
    896 
    897 		/*
    898 		 * Elf32 will never have the extra data field that
    899 		 * Elf64's r_info field can have, so ignore it.
    900 		 */
    901 		/* LINTED */
    902 		r->r_info	= ELF32_R_INFO(ELF64_R_SYM(src->r_info),
    903 		    ELF64_R_TYPE(src->r_info));
    904 	} else {
    905 		((Elf64_Rela *)dst->d_buf)[ndx] = *(Elf64_Rela *)src;
    906 	}
    907 
    908 	ELFUNLOCK(EDATA_ELF(dst));
    909 
    910 	return (rc);
    911 }
    912 
    913 
    914 GElf_Rel *
    915 gelf_getrel(Elf_Data *src, int ndx, GElf_Rel *dst)
    916 {
    917 	int	class;
    918 	size_t	entsize;
    919 
    920 	if (src == NULL)
    921 		return (NULL);
    922 
    923 	class = EDATA_CLASS(src);
    924 	if (class == ELFCLASS32)
    925 		entsize = sizeof (Elf32_Rel);
    926 	else if (class == ELFCLASS64)
    927 		entsize = sizeof (GElf_Rel);
    928 	else {
    929 		_elf_seterr(EREQ_CLASS, 0);
    930 		return (NULL);
    931 	}
    932 	EDATA_READLOCKS(src);
    933 
    934 	if ((entsize * ndx) >= src->d_size) {
    935 		_elf_seterr(EREQ_RAND, 0);
    936 		dst = NULL;
    937 	} else if (class == ELFCLASS32) {
    938 		Elf32_Rel * r = &((Elf32_Rel *)src->d_buf)[ndx];
    939 
    940 		dst->r_offset	= (GElf_Addr)r->r_offset;
    941 
    942 		/*
    943 		 * Elf32 will never have the extra data field that
    944 		 * Elf64's r_info field can have, so ignore it.
    945 		 */
    946 		/* LINTED */
    947 		dst->r_info	= ELF64_R_INFO(ELF32_R_SYM(r->r_info),
    948 		    ELF32_R_TYPE(r->r_info));
    949 	} else
    950 		*dst = ((Elf64_Rel *)src->d_buf)[ndx];
    951 
    952 	EDATA_READUNLOCKS(src);
    953 	return (dst);
    954 }
    955 
    956 
    957 int
    958 gelf_update_rel(Elf_Data *dst, int ndx, GElf_Rel *src)
    959 {
    960 	int	class, rc = 1;
    961 	size_t	entsize;
    962 
    963 	if (dst == NULL)
    964 		return (0);
    965 
    966 	class = EDATA_CLASS(dst);
    967 	if (class == ELFCLASS32)
    968 		entsize = sizeof (Elf32_Rel);
    969 	else if (class == ELFCLASS64)
    970 		entsize = sizeof (GElf_Rel);
    971 	else {
    972 		_elf_seterr(EREQ_CLASS, 0);
    973 		return (0);
    974 	}
    975 	ELFWLOCK(EDATA_ELF(dst));
    976 
    977 	if ((entsize * ndx) >= dst->d_size) {
    978 		_elf_seterr(EREQ_RAND, 0);
    979 		rc = 0;
    980 	} else if (class == ELFCLASS32) {
    981 		Elf32_Rel * r = &((Elf32_Rel *)dst->d_buf)[ndx];
    982 
    983 		/* LINTED */
    984 		r->r_offset	= (Elf32_Addr) src->r_offset;
    985 
    986 		/*
    987 		 * Elf32 will never have the extra data field that
    988 		 * Elf64's r_info field can have, so ignore it.
    989 		 */
    990 		/* LINTED */
    991 		r->r_info	= ELF32_R_INFO(ELF64_R_SYM(src->r_info),
    992 		    ELF64_R_TYPE(src->r_info));
    993 
    994 	} else {
    995 		((Elf64_Rel *)dst->d_buf)[ndx] = *(Elf64_Rel *)src;
    996 	}
    997 
    998 	ELFUNLOCK(EDATA_ELF(dst));
    999 	return (rc);
   1000 }
   1001 
   1002 long
   1003 gelf_checksum(Elf *elf)
   1004 {
   1005 	int class = gelf_getclass(elf);
   1006 
   1007 	if (class == ELFCLASS32)
   1008 		return (elf32_checksum(elf));
   1009 	else if (class == ELFCLASS64)
   1010 		return (elf64_checksum(elf));
   1011 
   1012 	_elf_seterr(EREQ_CLASS, 0);
   1013 	return (0);
   1014 }
   1015 
   1016 GElf_Cap *
   1017 gelf_getcap(Elf_Data *data, int ndx, GElf_Cap *dst)
   1018 {
   1019 	int	class;
   1020 	size_t	entsize;
   1021 
   1022 	if (data == NULL)
   1023 		return (NULL);
   1024 
   1025 	class = EDATA_CLASS(data);
   1026 	if (class == ELFCLASS32)
   1027 		entsize = sizeof (Elf32_Cap);
   1028 	else if (class == ELFCLASS64)
   1029 		entsize = sizeof (GElf_Cap);
   1030 	else {
   1031 		_elf_seterr(EREQ_CLASS, 0);
   1032 		return (NULL);
   1033 	}
   1034 
   1035 	EDATA_READLOCKS(data);
   1036 
   1037 	if ((entsize * ndx) >= data->d_size) {
   1038 		_elf_seterr(EREQ_RAND, 0);
   1039 		dst = NULL;
   1040 	} else if (class == ELFCLASS32) {
   1041 		Elf32_Cap	*c = &(((Elf32_Cap *)data->d_buf)[ndx]);
   1042 
   1043 		dst->c_tag = (Elf64_Xword)c->c_tag;
   1044 		dst->c_un.c_val = (Elf64_Xword)c->c_un.c_val;
   1045 	} else
   1046 		*dst = ((GElf_Cap *)data->d_buf)[ndx];
   1047 
   1048 	EDATA_READUNLOCKS(data);
   1049 	return (dst);
   1050 }
   1051 
   1052 int
   1053 gelf_update_cap(Elf_Data *dst, int ndx, GElf_Cap *src)
   1054 {
   1055 	int	class, rc = 1;
   1056 	size_t	entsize;
   1057 
   1058 	if (dst == NULL)
   1059 		return (0);
   1060 
   1061 	class = EDATA_CLASS(dst);
   1062 	if (class == ELFCLASS32)
   1063 		entsize = sizeof (Elf32_Cap);
   1064 	else if (class == ELFCLASS64)
   1065 		entsize = sizeof (GElf_Cap);
   1066 	else {
   1067 		_elf_seterr(EREQ_CLASS, 0);
   1068 		return (0);
   1069 	}
   1070 
   1071 	ELFWLOCK(EDATA_ELF(dst));
   1072 
   1073 	if ((entsize * ndx) >= dst->d_size) {
   1074 		_elf_seterr(EREQ_RAND, 0);
   1075 		rc = 0;
   1076 	} else if (class == ELFCLASS32) {
   1077 		Elf32_Cap	*c = &(((Elf32_Cap *)dst->d_buf)[ndx]);
   1078 
   1079 		c->c_tag = (Elf32_Word)src->c_tag;
   1080 		c->c_un.c_val = (Elf32_Word)src->c_un.c_val;
   1081 	} else
   1082 		((Elf64_Cap *)dst->d_buf)[ndx] = *((Elf64_Cap *)src);
   1083 
   1084 	ELFUNLOCK(EDATA_ELF(dst));
   1085 	return (rc);
   1086 }
   1087 
   1088 /*
   1089  * If the specified object has a dynamic section, and that section
   1090  * contains a DT_FLAGS_1 entry, then return the value of that entry.
   1091  * Otherwise, return 0.
   1092  */
   1093 GElf_Xword
   1094 _gelf_getdyndtflags_1(Elf *elf)
   1095 {
   1096 	Elf_Scn *scn = NULL;
   1097 	Elf_Data *data;
   1098 	GElf_Shdr shdr;
   1099 	GElf_Dyn dyn;
   1100 	int i, n;
   1101 
   1102 	while (scn = elf_nextscn(elf, scn)) {
   1103 		if (gelf_getshdr(scn, &shdr) == NULL)
   1104 			break;
   1105 		if (shdr.sh_type != SHT_DYNAMIC)
   1106 			continue;
   1107 		if (data = elf_getdata(scn, NULL)) {
   1108 			n = shdr.sh_size / shdr.sh_entsize;
   1109 			for (i = 0; i < n; i++) {
   1110 				(void) gelf_getdyn(data, i, &dyn);
   1111 				if (dyn.d_tag == DT_FLAGS_1) {
   1112 					return (dyn.d_un.d_val);
   1113 				}
   1114 			}
   1115 		}
   1116 		break;
   1117 	}
   1118 	return (0);
   1119 }
   1120