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