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