gelf.c revision 9900:1b86d65a4f9e
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
54size_t
55gelf_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
73int
74gelf_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
86GElf_Ehdr *
87gelf_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
137int
138gelf_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
199unsigned long
200gelf_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
215GElf_Phdr *
216gelf_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
262int
263gelf_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
311unsigned long
312gelf_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
330GElf_Shdr *
331gelf_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
374int
375gelf_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 */
429Elf_Data *
430gelf_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
448Elf_Data *
449gelf_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
467GElf_Sym *
468gelf_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
509int
510gelf_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
554GElf_Syminfo *
555gelf_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
590int
591gelf_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
624GElf_Dyn *
625gelf_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
660int
661gelf_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
699GElf_Sym *
700gelf_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
720int
721gelf_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
740GElf_Move *
741gelf_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
780int
781gelf_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
821GElf_Rela *
822gelf_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
866int
867gelf_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
914GElf_Rel *
915gelf_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
957int
958gelf_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
1002long
1003gelf_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
1016GElf_Cap *
1017gelf_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
1052int
1053gelf_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 */
1093GElf_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