1 /* $NetBSD: libelf_convert.m4,v 1.7 2009/12/19 08:47:46 thorpej Exp $ */
4 * Copyright (c) 2006,2007 Joseph Koshy
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 /* __FBSDID("$FreeBSD: src/lib/libelf/libelf_convert.m4,v 1.4.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $"); */
32 #include <sys/types.h>
40 /* WARNING: GENERATED FROM __file__. */
43 * Macros to swap various integral quantities.
46 #define SWAP_HALF(X) do { \
47 uint16_t _x = (uint16_t) (X); \
48 uint32_t _t = _x & 0xFF; \
49 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
50 (X) = (uint16_t)(_t & 0xFFFF); \
51 } while (/*CONSTCOND*/0)
52 #define SWAP_WORD(X) do { \
53 uint32_t _x = (uint32_t) (X); \
54 uint32_t _t = _x & 0xFF; \
55 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
56 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
57 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
59 } while (/*CONSTCOND*/0)
60 #define SWAP_ADDR32(X) SWAP_WORD(X)
61 #define SWAP_OFF32(X) SWAP_WORD(X)
62 #define SWAP_SWORD(X) SWAP_WORD(X)
63 #define SWAP_WORD64(X) do { \
64 uint64_t _x = (uint64_t) (X); \
65 uint64_t _t = _x & 0xFF; \
66 _t <<= 8; _x >>= 8; _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; \
74 } while (/*CONSTCOND*/0)
75 #define SWAP_ADDR64(X) SWAP_WORD64(X)
76 #define SWAP_LWORD(X) SWAP_WORD64(X)
77 #define SWAP_OFF64(X) SWAP_WORD64(X)
78 #define SWAP_SXWORD(X) SWAP_WORD64(X)
79 #define SWAP_XWORD(X) SWAP_WORD64(X)
82 * Write out various integral values. The destination pointer could
83 * be unaligned. Values are written out in native byte order. The
84 * destination pointer is incremented after the write.
86 #define WRITE_BYTE(P,X) do { \
87 unsigned char *const _p = (void *) (P); \
88 _p[0] = (unsigned char) (X); \
89 (P) = (void *)(_p + 1); \
90 } while (/*CONSTCOND*/0)
91 #define WRITE_HALF(P,X) do { \
96 unsigned char *const _p = (void *) (P); \
98 _p[0] = _t.bytes[0]; \
99 _p[1] = _t.bytes[1]; \
100 (P) = (void *)(_p + 2); \
101 } while (/*CONSTCOND*/0)
102 #define WRITE_WORD(P,X) do { \
107 unsigned char *const _p = (void *) (P); \
109 _p[0] = _t.bytes[0]; \
110 _p[1] = _t.bytes[1]; \
111 _p[2] = _t.bytes[2]; \
112 _p[3] = _t.bytes[3]; \
113 (P) = (void *)(_p + 4); \
114 } while (/*CONSTCOND*/0)
115 #define WRITE_ADDR32(P,X) WRITE_WORD(P,X)
116 #define WRITE_OFF32(P,X) WRITE_WORD(P,X)
117 #define WRITE_SWORD(P,X) WRITE_WORD(P,X)
118 #define WRITE_WORD64(P,X) do { \
123 unsigned char *const _p = (void *) (P); \
125 _p[0] = _t.bytes[0]; \
126 _p[1] = _t.bytes[1]; \
127 _p[2] = _t.bytes[2]; \
128 _p[3] = _t.bytes[3]; \
129 _p[4] = _t.bytes[4]; \
130 _p[5] = _t.bytes[5]; \
131 _p[6] = _t.bytes[6]; \
132 _p[7] = _t.bytes[7]; \
133 (P) = (void *)(_p + 8); \
134 } while (/*CONSTCOND*/0)
135 #define WRITE_ADDR64(P,X) WRITE_WORD64(P,X)
136 #define WRITE_LWORD(P,X) WRITE_WORD64(P,X)
137 #define WRITE_OFF64(P,X) WRITE_WORD64(P,X)
138 #define WRITE_SXWORD(P,X) WRITE_WORD64(P,X)
139 #define WRITE_XWORD(P,X) WRITE_WORD64(P,X)
140 #define WRITE_IDENT(P,X) do { \
141 (void) memcpy((P), (X), sizeof((X))); \
142 (P) = (P) + EI_NIDENT; \
143 } while (/*CONSTCOND*/0)
146 * Read in various integral values. The source pointer could be
147 * unaligned. Values are read in native byte order. The source
148 * pointer is incremented appropriately.
151 #define READ_BYTE(P,X) do { \
152 const unsigned char *const _p = \
153 (const void *) (P); \
156 } while (/*CONSTCOND*/0)
157 #define READ_HALF(P,X) do { \
159 unsigned char *const _q = (void *) &_t; \
160 const unsigned char *const _p = \
161 (const void *) (P); \
166 } while (/*CONSTCOND*/0)
167 #define READ_WORD(P,X) do { \
169 unsigned char *const _q = (void *) &_t; \
170 const unsigned char *const _p = \
171 (const void *) (P); \
178 } while (/*CONSTCOND*/0)
179 #define READ_ADDR32(P,X) READ_WORD(P,X)
180 #define READ_OFF32(P,X) READ_WORD(P,X)
181 #define READ_SWORD(P,X) READ_WORD(P,X)
182 #define READ_WORD64(P,X) do { \
184 unsigned char *const _q = (void *) &_t; \
185 const unsigned char *const _p = \
186 (const void *) (P); \
197 } while (/*CONSTCOND*/0)
198 #define READ_ADDR64(P,X) READ_WORD64(P,X)
199 #define READ_LWORD(P,X) READ_WORD64(P,X)
200 #define READ_OFF64(P,X) READ_WORD64(P,X)
201 #define READ_SXWORD(P,X) READ_WORD64(P,X)
202 #define READ_XWORD(P,X) READ_WORD64(P,X)
203 #define READ_IDENT(P,X) do { \
204 (void) memcpy((X), (P), sizeof((X))); \
205 (P) = (P) + EI_NIDENT; \
206 } while (/*CONSTCOND*/0)
208 #define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1))
213 * Generate conversion routines for converting between in-memory and
214 * file representations of Elf data structures.
216 * `In-memory' representations of an Elf data structure use natural
217 * alignments and native byte ordering. This allows arithmetic and
218 * casting to work as expected. On the other hand the `file'
219 * representation of an ELF data structure could be packed tighter
220 * than its `in-memory' representation, and could be of a differing
221 * byte order. An additional complication is that `ar' only pads data
222 * to even addresses and so ELF archive member data being read from
223 * inside an `ar' archive could end up at misaligned memory addresses.
225 * Consequently, casting the `char *' pointers that point to memory
226 * representations (i.e., source pointers for the *_tof() functions
227 * and the destination pointers for the *_tom() functions), is safe,
228 * as these pointers should be correctly aligned for the memory type
229 * already. However, pointers to file representations have to be
230 * treated as being potentially unaligned and no casting can be done.
233 include(SRCDIR`/elf_types.m4')
236 * `IGNORE'_* flags turn off generation of template code.
240 `define(IGNORE_$1`'32, 1)
241 define(IGNORE_$1`'64, 1)')
246 define(IGNORE_BYTE, 1) /* 'lator, leave 'em bytes alone */
247 define(IGNORE_NOTE, 1)
248 define(IGNORE_SXWORD32, 1)
249 define(IGNORE_XWORD32, 1)
252 * `BASE'_XXX flags cause class agnostic template functions
256 define(`BASE_BYTE', 1)
257 define(`BASE_HALF', 1)
258 define(`BASE_NOTE', 1)
259 define(`BASE_WORD', 1)
260 define(`BASE_LWORD', 1)
261 define(`BASE_SWORD', 1)
262 define(`BASE_XWORD', 1)
263 define(`BASE_SXWORD', 1)
266 * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated
267 * for each primitive type.
270 define(`SIZEDEP_ADDR', 1)
271 define(`SIZEDEP_OFF', 1)
274 * `Primitive' ELF types are those that are an alias for an integral
275 * type. They have no internal structure. These can be copied using
276 * a `memcpy()', and byteswapped in straightforward way.
279 * `$1': Name of the ELF type.
280 * `$2': C structure name suffix
281 * `$3': ELF class specifier for symbols, one of [`', `32', `64']
282 * `$4': ELF class specifier for types, one of [`32', `64']
284 define(`MAKEPRIM_TO_F',`
286 libelf_cvt_$1$3_tof(char *dst, char *src, size_t count, int byteswap)
288 Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src;
291 if (dst == src && !byteswap)
295 (void) memcpy(dst, src, count * sizeof(*s));
299 for (c = 0; c < count; c++) {
307 define(`MAKEPRIM_TO_M',`
309 libelf_cvt_$1$3_tom(char *dst, char *src, size_t count, int byteswap)
311 Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst;
314 if (dst == src && !byteswap)
318 (void) memcpy(dst, src, count * sizeof(*d));
322 for (c = 0; c < count; c++) {
331 `ifdef(`IGNORE_'$2,`',
337 `SWAP_$2'SZ()`(t.$1);
339 define(`SWAP_MEMBERS',
341 `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
343 define(`SWAP_STRUCT',
344 `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
345 SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
347 define(`WRITE_FIELD',
354 `WRITE_$2'SZ()`(dst,t.$1);
356 define(`WRITE_MEMBERS',
358 `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
360 define(`WRITE_STRUCT',
361 `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
362 WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
371 `READ_$2'SZ()`(s,t.$1);
374 define(`READ_MEMBERS',
376 `READ_FIELD($1)READ_MEMBERS(shift($@))')')
378 define(`READ_STRUCT',
379 `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
380 READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
383 * Converters for non-integral ELF data structures.
385 * When converting data to file representation, the source pointer
386 * will be naturally aligned for a data structure's in-memory
387 * representation. When converting data to memory, the destination
388 * pointer will be similarly aligned.
390 * For in-place conversions, when converting to file representations,
391 * the source buffer is large enough to hold `file' data. When
392 * converting from file to memory, we need to be careful to work
393 * `backwards', to avoid overwriting unconverted data.
396 * `$1': Name of the ELF type.
397 * `$2': C structure name suffix.
398 * `$3': ELF class specifier, one of [`', `32', `64']
402 `ifdef(`IGNORE_'$1$3,`',`
404 libelf_cvt$3_$1_tof(char *dst, char *src, size_t count, int byteswap)
409 s = (Elf$3_$2 *) (uintptr_t) src;
410 for (c = 0; c < count; c++) {
421 `ifdef(`IGNORE_'$1$3,`',`
423 libelf_cvt$3_$1_tom(char *dst, char *src, size_t count, int byteswap)
426 unsigned char *s,*s0;
429 fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
430 d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
431 s0 = (unsigned char *) src + (count - 1) * fsz;
445 * Make type convertor functions from the type definition
447 * - if the type is a base (i.e., `primitive') type:
448 * - if it is marked as to be ignored (i.e., `IGNORE_'TYPE)
449 * is defined, we skip the code generation step.
450 * - if the type is declared as `SIZEDEP', then 32 and 64 bit
451 * variants of the conversion functions are generated.
452 * - otherwise a 32 bit variant is generated.
453 * - if the type is a structure type, we generate 32 and 64 bit
454 * variants of the conversion functions.
457 define(`MAKE_TYPE_CONVERTER',
460 `ifdef(`IGNORE_'$1,`',
461 `MAKEPRIM_TO_F($1,$2,`',64)
462 MAKEPRIM_TO_M($1,$2,`',64)')',
464 `MAKEPRIM_TO_F($1,$2,32,32)dnl
465 MAKEPRIM_TO_M($1,$2,32,32)dnl
466 MAKEPRIM_TO_F($1,$2,64,64)dnl
467 MAKEPRIM_TO_M($1,$2,64,64)',
468 `MAKE_TO_F($1,$2,32)dnl
469 MAKE_TO_F($1,$2,64)dnl
470 MAKE_TO_M($1,$2,32)dnl
471 MAKE_TO_M($1,$2,64)')')
475 define(`MAKE_TYPE_CONVERTERS',
477 `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
482 * Sections of type ELF_T_BYTE are never byteswapped, consequently a
483 * simple memcpy suffices for both directions of conversion.
488 libelf_cvt_BYTE_tox(char *dst, char *src, size_t count, int byteswap __unused)
491 (void) memcpy(dst, src, count);
495 * Elf note structures comprise a fixed size header followed by variable
496 * length strings. The fixed size header needs to be byte swapped, but
499 * Argument `count' denotes the total number of bytes to be converted.
502 libelf_cvt_NOTE_tom(char *dst, char *src, size_t count, int byteswap)
504 uint32_t namesz, descsz, type;
505 Elf32_Nhdr *en; /* Elf32_Nhdr and Elf64_Nhdr are equiv. */
508 if (dst == src && !byteswap)
512 (void) memcpy(dst, src, count);
516 while (count > sizeof(Elf32_Nhdr)) {
518 READ_WORD(src, namesz);
519 READ_WORD(src, descsz);
520 READ_WORD(src, type);
528 en = (Elf32_Nhdr *) (uintptr_t) dst;
529 en->n_namesz = namesz;
530 en->n_descsz = descsz;
533 dst += sizeof(Elf32_Nhdr);
538 sz = namesz + descsz;
543 (void) memcpy(dst, src, sz);
552 libelf_cvt_NOTE_tof(char *dst, char *src, size_t count, int byteswap)
554 uint32_t namesz, descsz, type;
555 Elf32_Nhdr *en; /* Elf32_Nhdr and Elf64_Nhdr are equiv. */
558 if (dst == src && !byteswap)
562 (void) memcpy(dst, src, count);
566 while (count > sizeof(Elf32_Nhdr)) {
568 en = (Elf32_Nhdr *) (uintptr_t) src;
569 namesz = en->n_namesz;
570 descsz = en->n_descsz;
580 WRITE_WORD(dst, namesz);
581 WRITE_WORD(dst, descsz);
582 WRITE_WORD(dst, type);
584 src += sizeof(Elf32_Nhdr);
589 sz = namesz + descsz;
594 (void) memcpy(dst, src, sz);
602 MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
605 void (*tof32)(char *dst, char *src, size_t cnt, int byteswap);
606 void (*tom32)(char *dst, char *src, size_t cnt, int byteswap);
607 void (*tof64)(char *dst, char *src, size_t cnt, int byteswap);
608 void (*tom64)(char *dst, char *src, size_t cnt, int byteswap);
613 `ifdef(`IGNORE_'$1$2,
616 `.$3$2 = libelf_cvt_$1_$3',
618 `.$3$2 = libelf_cvt_$1$2_$3',
619 `.$3$2 = libelf_cvt$2_$1_$3')')')')
621 define(`CONVERTER_NAME',
622 `ifdef(`IGNORE_'$1,`',
625 CONV($1,32,tof), CONV($1,32,tom),
626 CONV($1,64,tof), CONV($1,64,tom) },
630 define(`CONVERTER_NAMES',
632 `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
634 undefine(`IGNORE_BYTE32', `IGNORE_BYTE64')
637 static struct converters cvt[ELF_T_NUM] = {
638 CONVERTER_NAMES(ELF_TYPE_LIST)
641 * Types that needs hand-coded converters follow.
645 .tof32 = libelf_cvt_BYTE_tox,
646 .tom32 = libelf_cvt_BYTE_tox,
647 .tof64 = libelf_cvt_BYTE_tox,
648 .tom64 = libelf_cvt_BYTE_tox
651 .tof32 = libelf_cvt_NOTE_tof,
652 .tom32 = libelf_cvt_NOTE_tom,
653 .tof64 = libelf_cvt_NOTE_tof,
654 .tom64 = libelf_cvt_NOTE_tom
658 void (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
659 (char *_dst, char *_src, size_t _cnt, int _byteswap)
661 assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
662 assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
664 if (t >= ELF_T_NUM ||
665 (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
666 (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
669 return ((elfclass == ELFCLASS32) ?
670 (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
671 (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));