Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / bsd / libelf / dist / libelf_convert.m4
blobc9ec626ec2aa0ddf05ca4e647256291b792de8eb
1 /*      $NetBSD: libelf_convert.m4,v 1.7 2009/12/19 08:47:46 thorpej Exp $      */
3 /*-
4  * Copyright (c) 2006,2007 Joseph Koshy
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
15  *
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
26  * SUCH DAMAGE.
27  */
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>
34 #include <assert.h>
35 #include <libelf.h>
36 #include <string.h>
38 #include "_libelf.h"
40 /* WARNING: GENERATED FROM __file__. */
43  * Macros to swap various integral quantities.
44  */
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;                    \
58                 (X) = _t;                                               \
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;                    \
73                 (X) = _t;                                               \
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.
85  */
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 {                                            \
92                 union {                                                 \
93                         uint16_t val;                                   \
94                         uint8_t bytes[2];                               \
95                 } _t;                                                   \
96                 unsigned char *const _p = (void *) (P);                 \
97                 _t.val = (X);                                           \
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 {                                            \
103                 union {                                                 \
104                         uint32_t val;                                   \
105                         uint8_t bytes[4];                               \
106                 } _t;                                                   \
107                 unsigned char *const _p = (void *) (P);                 \
108                 _t.val = (X);                                           \
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 {                                    \
119                 union {                                                 \
120                         uint64_t val;                                   \
121                         uint8_t bytes[8];                               \
122                 } _t;                                                   \
123                 unsigned char *const _p = (void *) (P);                 \
124                 _t.val = (X);                                           \
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.
149  */
151 #define READ_BYTE(P,X)  do {                                            \
152                 const unsigned char *const _p =                         \
153                         (const void *) (P);                             \
154                 (X)             = _p[0];                                \
155                 (P)             = (P) + 1;                              \
156         } while (/*CONSTCOND*/0)
157 #define READ_HALF(P,X)  do {                                            \
158                 uint16_t _t;                                            \
159                 unsigned char *const _q = (void *) &_t;                 \
160                 const unsigned char *const _p =                         \
161                         (const void *) (P);                             \
162                 _q[0]           = _p[0];                                \
163                 _q[1]           = _p[1];                                \
164                 (P)             = (P) + 2;                              \
165                 (X)             = _t;                                   \
166         } while (/*CONSTCOND*/0)
167 #define READ_WORD(P,X)  do {                                            \
168                 uint32_t _t;                                            \
169                 unsigned char *const _q = (void *) &_t;                 \
170                 const unsigned char *const _p =                         \
171                         (const void *) (P);                             \
172                 _q[0]           = _p[0];                                \
173                 _q[1]           = _p[1];                                \
174                 _q[2]           = _p[2];                                \
175                 _q[3]           = _p[3];                                \
176                 (P)             = (P) + 4;                              \
177                 (X)             = _t;                                   \
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 {                                    \
183                 uint64_t _t;                                            \
184                 unsigned char *const _q = (void *) &_t;                 \
185                 const unsigned char *const _p =                         \
186                         (const void *) (P);                             \
187                 _q[0]           = _p[0];                                \
188                 _q[1]           = _p[1];                                \
189                 _q[2]           = _p[2];                                \
190                 _q[3]           = _p[3];                                \
191                 _q[4]           = _p[4];                                \
192                 _q[5]           = _p[5];                                \
193                 _q[6]           = _p[6];                                \
194                 _q[7]           = _p[7];                                \
195                 (P)             = (P) + 8;                              \
196                 (X)             = _t;                                   \
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))
210 divert(-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.
231  */
233 include(SRCDIR`/elf_types.m4')
236  * `IGNORE'_* flags turn off generation of template code.
237  */
239 define(`IGNORE',
240   `define(IGNORE_$1`'32,        1)
241    define(IGNORE_$1`'64,        1)')
243 IGNORE(MOVEP)
244 IGNORE(NOTE)
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
253  * to be generated.
254  */
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.
268  */
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.
278  * Macro use:
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']
283  */
284 define(`MAKEPRIM_TO_F',`
285 static void
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;
289         size_t c;
291         if (dst == src && !byteswap)
292                 return;
294         if (!byteswap) {
295                 (void) memcpy(dst, src, count * sizeof(*s));
296                 return;
297         }
299         for (c = 0; c < count; c++) {
300                 t = *s++;
301                 SWAP_$1$3(t);
302                 WRITE_$1$3(dst,t);
303         }
307 define(`MAKEPRIM_TO_M',`
308 static void
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;
312         size_t c;
314         if (dst == src && !byteswap)
315                 return;
317         if (!byteswap) {
318                 (void) memcpy(dst, src, count * sizeof(*d));
319                 return;
320         }
322         for (c = 0; c < count; c++) {
323                 READ_$1$3(src,t);
324                 SWAP_$1$3(t);
325                 *d++ = t;
326         }
330 define(`SWAP_FIELD',
331   `ifdef(`IGNORE_'$2,`',
332     `ifelse(BASE_$2,1,
333       `SWAP_$2(t.$1);
334                         ',
335       `ifelse($2,BYTE,`',
336         `ifelse($2,IDENT,`',
337           `SWAP_$2'SZ()`(t.$1);
338                         ')')')')')
339 define(`SWAP_MEMBERS',
340   `ifelse($#,1,`/**/',
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',
348   `ifelse(BASE_$2,1,
349     `WRITE_$2(dst,t.$1);
350                 ',
351     `ifelse($2,IDENT,
352       `WRITE_$2(dst,t.$1);
353                 ',
354       `WRITE_$2'SZ()`(dst,t.$1);
355                 ')')')
356 define(`WRITE_MEMBERS',
357   `ifelse($#,1,`/**/',
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')')
364 define(`READ_FIELD',
365   `ifelse(BASE_$2,1,
366     `READ_$2(s,t.$1);
367                 ',
368     `ifelse($2,IDENT,
369       `READ_$2(s,t.$1);
370                 ',
371       `READ_$2'SZ()`(s,t.$1);
372                 ')')')
374 define(`READ_MEMBERS',
375   `ifelse($#,1,`/**/',
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.
395  * Macro use:
396  * `$1': Name of the ELF type.
397  * `$2': C structure name suffix.
398  * `$3': ELF class specifier, one of [`', `32', `64']
399  */
401 define(`MAKE_TO_F',
402   `ifdef(`IGNORE_'$1$3,`',`
403 static void
404 libelf_cvt$3_$1_tof(char *dst, char *src, size_t count, int byteswap)
406         Elf$3_$2        t, *s;
407         size_t c;
409         s = (Elf$3_$2 *) (uintptr_t) src;
410         for (c = 0; c < count; c++) {
411                 t = *s++;
412                 if (byteswap) {
413                         SWAP_STRUCT($2,$3)
414                 }
415                 WRITE_STRUCT($2,$3)
416         }
418 ')')
420 define(`MAKE_TO_M',
421   `ifdef(`IGNORE_'$1$3,`',`
422 static void
423 libelf_cvt$3_$1_tom(char *dst, char *src, size_t count, int byteswap)
425         Elf$3_$2         t, *d;
426         unsigned char   *s,*s0;
427         size_t          fsz;
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;
433         while (count--) {
434                 s = s0;
435                 READ_STRUCT($2,$3)
436                 if (byteswap) {
437                         SWAP_STRUCT($2,$3)
438                 }
439                 *d-- = t; s0 -= fsz;
440         }
442 ')')
445  * Make type convertor functions from the type definition
446  * of the ELF type:
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.
455  */
457 define(`MAKE_TYPE_CONVERTER',
458   `#if  $3 /* $1 */
459 ifdef(`BASE'_$1,
460     `ifdef(`IGNORE_'$1,`',
461       `MAKEPRIM_TO_F($1,$2,`',64)
462        MAKEPRIM_TO_M($1,$2,`',64)')',
463     `ifdef(`SIZEDEP_'$1,
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)')')
472 #endif /* $1 */
475 define(`MAKE_TYPE_CONVERTERS',
476   `ifelse($#,1,`',
477     `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
479 divert(0)
482  * Sections of type ELF_T_BYTE are never byteswapped, consequently a
483  * simple memcpy suffices for both directions of conversion.
484  */
486 /*ARGSUSED*/
487 static void
488 libelf_cvt_BYTE_tox(char *dst, char *src, size_t count, int byteswap __unused)
490         if (dst != src)
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
497  * not the strings.
499  * Argument `count' denotes the total number of bytes to be converted.
500  */
501 static void
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. */
506         size_t sz;
508         if (dst == src && !byteswap)
509                 return;
511         if (!byteswap) {
512                 (void) memcpy(dst, src, count);
513                 return;
514         }
516         while (count > sizeof(Elf32_Nhdr)) {
518                 READ_WORD(src, namesz);
519                 READ_WORD(src, descsz);
520                 READ_WORD(src, type);
522                 if (byteswap) {
523                         SWAP_WORD(namesz);
524                         SWAP_WORD(descsz);
525                         SWAP_WORD(type);
526                 }
528                 en = (Elf32_Nhdr *) (uintptr_t) dst;
529                 en->n_namesz = namesz;
530                 en->n_descsz = descsz;
531                 en->n_type = type;
533                 dst += sizeof(Elf32_Nhdr);
535                 ROUNDUP2(namesz, 4);
536                 ROUNDUP2(descsz, 4);
538                 sz = namesz + descsz;
540                 if (count < sz)
541                         sz = count;
543                 (void) memcpy(dst, src, sz);
545                 src += sz;
546                 dst += sz;
547                 count -= sz;
548         }
551 static void
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. */
556         size_t sz;
558         if (dst == src && !byteswap)
559                 return;
561         if (!byteswap) {
562                 (void) memcpy(dst, src, count);
563                 return;
564         }
566         while (count > sizeof(Elf32_Nhdr)) {
568                 en = (Elf32_Nhdr *) (uintptr_t) src;
569                 namesz = en->n_namesz;
570                 descsz = en->n_descsz;
571                 type = en->n_type;
573                 if (byteswap) {
574                         SWAP_WORD(namesz);
575                         SWAP_WORD(descsz);
576                         SWAP_WORD(type);
577                 }
580                 WRITE_WORD(dst, namesz);
581                 WRITE_WORD(dst, descsz);
582                 WRITE_WORD(dst, type);
584                 src += sizeof(Elf32_Nhdr);
586                 ROUNDUP2(namesz, 4);
587                 ROUNDUP2(descsz, 4);
589                 sz = namesz + descsz;
591                 if (count < sz)
592                         sz = count;
594                 (void) memcpy(dst, src, sz);
596                 src += sz;
597                 dst += sz;
598                 count -= sz;
599         }
602 MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
604 struct converters {
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);
611 divert(-1)
612 define(`CONV',
613   `ifdef(`IGNORE_'$1$2,
614     `.$3$2 = NULL',
615     `ifdef(`BASE_'$1,
616       `.$3$2 = libelf_cvt_$1_$3',
617       `ifdef(`SIZEDEP_'$1,
618         `.$3$2 = libelf_cvt_$1$2_$3',
619         `.$3$2 = libelf_cvt$2_$1_$3')')')')
621 define(`CONVERTER_NAME',
622   `ifdef(`IGNORE_'$1,`',
623     `#if        $3
624     [ELF_T_$1] = {
625         CONV($1,32,tof), CONV($1,32,tom),
626         CONV($1,64,tof), CONV($1,64,tom) },
627 #endif
628 ')')
630 define(`CONVERTER_NAMES',
631   `ifelse($#,1,`',
632     `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
634 undefine(`IGNORE_BYTE32', `IGNORE_BYTE64')
635 divert(0)
637 static struct converters cvt[ELF_T_NUM] = {
638 CONVERTER_NAMES(ELF_TYPE_LIST)
640         /*
641          * Types that needs hand-coded converters follow.
642          */
644         [ELF_T_BYTE] = {
645                 .tof32 = libelf_cvt_BYTE_tox,
646                 .tom32 = libelf_cvt_BYTE_tox,
647                 .tof64 = libelf_cvt_BYTE_tox,
648                 .tom64 = libelf_cvt_BYTE_tox
649         },
650         [ELF_T_NOTE] = {
651                 .tof32 = libelf_cvt_NOTE_tof,
652                 .tom32 = libelf_cvt_NOTE_tom,
653                 .tof64 = libelf_cvt_NOTE_tof,
654                 .tom64 = libelf_cvt_NOTE_tom
655         }
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))
667                 return (NULL);
669         return ((elfclass == ELFCLASS32) ?
670             (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
671             (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));