xref: /illumos-gate/usr/src/cmd/sgs/libelf/common/gelf.c (revision 33c72b7598992897b94815b1f47b7b8077e53808)
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 (0);
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_getdynval(Elf *elf, GElf_Sxword tag)
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 == tag) {
1112 					return (dyn.d_un.d_val);
1113 				}
1114 			}
1115 		}
1116 		break;
1117 	}
1118 	return (0);
1119 }
1120 
1121 GElf_Xword
1122 _gelf_getdyndtflags_1(Elf *elf)
1123 {
1124 	return (_gelf_getdynval(elf, DT_FLAGS_1));
1125 }
1126