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