]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libelf/libelf_convert.m4
This commit was generated by cvs2svn to compensate for changes in r164219,
[FreeBSD/FreeBSD.git] / lib / libelf / libelf_convert.m4
1 /*-
2  * Copyright (c) 2006 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 <string.h>
37
38 #include "_libelf.h"
39
40 /* WARNING: GENERATED FROM __file__. */
41
42 /*
43  * Macros to swap various integral quantities.
44  */
45
46 #define SWAP_HALF(X)    do {                                            \
47                 uint16_t _x = (uint16_t) (X);                           \
48                 uint16_t _t = _x & 0xFF;                                \
49                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
50                 (X) = _t;                                               \
51         } while (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 (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 (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)
80
81 /*
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 = (unsigned char *) (P);        \
88                 _p[0]           = (unsigned char) (X);                  \
89                 (P)             = _p + 1;                               \
90         } while (0)
91 #define WRITE_HALF(P,X) do {                                            \
92                 uint16_t _t     = (X);                                  \
93                 unsigned char *const _p = (unsigned char *) (P);        \
94                 unsigned const char *const _q = (unsigned char *) &_t;  \
95                 _p[0]           = _q[0];                                \
96                 _p[1]           = _q[1];                                \
97                 (P)             = _p + 2;                               \
98         } while (0)
99 #define WRITE_WORD(P,X) do {                                            \
100                 uint32_t _t     = (X);                                  \
101                 unsigned char *const _p = (unsigned char *) (P);        \
102                 unsigned const char *const _q = (unsigned char *) &_t;  \
103                 _p[0]           = _q[0];                                \
104                 _p[1]           = _q[1];                                \
105                 _p[2]           = _q[2];                                \
106                 _p[3]           = _q[3];                                \
107                 (P)             = _p + 4;                               \
108         } while (0)
109 #define WRITE_ADDR32(P,X)       WRITE_WORD(P,X)
110 #define WRITE_OFF32(P,X)        WRITE_WORD(P,X)
111 #define WRITE_SWORD(P,X)        WRITE_WORD(P,X)
112 #define WRITE_WORD64(P,X)       do {                                    \
113                 uint64_t _t     = (X);                                  \
114                 unsigned char *const _p = (unsigned char *) (P);        \
115                 unsigned const char *const _q = (unsigned char *) &_t;  \
116                 _p[0]           = _q[0];                                \
117                 _p[1]           = _q[1];                                \
118                 _p[2]           = _q[2];                                \
119                 _p[3]           = _q[3];                                \
120                 _p[4]           = _q[4];                                \
121                 _p[5]           = _q[5];                                \
122                 _p[6]           = _q[6];                                \
123                 _p[7]           = _q[7];                                \
124                 (P)             = _p + 8;                               \
125         } while (0)
126 #define WRITE_ADDR64(P,X)       WRITE_WORD64(P,X)
127 #define WRITE_LWORD(P,X)        WRITE_WORD64(P,X)
128 #define WRITE_OFF64(P,X)        WRITE_WORD64(P,X)
129 #define WRITE_SXWORD(P,X)       WRITE_WORD64(P,X)
130 #define WRITE_XWORD(P,X)        WRITE_WORD64(P,X)
131 #define WRITE_IDENT(P,X)        do {                                    \
132                 (void) memcpy((P), (X), sizeof((X)));                   \
133                 (P)             = (P) + EI_NIDENT;                      \
134         } while (0)
135
136 /*
137  * Read in various integral values.  The source pointer could be
138  * unaligned.  Values are read in in native byte order.  The source
139  * pointer is incremented appropriately.
140  */
141
142 #define READ_BYTE(P,X)  do {                                            \
143                 const unsigned char *const _p =                         \
144                         (const unsigned char *) (P);                    \
145                 (X)             = _p[0];                                \
146                 (P)             = (P) + 1;                              \
147         } while (0)
148 #define READ_HALF(P,X)  do {                                            \
149                 uint16_t _t;                                            \
150                 unsigned char *const _q = (unsigned char *) &_t;        \
151                 const unsigned char *const _p =                         \
152                         (const unsigned char *) (P);                    \
153                 _q[0]           = _p[0];                                \
154                 _q[1]           = _p[1];                                \
155                 (P)             = (P) + 2;                              \
156                 (X)             = _t;                                   \
157         } while (0)
158 #define READ_WORD(P,X)  do {                                            \
159                 uint32_t _t;                                            \
160                 unsigned char *const _q = (unsigned char *) &_t;        \
161                 const unsigned char *const _p =                         \
162                         (const unsigned char *) (P);                    \
163                 _q[0]           = _p[0];                                \
164                 _q[1]           = _p[1];                                \
165                 _q[2]           = _p[2];                                \
166                 _q[3]           = _p[3];                                \
167                 (P)             = (P) + 4;                              \
168                 (X)             = _t;                                   \
169         } while (0)
170 #define READ_ADDR32(P,X)        READ_WORD(P,X)
171 #define READ_OFF32(P,X)         READ_WORD(P,X)
172 #define READ_SWORD(P,X)         READ_WORD(P,X)
173 #define READ_WORD64(P,X)        do {                                    \
174                 uint64_t _t;                                            \
175                 unsigned char *const _q = (unsigned char *) &_t;        \
176                 const unsigned char *const _p =                         \
177                         (const unsigned char *) (P);                    \
178                 _q[0]           = _p[0];                                \
179                 _q[1]           = _p[1];                                \
180                 _q[2]           = _p[2];                                \
181                 _q[3]           = _p[3];                                \
182                 _q[4]           = _p[4];                                \
183                 _q[5]           = _p[5];                                \
184                 _q[6]           = _p[6];                                \
185                 _q[7]           = _p[7];                                \
186                 (P)             = (P) + 8;                              \
187                 (X)             = _t;                                   \
188         } while (0)
189 #define READ_ADDR64(P,X)        READ_WORD64(P,X)
190 #define READ_LWORD(P,X)         READ_WORD64(P,X)
191 #define READ_OFF64(P,X)         READ_WORD64(P,X)
192 #define READ_SXWORD(P,X)        READ_WORD64(P,X)
193 #define READ_XWORD(P,X)         READ_WORD64(P,X)
194 #define READ_IDENT(P,X)         do {                                    \
195                 (void) memcpy((X), (P), sizeof((X)));                   \
196                 (P)             = (P) + EI_NIDENT;                      \
197         } while (0)
198
199 #define ROUNDUP2(V,N)   (V) = ((((V) + (N) - 1)) & ~((N) - 1))
200
201 divert(-1)
202
203 /*
204  * Generate conversion routines for converting between in-memory and
205  * file representations of Elf data structures.
206  *
207  * `In-memory' representations of an Elf data structure use natural
208  * alignments and native byte ordering.  This allows arithmetic and
209  * casting to work as expected.  On the other hand the `file'
210  * representation of an ELF data structure could be packed tighter
211  * than its `in-memory' representation, and could be of a differing
212  * byte order.  An additional complication is that `ar' only pads data
213  * to even addresses and so ELF archive member data being read from
214  * inside an `ar' archive could end up at misaligned memory addresses.
215  *
216  * Consequently, casting the `char *' pointers that point to memory
217  * representations (i.e., source pointers for the *_tof() functions
218  * and the destination pointers for the *_tom() functions), is safe,
219  * as these pointers should be correctly aligned for the memory type
220  * already.  However, pointers to file representations have to be
221  * treated as being potentially unaligned and no casting can be done.
222  */
223
224 include(SRCDIR`/elf_types.m4')
225
226 /*
227  * `IGNORE'_* flags turn off generation of template code.
228  */
229
230 define(`IGNORE',
231   `define(IGNORE_$1`'32,        1)
232    define(IGNORE_$1`'64,        1)')
233
234 IGNORE(MOVEP)
235 IGNORE(NOTE)
236
237 ifelse(eval(OSRELDATE < 700009),1,
238   `IGNORE(CAP)
239    IGNORE(MOVE)
240    IGNORE(SYMINFO)
241    IGNORE(VDEF)
242    IGNORE(VNEED)
243    define(`IGNORE_LWORD',       1)',
244   `')
245
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)
250
251 /*
252  * `BASE'_XXX flags cause class agnostic template functions
253  * to be generated.
254  */
255
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)
264
265 /*
266  * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated
267  * for each primitive type.
268  */
269
270 define(`SIZEDEP_ADDR',  1)
271 define(`SIZEDEP_OFF',   1)
272
273 /*
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.
277  *
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)
287 {
288         Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src;
289         size_t c;
290
291         if (dst == src && !byteswap)
292                 return;
293
294         if (!byteswap) {
295                 (void) memcpy(dst, src, count * sizeof(*s));
296                 return;
297         }
298
299         for (c = 0; c < count; c++) {
300                 t = *s++;
301                 SWAP_$1$3(t);
302                 WRITE_$1$3(dst,t);
303         }
304 }
305 ')
306
307 define(`MAKEPRIM_TO_M',`
308 static void
309 libelf_cvt_$1$3_tom(char *dst, char *src, size_t count, int byteswap)
310 {
311         Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst;
312         size_t c;
313
314         if (dst == src && !byteswap)
315                 return;
316
317         if (!byteswap) {
318                 (void) memcpy(dst, src, count * sizeof(*d));
319                 return;
320         }
321
322         for (c = 0; c < count; c++) {
323                 READ_$1$3(src,t);
324                 SWAP_$1$3(t);
325                 *d++ = t;
326         }
327 }
328 ')
329
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($@))')')
342
343 define(`SWAP_STRUCT',
344   `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
345                         SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
346
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($@))')')
359
360 define(`WRITE_STRUCT',
361   `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
362                 WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
363
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                 ')')')
373
374 define(`READ_MEMBERS',
375   `ifelse($#,1,`/**/',
376     `READ_FIELD($1)READ_MEMBERS(shift($@))')')
377
378 define(`READ_STRUCT',
379   `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
380                 READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
381
382 /*
383  * Converters for non-integral ELF data structures.
384  *
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.
389  *
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.
394  *
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  */
400
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)
405 {
406         Elf$3_$2        t, *s;
407         size_t c;
408
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         }
417 }
418 ')')
419
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)
424 {
425         Elf$3_$2         t, *d;
426         unsigned char   *s,*s0;
427         size_t          fsz;
428
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;
432
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         }
441 }
442 ')')
443
444 /*
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  */
456
457 define(`MAKE_TYPE_CONVERTER',
458   `ifdef(`BASE'_$1,
459     `ifdef(`IGNORE_'$1,`',
460       `MAKEPRIM_TO_F($1,$2,`',64)
461        MAKEPRIM_TO_M($1,$2,`',64)')',
462     `ifdef(`SIZEDEP_'$1,
463       `MAKEPRIM_TO_F($1,$2,32,32)dnl
464        MAKEPRIM_TO_M($1,$2,32,32)dnl
465        MAKEPRIM_TO_F($1,$2,64,64)dnl
466        MAKEPRIM_TO_M($1,$2,64,64)',
467       `MAKE_TO_F($1,$2,32)dnl
468        MAKE_TO_F($1,$2,64)dnl
469        MAKE_TO_M($1,$2,32)dnl
470        MAKE_TO_M($1,$2,64)')')')
471
472 define(`MAKE_TYPE_CONVERTERS',
473   `ifelse($#,1,`',
474     `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
475
476 divert(0)
477
478 /*
479  * Sections of type ELF_T_BYTE are never byteswapped, consequently a
480  * simple memcpy suffices for both directions of conversion.
481  */
482
483 static void
484 libelf_cvt_BYTE_tox(char *dst, char *src, size_t count, int byteswap)
485 {
486         (void) byteswap;
487         if (dst != src)
488                 (void) memcpy(dst, src, count);
489 }
490
491 /*
492  * Elf_Note structures comprise a fixed size header followed by variable
493  * length strings.  The fixed size header needs to be byte swapped, but
494  * not the strings.
495  *
496  * Argument `count' denotes the total number of bytes to be converted.
497  */
498 static void
499 libelf_cvt_NOTE_tom(char *dst, char *src, size_t count, int byteswap)
500 {
501         uint32_t namesz, descsz, type;
502         Elf_Note *en;
503         size_t sz;
504
505         if (dst == src && !byteswap)
506                 return;
507
508         if (!byteswap) {
509                 (void) memcpy(dst, src, count);
510                 return;
511         }
512
513         while (count > sizeof(Elf_Note)) {
514
515                 READ_WORD(src, namesz);
516                 READ_WORD(src, descsz);
517                 READ_WORD(src, type);
518
519                 if (byteswap) {
520                         SWAP_WORD(namesz);
521                         SWAP_WORD(descsz);
522                         SWAP_WORD(type);
523                 }
524
525                 en = (Elf_Note *) (uintptr_t) dst;
526                 en->n_namesz = namesz;
527                 en->n_descsz = descsz;
528                 en->n_type = type;
529
530                 dst += sizeof(Elf_Note);
531
532                 ROUNDUP2(namesz, 4);
533                 ROUNDUP2(descsz, 4);
534
535                 sz = namesz + descsz;
536
537                 if (count < sz)
538                         sz = count;
539
540                 (void) memcpy(dst, src, sz);
541
542                 src += sz;
543                 dst += sz;
544                 count -= sz;
545         }
546 }
547
548 static void
549 libelf_cvt_NOTE_tof(char *dst, char *src, size_t count, int byteswap)
550 {
551         uint32_t namesz, descsz, type;
552         Elf_Note *en;
553         size_t sz;
554
555         if (dst == src && !byteswap)
556                 return;
557
558         if (!byteswap) {
559                 (void) memcpy(dst, src, count);
560                 return;
561         }
562
563         while (count > sizeof(Elf_Note)) {
564
565                 en = (Elf_Note *) (uintptr_t) src;
566                 namesz = en->n_namesz;
567                 descsz = en->n_descsz;
568                 type = en->n_type;
569
570                 if (byteswap) {
571                         SWAP_WORD(namesz);
572                         SWAP_WORD(descsz);
573                         SWAP_WORD(type);
574                 }
575
576
577                 WRITE_WORD(dst, namesz);
578                 WRITE_WORD(dst, descsz);
579                 WRITE_WORD(dst, type);
580
581                 src += sizeof(Elf_Note);
582
583                 ROUNDUP2(namesz, 4);
584                 ROUNDUP2(descsz, 4);
585
586                 sz = namesz + descsz;
587
588                 if (count < sz)
589                         sz = count;
590
591                 (void) memcpy(dst, src, sz);
592
593                 src += sz;
594                 dst += sz;
595                 count -= sz;
596         }
597 }
598
599 MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
600
601 struct converters {
602         void    (*tof32)(char *dst, char *src, size_t cnt, int byteswap);
603         void    (*tom32)(char *dst, char *src, size_t cnt, int byteswap);
604         void    (*tof64)(char *dst, char *src, size_t cnt, int byteswap);
605         void    (*tom64)(char *dst, char *src, size_t cnt, int byteswap);
606 };
607
608 divert(-1)
609 define(`CONV',
610   `ifdef(`IGNORE_'$1$2,
611     `.$3$2 = NULL',
612     `ifdef(`BASE_'$1,
613       `ifdef(`IGNORE_'$1,
614         `.$3$2 = NULL',
615         `.$3$2 = libelf_cvt_$1_$3')',
616       `ifdef(`SIZEDEP_'$1,
617         `.$3$2 = libelf_cvt_$1$2_$3',
618         `.$3$2 = libelf_cvt$2_$1_$3')')')')
619
620 define(`CONVERTER_NAME',
621   `[ELF_T_$1] = {
622         CONV($1,32,tof), CONV($1,32,tom),
623         CONV($1,64,tof), CONV($1,64,tom) },
624 ')')
625
626 define(`CONVERTER_NAMES',
627   `ifelse($#,1,`',
628     `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
629
630 undefine(`IGNORE_BYTE32', `IGNORE_BYTE64')
631 divert(0)
632
633 static struct converters cvt[ELF_T_NUM] = {
634 CONVERTER_NAMES(ELF_TYPE_LIST)
635
636         /*
637          * Types that needs hand-coded converters follow.
638          */
639
640         [ELF_T_BYTE] = {
641                 .tof32 = libelf_cvt_BYTE_tox,
642                 .tom32 = libelf_cvt_BYTE_tox,
643                 .tof64 = libelf_cvt_BYTE_tox,
644                 .tom64 = libelf_cvt_BYTE_tox
645         },
646         [ELF_T_NOTE] = {
647                 .tof32 = libelf_cvt_NOTE_tof,
648                 .tom32 = libelf_cvt_NOTE_tom,
649                 .tof64 = libelf_cvt_NOTE_tof,
650                 .tom64 = libelf_cvt_NOTE_tom
651         }
652 };
653
654 void (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
655  (char *_dst, char *_src, size_t _cnt, int _byteswap)
656 {
657         assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
658         assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
659
660         if (t >= ELF_T_NUM ||
661             (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
662             (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
663                 return (NULL);
664
665         return ((elfclass == ELFCLASS32) ?
666             (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
667             (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));
668 }