1*f8fb3368SJohn Marino/*-
2*f8fb3368SJohn Marino * Copyright (c) 2006-2011 Joseph Koshy
3*f8fb3368SJohn Marino * All rights reserved.
4*f8fb3368SJohn Marino *
5*f8fb3368SJohn Marino * Redistribution and use in source and binary forms, with or without
6*f8fb3368SJohn Marino * modification, are permitted provided that the following conditions
7*f8fb3368SJohn Marino * are met:
8*f8fb3368SJohn Marino * 1. Redistributions of source code must retain the above copyright
9*f8fb3368SJohn Marino *    notice, this list of conditions and the following disclaimer.
10*f8fb3368SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
11*f8fb3368SJohn Marino *    notice, this list of conditions and the following disclaimer in the
12*f8fb3368SJohn Marino *    documentation and/or other materials provided with the distribution.
13*f8fb3368SJohn Marino *
14*f8fb3368SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*f8fb3368SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*f8fb3368SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*f8fb3368SJohn Marino * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*f8fb3368SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*f8fb3368SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*f8fb3368SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*f8fb3368SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*f8fb3368SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*f8fb3368SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*f8fb3368SJohn Marino * SUCH DAMAGE.
25*f8fb3368SJohn Marino */
26*f8fb3368SJohn Marino
27*f8fb3368SJohn Marino#include <assert.h>
28*f8fb3368SJohn Marino#include <libelf.h>
29*f8fb3368SJohn Marino#include <string.h>
30*f8fb3368SJohn Marino
31*f8fb3368SJohn Marino#include "_libelf.h"
32*f8fb3368SJohn Marino
33*f8fb3368SJohn MarinoELFTC_VCSID("$Id: libelf_convert.m4 3174 2015-03-27 17:13:41Z emaste $");
34*f8fb3368SJohn Marino
35*f8fb3368SJohn Marino/* WARNING: GENERATED FROM __file__. */
36*f8fb3368SJohn Marino
37*f8fb3368SJohn Marinodivert(-1)
38*f8fb3368SJohn Marino
39*f8fb3368SJohn Marino# Generate conversion routines for converting between in-memory and
40*f8fb3368SJohn Marino# file representations of Elf data structures.
41*f8fb3368SJohn Marino#
42*f8fb3368SJohn Marino# These conversions use the type information defined in `elf_types.m4'.
43*f8fb3368SJohn Marino
44*f8fb3368SJohn Marinoinclude(SRCDIR`/elf_types.m4')
45*f8fb3368SJohn Marino
46*f8fb3368SJohn Marino# For the purposes of generating conversion code, ELF types may be
47*f8fb3368SJohn Marino# classified according to the following characteristics:
48*f8fb3368SJohn Marino#
49*f8fb3368SJohn Marino# 1. Whether the ELF type can be directly mapped to an integral C
50*f8fb3368SJohn Marino#    language type.  For example, the ELF_T_WORD type maps directly to
51*f8fb3368SJohn Marino#    a 'uint32_t', but ELF_T_GNUHASH lacks a matching C type.
52*f8fb3368SJohn Marino#
53*f8fb3368SJohn Marino# 2. Whether the type has word size dependent variants.  For example,
54*f8fb3368SJohn Marino#    ELT_T_EHDR is represented using C types Elf32_Ehdr and El64_Ehdr,
55*f8fb3368SJohn Marino#    and the ELF_T_ADDR and ELF_T_OFF types have integral C types that
56*f8fb3368SJohn Marino#    can be 32- or 64- bit wide.
57*f8fb3368SJohn Marino#
58*f8fb3368SJohn Marino# 3. Whether the ELF types has a fixed representation or not.  For
59*f8fb3368SJohn Marino#    example, the ELF_T_SYM type has a fixed size file representation,
60*f8fb3368SJohn Marino#    some types like ELF_T_NOTE and ELF_T_GNUHASH use a variable size
61*f8fb3368SJohn Marino#    representation.
62*f8fb3368SJohn Marino#
63*f8fb3368SJohn Marino# We use m4 macros to generate conversion code for ELF types that have
64*f8fb3368SJohn Marino# a fixed size representation.  Conversion functions for the remaining
65*f8fb3368SJohn Marino# types are coded by hand.
66*f8fb3368SJohn Marino#
67*f8fb3368SJohn Marino#* Handling File and Memory Representations
68*f8fb3368SJohn Marino#
69*f8fb3368SJohn Marino# `In-memory' representations of an Elf data structure use natural
70*f8fb3368SJohn Marino# alignments and native byte ordering.  This allows pointer arithmetic
71*f8fb3368SJohn Marino# and casting to work as expected.  On the other hand, the `file'
72*f8fb3368SJohn Marino# representation of an ELF data structure could possibly be packed
73*f8fb3368SJohn Marino# tighter than its `in-memory' representation, and could be of a
74*f8fb3368SJohn Marino# differing byte order.  Reading ELF objects that are members of `ar'
75*f8fb3368SJohn Marino# archives present an additional complication: `ar' pads file data to
76*f8fb3368SJohn Marino# even addresses, so file data structures in an archive member
77*f8fb3368SJohn Marino# residing inside an `ar' archive could be at misaligned memory
78*f8fb3368SJohn Marino# addresses when brought into memory.
79*f8fb3368SJohn Marino#
80*f8fb3368SJohn Marino# In summary, casting the `char *' pointers that point to memory
81*f8fb3368SJohn Marino# representations (i.e., source pointers for the *_tof() functions and
82*f8fb3368SJohn Marino# the destination pointers for the *_tom() functions), is safe, as
83*f8fb3368SJohn Marino# these pointers should be correctly aligned for the memory type
84*f8fb3368SJohn Marino# already.  However, pointers to file representations have to be
85*f8fb3368SJohn Marino# treated as being potentially unaligned and no casting can be done.
86*f8fb3368SJohn Marino
87*f8fb3368SJohn Marino# NOCVT(TYPE) -- Do not generate the cvt[] structure entry for TYPE
88*f8fb3368SJohn Marinodefine(`NOCVT',`define(`NOCVT_'$1,1)')
89*f8fb3368SJohn Marino
90*f8fb3368SJohn Marino# NOFUNC(TYPE) -- Do not generate a conversion function for TYPE
91*f8fb3368SJohn Marinodefine(`NOFUNC',`define(`NOFUNC_'$1,1)')
92*f8fb3368SJohn Marino
93*f8fb3368SJohn Marino# IGNORE(TYPE) -- Completely ignore the type.
94*f8fb3368SJohn Marinodefine(`IGNORE',`NOCVT($1)NOFUNC($1)')
95*f8fb3368SJohn Marino
96*f8fb3368SJohn Marino# Mark ELF types that should not be processed by the M4 macros below.
97*f8fb3368SJohn Marino
98*f8fb3368SJohn Marino# Types for which we use functions with non-standard names.
99*f8fb3368SJohn MarinoIGNORE(`BYTE')			# Uses a wrapper around memcpy().
100*f8fb3368SJohn MarinoIGNORE(`NOTE')			# Not a fixed size type.
101*f8fb3368SJohn Marino
102*f8fb3368SJohn Marino# Types for which we supply hand-coded functions.
103*f8fb3368SJohn MarinoNOFUNC(`GNUHASH')		# A type with complex internal structure.
104*f8fb3368SJohn MarinoNOFUNC(`VDEF')			# See MAKE_VERSION_CONVERTERS below.
105*f8fb3368SJohn MarinoNOFUNC(`VNEED')			# ..
106*f8fb3368SJohn Marino
107*f8fb3368SJohn Marino# Unimplemented types.
108*f8fb3368SJohn MarinoIGNORE(`MOVEP')
109*f8fb3368SJohn Marino
110*f8fb3368SJohn Marino# ELF types that don't exist in a 32-bit world.
111*f8fb3368SJohn MarinoNOFUNC(`XWORD32')
112*f8fb3368SJohn MarinoNOFUNC(`SXWORD32')
113*f8fb3368SJohn Marino
114*f8fb3368SJohn Marino# `Primitive' ELF types are those that are an alias for an integral
115*f8fb3368SJohn Marino# type.  As they have no internal structure, they can be copied using
116*f8fb3368SJohn Marino# a `memcpy()', and byteswapped in straightforward way.
117*f8fb3368SJohn Marino#
118*f8fb3368SJohn Marino# Mark all ELF types that directly map to integral C types.
119*f8fb3368SJohn Marinodefine(`PRIM_ADDR',	1)
120*f8fb3368SJohn Marinodefine(`PRIM_BYTE',	1)
121*f8fb3368SJohn Marinodefine(`PRIM_HALF',	1)
122*f8fb3368SJohn Marinodefine(`PRIM_LWORD',	1)
123*f8fb3368SJohn Marinodefine(`PRIM_OFF',	1)
124*f8fb3368SJohn Marinodefine(`PRIM_SWORD',	1)
125*f8fb3368SJohn Marinodefine(`PRIM_SXWORD',	1)
126*f8fb3368SJohn Marinodefine(`PRIM_WORD',	1)
127*f8fb3368SJohn Marinodefine(`PRIM_XWORD',	1)
128*f8fb3368SJohn Marino
129*f8fb3368SJohn Marino# Note the primitive types that are size-dependent.
130*f8fb3368SJohn Marinodefine(`SIZEDEP_ADDR',	1)
131*f8fb3368SJohn Marinodefine(`SIZEDEP_OFF',	1)
132*f8fb3368SJohn Marino
133*f8fb3368SJohn Marino# Generate conversion functions for primitive types.
134*f8fb3368SJohn Marino#
135*f8fb3368SJohn Marino# Macro use: MAKEPRIMFUNCS(ELFTYPE,CTYPE,TYPESIZE,SYMSIZE)
136*f8fb3368SJohn Marino# `$1': Name of the ELF type.
137*f8fb3368SJohn Marino# `$2': C structure name suffix.
138*f8fb3368SJohn Marino# `$3': ELF class specifier for types, one of [`32', `64'].
139*f8fb3368SJohn Marino# `$4': Additional ELF class specifier, one of [`', `32', `64'].
140*f8fb3368SJohn Marino#
141*f8fb3368SJohn Marino# Generates a pair of conversion functions.
142*f8fb3368SJohn Marinodefine(`MAKEPRIMFUNCS',`
143*f8fb3368SJohn Marinostatic int
144*f8fb3368SJohn Marino_libelf_cvt_$1$4_tof(unsigned char *dst, size_t dsz, unsigned char *src,
145*f8fb3368SJohn Marino    size_t count, int byteswap)
146*f8fb3368SJohn Marino{
147*f8fb3368SJohn Marino	Elf$3_$2 t, *s = (Elf$3_$2 *) (uintptr_t) src;
148*f8fb3368SJohn Marino	size_t c;
149*f8fb3368SJohn Marino
150*f8fb3368SJohn Marino	(void) dsz;
151*f8fb3368SJohn Marino
152*f8fb3368SJohn Marino	if (!byteswap) {
153*f8fb3368SJohn Marino		(void) memcpy(dst, src, count * sizeof(*s));
154*f8fb3368SJohn Marino		return (1);
155*f8fb3368SJohn Marino	}
156*f8fb3368SJohn Marino
157*f8fb3368SJohn Marino	for (c = 0; c < count; c++) {
158*f8fb3368SJohn Marino		t = *s++;
159*f8fb3368SJohn Marino		SWAP_$1$4(t);
160*f8fb3368SJohn Marino		WRITE_$1$4(dst,t);
161*f8fb3368SJohn Marino	}
162*f8fb3368SJohn Marino
163*f8fb3368SJohn Marino	return (1);
164*f8fb3368SJohn Marino}
165*f8fb3368SJohn Marino
166*f8fb3368SJohn Marinostatic int
167*f8fb3368SJohn Marino_libelf_cvt_$1$4_tom(unsigned char *dst, size_t dsz, unsigned char *src,
168*f8fb3368SJohn Marino    size_t count, int byteswap)
169*f8fb3368SJohn Marino{
170*f8fb3368SJohn Marino	Elf$3_$2 t, *d = (Elf$3_$2 *) (uintptr_t) dst;
171*f8fb3368SJohn Marino	size_t c;
172*f8fb3368SJohn Marino
173*f8fb3368SJohn Marino	if (dsz < count * sizeof(Elf$3_$2))
174*f8fb3368SJohn Marino		return (0);
175*f8fb3368SJohn Marino
176*f8fb3368SJohn Marino	if (!byteswap) {
177*f8fb3368SJohn Marino		(void) memcpy(dst, src, count * sizeof(*d));
178*f8fb3368SJohn Marino		return (1);
179*f8fb3368SJohn Marino	}
180*f8fb3368SJohn Marino
181*f8fb3368SJohn Marino	for (c = 0; c < count; c++) {
182*f8fb3368SJohn Marino		READ_$1$4(src,t);
183*f8fb3368SJohn Marino		SWAP_$1$4(t);
184*f8fb3368SJohn Marino		*d++ = t;
185*f8fb3368SJohn Marino	}
186*f8fb3368SJohn Marino
187*f8fb3368SJohn Marino	return (1);
188*f8fb3368SJohn Marino}
189*f8fb3368SJohn Marino')
190*f8fb3368SJohn Marino
191*f8fb3368SJohn Marino#
192*f8fb3368SJohn Marino# Handling composite ELF types
193*f8fb3368SJohn Marino#
194*f8fb3368SJohn Marino
195*f8fb3368SJohn Marino# SWAP_FIELD(FIELDNAME,ELFTYPE) -- Generate code to swap one field.
196*f8fb3368SJohn Marinodefine(`SWAP_FIELD',
197*f8fb3368SJohn Marino  `ifdef(`SIZEDEP_'$2,
198*f8fb3368SJohn Marino    `SWAP_$2'SZ()`(t.$1);
199*f8fb3368SJohn Marino			',
200*f8fb3368SJohn Marino    `SWAP_$2(t.$1);
201*f8fb3368SJohn Marino			')')
202*f8fb3368SJohn Marino
203*f8fb3368SJohn Marino# SWAP_MEMBERS(STRUCT) -- Iterate over a structure definition.
204*f8fb3368SJohn Marinodefine(`SWAP_MEMBERS',
205*f8fb3368SJohn Marino  `ifelse($#,1,`/**/',
206*f8fb3368SJohn Marino     `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
207*f8fb3368SJohn Marino
208*f8fb3368SJohn Marino# SWAP_STRUCT(CTYPE,SIZE) -- Generate code to swap an ELF structure.
209*f8fb3368SJohn Marinodefine(`SWAP_STRUCT',
210*f8fb3368SJohn Marino  `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
211*f8fb3368SJohn Marino			SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
212*f8fb3368SJohn Marino
213*f8fb3368SJohn Marino# WRITE_FIELD(ELFTYPE,FIELDNAME) -- Generate code to write one field.
214*f8fb3368SJohn Marinodefine(`WRITE_FIELD',
215*f8fb3368SJohn Marino  `ifdef(`SIZEDEP_'$2,
216*f8fb3368SJohn Marino    `WRITE_$2'SZ()`(dst,t.$1);
217*f8fb3368SJohn Marino		',
218*f8fb3368SJohn Marino    `WRITE_$2(dst,t.$1);
219*f8fb3368SJohn Marino		')')
220*f8fb3368SJohn Marino
221*f8fb3368SJohn Marino# WRITE_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
222*f8fb3368SJohn Marinodefine(`WRITE_MEMBERS',
223*f8fb3368SJohn Marino  `ifelse($#,1,`/**/',
224*f8fb3368SJohn Marino    `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
225*f8fb3368SJohn Marino
226*f8fb3368SJohn Marino# WRITE_STRUCT(CTYPE,SIZE) -- Generate code to write out an ELF structure.
227*f8fb3368SJohn Marinodefine(`WRITE_STRUCT',
228*f8fb3368SJohn Marino  `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
229*f8fb3368SJohn Marino		WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
230*f8fb3368SJohn Marino
231*f8fb3368SJohn Marino# READ_FIELD(ELFTYPE,CTYPE) -- Generate code to read one field.
232*f8fb3368SJohn Marinodefine(`READ_FIELD',
233*f8fb3368SJohn Marino  `ifdef(`SIZEDEP_'$2,
234*f8fb3368SJohn Marino    `READ_$2'SZ()`(s,t.$1);
235*f8fb3368SJohn Marino		',
236*f8fb3368SJohn Marino    `READ_$2(s,t.$1);
237*f8fb3368SJohn Marino		')')
238*f8fb3368SJohn Marino
239*f8fb3368SJohn Marino# READ_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
240*f8fb3368SJohn Marinodefine(`READ_MEMBERS',
241*f8fb3368SJohn Marino  `ifelse($#,1,`/**/',
242*f8fb3368SJohn Marino    `READ_FIELD($1)READ_MEMBERS(shift($@))')')
243*f8fb3368SJohn Marino
244*f8fb3368SJohn Marino# READ_STRUCT(CTYPE,SIZE) -- Generate code to read an ELF structure.
245*f8fb3368SJohn Marinodefine(`READ_STRUCT',
246*f8fb3368SJohn Marino  `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
247*f8fb3368SJohn Marino		READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
248*f8fb3368SJohn Marino
249*f8fb3368SJohn Marino
250*f8fb3368SJohn Marino# MAKECOMPFUNCS -- Generate converters for composite ELF structures.
251*f8fb3368SJohn Marino#
252*f8fb3368SJohn Marino# When converting data to file representation, the source pointer will
253*f8fb3368SJohn Marino# be naturally aligned for a data structure's in-memory
254*f8fb3368SJohn Marino# representation.  When converting data to memory, the destination
255*f8fb3368SJohn Marino# pointer will be similarly aligned.
256*f8fb3368SJohn Marino#
257*f8fb3368SJohn Marino# For in-place conversions, when converting to file representations,
258*f8fb3368SJohn Marino# the source buffer is large enough to hold `file' data.  When
259*f8fb3368SJohn Marino# converting from file to memory, we need to be careful to work
260*f8fb3368SJohn Marino# `backwards', to avoid overwriting unconverted data.
261*f8fb3368SJohn Marino#
262*f8fb3368SJohn Marino# Macro use:
263*f8fb3368SJohn Marino# `$1': Name of the ELF type.
264*f8fb3368SJohn Marino# `$2': C structure name suffix.
265*f8fb3368SJohn Marino# `$3': ELF class specifier, one of [`', `32', `64']
266*f8fb3368SJohn Marinodefine(`MAKECOMPFUNCS', `ifdef(`NOFUNC_'$1$3,`',`
267*f8fb3368SJohn Marinostatic int
268*f8fb3368SJohn Marino_libelf_cvt_$1$3_tof(unsigned char *dst, size_t dsz, unsigned char *src,
269*f8fb3368SJohn Marino    size_t count, int byteswap)
270*f8fb3368SJohn Marino{
271*f8fb3368SJohn Marino	Elf$3_$2	t, *s;
272*f8fb3368SJohn Marino	size_t c;
273*f8fb3368SJohn Marino
274*f8fb3368SJohn Marino	(void) dsz;
275*f8fb3368SJohn Marino
276*f8fb3368SJohn Marino	s = (Elf$3_$2 *) (uintptr_t) src;
277*f8fb3368SJohn Marino	for (c = 0; c < count; c++) {
278*f8fb3368SJohn Marino		t = *s++;
279*f8fb3368SJohn Marino		if (byteswap) {
280*f8fb3368SJohn Marino			SWAP_STRUCT($2,$3)
281*f8fb3368SJohn Marino		}
282*f8fb3368SJohn Marino		WRITE_STRUCT($2,$3)
283*f8fb3368SJohn Marino	}
284*f8fb3368SJohn Marino
285*f8fb3368SJohn Marino	return (1);
286*f8fb3368SJohn Marino}
287*f8fb3368SJohn Marino
288*f8fb3368SJohn Marinostatic int
289*f8fb3368SJohn Marino_libelf_cvt_$1$3_tom(unsigned char *dst, size_t dsz, unsigned char *src,
290*f8fb3368SJohn Marino    size_t count, int byteswap)
291*f8fb3368SJohn Marino{
292*f8fb3368SJohn Marino	Elf$3_$2	t, *d;
293*f8fb3368SJohn Marino	unsigned char	*s,*s0;
294*f8fb3368SJohn Marino	size_t		fsz;
295*f8fb3368SJohn Marino
296*f8fb3368SJohn Marino	fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
297*f8fb3368SJohn Marino	d   = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
298*f8fb3368SJohn Marino	s0  = src + (count - 1) * fsz;
299*f8fb3368SJohn Marino
300*f8fb3368SJohn Marino	if (dsz < count * sizeof(Elf$3_$2))
301*f8fb3368SJohn Marino		return (0);
302*f8fb3368SJohn Marino
303*f8fb3368SJohn Marino	while (count--) {
304*f8fb3368SJohn Marino		s = s0;
305*f8fb3368SJohn Marino		READ_STRUCT($2,$3)
306*f8fb3368SJohn Marino		if (byteswap) {
307*f8fb3368SJohn Marino			SWAP_STRUCT($2,$3)
308*f8fb3368SJohn Marino		}
309*f8fb3368SJohn Marino		*d-- = t; s0 -= fsz;
310*f8fb3368SJohn Marino	}
311*f8fb3368SJohn Marino
312*f8fb3368SJohn Marino	return (1);
313*f8fb3368SJohn Marino}
314*f8fb3368SJohn Marino')')
315*f8fb3368SJohn Marino
316*f8fb3368SJohn Marino# MAKE_TYPE_CONVERTER(ELFTYPE,CTYPE)
317*f8fb3368SJohn Marino#
318*f8fb3368SJohn Marino# Make type convertor functions from the type definition
319*f8fb3368SJohn Marino# of the ELF type:
320*f8fb3368SJohn Marino# - Skip convertors marked as `NOFUNC'.
321*f8fb3368SJohn Marino# - Invoke `MAKEPRIMFUNCS' or `MAKECOMPFUNCS' as appropriate.
322*f8fb3368SJohn Marinodefine(`MAKE_TYPE_CONVERTER',
323*f8fb3368SJohn Marino  `ifdef(`NOFUNC_'$1,`',
324*f8fb3368SJohn Marino    `ifdef(`PRIM_'$1,
325*f8fb3368SJohn Marino      `ifdef(`SIZEDEP_'$1,
326*f8fb3368SJohn Marino	`MAKEPRIMFUNCS($1,$2,32,32)dnl
327*f8fb3368SJohn Marino	 MAKEPRIMFUNCS($1,$2,64,64)',
328*f8fb3368SJohn Marino	`MAKEPRIMFUNCS($1,$2,64)')',
329*f8fb3368SJohn Marino      `MAKECOMPFUNCS($1,$2,32)dnl
330*f8fb3368SJohn Marino       MAKECOMPFUNCS($1,$2,64)')')')
331*f8fb3368SJohn Marino
332*f8fb3368SJohn Marino# MAKE_TYPE_CONVERTERS(ELFTYPELIST) -- Generate conversion functions.
333*f8fb3368SJohn Marinodefine(`MAKE_TYPE_CONVERTERS',
334*f8fb3368SJohn Marino  `ifelse($#,1,`',
335*f8fb3368SJohn Marino    `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
336*f8fb3368SJohn Marino
337*f8fb3368SJohn Marino
338*f8fb3368SJohn Marino#
339*f8fb3368SJohn Marino# Macros to generate entries for the table of convertors.
340*f8fb3368SJohn Marino#
341*f8fb3368SJohn Marino
342*f8fb3368SJohn Marino# CONV(ELFTYPE,SIZE,DIRECTION)
343*f8fb3368SJohn Marino#
344*f8fb3368SJohn Marino# Generate the name of a convertor function.
345*f8fb3368SJohn Marinodefine(`CONV',
346*f8fb3368SJohn Marino  `ifdef(`NOFUNC_'$1$2,
347*f8fb3368SJohn Marino    `.$3$2 = NULL',
348*f8fb3368SJohn Marino    `ifdef(`PRIM_'$1,
349*f8fb3368SJohn Marino      `ifdef(`SIZEDEP_'$1,
350*f8fb3368SJohn Marino	`.$3$2 = _libelf_cvt_$1$2_$3',
351*f8fb3368SJohn Marino	`.$3$2 = _libelf_cvt_$1_$3')',
352*f8fb3368SJohn Marino      `.$3$2 = _libelf_cvt_$1$2_$3')')')
353*f8fb3368SJohn Marino
354*f8fb3368SJohn Marino# CONVERTER_NAME(ELFTYPE)
355*f8fb3368SJohn Marino#
356*f8fb3368SJohn Marino# Generate the contents of one `struct cvt' instance.
357*f8fb3368SJohn Marinodefine(`CONVERTER_NAME',
358*f8fb3368SJohn Marino  `ifdef(`NOCVT_'$1,`',
359*f8fb3368SJohn Marino    `	[ELF_T_$1] = {
360*f8fb3368SJohn Marino		CONV($1,32,tof),
361*f8fb3368SJohn Marino		CONV($1,32,tom),
362*f8fb3368SJohn Marino		CONV($1,64,tof),
363*f8fb3368SJohn Marino		CONV($1,64,tom)
364*f8fb3368SJohn Marino	},
365*f8fb3368SJohn Marino
366*f8fb3368SJohn Marino')')
367*f8fb3368SJohn Marino
368*f8fb3368SJohn Marino# CONVERTER_NAMES(ELFTYPELIST)
369*f8fb3368SJohn Marino#
370*f8fb3368SJohn Marino# Generate the `struct cvt[]' array.
371*f8fb3368SJohn Marinodefine(`CONVERTER_NAMES',
372*f8fb3368SJohn Marino  `ifelse($#,1,`',
373*f8fb3368SJohn Marino    `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
374*f8fb3368SJohn Marino
375*f8fb3368SJohn Marino#
376*f8fb3368SJohn Marino# Handling ELF version sections.
377*f8fb3368SJohn Marino#
378*f8fb3368SJohn Marino
379*f8fb3368SJohn Marino# _FSZ(FIELD,BASETYPE) - return the file size for a field.
380*f8fb3368SJohn Marinodefine(`_FSZ',
381*f8fb3368SJohn Marino  `ifelse($2,`HALF',2,
382*f8fb3368SJohn Marino     $2,`WORD',4)')
383*f8fb3368SJohn Marino
384*f8fb3368SJohn Marino# FSZ(STRUCT) - determine the file size of a structure.
385*f8fb3368SJohn Marinodefine(`FSZ',
386*f8fb3368SJohn Marino  `ifelse($#,1,0,
387*f8fb3368SJohn Marino    `eval(_FSZ($1) + FSZ(shift($@)))')')
388*f8fb3368SJohn Marino
389*f8fb3368SJohn Marino# MAKE_VERSION_CONVERTERS(TYPE,BASE,AUX,PFX) -- Generate conversion
390*f8fb3368SJohn Marino# functions for versioning structures.
391*f8fb3368SJohn Marinodefine(`MAKE_VERSION_CONVERTERS',
392*f8fb3368SJohn Marino  `MAKE_VERSION_CONVERTER($1,$2,$3,$4,32)
393*f8fb3368SJohn Marino   MAKE_VERSION_CONVERTER($1,$2,$3,$4,64)')
394*f8fb3368SJohn Marino
395*f8fb3368SJohn Marino# MAKE_VERSION_CONVERTOR(TYPE,CBASE,CAUX,PFX,SIZE) -- Generate a
396*f8fb3368SJohn Marino# conversion function.
397*f8fb3368SJohn Marinodefine(`MAKE_VERSION_CONVERTER',`
398*f8fb3368SJohn Marinostatic int
399*f8fb3368SJohn Marino_libelf_cvt_$1$5_tof(unsigned char *dst, size_t dsz, unsigned char *src,
400*f8fb3368SJohn Marino    size_t count, int byteswap)
401*f8fb3368SJohn Marino{
402*f8fb3368SJohn Marino	Elf$5_$2	t;
403*f8fb3368SJohn Marino	Elf$5_$3	a;
404*f8fb3368SJohn Marino	const size_t	verfsz = FSZ(Elf$5_$2_DEF);
405*f8fb3368SJohn Marino	const size_t	auxfsz = FSZ(Elf$5_$3_DEF);
406*f8fb3368SJohn Marino	const size_t	vermsz = sizeof(Elf$5_$2);
407*f8fb3368SJohn Marino	const size_t	auxmsz = sizeof(Elf$5_$3);
408*f8fb3368SJohn Marino	unsigned char * const dstend = dst + dsz;
409*f8fb3368SJohn Marino	unsigned char * const srcend = src + count;
410*f8fb3368SJohn Marino	unsigned char	*dtmp, *dstaux, *srcaux;
411*f8fb3368SJohn Marino	Elf$5_Word	aux, anext, cnt, vnext;
412*f8fb3368SJohn Marino
413*f8fb3368SJohn Marino	for (dtmp = dst, vnext = ~0U;
414*f8fb3368SJohn Marino	     vnext != 0 && dtmp + verfsz <= dstend && src + vermsz <= srcend;
415*f8fb3368SJohn Marino	     dtmp += vnext, src += vnext) {
416*f8fb3368SJohn Marino
417*f8fb3368SJohn Marino		/* Read in an Elf$5_$2 structure. */
418*f8fb3368SJohn Marino		t = *((Elf$5_$2 *) (uintptr_t) src);
419*f8fb3368SJohn Marino
420*f8fb3368SJohn Marino		aux = t.$4_aux;
421*f8fb3368SJohn Marino		cnt = t.$4_cnt;
422*f8fb3368SJohn Marino		vnext = t.$4_next;
423*f8fb3368SJohn Marino
424*f8fb3368SJohn Marino		if (byteswap) {
425*f8fb3368SJohn Marino			SWAP_STRUCT($2, $5)
426*f8fb3368SJohn Marino		}
427*f8fb3368SJohn Marino
428*f8fb3368SJohn Marino		dst = dtmp;
429*f8fb3368SJohn Marino		WRITE_STRUCT($2, $5)
430*f8fb3368SJohn Marino
431*f8fb3368SJohn Marino		if (aux < verfsz)
432*f8fb3368SJohn Marino			return (0);
433*f8fb3368SJohn Marino
434*f8fb3368SJohn Marino		/* Process AUX entries. */
435*f8fb3368SJohn Marino		for (anext = ~0U, dstaux = dtmp + aux, srcaux = src + aux;
436*f8fb3368SJohn Marino		     cnt != 0 && anext != 0 && dstaux + auxfsz <= dstend &&
437*f8fb3368SJohn Marino			srcaux + auxmsz <= srcend;
438*f8fb3368SJohn Marino		     dstaux += anext, srcaux += anext, cnt--) {
439*f8fb3368SJohn Marino
440*f8fb3368SJohn Marino			/* Read in an Elf$5_$3 structure. */
441*f8fb3368SJohn Marino			a = *((Elf$5_$3 *) (uintptr_t) srcaux);
442*f8fb3368SJohn Marino			anext = a.$4a_next;
443*f8fb3368SJohn Marino
444*f8fb3368SJohn Marino			if (byteswap) {
445*f8fb3368SJohn Marino				pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
446*f8fb3368SJohn Marino			}
447*f8fb3368SJohn Marino
448*f8fb3368SJohn Marino			dst = dstaux;
449*f8fb3368SJohn Marino			pushdef(`t',`a')WRITE_STRUCT($3, $5)popdef(`t')
450*f8fb3368SJohn Marino		}
451*f8fb3368SJohn Marino
452*f8fb3368SJohn Marino		if (anext || cnt)
453*f8fb3368SJohn Marino			return (0);
454*f8fb3368SJohn Marino	}
455*f8fb3368SJohn Marino
456*f8fb3368SJohn Marino	if (vnext)
457*f8fb3368SJohn Marino		return (0);
458*f8fb3368SJohn Marino
459*f8fb3368SJohn Marino	return (1);
460*f8fb3368SJohn Marino}
461*f8fb3368SJohn Marino
462*f8fb3368SJohn Marinostatic int
463*f8fb3368SJohn Marino_libelf_cvt_$1$5_tom(unsigned char *dst, size_t dsz, unsigned char *src,
464*f8fb3368SJohn Marino    size_t count, int byteswap)
465*f8fb3368SJohn Marino{
466*f8fb3368SJohn Marino	Elf$5_$2	t, *dp;
467*f8fb3368SJohn Marino	Elf$5_$3	a, *ap;
468*f8fb3368SJohn Marino	const size_t	verfsz = FSZ(Elf$5_$2_DEF);
469*f8fb3368SJohn Marino	const size_t	auxfsz = FSZ(Elf$5_$3_DEF);
470*f8fb3368SJohn Marino	const size_t	vermsz = sizeof(Elf$5_$2);
471*f8fb3368SJohn Marino	const size_t	auxmsz = sizeof(Elf$5_$3);
472*f8fb3368SJohn Marino	unsigned char * const dstend = dst + dsz;
473*f8fb3368SJohn Marino	unsigned char * const srcend = src + count;
474*f8fb3368SJohn Marino	unsigned char	*dstaux, *s, *srcaux, *stmp;
475*f8fb3368SJohn Marino	Elf$5_Word	aux, anext, cnt, vnext;
476*f8fb3368SJohn Marino
477*f8fb3368SJohn Marino	for (stmp = src, vnext = ~0U;
478*f8fb3368SJohn Marino	     vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
479*f8fb3368SJohn Marino	     stmp += vnext, dst += vnext) {
480*f8fb3368SJohn Marino
481*f8fb3368SJohn Marino		/* Read in a $1 structure. */
482*f8fb3368SJohn Marino		s = stmp;
483*f8fb3368SJohn Marino		READ_STRUCT($2, $5)
484*f8fb3368SJohn Marino		if (byteswap) {
485*f8fb3368SJohn Marino			SWAP_STRUCT($2, $5)
486*f8fb3368SJohn Marino		}
487*f8fb3368SJohn Marino
488*f8fb3368SJohn Marino		dp = (Elf$5_$2 *) (uintptr_t) dst;
489*f8fb3368SJohn Marino		*dp = t;
490*f8fb3368SJohn Marino
491*f8fb3368SJohn Marino		aux = t.$4_aux;
492*f8fb3368SJohn Marino		cnt = t.$4_cnt;
493*f8fb3368SJohn Marino		vnext = t.$4_next;
494*f8fb3368SJohn Marino
495*f8fb3368SJohn Marino		if (aux < vermsz)
496*f8fb3368SJohn Marino			return (0);
497*f8fb3368SJohn Marino
498*f8fb3368SJohn Marino		/* Process AUX entries. */
499*f8fb3368SJohn Marino		for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux;
500*f8fb3368SJohn Marino		     cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
501*f8fb3368SJohn Marino			srcaux + auxfsz <= srcend;
502*f8fb3368SJohn Marino		     dstaux += anext, srcaux += anext, cnt--) {
503*f8fb3368SJohn Marino
504*f8fb3368SJohn Marino			s = srcaux;
505*f8fb3368SJohn Marino			pushdef(`t',`a')READ_STRUCT($3, $5)popdef(`t')
506*f8fb3368SJohn Marino
507*f8fb3368SJohn Marino			if (byteswap) {
508*f8fb3368SJohn Marino				pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
509*f8fb3368SJohn Marino			}
510*f8fb3368SJohn Marino
511*f8fb3368SJohn Marino			anext = a.$4a_next;
512*f8fb3368SJohn Marino
513*f8fb3368SJohn Marino			ap = ((Elf$5_$3 *) (uintptr_t) dstaux);
514*f8fb3368SJohn Marino			*ap = a;
515*f8fb3368SJohn Marino		}
516*f8fb3368SJohn Marino
517*f8fb3368SJohn Marino		if (anext || cnt)
518*f8fb3368SJohn Marino			return (0);
519*f8fb3368SJohn Marino	}
520*f8fb3368SJohn Marino
521*f8fb3368SJohn Marino	if (vnext)
522*f8fb3368SJohn Marino		return (0);
523*f8fb3368SJohn Marino
524*f8fb3368SJohn Marino	return (1);
525*f8fb3368SJohn Marino}')
526*f8fb3368SJohn Marino
527*f8fb3368SJohn Marinodivert(0)
528*f8fb3368SJohn Marino
529*f8fb3368SJohn Marino/*
530*f8fb3368SJohn Marino * C macros to byte swap integral quantities.
531*f8fb3368SJohn Marino */
532*f8fb3368SJohn Marino
533*f8fb3368SJohn Marino#define	SWAP_BYTE(X)	do { (void) (X); } while (0)
534*f8fb3368SJohn Marino#define	SWAP_IDENT(X)	do { (void) (X); } while (0)
535*f8fb3368SJohn Marino#define	SWAP_HALF(X)	do {						\
536*f8fb3368SJohn Marino		uint16_t _x = (uint16_t) (X);				\
537*f8fb3368SJohn Marino		uint32_t _t = _x & 0xFFU;				\
538*f8fb3368SJohn Marino		_t <<= 8U; _x >>= 8U; _t |= _x & 0xFFU;			\
539*f8fb3368SJohn Marino		(X) = (uint16_t) _t;					\
540*f8fb3368SJohn Marino	} while (0)
541*f8fb3368SJohn Marino#define	_SWAP_WORD(X, T) do {						\
542*f8fb3368SJohn Marino		uint32_t _x = (uint32_t) (X);				\
543*f8fb3368SJohn Marino		uint32_t _t = _x & 0xFF;				\
544*f8fb3368SJohn Marino		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
545*f8fb3368SJohn Marino		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
546*f8fb3368SJohn Marino		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
547*f8fb3368SJohn Marino		(X) = (T) _t;						\
548*f8fb3368SJohn Marino	} while (0)
549*f8fb3368SJohn Marino#define	SWAP_ADDR32(X)	_SWAP_WORD(X, Elf32_Addr)
550*f8fb3368SJohn Marino#define	SWAP_OFF32(X)	_SWAP_WORD(X, Elf32_Off)
551*f8fb3368SJohn Marino#define	SWAP_SWORD(X)	_SWAP_WORD(X, Elf32_Sword)
552*f8fb3368SJohn Marino#define	SWAP_WORD(X)	_SWAP_WORD(X, Elf32_Word)
553*f8fb3368SJohn Marino#define	_SWAP_WORD64(X, T) do {						\
554*f8fb3368SJohn Marino		uint64_t _x = (uint64_t) (X);				\
555*f8fb3368SJohn Marino		uint64_t _t = _x & 0xFF;				\
556*f8fb3368SJohn Marino		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
557*f8fb3368SJohn Marino		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
558*f8fb3368SJohn Marino		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
559*f8fb3368SJohn Marino		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
560*f8fb3368SJohn Marino		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
561*f8fb3368SJohn Marino		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
562*f8fb3368SJohn Marino		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
563*f8fb3368SJohn Marino		(X) = (T) _t;						\
564*f8fb3368SJohn Marino	} while (0)
565*f8fb3368SJohn Marino#define	SWAP_ADDR64(X)	_SWAP_WORD64(X, Elf64_Addr)
566*f8fb3368SJohn Marino#define	SWAP_LWORD(X)	_SWAP_WORD64(X, Elf64_Lword)
567*f8fb3368SJohn Marino#define	SWAP_OFF64(X)	_SWAP_WORD64(X, Elf64_Off)
568*f8fb3368SJohn Marino#define	SWAP_SXWORD(X)	_SWAP_WORD64(X, Elf64_Sxword)
569*f8fb3368SJohn Marino#define	SWAP_XWORD(X)	_SWAP_WORD64(X, Elf64_Xword)
570*f8fb3368SJohn Marino
571*f8fb3368SJohn Marino/*
572*f8fb3368SJohn Marino * C macros to write out various integral values.
573*f8fb3368SJohn Marino *
574*f8fb3368SJohn Marino * Note:
575*f8fb3368SJohn Marino * - The destination pointer could be unaligned.
576*f8fb3368SJohn Marino * - Values are written out in native byte order.
577*f8fb3368SJohn Marino * - The destination pointer is incremented after the write.
578*f8fb3368SJohn Marino */
579*f8fb3368SJohn Marino#define	WRITE_BYTE(P,X) do {						\
580*f8fb3368SJohn Marino		unsigned char *const _p = (unsigned char *) (P);	\
581*f8fb3368SJohn Marino		_p[0]		= (unsigned char) (X);			\
582*f8fb3368SJohn Marino		(P)		= _p + 1;				\
583*f8fb3368SJohn Marino	} while (0)
584*f8fb3368SJohn Marino#define	WRITE_HALF(P,X)	do {						\
585*f8fb3368SJohn Marino		uint16_t _t	= (X);					\
586*f8fb3368SJohn Marino		unsigned char *const _p	= (unsigned char *) (P);	\
587*f8fb3368SJohn Marino		const unsigned char *const _q = (unsigned char *) &_t;	\
588*f8fb3368SJohn Marino		_p[0]		= _q[0];				\
589*f8fb3368SJohn Marino		_p[1]		= _q[1];				\
590*f8fb3368SJohn Marino		(P)		= _p + 2;				\
591*f8fb3368SJohn Marino	} while (0)
592*f8fb3368SJohn Marino#define	WRITE_WORD(P,X) do {						\
593*f8fb3368SJohn Marino		uint32_t _t	= (uint32_t) (X);			\
594*f8fb3368SJohn Marino		unsigned char *const _p	= (unsigned char *) (P);	\
595*f8fb3368SJohn Marino		const unsigned char *const _q = (unsigned char *) &_t;	\
596*f8fb3368SJohn Marino		_p[0]		= _q[0];				\
597*f8fb3368SJohn Marino		_p[1]		= _q[1];				\
598*f8fb3368SJohn Marino		_p[2]		= _q[2];				\
599*f8fb3368SJohn Marino		_p[3]		= _q[3];				\
600*f8fb3368SJohn Marino		(P)		= _p + 4;				\
601*f8fb3368SJohn Marino	} while (0)
602*f8fb3368SJohn Marino#define	WRITE_ADDR32(P,X)	WRITE_WORD(P,X)
603*f8fb3368SJohn Marino#define	WRITE_OFF32(P,X)	WRITE_WORD(P,X)
604*f8fb3368SJohn Marino#define	WRITE_SWORD(P,X)	WRITE_WORD(P,X)
605*f8fb3368SJohn Marino#define	WRITE_WORD64(P,X)	do {					\
606*f8fb3368SJohn Marino		uint64_t _t	= (uint64_t) (X);			\
607*f8fb3368SJohn Marino		unsigned char *const _p	= (unsigned char *) (P);	\
608*f8fb3368SJohn Marino		const unsigned char *const _q = (unsigned char *) &_t;	\
609*f8fb3368SJohn Marino		_p[0]		= _q[0];				\
610*f8fb3368SJohn Marino		_p[1]		= _q[1];				\
611*f8fb3368SJohn Marino		_p[2]		= _q[2];				\
612*f8fb3368SJohn Marino		_p[3]		= _q[3];				\
613*f8fb3368SJohn Marino		_p[4]		= _q[4];				\
614*f8fb3368SJohn Marino		_p[5]		= _q[5];				\
615*f8fb3368SJohn Marino		_p[6]		= _q[6];				\
616*f8fb3368SJohn Marino		_p[7]		= _q[7];				\
617*f8fb3368SJohn Marino		(P)		= _p + 8;				\
618*f8fb3368SJohn Marino	} while (0)
619*f8fb3368SJohn Marino#define	WRITE_ADDR64(P,X)	WRITE_WORD64(P,X)
620*f8fb3368SJohn Marino#define	WRITE_LWORD(P,X)	WRITE_WORD64(P,X)
621*f8fb3368SJohn Marino#define	WRITE_OFF64(P,X)	WRITE_WORD64(P,X)
622*f8fb3368SJohn Marino#define	WRITE_SXWORD(P,X)	WRITE_WORD64(P,X)
623*f8fb3368SJohn Marino#define	WRITE_XWORD(P,X)	WRITE_WORD64(P,X)
624*f8fb3368SJohn Marino#define	WRITE_IDENT(P,X)	do {					\
625*f8fb3368SJohn Marino		(void) memcpy((P), (X), sizeof((X)));			\
626*f8fb3368SJohn Marino		(P)		= (P) + EI_NIDENT;			\
627*f8fb3368SJohn Marino	} while (0)
628*f8fb3368SJohn Marino
629*f8fb3368SJohn Marino/*
630*f8fb3368SJohn Marino * C macros to read in various integral values.
631*f8fb3368SJohn Marino *
632*f8fb3368SJohn Marino * Note:
633*f8fb3368SJohn Marino * - The source pointer could be unaligned.
634*f8fb3368SJohn Marino * - Values are read in native byte order.
635*f8fb3368SJohn Marino * - The source pointer is incremented appropriately.
636*f8fb3368SJohn Marino */
637*f8fb3368SJohn Marino
638*f8fb3368SJohn Marino#define	READ_BYTE(P,X)	do {						\
639*f8fb3368SJohn Marino		const unsigned char *const _p =				\
640*f8fb3368SJohn Marino			(const unsigned char *) (P);			\
641*f8fb3368SJohn Marino		(X)		= _p[0];				\
642*f8fb3368SJohn Marino		(P)		= (P) + 1;				\
643*f8fb3368SJohn Marino	} while (0)
644*f8fb3368SJohn Marino#define	READ_HALF(P,X)	do {						\
645*f8fb3368SJohn Marino		uint16_t _t;						\
646*f8fb3368SJohn Marino		unsigned char *const _q = (unsigned char *) &_t;	\
647*f8fb3368SJohn Marino		const unsigned char *const _p =				\
648*f8fb3368SJohn Marino			(const unsigned char *) (P);			\
649*f8fb3368SJohn Marino		_q[0]		= _p[0];				\
650*f8fb3368SJohn Marino		_q[1]		= _p[1];				\
651*f8fb3368SJohn Marino		(P)		= (P) + 2;				\
652*f8fb3368SJohn Marino		(X)		= _t;					\
653*f8fb3368SJohn Marino	} while (0)
654*f8fb3368SJohn Marino#define	_READ_WORD(P,X,T) do {						\
655*f8fb3368SJohn Marino		uint32_t _t;						\
656*f8fb3368SJohn Marino		unsigned char *const _q = (unsigned char *) &_t;	\
657*f8fb3368SJohn Marino		const unsigned char *const _p =				\
658*f8fb3368SJohn Marino			(const unsigned char *) (P);			\
659*f8fb3368SJohn Marino		_q[0]		= _p[0];				\
660*f8fb3368SJohn Marino		_q[1]		= _p[1];				\
661*f8fb3368SJohn Marino		_q[2]		= _p[2];				\
662*f8fb3368SJohn Marino		_q[3]		= _p[3];				\
663*f8fb3368SJohn Marino		(P)		= (P) + 4;				\
664*f8fb3368SJohn Marino		(X)		= (T) _t;				\
665*f8fb3368SJohn Marino	} while (0)
666*f8fb3368SJohn Marino#define	READ_ADDR32(P,X)	_READ_WORD(P, X, Elf32_Addr)
667*f8fb3368SJohn Marino#define	READ_OFF32(P,X)		_READ_WORD(P, X, Elf32_Off)
668*f8fb3368SJohn Marino#define	READ_SWORD(P,X)		_READ_WORD(P, X, Elf32_Sword)
669*f8fb3368SJohn Marino#define	READ_WORD(P,X)		_READ_WORD(P, X, Elf32_Word)
670*f8fb3368SJohn Marino#define	_READ_WORD64(P,X,T)	do {					\
671*f8fb3368SJohn Marino		uint64_t _t;						\
672*f8fb3368SJohn Marino		unsigned char *const _q = (unsigned char *) &_t;	\
673*f8fb3368SJohn Marino		const unsigned char *const _p =				\
674*f8fb3368SJohn Marino			(const unsigned char *) (P);			\
675*f8fb3368SJohn Marino		_q[0]		= _p[0];				\
676*f8fb3368SJohn Marino		_q[1]		= _p[1];				\
677*f8fb3368SJohn Marino		_q[2]		= _p[2];				\
678*f8fb3368SJohn Marino		_q[3]		= _p[3];				\
679*f8fb3368SJohn Marino		_q[4]		= _p[4];				\
680*f8fb3368SJohn Marino		_q[5]		= _p[5];				\
681*f8fb3368SJohn Marino		_q[6]		= _p[6];				\
682*f8fb3368SJohn Marino		_q[7]		= _p[7];				\
683*f8fb3368SJohn Marino		(P)		= (P) + 8;				\
684*f8fb3368SJohn Marino		(X)		= (T) _t;				\
685*f8fb3368SJohn Marino	} while (0)
686*f8fb3368SJohn Marino#define	READ_ADDR64(P,X)	_READ_WORD64(P, X, Elf64_Addr)
687*f8fb3368SJohn Marino#define	READ_LWORD(P,X)		_READ_WORD64(P, X, Elf64_Lword)
688*f8fb3368SJohn Marino#define	READ_OFF64(P,X)		_READ_WORD64(P, X, Elf64_Off)
689*f8fb3368SJohn Marino#define	READ_SXWORD(P,X)	_READ_WORD64(P, X, Elf64_Sxword)
690*f8fb3368SJohn Marino#define	READ_XWORD(P,X)		_READ_WORD64(P, X, Elf64_Xword)
691*f8fb3368SJohn Marino#define	READ_IDENT(P,X)		do {					\
692*f8fb3368SJohn Marino		(void) memcpy((X), (P), sizeof((X)));			\
693*f8fb3368SJohn Marino		(P)		= (P) + EI_NIDENT;			\
694*f8fb3368SJohn Marino	} while (0)
695*f8fb3368SJohn Marino
696*f8fb3368SJohn Marino#define	ROUNDUP2(V,N)	(V) = ((((V) + (N) - 1)) & ~((N) - 1))
697*f8fb3368SJohn Marino
698*f8fb3368SJohn Marino/*[*/
699*f8fb3368SJohn MarinoMAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
700*f8fb3368SJohn MarinoMAKE_VERSION_CONVERTERS(VDEF,Verdef,Verdaux,vd)
701*f8fb3368SJohn MarinoMAKE_VERSION_CONVERTERS(VNEED,Verneed,Vernaux,vn)
702*f8fb3368SJohn Marino/*]*/
703*f8fb3368SJohn Marino
704*f8fb3368SJohn Marino/*
705*f8fb3368SJohn Marino * Sections of type ELF_T_BYTE are never byteswapped, consequently a
706*f8fb3368SJohn Marino * simple memcpy suffices for both directions of conversion.
707*f8fb3368SJohn Marino */
708*f8fb3368SJohn Marino
709*f8fb3368SJohn Marinostatic int
710*f8fb3368SJohn Marino_libelf_cvt_BYTE_tox(unsigned char *dst, size_t dsz, unsigned char *src,
711*f8fb3368SJohn Marino    size_t count, int byteswap)
712*f8fb3368SJohn Marino{
713*f8fb3368SJohn Marino	(void) byteswap;
714*f8fb3368SJohn Marino	if (dsz < count)
715*f8fb3368SJohn Marino		return (0);
716*f8fb3368SJohn Marino	if (dst != src)
717*f8fb3368SJohn Marino		(void) memcpy(dst, src, count);
718*f8fb3368SJohn Marino	return (1);
719*f8fb3368SJohn Marino}
720*f8fb3368SJohn Marino
721*f8fb3368SJohn Marino/*
722*f8fb3368SJohn Marino * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit
723*f8fb3368SJohn Marino * words.  Bloom filter data comes next, followed by hash buckets and the
724*f8fb3368SJohn Marino * hash chain.
725*f8fb3368SJohn Marino *
726*f8fb3368SJohn Marino * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit
727*f8fb3368SJohn Marino * wide on ELFCLASS32 objects.  The other objects in this section are 32
728*f8fb3368SJohn Marino * bits wide.
729*f8fb3368SJohn Marino *
730*f8fb3368SJohn Marino * Argument `srcsz' denotes the number of bytes to be converted.  In the
731*f8fb3368SJohn Marino * 32-bit case we need to translate `srcsz' to a count of 32-bit words.
732*f8fb3368SJohn Marino */
733*f8fb3368SJohn Marino
734*f8fb3368SJohn Marinostatic int
735*f8fb3368SJohn Marino_libelf_cvt_GNUHASH32_tom(unsigned char *dst, size_t dsz, unsigned char *src,
736*f8fb3368SJohn Marino    size_t srcsz, int byteswap)
737*f8fb3368SJohn Marino{
738*f8fb3368SJohn Marino	return (_libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t),
739*f8fb3368SJohn Marino		byteswap));
740*f8fb3368SJohn Marino}
741*f8fb3368SJohn Marino
742*f8fb3368SJohn Marinostatic int
743*f8fb3368SJohn Marino_libelf_cvt_GNUHASH32_tof(unsigned char *dst, size_t dsz, unsigned char *src,
744*f8fb3368SJohn Marino    size_t srcsz, int byteswap)
745*f8fb3368SJohn Marino{
746*f8fb3368SJohn Marino	return (_libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t),
747*f8fb3368SJohn Marino		byteswap));
748*f8fb3368SJohn Marino}
749*f8fb3368SJohn Marino
750*f8fb3368SJohn Marinostatic int
751*f8fb3368SJohn Marino_libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
752*f8fb3368SJohn Marino    size_t srcsz, int byteswap)
753*f8fb3368SJohn Marino{
754*f8fb3368SJohn Marino	size_t sz;
755*f8fb3368SJohn Marino	uint64_t t64, *bloom64;
756*f8fb3368SJohn Marino	Elf_GNU_Hash_Header *gh;
757*f8fb3368SJohn Marino	uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
758*f8fb3368SJohn Marino	uint32_t *buckets, *chains;
759*f8fb3368SJohn Marino
760*f8fb3368SJohn Marino	sz = 4 * sizeof(uint32_t);	/* File header is 4 words long. */
761*f8fb3368SJohn Marino	if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
762*f8fb3368SJohn Marino		return (0);
763*f8fb3368SJohn Marino
764*f8fb3368SJohn Marino	/* Read in the section header and byteswap if needed. */
765*f8fb3368SJohn Marino	READ_WORD(src, nbuckets);
766*f8fb3368SJohn Marino	READ_WORD(src, symndx);
767*f8fb3368SJohn Marino	READ_WORD(src, maskwords);
768*f8fb3368SJohn Marino	READ_WORD(src, shift2);
769*f8fb3368SJohn Marino
770*f8fb3368SJohn Marino	srcsz -= sz;
771*f8fb3368SJohn Marino
772*f8fb3368SJohn Marino	if (byteswap) {
773*f8fb3368SJohn Marino		SWAP_WORD(nbuckets);
774*f8fb3368SJohn Marino		SWAP_WORD(symndx);
775*f8fb3368SJohn Marino		SWAP_WORD(maskwords);
776*f8fb3368SJohn Marino		SWAP_WORD(shift2);
777*f8fb3368SJohn Marino	}
778*f8fb3368SJohn Marino
779*f8fb3368SJohn Marino	/* Check source buffer and destination buffer sizes. */
780*f8fb3368SJohn Marino	sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
781*f8fb3368SJohn Marino	if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
782*f8fb3368SJohn Marino		return (0);
783*f8fb3368SJohn Marino
784*f8fb3368SJohn Marino	gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
785*f8fb3368SJohn Marino	gh->gh_nbuckets  = nbuckets;
786*f8fb3368SJohn Marino	gh->gh_symndx    = symndx;
787*f8fb3368SJohn Marino	gh->gh_maskwords = maskwords;
788*f8fb3368SJohn Marino	gh->gh_shift2    = shift2;
789*f8fb3368SJohn Marino
790*f8fb3368SJohn Marino	dsz -= sizeof(Elf_GNU_Hash_Header);
791*f8fb3368SJohn Marino	dst += sizeof(Elf_GNU_Hash_Header);
792*f8fb3368SJohn Marino
793*f8fb3368SJohn Marino	bloom64 = (uint64_t *) (uintptr_t) dst;
794*f8fb3368SJohn Marino
795*f8fb3368SJohn Marino	/* Copy bloom filter data. */
796*f8fb3368SJohn Marino	for (n = 0; n < maskwords; n++) {
797*f8fb3368SJohn Marino		READ_XWORD(src, t64);
798*f8fb3368SJohn Marino		if (byteswap)
799*f8fb3368SJohn Marino			SWAP_XWORD(t64);
800*f8fb3368SJohn Marino		bloom64[n] = t64;
801*f8fb3368SJohn Marino	}
802*f8fb3368SJohn Marino
803*f8fb3368SJohn Marino	/* The hash buckets follows the bloom filter. */
804*f8fb3368SJohn Marino	dst += maskwords * sizeof(uint64_t);
805*f8fb3368SJohn Marino	buckets = (uint32_t *) (uintptr_t) dst;
806*f8fb3368SJohn Marino
807*f8fb3368SJohn Marino	for (n = 0; n < nbuckets; n++) {
808*f8fb3368SJohn Marino		READ_WORD(src, t32);
809*f8fb3368SJohn Marino		if (byteswap)
810*f8fb3368SJohn Marino			SWAP_WORD(t32);
811*f8fb3368SJohn Marino		buckets[n] = t32;
812*f8fb3368SJohn Marino	}
813*f8fb3368SJohn Marino
814*f8fb3368SJohn Marino	dst += nbuckets * sizeof(uint32_t);
815*f8fb3368SJohn Marino
816*f8fb3368SJohn Marino	/* The hash chain follows the hash buckets. */
817*f8fb3368SJohn Marino	dsz -= sz;
818*f8fb3368SJohn Marino	srcsz -= sz;
819*f8fb3368SJohn Marino
820*f8fb3368SJohn Marino	if (dsz < srcsz)	/* Destination lacks space. */
821*f8fb3368SJohn Marino		return (0);
822*f8fb3368SJohn Marino
823*f8fb3368SJohn Marino	nchains = srcsz / sizeof(uint32_t);
824*f8fb3368SJohn Marino	chains = (uint32_t *) (uintptr_t) dst;
825*f8fb3368SJohn Marino
826*f8fb3368SJohn Marino	for (n = 0; n < nchains; n++) {
827*f8fb3368SJohn Marino		READ_WORD(src, t32);
828*f8fb3368SJohn Marino		if (byteswap)
829*f8fb3368SJohn Marino			SWAP_WORD(t32);
830*f8fb3368SJohn Marino		*chains++ = t32;
831*f8fb3368SJohn Marino	}
832*f8fb3368SJohn Marino
833*f8fb3368SJohn Marino	return (1);
834*f8fb3368SJohn Marino}
835*f8fb3368SJohn Marino
836*f8fb3368SJohn Marinostatic int
837*f8fb3368SJohn Marino_libelf_cvt_GNUHASH64_tof(unsigned char *dst, size_t dsz, unsigned char *src,
838*f8fb3368SJohn Marino    size_t srcsz, int byteswap)
839*f8fb3368SJohn Marino{
840*f8fb3368SJohn Marino	uint32_t *s32;
841*f8fb3368SJohn Marino	size_t sz, hdrsz;
842*f8fb3368SJohn Marino	uint64_t *s64, t64;
843*f8fb3368SJohn Marino	Elf_GNU_Hash_Header *gh;
844*f8fb3368SJohn Marino	uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32;
845*f8fb3368SJohn Marino
846*f8fb3368SJohn Marino	hdrsz = 4 * sizeof(uint32_t);	/* Header is 4x32 bits. */
847*f8fb3368SJohn Marino	if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header))
848*f8fb3368SJohn Marino		return (0);
849*f8fb3368SJohn Marino
850*f8fb3368SJohn Marino	gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
851*f8fb3368SJohn Marino
852*f8fb3368SJohn Marino	t0 = nbuckets = gh->gh_nbuckets;
853*f8fb3368SJohn Marino	t1 = gh->gh_symndx;
854*f8fb3368SJohn Marino	t2 = maskwords = gh->gh_maskwords;
855*f8fb3368SJohn Marino	t3 = gh->gh_shift2;
856*f8fb3368SJohn Marino
857*f8fb3368SJohn Marino	src   += sizeof(Elf_GNU_Hash_Header);
858*f8fb3368SJohn Marino	srcsz -= sizeof(Elf_GNU_Hash_Header);
859*f8fb3368SJohn Marino	dsz   -= hdrsz;
860*f8fb3368SJohn Marino
861*f8fb3368SJohn Marino	sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
862*f8fb3368SJohn Marino	    sizeof(uint64_t);
863*f8fb3368SJohn Marino
864*f8fb3368SJohn Marino	if (srcsz < sz || dsz < sz)
865*f8fb3368SJohn Marino		return (0);
866*f8fb3368SJohn Marino
867*f8fb3368SJohn Marino	/* Write out the header. */
868*f8fb3368SJohn Marino	if (byteswap) {
869*f8fb3368SJohn Marino		SWAP_WORD(t0);
870*f8fb3368SJohn Marino		SWAP_WORD(t1);
871*f8fb3368SJohn Marino		SWAP_WORD(t2);
872*f8fb3368SJohn Marino		SWAP_WORD(t3);
873*f8fb3368SJohn Marino	}
874*f8fb3368SJohn Marino
875*f8fb3368SJohn Marino	WRITE_WORD(dst, t0);
876*f8fb3368SJohn Marino	WRITE_WORD(dst, t1);
877*f8fb3368SJohn Marino	WRITE_WORD(dst, t2);
878*f8fb3368SJohn Marino	WRITE_WORD(dst, t3);
879*f8fb3368SJohn Marino
880*f8fb3368SJohn Marino	/* Copy the bloom filter and the hash table. */
881*f8fb3368SJohn Marino	s64 = (uint64_t *) (uintptr_t) src;
882*f8fb3368SJohn Marino	for (n = 0; n < maskwords; n++) {
883*f8fb3368SJohn Marino		t64 = *s64++;
884*f8fb3368SJohn Marino		if (byteswap)
885*f8fb3368SJohn Marino			SWAP_XWORD(t64);
886*f8fb3368SJohn Marino		WRITE_WORD64(dst, t64);
887*f8fb3368SJohn Marino	}
888*f8fb3368SJohn Marino
889*f8fb3368SJohn Marino	s32 = (uint32_t *) s64;
890*f8fb3368SJohn Marino	for (n = 0; n < nbuckets; n++) {
891*f8fb3368SJohn Marino		t32 = *s32++;
892*f8fb3368SJohn Marino		if (byteswap)
893*f8fb3368SJohn Marino			SWAP_WORD(t32);
894*f8fb3368SJohn Marino		WRITE_WORD(dst, t32);
895*f8fb3368SJohn Marino	}
896*f8fb3368SJohn Marino
897*f8fb3368SJohn Marino	srcsz -= sz;
898*f8fb3368SJohn Marino	dsz   -= sz;
899*f8fb3368SJohn Marino
900*f8fb3368SJohn Marino	/* Copy out the hash chains. */
901*f8fb3368SJohn Marino	if (dsz < srcsz)
902*f8fb3368SJohn Marino		return (0);
903*f8fb3368SJohn Marino
904*f8fb3368SJohn Marino	nchains = srcsz / sizeof(uint32_t);
905*f8fb3368SJohn Marino	for (n = 0; n < nchains; n++) {
906*f8fb3368SJohn Marino		t32 = *s32++;
907*f8fb3368SJohn Marino		if (byteswap)
908*f8fb3368SJohn Marino			SWAP_WORD(t32);
909*f8fb3368SJohn Marino		WRITE_WORD(dst, t32);
910*f8fb3368SJohn Marino	}
911*f8fb3368SJohn Marino
912*f8fb3368SJohn Marino	return (1);
913*f8fb3368SJohn Marino}
914*f8fb3368SJohn Marino
915*f8fb3368SJohn Marino/*
916*f8fb3368SJohn Marino * Elf_Note structures comprise a fixed size header followed by variable
917*f8fb3368SJohn Marino * length strings.  The fixed size header needs to be byte swapped, but
918*f8fb3368SJohn Marino * not the strings.
919*f8fb3368SJohn Marino *
920*f8fb3368SJohn Marino * Argument `count' denotes the total number of bytes to be converted.
921*f8fb3368SJohn Marino * The destination buffer needs to be at least `count' bytes in size.
922*f8fb3368SJohn Marino */
923*f8fb3368SJohn Marinostatic int
924*f8fb3368SJohn Marino_libelf_cvt_NOTE_tom(unsigned char *dst, size_t dsz, unsigned char *src,
925*f8fb3368SJohn Marino    size_t count, int byteswap)
926*f8fb3368SJohn Marino{
927*f8fb3368SJohn Marino	uint32_t namesz, descsz, type;
928*f8fb3368SJohn Marino	Elf_Note *en;
929*f8fb3368SJohn Marino	size_t sz, hdrsz;
930*f8fb3368SJohn Marino
931*f8fb3368SJohn Marino	if (dsz < count)	/* Destination buffer is too small. */
932*f8fb3368SJohn Marino		return (0);
933*f8fb3368SJohn Marino
934*f8fb3368SJohn Marino	hdrsz = 3 * sizeof(uint32_t);
935*f8fb3368SJohn Marino	if (count < hdrsz)		/* Source too small. */
936*f8fb3368SJohn Marino		return (0);
937*f8fb3368SJohn Marino
938*f8fb3368SJohn Marino	if (!byteswap) {
939*f8fb3368SJohn Marino		(void) memcpy(dst, src, count);
940*f8fb3368SJohn Marino		return (1);
941*f8fb3368SJohn Marino	}
942*f8fb3368SJohn Marino
943*f8fb3368SJohn Marino	/* Process all notes in the section. */
944*f8fb3368SJohn Marino	while (count > hdrsz) {
945*f8fb3368SJohn Marino		/* Read the note header. */
946*f8fb3368SJohn Marino		READ_WORD(src, namesz);
947*f8fb3368SJohn Marino		READ_WORD(src, descsz);
948*f8fb3368SJohn Marino		READ_WORD(src, type);
949*f8fb3368SJohn Marino
950*f8fb3368SJohn Marino		/* Translate. */
951*f8fb3368SJohn Marino		SWAP_WORD(namesz);
952*f8fb3368SJohn Marino		SWAP_WORD(descsz);
953*f8fb3368SJohn Marino		SWAP_WORD(type);
954*f8fb3368SJohn Marino
955*f8fb3368SJohn Marino		/* Copy out the translated note header. */
956*f8fb3368SJohn Marino		en = (Elf_Note *) (uintptr_t) dst;
957*f8fb3368SJohn Marino		en->n_namesz = namesz;
958*f8fb3368SJohn Marino		en->n_descsz = descsz;
959*f8fb3368SJohn Marino		en->n_type = type;
960*f8fb3368SJohn Marino
961*f8fb3368SJohn Marino		dsz -= sizeof(Elf_Note);
962*f8fb3368SJohn Marino		dst += sizeof(Elf_Note);
963*f8fb3368SJohn Marino		count -= hdrsz;
964*f8fb3368SJohn Marino
965*f8fb3368SJohn Marino		ROUNDUP2(namesz, 4U);
966*f8fb3368SJohn Marino		ROUNDUP2(descsz, 4U);
967*f8fb3368SJohn Marino
968*f8fb3368SJohn Marino		sz = namesz + descsz;
969*f8fb3368SJohn Marino
970*f8fb3368SJohn Marino		if (count < sz || dsz < sz)	/* Buffers are too small. */
971*f8fb3368SJohn Marino			return (0);
972*f8fb3368SJohn Marino
973*f8fb3368SJohn Marino		(void) memcpy(dst, src, sz);
974*f8fb3368SJohn Marino
975*f8fb3368SJohn Marino		src += sz;
976*f8fb3368SJohn Marino		dst += sz;
977*f8fb3368SJohn Marino
978*f8fb3368SJohn Marino		count -= sz;
979*f8fb3368SJohn Marino		dsz -= sz;
980*f8fb3368SJohn Marino	}
981*f8fb3368SJohn Marino
982*f8fb3368SJohn Marino	return (1);
983*f8fb3368SJohn Marino}
984*f8fb3368SJohn Marino
985*f8fb3368SJohn Marinostatic int
986*f8fb3368SJohn Marino_libelf_cvt_NOTE_tof(unsigned char *dst, size_t dsz, unsigned char *src,
987*f8fb3368SJohn Marino    size_t count, int byteswap)
988*f8fb3368SJohn Marino{
989*f8fb3368SJohn Marino	uint32_t namesz, descsz, type;
990*f8fb3368SJohn Marino	Elf_Note *en;
991*f8fb3368SJohn Marino	size_t sz;
992*f8fb3368SJohn Marino
993*f8fb3368SJohn Marino	if (dsz < count)
994*f8fb3368SJohn Marino		return (0);
995*f8fb3368SJohn Marino
996*f8fb3368SJohn Marino	if (!byteswap) {
997*f8fb3368SJohn Marino		(void) memcpy(dst, src, count);
998*f8fb3368SJohn Marino		return (1);
999*f8fb3368SJohn Marino	}
1000*f8fb3368SJohn Marino
1001*f8fb3368SJohn Marino	while (count > sizeof(Elf_Note)) {
1002*f8fb3368SJohn Marino
1003*f8fb3368SJohn Marino		en = (Elf_Note *) (uintptr_t) src;
1004*f8fb3368SJohn Marino		namesz = en->n_namesz;
1005*f8fb3368SJohn Marino		descsz = en->n_descsz;
1006*f8fb3368SJohn Marino		type = en->n_type;
1007*f8fb3368SJohn Marino
1008*f8fb3368SJohn Marino		sz = namesz;
1009*f8fb3368SJohn Marino		ROUNDUP2(sz, 4U);
1010*f8fb3368SJohn Marino		sz += descsz;
1011*f8fb3368SJohn Marino		ROUNDUP2(sz, 4U);
1012*f8fb3368SJohn Marino
1013*f8fb3368SJohn Marino		SWAP_WORD(namesz);
1014*f8fb3368SJohn Marino		SWAP_WORD(descsz);
1015*f8fb3368SJohn Marino		SWAP_WORD(type);
1016*f8fb3368SJohn Marino
1017*f8fb3368SJohn Marino		WRITE_WORD(dst, namesz);
1018*f8fb3368SJohn Marino		WRITE_WORD(dst, descsz);
1019*f8fb3368SJohn Marino		WRITE_WORD(dst, type);
1020*f8fb3368SJohn Marino
1021*f8fb3368SJohn Marino		src += sizeof(Elf_Note);
1022*f8fb3368SJohn Marino
1023*f8fb3368SJohn Marino		if (count < sz)
1024*f8fb3368SJohn Marino			sz = count;
1025*f8fb3368SJohn Marino
1026*f8fb3368SJohn Marino		(void) memcpy(dst, src, sz);
1027*f8fb3368SJohn Marino
1028*f8fb3368SJohn Marino		src += sz;
1029*f8fb3368SJohn Marino		dst += sz;
1030*f8fb3368SJohn Marino		count -= sz;
1031*f8fb3368SJohn Marino	}
1032*f8fb3368SJohn Marino
1033*f8fb3368SJohn Marino	return (1);
1034*f8fb3368SJohn Marino}
1035*f8fb3368SJohn Marino
1036*f8fb3368SJohn Marinostruct converters {
1037*f8fb3368SJohn Marino	int	(*tof32)(unsigned char *dst, size_t dsz, unsigned char *src,
1038*f8fb3368SJohn Marino		    size_t cnt, int byteswap);
1039*f8fb3368SJohn Marino	int	(*tom32)(unsigned char *dst, size_t dsz, unsigned char *src,
1040*f8fb3368SJohn Marino		    size_t cnt, int byteswap);
1041*f8fb3368SJohn Marino	int	(*tof64)(unsigned char *dst, size_t dsz, unsigned char *src,
1042*f8fb3368SJohn Marino		    size_t cnt, int byteswap);
1043*f8fb3368SJohn Marino	int	(*tom64)(unsigned char *dst, size_t dsz, unsigned char *src,
1044*f8fb3368SJohn Marino		    size_t cnt, int byteswap);
1045*f8fb3368SJohn Marino};
1046*f8fb3368SJohn Marino
1047*f8fb3368SJohn Marino
1048*f8fb3368SJohn Marinostatic struct converters cvt[ELF_T_NUM] = {
1049*f8fb3368SJohn Marino	/*[*/
1050*f8fb3368SJohn MarinoCONVERTER_NAMES(ELF_TYPE_LIST)
1051*f8fb3368SJohn Marino	/*]*/
1052*f8fb3368SJohn Marino
1053*f8fb3368SJohn Marino	/*
1054*f8fb3368SJohn Marino	 * Types that need hand-coded converters follow.
1055*f8fb3368SJohn Marino	 */
1056*f8fb3368SJohn Marino
1057*f8fb3368SJohn Marino	[ELF_T_BYTE] = {
1058*f8fb3368SJohn Marino		.tof32 = _libelf_cvt_BYTE_tox,
1059*f8fb3368SJohn Marino		.tom32 = _libelf_cvt_BYTE_tox,
1060*f8fb3368SJohn Marino		.tof64 = _libelf_cvt_BYTE_tox,
1061*f8fb3368SJohn Marino		.tom64 = _libelf_cvt_BYTE_tox
1062*f8fb3368SJohn Marino	},
1063*f8fb3368SJohn Marino
1064*f8fb3368SJohn Marino	[ELF_T_NOTE] = {
1065*f8fb3368SJohn Marino		.tof32 = _libelf_cvt_NOTE_tof,
1066*f8fb3368SJohn Marino		.tom32 = _libelf_cvt_NOTE_tom,
1067*f8fb3368SJohn Marino		.tof64 = _libelf_cvt_NOTE_tof,
1068*f8fb3368SJohn Marino		.tom64 = _libelf_cvt_NOTE_tom
1069*f8fb3368SJohn Marino	}
1070*f8fb3368SJohn Marino};
1071*f8fb3368SJohn Marino
1072*f8fb3368SJohn Marinoint (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
1073*f8fb3368SJohn Marino (unsigned char *_dst, size_t dsz, unsigned char *_src, size_t _cnt,
1074*f8fb3368SJohn Marino  int _byteswap)
1075*f8fb3368SJohn Marino{
1076*f8fb3368SJohn Marino	assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
1077*f8fb3368SJohn Marino	assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
1078*f8fb3368SJohn Marino
1079*f8fb3368SJohn Marino	if (t >= ELF_T_NUM ||
1080*f8fb3368SJohn Marino	    (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
1081*f8fb3368SJohn Marino	    (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
1082*f8fb3368SJohn Marino		return (NULL);
1083*f8fb3368SJohn Marino
1084*f8fb3368SJohn Marino	return ((elfclass == ELFCLASS32) ?
1085*f8fb3368SJohn Marino	    (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
1086*f8fb3368SJohn Marino	    (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));
1087*f8fb3368SJohn Marino}
1088