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