1/*-
2 * Copyright (c) 2006-2008 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__FBSDID("$FreeBSD$");
29
30#include <sys/types.h>
31#include <sys/elf32.h>
32#include <sys/elf64.h>
33
34#include <assert.h>
35#include <libelf.h>
36#include <osreldate.h>
37#include <string.h>
38
39#include "_libelf.h"
40
41/* WARNING: GENERATED FROM __file__. */
42
43/*
44 * Macros to swap various integral quantities.
45 */
46
47#define	SWAP_HALF(X) 	do {						\
48		uint16_t _x = (uint16_t) (X);				\
49		uint16_t _t = _x & 0xFF;				\
50		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
51		(X) = _t;						\
52	} while (0)
53#define	SWAP_WORD(X) 	do {						\
54		uint32_t _x = (uint32_t) (X);				\
55		uint32_t _t = _x & 0xFF;				\
56		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
57		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
58		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
59		(X) = _t;						\
60	} while (0)
61#define	SWAP_ADDR32(X)	SWAP_WORD(X)
62#define	SWAP_OFF32(X)	SWAP_WORD(X)
63#define	SWAP_SWORD(X)	SWAP_WORD(X)
64#define	SWAP_WORD64(X)	do {						\
65		uint64_t _x = (uint64_t) (X);				\
66		uint64_t _t = _x & 0xFF;				\
67		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
68		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
69		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
70		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
71		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
72		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
73		_t <<= 8; _x >>= 8; _t |= _x & 0xFF;			\
74		(X) = _t;						\
75	} while (0)
76#define	SWAP_ADDR64(X)	SWAP_WORD64(X)
77#define	SWAP_LWORD(X)	SWAP_WORD64(X)
78#define	SWAP_OFF64(X)	SWAP_WORD64(X)
79#define	SWAP_SXWORD(X)	SWAP_WORD64(X)
80#define	SWAP_XWORD(X)	SWAP_WORD64(X)
81
82/*
83 * Write out various integral values.  The destination pointer could
84 * be unaligned.  Values are written out in native byte order.  The
85 * destination pointer is incremented after the write.
86 */
87#define	WRITE_BYTE(P,X) do {						\
88		char *const _p = (char *) (P);	\
89		_p[0]		= (char) (X);			\
90		(P)		= _p + 1;				\
91	} while (0)
92#define	WRITE_HALF(P,X)	do {						\
93		uint16_t _t	= (X);					\
94		char *const _p	= (char *) (P);	\
95		const char *const _q = (char *) &_t;	\
96		_p[0]		= _q[0];				\
97		_p[1]		= _q[1];				\
98		(P) 		= _p + 2;				\
99	} while (0)
100#define	WRITE_WORD(P,X)	do {						\
101		uint32_t _t	= (X);					\
102		char *const _p	= (char *) (P);	\
103		const char *const _q = (char *) &_t;	\
104		_p[0]		= _q[0];				\
105		_p[1]		= _q[1];				\
106		_p[2]		= _q[2];				\
107		_p[3]		= _q[3];				\
108		(P)		= _p + 4;				\
109	} while (0)
110#define	WRITE_ADDR32(P,X)	WRITE_WORD(P,X)
111#define	WRITE_OFF32(P,X)	WRITE_WORD(P,X)
112#define	WRITE_SWORD(P,X)	WRITE_WORD(P,X)
113#define	WRITE_WORD64(P,X)	do {					\
114		uint64_t _t	= (X);					\
115		char *const _p	= (char *) (P);	\
116		const char *const _q = (char *) &_t;	\
117		_p[0]		= _q[0];				\
118		_p[1]		= _q[1];				\
119		_p[2]		= _q[2];				\
120		_p[3]		= _q[3];				\
121		_p[4]		= _q[4];				\
122		_p[5]		= _q[5];				\
123		_p[6]		= _q[6];				\
124		_p[7]		= _q[7];				\
125		(P)		= _p + 8;				\
126	} while (0)
127#define	WRITE_ADDR64(P,X)	WRITE_WORD64(P,X)
128#define	WRITE_LWORD(P,X)	WRITE_WORD64(P,X)
129#define	WRITE_OFF64(P,X)	WRITE_WORD64(P,X)
130#define	WRITE_SXWORD(P,X)	WRITE_WORD64(P,X)
131#define	WRITE_XWORD(P,X)	WRITE_WORD64(P,X)
132#define	WRITE_IDENT(P,X)	do {					\
133		(void) memcpy((P), (X), sizeof((X)));			\
134		(P)		= (P) + EI_NIDENT;			\
135	} while (0)
136
137/*
138 * Read in various integral values.  The source pointer could be
139 * unaligned.  Values are read in native byte order.  The source
140 * pointer is incremented appropriately.
141 */
142
143#define	READ_BYTE(P,X)	do {						\
144		const char *const _p =				\
145			(const char *) (P);			\
146		(X)		= _p[0];				\
147		(P)		= (P) + 1;				\
148	} while (0)
149#define	READ_HALF(P,X)	do {						\
150		uint16_t _t;						\
151		char *const _q = (char *) &_t;	\
152		const char *const _p =				\
153			(const char *) (P);			\
154		_q[0]		= _p[0];				\
155		_q[1]		= _p[1];				\
156		(P)		= (P) + 2;				\
157		(X)		= _t;					\
158	} while (0)
159#define	READ_WORD(P,X)	do {						\
160		uint32_t _t;						\
161		char *const _q = (char *) &_t;	\
162		const char *const _p =				\
163			(const char *) (P);			\
164		_q[0]		= _p[0];				\
165		_q[1]		= _p[1];				\
166		_q[2]		= _p[2];				\
167		_q[3]		= _p[3];				\
168		(P)		= (P) + 4;				\
169		(X)		= _t;					\
170	} while (0)
171#define	READ_ADDR32(P,X)	READ_WORD(P,X)
172#define	READ_OFF32(P,X)		READ_WORD(P,X)
173#define	READ_SWORD(P,X)		READ_WORD(P,X)
174#define	READ_WORD64(P,X)	do {					\
175		uint64_t _t;						\
176		char *const _q = (char *) &_t;	\
177		const char *const _p =				\
178			(const char *) (P);			\
179		_q[0]		= _p[0];				\
180		_q[1]		= _p[1];				\
181		_q[2]		= _p[2];				\
182		_q[3]		= _p[3];				\
183		_q[4]		= _p[4];				\
184		_q[5]		= _p[5];				\
185		_q[6]		= _p[6];				\
186		_q[7]		= _p[7];				\
187		(P)		= (P) + 8;				\
188		(X)		= _t;					\
189	} while (0)
190#define	READ_ADDR64(P,X)	READ_WORD64(P,X)
191#define	READ_LWORD(P,X)		READ_WORD64(P,X)
192#define	READ_OFF64(P,X)		READ_WORD64(P,X)
193#define	READ_SXWORD(P,X)	READ_WORD64(P,X)
194#define	READ_XWORD(P,X)		READ_WORD64(P,X)
195#define	READ_IDENT(P,X)		do {					\
196		(void) memcpy((X), (P), sizeof((X)));			\
197		(P)		= (P) + EI_NIDENT;			\
198	} while (0)
199
200#define	ROUNDUP2(V,N)	(V) = ((((V) + (N) - 1)) & ~((N) - 1))
201
202divert(-1)
203
204/*
205 * Generate conversion routines for converting between in-memory and
206 * file representations of Elf data structures.
207 *
208 * `In-memory' representations of an Elf data structure use natural
209 * alignments and native byte ordering.  This allows arithmetic and
210 * casting to work as expected.  On the other hand the `file'
211 * representation of an ELF data structure could be packed tighter
212 * than its `in-memory' representation, and could be of a differing
213 * byte order.  An additional complication is that `ar' only pads data
214 * to even addresses and so ELF archive member data being read from
215 * inside an `ar' archive could end up at misaligned memory addresses.
216 *
217 * Consequently, casting the `char *' pointers that point to memory
218 * representations (i.e., source pointers for the *_tof() functions
219 * and the destination pointers for the *_tom() functions), is safe,
220 * as these pointers should be correctly aligned for the memory type
221 * already.  However, pointers to file representations have to be
222 * treated as being potentially unaligned and no casting can be done.
223 */
224
225include(SRCDIR`/elf_types.m4')
226
227/*
228 * `IGNORE'_* flags turn off generation of template code.
229 */
230
231define(`IGNORE',
232  `define(IGNORE_$1`'32,	1)
233   define(IGNORE_$1`'64,	1)')
234
235IGNORE(MOVEP)
236IGNORE(NOTE)
237IGNORE(GNUHASH)
238
239define(IGNORE_BYTE,		1)	/* 'lator, leave 'em bytes alone */
240define(IGNORE_GNUHASH,		1)
241define(IGNORE_NOTE,		1)
242define(IGNORE_SXWORD32,		1)
243define(IGNORE_XWORD32,		1)
244
245/*
246 * `BASE'_XXX flags cause class agnostic template functions
247 * to be generated.
248 */
249
250define(`BASE_BYTE',	1)
251define(`BASE_HALF',	1)
252define(`BASE_NOTE',	1)
253define(`BASE_WORD',	1)
254define(`BASE_LWORD',	1)
255define(`BASE_SWORD',	1)
256define(`BASE_XWORD',	1)
257define(`BASE_SXWORD',	1)
258
259/*
260 * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated
261 * for each primitive type.
262 */
263
264define(`SIZEDEP_ADDR',	1)
265define(`SIZEDEP_OFF',	1)
266
267/*
268 * `Primitive' ELF types are those that are an alias for an integral
269 * type.  They have no internal structure. These can be copied using
270 * a `memcpy()', and byteswapped in straightforward way.
271 *
272 * Macro use:
273 * `$1': Name of the ELF type.
274 * `$2': C structure name suffix
275 * `$3': ELF class specifier for symbols, one of [`', `32', `64']
276 * `$4': ELF class specifier for types, one of [`32', `64']
277 */
278define(`MAKEPRIM_TO_F',`
279static int
280libelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count,
281    int byteswap)
282{
283	Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src;
284	size_t c;
285
286	(void) dsz;
287
288	if (!byteswap) {
289		(void) memcpy(dst, src, count * sizeof(*s));
290		return (1);
291	}
292
293	for (c = 0; c < count; c++) {
294		t = *s++;
295		SWAP_$1$3(t);
296		WRITE_$1$3(dst,t);
297	}
298
299	return (1);
300}
301')
302
303define(`MAKEPRIM_TO_M',`
304static int
305libelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count,
306    int byteswap)
307{
308	Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst;
309	size_t c;
310
311	if (dsz < count * sizeof(Elf$4_$2))
312		return (0);
313
314	if (!byteswap) {
315		(void) memcpy(dst, src, count * sizeof(*d));
316		return (1);
317	}
318
319	for (c = 0; c < count; c++) {
320		READ_$1$3(src,t);
321		SWAP_$1$3(t);
322		*d++ = t;
323	}
324
325	return (1);
326}
327')
328
329define(`SWAP_FIELD',
330  `ifdef(`IGNORE_'$2,`',
331    `ifelse(BASE_$2,1,
332      `SWAP_$2(t.$1);
333			',
334      `ifelse($2,BYTE,`',
335        `ifelse($2,IDENT,`',
336          `SWAP_$2'SZ()`(t.$1);
337			')')')')')
338define(`SWAP_MEMBERS',
339  `ifelse($#,1,`/**/',
340     `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
341
342define(`SWAP_STRUCT',
343  `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
344			SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
345
346define(`WRITE_FIELD',
347  `ifelse(BASE_$2,1,
348    `WRITE_$2(dst,t.$1);
349		',
350    `ifelse($2,IDENT,
351      `WRITE_$2(dst,t.$1);
352		',
353      `WRITE_$2'SZ()`(dst,t.$1);
354		')')')
355define(`WRITE_MEMBERS',
356  `ifelse($#,1,`/**/',
357    `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
358
359define(`WRITE_STRUCT',
360  `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
361		WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
362
363define(`READ_FIELD',
364  `ifelse(BASE_$2,1,
365    `READ_$2(s,t.$1);
366		',
367    `ifelse($2,IDENT,
368      `READ_$2(s,t.$1);
369		',
370      `READ_$2'SZ()`(s,t.$1);
371		')')')
372
373define(`READ_MEMBERS',
374  `ifelse($#,1,`/**/',
375    `READ_FIELD($1)READ_MEMBERS(shift($@))')')
376
377define(`READ_STRUCT',
378  `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
379		READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
380
381/*
382 * Converters for non-integral ELF data structures.
383 *
384 * When converting data to file representation, the source pointer
385 * will be naturally aligned for a data structure's in-memory
386 * representation.  When converting data to memory, the destination
387 * pointer will be similarly aligned.
388 *
389 * For in-place conversions, when converting to file representations,
390 * the source buffer is large enough to hold `file' data.  When
391 * converting from file to memory, we need to be careful to work
392 * `backwards', to avoid overwriting unconverted data.
393 *
394 * Macro use:
395 * `$1': Name of the ELF type.
396 * `$2': C structure name suffix.
397 * `$3': ELF class specifier, one of [`', `32', `64']
398 */
399
400define(`MAKE_TO_F',
401  `ifdef(`IGNORE_'$1$3,`',`
402static int
403libelf_cvt$3_$1_tof(char *dst, size_t dsz, char *src, size_t count,
404    int byteswap)
405{
406	Elf$3_$2	t, *s;
407	size_t c;
408
409	(void) dsz;
410
411	s = (Elf$3_$2 *) (uintptr_t) src;
412	for (c = 0; c < count; c++) {
413		t = *s++;
414		if (byteswap) {
415			SWAP_STRUCT($2,$3)
416		}
417		WRITE_STRUCT($2,$3)
418	}
419
420	return (1);
421}
422')')
423
424define(`MAKE_TO_M',
425  `ifdef(`IGNORE_'$1$3,`',`
426static int
427libelf_cvt$3_$1_tom(char *dst, size_t dsz, char *src, size_t count,
428    int byteswap)
429{
430	Elf$3_$2	 t, *d;
431	char		*s,*s0;
432	size_t		fsz;
433
434	fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
435	d   = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
436	s0  = (char *) src + (count - 1) * fsz;
437
438	if (dsz < count * sizeof(Elf$3_$2))
439		return (0);
440
441	while (count--) {
442		s = s0;
443		READ_STRUCT($2,$3)
444		if (byteswap) {
445			SWAP_STRUCT($2,$3)
446		}
447		*d-- = t; s0 -= fsz;
448	}
449
450	return (1);
451}
452')')
453
454/*
455 * Make type convertor functions from the type definition
456 * of the ELF type:
457 * - if the type is a base (i.e., `primitive') type:
458 *   - if it is marked as to be ignored (i.e., `IGNORE_'TYPE)
459 *     is defined, we skip the code generation step.
460 *   - if the type is declared as `SIZEDEP', then 32 and 64 bit
461 *     variants of the conversion functions are generated.
462 *   - otherwise a 32 bit variant is generated.
463 * - if the type is a structure type, we generate 32 and 64 bit
464 *   variants of the conversion functions.
465 */
466
467define(`MAKE_TYPE_CONVERTER',
468  `#if	__FreeBSD_version >= $3 /* $1 */
469ifdef(`BASE'_$1,
470    `ifdef(`IGNORE_'$1,`',
471      `MAKEPRIM_TO_F($1,$2,`',64)
472       MAKEPRIM_TO_M($1,$2,`',64)')',
473    `ifdef(`SIZEDEP_'$1,
474      `MAKEPRIM_TO_F($1,$2,32,32)dnl
475       MAKEPRIM_TO_M($1,$2,32,32)dnl
476       MAKEPRIM_TO_F($1,$2,64,64)dnl
477       MAKEPRIM_TO_M($1,$2,64,64)',
478      `MAKE_TO_F($1,$2,32)dnl
479       MAKE_TO_F($1,$2,64)dnl
480       MAKE_TO_M($1,$2,32)dnl
481       MAKE_TO_M($1,$2,64)')')
482#endif /* $1 */
483')
484
485define(`MAKE_TYPE_CONVERTERS',
486  `ifelse($#,1,`',
487    `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
488
489divert(0)
490
491/*
492 * Sections of type ELF_T_BYTE are never byteswapped, consequently a
493 * simple memcpy suffices for both directions of conversion.
494 */
495
496static int
497libelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count,
498    int byteswap)
499{
500	(void) byteswap;
501	if (dsz < count)
502		return (0);
503	if (dst != src)
504		(void) memcpy(dst, src, count);
505	return (1);
506}
507
508MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
509
510#if	__FreeBSD_version >= 800062
511/*
512 * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit
513 * words.  Bloom filter data comes next, followed by hash buckets and the
514 * hash chain.
515 *
516 * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit
517 * wide on ELFCLASS32 objects.  The other objects in this section are 32
518 * bits wide.
519 *
520 * Argument `srcsz' denotes the number of bytes to be converted.  In the
521 * 32-bit case we need to translate `srcsz' to a count of 32-bit words.
522 */
523
524static int
525libelf_cvt32_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz,
526    int byteswap)
527{
528	return (libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t),
529	        byteswap));
530}
531
532static int
533libelf_cvt32_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz,
534    int byteswap)
535{
536	return (libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t),
537	        byteswap));
538}
539
540static int
541libelf_cvt64_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz,
542    int byteswap)
543{
544	size_t sz;
545	uint64_t t64, *bloom64;
546	Elf_GNU_Hash_Header *gh;
547	uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
548	uint32_t *buckets, *chains;
549
550	sz = 4 * sizeof(uint32_t);	/* File header is 4 words long. */
551	if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
552		return (0);
553
554	/* Read in the section header and byteswap if needed. */
555	READ_WORD(src, nbuckets);
556	READ_WORD(src, symndx);
557	READ_WORD(src, maskwords);
558	READ_WORD(src, shift2);
559
560	srcsz -= sz;
561
562	if (byteswap) {
563		SWAP_WORD(nbuckets);
564		SWAP_WORD(symndx);
565		SWAP_WORD(maskwords);
566		SWAP_WORD(shift2);
567	}
568
569	/* Check source buffer and destination buffer sizes. */
570	sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
571	if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
572		return (0);
573
574	gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
575	gh->gh_nbuckets  = nbuckets;
576	gh->gh_symndx    = symndx;
577	gh->gh_maskwords = maskwords;
578	gh->gh_shift2    = shift2;
579
580	dsz -= sizeof(Elf_GNU_Hash_Header);
581	dst += sizeof(Elf_GNU_Hash_Header);
582
583	bloom64 = (uint64_t *) (uintptr_t) dst;
584
585	/* Copy bloom filter data. */
586	for (n = 0; n < maskwords; n++) {
587		READ_XWORD(src, t64);
588		if (byteswap)
589			SWAP_XWORD(t64);
590		bloom64[n] = t64;
591	}
592
593	/* The hash buckets follows the bloom filter. */
594	dst += maskwords * sizeof(uint64_t);
595	buckets = (uint32_t *) (uintptr_t) dst;
596
597	for (n = 0; n < nbuckets; n++) {
598		READ_WORD(src, t32);
599		if (byteswap)
600			SWAP_WORD(t32);
601		buckets[n] = t32;
602	}
603
604	dst += nbuckets * sizeof(uint32_t);
605
606	/* The hash chain follows the hash buckets. */
607	dsz -= sz;
608	srcsz -= sz;
609
610	if (dsz < srcsz)	/* Destination lacks space. */
611	        return (0);
612
613	nchains = srcsz / sizeof(uint32_t);
614	chains = (uint32_t *) (uintptr_t) dst;
615
616	for (n = 0; n < nchains; n++) {
617		READ_WORD(src, t32);
618		if (byteswap)
619			SWAP_WORD(t32);
620		*chains++ = t32;
621	}
622
623	return (1);
624}
625
626static int
627libelf_cvt64_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz,
628    int byteswap)
629{
630	uint32_t *s32;
631	size_t sz, hdrsz;
632	uint64_t *s64, t64;
633	Elf_GNU_Hash_Header *gh;
634	uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32;
635
636	hdrsz = 4 * sizeof(uint32_t);	/* Header is 4x32 bits. */
637	if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header))
638		return (0);
639
640	gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
641
642	t0 = nbuckets = gh->gh_nbuckets;
643	t1 = gh->gh_symndx;
644	t2 = maskwords = gh->gh_maskwords;
645	t3 = gh->gh_shift2;
646
647	src   += sizeof(Elf_GNU_Hash_Header);
648	srcsz -= sizeof(Elf_GNU_Hash_Header);
649	dsz   -= hdrsz;
650
651	sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
652	    sizeof(uint64_t);
653
654	if (srcsz < sz || dsz < sz)
655		return (0);
656
657 	/* Write out the header. */
658	if (byteswap) {
659		SWAP_WORD(t0);
660		SWAP_WORD(t1);
661		SWAP_WORD(t2);
662		SWAP_WORD(t3);
663	}
664
665	WRITE_WORD(dst, t0);
666	WRITE_WORD(dst, t1);
667	WRITE_WORD(dst, t2);
668	WRITE_WORD(dst, t3);
669
670	/* Copy the bloom filter and the hash table. */
671	s64 = (uint64_t *) (uintptr_t) src;
672	for (n = 0; n < maskwords; n++) {
673		t64 = *s64++;
674		if (byteswap)
675			SWAP_XWORD(t64);
676		WRITE_WORD64(dst, t64);
677	}
678
679	s32 = (uint32_t *) s64;
680	for (n = 0; n < nbuckets; n++) {
681		t32 = *s32++;
682		if (byteswap)
683			SWAP_WORD(t32);
684		WRITE_WORD(dst, t32);
685	}
686
687	srcsz -= sz;
688	dsz   -= sz;
689
690	/* Copy out the hash chains. */
691	if (dsz < srcsz)
692		return (0);
693
694	nchains = srcsz / sizeof(uint32_t);
695	for (n = 0; n < nchains; n++) {
696		t32 = *s32++;
697		if (byteswap)
698			SWAP_WORD(t32);
699		WRITE_WORD(dst, t32);
700	}
701
702	return (1);
703}
704#endif
705
706/*
707 * Elf_Note structures comprise a fixed size header followed by variable
708 * length strings.  The fixed size header needs to be byte swapped, but
709 * not the strings.
710 *
711 * Argument `count' denotes the total number of bytes to be converted.
712 * The destination buffer needs to be at least `count' bytes in size.
713 */
714static int
715libelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count,
716    int byteswap)
717{
718	uint32_t namesz, descsz, type;
719	Elf_Note *en;
720	size_t sz, hdrsz;
721
722	if (dsz < count)	/* Destination buffer is too small. */
723		return (0);
724
725	hdrsz = 3 * sizeof(uint32_t);
726	if (count < hdrsz)		/* Source too small. */
727		return (0);
728
729	if (!byteswap) {
730		(void) memcpy(dst, src, count);
731		return (1);
732	}
733
734	/* Process all notes in the section. */
735	while (count > hdrsz) {
736		/* Read the note header. */
737		READ_WORD(src, namesz);
738		READ_WORD(src, descsz);
739		READ_WORD(src, type);
740
741		/* Translate. */
742		SWAP_WORD(namesz);
743		SWAP_WORD(descsz);
744		SWAP_WORD(type);
745
746		/* Copy out the translated note header. */
747		en = (Elf_Note *) (uintptr_t) dst;
748		en->n_namesz = namesz;
749		en->n_descsz = descsz;
750		en->n_type = type;
751
752		dsz -= sizeof(Elf_Note);
753		dst += sizeof(Elf_Note);
754		count -= hdrsz;
755
756		ROUNDUP2(namesz, 4);
757		ROUNDUP2(descsz, 4);
758
759		sz = namesz + descsz;
760
761		if (count < sz || dsz < sz)	/* Buffers are too small. */
762			return (0);
763
764		(void) memcpy(dst, src, sz);
765
766		src += sz;
767		dst += sz;
768
769		count -= sz;
770		dsz -= sz;
771	}
772
773	return (1);
774}
775
776static int
777libelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count,
778    int byteswap)
779{
780	uint32_t namesz, descsz, type;
781	Elf_Note *en;
782	size_t sz;
783
784	if (dsz < count)
785		return (0);
786
787	if (!byteswap) {
788		(void) memcpy(dst, src, count);
789		return (1);
790	}
791
792	while (count > sizeof(Elf_Note)) {
793
794		en = (Elf_Note *) (uintptr_t) src;
795		namesz = en->n_namesz;
796		descsz = en->n_descsz;
797		type = en->n_type;
798
799		SWAP_WORD(namesz);
800		SWAP_WORD(descsz);
801		SWAP_WORD(type);
802
803		WRITE_WORD(dst, namesz);
804		WRITE_WORD(dst, descsz);
805		WRITE_WORD(dst, type);
806
807		src += sizeof(Elf_Note);
808
809		ROUNDUP2(namesz, 4);
810		ROUNDUP2(descsz, 4);
811
812		sz = namesz + descsz;
813
814		if (count < sz)
815			sz = count;
816
817		(void) memcpy(dst, src, sz);
818
819		src += sz;
820		dst += sz;
821		count -= sz;
822	}
823
824	return (1);
825}
826
827struct converters {
828	int	(*tof32)(char *dst, size_t dsz, char *src, size_t cnt,
829		    int byteswap);
830	int	(*tom32)(char *dst, size_t dsz, char *src, size_t cnt,
831		    int byteswap);
832	int	(*tof64)(char *dst, size_t dsz, char *src, size_t cnt,
833		    int byteswap);
834	int	(*tom64)(char *dst, size_t dsz, char *src, size_t cnt,
835		    int byteswap);
836};
837
838divert(-1)
839define(`CONV',
840  `ifdef(`IGNORE_'$1$2,
841    `.$3$2 = NULL',
842    `ifdef(`BASE_'$1,
843      `.$3$2 = libelf_cvt_$1_$3',
844      `ifdef(`SIZEDEP_'$1,
845        `.$3$2 = libelf_cvt_$1$2_$3',
846        `.$3$2 = libelf_cvt$2_$1_$3')')')')
847
848define(`CONVERTER_NAME',
849  `ifdef(`IGNORE_'$1,`',
850    `#if	__FreeBSD_version >= $3
851    [ELF_T_$1] = {
852        CONV($1,32,tof), CONV($1,32,tom),
853        CONV($1,64,tof), CONV($1,64,tom) },
854#endif
855')')
856
857define(`CONVERTER_NAMES',
858  `ifelse($#,1,`',
859    `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
860
861undefine(`IGNORE_BYTE32', `IGNORE_BYTE64')
862divert(0)
863
864static struct converters cvt[ELF_T_NUM] = {
865CONVERTER_NAMES(ELF_TYPE_LIST)
866
867	/*
868	 * Types that needs hand-coded converters follow.
869	 */
870
871	[ELF_T_BYTE] = {
872		.tof32 = libelf_cvt_BYTE_tox,
873		.tom32 = libelf_cvt_BYTE_tox,
874		.tof64 = libelf_cvt_BYTE_tox,
875		.tom64 = libelf_cvt_BYTE_tox
876	},
877
878#if	__FreeBSD_version >= 800062
879	[ELF_T_GNUHASH] = {
880		.tof32 = libelf_cvt32_GNUHASH_tof,
881		.tom32 = libelf_cvt32_GNUHASH_tom,
882		.tof64 = libelf_cvt64_GNUHASH_tof,
883		.tom64 = libelf_cvt64_GNUHASH_tom
884	},
885#endif
886
887	[ELF_T_NOTE] = {
888		.tof32 = libelf_cvt_NOTE_tof,
889		.tom32 = libelf_cvt_NOTE_tom,
890		.tof64 = libelf_cvt_NOTE_tof,
891		.tom64 = libelf_cvt_NOTE_tom
892	}
893};
894
895int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
896 (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap)
897{
898	assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
899	assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
900
901	if (t >= ELF_T_NUM ||
902	    (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
903	    (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
904		return (NULL);
905
906	return ((elfclass == ELFCLASS32) ?
907	    (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
908	    (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));
909}
910