14484Sbinkertn@umich.edu/*-
24484Sbinkertn@umich.edu * Copyright (c) 2006 Joseph Koshy
34484Sbinkertn@umich.edu * All rights reserved.
44484Sbinkertn@umich.edu *
54484Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without
64484Sbinkertn@umich.edu * modification, are permitted provided that the following conditions
74484Sbinkertn@umich.edu * are met:
84484Sbinkertn@umich.edu * 1. Redistributions of source code must retain the above copyright
94484Sbinkertn@umich.edu *    notice, this list of conditions and the following disclaimer.
104484Sbinkertn@umich.edu * 2. Redistributions in binary form must reproduce the above copyright
114484Sbinkertn@umich.edu *    notice, this list of conditions and the following disclaimer in the
124484Sbinkertn@umich.edu *    documentation and/or other materials provided with the distribution.
134484Sbinkertn@umich.edu *
144484Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
154484Sbinkertn@umich.edu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
164484Sbinkertn@umich.edu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
174484Sbinkertn@umich.edu * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
184484Sbinkertn@umich.edu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
194484Sbinkertn@umich.edu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
204484Sbinkertn@umich.edu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
214484Sbinkertn@umich.edu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
224484Sbinkertn@umich.edu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
234484Sbinkertn@umich.edu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
244484Sbinkertn@umich.edu * SUCH DAMAGE.
254484Sbinkertn@umich.edu */
264484Sbinkertn@umich.edu
274484Sbinkertn@umich.edu#include <sys/types.h>
284484Sbinkertn@umich.edu
294484Sbinkertn@umich.edu#include <assert.h>
304484Sbinkertn@umich.edu#include <string.h>
314484Sbinkertn@umich.edu
324484Sbinkertn@umich.edu#include "elf32.h"
334484Sbinkertn@umich.edu#include "elf64.h"
344484Sbinkertn@umich.edu#include "libelf.h"
354484Sbinkertn@umich.edu#include "_libelf.h"
364484Sbinkertn@umich.edu
374484Sbinkertn@umich.edu/* WARNING: GENERATED FROM __file__. */
384484Sbinkertn@umich.edu
394484Sbinkertn@umich.edu/*
404484Sbinkertn@umich.edu * Macros to swap various integral quantities.
414484Sbinkertn@umich.edu */
424484Sbinkertn@umich.edu
434484Sbinkertn@umich.edu#define	SWAP_HALF(X) 	do {						\
444484Sbinkertn@umich.edu		uint16_t _x = (uint16_t) (X);				\
454484Sbinkertn@umich.edu		uint16_t _t = _x & 0xFF;				\
464484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
474484Sbinkertn@umich.edu		(X) = _t;						\
484484Sbinkertn@umich.edu	} while (0)
494484Sbinkertn@umich.edu#define	SWAP_WORD(X) 	do {						\
504484Sbinkertn@umich.edu		uint32_t _x = (uint32_t) (X);				\
514484Sbinkertn@umich.edu		uint32_t _t = _x & 0xFF;				\
524484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
534484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
544484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
554484Sbinkertn@umich.edu		(X) = _t;						\
564484Sbinkertn@umich.edu	} while (0)
574484Sbinkertn@umich.edu#define	SWAP_ADDR32(X)	SWAP_WORD(X)
584484Sbinkertn@umich.edu#define	SWAP_OFF32(X)	SWAP_WORD(X)
594484Sbinkertn@umich.edu#define	SWAP_SWORD(X)	SWAP_WORD(X)
604484Sbinkertn@umich.edu#define	SWAP_WORD64(X)	do {						\
614484Sbinkertn@umich.edu		uint64_t _x = (uint64_t) (X);				\
624484Sbinkertn@umich.edu		uint64_t _t = _x & 0xFF;				\
634484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
644484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
654484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
664484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
674484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
684484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
694484Sbinkertn@umich.edu		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
704484Sbinkertn@umich.edu		(X) = _t;						\
714484Sbinkertn@umich.edu	} while (0)
724484Sbinkertn@umich.edu#define	SWAP_ADDR64(X)	SWAP_WORD64(X)
734484Sbinkertn@umich.edu#define	SWAP_LWORD(X)	SWAP_WORD64(X)
744484Sbinkertn@umich.edu#define	SWAP_OFF64(X)	SWAP_WORD64(X)
754484Sbinkertn@umich.edu#define	SWAP_SXWORD(X)	SWAP_WORD64(X)
764484Sbinkertn@umich.edu#define	SWAP_XWORD(X)	SWAP_WORD64(X)
774484Sbinkertn@umich.edu
784484Sbinkertn@umich.edu/*
794484Sbinkertn@umich.edu * Write out various integral values.  The destination pointer could
804484Sbinkertn@umich.edu * be unaligned.  Values are written out in native byte order.  The
814484Sbinkertn@umich.edu * destination pointer is incremented after the write.
824484Sbinkertn@umich.edu */
834484Sbinkertn@umich.edu#define	WRITE_BYTE(P,X) do {						\
844484Sbinkertn@umich.edu		unsigned char *const _p = (unsigned char *) (P);	\
854484Sbinkertn@umich.edu		_p[0]		= (unsigned char) (X);			\
864484Sbinkertn@umich.edu		(P)		= _p + 1;				\
874484Sbinkertn@umich.edu	} while (0)
884484Sbinkertn@umich.edu#define	WRITE_HALF(P,X)	do {						\
894484Sbinkertn@umich.edu		uint16_t _t	= (X);					\
904484Sbinkertn@umich.edu		unsigned char *const _p	= (unsigned char *) (P);	\
914484Sbinkertn@umich.edu		unsigned const char *const _q = (unsigned char *) &_t;	\
924484Sbinkertn@umich.edu		_p[0]		= _q[0];				\
934484Sbinkertn@umich.edu		_p[1]		= _q[1];				\
944484Sbinkertn@umich.edu		(P) 		= _p + 2;				\
954484Sbinkertn@umich.edu	} while (0)
964484Sbinkertn@umich.edu#define	WRITE_WORD(P,X)	do {						\
974484Sbinkertn@umich.edu		uint32_t _t	= (X);					\
984484Sbinkertn@umich.edu		unsigned char *const _p	= (unsigned char *) (P);	\
994484Sbinkertn@umich.edu		unsigned const char *const _q = (unsigned char *) &_t;	\
1004484Sbinkertn@umich.edu		_p[0]		= _q[0];				\
1014484Sbinkertn@umich.edu		_p[1]		= _q[1];				\
1024484Sbinkertn@umich.edu		_p[2]		= _q[2];				\
1034484Sbinkertn@umich.edu		_p[3]		= _q[3];				\
1044484Sbinkertn@umich.edu		(P)		= _p + 4;				\
1054484Sbinkertn@umich.edu	} while (0)
1064484Sbinkertn@umich.edu#define	WRITE_ADDR32(P,X)	WRITE_WORD(P,X)
1074484Sbinkertn@umich.edu#define	WRITE_OFF32(P,X)	WRITE_WORD(P,X)
1084484Sbinkertn@umich.edu#define	WRITE_SWORD(P,X)	WRITE_WORD(P,X)
1094484Sbinkertn@umich.edu#define	WRITE_WORD64(P,X)	do {					\
1104484Sbinkertn@umich.edu		uint64_t _t	= (X);					\
1114484Sbinkertn@umich.edu		unsigned char *const _p	= (unsigned char *) (P);	\
1124484Sbinkertn@umich.edu		unsigned const char *const _q = (unsigned char *) &_t;	\
1134484Sbinkertn@umich.edu		_p[0]		= _q[0];				\
1144484Sbinkertn@umich.edu		_p[1]		= _q[1];				\
1154484Sbinkertn@umich.edu		_p[2]		= _q[2];				\
1164484Sbinkertn@umich.edu		_p[3]		= _q[3];				\
1174484Sbinkertn@umich.edu		_p[4]		= _q[4];				\
1184484Sbinkertn@umich.edu		_p[5]		= _q[5];				\
1194484Sbinkertn@umich.edu		_p[6]		= _q[6];				\
1204484Sbinkertn@umich.edu		_p[7]		= _q[7];				\
1214484Sbinkertn@umich.edu		(P)		= _p + 8;				\
1224484Sbinkertn@umich.edu	} while (0)
1234484Sbinkertn@umich.edu#define	WRITE_ADDR64(P,X)	WRITE_WORD64(P,X)
1244484Sbinkertn@umich.edu#define	WRITE_LWORD(P,X)	WRITE_WORD64(P,X)
1254484Sbinkertn@umich.edu#define	WRITE_OFF64(P,X)	WRITE_WORD64(P,X)
1264484Sbinkertn@umich.edu#define	WRITE_SXWORD(P,X)	WRITE_WORD64(P,X)
1274484Sbinkertn@umich.edu#define	WRITE_XWORD(P,X)	WRITE_WORD64(P,X)
1284484Sbinkertn@umich.edu#define	WRITE_IDENT(P,X)	do {					\
1294484Sbinkertn@umich.edu		(void) memcpy((P), (X), sizeof((X)));			\
1304484Sbinkertn@umich.edu		(P)		= (P) + EI_NIDENT;			\
1314484Sbinkertn@umich.edu	} while (0)
1324484Sbinkertn@umich.edu
1334484Sbinkertn@umich.edu/*
1344484Sbinkertn@umich.edu * Read in various integral values.  The source pointer could be
1354484Sbinkertn@umich.edu * unaligned.  Values are read in in native byte order.  The source
1364484Sbinkertn@umich.edu * pointer is incremented appropriately.
1374484Sbinkertn@umich.edu */
1384484Sbinkertn@umich.edu
1394484Sbinkertn@umich.edu#define	READ_BYTE(P,X)	do {						\
1404484Sbinkertn@umich.edu		const unsigned char *const _p =				\
1414484Sbinkertn@umich.edu			(const unsigned char *) (P);			\
1424484Sbinkertn@umich.edu		(X)		= _p[0];				\
1434484Sbinkertn@umich.edu		(P)		= (P) + 1;				\
1444484Sbinkertn@umich.edu	} while (0)
1454484Sbinkertn@umich.edu#define	READ_HALF(P,X)	do {						\
1464484Sbinkertn@umich.edu		uint16_t _t;						\
1474484Sbinkertn@umich.edu		unsigned char *const _q = (unsigned char *) &_t;	\
1484484Sbinkertn@umich.edu		const unsigned char *const _p =				\
1494484Sbinkertn@umich.edu			(const unsigned char *) (P);			\
1504484Sbinkertn@umich.edu		_q[0]		= _p[0];				\
1514484Sbinkertn@umich.edu		_q[1]		= _p[1];				\
1524484Sbinkertn@umich.edu		(P)		= (P) + 2;				\
1534484Sbinkertn@umich.edu		(X)		= _t;					\
1544484Sbinkertn@umich.edu	} while (0)
1554484Sbinkertn@umich.edu#define	READ_WORD(P,X)	do {						\
1564484Sbinkertn@umich.edu		uint32_t _t;						\
1574484Sbinkertn@umich.edu		unsigned char *const _q = (unsigned char *) &_t;	\
1584484Sbinkertn@umich.edu		const unsigned char *const _p =				\
1594484Sbinkertn@umich.edu			(const unsigned char *) (P);			\
1604484Sbinkertn@umich.edu		_q[0]		= _p[0];				\
1614484Sbinkertn@umich.edu		_q[1]		= _p[1];				\
1624484Sbinkertn@umich.edu		_q[2]		= _p[2];				\
1634484Sbinkertn@umich.edu		_q[3]		= _p[3];				\
1644484Sbinkertn@umich.edu		(P)		= (P) + 4;				\
1654484Sbinkertn@umich.edu		(X)		= _t;					\
1664484Sbinkertn@umich.edu	} while (0)
1674484Sbinkertn@umich.edu#define	READ_ADDR32(P,X)	READ_WORD(P,X)
1684484Sbinkertn@umich.edu#define	READ_OFF32(P,X)		READ_WORD(P,X)
1694484Sbinkertn@umich.edu#define	READ_SWORD(P,X)		READ_WORD(P,X)
1704484Sbinkertn@umich.edu#define	READ_WORD64(P,X)	do {					\
1714484Sbinkertn@umich.edu		uint64_t _t;						\
1724484Sbinkertn@umich.edu		unsigned char *const _q = (unsigned char *) &_t;	\
1734484Sbinkertn@umich.edu		const unsigned char *const _p =				\
1744484Sbinkertn@umich.edu			(const unsigned char *) (P);			\
1754484Sbinkertn@umich.edu		_q[0]		= _p[0];				\
1764484Sbinkertn@umich.edu		_q[1]		= _p[1];				\
1774484Sbinkertn@umich.edu		_q[2]		= _p[2];				\
1784484Sbinkertn@umich.edu		_q[3]		= _p[3];				\
1794484Sbinkertn@umich.edu		_q[4]		= _p[4];				\
1804484Sbinkertn@umich.edu		_q[5]		= _p[5];				\
1814484Sbinkertn@umich.edu		_q[6]		= _p[6];				\
1824484Sbinkertn@umich.edu		_q[7]		= _p[7];				\
1834484Sbinkertn@umich.edu		(P)		= (P) + 8;				\
1844484Sbinkertn@umich.edu		(X)		= _t;					\
1854484Sbinkertn@umich.edu	} while (0)
1864484Sbinkertn@umich.edu#define	READ_ADDR64(P,X)	READ_WORD64(P,X)
1874484Sbinkertn@umich.edu#define	READ_LWORD(P,X)		READ_WORD64(P,X)
1884484Sbinkertn@umich.edu#define	READ_OFF64(P,X)		READ_WORD64(P,X)
1894484Sbinkertn@umich.edu#define	READ_SXWORD(P,X)	READ_WORD64(P,X)
1904484Sbinkertn@umich.edu#define	READ_XWORD(P,X)		READ_WORD64(P,X)
1914484Sbinkertn@umich.edu#define	READ_IDENT(P,X)		do {					\
1924484Sbinkertn@umich.edu		(void) memcpy((X), (P), sizeof((X)));			\
1934484Sbinkertn@umich.edu		(P)		= (P) + EI_NIDENT;			\
1944484Sbinkertn@umich.edu	} while (0)
1954484Sbinkertn@umich.edu
1964484Sbinkertn@umich.edu#define	ROUNDUP2(V,N)	(V) = ((((V) + (N) - 1)) & ~((N) - 1))
1974484Sbinkertn@umich.edu
1984484Sbinkertn@umich.edudivert(-1)
1994484Sbinkertn@umich.edu
2004484Sbinkertn@umich.edu/*
2014484Sbinkertn@umich.edu * Generate conversion routines for converting between in-memory and
2024484Sbinkertn@umich.edu * file representations of Elf data structures.
2034484Sbinkertn@umich.edu *
2044484Sbinkertn@umich.edu * `In-memory' representations of an Elf data structure use natural
2054484Sbinkertn@umich.edu * alignments and native byte ordering.  This allows arithmetic and
2064484Sbinkertn@umich.edu * casting to work as expected.  On the other hand the `file'
2074484Sbinkertn@umich.edu * representation of an ELF data structure could be packed tighter
2084484Sbinkertn@umich.edu * than its `in-memory' representation, and could be of a differing
2094484Sbinkertn@umich.edu * byte order.  An additional complication is that `ar' only pads data
2104484Sbinkertn@umich.edu * to even addresses and so ELF archive member data being read from
2114484Sbinkertn@umich.edu * inside an `ar' archive could end up at misaligned memory addresses.
2124484Sbinkertn@umich.edu *
2134484Sbinkertn@umich.edu * Consequently, casting the `char *' pointers that point to memory
2144484Sbinkertn@umich.edu * representations (i.e., source pointers for the *_tof() functions
2154484Sbinkertn@umich.edu * and the destination pointers for the *_tom() functions), is safe,
2164484Sbinkertn@umich.edu * as these pointers should be correctly aligned for the memory type
2174484Sbinkertn@umich.edu * already.  However, pointers to file representations have to be
2184484Sbinkertn@umich.edu * treated as being potentially unaligned and no casting can be done.
2194484Sbinkertn@umich.edu */
2204484Sbinkertn@umich.edu
2214484Sbinkertn@umich.eduinclude(SRCDIR`/elf_types.m4')
2224484Sbinkertn@umich.edu
2234484Sbinkertn@umich.edu/*
2244484Sbinkertn@umich.edu * `IGNORE'_* flags turn off generation of template code.
2254484Sbinkertn@umich.edu */
2264484Sbinkertn@umich.edu
2274484Sbinkertn@umich.edudefine(`IGNORE',
2284484Sbinkertn@umich.edu  `define(IGNORE_$1`'32,	1)
2294484Sbinkertn@umich.edu   define(IGNORE_$1`'64,	1)')
2304484Sbinkertn@umich.edu
2314484Sbinkertn@umich.eduIGNORE(MOVEP)
2324484Sbinkertn@umich.eduIGNORE(NOTE)
2334484Sbinkertn@umich.edu
2344484Sbinkertn@umich.edudefine(IGNORE_BYTE,		1)	/* 'lator, leave 'em bytes alone */
2354484Sbinkertn@umich.edudefine(IGNORE_NOTE,		1)
2364484Sbinkertn@umich.edudefine(IGNORE_SXWORD32,		1)
2374484Sbinkertn@umich.edudefine(IGNORE_XWORD32,		1)
2384484Sbinkertn@umich.edu
2394484Sbinkertn@umich.edu/*
2404484Sbinkertn@umich.edu * `BASE'_XXX flags cause class agnostic template functions
2414484Sbinkertn@umich.edu * to be generated.
2424484Sbinkertn@umich.edu */
2434484Sbinkertn@umich.edu
2444484Sbinkertn@umich.edudefine(`BASE_BYTE',	1)
2454484Sbinkertn@umich.edudefine(`BASE_HALF',	1)
2464484Sbinkertn@umich.edudefine(`BASE_NOTE',	1)
2474484Sbinkertn@umich.edudefine(`BASE_WORD',	1)
2484484Sbinkertn@umich.edudefine(`BASE_LWORD',	1)
2494484Sbinkertn@umich.edudefine(`BASE_SWORD',	1)
2504484Sbinkertn@umich.edudefine(`BASE_XWORD',	1)
2514484Sbinkertn@umich.edudefine(`BASE_SXWORD',	1)
2524484Sbinkertn@umich.edu
2534484Sbinkertn@umich.edu/*
2544484Sbinkertn@umich.edu * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated
2554484Sbinkertn@umich.edu * for each primitive type.
2564484Sbinkertn@umich.edu */
2574484Sbinkertn@umich.edu
2584484Sbinkertn@umich.edudefine(`SIZEDEP_ADDR',	1)
2594484Sbinkertn@umich.edudefine(`SIZEDEP_OFF',	1)
2604484Sbinkertn@umich.edu
2614484Sbinkertn@umich.edu/*
2624484Sbinkertn@umich.edu * `Primitive' ELF types are those that are an alias for an integral
2634484Sbinkertn@umich.edu * type.  They have no internal structure. These can be copied using
2644484Sbinkertn@umich.edu * a `memcpy()', and byteswapped in straightforward way.
2654484Sbinkertn@umich.edu *
2664484Sbinkertn@umich.edu * Macro use:
2674484Sbinkertn@umich.edu * `$1': Name of the ELF type.
2684484Sbinkertn@umich.edu * `$2': C structure name suffix
2694484Sbinkertn@umich.edu * `$3': ELF class specifier for symbols, one of [`', `32', `64']
2704484Sbinkertn@umich.edu * `$4': ELF class specifier for types, one of [`32', `64']
2714484Sbinkertn@umich.edu */
2724484Sbinkertn@umich.edudefine(`MAKEPRIM_TO_F',`
2734484Sbinkertn@umich.edustatic void
2744484Sbinkertn@umich.edulibelf_cvt_$1$3_tof(char *dst, char *src, size_t count, int byteswap)
2754484Sbinkertn@umich.edu{
2764484Sbinkertn@umich.edu	Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src;
2774484Sbinkertn@umich.edu	size_t c;
2784484Sbinkertn@umich.edu
2794484Sbinkertn@umich.edu	if (dst == src && !byteswap)
2804484Sbinkertn@umich.edu		return;
2814484Sbinkertn@umich.edu
2824484Sbinkertn@umich.edu	if (!byteswap) {
2834484Sbinkertn@umich.edu		(void) memcpy(dst, src, count * sizeof(*s));
2844484Sbinkertn@umich.edu		return;
2854484Sbinkertn@umich.edu	}
2864484Sbinkertn@umich.edu
2874484Sbinkertn@umich.edu	for (c = 0; c < count; c++) {
2884484Sbinkertn@umich.edu		t = *s++;
2894484Sbinkertn@umich.edu		SWAP_$1$3(t);
2904484Sbinkertn@umich.edu		WRITE_$1$3(dst,t);
2914484Sbinkertn@umich.edu	}
2924484Sbinkertn@umich.edu}
2934484Sbinkertn@umich.edu')
2944484Sbinkertn@umich.edu
2954484Sbinkertn@umich.edudefine(`MAKEPRIM_TO_M',`
2964484Sbinkertn@umich.edustatic void
2974484Sbinkertn@umich.edulibelf_cvt_$1$3_tom(char *dst, char *src, size_t count, int byteswap)
2984484Sbinkertn@umich.edu{
2994484Sbinkertn@umich.edu	Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst;
3004484Sbinkertn@umich.edu	size_t c;
3014484Sbinkertn@umich.edu
3024484Sbinkertn@umich.edu	if (dst == src && !byteswap)
3034484Sbinkertn@umich.edu		return;
3044484Sbinkertn@umich.edu
3054484Sbinkertn@umich.edu	if (!byteswap) {
3064484Sbinkertn@umich.edu		(void) memcpy(dst, src, count * sizeof(*d));
3074484Sbinkertn@umich.edu		return;
3084484Sbinkertn@umich.edu	}
3094484Sbinkertn@umich.edu
3104484Sbinkertn@umich.edu	for (c = 0; c < count; c++) {
3114484Sbinkertn@umich.edu		READ_$1$3(src,t);
3124484Sbinkertn@umich.edu		SWAP_$1$3(t);
3134484Sbinkertn@umich.edu		*d++ = t;
3144484Sbinkertn@umich.edu	}
3154484Sbinkertn@umich.edu}
3164484Sbinkertn@umich.edu')
3174484Sbinkertn@umich.edu
3184484Sbinkertn@umich.edudefine(`SWAP_FIELD',
3194484Sbinkertn@umich.edu  `ifdef(`IGNORE_'$2,`',
3204484Sbinkertn@umich.edu    `ifelse(BASE_$2,1,
3214484Sbinkertn@umich.edu      `SWAP_$2(t.$1);
3224484Sbinkertn@umich.edu			',
3234484Sbinkertn@umich.edu      `ifelse($2,BYTE,`',
3244484Sbinkertn@umich.edu        `ifelse($2,IDENT,`',
3254484Sbinkertn@umich.edu          `SWAP_$2'SZ()`(t.$1);
3264484Sbinkertn@umich.edu			')')')')')
3274484Sbinkertn@umich.edudefine(`SWAP_MEMBERS',
3284484Sbinkertn@umich.edu  `ifelse($#,1,`/**/',
3294484Sbinkertn@umich.edu     `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
3304484Sbinkertn@umich.edu
3314484Sbinkertn@umich.edudefine(`SWAP_STRUCT',
3324484Sbinkertn@umich.edu  `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
3334484Sbinkertn@umich.edu			SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
3344484Sbinkertn@umich.edu
3354484Sbinkertn@umich.edudefine(`WRITE_FIELD',
3364484Sbinkertn@umich.edu  `ifelse(BASE_$2,1,
3374484Sbinkertn@umich.edu    `WRITE_$2(dst,t.$1);
3384484Sbinkertn@umich.edu		',
3394484Sbinkertn@umich.edu    `ifelse($2,IDENT,
3404484Sbinkertn@umich.edu      `WRITE_$2(dst,t.$1);
3414484Sbinkertn@umich.edu		',
3424484Sbinkertn@umich.edu      `WRITE_$2'SZ()`(dst,t.$1);
3434484Sbinkertn@umich.edu		')')')
3444484Sbinkertn@umich.edudefine(`WRITE_MEMBERS',
3454484Sbinkertn@umich.edu  `ifelse($#,1,`/**/',
3464484Sbinkertn@umich.edu    `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
3474484Sbinkertn@umich.edu
3484484Sbinkertn@umich.edudefine(`WRITE_STRUCT',
3494484Sbinkertn@umich.edu  `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
3504484Sbinkertn@umich.edu		WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
3514484Sbinkertn@umich.edu
3524484Sbinkertn@umich.edudefine(`READ_FIELD',
3534484Sbinkertn@umich.edu  `ifelse(BASE_$2,1,
3544484Sbinkertn@umich.edu    `READ_$2(s,t.$1);
3554484Sbinkertn@umich.edu		',
3564484Sbinkertn@umich.edu    `ifelse($2,IDENT,
3574484Sbinkertn@umich.edu      `READ_$2(s,t.$1);
3584484Sbinkertn@umich.edu		',
3594484Sbinkertn@umich.edu      `READ_$2'SZ()`(s,t.$1);
3604484Sbinkertn@umich.edu		')')')
3614484Sbinkertn@umich.edu
3624484Sbinkertn@umich.edudefine(`READ_MEMBERS',
3634484Sbinkertn@umich.edu  `ifelse($#,1,`/**/',
3644484Sbinkertn@umich.edu    `READ_FIELD($1)READ_MEMBERS(shift($@))')')
3654484Sbinkertn@umich.edu
3664484Sbinkertn@umich.edudefine(`READ_STRUCT',
3674484Sbinkertn@umich.edu  `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
3684484Sbinkertn@umich.edu		READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
3694484Sbinkertn@umich.edu
3704484Sbinkertn@umich.edu/*
3714484Sbinkertn@umich.edu * Converters for non-integral ELF data structures.
3724484Sbinkertn@umich.edu *
3734484Sbinkertn@umich.edu * When converting data to file representation, the source pointer
3744484Sbinkertn@umich.edu * will be naturally aligned for a data structure's in-memory
3754484Sbinkertn@umich.edu * representation.  When converting data to memory, the destination
3764484Sbinkertn@umich.edu * pointer will be similarly aligned.
3774484Sbinkertn@umich.edu *
3784484Sbinkertn@umich.edu * For in-place conversions, when converting to file representations,
3794484Sbinkertn@umich.edu * the source buffer is large enough to hold `file' data.  When
3804484Sbinkertn@umich.edu * converting from file to memory, we need to be careful to work
3814484Sbinkertn@umich.edu * `backwards', to avoid overwriting unconverted data.
3824484Sbinkertn@umich.edu *
3834484Sbinkertn@umich.edu * Macro use:
3844484Sbinkertn@umich.edu * `$1': Name of the ELF type.
3854484Sbinkertn@umich.edu * `$2': C structure name suffix.
3864484Sbinkertn@umich.edu * `$3': ELF class specifier, one of [`', `32', `64']
3874484Sbinkertn@umich.edu */
3884484Sbinkertn@umich.edu
3894484Sbinkertn@umich.edudefine(`MAKE_TO_F',
3904484Sbinkertn@umich.edu  `ifdef(`IGNORE_'$1$3,`',`
3914484Sbinkertn@umich.edustatic void
3924484Sbinkertn@umich.edulibelf_cvt$3_$1_tof(char *dst, char *src, size_t count, int byteswap)
3934484Sbinkertn@umich.edu{
3944484Sbinkertn@umich.edu	Elf$3_$2	t, *s;
3954484Sbinkertn@umich.edu	size_t c;
3964484Sbinkertn@umich.edu
3974484Sbinkertn@umich.edu	s = (Elf$3_$2 *) (uintptr_t) src;
3984484Sbinkertn@umich.edu	for (c = 0; c < count; c++) {
3994484Sbinkertn@umich.edu		t = *s++;
4004484Sbinkertn@umich.edu		if (byteswap) {
4014484Sbinkertn@umich.edu			SWAP_STRUCT($2,$3)
4024484Sbinkertn@umich.edu		}
4034484Sbinkertn@umich.edu		WRITE_STRUCT($2,$3)
4044484Sbinkertn@umich.edu	}
4054484Sbinkertn@umich.edu}
4064484Sbinkertn@umich.edu')')
4074484Sbinkertn@umich.edu
4084484Sbinkertn@umich.edudefine(`MAKE_TO_M',
4094484Sbinkertn@umich.edu  `ifdef(`IGNORE_'$1$3,`',`
4104484Sbinkertn@umich.edustatic void
4114484Sbinkertn@umich.edulibelf_cvt$3_$1_tom(char *dst, char *src, size_t count, int byteswap)
4124484Sbinkertn@umich.edu{
4134484Sbinkertn@umich.edu	Elf$3_$2	 t, *d;
4144484Sbinkertn@umich.edu	unsigned char	*s,*s0;
4154484Sbinkertn@umich.edu	size_t		fsz;
4164484Sbinkertn@umich.edu
4174484Sbinkertn@umich.edu	fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
4184484Sbinkertn@umich.edu	d   = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
4194484Sbinkertn@umich.edu	s0  = (unsigned char *) src + (count - 1) * fsz;
4204484Sbinkertn@umich.edu
4214484Sbinkertn@umich.edu	while (count--) {
4224484Sbinkertn@umich.edu		s = s0;
4234484Sbinkertn@umich.edu		READ_STRUCT($2,$3)
4244484Sbinkertn@umich.edu		if (byteswap) {
4254484Sbinkertn@umich.edu			SWAP_STRUCT($2,$3)
4264484Sbinkertn@umich.edu		}
4274484Sbinkertn@umich.edu		*d-- = t; s0 -= fsz;
4284484Sbinkertn@umich.edu	}
4294484Sbinkertn@umich.edu}
4304484Sbinkertn@umich.edu')')
4314484Sbinkertn@umich.edu
4324484Sbinkertn@umich.edu/*
4334484Sbinkertn@umich.edu * Make type convertor functions from the type definition
4344484Sbinkertn@umich.edu * of the ELF type:
4354484Sbinkertn@umich.edu * - if the type is a base (i.e., `primitive') type:
4364484Sbinkertn@umich.edu *   - if it is marked as to be ignored (i.e., `IGNORE_'TYPE)
4374484Sbinkertn@umich.edu *     is defined, we skip the code generation step.
4384484Sbinkertn@umich.edu *   - if the type is declared as `SIZEDEP', then 32 and 64 bit
4394484Sbinkertn@umich.edu *     variants of the conversion functions are generated.
4404484Sbinkertn@umich.edu *   - otherwise a 32 bit variant is generated.
4414484Sbinkertn@umich.edu * - if the type is a structure type, we generate 32 and 64 bit
4424484Sbinkertn@umich.edu *   variants of the conversion functions.
4434484Sbinkertn@umich.edu */
4444484Sbinkertn@umich.edu
4454484Sbinkertn@umich.edudefine(`MAKE_TYPE_CONVERTER',
4464484Sbinkertn@umich.edu  `ifdef(`BASE'_$1,
4474484Sbinkertn@umich.edu    `ifdef(`IGNORE_'$1,`',
4484484Sbinkertn@umich.edu      `MAKEPRIM_TO_F($1,$2,`',64)
4494484Sbinkertn@umich.edu       MAKEPRIM_TO_M($1,$2,`',64)')',
4504484Sbinkertn@umich.edu    `ifdef(`SIZEDEP_'$1,
4514484Sbinkertn@umich.edu      `MAKEPRIM_TO_F($1,$2,32,32)dnl
4524484Sbinkertn@umich.edu       MAKEPRIM_TO_M($1,$2,32,32)dnl
4534484Sbinkertn@umich.edu       MAKEPRIM_TO_F($1,$2,64,64)dnl
4544484Sbinkertn@umich.edu       MAKEPRIM_TO_M($1,$2,64,64)',
4554484Sbinkertn@umich.edu      `MAKE_TO_F($1,$2,32)dnl
4564484Sbinkertn@umich.edu       MAKE_TO_F($1,$2,64)dnl
4574484Sbinkertn@umich.edu       MAKE_TO_M($1,$2,32)dnl
4584484Sbinkertn@umich.edu       MAKE_TO_M($1,$2,64)')')
4594484Sbinkertn@umich.edu')
4604484Sbinkertn@umich.edu
4614484Sbinkertn@umich.edudefine(`MAKE_TYPE_CONVERTERS',
4624484Sbinkertn@umich.edu  `ifelse($#,1,`',
4634484Sbinkertn@umich.edu    `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
4644484Sbinkertn@umich.edu
4654484Sbinkertn@umich.edudivert(0)
4664484Sbinkertn@umich.edu
4674484Sbinkertn@umich.edu/*
4684484Sbinkertn@umich.edu * Sections of type ELF_T_BYTE are never byteswapped, consequently a
4694484Sbinkertn@umich.edu * simple memcpy suffices for both directions of conversion.
4704484Sbinkertn@umich.edu */
4714484Sbinkertn@umich.edu
4724484Sbinkertn@umich.edustatic void
4734484Sbinkertn@umich.edulibelf_cvt_BYTE_tox(char *dst, char *src, size_t count, int byteswap)
4744484Sbinkertn@umich.edu{
4754484Sbinkertn@umich.edu	(void) byteswap;
4764484Sbinkertn@umich.edu	if (dst != src)
4774484Sbinkertn@umich.edu		(void) memcpy(dst, src, count);
4784484Sbinkertn@umich.edu}
4794484Sbinkertn@umich.edu
4804484Sbinkertn@umich.edu/*
4814484Sbinkertn@umich.edu * Elf_Note structures comprise a fixed size header followed by variable
4824484Sbinkertn@umich.edu * length strings.  The fixed size header needs to be byte swapped, but
4834484Sbinkertn@umich.edu * not the strings.
4844484Sbinkertn@umich.edu *
4854484Sbinkertn@umich.edu * Argument `count' denotes the total number of bytes to be converted.
4864484Sbinkertn@umich.edu */
4874484Sbinkertn@umich.edustatic void
4884484Sbinkertn@umich.edulibelf_cvt_NOTE_tom(char *dst, char *src, size_t count, int byteswap)
4894484Sbinkertn@umich.edu{
4904484Sbinkertn@umich.edu	uint32_t namesz, descsz, type;
4914484Sbinkertn@umich.edu	Elf_Note *en;
4924484Sbinkertn@umich.edu	size_t sz;
4934484Sbinkertn@umich.edu
4944484Sbinkertn@umich.edu	if (dst == src && !byteswap)
4954484Sbinkertn@umich.edu		return;
4964484Sbinkertn@umich.edu
4974484Sbinkertn@umich.edu	if (!byteswap) {
4984484Sbinkertn@umich.edu		(void) memcpy(dst, src, count);
4994484Sbinkertn@umich.edu		return;
5004484Sbinkertn@umich.edu	}
5014484Sbinkertn@umich.edu
5024484Sbinkertn@umich.edu	while (count > sizeof(Elf_Note)) {
5034484Sbinkertn@umich.edu
5044484Sbinkertn@umich.edu		READ_WORD(src, namesz);
5054484Sbinkertn@umich.edu		READ_WORD(src, descsz);
5064484Sbinkertn@umich.edu		READ_WORD(src, type);
5074484Sbinkertn@umich.edu
5084484Sbinkertn@umich.edu		if (byteswap) {
5094484Sbinkertn@umich.edu			SWAP_WORD(namesz);
5104484Sbinkertn@umich.edu			SWAP_WORD(descsz);
5114484Sbinkertn@umich.edu			SWAP_WORD(type);
5124484Sbinkertn@umich.edu		}
5134484Sbinkertn@umich.edu
5144484Sbinkertn@umich.edu		en = (Elf_Note *) (uintptr_t) dst;
5154484Sbinkertn@umich.edu		en->n_namesz = namesz;
5164484Sbinkertn@umich.edu		en->n_descsz = descsz;
5174484Sbinkertn@umich.edu		en->n_type = type;
5184484Sbinkertn@umich.edu
5194484Sbinkertn@umich.edu		dst += sizeof(Elf_Note);
5204484Sbinkertn@umich.edu
5214484Sbinkertn@umich.edu		ROUNDUP2(namesz, 4);
5224484Sbinkertn@umich.edu		ROUNDUP2(descsz, 4);
5234484Sbinkertn@umich.edu
5244484Sbinkertn@umich.edu		sz = namesz + descsz;
5254484Sbinkertn@umich.edu
5264484Sbinkertn@umich.edu		if (count < sz)
5274484Sbinkertn@umich.edu			sz = count;
5284484Sbinkertn@umich.edu
5294484Sbinkertn@umich.edu		(void) memcpy(dst, src, sz);
5304484Sbinkertn@umich.edu
5314484Sbinkertn@umich.edu		src += sz;
5324484Sbinkertn@umich.edu		dst += sz;
5334484Sbinkertn@umich.edu		count -= sz;
5344484Sbinkertn@umich.edu	}
5354484Sbinkertn@umich.edu}
5364484Sbinkertn@umich.edu
5374484Sbinkertn@umich.edustatic void
5384484Sbinkertn@umich.edulibelf_cvt_NOTE_tof(char *dst, char *src, size_t count, int byteswap)
5394484Sbinkertn@umich.edu{
5404484Sbinkertn@umich.edu	uint32_t namesz, descsz, type;
5414484Sbinkertn@umich.edu	Elf_Note *en;
5424484Sbinkertn@umich.edu	size_t sz;
5434484Sbinkertn@umich.edu
5444484Sbinkertn@umich.edu	if (dst == src && !byteswap)
5454484Sbinkertn@umich.edu		return;
5464484Sbinkertn@umich.edu
5474484Sbinkertn@umich.edu	if (!byteswap) {
5484484Sbinkertn@umich.edu		(void) memcpy(dst, src, count);
5494484Sbinkertn@umich.edu		return;
5504484Sbinkertn@umich.edu	}
5514484Sbinkertn@umich.edu
5524484Sbinkertn@umich.edu	while (count > sizeof(Elf_Note)) {
5534484Sbinkertn@umich.edu
5544484Sbinkertn@umich.edu		en = (Elf_Note *) (uintptr_t) src;
5554484Sbinkertn@umich.edu		namesz = en->n_namesz;
5564484Sbinkertn@umich.edu		descsz = en->n_descsz;
5574484Sbinkertn@umich.edu		type = en->n_type;
5584484Sbinkertn@umich.edu
5594484Sbinkertn@umich.edu		if (byteswap) {
5604484Sbinkertn@umich.edu			SWAP_WORD(namesz);
5614484Sbinkertn@umich.edu			SWAP_WORD(descsz);
5624484Sbinkertn@umich.edu			SWAP_WORD(type);
5634484Sbinkertn@umich.edu		}
5644484Sbinkertn@umich.edu
5654484Sbinkertn@umich.edu
5664484Sbinkertn@umich.edu		WRITE_WORD(dst, namesz);
5674484Sbinkertn@umich.edu		WRITE_WORD(dst, descsz);
5684484Sbinkertn@umich.edu		WRITE_WORD(dst, type);
5694484Sbinkertn@umich.edu
5704484Sbinkertn@umich.edu		src += sizeof(Elf_Note);
5714484Sbinkertn@umich.edu
5724484Sbinkertn@umich.edu		ROUNDUP2(namesz, 4);
5734484Sbinkertn@umich.edu		ROUNDUP2(descsz, 4);
5744484Sbinkertn@umich.edu
5754484Sbinkertn@umich.edu		sz = namesz + descsz;
5764484Sbinkertn@umich.edu
5774484Sbinkertn@umich.edu		if (count < sz)
5784484Sbinkertn@umich.edu			sz = count;
5794484Sbinkertn@umich.edu
5804484Sbinkertn@umich.edu		(void) memcpy(dst, src, sz);
5814484Sbinkertn@umich.edu
5824484Sbinkertn@umich.edu		src += sz;
5834484Sbinkertn@umich.edu		dst += sz;
5844484Sbinkertn@umich.edu		count -= sz;
5854484Sbinkertn@umich.edu	}
5864484Sbinkertn@umich.edu}
5874484Sbinkertn@umich.edu
5884484Sbinkertn@umich.eduMAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
5894484Sbinkertn@umich.edu
5904484Sbinkertn@umich.edustruct converters {
5914484Sbinkertn@umich.edu	void	(*tof32)(char *dst, char *src, size_t cnt, int byteswap);
5924484Sbinkertn@umich.edu	void	(*tom32)(char *dst, char *src, size_t cnt, int byteswap);
5934484Sbinkertn@umich.edu	void	(*tof64)(char *dst, char *src, size_t cnt, int byteswap);
5944484Sbinkertn@umich.edu	void	(*tom64)(char *dst, char *src, size_t cnt, int byteswap);
5954484Sbinkertn@umich.edu};
5964484Sbinkertn@umich.edu
5974484Sbinkertn@umich.edudivert(-1)
5984484Sbinkertn@umich.edudefine(`CONV',
5994484Sbinkertn@umich.edu  `ifdef(`IGNORE_'$1$2,
6004484Sbinkertn@umich.edu    `.$3$2 = NULL',
6014484Sbinkertn@umich.edu    `ifdef(`BASE_'$1,
6024484Sbinkertn@umich.edu      `ifdef(`IGNORE_'$1,
6034484Sbinkertn@umich.edu	`.$3$2 = NULL',
6044484Sbinkertn@umich.edu        `.$3$2 = libelf_cvt_$1_$3')',
6054484Sbinkertn@umich.edu      `ifdef(`SIZEDEP_'$1,
6064484Sbinkertn@umich.edu        `.$3$2 = libelf_cvt_$1$2_$3',
6074484Sbinkertn@umich.edu        `.$3$2 = libelf_cvt$2_$1_$3')')')')
6084484Sbinkertn@umich.edu
6094484Sbinkertn@umich.edudefine(`CONVERTER_NAME',
6104484Sbinkertn@umich.edu  `[ELF_T_$1] = {
6114484Sbinkertn@umich.edu        CONV($1,32,tof), CONV($1,32,tom),
6124484Sbinkertn@umich.edu        CONV($1,64,tof), CONV($1,64,tom) },')')
6134484Sbinkertn@umich.edu
6144484Sbinkertn@umich.edudefine(`CONVERTER_NAMES',
6154484Sbinkertn@umich.edu  `ifelse($#,1,`',
6164484Sbinkertn@umich.edu    `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
6174484Sbinkertn@umich.edu
6184484Sbinkertn@umich.eduundefine(`IGNORE_BYTE32')
6194484Sbinkertn@umich.eduundefine(`IGNORE_BYTE64')
6204484Sbinkertn@umich.edudivert(0)
6214484Sbinkertn@umich.edu
6224484Sbinkertn@umich.edustatic struct converters cvt[ELF_T_NUM] = {
6234484Sbinkertn@umich.eduCONVERTER_NAMES(ELF_TYPE_LIST)
6244484Sbinkertn@umich.edu
6254484Sbinkertn@umich.edu	/*
6264484Sbinkertn@umich.edu	 * Types that needs hand-coded converters follow.
6274484Sbinkertn@umich.edu	 */
6284484Sbinkertn@umich.edu
6294484Sbinkertn@umich.edu	[ELF_T_BYTE] = {
6304484Sbinkertn@umich.edu		.tof32 = libelf_cvt_BYTE_tox,
6314484Sbinkertn@umich.edu		.tom32 = libelf_cvt_BYTE_tox,
6324484Sbinkertn@umich.edu		.tof64 = libelf_cvt_BYTE_tox,
6334484Sbinkertn@umich.edu		.tom64 = libelf_cvt_BYTE_tox
6344484Sbinkertn@umich.edu	},
6354484Sbinkertn@umich.edu	[ELF_T_NOTE] = {
6364484Sbinkertn@umich.edu		.tof32 = libelf_cvt_NOTE_tof,
6374484Sbinkertn@umich.edu		.tom32 = libelf_cvt_NOTE_tom,
6384484Sbinkertn@umich.edu		.tof64 = libelf_cvt_NOTE_tof,
6394484Sbinkertn@umich.edu		.tom64 = libelf_cvt_NOTE_tom
6404484Sbinkertn@umich.edu	}
6414484Sbinkertn@umich.edu};
6424484Sbinkertn@umich.edu
6434484Sbinkertn@umich.eduvoid (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
6444484Sbinkertn@umich.edu (char *_dst, char *_src, size_t _cnt, int _byteswap)
6454484Sbinkertn@umich.edu{
6464484Sbinkertn@umich.edu	assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
6474484Sbinkertn@umich.edu	assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
6484484Sbinkertn@umich.edu
6494484Sbinkertn@umich.edu	if (t >= ELF_T_NUM ||
6504484Sbinkertn@umich.edu	    (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
6514484Sbinkertn@umich.edu	    (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
6524484Sbinkertn@umich.edu		return (NULL);
6534484Sbinkertn@umich.edu
6544484Sbinkertn@umich.edu	return ((elfclass == ELFCLASS32) ?
6554484Sbinkertn@umich.edu	    (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
6564484Sbinkertn@umich.edu	    (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));
6574484Sbinkertn@umich.edu}
658