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