1164190Sjkoshy/*-
2210344Skaiw * Copyright (c) 2006-2008 Joseph Koshy
3164190Sjkoshy * All rights reserved.
4164190Sjkoshy *
5164190Sjkoshy * Redistribution and use in source and binary forms, with or without
6164190Sjkoshy * modification, are permitted provided that the following conditions
7164190Sjkoshy * are met:
8164190Sjkoshy * 1. Redistributions of source code must retain the above copyright
9164190Sjkoshy *    notice, this list of conditions and the following disclaimer.
10164190Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright
11164190Sjkoshy *    notice, this list of conditions and the following disclaimer in the
12164190Sjkoshy *    documentation and/or other materials provided with the distribution.
13164190Sjkoshy *
14164190Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15164190Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16164190Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17164190Sjkoshy * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18164190Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19164190Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20164190Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21164190Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22164190Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23164190Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24164190Sjkoshy * SUCH DAMAGE.
25164190Sjkoshy */
26164190Sjkoshy
27164190Sjkoshy#include <sys/cdefs.h>
28164190Sjkoshy__FBSDID("$FreeBSD: releng/10.2/lib/libelf/libelf_convert.m4 219126 2011-03-01 11:47:51Z brucec $");
29164190Sjkoshy
30164190Sjkoshy#include <sys/types.h>
31164190Sjkoshy#include <sys/elf32.h>
32164190Sjkoshy#include <sys/elf64.h>
33164190Sjkoshy
34164190Sjkoshy#include <assert.h>
35164190Sjkoshy#include <libelf.h>
36165317Sjkoshy#include <osreldate.h>
37164190Sjkoshy#include <string.h>
38164190Sjkoshy
39164190Sjkoshy#include "_libelf.h"
40164190Sjkoshy
41164190Sjkoshy/* WARNING: GENERATED FROM __file__. */
42164190Sjkoshy
43164190Sjkoshy/*
44164190Sjkoshy * Macros to swap various integral quantities.
45164190Sjkoshy */
46164190Sjkoshy
47164190Sjkoshy#define	SWAP_HALF(X) 	do {						\
48164190Sjkoshy		uint16_t _x = (uint16_t) (X);				\
49164190Sjkoshy		uint16_t _t = _x & 0xFF;				\
50164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
51164190Sjkoshy		(X) = _t;						\
52164190Sjkoshy	} while (0)
53164190Sjkoshy#define	SWAP_WORD(X) 	do {						\
54164190Sjkoshy		uint32_t _x = (uint32_t) (X);				\
55164190Sjkoshy		uint32_t _t = _x & 0xFF;				\
56164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
57164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
58164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
59164190Sjkoshy		(X) = _t;						\
60164190Sjkoshy	} while (0)
61164190Sjkoshy#define	SWAP_ADDR32(X)	SWAP_WORD(X)
62164190Sjkoshy#define	SWAP_OFF32(X)	SWAP_WORD(X)
63164190Sjkoshy#define	SWAP_SWORD(X)	SWAP_WORD(X)
64164190Sjkoshy#define	SWAP_WORD64(X)	do {						\
65164190Sjkoshy		uint64_t _x = (uint64_t) (X);				\
66164190Sjkoshy		uint64_t _t = _x & 0xFF;				\
67164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
68164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
69164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
70164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
71164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
72164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
73164190Sjkoshy		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
74164190Sjkoshy		(X) = _t;						\
75164190Sjkoshy	} while (0)
76164190Sjkoshy#define	SWAP_ADDR64(X)	SWAP_WORD64(X)
77164190Sjkoshy#define	SWAP_LWORD(X)	SWAP_WORD64(X)
78164190Sjkoshy#define	SWAP_OFF64(X)	SWAP_WORD64(X)
79164190Sjkoshy#define	SWAP_SXWORD(X)	SWAP_WORD64(X)
80164190Sjkoshy#define	SWAP_XWORD(X)	SWAP_WORD64(X)
81164190Sjkoshy
82164190Sjkoshy/*
83164190Sjkoshy * Write out various integral values.  The destination pointer could
84164190Sjkoshy * be unaligned.  Values are written out in native byte order.  The
85164190Sjkoshy * destination pointer is incremented after the write.
86164190Sjkoshy */
87164190Sjkoshy#define	WRITE_BYTE(P,X) do {						\
88210344Skaiw		char *const _p = (char *) (P);	\
89210344Skaiw		_p[0]		= (char) (X);			\
90164190Sjkoshy		(P)		= _p + 1;				\
91164190Sjkoshy	} while (0)
92164190Sjkoshy#define	WRITE_HALF(P,X)	do {						\
93164190Sjkoshy		uint16_t _t	= (X);					\
94210344Skaiw		char *const _p	= (char *) (P);	\
95210344Skaiw		const char *const _q = (char *) &_t;	\
96164190Sjkoshy		_p[0]		= _q[0];				\
97164190Sjkoshy		_p[1]		= _q[1];				\
98164190Sjkoshy		(P) 		= _p + 2;				\
99164190Sjkoshy	} while (0)
100164190Sjkoshy#define	WRITE_WORD(P,X)	do {						\
101164190Sjkoshy		uint32_t _t	= (X);					\
102210344Skaiw		char *const _p	= (char *) (P);	\
103210344Skaiw		const char *const _q = (char *) &_t;	\
104164190Sjkoshy		_p[0]		= _q[0];				\
105164190Sjkoshy		_p[1]		= _q[1];				\
106164190Sjkoshy		_p[2]		= _q[2];				\
107164190Sjkoshy		_p[3]		= _q[3];				\
108164190Sjkoshy		(P)		= _p + 4;				\
109164190Sjkoshy	} while (0)
110164190Sjkoshy#define	WRITE_ADDR32(P,X)	WRITE_WORD(P,X)
111164190Sjkoshy#define	WRITE_OFF32(P,X)	WRITE_WORD(P,X)
112164190Sjkoshy#define	WRITE_SWORD(P,X)	WRITE_WORD(P,X)
113164190Sjkoshy#define	WRITE_WORD64(P,X)	do {					\
114164190Sjkoshy		uint64_t _t	= (X);					\
115210344Skaiw		char *const _p	= (char *) (P);	\
116210344Skaiw		const char *const _q = (char *) &_t;	\
117164190Sjkoshy		_p[0]		= _q[0];				\
118164190Sjkoshy		_p[1]		= _q[1];				\
119164190Sjkoshy		_p[2]		= _q[2];				\
120164190Sjkoshy		_p[3]		= _q[3];				\
121164190Sjkoshy		_p[4]		= _q[4];				\
122164190Sjkoshy		_p[5]		= _q[5];				\
123164190Sjkoshy		_p[6]		= _q[6];				\
124164190Sjkoshy		_p[7]		= _q[7];				\
125164190Sjkoshy		(P)		= _p + 8;				\
126164190Sjkoshy	} while (0)
127164190Sjkoshy#define	WRITE_ADDR64(P,X)	WRITE_WORD64(P,X)
128164190Sjkoshy#define	WRITE_LWORD(P,X)	WRITE_WORD64(P,X)
129164190Sjkoshy#define	WRITE_OFF64(P,X)	WRITE_WORD64(P,X)
130164190Sjkoshy#define	WRITE_SXWORD(P,X)	WRITE_WORD64(P,X)
131164190Sjkoshy#define	WRITE_XWORD(P,X)	WRITE_WORD64(P,X)
132164190Sjkoshy#define	WRITE_IDENT(P,X)	do {					\
133164190Sjkoshy		(void) memcpy((P), (X), sizeof((X)));			\
134164190Sjkoshy		(P)		= (P) + EI_NIDENT;			\
135164190Sjkoshy	} while (0)
136164190Sjkoshy
137164190Sjkoshy/*
138164190Sjkoshy * Read in various integral values.  The source pointer could be
139219126Sbrucec * unaligned.  Values are read in native byte order.  The source
140164190Sjkoshy * pointer is incremented appropriately.
141164190Sjkoshy */
142164190Sjkoshy
143164190Sjkoshy#define	READ_BYTE(P,X)	do {						\
144210344Skaiw		const char *const _p =				\
145210344Skaiw			(const char *) (P);			\
146164190Sjkoshy		(X)		= _p[0];				\
147164190Sjkoshy		(P)		= (P) + 1;				\
148164190Sjkoshy	} while (0)
149164190Sjkoshy#define	READ_HALF(P,X)	do {						\
150164190Sjkoshy		uint16_t _t;						\
151210344Skaiw		char *const _q = (char *) &_t;	\
152210344Skaiw		const char *const _p =				\
153210344Skaiw			(const char *) (P);			\
154164190Sjkoshy		_q[0]		= _p[0];				\
155164190Sjkoshy		_q[1]		= _p[1];				\
156164190Sjkoshy		(P)		= (P) + 2;				\
157164190Sjkoshy		(X)		= _t;					\
158164190Sjkoshy	} while (0)
159164190Sjkoshy#define	READ_WORD(P,X)	do {						\
160164190Sjkoshy		uint32_t _t;						\
161210344Skaiw		char *const _q = (char *) &_t;	\
162210344Skaiw		const char *const _p =				\
163210344Skaiw			(const char *) (P);			\
164164190Sjkoshy		_q[0]		= _p[0];				\
165164190Sjkoshy		_q[1]		= _p[1];				\
166164190Sjkoshy		_q[2]		= _p[2];				\
167164190Sjkoshy		_q[3]		= _p[3];				\
168164190Sjkoshy		(P)		= (P) + 4;				\
169164190Sjkoshy		(X)		= _t;					\
170164190Sjkoshy	} while (0)
171164190Sjkoshy#define	READ_ADDR32(P,X)	READ_WORD(P,X)
172164190Sjkoshy#define	READ_OFF32(P,X)		READ_WORD(P,X)
173164190Sjkoshy#define	READ_SWORD(P,X)		READ_WORD(P,X)
174164190Sjkoshy#define	READ_WORD64(P,X)	do {					\
175164190Sjkoshy		uint64_t _t;						\
176210344Skaiw		char *const _q = (char *) &_t;	\
177210344Skaiw		const char *const _p =				\
178210344Skaiw			(const char *) (P);			\
179164190Sjkoshy		_q[0]		= _p[0];				\
180164190Sjkoshy		_q[1]		= _p[1];				\
181164190Sjkoshy		_q[2]		= _p[2];				\
182164190Sjkoshy		_q[3]		= _p[3];				\
183164190Sjkoshy		_q[4]		= _p[4];				\
184164190Sjkoshy		_q[5]		= _p[5];				\
185164190Sjkoshy		_q[6]		= _p[6];				\
186164190Sjkoshy		_q[7]		= _p[7];				\
187164190Sjkoshy		(P)		= (P) + 8;				\
188164190Sjkoshy		(X)		= _t;					\
189164190Sjkoshy	} while (0)
190164190Sjkoshy#define	READ_ADDR64(P,X)	READ_WORD64(P,X)
191164190Sjkoshy#define	READ_LWORD(P,X)		READ_WORD64(P,X)
192164190Sjkoshy#define	READ_OFF64(P,X)		READ_WORD64(P,X)
193164190Sjkoshy#define	READ_SXWORD(P,X)	READ_WORD64(P,X)
194164190Sjkoshy#define	READ_XWORD(P,X)		READ_WORD64(P,X)
195164190Sjkoshy#define	READ_IDENT(P,X)		do {					\
196164190Sjkoshy		(void) memcpy((X), (P), sizeof((X)));			\
197164190Sjkoshy		(P)		= (P) + EI_NIDENT;			\
198164190Sjkoshy	} while (0)
199164190Sjkoshy
200164190Sjkoshy#define	ROUNDUP2(V,N)	(V) = ((((V) + (N) - 1)) & ~((N) - 1))
201164190Sjkoshy
202164190Sjkoshydivert(-1)
203164190Sjkoshy
204164190Sjkoshy/*
205164190Sjkoshy * Generate conversion routines for converting between in-memory and
206164190Sjkoshy * file representations of Elf data structures.
207164190Sjkoshy *
208164190Sjkoshy * `In-memory' representations of an Elf data structure use natural
209164190Sjkoshy * alignments and native byte ordering.  This allows arithmetic and
210164190Sjkoshy * casting to work as expected.  On the other hand the `file'
211164190Sjkoshy * representation of an ELF data structure could be packed tighter
212164190Sjkoshy * than its `in-memory' representation, and could be of a differing
213164190Sjkoshy * byte order.  An additional complication is that `ar' only pads data
214164190Sjkoshy * to even addresses and so ELF archive member data being read from
215164190Sjkoshy * inside an `ar' archive could end up at misaligned memory addresses.
216164190Sjkoshy *
217164190Sjkoshy * Consequently, casting the `char *' pointers that point to memory
218164190Sjkoshy * representations (i.e., source pointers for the *_tof() functions
219164190Sjkoshy * and the destination pointers for the *_tom() functions), is safe,
220164190Sjkoshy * as these pointers should be correctly aligned for the memory type
221164190Sjkoshy * already.  However, pointers to file representations have to be
222164190Sjkoshy * treated as being potentially unaligned and no casting can be done.
223164190Sjkoshy */
224164190Sjkoshy
225164190Sjkoshyinclude(SRCDIR`/elf_types.m4')
226164190Sjkoshy
227164190Sjkoshy/*
228164190Sjkoshy * `IGNORE'_* flags turn off generation of template code.
229164190Sjkoshy */
230164190Sjkoshy
231164190Sjkoshydefine(`IGNORE',
232164190Sjkoshy  `define(IGNORE_$1`'32,	1)
233164190Sjkoshy   define(IGNORE_$1`'64,	1)')
234164190Sjkoshy
235164190SjkoshyIGNORE(MOVEP)
236164190SjkoshyIGNORE(NOTE)
237210341SkaiwIGNORE(GNUHASH)
238164190Sjkoshy
239164190Sjkoshydefine(IGNORE_BYTE,		1)	/* 'lator, leave 'em bytes alone */
240210338Skaiwdefine(IGNORE_GNUHASH,		1)
241164190Sjkoshydefine(IGNORE_NOTE,		1)
242164190Sjkoshydefine(IGNORE_SXWORD32,		1)
243164190Sjkoshydefine(IGNORE_XWORD32,		1)
244164190Sjkoshy
245164190Sjkoshy/*
246164190Sjkoshy * `BASE'_XXX flags cause class agnostic template functions
247164190Sjkoshy * to be generated.
248164190Sjkoshy */
249164190Sjkoshy
250164190Sjkoshydefine(`BASE_BYTE',	1)
251164190Sjkoshydefine(`BASE_HALF',	1)
252164190Sjkoshydefine(`BASE_NOTE',	1)
253164190Sjkoshydefine(`BASE_WORD',	1)
254164190Sjkoshydefine(`BASE_LWORD',	1)
255164190Sjkoshydefine(`BASE_SWORD',	1)
256164190Sjkoshydefine(`BASE_XWORD',	1)
257164190Sjkoshydefine(`BASE_SXWORD',	1)
258164190Sjkoshy
259164190Sjkoshy/*
260164190Sjkoshy * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated
261164190Sjkoshy * for each primitive type.
262164190Sjkoshy */
263164190Sjkoshy
264164190Sjkoshydefine(`SIZEDEP_ADDR',	1)
265164190Sjkoshydefine(`SIZEDEP_OFF',	1)
266164190Sjkoshy
267164190Sjkoshy/*
268164190Sjkoshy * `Primitive' ELF types are those that are an alias for an integral
269164190Sjkoshy * type.  They have no internal structure. These can be copied using
270164190Sjkoshy * a `memcpy()', and byteswapped in straightforward way.
271164190Sjkoshy *
272164190Sjkoshy * Macro use:
273164190Sjkoshy * `$1': Name of the ELF type.
274164190Sjkoshy * `$2': C structure name suffix
275164190Sjkoshy * `$3': ELF class specifier for symbols, one of [`', `32', `64']
276164190Sjkoshy * `$4': ELF class specifier for types, one of [`32', `64']
277164190Sjkoshy */
278164190Sjkoshydefine(`MAKEPRIM_TO_F',`
279210338Skaiwstatic int
280210338Skaiwlibelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count,
281210338Skaiw    int byteswap)
282164190Sjkoshy{
283164190Sjkoshy	Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src;
284164190Sjkoshy	size_t c;
285164190Sjkoshy
286210338Skaiw	(void) dsz;
287164190Sjkoshy
288164190Sjkoshy	if (!byteswap) {
289164190Sjkoshy		(void) memcpy(dst, src, count * sizeof(*s));
290210338Skaiw		return (1);
291164190Sjkoshy	}
292164190Sjkoshy
293164190Sjkoshy	for (c = 0; c < count; c++) {
294164190Sjkoshy		t = *s++;
295164190Sjkoshy		SWAP_$1$3(t);
296164190Sjkoshy		WRITE_$1$3(dst,t);
297164190Sjkoshy	}
298210338Skaiw
299210338Skaiw	return (1);
300164190Sjkoshy}
301164190Sjkoshy')
302164190Sjkoshy
303164190Sjkoshydefine(`MAKEPRIM_TO_M',`
304210338Skaiwstatic int
305210338Skaiwlibelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count,
306210338Skaiw    int byteswap)
307164190Sjkoshy{
308164190Sjkoshy	Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst;
309164190Sjkoshy	size_t c;
310164190Sjkoshy
311210338Skaiw	if (dsz < count * sizeof(Elf$4_$2))
312210338Skaiw		return (0);
313164190Sjkoshy
314164190Sjkoshy	if (!byteswap) {
315164190Sjkoshy		(void) memcpy(dst, src, count * sizeof(*d));
316210338Skaiw		return (1);
317164190Sjkoshy	}
318164190Sjkoshy
319164190Sjkoshy	for (c = 0; c < count; c++) {
320164190Sjkoshy		READ_$1$3(src,t);
321164190Sjkoshy		SWAP_$1$3(t);
322164190Sjkoshy		*d++ = t;
323164190Sjkoshy	}
324210338Skaiw
325210338Skaiw	return (1);
326164190Sjkoshy}
327164190Sjkoshy')
328164190Sjkoshy
329164190Sjkoshydefine(`SWAP_FIELD',
330164190Sjkoshy  `ifdef(`IGNORE_'$2,`',
331164190Sjkoshy    `ifelse(BASE_$2,1,
332164190Sjkoshy      `SWAP_$2(t.$1);
333164190Sjkoshy			',
334164190Sjkoshy      `ifelse($2,BYTE,`',
335164190Sjkoshy        `ifelse($2,IDENT,`',
336164190Sjkoshy          `SWAP_$2'SZ()`(t.$1);
337164190Sjkoshy			')')')')')
338164190Sjkoshydefine(`SWAP_MEMBERS',
339164190Sjkoshy  `ifelse($#,1,`/**/',
340164190Sjkoshy     `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
341164190Sjkoshy
342164190Sjkoshydefine(`SWAP_STRUCT',
343164190Sjkoshy  `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
344164190Sjkoshy			SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
345164190Sjkoshy
346164190Sjkoshydefine(`WRITE_FIELD',
347164190Sjkoshy  `ifelse(BASE_$2,1,
348164190Sjkoshy    `WRITE_$2(dst,t.$1);
349164190Sjkoshy		',
350164190Sjkoshy    `ifelse($2,IDENT,
351164190Sjkoshy      `WRITE_$2(dst,t.$1);
352164190Sjkoshy		',
353164190Sjkoshy      `WRITE_$2'SZ()`(dst,t.$1);
354164190Sjkoshy		')')')
355164190Sjkoshydefine(`WRITE_MEMBERS',
356164190Sjkoshy  `ifelse($#,1,`/**/',
357164190Sjkoshy    `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
358164190Sjkoshy
359164190Sjkoshydefine(`WRITE_STRUCT',
360164190Sjkoshy  `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
361164190Sjkoshy		WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
362164190Sjkoshy
363164190Sjkoshydefine(`READ_FIELD',
364164190Sjkoshy  `ifelse(BASE_$2,1,
365164190Sjkoshy    `READ_$2(s,t.$1);
366164190Sjkoshy		',
367164190Sjkoshy    `ifelse($2,IDENT,
368164190Sjkoshy      `READ_$2(s,t.$1);
369164190Sjkoshy		',
370164190Sjkoshy      `READ_$2'SZ()`(s,t.$1);
371164190Sjkoshy		')')')
372164190Sjkoshy
373164190Sjkoshydefine(`READ_MEMBERS',
374164190Sjkoshy  `ifelse($#,1,`/**/',
375164190Sjkoshy    `READ_FIELD($1)READ_MEMBERS(shift($@))')')
376164190Sjkoshy
377164190Sjkoshydefine(`READ_STRUCT',
378164190Sjkoshy  `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
379164190Sjkoshy		READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
380164190Sjkoshy
381164190Sjkoshy/*
382164190Sjkoshy * Converters for non-integral ELF data structures.
383164190Sjkoshy *
384164190Sjkoshy * When converting data to file representation, the source pointer
385164190Sjkoshy * will be naturally aligned for a data structure's in-memory
386164190Sjkoshy * representation.  When converting data to memory, the destination
387164190Sjkoshy * pointer will be similarly aligned.
388164190Sjkoshy *
389164190Sjkoshy * For in-place conversions, when converting to file representations,
390164190Sjkoshy * the source buffer is large enough to hold `file' data.  When
391164190Sjkoshy * converting from file to memory, we need to be careful to work
392164190Sjkoshy * `backwards', to avoid overwriting unconverted data.
393164190Sjkoshy *
394164190Sjkoshy * Macro use:
395164190Sjkoshy * `$1': Name of the ELF type.
396164190Sjkoshy * `$2': C structure name suffix.
397164190Sjkoshy * `$3': ELF class specifier, one of [`', `32', `64']
398164190Sjkoshy */
399164190Sjkoshy
400164190Sjkoshydefine(`MAKE_TO_F',
401164190Sjkoshy  `ifdef(`IGNORE_'$1$3,`',`
402210338Skaiwstatic int
403210338Skaiwlibelf_cvt$3_$1_tof(char *dst, size_t dsz, char *src, size_t count,
404210338Skaiw    int byteswap)
405164190Sjkoshy{
406164190Sjkoshy	Elf$3_$2	t, *s;
407164190Sjkoshy	size_t c;
408164190Sjkoshy
409210338Skaiw	(void) dsz;
410210338Skaiw
411164190Sjkoshy	s = (Elf$3_$2 *) (uintptr_t) src;
412164190Sjkoshy	for (c = 0; c < count; c++) {
413164190Sjkoshy		t = *s++;
414164190Sjkoshy		if (byteswap) {
415164190Sjkoshy			SWAP_STRUCT($2,$3)
416164190Sjkoshy		}
417164190Sjkoshy		WRITE_STRUCT($2,$3)
418164190Sjkoshy	}
419210338Skaiw
420210338Skaiw	return (1);
421164190Sjkoshy}
422164190Sjkoshy')')
423164190Sjkoshy
424164190Sjkoshydefine(`MAKE_TO_M',
425164190Sjkoshy  `ifdef(`IGNORE_'$1$3,`',`
426210338Skaiwstatic int
427210338Skaiwlibelf_cvt$3_$1_tom(char *dst, size_t dsz, char *src, size_t count,
428210338Skaiw    int byteswap)
429164190Sjkoshy{
430164190Sjkoshy	Elf$3_$2	 t, *d;
431210344Skaiw	char		*s,*s0;
432164190Sjkoshy	size_t		fsz;
433164190Sjkoshy
434164190Sjkoshy	fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
435164190Sjkoshy	d   = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
436210344Skaiw	s0  = (char *) src + (count - 1) * fsz;
437164190Sjkoshy
438210338Skaiw	if (dsz < count * sizeof(Elf$3_$2))
439210338Skaiw		return (0);
440210338Skaiw
441164190Sjkoshy	while (count--) {
442164190Sjkoshy		s = s0;
443164190Sjkoshy		READ_STRUCT($2,$3)
444164190Sjkoshy		if (byteswap) {
445164190Sjkoshy			SWAP_STRUCT($2,$3)
446164190Sjkoshy		}
447164190Sjkoshy		*d-- = t; s0 -= fsz;
448164190Sjkoshy	}
449210338Skaiw
450210338Skaiw	return (1);
451164190Sjkoshy}
452164190Sjkoshy')')
453164190Sjkoshy
454164190Sjkoshy/*
455164190Sjkoshy * Make type convertor functions from the type definition
456164190Sjkoshy * of the ELF type:
457164190Sjkoshy * - if the type is a base (i.e., `primitive') type:
458164190Sjkoshy *   - if it is marked as to be ignored (i.e., `IGNORE_'TYPE)
459164190Sjkoshy *     is defined, we skip the code generation step.
460164190Sjkoshy *   - if the type is declared as `SIZEDEP', then 32 and 64 bit
461164190Sjkoshy *     variants of the conversion functions are generated.
462164190Sjkoshy *   - otherwise a 32 bit variant is generated.
463164190Sjkoshy * - if the type is a structure type, we generate 32 and 64 bit
464164190Sjkoshy *   variants of the conversion functions.
465164190Sjkoshy */
466164190Sjkoshy
467164190Sjkoshydefine(`MAKE_TYPE_CONVERTER',
468165317Sjkoshy  `#if	__FreeBSD_version >= $3 /* $1 */
469165317Sjkoshyifdef(`BASE'_$1,
470164190Sjkoshy    `ifdef(`IGNORE_'$1,`',
471164190Sjkoshy      `MAKEPRIM_TO_F($1,$2,`',64)
472164190Sjkoshy       MAKEPRIM_TO_M($1,$2,`',64)')',
473164190Sjkoshy    `ifdef(`SIZEDEP_'$1,
474164190Sjkoshy      `MAKEPRIM_TO_F($1,$2,32,32)dnl
475164190Sjkoshy       MAKEPRIM_TO_M($1,$2,32,32)dnl
476164190Sjkoshy       MAKEPRIM_TO_F($1,$2,64,64)dnl
477164190Sjkoshy       MAKEPRIM_TO_M($1,$2,64,64)',
478164190Sjkoshy      `MAKE_TO_F($1,$2,32)dnl
479164190Sjkoshy       MAKE_TO_F($1,$2,64)dnl
480164190Sjkoshy       MAKE_TO_M($1,$2,32)dnl
481165317Sjkoshy       MAKE_TO_M($1,$2,64)')')
482165317Sjkoshy#endif /* $1 */
483165317Sjkoshy')
484164190Sjkoshy
485164190Sjkoshydefine(`MAKE_TYPE_CONVERTERS',
486164190Sjkoshy  `ifelse($#,1,`',
487164190Sjkoshy    `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
488164190Sjkoshy
489164190Sjkoshydivert(0)
490164190Sjkoshy
491164190Sjkoshy/*
492164190Sjkoshy * Sections of type ELF_T_BYTE are never byteswapped, consequently a
493164190Sjkoshy * simple memcpy suffices for both directions of conversion.
494164190Sjkoshy */
495164190Sjkoshy
496210338Skaiwstatic int
497210338Skaiwlibelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count,
498210338Skaiw    int byteswap)
499164190Sjkoshy{
500164190Sjkoshy	(void) byteswap;
501210338Skaiw	if (dsz < count)
502210338Skaiw		return (0);
503164190Sjkoshy	if (dst != src)
504164190Sjkoshy		(void) memcpy(dst, src, count);
505210338Skaiw	return (1);
506164190Sjkoshy}
507164190Sjkoshy
508210341SkaiwMAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
509210341Skaiw
510210559Skaiw#if	__FreeBSD_version >= 800062
511164190Sjkoshy/*
512210341Skaiw * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit
513210341Skaiw * words.  Bloom filter data comes next, followed by hash buckets and the
514210341Skaiw * hash chain.
515210341Skaiw *
516210341Skaiw * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit
517210341Skaiw * wide on ELFCLASS32 objects.  The other objects in this section are 32
518210341Skaiw * bits wide.
519210341Skaiw *
520210341Skaiw * Argument `srcsz' denotes the number of bytes to be converted.  In the
521210341Skaiw * 32-bit case we need to translate `srcsz' to a count of 32-bit words.
522210341Skaiw */
523210341Skaiw
524210341Skaiwstatic int
525210341Skaiwlibelf_cvt32_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz,
526210341Skaiw    int byteswap)
527210341Skaiw{
528210341Skaiw	return (libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t),
529210341Skaiw	        byteswap));
530210341Skaiw}
531210341Skaiw
532210341Skaiwstatic int
533210341Skaiwlibelf_cvt32_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz,
534210341Skaiw    int byteswap)
535210341Skaiw{
536210341Skaiw	return (libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t),
537210341Skaiw	        byteswap));
538210341Skaiw}
539210341Skaiw
540210341Skaiwstatic int
541210341Skaiwlibelf_cvt64_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz,
542210341Skaiw    int byteswap)
543210341Skaiw{
544210341Skaiw	size_t sz;
545210341Skaiw	uint64_t t64, *bloom64;
546210341Skaiw	Elf_GNU_Hash_Header *gh;
547210341Skaiw	uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
548210341Skaiw	uint32_t *buckets, *chains;
549210341Skaiw
550210341Skaiw	sz = 4 * sizeof(uint32_t);	/* File header is 4 words long. */
551210341Skaiw	if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
552210341Skaiw		return (0);
553210341Skaiw
554210341Skaiw	/* Read in the section header and byteswap if needed. */
555210341Skaiw	READ_WORD(src, nbuckets);
556210341Skaiw	READ_WORD(src, symndx);
557210341Skaiw	READ_WORD(src, maskwords);
558210341Skaiw	READ_WORD(src, shift2);
559210341Skaiw
560210341Skaiw	srcsz -= sz;
561210341Skaiw
562210341Skaiw	if (byteswap) {
563210341Skaiw		SWAP_WORD(nbuckets);
564210341Skaiw		SWAP_WORD(symndx);
565210341Skaiw		SWAP_WORD(maskwords);
566210341Skaiw		SWAP_WORD(shift2);
567210341Skaiw	}
568210341Skaiw
569210341Skaiw	/* Check source buffer and destination buffer sizes. */
570210341Skaiw	sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
571210341Skaiw	if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
572210341Skaiw		return (0);
573210341Skaiw
574210341Skaiw	gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
575210341Skaiw	gh->gh_nbuckets  = nbuckets;
576210341Skaiw	gh->gh_symndx    = symndx;
577210341Skaiw	gh->gh_maskwords = maskwords;
578210341Skaiw	gh->gh_shift2    = shift2;
579210341Skaiw	
580210341Skaiw	dsz -= sizeof(Elf_GNU_Hash_Header);
581210341Skaiw	dst += sizeof(Elf_GNU_Hash_Header);
582210341Skaiw
583210341Skaiw	bloom64 = (uint64_t *) (uintptr_t) dst;
584210341Skaiw
585210341Skaiw	/* Copy bloom filter data. */
586210341Skaiw	for (n = 0; n < maskwords; n++) {
587210341Skaiw		READ_XWORD(src, t64);
588210341Skaiw		if (byteswap)
589210341Skaiw			SWAP_XWORD(t64);
590210341Skaiw		bloom64[n] = t64;
591210341Skaiw	}
592210341Skaiw
593210341Skaiw	/* The hash buckets follows the bloom filter. */
594210341Skaiw	dst += maskwords * sizeof(uint64_t);
595210341Skaiw	buckets = (uint32_t *) (uintptr_t) dst;
596210341Skaiw
597210341Skaiw	for (n = 0; n < nbuckets; n++) {
598210341Skaiw		READ_WORD(src, t32);
599210341Skaiw		if (byteswap)
600210341Skaiw			SWAP_WORD(t32);
601210341Skaiw		buckets[n] = t32;
602210341Skaiw	}
603210341Skaiw
604210341Skaiw	dst += nbuckets * sizeof(uint32_t);
605210341Skaiw
606210341Skaiw	/* The hash chain follows the hash buckets. */
607210341Skaiw	dsz -= sz;
608210341Skaiw	srcsz -= sz;
609210341Skaiw
610210341Skaiw	if (dsz < srcsz)	/* Destination lacks space. */
611210341Skaiw	        return (0);
612210341Skaiw
613210341Skaiw	nchains = srcsz / sizeof(uint32_t);
614210341Skaiw	chains = (uint32_t *) (uintptr_t) dst;
615210341Skaiw
616210341Skaiw	for (n = 0; n < nchains; n++) {
617210341Skaiw		READ_WORD(src, t32);
618210341Skaiw		if (byteswap)
619210341Skaiw			SWAP_WORD(t32);
620210341Skaiw		*chains++ = t32;
621210341Skaiw	}
622210341Skaiw
623210341Skaiw	return (1);
624210341Skaiw}
625210341Skaiw
626210341Skaiwstatic int
627210341Skaiwlibelf_cvt64_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz,
628210341Skaiw    int byteswap)
629210341Skaiw{
630210341Skaiw	uint32_t *s32;
631210341Skaiw	size_t sz, hdrsz;
632210341Skaiw	uint64_t *s64, t64;
633210341Skaiw	Elf_GNU_Hash_Header *gh;
634210341Skaiw	uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32;
635210341Skaiw
636210341Skaiw	hdrsz = 4 * sizeof(uint32_t);	/* Header is 4x32 bits. */
637210341Skaiw	if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header))
638210341Skaiw		return (0);
639210341Skaiw
640210341Skaiw	gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
641210341Skaiw
642210341Skaiw	t0 = nbuckets = gh->gh_nbuckets;
643210341Skaiw	t1 = gh->gh_symndx;
644210341Skaiw	t2 = maskwords = gh->gh_maskwords;
645210341Skaiw	t3 = gh->gh_shift2;
646210341Skaiw
647210341Skaiw	src   += sizeof(Elf_GNU_Hash_Header);
648210341Skaiw	srcsz -= sizeof(Elf_GNU_Hash_Header);
649210341Skaiw	dsz   -= hdrsz;
650210341Skaiw
651210341Skaiw	sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
652210341Skaiw	    sizeof(uint64_t);
653210341Skaiw
654210341Skaiw	if (srcsz < sz || dsz < sz)
655210341Skaiw		return (0);
656210341Skaiw
657210341Skaiw 	/* Write out the header. */
658210341Skaiw	if (byteswap) {
659210341Skaiw		SWAP_WORD(t0);
660210341Skaiw		SWAP_WORD(t1);
661210341Skaiw		SWAP_WORD(t2);
662210341Skaiw		SWAP_WORD(t3);
663210341Skaiw	}
664210341Skaiw
665210341Skaiw	WRITE_WORD(dst, t0);
666210341Skaiw	WRITE_WORD(dst, t1);
667210341Skaiw	WRITE_WORD(dst, t2);
668210341Skaiw	WRITE_WORD(dst, t3);
669210341Skaiw
670210341Skaiw	/* Copy the bloom filter and the hash table. */
671210341Skaiw	s64 = (uint64_t *) (uintptr_t) src;
672210341Skaiw	for (n = 0; n < maskwords; n++) {
673210341Skaiw		t64 = *s64++;
674210341Skaiw		if (byteswap)
675210341Skaiw			SWAP_XWORD(t64);
676210341Skaiw		WRITE_WORD64(dst, t64);
677210341Skaiw	}
678210341Skaiw
679210341Skaiw	s32 = (uint32_t *) s64;
680210341Skaiw	for (n = 0; n < nbuckets; n++) {
681210341Skaiw		t32 = *s32++;
682210341Skaiw		if (byteswap)
683210341Skaiw			SWAP_WORD(t32);
684210341Skaiw		WRITE_WORD(dst, t32);
685210341Skaiw	}
686210341Skaiw
687210341Skaiw	srcsz -= sz;
688210341Skaiw	dsz   -= sz;
689210341Skaiw
690210341Skaiw	/* Copy out the hash chains. */
691210341Skaiw	if (dsz < srcsz)
692210341Skaiw		return (0);
693210341Skaiw
694210341Skaiw	nchains = srcsz / sizeof(uint32_t);
695210341Skaiw	for (n = 0; n < nchains; n++) {
696210341Skaiw		t32 = *s32++;
697210341Skaiw		if (byteswap)
698210341Skaiw			SWAP_WORD(t32);
699210341Skaiw		WRITE_WORD(dst, t32);
700210341Skaiw	}
701210341Skaiw
702210341Skaiw	return (1);
703210341Skaiw}
704210559Skaiw#endif
705210341Skaiw
706210341Skaiw/*
707164190Sjkoshy * Elf_Note structures comprise a fixed size header followed by variable
708164190Sjkoshy * length strings.  The fixed size header needs to be byte swapped, but
709164190Sjkoshy * not the strings.
710164190Sjkoshy *
711164190Sjkoshy * Argument `count' denotes the total number of bytes to be converted.
712210341Skaiw * The destination buffer needs to be at least `count' bytes in size.
713164190Sjkoshy */
714210338Skaiwstatic int
715210338Skaiwlibelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count, 
716210338Skaiw    int byteswap)
717164190Sjkoshy{
718164190Sjkoshy	uint32_t namesz, descsz, type;
719164190Sjkoshy	Elf_Note *en;
720210338Skaiw	size_t sz, hdrsz;
721164190Sjkoshy
722210338Skaiw	if (dsz < count)	/* Destination buffer is too small. */
723210338Skaiw		return (0);
724164190Sjkoshy
725210338Skaiw	hdrsz = 3 * sizeof(uint32_t);
726210338Skaiw	if (count < hdrsz)		/* Source too small. */
727210338Skaiw		return (0);
728210338Skaiw
729164190Sjkoshy	if (!byteswap) {
730164190Sjkoshy		(void) memcpy(dst, src, count);
731210338Skaiw		return (1);
732164190Sjkoshy	}
733164190Sjkoshy
734210338Skaiw	/* Process all notes in the section. */
735210338Skaiw	while (count > hdrsz) {
736210338Skaiw		/* Read the note header. */
737164190Sjkoshy		READ_WORD(src, namesz);
738164190Sjkoshy		READ_WORD(src, descsz);
739164190Sjkoshy		READ_WORD(src, type);
740164190Sjkoshy
741210338Skaiw		/* Translate. */
742210338Skaiw		SWAP_WORD(namesz);
743210338Skaiw		SWAP_WORD(descsz);
744210338Skaiw		SWAP_WORD(type);
745164190Sjkoshy
746210338Skaiw		/* Copy out the translated note header. */
747164190Sjkoshy		en = (Elf_Note *) (uintptr_t) dst;
748164190Sjkoshy		en->n_namesz = namesz;
749164190Sjkoshy		en->n_descsz = descsz;
750164190Sjkoshy		en->n_type = type;
751164190Sjkoshy
752210338Skaiw		dsz -= sizeof(Elf_Note);
753164190Sjkoshy		dst += sizeof(Elf_Note);
754210338Skaiw		count -= hdrsz;
755164190Sjkoshy
756164190Sjkoshy		ROUNDUP2(namesz, 4);
757164190Sjkoshy		ROUNDUP2(descsz, 4);
758164190Sjkoshy
759164190Sjkoshy		sz = namesz + descsz;
760164190Sjkoshy
761210338Skaiw		if (count < sz || dsz < sz)	/* Buffers are too small. */
762210338Skaiw			return (0);
763164190Sjkoshy
764164190Sjkoshy		(void) memcpy(dst, src, sz);
765164190Sjkoshy
766164190Sjkoshy		src += sz;
767164190Sjkoshy		dst += sz;
768210338Skaiw
769164190Sjkoshy		count -= sz;
770210341Skaiw		dsz -= sz;
771164190Sjkoshy	}
772210338Skaiw
773210338Skaiw	return (1);
774164190Sjkoshy}
775164190Sjkoshy
776210338Skaiwstatic int
777210338Skaiwlibelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count,
778210338Skaiw    int byteswap)
779164190Sjkoshy{
780164190Sjkoshy	uint32_t namesz, descsz, type;
781164190Sjkoshy	Elf_Note *en;
782164190Sjkoshy	size_t sz;
783164190Sjkoshy
784210338Skaiw	if (dsz < count)
785210338Skaiw		return (0);
786164190Sjkoshy
787164190Sjkoshy	if (!byteswap) {
788164190Sjkoshy		(void) memcpy(dst, src, count);
789210338Skaiw		return (1);
790164190Sjkoshy	}
791164190Sjkoshy
792164190Sjkoshy	while (count > sizeof(Elf_Note)) {
793164190Sjkoshy
794164190Sjkoshy		en = (Elf_Note *) (uintptr_t) src;
795164190Sjkoshy		namesz = en->n_namesz;
796164190Sjkoshy		descsz = en->n_descsz;
797164190Sjkoshy		type = en->n_type;
798164190Sjkoshy
799210338Skaiw		SWAP_WORD(namesz);
800210338Skaiw		SWAP_WORD(descsz);
801210338Skaiw		SWAP_WORD(type);
802164190Sjkoshy
803164190Sjkoshy		WRITE_WORD(dst, namesz);
804164190Sjkoshy		WRITE_WORD(dst, descsz);
805164190Sjkoshy		WRITE_WORD(dst, type);
806164190Sjkoshy
807164190Sjkoshy		src += sizeof(Elf_Note);
808164190Sjkoshy
809164190Sjkoshy		ROUNDUP2(namesz, 4);
810164190Sjkoshy		ROUNDUP2(descsz, 4);
811164190Sjkoshy
812164190Sjkoshy		sz = namesz + descsz;
813164190Sjkoshy
814164190Sjkoshy		if (count < sz)
815164190Sjkoshy			sz = count;
816164190Sjkoshy
817164190Sjkoshy		(void) memcpy(dst, src, sz);
818164190Sjkoshy
819164190Sjkoshy		src += sz;
820164190Sjkoshy		dst += sz;
821164190Sjkoshy		count -= sz;
822164190Sjkoshy	}
823210338Skaiw
824210338Skaiw	return (1);
825164190Sjkoshy}
826164190Sjkoshy
827164190Sjkoshystruct converters {
828210338Skaiw	int	(*tof32)(char *dst, size_t dsz, char *src, size_t cnt,
829210338Skaiw		    int byteswap);
830210338Skaiw	int	(*tom32)(char *dst, size_t dsz, char *src, size_t cnt,
831210338Skaiw		    int byteswap);
832210338Skaiw	int	(*tof64)(char *dst, size_t dsz, char *src, size_t cnt,
833210338Skaiw		    int byteswap);
834210338Skaiw	int	(*tom64)(char *dst, size_t dsz, char *src, size_t cnt,
835210338Skaiw		    int byteswap);
836164190Sjkoshy};
837164190Sjkoshy
838164190Sjkoshydivert(-1)
839164190Sjkoshydefine(`CONV',
840164190Sjkoshy  `ifdef(`IGNORE_'$1$2,
841164190Sjkoshy    `.$3$2 = NULL',
842164190Sjkoshy    `ifdef(`BASE_'$1,
843172099Sjkoshy      `.$3$2 = libelf_cvt_$1_$3',
844164190Sjkoshy      `ifdef(`SIZEDEP_'$1,
845164190Sjkoshy        `.$3$2 = libelf_cvt_$1$2_$3',
846164190Sjkoshy        `.$3$2 = libelf_cvt$2_$1_$3')')')')
847164190Sjkoshy
848164190Sjkoshydefine(`CONVERTER_NAME',
849172099Sjkoshy  `ifdef(`IGNORE_'$1,`',
850172099Sjkoshy    `#if	__FreeBSD_version >= $3
851165317Sjkoshy    [ELF_T_$1] = {
852164190Sjkoshy        CONV($1,32,tof), CONV($1,32,tom),
853164190Sjkoshy        CONV($1,64,tof), CONV($1,64,tom) },
854165317Sjkoshy#endif
855164190Sjkoshy')')
856164190Sjkoshy
857164190Sjkoshydefine(`CONVERTER_NAMES',
858164190Sjkoshy  `ifelse($#,1,`',
859164190Sjkoshy    `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
860164190Sjkoshy
861164190Sjkoshyundefine(`IGNORE_BYTE32', `IGNORE_BYTE64')
862164190Sjkoshydivert(0)
863164190Sjkoshy
864164190Sjkoshystatic struct converters cvt[ELF_T_NUM] = {
865164190SjkoshyCONVERTER_NAMES(ELF_TYPE_LIST)
866164190Sjkoshy
867164190Sjkoshy	/*
868164190Sjkoshy	 * Types that needs hand-coded converters follow.
869164190Sjkoshy	 */
870164190Sjkoshy
871164190Sjkoshy	[ELF_T_BYTE] = {
872164190Sjkoshy		.tof32 = libelf_cvt_BYTE_tox,
873164190Sjkoshy		.tom32 = libelf_cvt_BYTE_tox,
874164190Sjkoshy		.tof64 = libelf_cvt_BYTE_tox,
875164190Sjkoshy		.tom64 = libelf_cvt_BYTE_tox
876164190Sjkoshy	},
877210341Skaiw
878210559Skaiw#if	__FreeBSD_version >= 800062
879210341Skaiw	[ELF_T_GNUHASH] = {
880210341Skaiw		.tof32 = libelf_cvt32_GNUHASH_tof,
881210341Skaiw		.tom32 = libelf_cvt32_GNUHASH_tom,
882210341Skaiw		.tof64 = libelf_cvt64_GNUHASH_tof,
883210341Skaiw		.tom64 = libelf_cvt64_GNUHASH_tom
884210341Skaiw	},
885210559Skaiw#endif
886210341Skaiw
887164190Sjkoshy	[ELF_T_NOTE] = {
888164190Sjkoshy		.tof32 = libelf_cvt_NOTE_tof,
889164190Sjkoshy		.tom32 = libelf_cvt_NOTE_tom,
890164190Sjkoshy		.tof64 = libelf_cvt_NOTE_tof,
891164190Sjkoshy		.tom64 = libelf_cvt_NOTE_tom
892164190Sjkoshy	}
893164190Sjkoshy};
894164190Sjkoshy
895210338Skaiwint (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
896210338Skaiw (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap)
897164190Sjkoshy{
898164190Sjkoshy	assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
899164190Sjkoshy	assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
900164190Sjkoshy
901164190Sjkoshy	if (t >= ELF_T_NUM ||
902164190Sjkoshy	    (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
903164190Sjkoshy	    (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
904164190Sjkoshy		return (NULL);
905164190Sjkoshy
906164190Sjkoshy	return ((elfclass == ELFCLASS32) ?
907164190Sjkoshy	    (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
908164190Sjkoshy	    (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));
909164190Sjkoshy}
910