Drop main() prototype. Syncs with NetBSD-8
[minix.git] / external / bsd / elftoolchain / dist / libelf / libelf_convert.m4
blobcf082d2530200e157b5a1bbb0d5fa48a082b3398
1 /*      $NetBSD: libelf_convert.m4,v 1.2 2014/03/09 16:58:04 christos Exp $     */
3 /*-
4  * Copyright (c) 2006-2011 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 #if HAVE_NBTOOL_CONFIG_H
30 # include "nbtool_config.h"
31 #endif
33 #include <sys/cdefs.h>
35 #include <assert.h>
36 #include <libelf.h>
37 #include <string.h>
39 #include "_libelf.h"
41 __RCSID("$NetBSD: libelf_convert.m4,v 1.2 2014/03/09 16:58:04 christos Exp $");
42 ELFTC_VCSID("Id: libelf_convert.m4 2361 2011-12-28 12:03:05Z jkoshy ");
44 /* WARNING: GENERATED FROM __file__. */
46 divert(-1)
48 # Generate conversion routines for converting between in-memory and
49 # file representations of Elf data structures.
51 # These conversions use the type information defined in `elf_types.m4'.
53 include(SRCDIR`/elf_types.m4')
55 # For the purposes of generating conversion code, ELF types may be
56 # classified according to the following characteristics:
58 # 1. Whether the ELF type can be directly mapped to an integral C
59 #    language type.  For example, the ELF_T_WORD type maps directly to
60 #    a 'uint32_t', but ELF_T_GNUHASH lacks a matching C type.
62 # 2. Whether the type has word size dependent variants.  For example,
63 #    ELT_T_EHDR is represented using C types Elf32_Ehdr and El64_Ehdr,
64 #    and the ELF_T_ADDR and ELF_T_OFF types have integral C types that
65 #    can be 32- or 64- bit wide.
67 # 3. Whether the ELF types has a fixed representation or not.  For
68 #    example, the ELF_T_SYM type has a fixed size file representation,
69 #    some types like ELF_T_NOTE and ELF_T_GNUHASH use a variable size
70 #    representation.
72 # We use m4 macros to generate conversion code for ELF types that have
73 # a fixed size representation.  Conversion functions for the remaining
74 # types are coded by hand.
76 #* Handling File and Memory Representations
78 # `In-memory' representations of an Elf data structure use natural
79 # alignments and native byte ordering.  This allows pointer arithmetic
80 # and casting to work as expected.  On the other hand, the `file'
81 # representation of an ELF data structure could possibly be packed
82 # tighter than its `in-memory' representation, and could be of a
83 # differing byte order.  Reading ELF objects that are members of `ar'
84 # archives present an additional complication: `ar' pads file data to
85 # even addresses, so file data structures in an archive member
86 # residing inside an `ar' archive could be at misaligned memory
87 # addresses when brought into memory.
89 # In summary, casting the `char *' pointers that point to memory
90 # representations (i.e., source pointers for the *_tof() functions and
91 # the destination pointers for the *_tom() functions), is safe, as
92 # these pointers should be correctly aligned for the memory type
93 # already.  However, pointers to file representations have to be
94 # treated as being potentially unaligned and no casting can be done.
96 # NOCVT(TYPE) -- Do not generate the cvt[] structure entry for TYPE
97 define(`NOCVT',`define(`NOCVT_'$1,1)')
99 # NOFUNC(TYPE) -- Do not generate a conversion function for TYPE
100 define(`NOFUNC',`define(`NOFUNC_'$1,1)')
102 # IGNORE(TYPE) -- Completely ignore the type.
103 define(`IGNORE',`NOCVT($1)NOFUNC($1)')
105 # Mark ELF types that should not be processed by the M4 macros below.
107 # Types for which we use functions with non-standard names.
108 IGNORE(`BYTE')                  # Uses a wrapper around memcpy().
109 IGNORE(`NOTE')                  # Not a fixed size type.
111 # Types for which we supply hand-coded functions.
112 NOFUNC(`GNUHASH')               # A type with complex internal structure.
113 NOFUNC(`VDEF')                  # See MAKE_VERSION_CONVERTERS below.
114 NOFUNC(`VNEED')                 # ..
116 # Unimplemented types.
117 IGNORE(`MOVEP')
119 # ELF types that don't exist in a 32-bit world.
120 NOFUNC(`XWORD32')
121 NOFUNC(`SXWORD32')
123 # `Primitive' ELF types are those that are an alias for an integral
124 # type.  As they have no internal structure, they can be copied using
125 # a `memcpy()', and byteswapped in straightforward way.
127 # Mark all ELF types that directly map to integral C types.
128 define(`PRIM_ADDR',     1)
129 define(`PRIM_BYTE',     1)
130 define(`PRIM_HALF',     1)
131 define(`PRIM_LWORD',    1)
132 define(`PRIM_OFF',      1)
133 define(`PRIM_SWORD',    1)
134 define(`PRIM_SXWORD',   1)
135 define(`PRIM_WORD',     1)
136 define(`PRIM_XWORD',    1)
138 # Note the primitive types that are size-dependent.
139 define(`SIZEDEP_ADDR',  1)
140 define(`SIZEDEP_OFF',   1)
142 # Generate conversion functions for primitive types.
144 # Macro use: MAKEPRIMFUNCS(ELFTYPE,CTYPE,TYPESIZE,SYMSIZE)
145 # `$1': Name of the ELF type.
146 # `$2': C structure name suffix.
147 # `$3': ELF class specifier for types, one of [`32', `64'].
148 # `$4': Additional ELF class specifier, one of [`', `32', `64'].
150 # Generates a pair of conversion functions.
151 define(`MAKEPRIMFUNCS',`
152 static int
153 _libelf_cvt_$1$4_tof(char *dst, size_t dsz, char *src, size_t count,
154     int byteswap)
156         Elf$3_$2 t, *s = (Elf$3_$2 *) (uintptr_t) src;
157         size_t c;
159         (void) dsz;
161         if (!byteswap) {
162                 (void) memcpy(dst, src, count * sizeof(*s));
163                 return (1);
164         }
166         for (c = 0; c < count; c++) {
167                 t = *s++;
168                 SWAP_$1$4(t);
169                 WRITE_$1$4(dst,t);
170         }
172         return (1);
175 static int
176 _libelf_cvt_$1$4_tom(char *dst, size_t dsz, char *src, size_t count,
177     int byteswap)
179         Elf$3_$2 t, *d = (Elf$3_$2 *) (uintptr_t) dst;
180         size_t c;
182         if (dsz < count * sizeof(Elf$3_$2))
183                 return (0);
185         if (!byteswap) {
186                 (void) memcpy(dst, src, count * sizeof(*d));
187                 return (1);
188         }
190         for (c = 0; c < count; c++) {
191                 READ_$1$4(src,t);
192                 SWAP_$1$4(t);
193                 *d++ = t;
194         }
196         return (1);
201 # Handling composite ELF types
204 # SWAP_FIELD(FIELDNAME,ELFTYPE) -- Generate code to swap one field.
205 define(`SWAP_FIELD',
206   `ifdef(`SIZEDEP_'$2,
207     `SWAP_$2'SZ()`(t.$1);
208                         ',
209     `SWAP_$2(t.$1);
210                         ')')
212 # SWAP_MEMBERS(STRUCT) -- Iterate over a structure definition.
213 define(`SWAP_MEMBERS',
214   `ifelse($#,1,`/**/',
215      `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
217 # SWAP_STRUCT(CTYPE,SIZE) -- Generate code to swap an ELF structure.
218 define(`SWAP_STRUCT',
219   `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
220                         SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
222 # WRITE_FIELD(ELFTYPE,FIELDNAME) -- Generate code to write one field.
223 define(`WRITE_FIELD',
224   `ifdef(`SIZEDEP_'$2,
225     `WRITE_$2'SZ()`(dst,t.$1);
226                 ',
227     `WRITE_$2(dst,t.$1);
228                 ')')
230 # WRITE_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
231 define(`WRITE_MEMBERS',
232   `ifelse($#,1,`/**/',
233     `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
235 # WRITE_STRUCT(CTYPE,SIZE) -- Generate code to write out an ELF structure.
236 define(`WRITE_STRUCT',
237   `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
238                 WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
240 # READ_FIELD(ELFTYPE,CTYPE) -- Generate code to read one field.
241 define(`READ_FIELD',
242   `ifdef(`SIZEDEP_'$2,
243     `READ_$2'SZ()`(s,t.$1);
244                 ',
245     `READ_$2(s,t.$1);
246                 ')')
248 # READ_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
249 define(`READ_MEMBERS',
250   `ifelse($#,1,`/**/',
251     `READ_FIELD($1)READ_MEMBERS(shift($@))')')
253 # READ_STRUCT(CTYPE,SIZE) -- Generate code to read an ELF structure.
254 define(`READ_STRUCT',
255   `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
256                 READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
259 # MAKECOMPFUNCS -- Generate converters for composite ELF structures.
261 # When converting data to file representation, the source pointer will
262 # be naturally aligned for a data structure's in-memory
263 # representation.  When converting data to memory, the destination
264 # pointer will be similarly aligned.
266 # For in-place conversions, when converting to file representations,
267 # the source buffer is large enough to hold `file' data.  When
268 # converting from file to memory, we need to be careful to work
269 # `backwards', to avoid overwriting unconverted data.
271 # Macro use:
272 # `$1': Name of the ELF type.
273 # `$2': C structure name suffix.
274 # `$3': ELF class specifier, one of [`', `32', `64']
275 define(`MAKECOMPFUNCS', `ifdef(`NOFUNC_'$1$3,`',`
276 static int
277 _libelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count,
278     int byteswap)
280         Elf$3_$2        t, *s;
281         size_t c;
283         (void) dsz;
285         s = (Elf$3_$2 *) (uintptr_t) src;
286         for (c = 0; c < count; c++) {
287                 t = *s++;
288                 if (byteswap) {
289                         SWAP_STRUCT($2,$3)
290                 }
291                 WRITE_STRUCT($2,$3)
292         }
294         return (1);
297 static int
298 _libelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count,
299     int byteswap)
301         Elf$3_$2         t, *d;
302         char            *s,*s0;
303         size_t          fsz;
305         fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
306         d   = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
307         s0  = (char *) src + (count - 1) * fsz;
309         if (dsz < count * sizeof(Elf$3_$2))
310                 return (0);
312         while (count--) {
313                 s = s0;
314                 READ_STRUCT($2,$3)
315                 if (byteswap) {
316                         SWAP_STRUCT($2,$3)
317                 }
318                 *d-- = t; s0 -= fsz;
319         }
321         return (1);
323 ')')
325 # MAKE_TYPE_CONVERTER(ELFTYPE,CTYPE)
327 # Make type convertor functions from the type definition
328 # of the ELF type:
329 # - Skip convertors marked as `NOFUNC'.
330 # - Invoke `MAKEPRIMFUNCS' or `MAKECOMPFUNCS' as appropriate.
331 define(`MAKE_TYPE_CONVERTER',
332   `ifdef(`NOFUNC_'$1,`',
333     `ifdef(`PRIM_'$1,
334       `ifdef(`SIZEDEP_'$1,
335         `MAKEPRIMFUNCS($1,$2,32,32)dnl
336          MAKEPRIMFUNCS($1,$2,64,64)',
337         `MAKEPRIMFUNCS($1,$2,64)')',
338       `MAKECOMPFUNCS($1,$2,32)dnl
339        MAKECOMPFUNCS($1,$2,64)')')')
341 # MAKE_TYPE_CONVERTERS(ELFTYPELIST) -- Generate conversion functions.
342 define(`MAKE_TYPE_CONVERTERS',
343   `ifelse($#,1,`',
344     `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
348 # Macros to generate entries for the table of convertors.
351 # CONV(ELFTYPE,SIZE,DIRECTION)
353 # Generate the name of a convertor function.
354 define(`CONV',
355   `ifdef(`NOFUNC_'$1$2,
356     `.$3$2 = NULL',
357     `ifdef(`PRIM_'$1,
358       `ifdef(`SIZEDEP_'$1,
359         `.$3$2 = _libelf_cvt_$1$2_$3',
360         `.$3$2 = _libelf_cvt_$1_$3')',
361       `.$3$2 = _libelf_cvt_$1$2_$3')')')
363 # CONVERTER_NAME(ELFTYPE)
365 # Generate the contents of one `struct cvt' instance.
366 define(`CONVERTER_NAME',
367   `ifdef(`NOCVT_'$1,`',
368     `   [ELF_T_$1] = {
369                 CONV($1,32,tof),
370                 CONV($1,32,tom),
371                 CONV($1,64,tof),
372                 CONV($1,64,tom)
373         },
375 ')')
377 # CONVERTER_NAMES(ELFTYPELIST)
379 # Generate the `struct cvt[]' array.
380 define(`CONVERTER_NAMES',
381   `ifelse($#,1,`',
382     `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
385 # Handling ELF version sections.
388 # _FSZ(FIELD,BASETYPE) - return the file size for a field.
389 define(`_FSZ',
390   `ifelse($2,`HALF',2,
391      $2,`WORD',4)')
393 # FSZ(STRUCT) - determine the file size of a structure.
394 define(`FSZ',
395   `ifelse($#,1,0,
396     `eval(_FSZ($1) + FSZ(shift($@)))')')
398 # MAKE_VERSION_CONVERTERS(TYPE,BASE,AUX,PFX) -- Generate conversion
399 # functions for versioning structures.
400 define(`MAKE_VERSION_CONVERTERS',
401   `MAKE_VERSION_CONVERTER($1,$2,$3,$4,32)
402    MAKE_VERSION_CONVERTER($1,$2,$3,$4,64)')
404 # MAKE_VERSION_CONVERTOR(TYPE,CBASE,CAUX,PFX,SIZE) -- Generate a
405 # conversion function.
406 define(`MAKE_VERSION_CONVERTER',`
407 static int
408 _libelf_cvt_$1$5_tof(char *dst, size_t dsz, char *src, size_t count,
409     int byteswap)
411         Elf$5_$2        t;
412         Elf$5_$3        a;
413         const size_t    verfsz = FSZ(Elf$5_$2_DEF);
414         const size_t    auxfsz = FSZ(Elf$5_$3_DEF);
415         const size_t    vermsz = sizeof(Elf$5_$2);
416         const size_t    auxmsz = sizeof(Elf$5_$3);
417         char * const    dstend = dst + dsz;
418         char * const    srcend = src + count;
419         char            *dtmp, *dstaux, *srcaux;
420         Elf$5_Word      aux, anext, cnt, vnext;
422         for (dtmp = dst, vnext = ~0;
423              vnext != 0 && dtmp + verfsz <= dstend && src + vermsz <= srcend;
424              dtmp += vnext, src += vnext) {
426                 /* Read in an Elf$5_$2 structure. */
427                 t = *((Elf$5_$2 *) (uintptr_t) src);
429                 aux = t.$4_aux;
430                 cnt = t.$4_cnt;
431                 vnext = t.$4_next;
433                 if (byteswap) {
434                         SWAP_STRUCT($2, $5)
435                 }
437                 dst = dtmp;
438                 WRITE_STRUCT($2, $5)
440                 if (aux < verfsz)
441                         return (0);
443                 /* Process AUX entries. */
444                 for (anext = ~0, dstaux = dtmp + aux, srcaux = src + aux;
445                      cnt != 0 && anext != 0 && dstaux + auxfsz <= dstend &&
446                         srcaux + auxmsz <= srcend;
447                      dstaux += anext, srcaux += anext, cnt--) {
449                         /* Read in an Elf$5_$3 structure. */
450                         a = *((Elf$5_$3 *) (uintptr_t) srcaux);
451                         anext = a.$4a_next;
453                         if (byteswap) {
454                                 pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
455                         }
457                         dst = dstaux;
458                         pushdef(`t',`a')WRITE_STRUCT($3, $5)popdef(`t')
459                 }
461                 if (anext || cnt)
462                         return (0);
463         }
465         if (vnext)
466                 return (0);
468         return (1);
471 static int
472 _libelf_cvt_$1$5_tom(char *dst, size_t dsz, char *src, size_t count,
473     int byteswap)
475         Elf$5_$2        t, *dp;
476         Elf$5_$3        a, *ap;
477         const size_t    verfsz = FSZ(Elf$5_$2_DEF);
478         const size_t    auxfsz = FSZ(Elf$5_$3_DEF);
479         const size_t    vermsz = sizeof(Elf$5_$2);
480         const size_t    auxmsz = sizeof(Elf$5_$3);
481         char * const    dstend = dst + dsz;
482         char * const    srcend = src + count;
483         char            *dstaux, *s, *srcaux, *stmp;
484         Elf$5_Word      aux, anext, cnt, vnext;
486         for (stmp = src, vnext = ~0;
487              vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
488              stmp += vnext, dst += vnext) {
490                 /* Read in a $1 structure. */
491                 s = stmp;
492                 READ_STRUCT($2, $5)
493                 if (byteswap) {
494                         SWAP_STRUCT($2, $5)
495                 }
497                 dp = (Elf$5_$2 *) (uintptr_t) dst;
498                 *dp = t;
500                 aux = t.$4_aux;
501                 cnt = t.$4_cnt;
502                 vnext = t.$4_next;
504                 if (aux < vermsz)
505                         return (0);
507                 /* Process AUX entries. */
508                 for (anext = ~0, dstaux = dst + aux, srcaux = stmp + aux;
509                      cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
510                         srcaux + auxfsz <= srcend;
511                      dstaux += anext, srcaux += anext, cnt--) {
513                         s = srcaux;
514                         pushdef(`t',`a')READ_STRUCT($3, $5)popdef(`t')
516                         if (byteswap) {
517                                 pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
518                         }
520                         anext = a.$4a_next;
522                         ap = ((Elf$5_$3 *) (uintptr_t) dstaux);
523                         *ap = a;
524                 }
526                 if (anext || cnt)
527                         return (0);
528         }
530         if (vnext)
531                 return (0);
533         return (1);
536 divert(0)
539  * C macros to byte swap integral quantities.
540  */
542 #define SWAP_BYTE(X)    do { (void) (X); } while (0)
543 #define SWAP_IDENT(X)   do { (void) (X); } while (0)
544 #define SWAP_HALF(X)    do {                                            \
545                 uint16_t _x = (uint16_t) (X);                           \
546                 uint32_t _t = _x & 0xFF;                                \
547                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
548                 (X) = _t;                                               \
549         } while (/*CONSTCOND*/0)
550 #define SWAP_WORD(X)    do {                                            \
551                 uint32_t _x = (uint32_t) (X);                           \
552                 uint32_t _t = _x & 0xFF;                                \
553                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
554                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
555                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
556                 (X) = _t;                                               \
557         } while (/*CONSTCOND*/0)
558 #define SWAP_ADDR32(X)  SWAP_WORD(X)
559 #define SWAP_OFF32(X)   SWAP_WORD(X)
560 #define SWAP_SWORD(X)   SWAP_WORD(X)
561 #define SWAP_WORD64(X)  do {                                            \
562                 uint64_t _x = (uint64_t) (X);                           \
563                 uint64_t _t = _x & 0xFF;                                \
564                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
565                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
566                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
567                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
568                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
569                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
570                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
571                 (X) = _t;                                               \
572         } while (/*CONSTCOND*/0)
573 #define SWAP_ADDR64(X)  SWAP_WORD64(X)
574 #define SWAP_LWORD(X)   SWAP_WORD64(X)
575 #define SWAP_OFF64(X)   SWAP_WORD64(X)
576 #define SWAP_SXWORD(X)  SWAP_WORD64(X)
577 #define SWAP_XWORD(X)   SWAP_WORD64(X)
580  * C macros to write out various integral values.
582  * Note:
583  * - The destination pointer could be unaligned.
584  * - Values are written out in native byte order.
585  * - The destination pointer is incremented after the write.
586  */
587 #define WRITE_BYTE(P,X) do {                                            \
588                 char *const _p = (void *) (P);                          \
589                 _p[0]           = (char) (X);                           \
590                 (P)             = (void *)(_p + 1);                     \
591         } while (/*CONSTCOND*/0)
592 #define WRITE_HALF(P,X) do {                                            \
593                 union {                                                 \
594                         uint16_t val;                                   \
595                         uint8_t bytes[2];                               \
596                 } _t;                                                   \
597                 unsigned char *const _p = (void *) (P);                 \
598                 _t.val = (X);                                           \
599                 _p[0]           = _t.bytes[0];                          \
600                 _p[1]           = _t.bytes[1];                          \
601                 (P)             = (void *)(_p + 2);                     \
602         } while (/*CONSTCOND*/0)
603 #define WRITE_WORD(P,X) do {                                            \
604                 union {                                                 \
605                         uint32_t val;                                   \
606                         uint8_t bytes[4];                               \
607                 } _t;                                                   \
608                 unsigned char *const _p = (void *) (P);                 \
609                 _t.val = (X);                                           \
610                 _p[0]           = _t.bytes[0];                          \
611                 _p[1]           = _t.bytes[1];                          \
612                 _p[2]           = _t.bytes[2];                          \
613                 _p[3]           = _t.bytes[3];                          \
614                 (P)             = (void *)(_p + 4);                     \
615         } while (/*CONSTCOND*/0)
616 #define WRITE_ADDR32(P,X)       WRITE_WORD(P,X)
617 #define WRITE_OFF32(P,X)        WRITE_WORD(P,X)
618 #define WRITE_SWORD(P,X)        WRITE_WORD(P,X)
619 #define WRITE_WORD64(P,X)       do {                                    \
620                 union {                                                 \
621                         uint64_t val;                                   \
622                         uint8_t bytes[8];                               \
623                 } _t;                                                   \
624                 unsigned char *const _p = (void *) (P);                 \
625                 _t.val = (X);                                           \
626                 _p[0]           = _t.bytes[0];                          \
627                 _p[1]           = _t.bytes[1];                          \
628                 _p[2]           = _t.bytes[2];                          \
629                 _p[3]           = _t.bytes[3];                          \
630                 _p[4]           = _t.bytes[4];                          \
631                 _p[5]           = _t.bytes[5];                          \
632                 _p[6]           = _t.bytes[6];                          \
633                 _p[7]           = _t.bytes[7];                          \
634                 (P)             = (void *)(_p + 8);                     \
635         } while (/*CONSTCOND*/0)
636 #define WRITE_ADDR64(P,X)       WRITE_WORD64(P,X)
637 #define WRITE_LWORD(P,X)        WRITE_WORD64(P,X)
638 #define WRITE_OFF64(P,X)        WRITE_WORD64(P,X)
639 #define WRITE_SXWORD(P,X)       WRITE_WORD64(P,X)
640 #define WRITE_XWORD(P,X)        WRITE_WORD64(P,X)
641 #define WRITE_IDENT(P,X)        do {                                    \
642                 (void) memcpy((P), (X), sizeof((X)));                   \
643                 (P)             = (P) + EI_NIDENT;                      \
644         } while (/*CONSTCOND*/0)
647  * C macros to read in various integral values.
649  * Note:
650  * - The source pointer could be unaligned.
651  * - Values are read in native byte order.
652  * - The source pointer is incremented appropriately.
653  */
655 #define READ_BYTE(P,X)  do {                                            \
656                 const char *const _p =                                  \
657                         (const void *) (P);                             \
658                 (X)             = _p[0];                                \
659                 (P)             = (P) + 1;                              \
660         } while (/*CONSTCOND*/0)
661 #define READ_HALF(P,X)  do {                                            \
662                 uint16_t _t;                                            \
663                 char *const _q = (char *) &_t;  \
664                 const char *const _p =                          \
665                         (const char *) (P);                     \
666                 _q[0]           = _p[0];                                \
667                 _q[1]           = _p[1];                                \
668                 (P)             = (P) + 2;                              \
669                 (X)             = _t;                                   \
670         } while (/*CONSTCOND*/0)
671 #define READ_WORD(P,X)  do {                                            \
672                 uint32_t _t;                                            \
673                 char *const _q = (void *) &_t;  \
674                 const char *const _p =                          \
675                         (const void *) (P);                     \
676                 _q[0]           = _p[0];                                \
677                 _q[1]           = _p[1];                                \
678                 _q[2]           = _p[2];                                \
679                 _q[3]           = _p[3];                                \
680                 (P)             = (P) + 4;                              \
681                 (X)             = _t;                                   \
682         } while (/*CONSTCOND*/0)
683 #define READ_ADDR32(P,X)        READ_WORD(P,X)
684 #define READ_OFF32(P,X)         READ_WORD(P,X)
685 #define READ_SWORD(P,X)         READ_WORD(P,X)
686 #define READ_WORD64(P,X)        do {                                    \
687                 uint64_t _t;                                            \
688                 char *const _q = (void *) &_t;  \
689                 const char *const _p =                          \
690                         (const void *) (P);                     \
691                 _q[0]           = _p[0];                                \
692                 _q[1]           = _p[1];                                \
693                 _q[2]           = _p[2];                                \
694                 _q[3]           = _p[3];                                \
695                 _q[4]           = _p[4];                                \
696                 _q[5]           = _p[5];                                \
697                 _q[6]           = _p[6];                                \
698                 _q[7]           = _p[7];                                \
699                 (P)             = (P) + 8;                              \
700                 (X)             = _t;                                   \
701         } while (/*CONSTCOND*/0)
702 #define READ_ADDR64(P,X)        READ_WORD64(P,X)
703 #define READ_LWORD(P,X)         READ_WORD64(P,X)
704 #define READ_OFF64(P,X)         READ_WORD64(P,X)
705 #define READ_SXWORD(P,X)        READ_WORD64(P,X)
706 #define READ_XWORD(P,X)         READ_WORD64(P,X)
707 #define READ_IDENT(P,X)         do {                                    \
708                 (void) memcpy((X), (P), sizeof((X)));                   \
709                 (P)             = (P) + EI_NIDENT;                      \
710         } while (/*CONSTCOND*/0)
712 #define ROUNDUP2(V,N)   (V) = ((((V) + (N) - 1)) & ~((N) - 1))
714 /*[*/
715 MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
716 MAKE_VERSION_CONVERTERS(VDEF,Verdef,Verdaux,vd)
717 MAKE_VERSION_CONVERTERS(VNEED,Verneed,Vernaux,vn)
718 /*]*/
721  * Sections of type ELF_T_BYTE are never byteswapped, consequently a
722  * simple memcpy suffices for both directions of conversion.
723  */
725 /*ARGSUSED*/
726 static int
727 _libelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count,
728     int byteswap)
730         (void) byteswap;
731         if (dsz < count)
732                 return (0);
733         if (dst != src)
734                 (void) memcpy(dst, src, count);
735         return (1);
739  * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit
740  * words.  Bloom filter data comes next, followed by hash buckets and the
741  * hash chain.
743  * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit
744  * wide on ELFCLASS32 objects.  The other objects in this section are 32
745  * bits wide.
747  * Argument `srcsz' denotes the number of bytes to be converted.  In the
748  * 32-bit case we need to translate `srcsz' to a count of 32-bit words.
749  */
751 static int
752 _libelf_cvt_GNUHASH32_tom(char *dst, size_t dsz, char *src, size_t srcsz,
753     int byteswap)
755         return (_libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t),
756                 byteswap));
759 static int
760 _libelf_cvt_GNUHASH32_tof(char *dst, size_t dsz, char *src, size_t srcsz,
761     int byteswap)
763         return (_libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t),
764                 byteswap));
767 static int
768 _libelf_cvt_GNUHASH64_tom(char *dst, size_t dsz, char *src, size_t srcsz,
769     int byteswap)
771         size_t sz;
772         uint64_t t64, *bloom64;
773         Elf_GNU_Hash_Header *gh;
774         uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
775         uint32_t *buckets, *chains;
777         sz = 4 * sizeof(uint32_t);      /* File header is 4 words long. */
778         if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
779                 return (0);
781         /* Read in the section header and byteswap if needed. */
782         READ_WORD(src, nbuckets);
783         READ_WORD(src, symndx);
784         READ_WORD(src, maskwords);
785         READ_WORD(src, shift2);
787         srcsz -= sz;
789         if (byteswap) {
790                 SWAP_WORD(nbuckets);
791                 SWAP_WORD(symndx);
792                 SWAP_WORD(maskwords);
793                 SWAP_WORD(shift2);
794         }
796         /* Check source buffer and destination buffer sizes. */
797         sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
798         if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
799                 return (0);
801         gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
802         gh->gh_nbuckets  = nbuckets;
803         gh->gh_symndx    = symndx;
804         gh->gh_maskwords = maskwords;
805         gh->gh_shift2    = shift2;
807         dsz -= sizeof(Elf_GNU_Hash_Header);
808         dst += sizeof(Elf_GNU_Hash_Header);
810         bloom64 = (uint64_t *) (uintptr_t) dst;
812         /* Copy bloom filter data. */
813         for (n = 0; n < maskwords; n++) {
814                 READ_XWORD(src, t64);
815                 if (byteswap)
816                         SWAP_XWORD(t64);
817                 bloom64[n] = t64;
818         }
820         /* The hash buckets follows the bloom filter. */
821         dst += maskwords * sizeof(uint64_t);
822         buckets = (uint32_t *) (uintptr_t) dst;
824         for (n = 0; n < nbuckets; n++) {
825                 READ_WORD(src, t32);
826                 if (byteswap)
827                         SWAP_WORD(t32);
828                 buckets[n] = t32;
829         }
831         dst += nbuckets * sizeof(uint32_t);
833         /* The hash chain follows the hash buckets. */
834         dsz -= sz;
835         srcsz -= sz;
837         if (dsz < srcsz)        /* Destination lacks space. */
838                 return (0);
840         nchains = srcsz / sizeof(uint32_t);
841         chains = (uint32_t *) (uintptr_t) dst;
843         for (n = 0; n < nchains; n++) {
844                 READ_WORD(src, t32);
845                 if (byteswap)
846                         SWAP_WORD(t32);
847                 *chains++ = t32;
848         }
850         return (1);
853 static int
854 _libelf_cvt_GNUHASH64_tof(char *dst, size_t dsz, char *src, size_t srcsz,
855     int byteswap)
857         uint32_t *s32;
858         size_t sz, hdrsz;
859         uint64_t *s64, t64;
860         Elf_GNU_Hash_Header *gh;
861         uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32;
863         hdrsz = 4 * sizeof(uint32_t);   /* Header is 4x32 bits. */
864         if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header))
865                 return (0);
867         gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
869         t0 = nbuckets = gh->gh_nbuckets;
870         t1 = gh->gh_symndx;
871         t2 = maskwords = gh->gh_maskwords;
872         t3 = gh->gh_shift2;
874         src   += sizeof(Elf_GNU_Hash_Header);
875         srcsz -= sizeof(Elf_GNU_Hash_Header);
876         dsz   -= hdrsz;
878         sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
879             sizeof(uint64_t);
881         if (srcsz < sz || dsz < sz)
882                 return (0);
884         /* Write out the header. */
885         if (byteswap) {
886                 SWAP_WORD(t0);
887                 SWAP_WORD(t1);
888                 SWAP_WORD(t2);
889                 SWAP_WORD(t3);
890         }
892         WRITE_WORD(dst, t0);
893         WRITE_WORD(dst, t1);
894         WRITE_WORD(dst, t2);
895         WRITE_WORD(dst, t3);
897         /* Copy the bloom filter and the hash table. */
898         s64 = (uint64_t *) (uintptr_t) src;
899         for (n = 0; n < maskwords; n++) {
900                 t64 = *s64++;
901                 if (byteswap)
902                         SWAP_XWORD(t64);
903                 WRITE_WORD64(dst, t64);
904         }
906         s32 = (uint32_t *) s64;
907         for (n = 0; n < nbuckets; n++) {
908                 t32 = *s32++;
909                 if (byteswap)
910                         SWAP_WORD(t32);
911                 WRITE_WORD(dst, t32);
912         }
914         srcsz -= sz;
915         dsz   -= sz;
917         /* Copy out the hash chains. */
918         if (dsz < srcsz)
919                 return (0);
921         nchains = srcsz / sizeof(uint32_t);
922         for (n = 0; n < nchains; n++) {
923                 t32 = *s32++;
924                 if (byteswap)
925                         SWAP_WORD(t32);
926                 WRITE_WORD(dst, t32);
927         }
929         return (1);
933  * Elf note structures comprise a fixed size header followed by variable
934  * length strings.  The fixed size header needs to be byte swapped, but
935  * not the strings.
937  * Argument `count' denotes the total number of bytes to be converted.
938  * The destination buffer needs to be at least `count' bytes in size.
939  */
940 static int
941 _libelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count,
942     int byteswap)
944         uint32_t namesz, descsz, type;
945         Elf_Note *en;
946         size_t sz, hdrsz;
948         if (dsz < count)        /* Destination buffer is too small. */
949                 return (0);
951         hdrsz = 3 * sizeof(uint32_t);
952         if (count < hdrsz)              /* Source too small. */
953                 return (0);
955         if (!byteswap) {
956                 (void) memcpy(dst, src, count);
957                 return (1);
958         }
960         /* Process all notes in the section. */
961         while (count > hdrsz) {
962                 /* Read the note header. */
963                 READ_WORD(src, namesz);
964                 READ_WORD(src, descsz);
965                 READ_WORD(src, type);
967                 /* Translate. */
968                 SWAP_WORD(namesz);
969                 SWAP_WORD(descsz);
970                 SWAP_WORD(type);
972                 /* Copy out the translated note header. */
973                 en = (Elf_Note *) (uintptr_t) dst;
974                 en->n_namesz = namesz;
975                 en->n_descsz = descsz;
976                 en->n_type = type;
978                 dsz -= sizeof(Elf_Note);
979                 dst += sizeof(Elf_Note);
980                 count -= hdrsz;
982                 ROUNDUP2(namesz, 4);
983                 ROUNDUP2(descsz, 4);
985                 sz = namesz + descsz;
987                 if (count < sz || dsz < sz)     /* Buffers are too small. */
988                         return (0);
990                 (void) memcpy(dst, src, sz);
992                 src += sz;
993                 dst += sz;
995                 count -= sz;
996                 dsz -= sz;
997         }
999         return (1);
1002 static int
1003 _libelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count,
1004     int byteswap)
1006         uint32_t namesz, descsz, type;
1007         Elf_Note *en;
1008         size_t sz;
1010         if (dsz < count)
1011                 return (0);
1013         if (!byteswap) {
1014                 (void) memcpy(dst, src, count);
1015                 return (1);
1016         }
1018         while (count > sizeof(Elf_Note)) {
1020                 en = (Elf_Note *) (uintptr_t) src;
1021                 namesz = en->n_namesz;
1022                 descsz = en->n_descsz;
1023                 type = en->n_type;
1025                 SWAP_WORD(namesz);
1026                 SWAP_WORD(descsz);
1027                 SWAP_WORD(type);
1029                 WRITE_WORD(dst, namesz);
1030                 WRITE_WORD(dst, descsz);
1031                 WRITE_WORD(dst, type);
1033                 src += sizeof(Elf_Note);
1035                 ROUNDUP2(namesz, 4);
1036                 ROUNDUP2(descsz, 4);
1038                 sz = namesz + descsz;
1040                 if (count < sz)
1041                         sz = count;
1043                 (void) memcpy(dst, src, sz);
1045                 src += sz;
1046                 dst += sz;
1047                 count -= sz;
1048         }
1050         return (1);
1053 struct converters {
1054         int     (*tof32)(char *dst, size_t dsz, char *src, size_t cnt,
1055                     int byteswap);
1056         int     (*tom32)(char *dst, size_t dsz, char *src, size_t cnt,
1057                     int byteswap);
1058         int     (*tof64)(char *dst, size_t dsz, char *src, size_t cnt,
1059                     int byteswap);
1060         int     (*tom64)(char *dst, size_t dsz, char *src, size_t cnt,
1061                     int byteswap);
1065 static struct converters cvt[ELF_T_NUM] = {
1066         /*[*/
1067 CONVERTER_NAMES(ELF_TYPE_LIST)
1068         /*]*/
1070         /*
1071          * Types that need hand-coded converters follow.
1072          */
1074         [ELF_T_BYTE] = {
1075                 .tof32 = _libelf_cvt_BYTE_tox,
1076                 .tom32 = _libelf_cvt_BYTE_tox,
1077                 .tof64 = _libelf_cvt_BYTE_tox,
1078                 .tom64 = _libelf_cvt_BYTE_tox
1079         },
1081         [ELF_T_NOTE] = {
1082                 .tof32 = _libelf_cvt_NOTE_tof,
1083                 .tom32 = _libelf_cvt_NOTE_tom,
1084                 .tof64 = _libelf_cvt_NOTE_tof,
1085                 .tom64 = _libelf_cvt_NOTE_tom
1086         }
1089 int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
1090  (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap)
1092         assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
1093         assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
1095         if (t >= ELF_T_NUM ||
1096             (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
1097             (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
1098                 return (NULL);
1100         return ((elfclass == ELFCLASS32) ?
1101             (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
1102             (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));