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