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	"@(#)gelf.c	1.29	07/09/04 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
56size_t
57gelf_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
75int
76gelf_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
88GElf_Ehdr *
89gelf_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
139int
140gelf_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
201unsigned long
202gelf_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
217GElf_Phdr *
218gelf_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
264int
265gelf_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 (0);
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
313unsigned long
314gelf_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
332GElf_Shdr *
333gelf_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
376int
377gelf_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 */
431Elf_Data *
432gelf_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
450Elf_Data *
451gelf_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
469GElf_Sym *
470gelf_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
511int
512gelf_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
556GElf_Syminfo *
557gelf_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
592int
593gelf_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
626GElf_Dyn *
627gelf_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
662int
663gelf_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
701GElf_Sym *
702gelf_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
722int
723gelf_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
742GElf_Move *
743gelf_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
782int
783gelf_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
823GElf_Rela *
824gelf_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
868int
869gelf_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
916GElf_Rel *
917gelf_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
959int
960gelf_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
1004long
1005gelf_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
1018GElf_Cap *
1019gelf_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
1054int
1055gelf_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 */
1095GElf_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