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