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