xref: /dflybsd-src/lib/libexecinfo/private_libelf.h (revision 77bd33e17033047707557baf11c4799f1d4a3110)
1*77bd33e1Szrj /*-
2*77bd33e1Szrj  * Copyright (c) 2006,2008-2010 Joseph Koshy
3*77bd33e1Szrj  * All rights reserved.
4*77bd33e1Szrj  *
5*77bd33e1Szrj  * Redistribution and use in source and binary forms, with or without
6*77bd33e1Szrj  * modification, are permitted provided that the following conditions
7*77bd33e1Szrj  * are met:
8*77bd33e1Szrj  * 1. Redistributions of source code must retain the above copyright
9*77bd33e1Szrj  *    notice, this list of conditions and the following disclaimer.
10*77bd33e1Szrj  * 2. Redistributions in binary form must reproduce the above copyright
11*77bd33e1Szrj  *    notice, this list of conditions and the following disclaimer in the
12*77bd33e1Szrj  *    documentation and/or other materials provided with the distribution.
13*77bd33e1Szrj  *
14*77bd33e1Szrj  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*77bd33e1Szrj  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*77bd33e1Szrj  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*77bd33e1Szrj  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*77bd33e1Szrj  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*77bd33e1Szrj  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*77bd33e1Szrj  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*77bd33e1Szrj  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*77bd33e1Szrj  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*77bd33e1Szrj  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*77bd33e1Szrj  * SUCH DAMAGE.
25*77bd33e1Szrj  */
26*77bd33e1Szrj 
27*77bd33e1Szrj #ifndef _PRIVATE_LIBELF_H_
28*77bd33e1Szrj #define	_PRIVATE_LIBELF_H_
29*77bd33e1Szrj 
30*77bd33e1Szrj #include <sys/param.h>
31*77bd33e1Szrj #include <sys/endian.h>
32*77bd33e1Szrj #include <sys/queue.h>
33*77bd33e1Szrj #include <sys/mman.h>
34*77bd33e1Szrj #include <sys/stat.h>
35*77bd33e1Szrj #include <sys/types.h>
36*77bd33e1Szrj #include <assert.h>
37*77bd33e1Szrj #include <errno.h>
38*77bd33e1Szrj #include <limits.h>
39*77bd33e1Szrj #include <stddef.h>
40*77bd33e1Szrj #include <stdint.h>
41*77bd33e1Szrj #include <unistd.h>
42*77bd33e1Szrj 
43*77bd33e1Szrj /* _libelf_config.h */
44*77bd33e1Szrj #if defined(__DragonFly__)
45*77bd33e1Szrj #define	LIBELF_ARCH		EM_X86_64
46*77bd33e1Szrj #define	LIBELF_BYTEORDER	ELFDATA2LSB
47*77bd33e1Szrj #define	LIBELF_CLASS		ELFCLASS64
48*77bd33e1Szrj #endif	/* __DragonFly__ */
49*77bd33e1Szrj 
50*77bd33e1Szrj /* _elftc.h */
51*77bd33e1Szrj #if defined(__DragonFly__)
52*77bd33e1Szrj #define	ELFTC_BYTE_ORDER			_BYTE_ORDER
53*77bd33e1Szrj #define	ELFTC_BYTE_ORDER_LITTLE_ENDIAN		_LITTLE_ENDIAN
54*77bd33e1Szrj #define	ELFTC_BYTE_ORDER_BIG_ENDIAN		_BIG_ENDIAN
55*77bd33e1Szrj #define	ELFTC_HAVE_MMAP				1
56*77bd33e1Szrj #define	STAILQ_FOREACH_SAFE			STAILQ_FOREACH_MUTABLE
57*77bd33e1Szrj #endif
58*77bd33e1Szrj 
59*77bd33e1Szrj #if 1
60*77bd33e1Szrj #define	_libelf_allocate_data		__ei_libelf_allocate_data
61*77bd33e1Szrj #define	_libelf_allocate_elf		__ei_libelf_allocate_elf
62*77bd33e1Szrj #define	_libelf_allocate_scn		__ei_libelf_allocate_scn
63*77bd33e1Szrj #define	_libelf_cvt_ADDR64_tom		__ei_libelf_cvt_ADDR64_tom
64*77bd33e1Szrj #define	_libelf_cvt_BYTE_tox		__ei_libelf_cvt_BYTE_tox
65*77bd33e1Szrj #define	_libelf_cvt_CAP64_tom		__ei_libelf_cvt_CAP64_tom
66*77bd33e1Szrj #define	_libelf_cvt_DYN64_tom		__ei_libelf_cvt_DYN64_tom
67*77bd33e1Szrj #define	_libelf_cvt_EHDR64_tom		__ei_libelf_cvt_EHDR64_tom
68*77bd33e1Szrj #define	_libelf_cvt_GNUHASH64_tom	__ei_libelf_cvt_GNUHASH64_tom
69*77bd33e1Szrj #define	_libelf_cvt_HALF_tom		__ei_libelf_cvt_HALF_tom
70*77bd33e1Szrj #define	_libelf_cvt_LWORD_tom		__ei_libelf_cvt_LWORD_tom
71*77bd33e1Szrj #define	_libelf_cvt_MOVE64_tom		__ei_libelf_cvt_MOVE64_tom
72*77bd33e1Szrj #define	_libelf_cvt_NOTE_tom		__ei_libelf_cvt_NOTE_tom
73*77bd33e1Szrj #define	_libelf_cvt_OFF64_tom		__ei_libelf_cvt_OFF64_tom
74*77bd33e1Szrj #define	_libelf_cvt_PHDR64_tom		__ei_libelf_cvt_PHDR64_tom
75*77bd33e1Szrj #define	_libelf_cvt_REL64_tom		__ei_libelf_cvt_REL64_tom
76*77bd33e1Szrj #define	_libelf_cvt_RELA64_tom		__ei_libelf_cvt_RELA64_tom
77*77bd33e1Szrj #define	_libelf_cvt_SHDR64_tom		__ei_libelf_cvt_SHDR64_tom
78*77bd33e1Szrj #define	_libelf_cvt_SWORD_tom		__ei_libelf_cvt_SWORD_tom
79*77bd33e1Szrj #define	_libelf_cvt_SXWORD_tom		__ei_libelf_cvt_SXWORD_tom
80*77bd33e1Szrj #define	_libelf_cvt_SYM64_tom		__ei_libelf_cvt_SYM64_tom
81*77bd33e1Szrj #define	_libelf_cvt_SYMINFO64_tom	__ei_libelf_cvt_SYMINFO64_tom
82*77bd33e1Szrj #define	_libelf_cvt_VDEF64_tom		__ei_libelf_cvt_VDEF64_tom
83*77bd33e1Szrj #define	_libelf_cvt_VNEED64_tom		__ei_libelf_cvt_VNEED64_tom
84*77bd33e1Szrj #define	_libelf_cvt_WORD_tom		__ei_libelf_cvt_WORD_tom
85*77bd33e1Szrj #define	_libelf_cvt_XWORD_tom		__ei_libelf_cvt_XWORD_tom
86*77bd33e1Szrj #define	_libelf_ehdr			__ei_libelf_ehdr
87*77bd33e1Szrj #define	_libelf_fsize			__ei_libelf_fsize
88*77bd33e1Szrj #define	_libelf_get_translator		__ei_libelf_get_translator
89*77bd33e1Szrj #define	_libelf_getshdr			__ei_libelf_getshdr
90*77bd33e1Szrj #define	_libelf_init_elf		__ei_libelf_init_elf
91*77bd33e1Szrj #define	_libelf_load_extended		__ei_libelf_load_extended
92*77bd33e1Szrj #define	_libelf_load_section_headers	__ei_libelf_load_section_headers
93*77bd33e1Szrj #define	_libelf_memory			__ei_libelf_memory
94*77bd33e1Szrj #define	_libelf_msize			__ei_libelf_msize
95*77bd33e1Szrj #define	_libelf_open_object		__ei_libelf_open_object
96*77bd33e1Szrj #define	_libelf_read_special_file	__ei_libelf_read_special_file
97*77bd33e1Szrj #define	_libelf_release_data		__ei_libelf_release_data
98*77bd33e1Szrj #define	_libelf_release_elf		__ei_libelf_release_elf
99*77bd33e1Szrj #define	_libelf_release_scn		__ei_libelf_release_scn
100*77bd33e1Szrj #define	_libelf_xlate_shtype		__ei_libelf_xlate_shtype
101*77bd33e1Szrj #define	_libelf		__ei_libelf
102*77bd33e1Szrj 
103*77bd33e1Szrj #define	elf64_fsize	__ei_elf64_fsize
104*77bd33e1Szrj #define	elf_getscn	__ei_elf_getscn
105*77bd33e1Szrj 
106*77bd33e1Szrj #define	elf_begin	_ei_elf_begin
107*77bd33e1Szrj #define	elf_end		_ei_elf_end
108*77bd33e1Szrj #define	elf_errmsg	_ei_elf_errmsg
109*77bd33e1Szrj #define	elf_errno	_ei_elf_errno
110*77bd33e1Szrj #define	elf_getdata	_ei_elf_getdata
111*77bd33e1Szrj #define	elf_nextscn	_ei_elf_nextscn
112*77bd33e1Szrj #define	elf_strptr	_ei_elf_strptr
113*77bd33e1Szrj #define	elf_version	_ei_elf_version
114*77bd33e1Szrj #define	gelf_getshdr	_ei_gelf_getshdr
115*77bd33e1Szrj #define	gelf_getsym	_ei_gelf_getsym
116*77bd33e1Szrj #endif
117*77bd33e1Szrj 
118*77bd33e1Szrj /* elfdefinitions.h */
119*77bd33e1Szrj /*
120*77bd33e1Szrj  * Offsets in the `ei_ident[]` field of an ELF executable header.
121*77bd33e1Szrj  */
122*77bd33e1Szrj #define	_ELF_DEFINE_EI_OFFSETS()			\
123*77bd33e1Szrj _ELF_DEFINE_EI(EI_MAG0,     0, "magic number")		\
124*77bd33e1Szrj _ELF_DEFINE_EI(EI_MAG1,     1, "magic number")		\
125*77bd33e1Szrj _ELF_DEFINE_EI(EI_MAG2,     2, "magic number")		\
126*77bd33e1Szrj _ELF_DEFINE_EI(EI_MAG3,     3, "magic number")		\
127*77bd33e1Szrj _ELF_DEFINE_EI(EI_CLASS,    4, "file class")		\
128*77bd33e1Szrj _ELF_DEFINE_EI(EI_DATA,     5, "data encoding")		\
129*77bd33e1Szrj _ELF_DEFINE_EI(EI_VERSION,  6, "file version")		\
130*77bd33e1Szrj _ELF_DEFINE_EI(EI_OSABI,    7, "OS ABI kind")		\
131*77bd33e1Szrj _ELF_DEFINE_EI(EI_ABIVERSION, 8, "OS ABI version")	\
132*77bd33e1Szrj _ELF_DEFINE_EI(EI_PAD,	    9, "padding start")		\
133*77bd33e1Szrj _ELF_DEFINE_EI(EI_NIDENT,  16, "total size")
134*77bd33e1Szrj 
135*77bd33e1Szrj #undef	_ELF_DEFINE_EI
136*77bd33e1Szrj #define	_ELF_DEFINE_EI(N, V, DESCR)	N = V ,
137*77bd33e1Szrj enum {
138*77bd33e1Szrj 	_ELF_DEFINE_EI_OFFSETS()
139*77bd33e1Szrj 	EI__LAST__
140*77bd33e1Szrj };
141*77bd33e1Szrj 
142*77bd33e1Szrj /*
143*77bd33e1Szrj  * The ELF class of an object.
144*77bd33e1Szrj  */
145*77bd33e1Szrj #define	_ELF_DEFINE_ELFCLASS()				\
146*77bd33e1Szrj _ELF_DEFINE_EC(ELFCLASSNONE, 0, "Unknown ELF class")	\
147*77bd33e1Szrj _ELF_DEFINE_EC(ELFCLASS32,   1, "32 bit objects")	\
148*77bd33e1Szrj _ELF_DEFINE_EC(ELFCLASS64,   2, "64 bit objects")
149*77bd33e1Szrj 
150*77bd33e1Szrj #undef	_ELF_DEFINE_EC
151*77bd33e1Szrj #define	_ELF_DEFINE_EC(N, V, DESCR)	N = V ,
152*77bd33e1Szrj enum {
153*77bd33e1Szrj 	_ELF_DEFINE_ELFCLASS()
154*77bd33e1Szrj 	EC__LAST__
155*77bd33e1Szrj };
156*77bd33e1Szrj 
157*77bd33e1Szrj /*
158*77bd33e1Szrj  * Endianness of data in an ELF object.
159*77bd33e1Szrj  */
160*77bd33e1Szrj 
161*77bd33e1Szrj #define	_ELF_DEFINE_ELF_DATA_ENDIANNESS()			\
162*77bd33e1Szrj _ELF_DEFINE_ED(ELFDATANONE, 0, "Unknown data endianness")	\
163*77bd33e1Szrj _ELF_DEFINE_ED(ELFDATA2LSB, 1, "little endian")			\
164*77bd33e1Szrj _ELF_DEFINE_ED(ELFDATA2MSB, 2, "big endian")
165*77bd33e1Szrj 
166*77bd33e1Szrj #undef	_ELF_DEFINE_ED
167*77bd33e1Szrj #define	_ELF_DEFINE_ED(N, V, DESCR)	N = V ,
168*77bd33e1Szrj enum {
169*77bd33e1Szrj 	_ELF_DEFINE_ELF_DATA_ENDIANNESS()
170*77bd33e1Szrj 	ED__LAST__
171*77bd33e1Szrj };
172*77bd33e1Szrj 
173*77bd33e1Szrj /*
174*77bd33e1Szrj  * Values of the magic numbers used in identification array.
175*77bd33e1Szrj  */
176*77bd33e1Szrj #define	_ELF_DEFINE_ELF_MAGIC()			\
177*77bd33e1Szrj _ELF_DEFINE_EMAG(ELFMAG0, 0x7FU)		\
178*77bd33e1Szrj _ELF_DEFINE_EMAG(ELFMAG1, 'E')			\
179*77bd33e1Szrj _ELF_DEFINE_EMAG(ELFMAG2, 'L')			\
180*77bd33e1Szrj _ELF_DEFINE_EMAG(ELFMAG3, 'F')
181*77bd33e1Szrj 
182*77bd33e1Szrj #undef	_ELF_DEFINE_EMAG
183*77bd33e1Szrj #define	_ELF_DEFINE_EMAG(N, V)		N = V ,
184*77bd33e1Szrj enum {
185*77bd33e1Szrj 	_ELF_DEFINE_ELF_MAGIC()
186*77bd33e1Szrj 	ELFMAG__LAST__
187*77bd33e1Szrj };
188*77bd33e1Szrj 
189*77bd33e1Szrj /*
190*77bd33e1Szrj  * ELF Machine types: (EM_*).
191*77bd33e1Szrj  */
192*77bd33e1Szrj #define	_ELF_DEFINE_ELF_MACHINES()					\
193*77bd33e1Szrj _ELF_DEFINE_EM(EM_NONE,             0, "No machine")			\
194*77bd33e1Szrj _ELF_DEFINE_EM(EM_386,              3, "Intel 80386")			\
195*77bd33e1Szrj _ELF_DEFINE_EM(EM_X86_64,           62, "AMD x86-64 architecture")
196*77bd33e1Szrj 
197*77bd33e1Szrj #undef	_ELF_DEFINE_EM
198*77bd33e1Szrj #define	_ELF_DEFINE_EM(N, V, DESCR)	N = V ,
199*77bd33e1Szrj enum {
200*77bd33e1Szrj 	_ELF_DEFINE_ELF_MACHINES()
201*77bd33e1Szrj 	EM__LAST__
202*77bd33e1Szrj };
203*77bd33e1Szrj 
204*77bd33e1Szrj /* ELF file format version numbers. */
205*77bd33e1Szrj #define	EV_NONE		0
206*77bd33e1Szrj #define	EV_CURRENT	1
207*77bd33e1Szrj 
208*77bd33e1Szrj /*
209*77bd33e1Szrj  * Special section indices.
210*77bd33e1Szrj  */
211*77bd33e1Szrj #define _ELF_DEFINE_SECTION_INDICES()					\
212*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_UNDEF,	0,	 "undefined section")		\
213*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_LORESERVE,	0xFF00U, "start of reserved area")	\
214*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_LOPROC,	0xFF00U,				\
215*77bd33e1Szrj 	"start of processor-specific range")				\
216*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_BEFORE,	0xFF00U, "used for section ordering")	\
217*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_AFTER,	0xFF01U, "used for section ordering")	\
218*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_AMD64_LCOMMON, 0xFF02U, "large common block label") \
219*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_MIPS_ACOMMON, 0xFF00U,				\
220*77bd33e1Szrj 	"allocated common symbols in a DSO")				\
221*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_MIPS_TEXT,	0xFF01U, "Reserved (obsolete)")		\
222*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_MIPS_DATA,	0xFF02U, "Reserved (obsolete)")		\
223*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_MIPS_SCOMMON, 0xFF03U,				\
224*77bd33e1Szrj 	"gp-addressable common symbols")				\
225*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_MIPS_SUNDEFINED, 0xFF04U,				\
226*77bd33e1Szrj 	"gp-addressable undefined symbols")				\
227*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_MIPS_LCOMMON, 0xFF05U, "local common symbols")	\
228*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_MIPS_LUNDEFINED, 0xFF06U,				\
229*77bd33e1Szrj 	"local undefined symbols")					\
230*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_HIPROC,	0xFF1FU,				\
231*77bd33e1Szrj 	"end of processor-specific range")				\
232*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_LOOS,	0xFF20U,				\
233*77bd33e1Szrj 	"start of OS-specific range")					\
234*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_SUNW_IGNORE, 0xFF3FU, "used by dtrace")		\
235*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_HIOS,	0xFF3FU,				\
236*77bd33e1Szrj 	"end of OS-specific range")					\
237*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_ABS,	0xFFF1U, "absolute references")		\
238*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_COMMON,	0xFFF2U, "references to COMMON areas")	\
239*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_XINDEX,	0xFFFFU, "extended index")		\
240*77bd33e1Szrj _ELF_DEFINE_SHN(SHN_HIRESERVE,	0xFFFFU, "end of reserved area")
241*77bd33e1Szrj 
242*77bd33e1Szrj #undef	_ELF_DEFINE_SHN
243*77bd33e1Szrj #define	_ELF_DEFINE_SHN(N, V, DESCR)	N = V ,
244*77bd33e1Szrj enum {
245*77bd33e1Szrj 	_ELF_DEFINE_SECTION_INDICES()
246*77bd33e1Szrj 	SHN__LAST__
247*77bd33e1Szrj };
248*77bd33e1Szrj 
249*77bd33e1Szrj /*
250*77bd33e1Szrj  * Section types.
251*77bd33e1Szrj  */
252*77bd33e1Szrj 
253*77bd33e1Szrj #define	_ELF_DEFINE_SECTION_TYPES()					\
254*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_NULL,            0, "inactive header")		\
255*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_PROGBITS,        1, "program defined information")	\
256*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SYMTAB,          2, "symbol table")			\
257*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_STRTAB,          3, "string table")			\
258*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_RELA,            4,					\
259*77bd33e1Szrj 	"relocation entries with addends")				\
260*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_HASH,            5, "symbol hash table")		\
261*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_DYNAMIC,         6,					\
262*77bd33e1Szrj 	"information for dynamic linking")				\
263*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_NOTE,            7, "additional notes")		\
264*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_NOBITS,          8, "section occupying no space")	\
265*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_REL,             9,					\
266*77bd33e1Szrj 	"relocation entries without addends")				\
267*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SHLIB,           10, "reserved")			\
268*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_DYNSYM,          11, "symbol table")		\
269*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_INIT_ARRAY,      14,				\
270*77bd33e1Szrj 	"pointers to initialization functions")				\
271*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_FINI_ARRAY,      15,				\
272*77bd33e1Szrj 	"pointers to termination functions")				\
273*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_PREINIT_ARRAY,   16,				\
274*77bd33e1Szrj 	"pointers to functions called before initialization")		\
275*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_GROUP,           17, "defines a section group")	\
276*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SYMTAB_SHNDX,    18,				\
277*77bd33e1Szrj 	"used for extended section numbering")				\
278*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_LOOS,            0x60000000UL,			\
279*77bd33e1Szrj 	"start of OS-specific range")					\
280*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_dof,	     0x6FFFFFF4UL,			\
281*77bd33e1Szrj 	"used by dtrace")						\
282*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_cap,	     0x6FFFFFF5UL,			\
283*77bd33e1Szrj 	"capability requirements")					\
284*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_GNU_ATTRIBUTES,  0x6FFFFFF5UL,			\
285*77bd33e1Szrj 	"object attributes")						\
286*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_SIGNATURE,  0x6FFFFFF6UL,			\
287*77bd33e1Szrj 	"module verification signature")				\
288*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_GNU_HASH,	     0x6FFFFFF6UL,			\
289*77bd33e1Szrj 	"GNU Hash sections")						\
290*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_GNU_LIBLIST,     0x6FFFFFF7UL,			\
291*77bd33e1Szrj 	"List of libraries to be prelinked")				\
292*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_ANNOTATE,   0x6FFFFFF7UL,			\
293*77bd33e1Szrj 	"special section where unresolved references are allowed")	\
294*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_DEBUGSTR,   0x6FFFFFF8UL,			\
295*77bd33e1Szrj 	"debugging information")					\
296*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_CHECKSUM,	     0x6FFFFFF8UL,			\
297*77bd33e1Szrj 	"checksum for dynamic shared objects")				\
298*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_DEBUG,      0x6FFFFFF9UL,			\
299*77bd33e1Szrj 	"debugging information")					\
300*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_move,       0x6FFFFFFAUL,			\
301*77bd33e1Szrj 	"information to handle partially initialized symbols")		\
302*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_COMDAT,     0x6FFFFFFBUL,			\
303*77bd33e1Szrj 	"section supporting merging of multiple copies of data")	\
304*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_syminfo,    0x6FFFFFFCUL,			\
305*77bd33e1Szrj 	"additional symbol information")				\
306*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_verdef,     0x6FFFFFFDUL,			\
307*77bd33e1Szrj 	"symbol versioning information")				\
308*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_verneed,    0x6FFFFFFEUL,			\
309*77bd33e1Szrj 	"symbol versioning requirements")				\
310*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SUNW_versym,     0x6FFFFFFFUL,			\
311*77bd33e1Szrj 	"symbol versioning table")					\
312*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_HIOS,            0x6FFFFFFFUL,			\
313*77bd33e1Szrj 	"end of OS-specific range")					\
314*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_LOPROC,          0x70000000UL,			\
315*77bd33e1Szrj 	"start of processor-specific range")				\
316*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_ARM_EXIDX,       0x70000001UL,			\
317*77bd33e1Szrj 	"exception index table")					\
318*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_ARM_PREEMPTMAP,  0x70000002UL,			\
319*77bd33e1Szrj 	"BPABI DLL dynamic linking preemption map")			\
320*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_ARM_ATTRIBUTES,  0x70000003UL,			\
321*77bd33e1Szrj 	"object file compatibility attributes")				\
322*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_ARM_DEBUGOVERLAY, 0x70000004UL,			\
323*77bd33e1Szrj 	"overlay debug information")					\
324*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_ARM_OVERLAYSECTION, 0x70000005UL,			\
325*77bd33e1Szrj 	"overlay debug information")					\
326*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_LIBLIST,    0x70000000UL,			\
327*77bd33e1Szrj 	"DSO library information used in link")				\
328*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_MSYM,       0x70000001UL,			\
329*77bd33e1Szrj 	"MIPS symbol table extension")					\
330*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_CONFLICT,   0x70000002UL,			\
331*77bd33e1Szrj 	"symbol conflicting with DSO-defined symbols ")			\
332*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_GPTAB,      0x70000003UL,			\
333*77bd33e1Szrj 	"global pointer table")						\
334*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_UCODE,      0x70000004UL,			\
335*77bd33e1Szrj 	"reserved")							\
336*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_DEBUG,      0x70000005UL,			\
337*77bd33e1Szrj 	"reserved (obsolete debug information)")			\
338*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_REGINFO,    0x70000006UL,			\
339*77bd33e1Szrj 	"register usage information")					\
340*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_PACKAGE,    0x70000007UL,			\
341*77bd33e1Szrj 	"OSF reserved")							\
342*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_PACKSYM,    0x70000008UL,			\
343*77bd33e1Szrj 	"OSF reserved")							\
344*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_RELD,       0x70000009UL,			\
345*77bd33e1Szrj 	"dynamic relocation")						\
346*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_IFACE,      0x7000000BUL,			\
347*77bd33e1Szrj 	"subprogram interface information")				\
348*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_CONTENT,    0x7000000CUL,			\
349*77bd33e1Szrj 	"section content classification")				\
350*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_OPTIONS,     0x7000000DUL,			\
351*77bd33e1Szrj 	"general options")						\
352*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_DELTASYM,   0x7000001BUL,			\
353*77bd33e1Szrj 	"Delta C++: symbol table")					\
354*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_DELTAINST,  0x7000001CUL,			\
355*77bd33e1Szrj 	"Delta C++: instance table")					\
356*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_DELTACLASS, 0x7000001DUL,			\
357*77bd33e1Szrj 	"Delta C++: class table")					\
358*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_DWARF,      0x7000001EUL,			\
359*77bd33e1Szrj 	"DWARF debug information")					\
360*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_DELTADECL,  0x7000001FUL,			\
361*77bd33e1Szrj 	"Delta C++: declarations")					\
362*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_SYMBOL_LIB, 0x70000020UL,			\
363*77bd33e1Szrj 	"symbol-to-library mapping")					\
364*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_EVENTS,     0x70000021UL,			\
365*77bd33e1Szrj 	"event locations")						\
366*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_TRANSLATE,  0x70000022UL,			\
367*77bd33e1Szrj 	"???")								\
368*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_PIXIE,      0x70000023UL,			\
369*77bd33e1Szrj 	"special pixie sections")					\
370*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_XLATE,      0x70000024UL,			\
371*77bd33e1Szrj 	"address translation table")					\
372*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_XLATE_DEBUG, 0x70000025UL,			\
373*77bd33e1Szrj 	"SGI internal address translation table")			\
374*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_WHIRL,      0x70000026UL,			\
375*77bd33e1Szrj 	"intermediate code")						\
376*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_EH_REGION,  0x70000027UL,			\
377*77bd33e1Szrj 	"C++ exception handling region info")				\
378*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_XLATE_OLD,  0x70000028UL,			\
379*77bd33e1Szrj 	"obsolete")							\
380*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_PDR_EXCEPTION, 0x70000029UL,			\
381*77bd33e1Szrj 	"runtime procedure descriptor table exception information")	\
382*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_MIPS_ABIFLAGS,   0x7000002AUL,			\
383*77bd33e1Szrj 	"ABI flags")							\
384*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_SPARC_GOTDATA,   0x70000000UL,			\
385*77bd33e1Szrj 	"SPARC-specific data")						\
386*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_AMD64_UNWIND,    0x70000001UL,			\
387*77bd33e1Szrj 	"unwind tables for the AMD64")					\
388*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_ORDERED,         0x7FFFFFFFUL,			\
389*77bd33e1Szrj 	"sort entries in the section")					\
390*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_HIPROC,          0x7FFFFFFFUL,			\
391*77bd33e1Szrj 	"end of processor-specific range")				\
392*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_LOUSER,          0x80000000UL,			\
393*77bd33e1Szrj 	"start of application-specific range")				\
394*77bd33e1Szrj _ELF_DEFINE_SHT(SHT_HIUSER,          0xFFFFFFFFUL,			\
395*77bd33e1Szrj 	"end of application-specific range")
396*77bd33e1Szrj 
397*77bd33e1Szrj #undef	_ELF_DEFINE_SHT
398*77bd33e1Szrj #define	_ELF_DEFINE_SHT(N, V, DESCR)	N = V ,
399*77bd33e1Szrj enum {
400*77bd33e1Szrj 	_ELF_DEFINE_SECTION_TYPES()
401*77bd33e1Szrj 	SHT__LAST__ = SHT_HIUSER
402*77bd33e1Szrj };
403*77bd33e1Szrj 
404*77bd33e1Szrj #define	PN_XNUM			0xFFFFU /* Use extended section numbering. */
405*77bd33e1Szrj 
406*77bd33e1Szrj /**
407*77bd33e1Szrj  ** ELF Types.
408*77bd33e1Szrj  **/
409*77bd33e1Szrj 
410*77bd33e1Szrj typedef uint64_t	Elf64_Addr;	/* Program address. */
411*77bd33e1Szrj typedef uint16_t	Elf64_Half;	/* Unsigned medium integer. */
412*77bd33e1Szrj typedef uint64_t	Elf64_Off;	/* File offset. */
413*77bd33e1Szrj typedef int32_t		Elf64_Sword;	/* Signed integer. */
414*77bd33e1Szrj typedef uint32_t	Elf64_Word;	/* Unsigned integer. */
415*77bd33e1Szrj typedef uint64_t	Elf64_Lword;	/* Unsigned long integer. */
416*77bd33e1Szrj typedef uint64_t	Elf64_Xword;	/* Unsigned long integer. */
417*77bd33e1Szrj typedef int64_t		Elf64_Sxword;	/* Signed long integer. */
418*77bd33e1Szrj 
419*77bd33e1Szrj /*
420*77bd33e1Szrj  * Capability descriptors.
421*77bd33e1Szrj  */
422*77bd33e1Szrj typedef struct {
423*77bd33e1Szrj 	Elf64_Xword	c_tag;	     /* Type of entry. */
424*77bd33e1Szrj 	union {
425*77bd33e1Szrj 		Elf64_Xword	c_val; /* Integer value. */
426*77bd33e1Szrj 		Elf64_Addr	c_ptr; /* Pointer value. */
427*77bd33e1Szrj 	} c_un;
428*77bd33e1Szrj } Elf64_Cap;
429*77bd33e1Szrj 
430*77bd33e1Szrj /*
431*77bd33e1Szrj  * Dynamic section entries.
432*77bd33e1Szrj  */
433*77bd33e1Szrj typedef struct {
434*77bd33e1Szrj 	Elf64_Sxword	d_tag;	     /* Type of entry. */
435*77bd33e1Szrj 	union {
436*77bd33e1Szrj 		Elf64_Xword	d_val; /* Integer value. */
437*77bd33e1Szrj 		Elf64_Addr	d_ptr; /* Pointer value; */
438*77bd33e1Szrj 	} d_un;
439*77bd33e1Szrj } Elf64_Dyn;
440*77bd33e1Szrj 
441*77bd33e1Szrj /*
442*77bd33e1Szrj  * The executable header (EHDR).
443*77bd33e1Szrj  */
444*77bd33e1Szrj typedef struct {
445*77bd33e1Szrj 	unsigned char   e_ident[EI_NIDENT]; /* ELF identification. */
446*77bd33e1Szrj 	Elf64_Half      e_type;	     /* Object file type (ET_*). */
447*77bd33e1Szrj 	Elf64_Half      e_machine;   /* Machine type (EM_*). */
448*77bd33e1Szrj 	Elf64_Word      e_version;   /* File format version (EV_*). */
449*77bd33e1Szrj 	Elf64_Addr      e_entry;     /* Start address. */
450*77bd33e1Szrj 	Elf64_Off       e_phoff;     /* File offset to the PHDR table. */
451*77bd33e1Szrj 	Elf64_Off       e_shoff;     /* File offset to the SHDRheader. */
452*77bd33e1Szrj 	Elf64_Word      e_flags;     /* Flags (EF_*). */
453*77bd33e1Szrj 	Elf64_Half      e_ehsize;    /* Elf header size in bytes. */
454*77bd33e1Szrj 	Elf64_Half      e_phentsize; /* PHDR table entry size in bytes. */
455*77bd33e1Szrj 	Elf64_Half      e_phnum;     /* Number of PHDR entries. */
456*77bd33e1Szrj 	Elf64_Half      e_shentsize; /* SHDR table entry size in bytes. */
457*77bd33e1Szrj 	Elf64_Half      e_shnum;     /* Number of SHDR entries. */
458*77bd33e1Szrj 	Elf64_Half      e_shstrndx;  /* Index of section name string table. */
459*77bd33e1Szrj } Elf64_Ehdr;
460*77bd33e1Szrj 
461*77bd33e1Szrj /*
462*77bd33e1Szrj  * Note descriptors.
463*77bd33e1Szrj  */
464*77bd33e1Szrj 
465*77bd33e1Szrj typedef	struct {
466*77bd33e1Szrj 	uint32_t	n_namesz;    /* Length of note's name. */
467*77bd33e1Szrj 	uint32_t	n_descsz;    /* Length of note's value. */
468*77bd33e1Szrj 	uint32_t	n_type;	     /* Type of note. */
469*77bd33e1Szrj } Elf_Note;
470*77bd33e1Szrj 
471*77bd33e1Szrj /*
472*77bd33e1Szrj  * Program Header Table (PHDR) entries.
473*77bd33e1Szrj  */
474*77bd33e1Szrj typedef struct {
475*77bd33e1Szrj 	Elf64_Word	p_type;	     /* Type of segment. */
476*77bd33e1Szrj 	Elf64_Word	p_flags;     /* Segment flags. */
477*77bd33e1Szrj 	Elf64_Off	p_offset;    /* File offset to segment. */
478*77bd33e1Szrj 	Elf64_Addr	p_vaddr;     /* Virtual address in memory. */
479*77bd33e1Szrj 	Elf64_Addr	p_paddr;     /* Physical address (if relevant). */
480*77bd33e1Szrj 	Elf64_Xword	p_filesz;    /* Size of segment in file. */
481*77bd33e1Szrj 	Elf64_Xword	p_memsz;     /* Size of segment in memory. */
482*77bd33e1Szrj 	Elf64_Xword	p_align;     /* Alignment constraints. */
483*77bd33e1Szrj } Elf64_Phdr;
484*77bd33e1Szrj 
485*77bd33e1Szrj /*
486*77bd33e1Szrj  * Move entries, for describing data in COMMON blocks in a compact
487*77bd33e1Szrj  * manner.
488*77bd33e1Szrj  */
489*77bd33e1Szrj typedef struct {
490*77bd33e1Szrj 	Elf64_Lword	m_value;     /* Initialization value. */
491*77bd33e1Szrj 	Elf64_Xword	m_info;	     /* Encoded size and index. */
492*77bd33e1Szrj 	Elf64_Xword	m_poffset;   /* Offset relative to symbol. */
493*77bd33e1Szrj 	Elf64_Half	m_repeat;    /* Repeat count. */
494*77bd33e1Szrj 	Elf64_Half	m_stride;    /* Number of units to skip. */
495*77bd33e1Szrj } Elf64_Move;
496*77bd33e1Szrj 
497*77bd33e1Szrj /*
498*77bd33e1Szrj  * Section Header Table (SHDR) entries.
499*77bd33e1Szrj  */
500*77bd33e1Szrj typedef struct {
501*77bd33e1Szrj 	Elf64_Word	sh_name;     /* index of section name */
502*77bd33e1Szrj 	Elf64_Word	sh_type;     /* section type */
503*77bd33e1Szrj 	Elf64_Xword	sh_flags;    /* section flags */
504*77bd33e1Szrj 	Elf64_Addr	sh_addr;     /* in-memory address of section */
505*77bd33e1Szrj 	Elf64_Off	sh_offset;   /* file offset of section */
506*77bd33e1Szrj 	Elf64_Xword	sh_size;     /* section size in bytes */
507*77bd33e1Szrj 	Elf64_Word	sh_link;     /* section header table link */
508*77bd33e1Szrj 	Elf64_Word	sh_info;     /* extra information */
509*77bd33e1Szrj 	Elf64_Xword	sh_addralign; /* alignment constraint */
510*77bd33e1Szrj 	Elf64_Xword	sh_entsize;  /* size for fixed-size entries */
511*77bd33e1Szrj } Elf64_Shdr;
512*77bd33e1Szrj 
513*77bd33e1Szrj /*
514*77bd33e1Szrj  * Symbol table entries.
515*77bd33e1Szrj  */
516*77bd33e1Szrj typedef struct {
517*77bd33e1Szrj 	Elf64_Word	st_name;     /* index of symbol's name */
518*77bd33e1Szrj 	unsigned char	st_info;     /* type and binding attributes */
519*77bd33e1Szrj 	unsigned char	st_other;    /* visibility */
520*77bd33e1Szrj 	Elf64_Half	st_shndx;    /* index of related section */
521*77bd33e1Szrj 	Elf64_Addr	st_value;    /* value for the symbol */
522*77bd33e1Szrj 	Elf64_Xword	st_size;     /* size of associated data */
523*77bd33e1Szrj } Elf64_Sym;
524*77bd33e1Szrj 
525*77bd33e1Szrj /*
526*77bd33e1Szrj  * Syminfo descriptors, containing additional symbol information.
527*77bd33e1Szrj  */
528*77bd33e1Szrj typedef struct {
529*77bd33e1Szrj 	Elf64_Half	si_boundto;  /* Entry index with additional flags. */
530*77bd33e1Szrj 	Elf64_Half	si_flags;    /* Flags. */
531*77bd33e1Szrj } Elf64_Syminfo;
532*77bd33e1Szrj 
533*77bd33e1Szrj /*
534*77bd33e1Szrj  * Relocation descriptors.
535*77bd33e1Szrj  */
536*77bd33e1Szrj typedef struct {
537*77bd33e1Szrj 	Elf64_Addr	r_offset;    /* location to apply relocation to */
538*77bd33e1Szrj 	Elf64_Xword	r_info;      /* type+section for relocation */
539*77bd33e1Szrj } Elf64_Rel;
540*77bd33e1Szrj 
541*77bd33e1Szrj typedef struct {
542*77bd33e1Szrj 	Elf64_Addr	r_offset;    /* location to apply relocation to */
543*77bd33e1Szrj 	Elf64_Xword	r_info;      /* type+section for relocation */
544*77bd33e1Szrj 	Elf64_Sxword	r_addend;    /* constant addend */
545*77bd33e1Szrj } Elf64_Rela;
546*77bd33e1Szrj 
547*77bd33e1Szrj /*
548*77bd33e1Szrj  * Symbol versioning structures.
549*77bd33e1Szrj  */
550*77bd33e1Szrj typedef struct {
551*77bd33e1Szrj 	Elf64_Word	vda_name;    /* Index to name. */
552*77bd33e1Szrj 	Elf64_Word	vda_next;    /* Offset to next entry. */
553*77bd33e1Szrj } Elf64_Verdaux;
554*77bd33e1Szrj 
555*77bd33e1Szrj typedef struct {
556*77bd33e1Szrj 	Elf64_Word	vna_hash;    /* Hash value of dependency name. */
557*77bd33e1Szrj 	Elf64_Half	vna_flags;   /* Flags. */
558*77bd33e1Szrj 	Elf64_Half	vna_other;   /* Unused. */
559*77bd33e1Szrj 	Elf64_Word	vna_name;    /* Offset to dependency name. */
560*77bd33e1Szrj 	Elf64_Word	vna_next;    /* Offset to next vernaux entry. */
561*77bd33e1Szrj } Elf64_Vernaux;
562*77bd33e1Szrj 
563*77bd33e1Szrj typedef struct {
564*77bd33e1Szrj 	Elf64_Half	vd_version;  /* Version information. */
565*77bd33e1Szrj 	Elf64_Half	vd_flags;    /* Flags. */
566*77bd33e1Szrj 	Elf64_Half	vd_ndx;	     /* Index into the versym section. */
567*77bd33e1Szrj 	Elf64_Half	vd_cnt;	     /* Number of aux entries. */
568*77bd33e1Szrj 	Elf64_Word	vd_hash;     /* Hash value of name. */
569*77bd33e1Szrj 	Elf64_Word	vd_aux;	     /* Offset to aux entries. */
570*77bd33e1Szrj 	Elf64_Word	vd_next;     /* Offset to next version definition. */
571*77bd33e1Szrj } Elf64_Verdef;
572*77bd33e1Szrj 
573*77bd33e1Szrj typedef struct {
574*77bd33e1Szrj 	Elf64_Half	vn_version;  /* Version number. */
575*77bd33e1Szrj 	Elf64_Half	vn_cnt;	     /* Number of aux entries. */
576*77bd33e1Szrj 	Elf64_Word	vn_file;     /* Offset of associated file name. */
577*77bd33e1Szrj 	Elf64_Word	vn_aux;	     /* Offset of vernaux array. */
578*77bd33e1Szrj 	Elf64_Word	vn_next;     /* Offset of next verneed entry. */
579*77bd33e1Szrj } Elf64_Verneed;
580*77bd33e1Szrj 
581*77bd33e1Szrj /*
582*77bd33e1Szrj  * The header for GNU-style hash sections.
583*77bd33e1Szrj  */
584*77bd33e1Szrj 
585*77bd33e1Szrj typedef struct {
586*77bd33e1Szrj 	uint32_t	gh_nbuckets;	/* Number of hash buckets. */
587*77bd33e1Szrj 	uint32_t	gh_symndx;	/* First visible symbol in .dynsym. */
588*77bd33e1Szrj 	uint32_t	gh_maskwords;	/* #maskwords used in bloom filter. */
589*77bd33e1Szrj 	uint32_t	gh_shift2;	/* Bloom filter shift count. */
590*77bd33e1Szrj } Elf_GNU_Hash_Header;
591*77bd33e1Szrj 
592*77bd33e1Szrj /* libelf.h */
593*77bd33e1Szrj /* Library private data structures */
594*77bd33e1Szrj typedef struct _Elf Elf;
595*77bd33e1Szrj typedef struct _Elf_Scn Elf_Scn;
596*77bd33e1Szrj 
597*77bd33e1Szrj /* File types */
598*77bd33e1Szrj typedef enum {
599*77bd33e1Szrj 	ELF_K_NONE = 0,
600*77bd33e1Szrj 	ELF_K_AR,	/* `ar' archives */
601*77bd33e1Szrj 	ELF_K_COFF,	/* COFF files (unsupported) */
602*77bd33e1Szrj 	ELF_K_ELF,	/* ELF files */
603*77bd33e1Szrj 	ELF_K_NUM
604*77bd33e1Szrj } Elf_Kind;
605*77bd33e1Szrj 
606*77bd33e1Szrj /* Data types */
607*77bd33e1Szrj typedef enum {
608*77bd33e1Szrj 	ELF_T_ADDR,
609*77bd33e1Szrj 	ELF_T_BYTE,
610*77bd33e1Szrj 	ELF_T_CAP,
611*77bd33e1Szrj 	ELF_T_DYN,
612*77bd33e1Szrj 	ELF_T_EHDR,
613*77bd33e1Szrj 	ELF_T_HALF,
614*77bd33e1Szrj 	ELF_T_LWORD,
615*77bd33e1Szrj 	ELF_T_MOVE,
616*77bd33e1Szrj 	ELF_T_MOVEP,
617*77bd33e1Szrj 	ELF_T_NOTE,
618*77bd33e1Szrj 	ELF_T_OFF,
619*77bd33e1Szrj 	ELF_T_PHDR,
620*77bd33e1Szrj 	ELF_T_REL,
621*77bd33e1Szrj 	ELF_T_RELA,
622*77bd33e1Szrj 	ELF_T_SHDR,
623*77bd33e1Szrj 	ELF_T_SWORD,
624*77bd33e1Szrj 	ELF_T_SXWORD,
625*77bd33e1Szrj 	ELF_T_SYMINFO,
626*77bd33e1Szrj 	ELF_T_SYM,
627*77bd33e1Szrj 	ELF_T_VDEF,
628*77bd33e1Szrj 	ELF_T_VNEED,
629*77bd33e1Szrj 	ELF_T_WORD,
630*77bd33e1Szrj 	ELF_T_XWORD,
631*77bd33e1Szrj 	ELF_T_GNUHASH,	/* GNU style hash tables. */
632*77bd33e1Szrj 	ELF_T_NUM
633*77bd33e1Szrj } Elf_Type;
634*77bd33e1Szrj 
635*77bd33e1Szrj #define	ELF_T_FIRST	ELF_T_ADDR
636*77bd33e1Szrj #define	ELF_T_LAST	ELF_T_GNUHASH
637*77bd33e1Szrj 
638*77bd33e1Szrj /* Commands */
639*77bd33e1Szrj typedef enum {
640*77bd33e1Szrj 	ELF_C_NULL = 0,
641*77bd33e1Szrj 	ELF_C_CLR,
642*77bd33e1Szrj 	ELF_C_FDDONE,
643*77bd33e1Szrj 	ELF_C_FDREAD,
644*77bd33e1Szrj 	ELF_C_RDWR,
645*77bd33e1Szrj 	ELF_C_READ,
646*77bd33e1Szrj 	ELF_C_SET,
647*77bd33e1Szrj 	ELF_C_WRITE,
648*77bd33e1Szrj 	ELF_C_NUM
649*77bd33e1Szrj } Elf_Cmd;
650*77bd33e1Szrj 
651*77bd33e1Szrj /*
652*77bd33e1Szrj  * An `Elf_Data' structure describes data in an
653*77bd33e1Szrj  * ELF section.
654*77bd33e1Szrj  */
655*77bd33e1Szrj typedef struct _Elf_Data {
656*77bd33e1Szrj 	/*
657*77bd33e1Szrj 	 * `Public' members that are part of the ELF(3) API.
658*77bd33e1Szrj 	 */
659*77bd33e1Szrj 	uint64_t	d_align;
660*77bd33e1Szrj 	void		*d_buf;
661*77bd33e1Szrj 	uint64_t	d_off;
662*77bd33e1Szrj 	uint64_t	d_size;
663*77bd33e1Szrj 	Elf_Type	d_type;
664*77bd33e1Szrj 	unsigned int	d_version;
665*77bd33e1Szrj } Elf_Data;
666*77bd33e1Szrj 
667*77bd33e1Szrj /*
668*77bd33e1Szrj  * An `Elf_Arhdr' structure describes an archive
669*77bd33e1Szrj  * header.
670*77bd33e1Szrj  */
671*77bd33e1Szrj typedef struct {
672*77bd33e1Szrj 	time_t		ar_date;
673*77bd33e1Szrj 	char		*ar_name;	/* archive member name */
674*77bd33e1Szrj 	gid_t		ar_gid;
675*77bd33e1Szrj 	mode_t		ar_mode;
676*77bd33e1Szrj 	char		*ar_rawname;	/* 'raw' member name */
677*77bd33e1Szrj 	size_t		ar_size;
678*77bd33e1Szrj 	uid_t		ar_uid;
679*77bd33e1Szrj 
680*77bd33e1Szrj 	/*
681*77bd33e1Szrj 	 * Members that are not part of the public API.
682*77bd33e1Szrj 	 */
683*77bd33e1Szrj 	unsigned int	ar_flags;
684*77bd33e1Szrj } Elf_Arhdr;
685*77bd33e1Szrj 
686*77bd33e1Szrj /*
687*77bd33e1Szrj  * An `Elf_Arsym' describes an entry in the archive
688*77bd33e1Szrj  * symbol table.
689*77bd33e1Szrj  */
690*77bd33e1Szrj typedef struct {
691*77bd33e1Szrj 	off_t		as_off;		/* byte offset to member's header */
692*77bd33e1Szrj 	unsigned long	as_hash;	/* elf_hash() value for name */
693*77bd33e1Szrj 	char		*as_name;	/* null terminated symbol name */
694*77bd33e1Szrj } Elf_Arsym;
695*77bd33e1Szrj 
696*77bd33e1Szrj /*
697*77bd33e1Szrj  * Error numbers.
698*77bd33e1Szrj  */
699*77bd33e1Szrj 
700*77bd33e1Szrj enum Elf_Error {
701*77bd33e1Szrj 	ELF_E_NONE,	/* No error */
702*77bd33e1Szrj 	ELF_E_ARCHIVE,	/* Malformed ar(1) archive */
703*77bd33e1Szrj 	ELF_E_ARGUMENT,	/* Invalid argument */
704*77bd33e1Szrj 	ELF_E_CLASS,	/* Mismatched ELF class */
705*77bd33e1Szrj 	ELF_E_DATA,	/* Invalid data descriptor */
706*77bd33e1Szrj 	ELF_E_HEADER,	/* Missing or malformed ELF header */
707*77bd33e1Szrj 	ELF_E_IO,	/* I/O error */
708*77bd33e1Szrj 	ELF_E_LAYOUT,	/* Layout constraint violation */
709*77bd33e1Szrj 	ELF_E_MODE,	/* Wrong mode for ELF descriptor */
710*77bd33e1Szrj 	ELF_E_RANGE,	/* Value out of range */
711*77bd33e1Szrj 	ELF_E_RESOURCE,	/* Resource exhaustion */
712*77bd33e1Szrj 	ELF_E_SECTION,	/* Invalid section descriptor */
713*77bd33e1Szrj 	ELF_E_SEQUENCE,	/* API calls out of sequence */
714*77bd33e1Szrj 	ELF_E_UNIMPL,	/* Feature is unimplemented */
715*77bd33e1Szrj 	ELF_E_VERSION,	/* Unknown API version */
716*77bd33e1Szrj 	ELF_E_NUM	/* Max error number */
717*77bd33e1Szrj };
718*77bd33e1Szrj 
719*77bd33e1Szrj /*
720*77bd33e1Szrj  * Flags defined by the API.
721*77bd33e1Szrj  */
722*77bd33e1Szrj 
723*77bd33e1Szrj #define	ELF_F_LAYOUT	0x001U	/* application will layout the file */
724*77bd33e1Szrj #define	ELF_F_DIRTY	0x002U	/* a section or ELF file is dirty */
725*77bd33e1Szrj 
726*77bd33e1Szrj #ifdef __cplusplus
727*77bd33e1Szrj extern "C" {
728*77bd33e1Szrj #endif
729*77bd33e1Szrj static
730*77bd33e1Szrj Elf		*elf_begin(int _fd, Elf_Cmd _cmd, Elf *_elf);
731*77bd33e1Szrj static
732*77bd33e1Szrj int		elf_end(Elf *_elf);
733*77bd33e1Szrj static
734*77bd33e1Szrj const char	*elf_errmsg(int _error);
735*77bd33e1Szrj static
736*77bd33e1Szrj int		elf_errno(void);
737*77bd33e1Szrj static
738*77bd33e1Szrj Elf_Data	*elf_getdata(Elf_Scn *, Elf_Data *);
739*77bd33e1Szrj static
740*77bd33e1Szrj char		*elf_strptr(Elf *_elf, size_t _section, size_t _offset);
741*77bd33e1Szrj static
742*77bd33e1Szrj unsigned int	elf_version(unsigned int _version);
743*77bd33e1Szrj static
744*77bd33e1Szrj Elf_Scn		*elf_nextscn(Elf *_elf, Elf_Scn *_scn);
745*77bd33e1Szrj #ifdef __cplusplus
746*77bd33e1Szrj }
747*77bd33e1Szrj #endif
748*77bd33e1Szrj 
749*77bd33e1Szrj /* gelf.h */
750*77bd33e1Szrj typedef Elf64_Shdr	GElf_Shdr;	/* Section header */
751*77bd33e1Szrj typedef Elf64_Sym	GElf_Sym;	/* Symbol table entries */
752*77bd33e1Szrj 
753*77bd33e1Szrj #ifdef __cplusplus
754*77bd33e1Szrj extern "C" {
755*77bd33e1Szrj #endif
756*77bd33e1Szrj static
757*77bd33e1Szrj GElf_Shdr	*gelf_getshdr(Elf_Scn *_scn, GElf_Shdr *_dst);
758*77bd33e1Szrj static
759*77bd33e1Szrj GElf_Sym	*gelf_getsym(Elf_Data *_src, int _index, GElf_Sym *_dst);
760*77bd33e1Szrj #ifdef __cplusplus
761*77bd33e1Szrj }
762*77bd33e1Szrj #endif
763*77bd33e1Szrj 
764*77bd33e1Szrj /* _libelf.h */
765*77bd33e1Szrj /*
766*77bd33e1Szrj  * Library-private data structures.
767*77bd33e1Szrj  */
768*77bd33e1Szrj 
769*77bd33e1Szrj #define LIBELF_MSG_SIZE	256
770*77bd33e1Szrj 
771*77bd33e1Szrj struct _libelf_globals {
772*77bd33e1Szrj 	int		libelf_arch;
773*77bd33e1Szrj 	unsigned int	libelf_byteorder;
774*77bd33e1Szrj 	int		libelf_class;
775*77bd33e1Szrj 	int		libelf_error;
776*77bd33e1Szrj 	int		libelf_fillchar;
777*77bd33e1Szrj 	unsigned int	libelf_version;
778*77bd33e1Szrj 	unsigned char	libelf_msg[LIBELF_MSG_SIZE];
779*77bd33e1Szrj };
780*77bd33e1Szrj 
781*77bd33e1Szrj #if 0
782*77bd33e1Szrj extern struct _libelf_globals _libelf;
783*77bd33e1Szrj #endif
784*77bd33e1Szrj 
785*77bd33e1Szrj #define	LIBELF_PRIVATE(N)	(_libelf.libelf_##N)
786*77bd33e1Szrj 
787*77bd33e1Szrj #define	LIBELF_ELF_ERROR_MASK			0xFF
788*77bd33e1Szrj #define	LIBELF_OS_ERROR_SHIFT			8
789*77bd33e1Szrj 
790*77bd33e1Szrj #define	LIBELF_ERROR(E, O) (((E) & LIBELF_ELF_ERROR_MASK) |	\
791*77bd33e1Szrj 	((O) << LIBELF_OS_ERROR_SHIFT))
792*77bd33e1Szrj 
793*77bd33e1Szrj #define	LIBELF_SET_ERROR(E, O) do {					\
794*77bd33e1Szrj 		LIBELF_PRIVATE(error) = LIBELF_ERROR(ELF_E_##E, (O));	\
795*77bd33e1Szrj 	} while (0)
796*77bd33e1Szrj 
797*77bd33e1Szrj /*
798*77bd33e1Szrj  * Flags for library internal use.  These use the upper 16 bits of the
799*77bd33e1Szrj  * `e_flags' field.
800*77bd33e1Szrj  */
801*77bd33e1Szrj 
802*77bd33e1Szrj #define	LIBELF_F_DATA_MALLOCED	0x040000U /* whether data was malloc'ed */
803*77bd33e1Szrj #define	LIBELF_F_RAWFILE_MALLOC	0x080000U /* whether e_rawfile was malloc'ed */
804*77bd33e1Szrj #define	LIBELF_F_RAWFILE_MMAP	0x100000U /* whether e_rawfile was mmap'ed */
805*77bd33e1Szrj #define	LIBELF_F_SHDRS_LOADED	0x200000U /* whether all shdrs were read in */
806*77bd33e1Szrj #define	LIBELF_F_SPECIAL_FILE	0x400000U /* non-regular file */
807*77bd33e1Szrj 
808*77bd33e1Szrj struct _Elf {
809*77bd33e1Szrj 	int		e_activations;	/* activation count */
810*77bd33e1Szrj 	unsigned int	e_byteorder;	/* ELFDATA* */
811*77bd33e1Szrj 	int		e_class;	/* ELFCLASS*  */
812*77bd33e1Szrj 	Elf_Cmd		e_cmd;		/* ELF_C_* used at creation time */
813*77bd33e1Szrj 	int		e_fd;		/* associated file descriptor */
814*77bd33e1Szrj 	unsigned int	e_flags;	/* ELF_F_* & LIBELF_F_* flags */
815*77bd33e1Szrj 	Elf_Kind	e_kind;		/* ELF_K_* */
816*77bd33e1Szrj 	Elf		*e_parent;	/* non-NULL for archive members */
817*77bd33e1Szrj 	unsigned char	*e_rawfile;	/* uninterpreted bytes */
818*77bd33e1Szrj 	size_t		e_rawsize;	/* size of uninterpreted bytes */
819*77bd33e1Szrj 	unsigned int	e_version;	/* file version */
820*77bd33e1Szrj 
821*77bd33e1Szrj 	/*
822*77bd33e1Szrj 	 * Header information for archive members.  See the
823*77bd33e1Szrj 	 * LIBELF_F_AR_HEADER flag.
824*77bd33e1Szrj 	 */
825*77bd33e1Szrj 	union {
826*77bd33e1Szrj 		Elf_Arhdr	*e_arhdr;	/* translated header */
827*77bd33e1Szrj 		unsigned char	*e_rawhdr;	/* untranslated header */
828*77bd33e1Szrj 	} e_hdr;
829*77bd33e1Szrj 
830*77bd33e1Szrj 	union {
831*77bd33e1Szrj 		struct {		/* ar(1) archives */
832*77bd33e1Szrj 			off_t	e_next;	/* set by elf_rand()/elf_next() */
833*77bd33e1Szrj 			int	e_nchildren;
834*77bd33e1Szrj 			unsigned char *e_rawstrtab; /* file name strings */
835*77bd33e1Szrj 			size_t	e_rawstrtabsz;
836*77bd33e1Szrj 			unsigned char *e_rawsymtab;	/* symbol table */
837*77bd33e1Szrj 			size_t	e_rawsymtabsz;
838*77bd33e1Szrj 			Elf_Arsym *e_symtab;
839*77bd33e1Szrj 			size_t	e_symtabsz;
840*77bd33e1Szrj 		} e_ar;
841*77bd33e1Szrj 		struct {		/* regular ELF files */
842*77bd33e1Szrj 			union {
843*77bd33e1Szrj #if 0
844*77bd33e1Szrj 				Elf32_Ehdr *e_ehdr32;
845*77bd33e1Szrj #endif
846*77bd33e1Szrj 				Elf64_Ehdr *e_ehdr64;
847*77bd33e1Szrj 			} e_ehdr;
848*77bd33e1Szrj 			union {
849*77bd33e1Szrj #if 0
850*77bd33e1Szrj 				Elf32_Phdr *e_phdr32;
851*77bd33e1Szrj #endif
852*77bd33e1Szrj 				Elf64_Phdr *e_phdr64;
853*77bd33e1Szrj 			} e_phdr;
854*77bd33e1Szrj 			STAILQ_HEAD(, _Elf_Scn)	e_scn;	/* section list */
855*77bd33e1Szrj 			size_t	e_nphdr;	/* number of Phdr entries */
856*77bd33e1Szrj 			size_t	e_nscn;		/* number of sections */
857*77bd33e1Szrj 			size_t	e_strndx;	/* string table section index */
858*77bd33e1Szrj 		} e_elf;
859*77bd33e1Szrj 	} e_u;
860*77bd33e1Szrj };
861*77bd33e1Szrj 
862*77bd33e1Szrj /*
863*77bd33e1Szrj  * The internal descriptor wrapping the "Elf_Data" type.
864*77bd33e1Szrj  */
865*77bd33e1Szrj struct _Libelf_Data {
866*77bd33e1Szrj 	Elf_Data	d_data;		/* The exported descriptor. */
867*77bd33e1Szrj 	Elf_Scn		*d_scn;		/* The containing section */
868*77bd33e1Szrj 	unsigned int	d_flags;
869*77bd33e1Szrj 	STAILQ_ENTRY(_Libelf_Data) d_next;
870*77bd33e1Szrj };
871*77bd33e1Szrj 
872*77bd33e1Szrj struct _Elf_Scn {
873*77bd33e1Szrj 	union {
874*77bd33e1Szrj #if 0
875*77bd33e1Szrj 		Elf32_Shdr	s_shdr32;
876*77bd33e1Szrj #endif
877*77bd33e1Szrj 		Elf64_Shdr	s_shdr64;
878*77bd33e1Szrj 	} s_shdr;
879*77bd33e1Szrj 	STAILQ_HEAD(, _Libelf_Data) s_data;	/* translated data */
880*77bd33e1Szrj 	STAILQ_HEAD(, _Libelf_Data) s_rawdata;	/* raw data */
881*77bd33e1Szrj 	STAILQ_ENTRY(_Elf_Scn) s_next;
882*77bd33e1Szrj 	struct _Elf	*s_elf;		/* parent ELF descriptor */
883*77bd33e1Szrj 	unsigned int	s_flags;	/* flags for the section as a whole */
884*77bd33e1Szrj 	size_t		s_ndx;		/* index# for this section */
885*77bd33e1Szrj 	uint64_t	s_offset;	/* managed by elf_update() */
886*77bd33e1Szrj 	uint64_t	s_rawoff;	/* original offset in the file */
887*77bd33e1Szrj 	uint64_t	s_size;		/* managed by elf_update() */
888*77bd33e1Szrj };
889*77bd33e1Szrj 
890*77bd33e1Szrj enum {
891*77bd33e1Szrj 	ELF_TOFILE,
892*77bd33e1Szrj 	ELF_TOMEMORY
893*77bd33e1Szrj };
894*77bd33e1Szrj 
895*77bd33e1Szrj /* PRIVATE */
896*77bd33e1Szrj 
897*77bd33e1Szrj /* elf.c */
898*77bd33e1Szrj static struct _libelf_globals _libelf = {
899*77bd33e1Szrj 	.libelf_arch		= LIBELF_ARCH,
900*77bd33e1Szrj 	.libelf_byteorder	= LIBELF_BYTEORDER,
901*77bd33e1Szrj 	.libelf_class		= LIBELF_CLASS,
902*77bd33e1Szrj 	.libelf_error		= 0,
903*77bd33e1Szrj 	.libelf_fillchar	= 0,
904*77bd33e1Szrj 	.libelf_version		= EV_NONE
905*77bd33e1Szrj };
906*77bd33e1Szrj 
907*77bd33e1Szrj /* libelf_msize.c */
908*77bd33e1Szrj struct msize {
909*77bd33e1Szrj 	size_t	msz64;
910*77bd33e1Szrj };
911*77bd33e1Szrj 
912*77bd33e1Szrj static struct msize msize[ELF_T_NUM] = {
913*77bd33e1Szrj [ELF_T_ADDR] = { .msz64 = sizeof(Elf64_Addr) },
914*77bd33e1Szrj [ELF_T_BYTE] = { .msz64 = 1 },
915*77bd33e1Szrj [ELF_T_CAP] = { .msz64 = sizeof(Elf64_Cap) },
916*77bd33e1Szrj [ELF_T_DYN] = { .msz64 = sizeof(Elf64_Dyn) },
917*77bd33e1Szrj [ELF_T_EHDR] = { .msz64 = sizeof(Elf64_Ehdr) },
918*77bd33e1Szrj [ELF_T_GNUHASH] = { .msz64 = 1 },
919*77bd33e1Szrj [ELF_T_HALF] = { .msz64 = sizeof(Elf64_Half) },
920*77bd33e1Szrj [ELF_T_LWORD] = { .msz64 = sizeof(Elf64_Lword) },
921*77bd33e1Szrj [ELF_T_MOVE] = { .msz64 = sizeof(Elf64_Move) },
922*77bd33e1Szrj [ELF_T_MOVEP] = { .msz64 = 0 },
923*77bd33e1Szrj [ELF_T_NOTE] = { .msz64 = 1 },
924*77bd33e1Szrj [ELF_T_OFF] = { .msz64 = sizeof(Elf64_Off) },
925*77bd33e1Szrj [ELF_T_PHDR] = { .msz64 = sizeof(Elf64_Phdr) },
926*77bd33e1Szrj [ELF_T_REL] = { .msz64 = sizeof(Elf64_Rel) },
927*77bd33e1Szrj [ELF_T_RELA] = { .msz64 = sizeof(Elf64_Rela) },
928*77bd33e1Szrj [ELF_T_SHDR] = { .msz64 = sizeof(Elf64_Shdr) },
929*77bd33e1Szrj [ELF_T_SWORD] = { .msz64 = sizeof(Elf64_Sword) },
930*77bd33e1Szrj [ELF_T_SXWORD] = { .msz64 = sizeof(Elf64_Sxword) },
931*77bd33e1Szrj [ELF_T_SYMINFO] = { .msz64 = sizeof(Elf64_Syminfo) },
932*77bd33e1Szrj [ELF_T_SYM] = { .msz64 = sizeof(Elf64_Sym) },
933*77bd33e1Szrj [ELF_T_VDEF] = { .msz64 = 1 },
934*77bd33e1Szrj [ELF_T_VNEED] = { .msz64 = 1 },
935*77bd33e1Szrj [ELF_T_WORD] = { .msz64 = sizeof(Elf64_Word) },
936*77bd33e1Szrj [ELF_T_XWORD] = { .msz64 = sizeof(Elf64_Xword) },
937*77bd33e1Szrj };
938*77bd33e1Szrj 
939*77bd33e1Szrj static size_t
_libelf_msize(Elf_Type t,int elfclass,unsigned int version)940*77bd33e1Szrj _libelf_msize(Elf_Type t, int elfclass, unsigned int version)
941*77bd33e1Szrj {
942*77bd33e1Szrj 	size_t sz;
943*77bd33e1Szrj 
944*77bd33e1Szrj 	assert(/*elfclass == ELFCLASS32 ||*/ elfclass == ELFCLASS64);
945*77bd33e1Szrj 	assert((signed) t >= ELF_T_FIRST && t <= ELF_T_LAST);
946*77bd33e1Szrj 
947*77bd33e1Szrj 	if (version != EV_CURRENT) {
948*77bd33e1Szrj 		LIBELF_SET_ERROR(VERSION, 0);
949*77bd33e1Szrj 		return (0);
950*77bd33e1Szrj 	}
951*77bd33e1Szrj 
952*77bd33e1Szrj 	sz = /* (elfclass == ELFCLASS32) ? msize[t].msz32 : */ msize[t].msz64;
953*77bd33e1Szrj 
954*77bd33e1Szrj 	return (sz);
955*77bd33e1Szrj }
956*77bd33e1Szrj 
957*77bd33e1Szrj /* libelf_fsize.c */
958*77bd33e1Szrj struct tfsize {
959*77bd33e1Szrj 	size_t fsz64;
960*77bd33e1Szrj };
961*77bd33e1Szrj 
962*77bd33e1Szrj static struct tfsize tfsize[ELF_T_NUM] = {
963*77bd33e1Szrj [ELF_T_ADDR] =    { .fsz64 = sizeof(Elf64_Addr) },
964*77bd33e1Szrj [ELF_T_BYTE] =    { .fsz64 = 1 },
965*77bd33e1Szrj [ELF_T_CAP] =     { .fsz64 = sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
966*77bd33e1Szrj [ELF_T_DYN] =     { .fsz64 = sizeof(Elf64_Sxword)+sizeof(Elf64_Xword)+0 },
967*77bd33e1Szrj [ELF_T_EHDR] =    { .fsz64 = EI_NIDENT
968*77bd33e1Szrj 			    +sizeof(Elf64_Half)+sizeof(Elf64_Half)
969*77bd33e1Szrj 			    +sizeof(Elf64_Word)+sizeof(Elf64_Addr)
970*77bd33e1Szrj 			    +sizeof(Elf64_Off)+ sizeof(Elf64_Off)
971*77bd33e1Szrj 			    +sizeof(Elf64_Word)+sizeof(Elf64_Half)
972*77bd33e1Szrj 			    +sizeof(Elf64_Half)+sizeof(Elf64_Half)
973*77bd33e1Szrj 			    +sizeof(Elf64_Half)+sizeof(Elf64_Half)
974*77bd33e1Szrj 			    +sizeof(Elf64_Half)+0 },
975*77bd33e1Szrj [ELF_T_GNUHASH] = { .fsz64 = 1 },
976*77bd33e1Szrj [ELF_T_HALF] =    { .fsz64 = sizeof(Elf64_Half) },
977*77bd33e1Szrj [ELF_T_LWORD] =   { .fsz64 = sizeof(Elf64_Lword) },
978*77bd33e1Szrj [ELF_T_MOVE] =    { .fsz64 = sizeof(Elf64_Lword)+sizeof(Elf64_Xword)
979*77bd33e1Szrj 			    +sizeof(Elf64_Xword)+sizeof(Elf64_Half)
980*77bd33e1Szrj 			    +sizeof(Elf64_Half)+0 },
981*77bd33e1Szrj [ELF_T_MOVEP] =   { .fsz64 = 0 },
982*77bd33e1Szrj [ELF_T_NOTE] =    { .fsz64 = 1 },
983*77bd33e1Szrj [ELF_T_OFF] =     { .fsz64 = sizeof(Elf64_Off) },
984*77bd33e1Szrj [ELF_T_PHDR] =    { .fsz64 = sizeof(Elf64_Word)+sizeof(Elf64_Word)
985*77bd33e1Szrj 			    +sizeof(Elf64_Off)+ sizeof(Elf64_Addr)
986*77bd33e1Szrj 			    +sizeof(Elf64_Addr)+sizeof(Elf64_Xword)
987*77bd33e1Szrj 			    +sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
988*77bd33e1Szrj [ELF_T_REL] =     { .fsz64 = sizeof(Elf64_Addr)+sizeof(Elf64_Xword)+0 },
989*77bd33e1Szrj [ELF_T_RELA] =    { .fsz64 = sizeof(Elf64_Addr)+sizeof(Elf64_Xword)
990*77bd33e1Szrj 			    +sizeof(Elf64_Sxword)+0 },
991*77bd33e1Szrj [ELF_T_SHDR] =    { .fsz64 = sizeof(Elf64_Word)+sizeof(Elf64_Word)
992*77bd33e1Szrj 			    +sizeof(Elf64_Xword)+sizeof(Elf64_Addr)
993*77bd33e1Szrj 			    +sizeof(Elf64_Off)+ sizeof(Elf64_Xword)
994*77bd33e1Szrj 			    +sizeof(Elf64_Word)+sizeof(Elf64_Word)
995*77bd33e1Szrj 			    +sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
996*77bd33e1Szrj [ELF_T_SWORD] =   { .fsz64 = sizeof(Elf64_Sword) },
997*77bd33e1Szrj [ELF_T_SXWORD] =  { .fsz64 = sizeof(Elf64_Sxword) },
998*77bd33e1Szrj [ELF_T_SYMINFO] = { .fsz64 = sizeof(Elf64_Half)+sizeof(Elf64_Half)+0 },
999*77bd33e1Szrj [ELF_T_SYM] =     { .fsz64 = sizeof(Elf64_Word)+1+1+sizeof(Elf64_Half)
1000*77bd33e1Szrj 			    +sizeof(Elf64_Addr)+sizeof(Elf64_Xword)+0 },
1001*77bd33e1Szrj [ELF_T_VDEF] =    { .fsz64 = 1 },
1002*77bd33e1Szrj [ELF_T_VNEED] =   { .fsz64 = 1 },
1003*77bd33e1Szrj [ELF_T_WORD] =    { .fsz64 = sizeof(Elf64_Word) },
1004*77bd33e1Szrj [ELF_T_XWORD] =   { .fsz64 = sizeof(Elf64_Xword) },
1005*77bd33e1Szrj };
1006*77bd33e1Szrj 
1007*77bd33e1Szrj static size_t
_libelf_fsize(Elf_Type t,int ec,unsigned int v,size_t c)1008*77bd33e1Szrj _libelf_fsize(Elf_Type t, int ec, unsigned int v, size_t c)
1009*77bd33e1Szrj {
1010*77bd33e1Szrj 	size_t sz;
1011*77bd33e1Szrj 
1012*77bd33e1Szrj 	sz = 0;
1013*77bd33e1Szrj 	if (v != EV_CURRENT)
1014*77bd33e1Szrj 		LIBELF_SET_ERROR(VERSION, 0);
1015*77bd33e1Szrj 	else if ((int) t < ELF_T_FIRST || t > ELF_T_LAST)
1016*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
1017*77bd33e1Szrj 	else {
1018*77bd33e1Szrj 		sz = ec == ELFCLASS64 ? tfsize[t].fsz64 : /* tfsize[t].fsz32 */ 0;
1019*77bd33e1Szrj 		if (sz == 0)
1020*77bd33e1Szrj 			LIBELF_SET_ERROR(UNIMPL, 0);
1021*77bd33e1Szrj 	}
1022*77bd33e1Szrj 
1023*77bd33e1Szrj 	return (sz*c);
1024*77bd33e1Szrj }
1025*77bd33e1Szrj 
1026*77bd33e1Szrj /* gelf_fsize.c */
1027*77bd33e1Szrj static size_t
elf64_fsize(Elf_Type t,size_t c,unsigned int v)1028*77bd33e1Szrj elf64_fsize(Elf_Type t, size_t c, unsigned int v)
1029*77bd33e1Szrj {
1030*77bd33e1Szrj 	return (_libelf_fsize(t, ELFCLASS64, v, c));
1031*77bd33e1Szrj }
1032*77bd33e1Szrj 
1033*77bd33e1Szrj /* libelf_allocate.h */
1034*77bd33e1Szrj static Elf *
_libelf_allocate_elf(void)1035*77bd33e1Szrj _libelf_allocate_elf(void)
1036*77bd33e1Szrj {
1037*77bd33e1Szrj 	Elf *e;
1038*77bd33e1Szrj 
1039*77bd33e1Szrj 	if ((e = malloc(sizeof(*e))) == NULL) {
1040*77bd33e1Szrj 		LIBELF_SET_ERROR(RESOURCE, errno);
1041*77bd33e1Szrj 		return NULL;
1042*77bd33e1Szrj 	}
1043*77bd33e1Szrj 
1044*77bd33e1Szrj 	e->e_activations = 1;
1045*77bd33e1Szrj 	e->e_hdr.e_rawhdr = NULL;
1046*77bd33e1Szrj 	e->e_byteorder   = ELFDATANONE;
1047*77bd33e1Szrj 	e->e_class       = ELFCLASSNONE;
1048*77bd33e1Szrj 	e->e_cmd         = ELF_C_NULL;
1049*77bd33e1Szrj 	e->e_fd          = -1;
1050*77bd33e1Szrj 	e->e_flags	 = 0;
1051*77bd33e1Szrj 	e->e_kind        = ELF_K_NONE;
1052*77bd33e1Szrj 	e->e_parent      = NULL;
1053*77bd33e1Szrj 	e->e_rawfile     = NULL;
1054*77bd33e1Szrj 	e->e_rawsize     = 0;
1055*77bd33e1Szrj 	e->e_version     = LIBELF_PRIVATE(version);
1056*77bd33e1Szrj 
1057*77bd33e1Szrj 	(void) memset(&e->e_u, 0, sizeof(e->e_u));
1058*77bd33e1Szrj 
1059*77bd33e1Szrj 	return (e);
1060*77bd33e1Szrj }
1061*77bd33e1Szrj 
1062*77bd33e1Szrj static void
_libelf_init_elf(Elf * e,Elf_Kind kind)1063*77bd33e1Szrj _libelf_init_elf(Elf *e, Elf_Kind kind)
1064*77bd33e1Szrj {
1065*77bd33e1Szrj 	assert(e != NULL);
1066*77bd33e1Szrj 	assert(e->e_kind == ELF_K_NONE);
1067*77bd33e1Szrj 
1068*77bd33e1Szrj 	e->e_kind = kind;
1069*77bd33e1Szrj 
1070*77bd33e1Szrj 	switch (kind) {
1071*77bd33e1Szrj 	case ELF_K_ELF:
1072*77bd33e1Szrj 		STAILQ_INIT(&e->e_u.e_elf.e_scn);
1073*77bd33e1Szrj 		break;
1074*77bd33e1Szrj 	default:
1075*77bd33e1Szrj 		break;
1076*77bd33e1Szrj 	}
1077*77bd33e1Szrj }
1078*77bd33e1Szrj 
1079*77bd33e1Szrj #define	FREE(P)		do {				\
1080*77bd33e1Szrj 		if (P)					\
1081*77bd33e1Szrj 			free(P);			\
1082*77bd33e1Szrj 	} while (0)
1083*77bd33e1Szrj 
1084*77bd33e1Szrj static Elf *
_libelf_release_elf(Elf * e)1085*77bd33e1Szrj _libelf_release_elf(Elf *e)
1086*77bd33e1Szrj {
1087*77bd33e1Szrj #if 0
1088*77bd33e1Szrj 	Elf_Arhdr *arh;
1089*77bd33e1Szrj #endif
1090*77bd33e1Szrj 
1091*77bd33e1Szrj 	switch (e->e_kind) {
1092*77bd33e1Szrj #if 0
1093*77bd33e1Szrj 	case ELF_K_AR:
1094*77bd33e1Szrj 		FREE(e->e_u.e_ar.e_symtab);
1095*77bd33e1Szrj 		break;
1096*77bd33e1Szrj #endif
1097*77bd33e1Szrj 
1098*77bd33e1Szrj 	case ELF_K_ELF:
1099*77bd33e1Szrj 		switch (e->e_class) {
1100*77bd33e1Szrj #if 0
1101*77bd33e1Szrj 		case ELFCLASS32:
1102*77bd33e1Szrj 			FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
1103*77bd33e1Szrj 			FREE(e->e_u.e_elf.e_phdr.e_phdr32);
1104*77bd33e1Szrj 			break;
1105*77bd33e1Szrj #endif
1106*77bd33e1Szrj 		case ELFCLASS64:
1107*77bd33e1Szrj 			FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
1108*77bd33e1Szrj 			FREE(e->e_u.e_elf.e_phdr.e_phdr64);
1109*77bd33e1Szrj 			break;
1110*77bd33e1Szrj 		}
1111*77bd33e1Szrj 
1112*77bd33e1Szrj 		assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
1113*77bd33e1Szrj 
1114*77bd33e1Szrj #if 0
1115*77bd33e1Szrj 		if (e->e_flags & LIBELF_F_AR_HEADER) {
1116*77bd33e1Szrj 			arh = e->e_hdr.e_arhdr;
1117*77bd33e1Szrj 			FREE(arh->ar_name);
1118*77bd33e1Szrj 			FREE(arh->ar_rawname);
1119*77bd33e1Szrj 			free(arh);
1120*77bd33e1Szrj 		}
1121*77bd33e1Szrj #endif
1122*77bd33e1Szrj 
1123*77bd33e1Szrj 		break;
1124*77bd33e1Szrj 
1125*77bd33e1Szrj 	default:
1126*77bd33e1Szrj 		break;
1127*77bd33e1Szrj 	}
1128*77bd33e1Szrj 
1129*77bd33e1Szrj 	free(e);
1130*77bd33e1Szrj 
1131*77bd33e1Szrj 	return (NULL);
1132*77bd33e1Szrj }
1133*77bd33e1Szrj 
1134*77bd33e1Szrj #undef FREE
1135*77bd33e1Szrj 
1136*77bd33e1Szrj static struct _Libelf_Data *
_libelf_allocate_data(Elf_Scn * s)1137*77bd33e1Szrj _libelf_allocate_data(Elf_Scn *s)
1138*77bd33e1Szrj {
1139*77bd33e1Szrj 	struct _Libelf_Data *d;
1140*77bd33e1Szrj 
1141*77bd33e1Szrj 	if ((d = calloc((size_t) 1, sizeof(*d))) == NULL) {
1142*77bd33e1Szrj 		LIBELF_SET_ERROR(RESOURCE, 0);
1143*77bd33e1Szrj 		return (NULL);
1144*77bd33e1Szrj 	}
1145*77bd33e1Szrj 
1146*77bd33e1Szrj 	d->d_scn = s;
1147*77bd33e1Szrj 
1148*77bd33e1Szrj 	return (d);
1149*77bd33e1Szrj }
1150*77bd33e1Szrj 
1151*77bd33e1Szrj static struct _Libelf_Data *
_libelf_release_data(struct _Libelf_Data * d)1152*77bd33e1Szrj _libelf_release_data(struct _Libelf_Data *d)
1153*77bd33e1Szrj {
1154*77bd33e1Szrj 
1155*77bd33e1Szrj 	if (d->d_flags & LIBELF_F_DATA_MALLOCED)
1156*77bd33e1Szrj 		free(d->d_data.d_buf);
1157*77bd33e1Szrj 
1158*77bd33e1Szrj 	free(d);
1159*77bd33e1Szrj 
1160*77bd33e1Szrj 	return (NULL);
1161*77bd33e1Szrj }
1162*77bd33e1Szrj 
1163*77bd33e1Szrj static Elf_Scn *
_libelf_allocate_scn(Elf * e,size_t ndx)1164*77bd33e1Szrj _libelf_allocate_scn(Elf *e, size_t ndx)
1165*77bd33e1Szrj {
1166*77bd33e1Szrj 	Elf_Scn *s;
1167*77bd33e1Szrj 
1168*77bd33e1Szrj 	if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
1169*77bd33e1Szrj 		LIBELF_SET_ERROR(RESOURCE, errno);
1170*77bd33e1Szrj 		return (NULL);
1171*77bd33e1Szrj 	}
1172*77bd33e1Szrj 
1173*77bd33e1Szrj 	s->s_elf = e;
1174*77bd33e1Szrj 	s->s_ndx = ndx;
1175*77bd33e1Szrj 
1176*77bd33e1Szrj 	STAILQ_INIT(&s->s_data);
1177*77bd33e1Szrj 	STAILQ_INIT(&s->s_rawdata);
1178*77bd33e1Szrj 
1179*77bd33e1Szrj 	STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
1180*77bd33e1Szrj 
1181*77bd33e1Szrj 	return (s);
1182*77bd33e1Szrj }
1183*77bd33e1Szrj 
1184*77bd33e1Szrj static Elf_Scn *
_libelf_release_scn(Elf_Scn * s)1185*77bd33e1Szrj _libelf_release_scn(Elf_Scn *s)
1186*77bd33e1Szrj {
1187*77bd33e1Szrj 	Elf *e;
1188*77bd33e1Szrj 	struct _Libelf_Data *d, *td;
1189*77bd33e1Szrj 
1190*77bd33e1Szrj 	assert(s != NULL);
1191*77bd33e1Szrj 
1192*77bd33e1Szrj 	STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
1193*77bd33e1Szrj 		STAILQ_REMOVE(&s->s_data, d, _Libelf_Data, d_next);
1194*77bd33e1Szrj 		d = _libelf_release_data(d);
1195*77bd33e1Szrj 	}
1196*77bd33e1Szrj 
1197*77bd33e1Szrj 	STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) {
1198*77bd33e1Szrj 		assert((d->d_flags & LIBELF_F_DATA_MALLOCED) == 0);
1199*77bd33e1Szrj 		STAILQ_REMOVE(&s->s_rawdata, d, _Libelf_Data, d_next);
1200*77bd33e1Szrj 		d = _libelf_release_data(d);
1201*77bd33e1Szrj 	}
1202*77bd33e1Szrj 
1203*77bd33e1Szrj 	e = s->s_elf;
1204*77bd33e1Szrj 
1205*77bd33e1Szrj 	assert(e != NULL);
1206*77bd33e1Szrj 
1207*77bd33e1Szrj 	STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
1208*77bd33e1Szrj 
1209*77bd33e1Szrj 	free(s);
1210*77bd33e1Szrj 
1211*77bd33e1Szrj 	return (NULL);
1212*77bd33e1Szrj }
1213*77bd33e1Szrj 
1214*77bd33e1Szrj /* libelf_data.c */
1215*77bd33e1Szrj static int
_libelf_xlate_shtype(uint32_t sht)1216*77bd33e1Szrj _libelf_xlate_shtype(uint32_t sht)
1217*77bd33e1Szrj {
1218*77bd33e1Szrj 	/*
1219*77bd33e1Szrj 	 * Look for known section types.
1220*77bd33e1Szrj 	 */
1221*77bd33e1Szrj 	switch (sht) {
1222*77bd33e1Szrj 	case SHT_DYNAMIC:
1223*77bd33e1Szrj 		return (ELF_T_DYN);
1224*77bd33e1Szrj 	case SHT_DYNSYM:
1225*77bd33e1Szrj 		return (ELF_T_SYM);
1226*77bd33e1Szrj 	case SHT_FINI_ARRAY:
1227*77bd33e1Szrj 		return (ELF_T_ADDR);
1228*77bd33e1Szrj 	case SHT_GNU_HASH:
1229*77bd33e1Szrj 		return (ELF_T_GNUHASH);
1230*77bd33e1Szrj 	case SHT_GNU_LIBLIST:
1231*77bd33e1Szrj 		return (ELF_T_WORD);
1232*77bd33e1Szrj 	case SHT_GROUP:
1233*77bd33e1Szrj 		return (ELF_T_WORD);
1234*77bd33e1Szrj 	case SHT_HASH:
1235*77bd33e1Szrj 		return (ELF_T_WORD);
1236*77bd33e1Szrj 	case SHT_INIT_ARRAY:
1237*77bd33e1Szrj 		return (ELF_T_ADDR);
1238*77bd33e1Szrj 	case SHT_NOBITS:
1239*77bd33e1Szrj 		return (ELF_T_BYTE);
1240*77bd33e1Szrj 	case SHT_NOTE:
1241*77bd33e1Szrj 		return (ELF_T_NOTE);
1242*77bd33e1Szrj 	case SHT_PREINIT_ARRAY:
1243*77bd33e1Szrj 		return (ELF_T_ADDR);
1244*77bd33e1Szrj 	case SHT_PROGBITS:
1245*77bd33e1Szrj 		return (ELF_T_BYTE);
1246*77bd33e1Szrj 	case SHT_REL:
1247*77bd33e1Szrj 		return (ELF_T_REL);
1248*77bd33e1Szrj 	case SHT_RELA:
1249*77bd33e1Szrj 		return (ELF_T_RELA);
1250*77bd33e1Szrj 	case SHT_STRTAB:
1251*77bd33e1Szrj 		return (ELF_T_BYTE);
1252*77bd33e1Szrj 	case SHT_SYMTAB:
1253*77bd33e1Szrj 		return (ELF_T_SYM);
1254*77bd33e1Szrj 	case SHT_SYMTAB_SHNDX:
1255*77bd33e1Szrj 		return (ELF_T_WORD);
1256*77bd33e1Szrj 	case SHT_SUNW_dof:
1257*77bd33e1Szrj 		return (ELF_T_BYTE);
1258*77bd33e1Szrj 	case SHT_SUNW_move:
1259*77bd33e1Szrj 		return (ELF_T_MOVE);
1260*77bd33e1Szrj 	case SHT_SUNW_syminfo:
1261*77bd33e1Szrj 		return (ELF_T_SYMINFO);
1262*77bd33e1Szrj 	case SHT_SUNW_verdef:	/* == SHT_GNU_verdef */
1263*77bd33e1Szrj 		return (ELF_T_VDEF);
1264*77bd33e1Szrj 	case SHT_SUNW_verneed:	/* == SHT_GNU_verneed */
1265*77bd33e1Szrj 		return (ELF_T_VNEED);
1266*77bd33e1Szrj 	case SHT_SUNW_versym:	/* == SHT_GNU_versym */
1267*77bd33e1Szrj 		return (ELF_T_HALF);
1268*77bd33e1Szrj 	default:
1269*77bd33e1Szrj 		/*
1270*77bd33e1Szrj 		 * Values in the range [SHT_LOOS..SHT_HIUSER] (i.e.,
1271*77bd33e1Szrj 		 * OS, processor and user-defined section types) are
1272*77bd33e1Szrj 		 * legal, but since we do not know anything more about
1273*77bd33e1Szrj 		 * their semantics, we return a type of ELF_T_BYTE.
1274*77bd33e1Szrj 		 */
1275*77bd33e1Szrj 		if (sht >= SHT_LOOS && sht <= SHT_HIUSER)
1276*77bd33e1Szrj 			return (ELF_T_BYTE);
1277*77bd33e1Szrj 
1278*77bd33e1Szrj 		/*
1279*77bd33e1Szrj 		 * Other values are unsupported.
1280*77bd33e1Szrj 		 */
1281*77bd33e1Szrj 		return (-1);
1282*77bd33e1Szrj 	}
1283*77bd33e1Szrj }
1284*77bd33e1Szrj 
1285*77bd33e1Szrj /* libelf_convert.c */
1286*77bd33e1Szrj #define	SWAP_BYTE(X)	do { (void) (X); } while (0)
1287*77bd33e1Szrj #define	SWAP_IDENT(X)	do { (void) (X); } while (0)
1288*77bd33e1Szrj #define	SWAP_HALF(X)	do {						\
1289*77bd33e1Szrj 		uint16_t _x = (uint16_t) (X);				\
1290*77bd33e1Szrj 		uint32_t _t = _x & 0xFFU;				\
1291*77bd33e1Szrj 		_t <<= 8U; _x >>= 8U; _t |= _x & 0xFFU;			\
1292*77bd33e1Szrj 		(X) = (uint16_t) _t;					\
1293*77bd33e1Szrj 	} while (0)
1294*77bd33e1Szrj #define	_SWAP_WORD(X, T) do {						\
1295*77bd33e1Szrj 		uint32_t _x = (uint32_t) (X);				\
1296*77bd33e1Szrj 		uint32_t _t = _x & 0xFF;				\
1297*77bd33e1Szrj 		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
1298*77bd33e1Szrj 		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
1299*77bd33e1Szrj 		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
1300*77bd33e1Szrj 		(X) = (T) _t;						\
1301*77bd33e1Szrj 	} while (0)
1302*77bd33e1Szrj #define	SWAP_SWORD(X)	_SWAP_WORD(X, /* Elf32_Sword */ Elf64_Sword)
1303*77bd33e1Szrj #define	SWAP_WORD(X)	_SWAP_WORD(X, /* Elf32_Word */ Elf64_Word)
1304*77bd33e1Szrj #define	_SWAP_WORD64(X, T) do {						\
1305*77bd33e1Szrj 		uint64_t _x = (uint64_t) (X);				\
1306*77bd33e1Szrj 		uint64_t _t = _x & 0xFF;				\
1307*77bd33e1Szrj 		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
1308*77bd33e1Szrj 		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
1309*77bd33e1Szrj 		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
1310*77bd33e1Szrj 		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
1311*77bd33e1Szrj 		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
1312*77bd33e1Szrj 		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
1313*77bd33e1Szrj 		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
1314*77bd33e1Szrj 		(X) = (T) _t;						\
1315*77bd33e1Szrj 	} while (0)
1316*77bd33e1Szrj #define	SWAP_ADDR64(X)	_SWAP_WORD64(X, Elf64_Addr)
1317*77bd33e1Szrj #define	SWAP_LWORD(X)	_SWAP_WORD64(X, Elf64_Lword)
1318*77bd33e1Szrj #define	SWAP_OFF64(X)	_SWAP_WORD64(X, Elf64_Off)
1319*77bd33e1Szrj #define	SWAP_SXWORD(X)	_SWAP_WORD64(X, Elf64_Sxword)
1320*77bd33e1Szrj #define	SWAP_XWORD(X)	_SWAP_WORD64(X, Elf64_Xword)
1321*77bd33e1Szrj 
1322*77bd33e1Szrj #define	READ_BYTE(P,X)	do {						\
1323*77bd33e1Szrj 		const unsigned char *const _p =				\
1324*77bd33e1Szrj 			(const unsigned char *) (P);			\
1325*77bd33e1Szrj 		(X)		= _p[0];				\
1326*77bd33e1Szrj 		(P)		= (P) + 1;				\
1327*77bd33e1Szrj 	} while (0)
1328*77bd33e1Szrj #define	READ_HALF(P,X)	do {						\
1329*77bd33e1Szrj 		uint16_t _t;						\
1330*77bd33e1Szrj 		unsigned char *const _q = (unsigned char *) &_t;	\
1331*77bd33e1Szrj 		const unsigned char *const _p =				\
1332*77bd33e1Szrj 			(const unsigned char *) (P);			\
1333*77bd33e1Szrj 		_q[0]		= _p[0];				\
1334*77bd33e1Szrj 		_q[1]		= _p[1];				\
1335*77bd33e1Szrj 		(P)		= (P) + 2;				\
1336*77bd33e1Szrj 		(X)		= _t;					\
1337*77bd33e1Szrj 	} while (0)
1338*77bd33e1Szrj #define	_READ_WORD(P,X,T) do {						\
1339*77bd33e1Szrj 		uint32_t _t;						\
1340*77bd33e1Szrj 		unsigned char *const _q = (unsigned char *) &_t;	\
1341*77bd33e1Szrj 		const unsigned char *const _p =				\
1342*77bd33e1Szrj 			(const unsigned char *) (P);			\
1343*77bd33e1Szrj 		_q[0]		= _p[0];				\
1344*77bd33e1Szrj 		_q[1]		= _p[1];				\
1345*77bd33e1Szrj 		_q[2]		= _p[2];				\
1346*77bd33e1Szrj 		_q[3]		= _p[3];				\
1347*77bd33e1Szrj 		(P)		= (P) + 4;				\
1348*77bd33e1Szrj 		(X)		= (T) _t;				\
1349*77bd33e1Szrj 	} while (0)
1350*77bd33e1Szrj #define	READ_SWORD(P,X)		_READ_WORD(P, X, /*Elf32_Sword*/ Elf64_Sword)
1351*77bd33e1Szrj #define	READ_WORD(P,X)		_READ_WORD(P, X, /*Elf32_Word*/ Elf64_Word)
1352*77bd33e1Szrj #define	_READ_WORD64(P,X,T)	do {					\
1353*77bd33e1Szrj 		uint64_t _t;						\
1354*77bd33e1Szrj 		unsigned char *const _q = (unsigned char *) &_t;	\
1355*77bd33e1Szrj 		const unsigned char *const _p =				\
1356*77bd33e1Szrj 			(const unsigned char *) (P);			\
1357*77bd33e1Szrj 		_q[0]		= _p[0];				\
1358*77bd33e1Szrj 		_q[1]		= _p[1];				\
1359*77bd33e1Szrj 		_q[2]		= _p[2];				\
1360*77bd33e1Szrj 		_q[3]		= _p[3];				\
1361*77bd33e1Szrj 		_q[4]		= _p[4];				\
1362*77bd33e1Szrj 		_q[5]		= _p[5];				\
1363*77bd33e1Szrj 		_q[6]		= _p[6];				\
1364*77bd33e1Szrj 		_q[7]		= _p[7];				\
1365*77bd33e1Szrj 		(P)		= (P) + 8;				\
1366*77bd33e1Szrj 		(X)		= (T) _t;				\
1367*77bd33e1Szrj 	} while (0)
1368*77bd33e1Szrj #define	READ_ADDR64(P,X)	_READ_WORD64(P, X, Elf64_Addr)
1369*77bd33e1Szrj #define	READ_LWORD(P,X)		_READ_WORD64(P, X, Elf64_Lword)
1370*77bd33e1Szrj #define	READ_OFF64(P,X)		_READ_WORD64(P, X, Elf64_Off)
1371*77bd33e1Szrj #define	READ_SXWORD(P,X)	_READ_WORD64(P, X, Elf64_Sxword)
1372*77bd33e1Szrj #define	READ_XWORD(P,X)		_READ_WORD64(P, X, Elf64_Xword)
1373*77bd33e1Szrj #define	READ_IDENT(P,X)		do {					\
1374*77bd33e1Szrj 		(void) memcpy((X), (P), sizeof((X)));			\
1375*77bd33e1Szrj 		(P)		= (P) + EI_NIDENT;			\
1376*77bd33e1Szrj 	} while (0)
1377*77bd33e1Szrj 
1378*77bd33e1Szrj #define	ROUNDUP2(V,N)	(V) = ((((V) + (N) - 1)) & ~((N) - 1))
1379*77bd33e1Szrj 
1380*77bd33e1Szrj static int
_libelf_cvt_ADDR64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1381*77bd33e1Szrj _libelf_cvt_ADDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1382*77bd33e1Szrj     size_t count, int byteswap)
1383*77bd33e1Szrj {
1384*77bd33e1Szrj 	Elf64_Addr t, *d = (Elf64_Addr *) (uintptr_t) dst;
1385*77bd33e1Szrj 	size_t c;
1386*77bd33e1Szrj 
1387*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Addr))
1388*77bd33e1Szrj 		return (0);
1389*77bd33e1Szrj 
1390*77bd33e1Szrj 	if (!byteswap) {
1391*77bd33e1Szrj 		(void) memcpy(dst, src, count * sizeof(*d));
1392*77bd33e1Szrj 		return (1);
1393*77bd33e1Szrj 	}
1394*77bd33e1Szrj 
1395*77bd33e1Szrj 	for (c = 0; c < count; c++) {
1396*77bd33e1Szrj 		READ_ADDR64(src,t);
1397*77bd33e1Szrj 		SWAP_ADDR64(t);
1398*77bd33e1Szrj 		*d++ = t;
1399*77bd33e1Szrj 	}
1400*77bd33e1Szrj 
1401*77bd33e1Szrj 	return (1);
1402*77bd33e1Szrj }
1403*77bd33e1Szrj 
1404*77bd33e1Szrj static int
_libelf_cvt_CAP64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1405*77bd33e1Szrj _libelf_cvt_CAP64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1406*77bd33e1Szrj     size_t count, int byteswap)
1407*77bd33e1Szrj {
1408*77bd33e1Szrj 	Elf64_Cap	t, *d;
1409*77bd33e1Szrj 	unsigned char	*s,*s0;
1410*77bd33e1Szrj 	size_t		fsz;
1411*77bd33e1Szrj 
1412*77bd33e1Szrj 	fsz = elf64_fsize(ELF_T_CAP, (size_t) 1, EV_CURRENT);
1413*77bd33e1Szrj 	d   = ((Elf64_Cap *) (uintptr_t) dst) + (count - 1);
1414*77bd33e1Szrj 	s0  = src + (count - 1) * fsz;
1415*77bd33e1Szrj 
1416*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Cap))
1417*77bd33e1Szrj 		return (0);
1418*77bd33e1Szrj 
1419*77bd33e1Szrj 	while (count--) {
1420*77bd33e1Szrj 		s = s0;
1421*77bd33e1Szrj 		/* Read an Elf64_Cap */
1422*77bd33e1Szrj 		READ_XWORD(s,t.c_tag);
1423*77bd33e1Szrj 		READ_XWORD(s,t.c_un.c_val);
1424*77bd33e1Szrj 		/**/
1425*77bd33e1Szrj 		if (byteswap) {
1426*77bd33e1Szrj 			/* Swap an Elf64_Cap */
1427*77bd33e1Szrj 			SWAP_XWORD(t.c_tag);
1428*77bd33e1Szrj 			SWAP_XWORD(t.c_un.c_val);
1429*77bd33e1Szrj 			/**/
1430*77bd33e1Szrj 		}
1431*77bd33e1Szrj 		*d-- = t; s0 -= fsz;
1432*77bd33e1Szrj 	}
1433*77bd33e1Szrj 
1434*77bd33e1Szrj 	return (1);
1435*77bd33e1Szrj }
1436*77bd33e1Szrj 
1437*77bd33e1Szrj static int
_libelf_cvt_DYN64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1438*77bd33e1Szrj _libelf_cvt_DYN64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1439*77bd33e1Szrj     size_t count, int byteswap)
1440*77bd33e1Szrj {
1441*77bd33e1Szrj 	Elf64_Dyn	t, *d;
1442*77bd33e1Szrj 	unsigned char	*s,*s0;
1443*77bd33e1Szrj 	size_t		fsz;
1444*77bd33e1Szrj 
1445*77bd33e1Szrj 	fsz = elf64_fsize(ELF_T_DYN, (size_t) 1, EV_CURRENT);
1446*77bd33e1Szrj 	d   = ((Elf64_Dyn *) (uintptr_t) dst) + (count - 1);
1447*77bd33e1Szrj 	s0  = src + (count - 1) * fsz;
1448*77bd33e1Szrj 
1449*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Dyn))
1450*77bd33e1Szrj 		return (0);
1451*77bd33e1Szrj 
1452*77bd33e1Szrj 	while (count--) {
1453*77bd33e1Szrj 		s = s0;
1454*77bd33e1Szrj 		/* Read an Elf64_Dyn */
1455*77bd33e1Szrj 		READ_SXWORD(s,t.d_tag);
1456*77bd33e1Szrj 		READ_XWORD(s,t.d_un.d_ptr);
1457*77bd33e1Szrj 		/**/
1458*77bd33e1Szrj 		if (byteswap) {
1459*77bd33e1Szrj 			/* Swap an Elf64_Dyn */
1460*77bd33e1Szrj 			SWAP_SXWORD(t.d_tag);
1461*77bd33e1Szrj 			SWAP_XWORD(t.d_un.d_ptr);
1462*77bd33e1Szrj 			/**/
1463*77bd33e1Szrj 		}
1464*77bd33e1Szrj 		*d-- = t; s0 -= fsz;
1465*77bd33e1Szrj 	}
1466*77bd33e1Szrj 
1467*77bd33e1Szrj 	return (1);
1468*77bd33e1Szrj }
1469*77bd33e1Szrj 
1470*77bd33e1Szrj static int
_libelf_cvt_EHDR64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1471*77bd33e1Szrj _libelf_cvt_EHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1472*77bd33e1Szrj     size_t count, int byteswap)
1473*77bd33e1Szrj {
1474*77bd33e1Szrj 	Elf64_Ehdr	t, *d;
1475*77bd33e1Szrj 	unsigned char	*s,*s0;
1476*77bd33e1Szrj 	size_t		fsz;
1477*77bd33e1Szrj 
1478*77bd33e1Szrj 	fsz = elf64_fsize(ELF_T_EHDR, (size_t) 1, EV_CURRENT);
1479*77bd33e1Szrj 	d   = ((Elf64_Ehdr *) (uintptr_t) dst) + (count - 1);
1480*77bd33e1Szrj 	s0  = src + (count - 1) * fsz;
1481*77bd33e1Szrj 
1482*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Ehdr))
1483*77bd33e1Szrj 		return (0);
1484*77bd33e1Szrj 
1485*77bd33e1Szrj 	while (count--) {
1486*77bd33e1Szrj 		s = s0;
1487*77bd33e1Szrj 		/* Read an Elf64_Ehdr */
1488*77bd33e1Szrj 		READ_IDENT(s,t.e_ident);
1489*77bd33e1Szrj 		READ_HALF(s,t.e_type);
1490*77bd33e1Szrj 		READ_HALF(s,t.e_machine);
1491*77bd33e1Szrj 		READ_WORD(s,t.e_version);
1492*77bd33e1Szrj 		READ_ADDR64(s,t.e_entry);
1493*77bd33e1Szrj 		READ_OFF64(s,t.e_phoff);
1494*77bd33e1Szrj 		READ_OFF64(s,t.e_shoff);
1495*77bd33e1Szrj 		READ_WORD(s,t.e_flags);
1496*77bd33e1Szrj 		READ_HALF(s,t.e_ehsize);
1497*77bd33e1Szrj 		READ_HALF(s,t.e_phentsize);
1498*77bd33e1Szrj 		READ_HALF(s,t.e_phnum);
1499*77bd33e1Szrj 		READ_HALF(s,t.e_shentsize);
1500*77bd33e1Szrj 		READ_HALF(s,t.e_shnum);
1501*77bd33e1Szrj 		READ_HALF(s,t.e_shstrndx);
1502*77bd33e1Szrj 		/**/
1503*77bd33e1Szrj 		if (byteswap) {
1504*77bd33e1Szrj 			/* Swap an Elf64_Ehdr */
1505*77bd33e1Szrj 			SWAP_IDENT(t.e_ident);
1506*77bd33e1Szrj 			SWAP_HALF(t.e_type);
1507*77bd33e1Szrj 			SWAP_HALF(t.e_machine);
1508*77bd33e1Szrj 			SWAP_WORD(t.e_version);
1509*77bd33e1Szrj 			SWAP_ADDR64(t.e_entry);
1510*77bd33e1Szrj 			SWAP_OFF64(t.e_phoff);
1511*77bd33e1Szrj 			SWAP_OFF64(t.e_shoff);
1512*77bd33e1Szrj 			SWAP_WORD(t.e_flags);
1513*77bd33e1Szrj 			SWAP_HALF(t.e_ehsize);
1514*77bd33e1Szrj 			SWAP_HALF(t.e_phentsize);
1515*77bd33e1Szrj 			SWAP_HALF(t.e_phnum);
1516*77bd33e1Szrj 			SWAP_HALF(t.e_shentsize);
1517*77bd33e1Szrj 			SWAP_HALF(t.e_shnum);
1518*77bd33e1Szrj 			SWAP_HALF(t.e_shstrndx);
1519*77bd33e1Szrj 			/**/
1520*77bd33e1Szrj 		}
1521*77bd33e1Szrj 		*d-- = t; s0 -= fsz;
1522*77bd33e1Szrj 	}
1523*77bd33e1Szrj 
1524*77bd33e1Szrj 	return (1);
1525*77bd33e1Szrj }
1526*77bd33e1Szrj 
1527*77bd33e1Szrj static int
_libelf_cvt_HALF_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1528*77bd33e1Szrj _libelf_cvt_HALF_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1529*77bd33e1Szrj     size_t count, int byteswap)
1530*77bd33e1Szrj {
1531*77bd33e1Szrj 	Elf64_Half t, *d = (Elf64_Half *) (uintptr_t) dst;
1532*77bd33e1Szrj 	size_t c;
1533*77bd33e1Szrj 
1534*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Half))
1535*77bd33e1Szrj 		return (0);
1536*77bd33e1Szrj 
1537*77bd33e1Szrj 	if (!byteswap) {
1538*77bd33e1Szrj 		(void) memcpy(dst, src, count * sizeof(*d));
1539*77bd33e1Szrj 		return (1);
1540*77bd33e1Szrj 	}
1541*77bd33e1Szrj 
1542*77bd33e1Szrj 	for (c = 0; c < count; c++) {
1543*77bd33e1Szrj 		READ_HALF(src,t);
1544*77bd33e1Szrj 		SWAP_HALF(t);
1545*77bd33e1Szrj 		*d++ = t;
1546*77bd33e1Szrj 	}
1547*77bd33e1Szrj 
1548*77bd33e1Szrj 	return (1);
1549*77bd33e1Szrj }
1550*77bd33e1Szrj 
1551*77bd33e1Szrj static int
_libelf_cvt_LWORD_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1552*77bd33e1Szrj _libelf_cvt_LWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1553*77bd33e1Szrj     size_t count, int byteswap)
1554*77bd33e1Szrj {
1555*77bd33e1Szrj 	Elf64_Lword t, *d = (Elf64_Lword *) (uintptr_t) dst;
1556*77bd33e1Szrj 	size_t c;
1557*77bd33e1Szrj 
1558*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Lword))
1559*77bd33e1Szrj 		return (0);
1560*77bd33e1Szrj 
1561*77bd33e1Szrj 	if (!byteswap) {
1562*77bd33e1Szrj 		(void) memcpy(dst, src, count * sizeof(*d));
1563*77bd33e1Szrj 		return (1);
1564*77bd33e1Szrj 	}
1565*77bd33e1Szrj 
1566*77bd33e1Szrj 	for (c = 0; c < count; c++) {
1567*77bd33e1Szrj 		READ_LWORD(src,t);
1568*77bd33e1Szrj 		SWAP_LWORD(t);
1569*77bd33e1Szrj 		*d++ = t;
1570*77bd33e1Szrj 	}
1571*77bd33e1Szrj 
1572*77bd33e1Szrj 	return (1);
1573*77bd33e1Szrj }
1574*77bd33e1Szrj 
1575*77bd33e1Szrj static int
_libelf_cvt_MOVE64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1576*77bd33e1Szrj _libelf_cvt_MOVE64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1577*77bd33e1Szrj     size_t count, int byteswap)
1578*77bd33e1Szrj {
1579*77bd33e1Szrj 	Elf64_Move	t, *d;
1580*77bd33e1Szrj 	unsigned char	*s,*s0;
1581*77bd33e1Szrj 	size_t		fsz;
1582*77bd33e1Szrj 
1583*77bd33e1Szrj 	fsz = elf64_fsize(ELF_T_MOVE, (size_t) 1, EV_CURRENT);
1584*77bd33e1Szrj 	d   = ((Elf64_Move *) (uintptr_t) dst) + (count - 1);
1585*77bd33e1Szrj 	s0  = src + (count - 1) * fsz;
1586*77bd33e1Szrj 
1587*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Move))
1588*77bd33e1Szrj 		return (0);
1589*77bd33e1Szrj 
1590*77bd33e1Szrj 	while (count--) {
1591*77bd33e1Szrj 		s = s0;
1592*77bd33e1Szrj 		/* Read an Elf64_Move */
1593*77bd33e1Szrj 		READ_LWORD(s,t.m_value);
1594*77bd33e1Szrj 		READ_XWORD(s,t.m_info);
1595*77bd33e1Szrj 		READ_XWORD(s,t.m_poffset);
1596*77bd33e1Szrj 		READ_HALF(s,t.m_repeat);
1597*77bd33e1Szrj 		READ_HALF(s,t.m_stride);
1598*77bd33e1Szrj 		/**/
1599*77bd33e1Szrj 		if (byteswap) {
1600*77bd33e1Szrj 			/* Swap an Elf64_Move */
1601*77bd33e1Szrj 			SWAP_LWORD(t.m_value);
1602*77bd33e1Szrj 			SWAP_XWORD(t.m_info);
1603*77bd33e1Szrj 			SWAP_XWORD(t.m_poffset);
1604*77bd33e1Szrj 			SWAP_HALF(t.m_repeat);
1605*77bd33e1Szrj 			SWAP_HALF(t.m_stride);
1606*77bd33e1Szrj 			/**/
1607*77bd33e1Szrj 		}
1608*77bd33e1Szrj 		*d-- = t; s0 -= fsz;
1609*77bd33e1Szrj 	}
1610*77bd33e1Szrj 
1611*77bd33e1Szrj 	return (1);
1612*77bd33e1Szrj }
1613*77bd33e1Szrj 
1614*77bd33e1Szrj static int
_libelf_cvt_OFF64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1615*77bd33e1Szrj _libelf_cvt_OFF64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1616*77bd33e1Szrj     size_t count, int byteswap)
1617*77bd33e1Szrj {
1618*77bd33e1Szrj 	Elf64_Off t, *d = (Elf64_Off *) (uintptr_t) dst;
1619*77bd33e1Szrj 	size_t c;
1620*77bd33e1Szrj 
1621*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Off))
1622*77bd33e1Szrj 		return (0);
1623*77bd33e1Szrj 
1624*77bd33e1Szrj 	if (!byteswap) {
1625*77bd33e1Szrj 		(void) memcpy(dst, src, count * sizeof(*d));
1626*77bd33e1Szrj 		return (1);
1627*77bd33e1Szrj 	}
1628*77bd33e1Szrj 
1629*77bd33e1Szrj 	for (c = 0; c < count; c++) {
1630*77bd33e1Szrj 		READ_OFF64(src,t);
1631*77bd33e1Szrj 		SWAP_OFF64(t);
1632*77bd33e1Szrj 		*d++ = t;
1633*77bd33e1Szrj 	}
1634*77bd33e1Szrj 
1635*77bd33e1Szrj 	return (1);
1636*77bd33e1Szrj }
1637*77bd33e1Szrj 
1638*77bd33e1Szrj static int
_libelf_cvt_PHDR64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1639*77bd33e1Szrj _libelf_cvt_PHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1640*77bd33e1Szrj     size_t count, int byteswap)
1641*77bd33e1Szrj {
1642*77bd33e1Szrj 	Elf64_Phdr	t, *d;
1643*77bd33e1Szrj 	unsigned char	*s,*s0;
1644*77bd33e1Szrj 	size_t		fsz;
1645*77bd33e1Szrj 
1646*77bd33e1Szrj 	fsz = elf64_fsize(ELF_T_PHDR, (size_t) 1, EV_CURRENT);
1647*77bd33e1Szrj 	d   = ((Elf64_Phdr *) (uintptr_t) dst) + (count - 1);
1648*77bd33e1Szrj 	s0  = src + (count - 1) * fsz;
1649*77bd33e1Szrj 
1650*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Phdr))
1651*77bd33e1Szrj 		return (0);
1652*77bd33e1Szrj 
1653*77bd33e1Szrj 	while (count--) {
1654*77bd33e1Szrj 		s = s0;
1655*77bd33e1Szrj 		/* Read an Elf64_Phdr */
1656*77bd33e1Szrj 		READ_WORD(s,t.p_type);
1657*77bd33e1Szrj 		READ_WORD(s,t.p_flags);
1658*77bd33e1Szrj 		READ_OFF64(s,t.p_offset);
1659*77bd33e1Szrj 		READ_ADDR64(s,t.p_vaddr);
1660*77bd33e1Szrj 		READ_ADDR64(s,t.p_paddr);
1661*77bd33e1Szrj 		READ_XWORD(s,t.p_filesz);
1662*77bd33e1Szrj 		READ_XWORD(s,t.p_memsz);
1663*77bd33e1Szrj 		READ_XWORD(s,t.p_align);
1664*77bd33e1Szrj 		/**/
1665*77bd33e1Szrj 		if (byteswap) {
1666*77bd33e1Szrj 			/* Swap an Elf64_Phdr */
1667*77bd33e1Szrj 			SWAP_WORD(t.p_type);
1668*77bd33e1Szrj 			SWAP_WORD(t.p_flags);
1669*77bd33e1Szrj 			SWAP_OFF64(t.p_offset);
1670*77bd33e1Szrj 			SWAP_ADDR64(t.p_vaddr);
1671*77bd33e1Szrj 			SWAP_ADDR64(t.p_paddr);
1672*77bd33e1Szrj 			SWAP_XWORD(t.p_filesz);
1673*77bd33e1Szrj 			SWAP_XWORD(t.p_memsz);
1674*77bd33e1Szrj 			SWAP_XWORD(t.p_align);
1675*77bd33e1Szrj 			/**/
1676*77bd33e1Szrj 		}
1677*77bd33e1Szrj 		*d-- = t; s0 -= fsz;
1678*77bd33e1Szrj 	}
1679*77bd33e1Szrj 
1680*77bd33e1Szrj 	return (1);
1681*77bd33e1Szrj }
1682*77bd33e1Szrj 
1683*77bd33e1Szrj static int
_libelf_cvt_REL64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1684*77bd33e1Szrj _libelf_cvt_REL64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1685*77bd33e1Szrj     size_t count, int byteswap)
1686*77bd33e1Szrj {
1687*77bd33e1Szrj 	Elf64_Rel	t, *d;
1688*77bd33e1Szrj 	unsigned char	*s,*s0;
1689*77bd33e1Szrj 	size_t		fsz;
1690*77bd33e1Szrj 
1691*77bd33e1Szrj 	fsz = elf64_fsize(ELF_T_REL, (size_t) 1, EV_CURRENT);
1692*77bd33e1Szrj 	d   = ((Elf64_Rel *) (uintptr_t) dst) + (count - 1);
1693*77bd33e1Szrj 	s0  = src + (count - 1) * fsz;
1694*77bd33e1Szrj 
1695*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Rel))
1696*77bd33e1Szrj 		return (0);
1697*77bd33e1Szrj 
1698*77bd33e1Szrj 	while (count--) {
1699*77bd33e1Szrj 		s = s0;
1700*77bd33e1Szrj 		/* Read an Elf64_Rel */
1701*77bd33e1Szrj 		READ_ADDR64(s,t.r_offset);
1702*77bd33e1Szrj 		READ_XWORD(s,t.r_info);
1703*77bd33e1Szrj 		/**/
1704*77bd33e1Szrj 		if (byteswap) {
1705*77bd33e1Szrj 			/* Swap an Elf64_Rel */
1706*77bd33e1Szrj 			SWAP_ADDR64(t.r_offset);
1707*77bd33e1Szrj 			SWAP_XWORD(t.r_info);
1708*77bd33e1Szrj 			/**/
1709*77bd33e1Szrj 		}
1710*77bd33e1Szrj 		*d-- = t; s0 -= fsz;
1711*77bd33e1Szrj 	}
1712*77bd33e1Szrj 
1713*77bd33e1Szrj 	return (1);
1714*77bd33e1Szrj }
1715*77bd33e1Szrj 
1716*77bd33e1Szrj static int
_libelf_cvt_RELA64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1717*77bd33e1Szrj _libelf_cvt_RELA64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1718*77bd33e1Szrj     size_t count, int byteswap)
1719*77bd33e1Szrj {
1720*77bd33e1Szrj 	Elf64_Rela	t, *d;
1721*77bd33e1Szrj 	unsigned char	*s,*s0;
1722*77bd33e1Szrj 	size_t		fsz;
1723*77bd33e1Szrj 
1724*77bd33e1Szrj 	fsz = elf64_fsize(ELF_T_RELA, (size_t) 1, EV_CURRENT);
1725*77bd33e1Szrj 	d   = ((Elf64_Rela *) (uintptr_t) dst) + (count - 1);
1726*77bd33e1Szrj 	s0  = src + (count - 1) * fsz;
1727*77bd33e1Szrj 
1728*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Rela))
1729*77bd33e1Szrj 		return (0);
1730*77bd33e1Szrj 
1731*77bd33e1Szrj 	while (count--) {
1732*77bd33e1Szrj 		s = s0;
1733*77bd33e1Szrj 		/* Read an Elf64_Rela */
1734*77bd33e1Szrj 		READ_ADDR64(s,t.r_offset);
1735*77bd33e1Szrj 		READ_XWORD(s,t.r_info);
1736*77bd33e1Szrj 		READ_SXWORD(s,t.r_addend);
1737*77bd33e1Szrj 		/**/
1738*77bd33e1Szrj 		if (byteswap) {
1739*77bd33e1Szrj 			/* Swap an Elf64_Rela */
1740*77bd33e1Szrj 			SWAP_ADDR64(t.r_offset);
1741*77bd33e1Szrj 			SWAP_XWORD(t.r_info);
1742*77bd33e1Szrj 			SWAP_SXWORD(t.r_addend);
1743*77bd33e1Szrj 			/**/
1744*77bd33e1Szrj 		}
1745*77bd33e1Szrj 		*d-- = t; s0 -= fsz;
1746*77bd33e1Szrj 	}
1747*77bd33e1Szrj 
1748*77bd33e1Szrj 	return (1);
1749*77bd33e1Szrj }
1750*77bd33e1Szrj 
1751*77bd33e1Szrj static int
_libelf_cvt_SHDR64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1752*77bd33e1Szrj _libelf_cvt_SHDR64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1753*77bd33e1Szrj     size_t count, int byteswap)
1754*77bd33e1Szrj {
1755*77bd33e1Szrj 	Elf64_Shdr	t, *d;
1756*77bd33e1Szrj 	unsigned char	*s,*s0;
1757*77bd33e1Szrj 	size_t		fsz;
1758*77bd33e1Szrj 
1759*77bd33e1Szrj 	fsz = elf64_fsize(ELF_T_SHDR, (size_t) 1, EV_CURRENT);
1760*77bd33e1Szrj 	d   = ((Elf64_Shdr *) (uintptr_t) dst) + (count - 1);
1761*77bd33e1Szrj 	s0  = src + (count - 1) * fsz;
1762*77bd33e1Szrj 
1763*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Shdr))
1764*77bd33e1Szrj 		return (0);
1765*77bd33e1Szrj 
1766*77bd33e1Szrj 	while (count--) {
1767*77bd33e1Szrj 		s = s0;
1768*77bd33e1Szrj 		/* Read an Elf64_Shdr */
1769*77bd33e1Szrj 		READ_WORD(s,t.sh_name);
1770*77bd33e1Szrj 		READ_WORD(s,t.sh_type);
1771*77bd33e1Szrj 		READ_XWORD(s,t.sh_flags);
1772*77bd33e1Szrj 		READ_ADDR64(s,t.sh_addr);
1773*77bd33e1Szrj 		READ_OFF64(s,t.sh_offset);
1774*77bd33e1Szrj 		READ_XWORD(s,t.sh_size);
1775*77bd33e1Szrj 		READ_WORD(s,t.sh_link);
1776*77bd33e1Szrj 		READ_WORD(s,t.sh_info);
1777*77bd33e1Szrj 		READ_XWORD(s,t.sh_addralign);
1778*77bd33e1Szrj 		READ_XWORD(s,t.sh_entsize);
1779*77bd33e1Szrj 		/**/
1780*77bd33e1Szrj 		if (byteswap) {
1781*77bd33e1Szrj 			/* Swap an Elf64_Shdr */
1782*77bd33e1Szrj 			SWAP_WORD(t.sh_name);
1783*77bd33e1Szrj 			SWAP_WORD(t.sh_type);
1784*77bd33e1Szrj 			SWAP_XWORD(t.sh_flags);
1785*77bd33e1Szrj 			SWAP_ADDR64(t.sh_addr);
1786*77bd33e1Szrj 			SWAP_OFF64(t.sh_offset);
1787*77bd33e1Szrj 			SWAP_XWORD(t.sh_size);
1788*77bd33e1Szrj 			SWAP_WORD(t.sh_link);
1789*77bd33e1Szrj 			SWAP_WORD(t.sh_info);
1790*77bd33e1Szrj 			SWAP_XWORD(t.sh_addralign);
1791*77bd33e1Szrj 			SWAP_XWORD(t.sh_entsize);
1792*77bd33e1Szrj 			/**/
1793*77bd33e1Szrj 		}
1794*77bd33e1Szrj 		*d-- = t; s0 -= fsz;
1795*77bd33e1Szrj 	}
1796*77bd33e1Szrj 
1797*77bd33e1Szrj 	return (1);
1798*77bd33e1Szrj }
1799*77bd33e1Szrj 
1800*77bd33e1Szrj static int
_libelf_cvt_SWORD_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1801*77bd33e1Szrj _libelf_cvt_SWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1802*77bd33e1Szrj     size_t count, int byteswap)
1803*77bd33e1Szrj {
1804*77bd33e1Szrj 	Elf64_Sword t, *d = (Elf64_Sword *) (uintptr_t) dst;
1805*77bd33e1Szrj 	size_t c;
1806*77bd33e1Szrj 
1807*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Sword))
1808*77bd33e1Szrj 		return (0);
1809*77bd33e1Szrj 
1810*77bd33e1Szrj 	if (!byteswap) {
1811*77bd33e1Szrj 		(void) memcpy(dst, src, count * sizeof(*d));
1812*77bd33e1Szrj 		return (1);
1813*77bd33e1Szrj 	}
1814*77bd33e1Szrj 
1815*77bd33e1Szrj 	for (c = 0; c < count; c++) {
1816*77bd33e1Szrj 		READ_SWORD(src,t);
1817*77bd33e1Szrj 		SWAP_SWORD(t);
1818*77bd33e1Szrj 		*d++ = t;
1819*77bd33e1Szrj 	}
1820*77bd33e1Szrj 
1821*77bd33e1Szrj 	return (1);
1822*77bd33e1Szrj }
1823*77bd33e1Szrj 
1824*77bd33e1Szrj static int
_libelf_cvt_SXWORD_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1825*77bd33e1Szrj _libelf_cvt_SXWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1826*77bd33e1Szrj     size_t count, int byteswap)
1827*77bd33e1Szrj {
1828*77bd33e1Szrj 	Elf64_Sxword t, *d = (Elf64_Sxword *) (uintptr_t) dst;
1829*77bd33e1Szrj 	size_t c;
1830*77bd33e1Szrj 
1831*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Sxword))
1832*77bd33e1Szrj 		return (0);
1833*77bd33e1Szrj 
1834*77bd33e1Szrj 	if (!byteswap) {
1835*77bd33e1Szrj 		(void) memcpy(dst, src, count * sizeof(*d));
1836*77bd33e1Szrj 		return (1);
1837*77bd33e1Szrj 	}
1838*77bd33e1Szrj 
1839*77bd33e1Szrj 	for (c = 0; c < count; c++) {
1840*77bd33e1Szrj 		READ_SXWORD(src,t);
1841*77bd33e1Szrj 		SWAP_SXWORD(t);
1842*77bd33e1Szrj 		*d++ = t;
1843*77bd33e1Szrj 	}
1844*77bd33e1Szrj 
1845*77bd33e1Szrj 	return (1);
1846*77bd33e1Szrj }
1847*77bd33e1Szrj 
1848*77bd33e1Szrj static int
_libelf_cvt_SYMINFO64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1849*77bd33e1Szrj _libelf_cvt_SYMINFO64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1850*77bd33e1Szrj     size_t count, int byteswap)
1851*77bd33e1Szrj {
1852*77bd33e1Szrj 	Elf64_Syminfo	t, *d;
1853*77bd33e1Szrj 	unsigned char	*s,*s0;
1854*77bd33e1Szrj 	size_t		fsz;
1855*77bd33e1Szrj 
1856*77bd33e1Szrj 	fsz = elf64_fsize(ELF_T_SYMINFO, (size_t) 1, EV_CURRENT);
1857*77bd33e1Szrj 	d   = ((Elf64_Syminfo *) (uintptr_t) dst) + (count - 1);
1858*77bd33e1Szrj 	s0  = src + (count - 1) * fsz;
1859*77bd33e1Szrj 
1860*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Syminfo))
1861*77bd33e1Szrj 		return (0);
1862*77bd33e1Szrj 
1863*77bd33e1Szrj 	while (count--) {
1864*77bd33e1Szrj 		s = s0;
1865*77bd33e1Szrj 		/* Read an Elf64_Syminfo */
1866*77bd33e1Szrj 		READ_HALF(s,t.si_boundto);
1867*77bd33e1Szrj 		READ_HALF(s,t.si_flags);
1868*77bd33e1Szrj 		/**/
1869*77bd33e1Szrj 		if (byteswap) {
1870*77bd33e1Szrj 			/* Swap an Elf64_Syminfo */
1871*77bd33e1Szrj 			SWAP_HALF(t.si_boundto);
1872*77bd33e1Szrj 			SWAP_HALF(t.si_flags);
1873*77bd33e1Szrj 			/**/
1874*77bd33e1Szrj 		}
1875*77bd33e1Szrj 		*d-- = t; s0 -= fsz;
1876*77bd33e1Szrj 	}
1877*77bd33e1Szrj 
1878*77bd33e1Szrj 	return (1);
1879*77bd33e1Szrj }
1880*77bd33e1Szrj 
1881*77bd33e1Szrj static int
_libelf_cvt_SYM64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1882*77bd33e1Szrj _libelf_cvt_SYM64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1883*77bd33e1Szrj     size_t count, int byteswap)
1884*77bd33e1Szrj {
1885*77bd33e1Szrj 	Elf64_Sym	t, *d;
1886*77bd33e1Szrj 	unsigned char	*s,*s0;
1887*77bd33e1Szrj 	size_t		fsz;
1888*77bd33e1Szrj 
1889*77bd33e1Szrj 	fsz = elf64_fsize(ELF_T_SYM, (size_t) 1, EV_CURRENT);
1890*77bd33e1Szrj 	d   = ((Elf64_Sym *) (uintptr_t) dst) + (count - 1);
1891*77bd33e1Szrj 	s0  = src + (count - 1) * fsz;
1892*77bd33e1Szrj 
1893*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Sym))
1894*77bd33e1Szrj 		return (0);
1895*77bd33e1Szrj 
1896*77bd33e1Szrj 	while (count--) {
1897*77bd33e1Szrj 		s = s0;
1898*77bd33e1Szrj 		/* Read an Elf64_Sym */
1899*77bd33e1Szrj 		READ_WORD(s,t.st_name);
1900*77bd33e1Szrj 		READ_BYTE(s,t.st_info);
1901*77bd33e1Szrj 		READ_BYTE(s,t.st_other);
1902*77bd33e1Szrj 		READ_HALF(s,t.st_shndx);
1903*77bd33e1Szrj 		READ_ADDR64(s,t.st_value);
1904*77bd33e1Szrj 		READ_XWORD(s,t.st_size);
1905*77bd33e1Szrj 		/**/
1906*77bd33e1Szrj 		if (byteswap) {
1907*77bd33e1Szrj 			/* Swap an Elf64_Sym */
1908*77bd33e1Szrj 			SWAP_WORD(t.st_name);
1909*77bd33e1Szrj 			SWAP_BYTE(t.st_info);
1910*77bd33e1Szrj 			SWAP_BYTE(t.st_other);
1911*77bd33e1Szrj 			SWAP_HALF(t.st_shndx);
1912*77bd33e1Szrj 			SWAP_ADDR64(t.st_value);
1913*77bd33e1Szrj 			SWAP_XWORD(t.st_size);
1914*77bd33e1Szrj 			/**/
1915*77bd33e1Szrj 		}
1916*77bd33e1Szrj 		*d-- = t; s0 -= fsz;
1917*77bd33e1Szrj 	}
1918*77bd33e1Szrj 
1919*77bd33e1Szrj 	return (1);
1920*77bd33e1Szrj }
1921*77bd33e1Szrj 
1922*77bd33e1Szrj static int
_libelf_cvt_WORD_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1923*77bd33e1Szrj _libelf_cvt_WORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1924*77bd33e1Szrj     size_t count, int byteswap)
1925*77bd33e1Szrj {
1926*77bd33e1Szrj 	Elf64_Word t, *d = (Elf64_Word *) (uintptr_t) dst;
1927*77bd33e1Szrj 	size_t c;
1928*77bd33e1Szrj 
1929*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Word))
1930*77bd33e1Szrj 		return (0);
1931*77bd33e1Szrj 
1932*77bd33e1Szrj 	if (!byteswap) {
1933*77bd33e1Szrj 		(void) memcpy(dst, src, count * sizeof(*d));
1934*77bd33e1Szrj 		return (1);
1935*77bd33e1Szrj 	}
1936*77bd33e1Szrj 
1937*77bd33e1Szrj 	for (c = 0; c < count; c++) {
1938*77bd33e1Szrj 		READ_WORD(src,t);
1939*77bd33e1Szrj 		SWAP_WORD(t);
1940*77bd33e1Szrj 		*d++ = t;
1941*77bd33e1Szrj 	}
1942*77bd33e1Szrj 
1943*77bd33e1Szrj 	return (1);
1944*77bd33e1Szrj }
1945*77bd33e1Szrj 
1946*77bd33e1Szrj static int
_libelf_cvt_XWORD_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1947*77bd33e1Szrj _libelf_cvt_XWORD_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1948*77bd33e1Szrj     size_t count, int byteswap)
1949*77bd33e1Szrj {
1950*77bd33e1Szrj 	Elf64_Xword t, *d = (Elf64_Xword *) (uintptr_t) dst;
1951*77bd33e1Szrj 	size_t c;
1952*77bd33e1Szrj 
1953*77bd33e1Szrj 	if (dsz < count * sizeof(Elf64_Xword))
1954*77bd33e1Szrj 		return (0);
1955*77bd33e1Szrj 
1956*77bd33e1Szrj 	if (!byteswap) {
1957*77bd33e1Szrj 		(void) memcpy(dst, src, count * sizeof(*d));
1958*77bd33e1Szrj 		return (1);
1959*77bd33e1Szrj 	}
1960*77bd33e1Szrj 
1961*77bd33e1Szrj 	for (c = 0; c < count; c++) {
1962*77bd33e1Szrj 		READ_XWORD(src,t);
1963*77bd33e1Szrj 		SWAP_XWORD(t);
1964*77bd33e1Szrj 		*d++ = t;
1965*77bd33e1Szrj 	}
1966*77bd33e1Szrj 
1967*77bd33e1Szrj 	return (1);
1968*77bd33e1Szrj }
1969*77bd33e1Szrj 
1970*77bd33e1Szrj static int
_libelf_cvt_VDEF64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)1971*77bd33e1Szrj _libelf_cvt_VDEF64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
1972*77bd33e1Szrj     size_t count, int byteswap)
1973*77bd33e1Szrj {
1974*77bd33e1Szrj 	Elf64_Verdef	t, *dp;
1975*77bd33e1Szrj 	Elf64_Verdaux	a, *ap;
1976*77bd33e1Szrj 	const size_t	verfsz = 20;
1977*77bd33e1Szrj 	const size_t	auxfsz = 8;
1978*77bd33e1Szrj 	const size_t	vermsz = sizeof(Elf64_Verdef);
1979*77bd33e1Szrj 	const size_t	auxmsz = sizeof(Elf64_Verdaux);
1980*77bd33e1Szrj 	unsigned char * const dstend = dst + dsz;
1981*77bd33e1Szrj 	unsigned char * const srcend = src + count;
1982*77bd33e1Szrj 	unsigned char	*dstaux, *s, *srcaux, *stmp;
1983*77bd33e1Szrj 	Elf64_Word	aux, anext, cnt, vnext;
1984*77bd33e1Szrj 
1985*77bd33e1Szrj 	for (stmp = src, vnext = ~0U;
1986*77bd33e1Szrj 	     vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
1987*77bd33e1Szrj 	     stmp += vnext, dst += vnext) {
1988*77bd33e1Szrj 
1989*77bd33e1Szrj 		/* Read in a VDEF structure. */
1990*77bd33e1Szrj 		s = stmp;
1991*77bd33e1Szrj 		/* Read an Elf64_Verdef */
1992*77bd33e1Szrj 		READ_HALF(s,t.vd_version);
1993*77bd33e1Szrj 		READ_HALF(s,t.vd_flags);
1994*77bd33e1Szrj 		READ_HALF(s,t.vd_ndx);
1995*77bd33e1Szrj 		READ_HALF(s,t.vd_cnt);
1996*77bd33e1Szrj 		READ_WORD(s,t.vd_hash);
1997*77bd33e1Szrj 		READ_WORD(s,t.vd_aux);
1998*77bd33e1Szrj 		READ_WORD(s,t.vd_next);
1999*77bd33e1Szrj 		/**/
2000*77bd33e1Szrj 		if (byteswap) {
2001*77bd33e1Szrj 			/* Swap an Elf64_Verdef */
2002*77bd33e1Szrj 			SWAP_HALF(t.vd_version);
2003*77bd33e1Szrj 			SWAP_HALF(t.vd_flags);
2004*77bd33e1Szrj 			SWAP_HALF(t.vd_ndx);
2005*77bd33e1Szrj 			SWAP_HALF(t.vd_cnt);
2006*77bd33e1Szrj 			SWAP_WORD(t.vd_hash);
2007*77bd33e1Szrj 			SWAP_WORD(t.vd_aux);
2008*77bd33e1Szrj 			SWAP_WORD(t.vd_next);
2009*77bd33e1Szrj 			/**/
2010*77bd33e1Szrj 		}
2011*77bd33e1Szrj 
2012*77bd33e1Szrj 		dp = (Elf64_Verdef *) (uintptr_t) dst;
2013*77bd33e1Szrj 		*dp = t;
2014*77bd33e1Szrj 
2015*77bd33e1Szrj 		aux = t.vd_aux;
2016*77bd33e1Szrj 		cnt = t.vd_cnt;
2017*77bd33e1Szrj 		vnext = t.vd_next;
2018*77bd33e1Szrj 
2019*77bd33e1Szrj 		if (aux < vermsz)
2020*77bd33e1Szrj 			return (0);
2021*77bd33e1Szrj 
2022*77bd33e1Szrj 		/* Process AUX entries. */
2023*77bd33e1Szrj 		for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux;
2024*77bd33e1Szrj 		     cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
2025*77bd33e1Szrj 			srcaux + auxfsz <= srcend;
2026*77bd33e1Szrj 		     dstaux += anext, srcaux += anext, cnt--) {
2027*77bd33e1Szrj 
2028*77bd33e1Szrj 			s = srcaux;
2029*77bd33e1Szrj 			/* Read an Elf64_Verdaux */
2030*77bd33e1Szrj 		READ_WORD(s,a.vda_name);
2031*77bd33e1Szrj 		READ_WORD(s,a.vda_next);
2032*77bd33e1Szrj 		/**/
2033*77bd33e1Szrj 
2034*77bd33e1Szrj 			if (byteswap) {
2035*77bd33e1Szrj 				/* Swap an Elf64_Verdaux */
2036*77bd33e1Szrj 			SWAP_WORD(a.vda_name);
2037*77bd33e1Szrj 			SWAP_WORD(a.vda_next);
2038*77bd33e1Szrj 			/**/
2039*77bd33e1Szrj 			}
2040*77bd33e1Szrj 
2041*77bd33e1Szrj 			anext = a.vda_next;
2042*77bd33e1Szrj 
2043*77bd33e1Szrj 			ap = ((Elf64_Verdaux *) (uintptr_t) dstaux);
2044*77bd33e1Szrj 			*ap = a;
2045*77bd33e1Szrj 		}
2046*77bd33e1Szrj 
2047*77bd33e1Szrj 		if (anext || cnt)
2048*77bd33e1Szrj 			return (0);
2049*77bd33e1Szrj 	}
2050*77bd33e1Szrj 
2051*77bd33e1Szrj 	if (vnext)
2052*77bd33e1Szrj 		return (0);
2053*77bd33e1Szrj 
2054*77bd33e1Szrj 	return (1);
2055*77bd33e1Szrj }
2056*77bd33e1Szrj 
2057*77bd33e1Szrj static int
_libelf_cvt_VNEED64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)2058*77bd33e1Szrj _libelf_cvt_VNEED64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
2059*77bd33e1Szrj     size_t count, int byteswap)
2060*77bd33e1Szrj {
2061*77bd33e1Szrj 	Elf64_Verneed	t, *dp;
2062*77bd33e1Szrj 	Elf64_Vernaux	a, *ap;
2063*77bd33e1Szrj 	const size_t	verfsz = 16;
2064*77bd33e1Szrj 	const size_t	auxfsz = 16;
2065*77bd33e1Szrj 	const size_t	vermsz = sizeof(Elf64_Verneed);
2066*77bd33e1Szrj 	const size_t	auxmsz = sizeof(Elf64_Vernaux);
2067*77bd33e1Szrj 	unsigned char * const dstend = dst + dsz;
2068*77bd33e1Szrj 	unsigned char * const srcend = src + count;
2069*77bd33e1Szrj 	unsigned char	*dstaux, *s, *srcaux, *stmp;
2070*77bd33e1Szrj 	Elf64_Word	aux, anext, cnt, vnext;
2071*77bd33e1Szrj 
2072*77bd33e1Szrj 	for (stmp = src, vnext = ~0U;
2073*77bd33e1Szrj 	     vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
2074*77bd33e1Szrj 	     stmp += vnext, dst += vnext) {
2075*77bd33e1Szrj 
2076*77bd33e1Szrj 		/* Read in a VNEED structure. */
2077*77bd33e1Szrj 		s = stmp;
2078*77bd33e1Szrj 		/* Read an Elf64_Verneed */
2079*77bd33e1Szrj 		READ_HALF(s,t.vn_version);
2080*77bd33e1Szrj 		READ_HALF(s,t.vn_cnt);
2081*77bd33e1Szrj 		READ_WORD(s,t.vn_file);
2082*77bd33e1Szrj 		READ_WORD(s,t.vn_aux);
2083*77bd33e1Szrj 		READ_WORD(s,t.vn_next);
2084*77bd33e1Szrj 		/**/
2085*77bd33e1Szrj 		if (byteswap) {
2086*77bd33e1Szrj 			/* Swap an Elf64_Verneed */
2087*77bd33e1Szrj 			SWAP_HALF(t.vn_version);
2088*77bd33e1Szrj 			SWAP_HALF(t.vn_cnt);
2089*77bd33e1Szrj 			SWAP_WORD(t.vn_file);
2090*77bd33e1Szrj 			SWAP_WORD(t.vn_aux);
2091*77bd33e1Szrj 			SWAP_WORD(t.vn_next);
2092*77bd33e1Szrj 			/**/
2093*77bd33e1Szrj 		}
2094*77bd33e1Szrj 
2095*77bd33e1Szrj 		dp = (Elf64_Verneed *) (uintptr_t) dst;
2096*77bd33e1Szrj 		*dp = t;
2097*77bd33e1Szrj 
2098*77bd33e1Szrj 		aux = t.vn_aux;
2099*77bd33e1Szrj 		cnt = t.vn_cnt;
2100*77bd33e1Szrj 		vnext = t.vn_next;
2101*77bd33e1Szrj 
2102*77bd33e1Szrj 		if (aux < vermsz)
2103*77bd33e1Szrj 			return (0);
2104*77bd33e1Szrj 
2105*77bd33e1Szrj 		/* Process AUX entries. */
2106*77bd33e1Szrj 		for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux;
2107*77bd33e1Szrj 		     cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
2108*77bd33e1Szrj 			srcaux + auxfsz <= srcend;
2109*77bd33e1Szrj 		     dstaux += anext, srcaux += anext, cnt--) {
2110*77bd33e1Szrj 
2111*77bd33e1Szrj 			s = srcaux;
2112*77bd33e1Szrj 			/* Read an Elf64_Vernaux */
2113*77bd33e1Szrj 		READ_WORD(s,a.vna_hash);
2114*77bd33e1Szrj 		READ_HALF(s,a.vna_flags);
2115*77bd33e1Szrj 		READ_HALF(s,a.vna_other);
2116*77bd33e1Szrj 		READ_WORD(s,a.vna_name);
2117*77bd33e1Szrj 		READ_WORD(s,a.vna_next);
2118*77bd33e1Szrj 		/**/
2119*77bd33e1Szrj 
2120*77bd33e1Szrj 			if (byteswap) {
2121*77bd33e1Szrj 				/* Swap an Elf64_Vernaux */
2122*77bd33e1Szrj 			SWAP_WORD(a.vna_hash);
2123*77bd33e1Szrj 			SWAP_HALF(a.vna_flags);
2124*77bd33e1Szrj 			SWAP_HALF(a.vna_other);
2125*77bd33e1Szrj 			SWAP_WORD(a.vna_name);
2126*77bd33e1Szrj 			SWAP_WORD(a.vna_next);
2127*77bd33e1Szrj 			/**/
2128*77bd33e1Szrj 			}
2129*77bd33e1Szrj 
2130*77bd33e1Szrj 			anext = a.vna_next;
2131*77bd33e1Szrj 
2132*77bd33e1Szrj 			ap = ((Elf64_Vernaux *) (uintptr_t) dstaux);
2133*77bd33e1Szrj 			*ap = a;
2134*77bd33e1Szrj 		}
2135*77bd33e1Szrj 
2136*77bd33e1Szrj 		if (anext || cnt)
2137*77bd33e1Szrj 			return (0);
2138*77bd33e1Szrj 	}
2139*77bd33e1Szrj 
2140*77bd33e1Szrj 	if (vnext)
2141*77bd33e1Szrj 		return (0);
2142*77bd33e1Szrj 
2143*77bd33e1Szrj 	return (1);
2144*77bd33e1Szrj }
2145*77bd33e1Szrj 
2146*77bd33e1Szrj static int
_libelf_cvt_BYTE_tox(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)2147*77bd33e1Szrj _libelf_cvt_BYTE_tox(unsigned char *dst, size_t dsz, unsigned char *src,
2148*77bd33e1Szrj     size_t count, int byteswap)
2149*77bd33e1Szrj {
2150*77bd33e1Szrj 	(void) byteswap;
2151*77bd33e1Szrj 	if (dsz < count)
2152*77bd33e1Szrj 		return (0);
2153*77bd33e1Szrj 	if (dst != src)
2154*77bd33e1Szrj 		(void) memcpy(dst, src, count);
2155*77bd33e1Szrj 	return (1);
2156*77bd33e1Szrj }
2157*77bd33e1Szrj 
2158*77bd33e1Szrj static int
_libelf_cvt_GNUHASH64_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t srcsz,int byteswap)2159*77bd33e1Szrj _libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
2160*77bd33e1Szrj     size_t srcsz, int byteswap)
2161*77bd33e1Szrj {
2162*77bd33e1Szrj 	size_t sz;
2163*77bd33e1Szrj 	uint64_t t64, *bloom64;
2164*77bd33e1Szrj 	Elf_GNU_Hash_Header *gh;
2165*77bd33e1Szrj 	uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
2166*77bd33e1Szrj 	uint32_t *buckets, *chains;
2167*77bd33e1Szrj 
2168*77bd33e1Szrj 	sz = 4 * sizeof(uint32_t);	/* File header is 4 words long. */
2169*77bd33e1Szrj 	if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
2170*77bd33e1Szrj 		return (0);
2171*77bd33e1Szrj 
2172*77bd33e1Szrj 	/* Read in the section header and byteswap if needed. */
2173*77bd33e1Szrj 	READ_WORD(src, nbuckets);
2174*77bd33e1Szrj 	READ_WORD(src, symndx);
2175*77bd33e1Szrj 	READ_WORD(src, maskwords);
2176*77bd33e1Szrj 	READ_WORD(src, shift2);
2177*77bd33e1Szrj 
2178*77bd33e1Szrj 	srcsz -= sz;
2179*77bd33e1Szrj 
2180*77bd33e1Szrj 	if (byteswap) {
2181*77bd33e1Szrj 		SWAP_WORD(nbuckets);
2182*77bd33e1Szrj 		SWAP_WORD(symndx);
2183*77bd33e1Szrj 		SWAP_WORD(maskwords);
2184*77bd33e1Szrj 		SWAP_WORD(shift2);
2185*77bd33e1Szrj 	}
2186*77bd33e1Szrj 
2187*77bd33e1Szrj 	/* Check source buffer and destination buffer sizes. */
2188*77bd33e1Szrj 	sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
2189*77bd33e1Szrj 	if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
2190*77bd33e1Szrj 		return (0);
2191*77bd33e1Szrj 
2192*77bd33e1Szrj 	gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
2193*77bd33e1Szrj 	gh->gh_nbuckets  = nbuckets;
2194*77bd33e1Szrj 	gh->gh_symndx    = symndx;
2195*77bd33e1Szrj 	gh->gh_maskwords = maskwords;
2196*77bd33e1Szrj 	gh->gh_shift2    = shift2;
2197*77bd33e1Szrj 
2198*77bd33e1Szrj 	dsz -= sizeof(Elf_GNU_Hash_Header);
2199*77bd33e1Szrj 	dst += sizeof(Elf_GNU_Hash_Header);
2200*77bd33e1Szrj 
2201*77bd33e1Szrj 	bloom64 = (uint64_t *) (uintptr_t) dst;
2202*77bd33e1Szrj 
2203*77bd33e1Szrj 	/* Copy bloom filter data. */
2204*77bd33e1Szrj 	for (n = 0; n < maskwords; n++) {
2205*77bd33e1Szrj 		READ_XWORD(src, t64);
2206*77bd33e1Szrj 		if (byteswap)
2207*77bd33e1Szrj 			SWAP_XWORD(t64);
2208*77bd33e1Szrj 		bloom64[n] = t64;
2209*77bd33e1Szrj 	}
2210*77bd33e1Szrj 
2211*77bd33e1Szrj 	/* The hash buckets follows the bloom filter. */
2212*77bd33e1Szrj 	dst += maskwords * sizeof(uint64_t);
2213*77bd33e1Szrj 	buckets = (uint32_t *) (uintptr_t) dst;
2214*77bd33e1Szrj 
2215*77bd33e1Szrj 	for (n = 0; n < nbuckets; n++) {
2216*77bd33e1Szrj 		READ_WORD(src, t32);
2217*77bd33e1Szrj 		if (byteswap)
2218*77bd33e1Szrj 			SWAP_WORD(t32);
2219*77bd33e1Szrj 		buckets[n] = t32;
2220*77bd33e1Szrj 	}
2221*77bd33e1Szrj 
2222*77bd33e1Szrj 	dst += nbuckets * sizeof(uint32_t);
2223*77bd33e1Szrj 
2224*77bd33e1Szrj 	/* The hash chain follows the hash buckets. */
2225*77bd33e1Szrj 	dsz -= sz;
2226*77bd33e1Szrj 	srcsz -= sz;
2227*77bd33e1Szrj 
2228*77bd33e1Szrj 	if (dsz < srcsz)	/* Destination lacks space. */
2229*77bd33e1Szrj 		return (0);
2230*77bd33e1Szrj 
2231*77bd33e1Szrj 	nchains = srcsz / sizeof(uint32_t);
2232*77bd33e1Szrj 	chains = (uint32_t *) (uintptr_t) dst;
2233*77bd33e1Szrj 
2234*77bd33e1Szrj 	for (n = 0; n < nchains; n++) {
2235*77bd33e1Szrj 		READ_WORD(src, t32);
2236*77bd33e1Szrj 		if (byteswap)
2237*77bd33e1Szrj 			SWAP_WORD(t32);
2238*77bd33e1Szrj 		*chains++ = t32;
2239*77bd33e1Szrj 	}
2240*77bd33e1Szrj 
2241*77bd33e1Szrj 	return (1);
2242*77bd33e1Szrj }
2243*77bd33e1Szrj 
2244*77bd33e1Szrj static int
_libelf_cvt_NOTE_tom(unsigned char * dst,size_t dsz,unsigned char * src,size_t count,int byteswap)2245*77bd33e1Szrj _libelf_cvt_NOTE_tom(unsigned char *dst, size_t dsz, unsigned char *src,
2246*77bd33e1Szrj     size_t count, int byteswap)
2247*77bd33e1Szrj {
2248*77bd33e1Szrj 	uint32_t namesz, descsz, type;
2249*77bd33e1Szrj 	Elf_Note *en;
2250*77bd33e1Szrj 	size_t sz, hdrsz;
2251*77bd33e1Szrj 
2252*77bd33e1Szrj 	if (dsz < count)	/* Destination buffer is too small. */
2253*77bd33e1Szrj 		return (0);
2254*77bd33e1Szrj 
2255*77bd33e1Szrj 	hdrsz = 3 * sizeof(uint32_t);
2256*77bd33e1Szrj 	if (count < hdrsz)		/* Source too small. */
2257*77bd33e1Szrj 		return (0);
2258*77bd33e1Szrj 
2259*77bd33e1Szrj 	if (!byteswap) {
2260*77bd33e1Szrj 		(void) memcpy(dst, src, count);
2261*77bd33e1Szrj 		return (1);
2262*77bd33e1Szrj 	}
2263*77bd33e1Szrj 
2264*77bd33e1Szrj 	/* Process all notes in the section. */
2265*77bd33e1Szrj 	while (count > hdrsz) {
2266*77bd33e1Szrj 		/* Read the note header. */
2267*77bd33e1Szrj 		READ_WORD(src, namesz);
2268*77bd33e1Szrj 		READ_WORD(src, descsz);
2269*77bd33e1Szrj 		READ_WORD(src, type);
2270*77bd33e1Szrj 
2271*77bd33e1Szrj 		/* Translate. */
2272*77bd33e1Szrj 		SWAP_WORD(namesz);
2273*77bd33e1Szrj 		SWAP_WORD(descsz);
2274*77bd33e1Szrj 		SWAP_WORD(type);
2275*77bd33e1Szrj 
2276*77bd33e1Szrj 		/* Copy out the translated note header. */
2277*77bd33e1Szrj 		en = (Elf_Note *) (uintptr_t) dst;
2278*77bd33e1Szrj 		en->n_namesz = namesz;
2279*77bd33e1Szrj 		en->n_descsz = descsz;
2280*77bd33e1Szrj 		en->n_type = type;
2281*77bd33e1Szrj 
2282*77bd33e1Szrj 		dsz -= sizeof(Elf_Note);
2283*77bd33e1Szrj 		dst += sizeof(Elf_Note);
2284*77bd33e1Szrj 		count -= hdrsz;
2285*77bd33e1Szrj 
2286*77bd33e1Szrj 		ROUNDUP2(namesz, 4U);
2287*77bd33e1Szrj 		ROUNDUP2(descsz, 4U);
2288*77bd33e1Szrj 
2289*77bd33e1Szrj 		sz = namesz + descsz;
2290*77bd33e1Szrj 
2291*77bd33e1Szrj 		if (count < sz || dsz < sz)	/* Buffers are too small. */
2292*77bd33e1Szrj 			return (0);
2293*77bd33e1Szrj 
2294*77bd33e1Szrj 		(void) memcpy(dst, src, sz);
2295*77bd33e1Szrj 
2296*77bd33e1Szrj 		src += sz;
2297*77bd33e1Szrj 		dst += sz;
2298*77bd33e1Szrj 
2299*77bd33e1Szrj 		count -= sz;
2300*77bd33e1Szrj 		dsz -= sz;
2301*77bd33e1Szrj 	}
2302*77bd33e1Szrj 
2303*77bd33e1Szrj 	return (1);
2304*77bd33e1Szrj }
2305*77bd33e1Szrj 
2306*77bd33e1Szrj struct converters {
2307*77bd33e1Szrj 	int	(*tof32)(unsigned char *dst, size_t dsz, unsigned char *src,
2308*77bd33e1Szrj 		    size_t cnt, int byteswap);
2309*77bd33e1Szrj 	int	(*tom32)(unsigned char *dst, size_t dsz, unsigned char *src,
2310*77bd33e1Szrj 		    size_t cnt, int byteswap);
2311*77bd33e1Szrj 	int	(*tof64)(unsigned char *dst, size_t dsz, unsigned char *src,
2312*77bd33e1Szrj 		    size_t cnt, int byteswap);
2313*77bd33e1Szrj 	int	(*tom64)(unsigned char *dst, size_t dsz, unsigned char *src,
2314*77bd33e1Szrj 		    size_t cnt, int byteswap);
2315*77bd33e1Szrj };
2316*77bd33e1Szrj 
2317*77bd33e1Szrj static struct converters cvt[ELF_T_NUM] = {
2318*77bd33e1Szrj 	/*[*/
2319*77bd33e1Szrj 	[ELF_T_ADDR] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2320*77bd33e1Szrj 		.tom64 = _libelf_cvt_ADDR64_tom },
2321*77bd33e1Szrj 	[ELF_T_CAP] =     { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2322*77bd33e1Szrj 		.tom64 = _libelf_cvt_CAP64_tom },
2323*77bd33e1Szrj 	[ELF_T_DYN] =     { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2324*77bd33e1Szrj 		.tom64 = _libelf_cvt_DYN64_tom },
2325*77bd33e1Szrj 	[ELF_T_EHDR] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2326*77bd33e1Szrj 		.tom64 = _libelf_cvt_EHDR64_tom },
2327*77bd33e1Szrj 	[ELF_T_GNUHASH] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2328*77bd33e1Szrj 		.tom64 = _libelf_cvt_GNUHASH64_tom },
2329*77bd33e1Szrj 	[ELF_T_HALF] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2330*77bd33e1Szrj 		.tom64 = _libelf_cvt_HALF_tom },
2331*77bd33e1Szrj 	[ELF_T_LWORD] =   { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2332*77bd33e1Szrj 		.tom64 = _libelf_cvt_LWORD_tom },
2333*77bd33e1Szrj 	[ELF_T_MOVE] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2334*77bd33e1Szrj 		.tom64 = _libelf_cvt_MOVE64_tom },
2335*77bd33e1Szrj 	[ELF_T_OFF] =     { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2336*77bd33e1Szrj 		.tom64 = _libelf_cvt_OFF64_tom },
2337*77bd33e1Szrj 	[ELF_T_PHDR] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2338*77bd33e1Szrj 		.tom64 = _libelf_cvt_PHDR64_tom },
2339*77bd33e1Szrj 	[ELF_T_REL] =     { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2340*77bd33e1Szrj 		.tom64 = _libelf_cvt_REL64_tom },
2341*77bd33e1Szrj 	[ELF_T_RELA] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2342*77bd33e1Szrj 		.tom64 = _libelf_cvt_RELA64_tom },
2343*77bd33e1Szrj 	[ELF_T_SHDR] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2344*77bd33e1Szrj 		.tom64 = _libelf_cvt_SHDR64_tom },
2345*77bd33e1Szrj 	[ELF_T_SWORD] =   { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2346*77bd33e1Szrj 		.tom64 = _libelf_cvt_SWORD_tom },
2347*77bd33e1Szrj 	[ELF_T_SXWORD] =  { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2348*77bd33e1Szrj 		.tom64 = _libelf_cvt_SXWORD_tom },
2349*77bd33e1Szrj 	[ELF_T_SYMINFO] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2350*77bd33e1Szrj 		.tom64 = _libelf_cvt_SYMINFO64_tom },
2351*77bd33e1Szrj 	[ELF_T_SYM] =     { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2352*77bd33e1Szrj 		.tom64 = _libelf_cvt_SYM64_tom },
2353*77bd33e1Szrj 	[ELF_T_VDEF] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2354*77bd33e1Szrj 		.tom64 = _libelf_cvt_VDEF64_tom },
2355*77bd33e1Szrj 	[ELF_T_VNEED] =   { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2356*77bd33e1Szrj 		.tom64 = _libelf_cvt_VNEED64_tom },
2357*77bd33e1Szrj 	[ELF_T_WORD] =    { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2358*77bd33e1Szrj 		.tom64 = _libelf_cvt_WORD_tom },
2359*77bd33e1Szrj 	[ELF_T_XWORD] =   { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2360*77bd33e1Szrj 		.tom64 = _libelf_cvt_XWORD_tom },
2361*77bd33e1Szrj 	/*]*/
2362*77bd33e1Szrj 	/*
2363*77bd33e1Szrj 	 * Types that need hand-coded converters follow.
2364*77bd33e1Szrj 	 */
2365*77bd33e1Szrj 	[ELF_T_BYTE] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2366*77bd33e1Szrj 		.tom64 = _libelf_cvt_BYTE_tox },
2367*77bd33e1Szrj 	[ELF_T_NOTE] = { .tof32 = NULL, .tom32 = NULL, .tof64 = NULL,
2368*77bd33e1Szrj 		.tom64 = _libelf_cvt_NOTE_tom }
2369*77bd33e1Szrj };
2370*77bd33e1Szrj 
_libelf_get_translator(Elf_Type t,int direction,int elfclass)2371*77bd33e1Szrj static int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
2372*77bd33e1Szrj  (unsigned char *_dst, size_t dsz, unsigned char *_src, size_t _cnt,
2373*77bd33e1Szrj   int _byteswap)
2374*77bd33e1Szrj {
2375*77bd33e1Szrj 	assert(/* elfclass == ELFCLASS32 || */ elfclass == ELFCLASS64);
2376*77bd33e1Szrj 	assert(/* direction == ELF_TOFILE || */ direction == ELF_TOMEMORY);
2377*77bd33e1Szrj 
2378*77bd33e1Szrj 	if (t >= ELF_T_NUM ||
2379*77bd33e1Szrj 	    (/* elfclass != ELFCLASS32 && */ elfclass != ELFCLASS64) ||
2380*77bd33e1Szrj 	    (/* direction != ELF_TOFILE && */ direction != ELF_TOMEMORY))
2381*77bd33e1Szrj 		return (NULL);
2382*77bd33e1Szrj 
2383*77bd33e1Szrj #if 1
2384*77bd33e1Szrj 	return cvt[t].tom64;
2385*77bd33e1Szrj #else
2386*77bd33e1Szrj 	return ((elfclass == ELFCLASS32) ?
2387*77bd33e1Szrj 	    (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
2388*77bd33e1Szrj 	    (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));
2389*77bd33e1Szrj #endif
2390*77bd33e1Szrj }
2391*77bd33e1Szrj 
2392*77bd33e1Szrj /* libelf_ehdr.h */
2393*77bd33e1Szrj /*
2394*77bd33e1Szrj  * Retrieve counts for sections, phdrs and the section string table index
2395*77bd33e1Szrj  * from section header #0 of the ELF object.
2396*77bd33e1Szrj  */
2397*77bd33e1Szrj static int
_libelf_load_extended(Elf * e,int ec,uint64_t shoff,uint16_t phnum,uint16_t strndx)2398*77bd33e1Szrj _libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
2399*77bd33e1Szrj     uint16_t strndx)
2400*77bd33e1Szrj {
2401*77bd33e1Szrj 	Elf_Scn *scn;
2402*77bd33e1Szrj 	size_t fsz;
2403*77bd33e1Szrj 	int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
2404*77bd33e1Szrj 	    size_t _c, int _swap);
2405*77bd33e1Szrj 	uint32_t shtype;
2406*77bd33e1Szrj 
2407*77bd33e1Szrj 	assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
2408*77bd33e1Szrj 
2409*77bd33e1Szrj 	fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1);
2410*77bd33e1Szrj 	assert(fsz > 0);
2411*77bd33e1Szrj 
2412*77bd33e1Szrj 	if (e->e_rawsize < shoff + fsz) { /* raw file too small */
2413*77bd33e1Szrj 		LIBELF_SET_ERROR(HEADER, 0);
2414*77bd33e1Szrj 		return (0);
2415*77bd33e1Szrj 	}
2416*77bd33e1Szrj 
2417*77bd33e1Szrj 	if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL)
2418*77bd33e1Szrj 		return (0);
2419*77bd33e1Szrj 
2420*77bd33e1Szrj 	xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
2421*77bd33e1Szrj 	(*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
2422*77bd33e1Szrj 	    (unsigned char *) e->e_rawfile + shoff, (size_t) 1,
2423*77bd33e1Szrj 	    e->e_byteorder != LIBELF_PRIVATE(byteorder));
2424*77bd33e1Szrj 
2425*77bd33e1Szrj #define	GET_SHDR_MEMBER(M) (/* (ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M :*/ \
2426*77bd33e1Szrj 		scn->s_shdr.s_shdr64.M)
2427*77bd33e1Szrj 
2428*77bd33e1Szrj 	if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) {
2429*77bd33e1Szrj 		LIBELF_SET_ERROR(SECTION, 0);
2430*77bd33e1Szrj 		return (0);
2431*77bd33e1Szrj 	}
2432*77bd33e1Szrj 
2433*77bd33e1Szrj 	e->e_u.e_elf.e_nscn = (size_t) GET_SHDR_MEMBER(sh_size);
2434*77bd33e1Szrj 	e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum :
2435*77bd33e1Szrj 	    GET_SHDR_MEMBER(sh_info);
2436*77bd33e1Szrj 	e->e_u.e_elf.e_strndx = (strndx != SHN_XINDEX) ? strndx :
2437*77bd33e1Szrj 	    GET_SHDR_MEMBER(sh_link);
2438*77bd33e1Szrj #undef	GET_SHDR_MEMBER
2439*77bd33e1Szrj 
2440*77bd33e1Szrj 	return (1);
2441*77bd33e1Szrj }
2442*77bd33e1Szrj 
2443*77bd33e1Szrj #define	EHDR_INIT(E,SZ)	 do {						\
2444*77bd33e1Szrj 		Elf##SZ##_Ehdr *eh = (E);				\
2445*77bd33e1Szrj 		eh->e_ident[EI_MAG0] = ELFMAG0;				\
2446*77bd33e1Szrj 		eh->e_ident[EI_MAG1] = ELFMAG1;				\
2447*77bd33e1Szrj 		eh->e_ident[EI_MAG2] = ELFMAG2;				\
2448*77bd33e1Szrj 		eh->e_ident[EI_MAG3] = ELFMAG3;				\
2449*77bd33e1Szrj 		eh->e_ident[EI_CLASS] = ELFCLASS##SZ;			\
2450*77bd33e1Szrj 		eh->e_ident[EI_DATA]  = ELFDATANONE;			\
2451*77bd33e1Szrj 		eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version) & 0xFFU; \
2452*77bd33e1Szrj 		eh->e_machine = EM_NONE;				\
2453*77bd33e1Szrj 		eh->e_type    = ELF_K_NONE;				\
2454*77bd33e1Szrj 		eh->e_version = LIBELF_PRIVATE(version);		\
2455*77bd33e1Szrj 	} while (0)
2456*77bd33e1Szrj 
2457*77bd33e1Szrj static void *
_libelf_ehdr(Elf * e,int ec,int allocate)2458*77bd33e1Szrj _libelf_ehdr(Elf *e, int ec, int allocate)
2459*77bd33e1Szrj {
2460*77bd33e1Szrj 	void *ehdr;
2461*77bd33e1Szrj 	size_t fsz, msz;
2462*77bd33e1Szrj 	uint16_t phnum, shnum, strndx;
2463*77bd33e1Szrj 	uint64_t shoff;
2464*77bd33e1Szrj 	int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
2465*77bd33e1Szrj 	    size_t _c, int _swap);
2466*77bd33e1Szrj 
2467*77bd33e1Szrj 	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
2468*77bd33e1Szrj 
2469*77bd33e1Szrj 	if (e == NULL || e->e_kind != ELF_K_ELF) {
2470*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
2471*77bd33e1Szrj 		return (NULL);
2472*77bd33e1Szrj 	}
2473*77bd33e1Szrj 
2474*77bd33e1Szrj 	if (e->e_class != ELFCLASSNONE && e->e_class != ec) {
2475*77bd33e1Szrj 		LIBELF_SET_ERROR(CLASS, 0);
2476*77bd33e1Szrj 		return (NULL);
2477*77bd33e1Szrj 	}
2478*77bd33e1Szrj 
2479*77bd33e1Szrj 	if (e->e_version != EV_CURRENT) {
2480*77bd33e1Szrj 		LIBELF_SET_ERROR(VERSION, 0);
2481*77bd33e1Szrj 		return (NULL);
2482*77bd33e1Szrj 	}
2483*77bd33e1Szrj 
2484*77bd33e1Szrj 	if (e->e_class == ELFCLASSNONE)
2485*77bd33e1Szrj 		e->e_class = ec;
2486*77bd33e1Szrj 
2487*77bd33e1Szrj #if 0
2488*77bd33e1Szrj 	if (ec == ELFCLASS32)
2489*77bd33e1Szrj 		ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr32;
2490*77bd33e1Szrj 	else
2491*77bd33e1Szrj #endif
2492*77bd33e1Szrj 		ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr64;
2493*77bd33e1Szrj 
2494*77bd33e1Szrj 	if (ehdr != NULL)	/* already have a translated ehdr */
2495*77bd33e1Szrj 		return (ehdr);
2496*77bd33e1Szrj 
2497*77bd33e1Szrj 	fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
2498*77bd33e1Szrj 	assert(fsz > 0);
2499*77bd33e1Szrj 
2500*77bd33e1Szrj 	if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) {
2501*77bd33e1Szrj 		LIBELF_SET_ERROR(HEADER, 0);
2502*77bd33e1Szrj 		return (NULL);
2503*77bd33e1Szrj 	}
2504*77bd33e1Szrj 
2505*77bd33e1Szrj 	msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT);
2506*77bd33e1Szrj 
2507*77bd33e1Szrj 	assert(msz > 0);
2508*77bd33e1Szrj 
2509*77bd33e1Szrj 	if ((ehdr = calloc((size_t) 1, msz)) == NULL) {
2510*77bd33e1Szrj 		LIBELF_SET_ERROR(RESOURCE, 0);
2511*77bd33e1Szrj 		return (NULL);
2512*77bd33e1Szrj 	}
2513*77bd33e1Szrj 
2514*77bd33e1Szrj #if 0
2515*77bd33e1Szrj 	if (ec == ELFCLASS32) {
2516*77bd33e1Szrj 		e->e_u.e_elf.e_ehdr.e_ehdr32 = ehdr;
2517*77bd33e1Szrj 		EHDR_INIT(ehdr,32);
2518*77bd33e1Szrj 	} else
2519*77bd33e1Szrj #endif
2520*77bd33e1Szrj 	{
2521*77bd33e1Szrj 		e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr;
2522*77bd33e1Szrj 		EHDR_INIT(ehdr,64);
2523*77bd33e1Szrj 	}
2524*77bd33e1Szrj 
2525*77bd33e1Szrj 	if (allocate)
2526*77bd33e1Szrj 		e->e_flags |= ELF_F_DIRTY;
2527*77bd33e1Szrj 
2528*77bd33e1Szrj 	if (e->e_cmd == ELF_C_WRITE)
2529*77bd33e1Szrj 		return (ehdr);
2530*77bd33e1Szrj 
2531*77bd33e1Szrj 	xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec);
2532*77bd33e1Szrj 	(*xlator)((unsigned char*) ehdr, msz, e->e_rawfile, (size_t) 1,
2533*77bd33e1Szrj 	    e->e_byteorder != LIBELF_PRIVATE(byteorder));
2534*77bd33e1Szrj 
2535*77bd33e1Szrj 	/*
2536*77bd33e1Szrj 	 * If extended numbering is being used, read the correct
2537*77bd33e1Szrj 	 * number of sections and program header entries.
2538*77bd33e1Szrj 	 */
2539*77bd33e1Szrj #if 0
2540*77bd33e1Szrj 	if (ec == ELFCLASS32) {
2541*77bd33e1Szrj 		phnum = ((Elf32_Ehdr *) ehdr)->e_phnum;
2542*77bd33e1Szrj 		shnum = ((Elf32_Ehdr *) ehdr)->e_shnum;
2543*77bd33e1Szrj 		shoff = ((Elf32_Ehdr *) ehdr)->e_shoff;
2544*77bd33e1Szrj 		strndx = ((Elf32_Ehdr *) ehdr)->e_shstrndx;
2545*77bd33e1Szrj 	} else
2546*77bd33e1Szrj #endif
2547*77bd33e1Szrj 	{
2548*77bd33e1Szrj 		phnum = ((Elf64_Ehdr *) ehdr)->e_phnum;
2549*77bd33e1Szrj 		shnum = ((Elf64_Ehdr *) ehdr)->e_shnum;
2550*77bd33e1Szrj 		shoff = ((Elf64_Ehdr *) ehdr)->e_shoff;
2551*77bd33e1Szrj 		strndx = ((Elf64_Ehdr *) ehdr)->e_shstrndx;
2552*77bd33e1Szrj 	}
2553*77bd33e1Szrj 
2554*77bd33e1Szrj 	if (shnum >= SHN_LORESERVE ||
2555*77bd33e1Szrj 	    (shoff == 0LL && (shnum != 0 || phnum == PN_XNUM ||
2556*77bd33e1Szrj 		strndx == SHN_XINDEX))) {
2557*77bd33e1Szrj 		LIBELF_SET_ERROR(HEADER, 0);
2558*77bd33e1Szrj 		return (NULL);
2559*77bd33e1Szrj 	}
2560*77bd33e1Szrj 
2561*77bd33e1Szrj 	if (shnum != 0 || shoff == 0LL) { /* not using extended numbering */
2562*77bd33e1Szrj 		e->e_u.e_elf.e_nphdr = phnum;
2563*77bd33e1Szrj 		e->e_u.e_elf.e_nscn = shnum;
2564*77bd33e1Szrj 		e->e_u.e_elf.e_strndx = strndx;
2565*77bd33e1Szrj 	} else if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0)
2566*77bd33e1Szrj 		return (NULL);
2567*77bd33e1Szrj 
2568*77bd33e1Szrj 	return (ehdr);
2569*77bd33e1Szrj }
2570*77bd33e1Szrj 
2571*77bd33e1Szrj /* libelf_shdr.c */
2572*77bd33e1Szrj static void *
_libelf_getshdr(Elf_Scn * s,int ec)2573*77bd33e1Szrj _libelf_getshdr(Elf_Scn *s, int ec)
2574*77bd33e1Szrj {
2575*77bd33e1Szrj 	Elf *e;
2576*77bd33e1Szrj 
2577*77bd33e1Szrj 	if (s == NULL || (e = s->s_elf) == NULL ||
2578*77bd33e1Szrj 	    e->e_kind != ELF_K_ELF) {
2579*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
2580*77bd33e1Szrj 		return (NULL);
2581*77bd33e1Szrj 	}
2582*77bd33e1Szrj 
2583*77bd33e1Szrj 	if (ec == ELFCLASSNONE)
2584*77bd33e1Szrj 		ec = e->e_class;
2585*77bd33e1Szrj 
2586*77bd33e1Szrj 	if (ec != e->e_class) {
2587*77bd33e1Szrj 		LIBELF_SET_ERROR(CLASS, 0);
2588*77bd33e1Szrj 		return (NULL);
2589*77bd33e1Szrj 	}
2590*77bd33e1Szrj 
2591*77bd33e1Szrj 	return ((void *) &s->s_shdr);
2592*77bd33e1Szrj }
2593*77bd33e1Szrj 
2594*77bd33e1Szrj /* elf_scn.c */
2595*77bd33e1Szrj static int
_libelf_load_section_headers(Elf * e,void * ehdr)2596*77bd33e1Szrj _libelf_load_section_headers(Elf *e, void *ehdr)
2597*77bd33e1Szrj {
2598*77bd33e1Szrj 	Elf_Scn *scn;
2599*77bd33e1Szrj 	uint64_t shoff;
2600*77bd33e1Szrj #if 0
2601*77bd33e1Szrj 	Elf32_Ehdr *eh32;
2602*77bd33e1Szrj #endif
2603*77bd33e1Szrj 	Elf64_Ehdr *eh64;
2604*77bd33e1Szrj 	int ec, swapbytes;
2605*77bd33e1Szrj 	unsigned char *src;
2606*77bd33e1Szrj 	size_t fsz, i, shnum;
2607*77bd33e1Szrj 	int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
2608*77bd33e1Szrj 	    size_t _c, int _swap);
2609*77bd33e1Szrj 
2610*77bd33e1Szrj 	assert(e != NULL);
2611*77bd33e1Szrj 	assert(ehdr != NULL);
2612*77bd33e1Szrj 	assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0);
2613*77bd33e1Szrj 
2614*77bd33e1Szrj #define	CHECK_EHDR(E,EH)	do {				\
2615*77bd33e1Szrj 		if (shoff > e->e_rawsize ||			\
2616*77bd33e1Szrj 		    fsz != (EH)->e_shentsize ||			\
2617*77bd33e1Szrj 		    shnum > SIZE_MAX / fsz ||			\
2618*77bd33e1Szrj 		    fsz * shnum > e->e_rawsize - shoff) {	\
2619*77bd33e1Szrj 			LIBELF_SET_ERROR(HEADER, 0);		\
2620*77bd33e1Szrj 			return (0);				\
2621*77bd33e1Szrj 		}						\
2622*77bd33e1Szrj 	} while (0)
2623*77bd33e1Szrj 
2624*77bd33e1Szrj 	ec = e->e_class;
2625*77bd33e1Szrj 	fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
2626*77bd33e1Szrj 	assert(fsz > 0);
2627*77bd33e1Szrj 
2628*77bd33e1Szrj 	shnum = e->e_u.e_elf.e_nscn;
2629*77bd33e1Szrj 
2630*77bd33e1Szrj #if 0
2631*77bd33e1Szrj 	if (ec == ELFCLASS32) {
2632*77bd33e1Szrj 		eh32 = (Elf32_Ehdr *) ehdr;
2633*77bd33e1Szrj 		shoff = (uint64_t) eh32->e_shoff;
2634*77bd33e1Szrj 		CHECK_EHDR(e, eh32);
2635*77bd33e1Szrj 	} else
2636*77bd33e1Szrj #endif
2637*77bd33e1Szrj 	{
2638*77bd33e1Szrj 		eh64 = (Elf64_Ehdr *) ehdr;
2639*77bd33e1Szrj 		shoff = eh64->e_shoff;
2640*77bd33e1Szrj 		CHECK_EHDR(e, eh64);
2641*77bd33e1Szrj 	}
2642*77bd33e1Szrj 
2643*77bd33e1Szrj 	xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
2644*77bd33e1Szrj 
2645*77bd33e1Szrj 	swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder);
2646*77bd33e1Szrj 	src = e->e_rawfile + shoff;
2647*77bd33e1Szrj 
2648*77bd33e1Szrj 	/*
2649*77bd33e1Szrj 	 * If the file is using extended numbering then section #0
2650*77bd33e1Szrj 	 * would have already been read in.
2651*77bd33e1Szrj 	 */
2652*77bd33e1Szrj 
2653*77bd33e1Szrj 	i = 0;
2654*77bd33e1Szrj 	if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
2655*77bd33e1Szrj 		assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) ==
2656*77bd33e1Szrj 		    STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next));
2657*77bd33e1Szrj 
2658*77bd33e1Szrj 		i = 1;
2659*77bd33e1Szrj 		src += fsz;
2660*77bd33e1Szrj 	}
2661*77bd33e1Szrj 
2662*77bd33e1Szrj 	for (; i < shnum; i++, src += fsz) {
2663*77bd33e1Szrj 		if ((scn = _libelf_allocate_scn(e, i)) == NULL)
2664*77bd33e1Szrj 			return (0);
2665*77bd33e1Szrj 
2666*77bd33e1Szrj 		(*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
2667*77bd33e1Szrj 		    src, (size_t) 1, swapbytes);
2668*77bd33e1Szrj 
2669*77bd33e1Szrj #if 0
2670*77bd33e1Szrj 		if (ec == ELFCLASS32) {
2671*77bd33e1Szrj 			scn->s_offset = scn->s_rawoff =
2672*77bd33e1Szrj 			    scn->s_shdr.s_shdr32.sh_offset;
2673*77bd33e1Szrj 			scn->s_size = scn->s_shdr.s_shdr32.sh_size;
2674*77bd33e1Szrj 		} else
2675*77bd33e1Szrj #endif
2676*77bd33e1Szrj 		{
2677*77bd33e1Szrj 			scn->s_offset = scn->s_rawoff =
2678*77bd33e1Szrj 			    scn->s_shdr.s_shdr64.sh_offset;
2679*77bd33e1Szrj 			scn->s_size = scn->s_shdr.s_shdr64.sh_size;
2680*77bd33e1Szrj 		}
2681*77bd33e1Szrj 	}
2682*77bd33e1Szrj 
2683*77bd33e1Szrj 	e->e_flags |= LIBELF_F_SHDRS_LOADED;
2684*77bd33e1Szrj 
2685*77bd33e1Szrj 	return (1);
2686*77bd33e1Szrj }
2687*77bd33e1Szrj 
2688*77bd33e1Szrj static Elf_Scn *
elf_getscn(Elf * e,size_t index)2689*77bd33e1Szrj elf_getscn(Elf *e, size_t index)
2690*77bd33e1Szrj {
2691*77bd33e1Szrj 	int ec;
2692*77bd33e1Szrj 	void *ehdr;
2693*77bd33e1Szrj 	Elf_Scn *s;
2694*77bd33e1Szrj 
2695*77bd33e1Szrj 	if (e == NULL || e->e_kind != ELF_K_ELF ||
2696*77bd33e1Szrj 	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
2697*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
2698*77bd33e1Szrj 		return (NULL);
2699*77bd33e1Szrj 	}
2700*77bd33e1Szrj 
2701*77bd33e1Szrj 	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
2702*77bd33e1Szrj 		return (NULL);
2703*77bd33e1Szrj 
2704*77bd33e1Szrj 	if (e->e_cmd != ELF_C_WRITE &&
2705*77bd33e1Szrj 	    (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 &&
2706*77bd33e1Szrj 	    _libelf_load_section_headers(e, ehdr) == 0)
2707*77bd33e1Szrj 		return (NULL);
2708*77bd33e1Szrj 
2709*77bd33e1Szrj 	STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next)
2710*77bd33e1Szrj 		if (s->s_ndx == index)
2711*77bd33e1Szrj 			return (s);
2712*77bd33e1Szrj 
2713*77bd33e1Szrj 	LIBELF_SET_ERROR(ARGUMENT, 0);
2714*77bd33e1Szrj 	return (NULL);
2715*77bd33e1Szrj }
2716*77bd33e1Szrj 
2717*77bd33e1Szrj /* libelf_memory.c */
2718*77bd33e1Szrj static Elf *
_libelf_memory(unsigned char * image,size_t sz,int reporterror)2719*77bd33e1Szrj _libelf_memory(unsigned char *image, size_t sz, int reporterror)
2720*77bd33e1Szrj {
2721*77bd33e1Szrj 	Elf *e;
2722*77bd33e1Szrj 	int e_class;
2723*77bd33e1Szrj 	enum Elf_Error error;
2724*77bd33e1Szrj 	unsigned int e_byteorder, e_version;
2725*77bd33e1Szrj 
2726*77bd33e1Szrj 	assert(image != NULL);
2727*77bd33e1Szrj 	assert(sz > 0);
2728*77bd33e1Szrj 
2729*77bd33e1Szrj 	if ((e = _libelf_allocate_elf()) == NULL)
2730*77bd33e1Szrj 		return (NULL);
2731*77bd33e1Szrj 
2732*77bd33e1Szrj 	e->e_cmd = ELF_C_READ;
2733*77bd33e1Szrj 	e->e_rawfile = image;
2734*77bd33e1Szrj 	e->e_rawsize = sz;
2735*77bd33e1Szrj 
2736*77bd33e1Szrj #undef	LIBELF_IS_ELF
2737*77bd33e1Szrj #define	LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 &&		\
2738*77bd33e1Szrj 	(P)[EI_MAG1] == ELFMAG1 && (P)[EI_MAG2] == ELFMAG2 &&	\
2739*77bd33e1Szrj 	(P)[EI_MAG3] == ELFMAG3)
2740*77bd33e1Szrj 
2741*77bd33e1Szrj 	if (sz > EI_NIDENT && LIBELF_IS_ELF(image)) {
2742*77bd33e1Szrj 		e_byteorder = image[EI_DATA];
2743*77bd33e1Szrj 		e_class     = image[EI_CLASS];
2744*77bd33e1Szrj 		e_version   = image[EI_VERSION];
2745*77bd33e1Szrj 
2746*77bd33e1Szrj 		error = ELF_E_NONE;
2747*77bd33e1Szrj 
2748*77bd33e1Szrj 		if (e_version > EV_CURRENT)
2749*77bd33e1Szrj 			error = ELF_E_VERSION;
2750*77bd33e1Szrj 		else if ((e_byteorder != ELFDATA2LSB && e_byteorder !=
2751*77bd33e1Szrj 		    ELFDATA2MSB) || (e_class != ELFCLASS32 && e_class !=
2752*77bd33e1Szrj 		    ELFCLASS64))
2753*77bd33e1Szrj 			error = ELF_E_HEADER;
2754*77bd33e1Szrj 
2755*77bd33e1Szrj 		if (error != ELF_E_NONE) {
2756*77bd33e1Szrj 			if (reporterror) {
2757*77bd33e1Szrj 				LIBELF_PRIVATE(error) = LIBELF_ERROR(error, 0);
2758*77bd33e1Szrj 				(void) _libelf_release_elf(e);
2759*77bd33e1Szrj 				return (NULL);
2760*77bd33e1Szrj 			}
2761*77bd33e1Szrj 		} else {
2762*77bd33e1Szrj 			_libelf_init_elf(e, ELF_K_ELF);
2763*77bd33e1Szrj 
2764*77bd33e1Szrj 			e->e_byteorder = e_byteorder;
2765*77bd33e1Szrj 			e->e_class = e_class;
2766*77bd33e1Szrj 			e->e_version = e_version;
2767*77bd33e1Szrj 		}
2768*77bd33e1Szrj 	}
2769*77bd33e1Szrj #if 0
2770*77bd33e1Szrj 	else if (sz >= SARMAG &&
2771*77bd33e1Szrj 	    strncmp((const char *) image, ARMAG, (size_t) SARMAG) == 0)
2772*77bd33e1Szrj 		return (_libelf_ar_open(e, reporterror));
2773*77bd33e1Szrj #endif
2774*77bd33e1Szrj 
2775*77bd33e1Szrj 	return (e);
2776*77bd33e1Szrj }
2777*77bd33e1Szrj 
2778*77bd33e1Szrj /* libelf_open.c */
2779*77bd33e1Szrj #define	_LIBELF_INITSIZE	(64*1024)
2780*77bd33e1Szrj 
2781*77bd33e1Szrj static void *
_libelf_read_special_file(int fd,size_t * fsz)2782*77bd33e1Szrj _libelf_read_special_file(int fd, size_t *fsz)
2783*77bd33e1Szrj {
2784*77bd33e1Szrj 	ssize_t readsz;
2785*77bd33e1Szrj 	size_t bufsz, datasz;
2786*77bd33e1Szrj 	unsigned char *buf, *t;
2787*77bd33e1Szrj 
2788*77bd33e1Szrj 	datasz = 0;
2789*77bd33e1Szrj 	readsz = 0;
2790*77bd33e1Szrj 	bufsz = _LIBELF_INITSIZE;
2791*77bd33e1Szrj 	if ((buf = malloc(bufsz)) == NULL)
2792*77bd33e1Szrj 		goto resourceerror;
2793*77bd33e1Szrj 
2794*77bd33e1Szrj 	/*
2795*77bd33e1Szrj 	 * Read data from the file descriptor till we reach EOF, or
2796*77bd33e1Szrj 	 * till an error is encountered.
2797*77bd33e1Szrj 	 */
2798*77bd33e1Szrj 	do {
2799*77bd33e1Szrj 		/* Check if we need to expand the data buffer. */
2800*77bd33e1Szrj 		if (datasz == bufsz) {
2801*77bd33e1Szrj 			bufsz *= 2;
2802*77bd33e1Szrj 			if ((t = realloc(buf, bufsz)) == NULL)
2803*77bd33e1Szrj 				goto resourceerror;
2804*77bd33e1Szrj 			buf = t;
2805*77bd33e1Szrj 		}
2806*77bd33e1Szrj 
2807*77bd33e1Szrj 		do {
2808*77bd33e1Szrj 			assert(bufsz - datasz > 0);
2809*77bd33e1Szrj 			t = buf + datasz;
2810*77bd33e1Szrj 			if ((readsz = read(fd, t, bufsz - datasz)) <= 0)
2811*77bd33e1Szrj 				break;
2812*77bd33e1Szrj 			datasz += (size_t) readsz;
2813*77bd33e1Szrj 		} while (datasz < bufsz);
2814*77bd33e1Szrj 
2815*77bd33e1Szrj 	} while (readsz > 0);
2816*77bd33e1Szrj 
2817*77bd33e1Szrj 	if (readsz < 0) {
2818*77bd33e1Szrj 		LIBELF_SET_ERROR(IO, errno);
2819*77bd33e1Szrj 		goto error;
2820*77bd33e1Szrj 	}
2821*77bd33e1Szrj 
2822*77bd33e1Szrj 	assert(readsz == 0);
2823*77bd33e1Szrj 
2824*77bd33e1Szrj 	/*
2825*77bd33e1Szrj 	 * Free up extra buffer space.
2826*77bd33e1Szrj 	 */
2827*77bd33e1Szrj 	if (bufsz > datasz) {
2828*77bd33e1Szrj 		if (datasz > 0) {
2829*77bd33e1Szrj 			if ((t = realloc(buf, datasz)) == NULL)
2830*77bd33e1Szrj 				goto resourceerror;
2831*77bd33e1Szrj 			buf = t;
2832*77bd33e1Szrj 		} else {	/* Zero bytes read. */
2833*77bd33e1Szrj 			LIBELF_SET_ERROR(ARGUMENT, 0);
2834*77bd33e1Szrj 			free(buf);
2835*77bd33e1Szrj 			buf = NULL;
2836*77bd33e1Szrj 		}
2837*77bd33e1Szrj 	}
2838*77bd33e1Szrj 
2839*77bd33e1Szrj 	*fsz = datasz;
2840*77bd33e1Szrj 	return (buf);
2841*77bd33e1Szrj 
2842*77bd33e1Szrj resourceerror:
2843*77bd33e1Szrj 	LIBELF_SET_ERROR(RESOURCE, 0);
2844*77bd33e1Szrj error:
2845*77bd33e1Szrj 	if (buf != NULL)
2846*77bd33e1Szrj 		free(buf);
2847*77bd33e1Szrj 	return (NULL);
2848*77bd33e1Szrj }
2849*77bd33e1Szrj 
2850*77bd33e1Szrj static Elf *
_libelf_open_object(int fd,Elf_Cmd c,int reporterror)2851*77bd33e1Szrj _libelf_open_object(int fd, Elf_Cmd c, int reporterror)
2852*77bd33e1Szrj {
2853*77bd33e1Szrj 	Elf *e;
2854*77bd33e1Szrj 	void *m;
2855*77bd33e1Szrj 	mode_t mode;
2856*77bd33e1Szrj 	size_t fsize;
2857*77bd33e1Szrj 	struct stat sb;
2858*77bd33e1Szrj 	unsigned int flags;
2859*77bd33e1Szrj 
2860*77bd33e1Szrj 	assert(c == ELF_C_READ || c == ELF_C_RDWR || c == ELF_C_WRITE);
2861*77bd33e1Szrj 
2862*77bd33e1Szrj 	if (fstat(fd, &sb) < 0) {
2863*77bd33e1Szrj 		LIBELF_SET_ERROR(IO, errno);
2864*77bd33e1Szrj 		return (NULL);
2865*77bd33e1Szrj 	}
2866*77bd33e1Szrj 
2867*77bd33e1Szrj 	mode = sb.st_mode;
2868*77bd33e1Szrj 	fsize = (size_t) sb.st_size;
2869*77bd33e1Szrj 
2870*77bd33e1Szrj 	/*
2871*77bd33e1Szrj 	 * Reject unsupported file types.
2872*77bd33e1Szrj 	 */
2873*77bd33e1Szrj 	if (!S_ISREG(mode) && !S_ISCHR(mode) && !S_ISFIFO(mode) &&
2874*77bd33e1Szrj 	    !S_ISSOCK(mode)) {
2875*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
2876*77bd33e1Szrj 		return (NULL);
2877*77bd33e1Szrj 	}
2878*77bd33e1Szrj 
2879*77bd33e1Szrj 	/*
2880*77bd33e1Szrj 	 * For ELF_C_WRITE mode, allocate and return a descriptor.
2881*77bd33e1Szrj 	 */
2882*77bd33e1Szrj 	if (c == ELF_C_WRITE) {
2883*77bd33e1Szrj 		if ((e = _libelf_allocate_elf()) != NULL) {
2884*77bd33e1Szrj 			_libelf_init_elf(e, ELF_K_ELF);
2885*77bd33e1Szrj 			e->e_byteorder = LIBELF_PRIVATE(byteorder);
2886*77bd33e1Szrj 			e->e_fd = fd;
2887*77bd33e1Szrj 			e->e_cmd = c;
2888*77bd33e1Szrj 			if (!S_ISREG(mode))
2889*77bd33e1Szrj 				e->e_flags |= LIBELF_F_SPECIAL_FILE;
2890*77bd33e1Szrj 		}
2891*77bd33e1Szrj 
2892*77bd33e1Szrj 		return (e);
2893*77bd33e1Szrj 	}
2894*77bd33e1Szrj 
2895*77bd33e1Szrj 
2896*77bd33e1Szrj 	/*
2897*77bd33e1Szrj 	 * ELF_C_READ and ELF_C_RDWR mode.
2898*77bd33e1Szrj 	 */
2899*77bd33e1Szrj 	m = NULL;
2900*77bd33e1Szrj 	flags = 0;
2901*77bd33e1Szrj 	if (S_ISREG(mode)) {
2902*77bd33e1Szrj 
2903*77bd33e1Szrj 		/*
2904*77bd33e1Szrj 		 * Reject zero length files.
2905*77bd33e1Szrj 		 */
2906*77bd33e1Szrj 		if (fsize == 0) {
2907*77bd33e1Szrj 			LIBELF_SET_ERROR(ARGUMENT, 0);
2908*77bd33e1Szrj 			return (NULL);
2909*77bd33e1Szrj 		}
2910*77bd33e1Szrj 
2911*77bd33e1Szrj #if	ELFTC_HAVE_MMAP
2912*77bd33e1Szrj 		/*
2913*77bd33e1Szrj 		 * Always map regular files in with 'PROT_READ'
2914*77bd33e1Szrj 		 * permissions.
2915*77bd33e1Szrj 		 *
2916*77bd33e1Szrj 		 * For objects opened in ELF_C_RDWR mode, when
2917*77bd33e1Szrj 		 * elf_update(3) is called, we remove this mapping,
2918*77bd33e1Szrj 		 * write file data out using write(2), and map the new
2919*77bd33e1Szrj 		 * contents back.
2920*77bd33e1Szrj 		 */
2921*77bd33e1Szrj 		m = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, (off_t) 0);
2922*77bd33e1Szrj 
2923*77bd33e1Szrj 		if (m == MAP_FAILED)
2924*77bd33e1Szrj 			m = NULL;
2925*77bd33e1Szrj 		else
2926*77bd33e1Szrj 			flags = LIBELF_F_RAWFILE_MMAP;
2927*77bd33e1Szrj #endif
2928*77bd33e1Szrj 
2929*77bd33e1Szrj 		/*
2930*77bd33e1Szrj 		 * Fallback to a read() if the call to mmap() failed,
2931*77bd33e1Szrj 		 * or if mmap() is not available.
2932*77bd33e1Szrj 		 */
2933*77bd33e1Szrj 		if (m == NULL) {
2934*77bd33e1Szrj 			if ((m = malloc(fsize)) == NULL) {
2935*77bd33e1Szrj 				LIBELF_SET_ERROR(RESOURCE, 0);
2936*77bd33e1Szrj 				return (NULL);
2937*77bd33e1Szrj 			}
2938*77bd33e1Szrj 
2939*77bd33e1Szrj 			if (read(fd, m, fsize) != (ssize_t) fsize) {
2940*77bd33e1Szrj 				LIBELF_SET_ERROR(IO, errno);
2941*77bd33e1Szrj 				free(m);
2942*77bd33e1Szrj 				return (NULL);
2943*77bd33e1Szrj 			}
2944*77bd33e1Szrj 
2945*77bd33e1Szrj 			flags = LIBELF_F_RAWFILE_MALLOC;
2946*77bd33e1Szrj 		}
2947*77bd33e1Szrj 	} else if ((m = _libelf_read_special_file(fd, &fsize)) != NULL)
2948*77bd33e1Szrj 		flags = LIBELF_F_RAWFILE_MALLOC | LIBELF_F_SPECIAL_FILE;
2949*77bd33e1Szrj 	else
2950*77bd33e1Szrj 		return (NULL);
2951*77bd33e1Szrj 
2952*77bd33e1Szrj 	if ((e = _libelf_memory(m, fsize, reporterror)) == NULL) {
2953*77bd33e1Szrj 		assert((flags & LIBELF_F_RAWFILE_MALLOC) ||
2954*77bd33e1Szrj 		    (flags & LIBELF_F_RAWFILE_MMAP));
2955*77bd33e1Szrj 		if (flags & LIBELF_F_RAWFILE_MALLOC)
2956*77bd33e1Szrj 			free(m);
2957*77bd33e1Szrj #if	ELFTC_HAVE_MMAP
2958*77bd33e1Szrj 		else
2959*77bd33e1Szrj 			(void) munmap(m, fsize);
2960*77bd33e1Szrj #endif
2961*77bd33e1Szrj 		return (NULL);
2962*77bd33e1Szrj 	}
2963*77bd33e1Szrj 
2964*77bd33e1Szrj 	/* ar(1) archives aren't supported in RDWR mode. */
2965*77bd33e1Szrj #if 0
2966*77bd33e1Szrj 	if (c == ELF_C_RDWR && e->e_kind == ELF_K_AR) {
2967*77bd33e1Szrj 		(void) elf_end(e);
2968*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
2969*77bd33e1Szrj 		return (NULL);
2970*77bd33e1Szrj 	}
2971*77bd33e1Szrj #endif
2972*77bd33e1Szrj 
2973*77bd33e1Szrj 	e->e_flags |= flags;
2974*77bd33e1Szrj 	e->e_fd = fd;
2975*77bd33e1Szrj 	e->e_cmd = c;
2976*77bd33e1Szrj 
2977*77bd33e1Szrj 	return (e);
2978*77bd33e1Szrj }
2979*77bd33e1Szrj 
2980*77bd33e1Szrj static const char *_libelf_errors[] = {
2981*77bd33e1Szrj #define	DEFINE_ERROR(N,S)	[ELF_E_##N] = S
2982*77bd33e1Szrj 	DEFINE_ERROR(NONE,	"No Error"),
2983*77bd33e1Szrj 	DEFINE_ERROR(ARCHIVE,	"Malformed ar(1) archive"),
2984*77bd33e1Szrj 	DEFINE_ERROR(ARGUMENT,	"Invalid argument"),
2985*77bd33e1Szrj 	DEFINE_ERROR(CLASS,	"ELF class mismatch"),
2986*77bd33e1Szrj 	DEFINE_ERROR(DATA,	"Invalid data buffer descriptor"),
2987*77bd33e1Szrj 	DEFINE_ERROR(HEADER,	"Missing or malformed ELF header"),
2988*77bd33e1Szrj 	DEFINE_ERROR(IO,	"I/O error"),
2989*77bd33e1Szrj 	DEFINE_ERROR(LAYOUT,	"Layout constraint violation"),
2990*77bd33e1Szrj 	DEFINE_ERROR(MODE,	"Incorrect ELF descriptor mode"),
2991*77bd33e1Szrj 	DEFINE_ERROR(RANGE,	"Value out of range of target"),
2992*77bd33e1Szrj 	DEFINE_ERROR(RESOURCE,	"Resource exhaustion"),
2993*77bd33e1Szrj 	DEFINE_ERROR(SECTION,	"Invalid section descriptor"),
2994*77bd33e1Szrj 	DEFINE_ERROR(SEQUENCE,	"API calls out of sequence"),
2995*77bd33e1Szrj 	DEFINE_ERROR(UNIMPL,	"Unimplemented feature"),
2996*77bd33e1Szrj 	DEFINE_ERROR(VERSION,	"Unknown ELF API version"),
2997*77bd33e1Szrj 	DEFINE_ERROR(NUM,	"Unknown error")
2998*77bd33e1Szrj #undef	DEFINE_ERROR
2999*77bd33e1Szrj };
3000*77bd33e1Szrj 
3001*77bd33e1Szrj /* PUBLIC */
3002*77bd33e1Szrj 
3003*77bd33e1Szrj /* elf_errmsg.c */
3004*77bd33e1Szrj static const char *
elf_errmsg(int error)3005*77bd33e1Szrj elf_errmsg(int error)
3006*77bd33e1Szrj {
3007*77bd33e1Szrj 	int oserr;
3008*77bd33e1Szrj 
3009*77bd33e1Szrj 	if (error == ELF_E_NONE &&
3010*77bd33e1Szrj 	    (error = LIBELF_PRIVATE(error)) == 0)
3011*77bd33e1Szrj 	    return NULL;
3012*77bd33e1Szrj 	else if (error == -1)
3013*77bd33e1Szrj 	    error = LIBELF_PRIVATE(error);
3014*77bd33e1Szrj 
3015*77bd33e1Szrj 	oserr = error >> LIBELF_OS_ERROR_SHIFT;
3016*77bd33e1Szrj 	error &= LIBELF_ELF_ERROR_MASK;
3017*77bd33e1Szrj 
3018*77bd33e1Szrj 	if (error < ELF_E_NONE || error >= ELF_E_NUM)
3019*77bd33e1Szrj 		return _libelf_errors[ELF_E_NUM];
3020*77bd33e1Szrj 	if (oserr) {
3021*77bd33e1Szrj 		(void) snprintf((char *) LIBELF_PRIVATE(msg),
3022*77bd33e1Szrj 		    sizeof(LIBELF_PRIVATE(msg)), "%s: %s",
3023*77bd33e1Szrj 		    _libelf_errors[error], strerror(oserr));
3024*77bd33e1Szrj 		return (const char *)&LIBELF_PRIVATE(msg);
3025*77bd33e1Szrj 	}
3026*77bd33e1Szrj 	return _libelf_errors[error];
3027*77bd33e1Szrj }
3028*77bd33e1Szrj 
3029*77bd33e1Szrj /* elf_errno.c */
3030*77bd33e1Szrj static int
elf_errno(void)3031*77bd33e1Szrj elf_errno(void)
3032*77bd33e1Szrj {
3033*77bd33e1Szrj 	int old;
3034*77bd33e1Szrj 
3035*77bd33e1Szrj 	old = LIBELF_PRIVATE(error);
3036*77bd33e1Szrj 	LIBELF_PRIVATE(error) = 0;
3037*77bd33e1Szrj 	return (old & LIBELF_ELF_ERROR_MASK);
3038*77bd33e1Szrj }
3039*77bd33e1Szrj 
3040*77bd33e1Szrj /* elf_version.c */
3041*77bd33e1Szrj static unsigned int
elf_version(unsigned int v)3042*77bd33e1Szrj elf_version(unsigned int v)
3043*77bd33e1Szrj {
3044*77bd33e1Szrj 	unsigned int old;
3045*77bd33e1Szrj 
3046*77bd33e1Szrj 	if ((old = LIBELF_PRIVATE(version)) == EV_NONE)
3047*77bd33e1Szrj 		old = EV_CURRENT;
3048*77bd33e1Szrj 
3049*77bd33e1Szrj 	if (v == EV_NONE)
3050*77bd33e1Szrj 		return old;
3051*77bd33e1Szrj 	if (v > EV_CURRENT) {
3052*77bd33e1Szrj 		LIBELF_SET_ERROR(VERSION, 0);
3053*77bd33e1Szrj 		return EV_NONE;
3054*77bd33e1Szrj 	}
3055*77bd33e1Szrj 
3056*77bd33e1Szrj 	LIBELF_PRIVATE(version) = v;
3057*77bd33e1Szrj 	return (old);
3058*77bd33e1Szrj }
3059*77bd33e1Szrj 
3060*77bd33e1Szrj /* elf_begin.c */
3061*77bd33e1Szrj static Elf *
elf_begin(int fd,Elf_Cmd c,Elf * a)3062*77bd33e1Szrj elf_begin(int fd, Elf_Cmd c, Elf *a)
3063*77bd33e1Szrj {
3064*77bd33e1Szrj 	Elf *e;
3065*77bd33e1Szrj 
3066*77bd33e1Szrj 	e = NULL;
3067*77bd33e1Szrj 
3068*77bd33e1Szrj 	if (LIBELF_PRIVATE(version) == EV_NONE) {
3069*77bd33e1Szrj 		LIBELF_SET_ERROR(SEQUENCE, 0);
3070*77bd33e1Szrj 		return (NULL);
3071*77bd33e1Szrj 	}
3072*77bd33e1Szrj 
3073*77bd33e1Szrj 	switch (c) {
3074*77bd33e1Szrj 	case ELF_C_NULL:
3075*77bd33e1Szrj 		return (NULL);
3076*77bd33e1Szrj 
3077*77bd33e1Szrj 	case ELF_C_WRITE:
3078*77bd33e1Szrj 		/*
3079*77bd33e1Szrj 		 * The ELF_C_WRITE command is required to ignore the
3080*77bd33e1Szrj 		 * descriptor passed in.
3081*77bd33e1Szrj 		 */
3082*77bd33e1Szrj 		a = NULL;
3083*77bd33e1Szrj 		break;
3084*77bd33e1Szrj 
3085*77bd33e1Szrj 	case ELF_C_RDWR:
3086*77bd33e1Szrj 		if (a != NULL) { /* not allowed for ar(1) archives. */
3087*77bd33e1Szrj 			LIBELF_SET_ERROR(ARGUMENT, 0);
3088*77bd33e1Szrj 			return (NULL);
3089*77bd33e1Szrj 		}
3090*77bd33e1Szrj 		/*FALLTHROUGH*/
3091*77bd33e1Szrj 	case ELF_C_READ:
3092*77bd33e1Szrj 		/*
3093*77bd33e1Szrj 		 * Descriptor `a' could be for a regular ELF file, or
3094*77bd33e1Szrj 		 * for an ar(1) archive.  If descriptor `a' was opened
3095*77bd33e1Szrj 		 * using a valid file descriptor, we need to check if
3096*77bd33e1Szrj 		 * the passed in `fd' value matches the original one.
3097*77bd33e1Szrj 		 */
3098*77bd33e1Szrj 		if (a &&
3099*77bd33e1Szrj 		    ((a->e_fd != -1 && a->e_fd != fd) || c != a->e_cmd)) {
3100*77bd33e1Szrj 			LIBELF_SET_ERROR(ARGUMENT, 0);
3101*77bd33e1Szrj 			return (NULL);
3102*77bd33e1Szrj 		}
3103*77bd33e1Szrj 		break;
3104*77bd33e1Szrj 
3105*77bd33e1Szrj 	default:
3106*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
3107*77bd33e1Szrj 		return (NULL);
3108*77bd33e1Szrj 
3109*77bd33e1Szrj 	}
3110*77bd33e1Szrj 
3111*77bd33e1Szrj 	if (a == NULL)
3112*77bd33e1Szrj 		e = _libelf_open_object(fd, c, 1);
3113*77bd33e1Szrj #if 0
3114*77bd33e1Szrj 	else if (a->e_kind == ELF_K_AR)
3115*77bd33e1Szrj 		e = _libelf_ar_open_member(a->e_fd, c, a);
3116*77bd33e1Szrj #endif
3117*77bd33e1Szrj 	else
3118*77bd33e1Szrj 		(e = a)->e_activations++;
3119*77bd33e1Szrj 
3120*77bd33e1Szrj 	return (e);
3121*77bd33e1Szrj }
3122*77bd33e1Szrj 
3123*77bd33e1Szrj /* elf_end.c */
3124*77bd33e1Szrj static int
elf_end(Elf * e)3125*77bd33e1Szrj elf_end(Elf *e)
3126*77bd33e1Szrj {
3127*77bd33e1Szrj 	Elf *sv;
3128*77bd33e1Szrj 	Elf_Scn *scn, *tscn;
3129*77bd33e1Szrj 
3130*77bd33e1Szrj 	if (e == NULL || e->e_activations == 0)
3131*77bd33e1Szrj 		return (0);
3132*77bd33e1Szrj 
3133*77bd33e1Szrj 	if (--e->e_activations > 0)
3134*77bd33e1Szrj 		return (e->e_activations);
3135*77bd33e1Szrj 
3136*77bd33e1Szrj 	assert(e->e_activations == 0);
3137*77bd33e1Szrj 
3138*77bd33e1Szrj 	while (e && e->e_activations == 0) {
3139*77bd33e1Szrj 		switch (e->e_kind) {
3140*77bd33e1Szrj 		case ELF_K_AR:
3141*77bd33e1Szrj 			/*
3142*77bd33e1Szrj 			 * If we still have open child descriptors, we
3143*77bd33e1Szrj 			 * need to defer reclaiming resources till all
3144*77bd33e1Szrj 			 * the child descriptors for the archive are
3145*77bd33e1Szrj 			 * closed.
3146*77bd33e1Szrj 			 */
3147*77bd33e1Szrj 			if (e->e_u.e_ar.e_nchildren > 0)
3148*77bd33e1Szrj 				return (0);
3149*77bd33e1Szrj 			break;
3150*77bd33e1Szrj 		case ELF_K_ELF:
3151*77bd33e1Szrj 			/*
3152*77bd33e1Szrj 			 * Reclaim all section descriptors.
3153*77bd33e1Szrj 			 */
3154*77bd33e1Szrj 			STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next,
3155*77bd33e1Szrj 			    tscn)
3156*77bd33e1Szrj 				scn = _libelf_release_scn(scn);
3157*77bd33e1Szrj 			break;
3158*77bd33e1Szrj 		case ELF_K_NUM:
3159*77bd33e1Szrj 			assert(0);
3160*77bd33e1Szrj 		default:
3161*77bd33e1Szrj 			break;
3162*77bd33e1Szrj 		}
3163*77bd33e1Szrj 
3164*77bd33e1Szrj 		if (e->e_rawfile) {
3165*77bd33e1Szrj 			if (e->e_flags & LIBELF_F_RAWFILE_MALLOC)
3166*77bd33e1Szrj 				free(e->e_rawfile);
3167*77bd33e1Szrj #if	ELFTC_HAVE_MMAP
3168*77bd33e1Szrj 			else if (e->e_flags & LIBELF_F_RAWFILE_MMAP)
3169*77bd33e1Szrj 				(void) munmap(e->e_rawfile, e->e_rawsize);
3170*77bd33e1Szrj #endif
3171*77bd33e1Szrj 		}
3172*77bd33e1Szrj 
3173*77bd33e1Szrj 		sv = e;
3174*77bd33e1Szrj 		if ((e = e->e_parent) != NULL)
3175*77bd33e1Szrj 			e->e_u.e_ar.e_nchildren--;
3176*77bd33e1Szrj 		sv = _libelf_release_elf(sv);
3177*77bd33e1Szrj 	}
3178*77bd33e1Szrj 
3179*77bd33e1Szrj 	return (0);
3180*77bd33e1Szrj }
3181*77bd33e1Szrj 
3182*77bd33e1Szrj /* gelf_shdr.c */
3183*77bd33e1Szrj static GElf_Shdr *
gelf_getshdr(Elf_Scn * s,GElf_Shdr * d)3184*77bd33e1Szrj gelf_getshdr(Elf_Scn *s, GElf_Shdr *d)
3185*77bd33e1Szrj {
3186*77bd33e1Szrj 	int ec;
3187*77bd33e1Szrj 	void *sh;
3188*77bd33e1Szrj #if 0
3189*77bd33e1Szrj 	Elf32_Shdr *sh32;
3190*77bd33e1Szrj #endif
3191*77bd33e1Szrj 	Elf64_Shdr *sh64;
3192*77bd33e1Szrj 
3193*77bd33e1Szrj 	if (d == NULL) {
3194*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
3195*77bd33e1Szrj 		return (NULL);
3196*77bd33e1Szrj 	}
3197*77bd33e1Szrj 
3198*77bd33e1Szrj 	if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL)
3199*77bd33e1Szrj 		return (NULL);
3200*77bd33e1Szrj 
3201*77bd33e1Szrj 	ec = s->s_elf->e_class;
3202*77bd33e1Szrj 	assert(/* ec == ELFCLASS32 || */ ec == ELFCLASS64);
3203*77bd33e1Szrj 
3204*77bd33e1Szrj #if 0
3205*77bd33e1Szrj 	if (ec == ELFCLASS32) {
3206*77bd33e1Szrj 		sh32 = (Elf32_Shdr *) sh;
3207*77bd33e1Szrj 
3208*77bd33e1Szrj 		d->sh_name      = sh32->sh_name;
3209*77bd33e1Szrj 		d->sh_type      = sh32->sh_type;
3210*77bd33e1Szrj 		d->sh_flags     = (Elf64_Xword) sh32->sh_flags;
3211*77bd33e1Szrj 		d->sh_addr      = (Elf64_Addr) sh32->sh_addr;
3212*77bd33e1Szrj 		d->sh_offset    = (Elf64_Off) sh32->sh_offset;
3213*77bd33e1Szrj 		d->sh_size      = (Elf64_Xword) sh32->sh_size;
3214*77bd33e1Szrj 		d->sh_link      = sh32->sh_link;
3215*77bd33e1Szrj 		d->sh_info      = sh32->sh_info;
3216*77bd33e1Szrj 		d->sh_addralign = (Elf64_Xword) sh32->sh_addralign;
3217*77bd33e1Szrj 		d->sh_entsize   = (Elf64_Xword) sh32->sh_entsize;
3218*77bd33e1Szrj 	} else
3219*77bd33e1Szrj #endif
3220*77bd33e1Szrj 	{
3221*77bd33e1Szrj 		sh64 = (Elf64_Shdr *) sh;
3222*77bd33e1Szrj 		*d = *sh64;
3223*77bd33e1Szrj 	}
3224*77bd33e1Szrj 
3225*77bd33e1Szrj 	return (d);
3226*77bd33e1Szrj }
3227*77bd33e1Szrj 
3228*77bd33e1Szrj /* gelf_sym.c */
3229*77bd33e1Szrj static GElf_Sym *
gelf_getsym(Elf_Data * ed,int ndx,GElf_Sym * dst)3230*77bd33e1Szrj gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst)
3231*77bd33e1Szrj {
3232*77bd33e1Szrj 	int ec;
3233*77bd33e1Szrj 	Elf *e;
3234*77bd33e1Szrj 	size_t msz;
3235*77bd33e1Szrj 	Elf_Scn *scn;
3236*77bd33e1Szrj 	uint32_t sh_type;
3237*77bd33e1Szrj #if 0
3238*77bd33e1Szrj 	Elf32_Sym *sym32;
3239*77bd33e1Szrj #endif
3240*77bd33e1Szrj 	Elf64_Sym *sym64;
3241*77bd33e1Szrj 	struct _Libelf_Data *d;
3242*77bd33e1Szrj 
3243*77bd33e1Szrj 	d = (struct _Libelf_Data *) ed;
3244*77bd33e1Szrj 
3245*77bd33e1Szrj 	if (d == NULL || ndx < 0 || dst == NULL ||
3246*77bd33e1Szrj 	    (scn = d->d_scn) == NULL ||
3247*77bd33e1Szrj 	    (e = scn->s_elf) == NULL) {
3248*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
3249*77bd33e1Szrj 		return (NULL);
3250*77bd33e1Szrj 	}
3251*77bd33e1Szrj 
3252*77bd33e1Szrj 	ec = e->e_class;
3253*77bd33e1Szrj 	assert(/* ec == ELFCLASS32 || */ ec == ELFCLASS64);
3254*77bd33e1Szrj 
3255*77bd33e1Szrj #if 0
3256*77bd33e1Szrj 	if (ec == ELFCLASS32)
3257*77bd33e1Szrj 		sh_type = scn->s_shdr.s_shdr32.sh_type;
3258*77bd33e1Szrj 	else
3259*77bd33e1Szrj #endif
3260*77bd33e1Szrj 		sh_type = scn->s_shdr.s_shdr64.sh_type;
3261*77bd33e1Szrj 
3262*77bd33e1Szrj 	if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
3263*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
3264*77bd33e1Szrj 		return (NULL);
3265*77bd33e1Szrj 	}
3266*77bd33e1Szrj 
3267*77bd33e1Szrj 	msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);
3268*77bd33e1Szrj 
3269*77bd33e1Szrj 	assert(msz > 0);
3270*77bd33e1Szrj 	assert(ndx >= 0);
3271*77bd33e1Szrj 
3272*77bd33e1Szrj 	if (msz * (size_t) ndx >= d->d_data.d_size) {
3273*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
3274*77bd33e1Szrj 		return (NULL);
3275*77bd33e1Szrj 	}
3276*77bd33e1Szrj 
3277*77bd33e1Szrj #if 0
3278*77bd33e1Szrj 	if (ec == ELFCLASS32) {
3279*77bd33e1Szrj 		sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx;
3280*77bd33e1Szrj 
3281*77bd33e1Szrj 		dst->st_name  = sym32->st_name;
3282*77bd33e1Szrj 		dst->st_value = (Elf64_Addr) sym32->st_value;
3283*77bd33e1Szrj 		dst->st_size  = (Elf64_Xword) sym32->st_size;
3284*77bd33e1Szrj 		dst->st_info  = sym32->st_info;
3285*77bd33e1Szrj 		dst->st_other = sym32->st_other;
3286*77bd33e1Szrj 		dst->st_shndx = sym32->st_shndx;
3287*77bd33e1Szrj 	} else
3288*77bd33e1Szrj #endif
3289*77bd33e1Szrj 	{
3290*77bd33e1Szrj 		sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx;
3291*77bd33e1Szrj 
3292*77bd33e1Szrj 		*dst = *sym64;
3293*77bd33e1Szrj 	}
3294*77bd33e1Szrj 
3295*77bd33e1Szrj 	return (dst);
3296*77bd33e1Szrj }
3297*77bd33e1Szrj 
3298*77bd33e1Szrj /* elf_scn.c */
3299*77bd33e1Szrj static Elf_Scn *
elf_nextscn(Elf * e,Elf_Scn * s)3300*77bd33e1Szrj elf_nextscn(Elf *e, Elf_Scn *s)
3301*77bd33e1Szrj {
3302*77bd33e1Szrj 	if (e == NULL || (e->e_kind != ELF_K_ELF) ||
3303*77bd33e1Szrj 	    (s && s->s_elf != e)) {
3304*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
3305*77bd33e1Szrj 		return (NULL);
3306*77bd33e1Szrj 	}
3307*77bd33e1Szrj 
3308*77bd33e1Szrj 	return (s == NULL ? elf_getscn(e, (size_t) 1) :
3309*77bd33e1Szrj 	    STAILQ_NEXT(s, s_next));
3310*77bd33e1Szrj }
3311*77bd33e1Szrj 
3312*77bd33e1Szrj /* elf_strptr.c */
3313*77bd33e1Szrj static char *
elf_strptr(Elf * e,size_t scndx,size_t offset)3314*77bd33e1Szrj elf_strptr(Elf *e, size_t scndx, size_t offset)
3315*77bd33e1Szrj {
3316*77bd33e1Szrj 	Elf_Scn *s;
3317*77bd33e1Szrj 	Elf_Data *d;
3318*77bd33e1Szrj 	GElf_Shdr shdr;
3319*77bd33e1Szrj 	uint64_t alignment, count;
3320*77bd33e1Szrj 
3321*77bd33e1Szrj 	if (e == NULL || e->e_kind != ELF_K_ELF) {
3322*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
3323*77bd33e1Szrj 		return (NULL);
3324*77bd33e1Szrj 	}
3325*77bd33e1Szrj 
3326*77bd33e1Szrj 	if ((s = elf_getscn(e, scndx)) == NULL ||
3327*77bd33e1Szrj 	    gelf_getshdr(s, &shdr) == NULL)
3328*77bd33e1Szrj 		return (NULL);
3329*77bd33e1Szrj 
3330*77bd33e1Szrj 	if (shdr.sh_type != SHT_STRTAB ||
3331*77bd33e1Szrj 	    offset >= shdr.sh_size) {
3332*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
3333*77bd33e1Szrj 		return (NULL);
3334*77bd33e1Szrj 	}
3335*77bd33e1Szrj 
3336*77bd33e1Szrj 	d = NULL;
3337*77bd33e1Szrj 	if (e->e_flags & ELF_F_LAYOUT) {
3338*77bd33e1Szrj 
3339*77bd33e1Szrj 		/*
3340*77bd33e1Szrj 		 * The application is taking responsibility for the
3341*77bd33e1Szrj 		 * ELF object's layout, so we can directly translate
3342*77bd33e1Szrj 		 * an offset to a `char *' address using the `d_off'
3343*77bd33e1Szrj 		 * members of Elf_Data descriptors.
3344*77bd33e1Szrj 		 */
3345*77bd33e1Szrj 		while ((d = elf_getdata(s, d)) != NULL) {
3346*77bd33e1Szrj 
3347*77bd33e1Szrj 			if (d->d_buf == 0 || d->d_size == 0)
3348*77bd33e1Szrj 				continue;
3349*77bd33e1Szrj 
3350*77bd33e1Szrj 			if (d->d_type != ELF_T_BYTE) {
3351*77bd33e1Szrj 				LIBELF_SET_ERROR(DATA, 0);
3352*77bd33e1Szrj 				return (NULL);
3353*77bd33e1Szrj 			}
3354*77bd33e1Szrj 
3355*77bd33e1Szrj 			if (offset >= d->d_off &&
3356*77bd33e1Szrj 			    offset < d->d_off + d->d_size)
3357*77bd33e1Szrj 				return ((char *) d->d_buf + offset - d->d_off);
3358*77bd33e1Szrj 		}
3359*77bd33e1Szrj 	} else {
3360*77bd33e1Szrj 		/*
3361*77bd33e1Szrj 		 * Otherwise, the `d_off' members are not useable and
3362*77bd33e1Szrj 		 * we need to compute offsets ourselves, taking into
3363*77bd33e1Szrj 		 * account 'holes' in coverage of the section introduced
3364*77bd33e1Szrj 		 * by alignment requirements.
3365*77bd33e1Szrj 		 */
3366*77bd33e1Szrj 		count = (uint64_t) 0;	/* cumulative count of bytes seen */
3367*77bd33e1Szrj 		while ((d = elf_getdata(s, d)) != NULL && count <= offset) {
3368*77bd33e1Szrj 
3369*77bd33e1Szrj 			if (d->d_buf == NULL || d->d_size == 0)
3370*77bd33e1Szrj 				continue;
3371*77bd33e1Szrj 
3372*77bd33e1Szrj 			if (d->d_type != ELF_T_BYTE) {
3373*77bd33e1Szrj 				LIBELF_SET_ERROR(DATA, 0);
3374*77bd33e1Szrj 				return (NULL);
3375*77bd33e1Szrj 			}
3376*77bd33e1Szrj 
3377*77bd33e1Szrj 			if ((alignment = d->d_align) > 1) {
3378*77bd33e1Szrj 				if ((alignment & (alignment - 1)) != 0) {
3379*77bd33e1Szrj 					LIBELF_SET_ERROR(DATA, 0);
3380*77bd33e1Szrj 					return (NULL);
3381*77bd33e1Szrj 				}
3382*77bd33e1Szrj 				count = roundup2(count, alignment);
3383*77bd33e1Szrj 			}
3384*77bd33e1Szrj 
3385*77bd33e1Szrj 			if (offset < count) {
3386*77bd33e1Szrj 				/* offset starts in the 'hole' */
3387*77bd33e1Szrj 				LIBELF_SET_ERROR(ARGUMENT, 0);
3388*77bd33e1Szrj 				return (NULL);
3389*77bd33e1Szrj 			}
3390*77bd33e1Szrj 
3391*77bd33e1Szrj 			if (offset < count + d->d_size) {
3392*77bd33e1Szrj 				if (d->d_buf != NULL)
3393*77bd33e1Szrj 					return ((char *) d->d_buf +
3394*77bd33e1Szrj 					    offset - count);
3395*77bd33e1Szrj 				LIBELF_SET_ERROR(DATA, 0);
3396*77bd33e1Szrj 				return (NULL);
3397*77bd33e1Szrj 			}
3398*77bd33e1Szrj 
3399*77bd33e1Szrj 			count += d->d_size;
3400*77bd33e1Szrj 		}
3401*77bd33e1Szrj 	}
3402*77bd33e1Szrj 
3403*77bd33e1Szrj 	LIBELF_SET_ERROR(ARGUMENT, 0);
3404*77bd33e1Szrj 	return (NULL);
3405*77bd33e1Szrj }
3406*77bd33e1Szrj 
3407*77bd33e1Szrj /* elf_data.c */
3408*77bd33e1Szrj static Elf_Data *
elf_getdata(Elf_Scn * s,Elf_Data * ed)3409*77bd33e1Szrj elf_getdata(Elf_Scn *s, Elf_Data *ed)
3410*77bd33e1Szrj {
3411*77bd33e1Szrj 	Elf *e;
3412*77bd33e1Szrj 	unsigned int sh_type;
3413*77bd33e1Szrj 	int elfclass, elftype;
3414*77bd33e1Szrj 	size_t count, fsz, msz;
3415*77bd33e1Szrj 	struct _Libelf_Data *d;
3416*77bd33e1Szrj 	uint64_t sh_align, sh_offset, sh_size;
3417*77bd33e1Szrj 	int (*xlate)(unsigned char *_d, size_t _dsz, unsigned char *_s,
3418*77bd33e1Szrj 	    size_t _c, int _swap);
3419*77bd33e1Szrj 
3420*77bd33e1Szrj 	d = (struct _Libelf_Data *) ed;
3421*77bd33e1Szrj 
3422*77bd33e1Szrj 	if (s == NULL || (e = s->s_elf) == NULL ||
3423*77bd33e1Szrj 	    (d != NULL && s != d->d_scn)) {
3424*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
3425*77bd33e1Szrj 		return (NULL);
3426*77bd33e1Szrj 	}
3427*77bd33e1Szrj 
3428*77bd33e1Szrj 	assert(e->e_kind == ELF_K_ELF);
3429*77bd33e1Szrj 
3430*77bd33e1Szrj 	if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)
3431*77bd33e1Szrj 		return (&d->d_data);
3432*77bd33e1Szrj 
3433*77bd33e1Szrj 	if (d != NULL)
3434*77bd33e1Szrj 		return (&STAILQ_NEXT(d, d_next)->d_data);
3435*77bd33e1Szrj 
3436*77bd33e1Szrj 	if (e->e_rawfile == NULL) {
3437*77bd33e1Szrj 		/*
3438*77bd33e1Szrj 		 * In the ELF_C_WRITE case, there is no source that
3439*77bd33e1Szrj 		 * can provide data for the section.
3440*77bd33e1Szrj 		 */
3441*77bd33e1Szrj 		LIBELF_SET_ERROR(ARGUMENT, 0);
3442*77bd33e1Szrj 		return (NULL);
3443*77bd33e1Szrj 	}
3444*77bd33e1Szrj 
3445*77bd33e1Szrj 	elfclass = e->e_class;
3446*77bd33e1Szrj 
3447*77bd33e1Szrj 	assert(/* elfclass == ELFCLASS32 || */ elfclass == ELFCLASS64);
3448*77bd33e1Szrj 
3449*77bd33e1Szrj #if 0
3450*77bd33e1Szrj 	if (elfclass == ELFCLASS32) {
3451*77bd33e1Szrj 		sh_type   = s->s_shdr.s_shdr32.sh_type;
3452*77bd33e1Szrj 		sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
3453*77bd33e1Szrj 		sh_size   = (uint64_t) s->s_shdr.s_shdr32.sh_size;
3454*77bd33e1Szrj 		sh_align  = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
3455*77bd33e1Szrj 	} else
3456*77bd33e1Szrj #endif
3457*77bd33e1Szrj 	{
3458*77bd33e1Szrj 		sh_type   = s->s_shdr.s_shdr64.sh_type;
3459*77bd33e1Szrj 		sh_offset = s->s_shdr.s_shdr64.sh_offset;
3460*77bd33e1Szrj 		sh_size   = s->s_shdr.s_shdr64.sh_size;
3461*77bd33e1Szrj 		sh_align  = s->s_shdr.s_shdr64.sh_addralign;
3462*77bd33e1Szrj 	}
3463*77bd33e1Szrj 
3464*77bd33e1Szrj 	if (sh_type == SHT_NULL) {
3465*77bd33e1Szrj 		LIBELF_SET_ERROR(SECTION, 0);
3466*77bd33e1Szrj 		return (NULL);
3467*77bd33e1Szrj 	}
3468*77bd33e1Szrj 
3469*77bd33e1Szrj 	if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
3470*77bd33e1Szrj 	    elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
3471*77bd33e1Szrj 	    sh_offset + sh_size > (uint64_t) e->e_rawsize)) {
3472*77bd33e1Szrj 		LIBELF_SET_ERROR(SECTION, 0);
3473*77bd33e1Szrj 		return (NULL);
3474*77bd33e1Szrj 	}
3475*77bd33e1Szrj 
3476*77bd33e1Szrj 	if ((fsz = (/* elfclass == ELFCLASS32 ? elf32_fsize :*/ elf64_fsize)
3477*77bd33e1Szrj             (elftype, (size_t) 1, e->e_version)) == 0) {
3478*77bd33e1Szrj 		LIBELF_SET_ERROR(UNIMPL, 0);
3479*77bd33e1Szrj 		return (NULL);
3480*77bd33e1Szrj 	}
3481*77bd33e1Szrj 
3482*77bd33e1Szrj 	if (sh_size % fsz) {
3483*77bd33e1Szrj 		LIBELF_SET_ERROR(SECTION, 0);
3484*77bd33e1Szrj 		return (NULL);
3485*77bd33e1Szrj 	}
3486*77bd33e1Szrj 
3487*77bd33e1Szrj 	if (sh_size / fsz > SIZE_MAX) {
3488*77bd33e1Szrj 		LIBELF_SET_ERROR(RANGE, 0);
3489*77bd33e1Szrj 		return (NULL);
3490*77bd33e1Szrj 	}
3491*77bd33e1Szrj 
3492*77bd33e1Szrj 	count = (size_t) (sh_size / fsz);
3493*77bd33e1Szrj 
3494*77bd33e1Szrj 	msz = _libelf_msize(elftype, elfclass, e->e_version);
3495*77bd33e1Szrj 
3496*77bd33e1Szrj 	if (count > 0 && msz > SIZE_MAX / count) {
3497*77bd33e1Szrj 		LIBELF_SET_ERROR(RANGE, 0);
3498*77bd33e1Szrj 		return (NULL);
3499*77bd33e1Szrj 	}
3500*77bd33e1Szrj 
3501*77bd33e1Szrj 	assert(msz > 0);
3502*77bd33e1Szrj 	assert(count <= SIZE_MAX);
3503*77bd33e1Szrj 	assert(msz * count <= SIZE_MAX);
3504*77bd33e1Szrj 
3505*77bd33e1Szrj 	if ((d = _libelf_allocate_data(s)) == NULL)
3506*77bd33e1Szrj 		return (NULL);
3507*77bd33e1Szrj 
3508*77bd33e1Szrj 	d->d_data.d_buf     = NULL;
3509*77bd33e1Szrj 	d->d_data.d_off     = 0;
3510*77bd33e1Szrj 	d->d_data.d_align   = sh_align;
3511*77bd33e1Szrj 	d->d_data.d_size    = msz * count;
3512*77bd33e1Szrj 	d->d_data.d_type    = elftype;
3513*77bd33e1Szrj 	d->d_data.d_version = e->e_version;
3514*77bd33e1Szrj 
3515*77bd33e1Szrj 	if (sh_type == SHT_NOBITS || sh_size == 0) {
3516*77bd33e1Szrj 	        STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
3517*77bd33e1Szrj 		return (&d->d_data);
3518*77bd33e1Szrj         }
3519*77bd33e1Szrj 
3520*77bd33e1Szrj 	if ((d->d_data.d_buf = malloc(msz * count)) == NULL) {
3521*77bd33e1Szrj 		(void) _libelf_release_data(d);
3522*77bd33e1Szrj 		LIBELF_SET_ERROR(RESOURCE, 0);
3523*77bd33e1Szrj 		return (NULL);
3524*77bd33e1Szrj 	}
3525*77bd33e1Szrj 
3526*77bd33e1Szrj 	d->d_flags  |= LIBELF_F_DATA_MALLOCED;
3527*77bd33e1Szrj 
3528*77bd33e1Szrj 	xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass);
3529*77bd33e1Szrj 	if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size,
3530*77bd33e1Szrj 	    e->e_rawfile + sh_offset, count,
3531*77bd33e1Szrj 	    e->e_byteorder != LIBELF_PRIVATE(byteorder))) {
3532*77bd33e1Szrj 		_libelf_release_data(d);
3533*77bd33e1Szrj 		LIBELF_SET_ERROR(DATA, 0);
3534*77bd33e1Szrj 		return (NULL);
3535*77bd33e1Szrj 	}
3536*77bd33e1Szrj 
3537*77bd33e1Szrj 	STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
3538*77bd33e1Szrj 
3539*77bd33e1Szrj 	return (&d->d_data);
3540*77bd33e1Szrj }
3541*77bd33e1Szrj 
3542*77bd33e1Szrj #endif /* !_PRIVATE_LIBELF_H_ */
3543