Import ELF Tool Chain snapshot at revision 3475
[freebsd-src.git] / libelf / libelf_convert.m4
blobec395902a182c59bc5522ad9b5910d328fcf5063
1 /*-
2  * Copyright (c) 2006-2011 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  */
27 #include <assert.h>
28 #include <libelf.h>
29 #include <string.h>
31 #include "_libelf.h"
33 ELFTC_VCSID("$Id: libelf_convert.m4 3429 2016-03-12 04:12:39Z emaste $");
35 /* WARNING: GENERATED FROM __file__. */
37 divert(-1)
39 # Generate conversion routines for converting between in-memory and
40 # file representations of Elf data structures.
42 # These conversions use the type information defined in `elf_types.m4'.
44 include(SRCDIR`/elf_types.m4')
46 # For the purposes of generating conversion code, ELF types may be
47 # classified according to the following characteristics:
49 # 1. Whether the ELF type can be directly mapped to an integral C
50 #    language type.  For example, the ELF_T_WORD type maps directly to
51 #    a 'uint32_t', but ELF_T_GNUHASH lacks a matching C type.
53 # 2. Whether the type has word size dependent variants.  For example,
54 #    ELT_T_EHDR is represented using C types Elf32_Ehdr and El64_Ehdr,
55 #    and the ELF_T_ADDR and ELF_T_OFF types have integral C types that
56 #    can be 32- or 64- bit wide.
58 # 3. Whether the ELF types has a fixed representation or not.  For
59 #    example, the ELF_T_SYM type has a fixed size file representation,
60 #    some types like ELF_T_NOTE and ELF_T_GNUHASH use a variable size
61 #    representation.
63 # We use m4 macros to generate conversion code for ELF types that have
64 # a fixed size representation.  Conversion functions for the remaining
65 # types are coded by hand.
67 #* Handling File and Memory Representations
69 # `In-memory' representations of an Elf data structure use natural
70 # alignments and native byte ordering.  This allows pointer arithmetic
71 # and casting to work as expected.  On the other hand, the `file'
72 # representation of an ELF data structure could possibly be packed
73 # tighter than its `in-memory' representation, and could be of a
74 # differing byte order.  Reading ELF objects that are members of `ar'
75 # archives present an additional complication: `ar' pads file data to
76 # even addresses, so file data structures in an archive member
77 # residing inside an `ar' archive could be at misaligned memory
78 # addresses when brought into memory.
80 # In summary, casting the `char *' pointers that point to memory
81 # representations (i.e., source pointers for the *_tof() functions and
82 # the destination pointers for the *_tom() functions), is safe, as
83 # these pointers should be correctly aligned for the memory type
84 # already.  However, pointers to file representations have to be
85 # treated as being potentially unaligned and no casting can be done.
87 # NOCVT(TYPE) -- Do not generate the cvt[] structure entry for TYPE
88 define(`NOCVT',`define(`NOCVT_'$1,1)')
90 # NOFUNC(TYPE) -- Do not generate a conversion function for TYPE
91 define(`NOFUNC',`define(`NOFUNC_'$1,1)')
93 # IGNORE(TYPE) -- Completely ignore the type.
94 define(`IGNORE',`NOCVT($1)NOFUNC($1)')
96 # Mark ELF types that should not be processed by the M4 macros below.
98 # Types for which we use functions with non-standard names.
99 IGNORE(`BYTE')                  # Uses a wrapper around memcpy().
100 IGNORE(`NOTE')                  # Not a fixed size type.
102 # Types for which we supply hand-coded functions.
103 NOFUNC(`GNUHASH')               # A type with complex internal structure.
104 NOFUNC(`VDEF')                  # See MAKE_VERSION_CONVERTERS below.
105 NOFUNC(`VNEED')                 # ..
107 # Unimplemented types.
108 IGNORE(`MOVEP')
110 # ELF types that don't exist in a 32-bit world.
111 NOFUNC(`XWORD32')
112 NOFUNC(`SXWORD32')
114 # `Primitive' ELF types are those that are an alias for an integral
115 # type.  As they have no internal structure, they can be copied using
116 # a `memcpy()', and byteswapped in straightforward way.
118 # Mark all ELF types that directly map to integral C types.
119 define(`PRIM_ADDR',     1)
120 define(`PRIM_BYTE',     1)
121 define(`PRIM_HALF',     1)
122 define(`PRIM_LWORD',    1)
123 define(`PRIM_OFF',      1)
124 define(`PRIM_SWORD',    1)
125 define(`PRIM_SXWORD',   1)
126 define(`PRIM_WORD',     1)
127 define(`PRIM_XWORD',    1)
129 # Note the primitive types that are size-dependent.
130 define(`SIZEDEP_ADDR',  1)
131 define(`SIZEDEP_OFF',   1)
133 # Generate conversion functions for primitive types.
135 # Macro use: MAKEPRIMFUNCS(ELFTYPE,CTYPE,TYPESIZE,SYMSIZE)
136 # `$1': Name of the ELF type.
137 # `$2': C structure name suffix.
138 # `$3': ELF class specifier for types, one of [`32', `64'].
139 # `$4': Additional ELF class specifier, one of [`', `32', `64'].
141 # Generates a pair of conversion functions.
142 define(`MAKEPRIMFUNCS',`
143 static int
144 _libelf_cvt_$1$4_tof(unsigned char *dst, size_t dsz, unsigned char *src,
145     size_t count, int byteswap)
147         Elf$3_$2 t, *s = (Elf$3_$2 *) (uintptr_t) src;
148         size_t c;
150         (void) dsz;
152         if (!byteswap) {
153                 (void) memcpy(dst, src, count * sizeof(*s));
154                 return (1);
155         }
157         for (c = 0; c < count; c++) {
158                 t = *s++;
159                 SWAP_$1$4(t);
160                 WRITE_$1$4(dst,t);
161         }
163         return (1);
166 static int
167 _libelf_cvt_$1$4_tom(unsigned char *dst, size_t dsz, unsigned char *src,
168     size_t count, int byteswap)
170         Elf$3_$2 t, *d = (Elf$3_$2 *) (uintptr_t) dst;
171         size_t c;
173         if (dsz < count * sizeof(Elf$3_$2))
174                 return (0);
176         if (!byteswap) {
177                 (void) memcpy(dst, src, count * sizeof(*d));
178                 return (1);
179         }
181         for (c = 0; c < count; c++) {
182                 READ_$1$4(src,t);
183                 SWAP_$1$4(t);
184                 *d++ = t;
185         }
187         return (1);
192 # Handling composite ELF types
195 # SWAP_FIELD(FIELDNAME,ELFTYPE) -- Generate code to swap one field.
196 define(`SWAP_FIELD',
197   `ifdef(`SIZEDEP_'$2,
198     `SWAP_$2'SZ()`(t.$1);
199                         ',
200     `SWAP_$2(t.$1);
201                         ')')
203 # SWAP_MEMBERS(STRUCT) -- Iterate over a structure definition.
204 define(`SWAP_MEMBERS',
205   `ifelse($#,1,`/**/',
206      `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
208 # SWAP_STRUCT(CTYPE,SIZE) -- Generate code to swap an ELF structure.
209 define(`SWAP_STRUCT',
210   `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
211                         SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
213 # WRITE_FIELD(ELFTYPE,FIELDNAME) -- Generate code to write one field.
214 define(`WRITE_FIELD',
215   `ifdef(`SIZEDEP_'$2,
216     `WRITE_$2'SZ()`(dst,t.$1);
217                 ',
218     `WRITE_$2(dst,t.$1);
219                 ')')
221 # WRITE_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
222 define(`WRITE_MEMBERS',
223   `ifelse($#,1,`/**/',
224     `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
226 # WRITE_STRUCT(CTYPE,SIZE) -- Generate code to write out an ELF structure.
227 define(`WRITE_STRUCT',
228   `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
229                 WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
231 # READ_FIELD(ELFTYPE,CTYPE) -- Generate code to read one field.
232 define(`READ_FIELD',
233   `ifdef(`SIZEDEP_'$2,
234     `READ_$2'SZ()`(s,t.$1);
235                 ',
236     `READ_$2(s,t.$1);
237                 ')')
239 # READ_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
240 define(`READ_MEMBERS',
241   `ifelse($#,1,`/**/',
242     `READ_FIELD($1)READ_MEMBERS(shift($@))')')
244 # READ_STRUCT(CTYPE,SIZE) -- Generate code to read an ELF structure.
245 define(`READ_STRUCT',
246   `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
247                 READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
250 # MAKECOMPFUNCS -- Generate converters for composite ELF structures.
252 # When converting data to file representation, the source pointer will
253 # be naturally aligned for a data structure's in-memory
254 # representation.  When converting data to memory, the destination
255 # pointer will be similarly aligned.
257 # For in-place conversions, when converting to file representations,
258 # the source buffer is large enough to hold `file' data.  When
259 # converting from file to memory, we need to be careful to work
260 # `backwards', to avoid overwriting unconverted data.
262 # Macro use:
263 # `$1': Name of the ELF type.
264 # `$2': C structure name suffix.
265 # `$3': ELF class specifier, one of [`', `32', `64']
266 define(`MAKECOMPFUNCS', `ifdef(`NOFUNC_'$1$3,`',`
267 static int
268 _libelf_cvt_$1$3_tof(unsigned char *dst, size_t dsz, unsigned char *src,
269     size_t count, int byteswap)
271         Elf$3_$2        t, *s;
272         size_t c;
274         (void) dsz;
276         s = (Elf$3_$2 *) (uintptr_t) src;
277         for (c = 0; c < count; c++) {
278                 t = *s++;
279                 if (byteswap) {
280                         SWAP_STRUCT($2,$3)
281                 }
282                 WRITE_STRUCT($2,$3)
283         }
285         return (1);
288 static int
289 _libelf_cvt_$1$3_tom(unsigned char *dst, size_t dsz, unsigned char *src,
290     size_t count, int byteswap)
292         Elf$3_$2        t, *d;
293         unsigned char   *s,*s0;
294         size_t          fsz;
296         fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
297         d   = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
298         s0  = src + (count - 1) * fsz;
300         if (dsz < count * sizeof(Elf$3_$2))
301                 return (0);
303         while (count--) {
304                 s = s0;
305                 READ_STRUCT($2,$3)
306                 if (byteswap) {
307                         SWAP_STRUCT($2,$3)
308                 }
309                 *d-- = t; s0 -= fsz;
310         }
312         return (1);
314 ')')
316 # MAKE_TYPE_CONVERTER(ELFTYPE,CTYPE)
318 # Make type convertor functions from the type definition
319 # of the ELF type:
320 # - Skip convertors marked as `NOFUNC'.
321 # - Invoke `MAKEPRIMFUNCS' or `MAKECOMPFUNCS' as appropriate.
322 define(`MAKE_TYPE_CONVERTER',
323   `ifdef(`NOFUNC_'$1,`',
324     `ifdef(`PRIM_'$1,
325       `ifdef(`SIZEDEP_'$1,
326         `MAKEPRIMFUNCS($1,$2,32,32)dnl
327          MAKEPRIMFUNCS($1,$2,64,64)',
328         `MAKEPRIMFUNCS($1,$2,64)')',
329       `MAKECOMPFUNCS($1,$2,32)dnl
330        MAKECOMPFUNCS($1,$2,64)')')')
332 # MAKE_TYPE_CONVERTERS(ELFTYPELIST) -- Generate conversion functions.
333 define(`MAKE_TYPE_CONVERTERS',
334   `ifelse($#,1,`',
335     `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
339 # Macros to generate entries for the table of convertors.
342 # CONV(ELFTYPE,SIZE,DIRECTION)
344 # Generate the name of a convertor function.
345 define(`CONV',
346   `ifdef(`NOFUNC_'$1$2,
347     `.$3$2 = NULL',
348     `ifdef(`PRIM_'$1,
349       `ifdef(`SIZEDEP_'$1,
350         `.$3$2 = _libelf_cvt_$1$2_$3',
351         `.$3$2 = _libelf_cvt_$1_$3')',
352       `.$3$2 = _libelf_cvt_$1$2_$3')')')
354 # CONVERTER_NAME(ELFTYPE)
356 # Generate the contents of one `struct cvt' instance.
357 define(`CONVERTER_NAME',
358   `ifdef(`NOCVT_'$1,`',
359     `   [ELF_T_$1] = {
360                 CONV($1,32,tof),
361                 CONV($1,32,tom),
362                 CONV($1,64,tof),
363                 CONV($1,64,tom)
364         },
366 ')')
368 # CONVERTER_NAMES(ELFTYPELIST)
370 # Generate the `struct cvt[]' array.
371 define(`CONVERTER_NAMES',
372   `ifelse($#,1,`',
373     `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
376 # Handling ELF version sections.
379 # _FSZ(FIELD,BASETYPE) - return the file size for a field.
380 define(`_FSZ',
381   `ifelse($2,`HALF',2,
382      $2,`WORD',4)')
384 # FSZ(STRUCT) - determine the file size of a structure.
385 define(`FSZ',
386   `ifelse($#,1,0,
387     `eval(_FSZ($1) + FSZ(shift($@)))')')
389 # MAKE_VERSION_CONVERTERS(TYPE,BASE,AUX,PFX) -- Generate conversion
390 # functions for versioning structures.
391 define(`MAKE_VERSION_CONVERTERS',
392   `MAKE_VERSION_CONVERTER($1,$2,$3,$4,32)
393    MAKE_VERSION_CONVERTER($1,$2,$3,$4,64)')
395 # MAKE_VERSION_CONVERTOR(TYPE,CBASE,CAUX,PFX,SIZE) -- Generate a
396 # conversion function.
397 define(`MAKE_VERSION_CONVERTER',`
398 static int
399 _libelf_cvt_$1$5_tof(unsigned char *dst, size_t dsz, unsigned char *src,
400     size_t count, int byteswap)
402         Elf$5_$2        t;
403         Elf$5_$3        a;
404         const size_t    verfsz = FSZ(Elf$5_$2_DEF);
405         const size_t    auxfsz = FSZ(Elf$5_$3_DEF);
406         const size_t    vermsz = sizeof(Elf$5_$2);
407         const size_t    auxmsz = sizeof(Elf$5_$3);
408         unsigned char * const dstend = dst + dsz;
409         unsigned char * const srcend = src + count;
410         unsigned char   *dtmp, *dstaux, *srcaux;
411         Elf$5_Word      aux, anext, cnt, vnext;
413         for (dtmp = dst, vnext = ~0U;
414              vnext != 0 && dtmp + verfsz <= dstend && src + vermsz <= srcend;
415              dtmp += vnext, src += vnext) {
417                 /* Read in an Elf$5_$2 structure. */
418                 t = *((Elf$5_$2 *) (uintptr_t) src);
420                 aux = t.$4_aux;
421                 cnt = t.$4_cnt;
422                 vnext = t.$4_next;
424                 if (byteswap) {
425                         SWAP_STRUCT($2, $5)
426                 }
428                 dst = dtmp;
429                 WRITE_STRUCT($2, $5)
431                 if (aux < verfsz)
432                         return (0);
434                 /* Process AUX entries. */
435                 for (anext = ~0U, dstaux = dtmp + aux, srcaux = src + aux;
436                      cnt != 0 && anext != 0 && dstaux + auxfsz <= dstend &&
437                         srcaux + auxmsz <= srcend;
438                      dstaux += anext, srcaux += anext, cnt--) {
440                         /* Read in an Elf$5_$3 structure. */
441                         a = *((Elf$5_$3 *) (uintptr_t) srcaux);
442                         anext = a.$4a_next;
444                         if (byteswap) {
445                                 pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
446                         }
448                         dst = dstaux;
449                         pushdef(`t',`a')WRITE_STRUCT($3, $5)popdef(`t')
450                 }
452                 if (anext || cnt)
453                         return (0);
454         }
456         if (vnext)
457                 return (0);
459         return (1);
462 static int
463 _libelf_cvt_$1$5_tom(unsigned char *dst, size_t dsz, unsigned char *src,
464     size_t count, int byteswap)
466         Elf$5_$2        t, *dp;
467         Elf$5_$3        a, *ap;
468         const size_t    verfsz = FSZ(Elf$5_$2_DEF);
469         const size_t    auxfsz = FSZ(Elf$5_$3_DEF);
470         const size_t    vermsz = sizeof(Elf$5_$2);
471         const size_t    auxmsz = sizeof(Elf$5_$3);
472         unsigned char * const dstend = dst + dsz;
473         unsigned char * const srcend = src + count;
474         unsigned char   *dstaux, *s, *srcaux, *stmp;
475         Elf$5_Word      aux, anext, cnt, vnext;
477         for (stmp = src, vnext = ~0U;
478              vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
479              stmp += vnext, dst += vnext) {
481                 /* Read in a $1 structure. */
482                 s = stmp;
483                 READ_STRUCT($2, $5)
484                 if (byteswap) {
485                         SWAP_STRUCT($2, $5)
486                 }
488                 dp = (Elf$5_$2 *) (uintptr_t) dst;
489                 *dp = t;
491                 aux = t.$4_aux;
492                 cnt = t.$4_cnt;
493                 vnext = t.$4_next;
495                 if (aux < vermsz)
496                         return (0);
498                 /* Process AUX entries. */
499                 for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux;
500                      cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
501                         srcaux + auxfsz <= srcend;
502                      dstaux += anext, srcaux += anext, cnt--) {
504                         s = srcaux;
505                         pushdef(`t',`a')READ_STRUCT($3, $5)popdef(`t')
507                         if (byteswap) {
508                                 pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
509                         }
511                         anext = a.$4a_next;
513                         ap = ((Elf$5_$3 *) (uintptr_t) dstaux);
514                         *ap = a;
515                 }
517                 if (anext || cnt)
518                         return (0);
519         }
521         if (vnext)
522                 return (0);
524         return (1);
527 divert(0)
530  * C macros to byte swap integral quantities.
531  */
533 #define SWAP_BYTE(X)    do { (void) (X); } while (0)
534 #define SWAP_IDENT(X)   do { (void) (X); } while (0)
535 #define SWAP_HALF(X)    do {                                            \
536                 uint16_t _x = (uint16_t) (X);                           \
537                 uint32_t _t = _x & 0xFFU;                               \
538                 _t <<= 8U; _x >>= 8U; _t |= _x & 0xFFU;                 \
539                 (X) = (uint16_t) _t;                                    \
540         } while (0)
541 #define _SWAP_WORD(X, T) do {                                           \
542                 uint32_t _x = (uint32_t) (X);                           \
543                 uint32_t _t = _x & 0xFF;                                \
544                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
545                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
546                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
547                 (X) = (T) _t;                                           \
548         } while (0)
549 #define SWAP_ADDR32(X)  _SWAP_WORD(X, Elf32_Addr)
550 #define SWAP_OFF32(X)   _SWAP_WORD(X, Elf32_Off)
551 #define SWAP_SWORD(X)   _SWAP_WORD(X, Elf32_Sword)
552 #define SWAP_WORD(X)    _SWAP_WORD(X, Elf32_Word)
553 #define _SWAP_WORD64(X, T) do {                                         \
554                 uint64_t _x = (uint64_t) (X);                           \
555                 uint64_t _t = _x & 0xFF;                                \
556                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
557                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
558                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
559                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
560                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
561                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
562                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
563                 (X) = (T) _t;                                           \
564         } while (0)
565 #define SWAP_ADDR64(X)  _SWAP_WORD64(X, Elf64_Addr)
566 #define SWAP_LWORD(X)   _SWAP_WORD64(X, Elf64_Lword)
567 #define SWAP_OFF64(X)   _SWAP_WORD64(X, Elf64_Off)
568 #define SWAP_SXWORD(X)  _SWAP_WORD64(X, Elf64_Sxword)
569 #define SWAP_XWORD(X)   _SWAP_WORD64(X, Elf64_Xword)
572  * C macros to write out various integral values.
574  * Note:
575  * - The destination pointer could be unaligned.
576  * - Values are written out in native byte order.
577  * - The destination pointer is incremented after the write.
578  */
579 #define WRITE_BYTE(P,X) do {                                            \
580                 unsigned char *const _p = (unsigned char *) (P);        \
581                 _p[0]           = (unsigned char) (X);                  \
582                 (P)             = _p + 1;                               \
583         } while (0)
584 #define WRITE_HALF(P,X) do {                                            \
585                 uint16_t _t     = (X);                                  \
586                 unsigned char *const _p = (unsigned char *) (P);        \
587                 const unsigned char *const _q = (unsigned char *) &_t;  \
588                 _p[0]           = _q[0];                                \
589                 _p[1]           = _q[1];                                \
590                 (P)             = _p + 2;                               \
591         } while (0)
592 #define WRITE_WORD(P,X) do {                                            \
593                 uint32_t _t     = (uint32_t) (X);                       \
594                 unsigned char *const _p = (unsigned char *) (P);        \
595                 const unsigned char *const _q = (unsigned char *) &_t;  \
596                 _p[0]           = _q[0];                                \
597                 _p[1]           = _q[1];                                \
598                 _p[2]           = _q[2];                                \
599                 _p[3]           = _q[3];                                \
600                 (P)             = _p + 4;                               \
601         } while (0)
602 #define WRITE_ADDR32(P,X)       WRITE_WORD(P,X)
603 #define WRITE_OFF32(P,X)        WRITE_WORD(P,X)
604 #define WRITE_SWORD(P,X)        WRITE_WORD(P,X)
605 #define WRITE_WORD64(P,X)       do {                                    \
606                 uint64_t _t     = (uint64_t) (X);                       \
607                 unsigned char *const _p = (unsigned char *) (P);        \
608                 const unsigned char *const _q = (unsigned char *) &_t;  \
609                 _p[0]           = _q[0];                                \
610                 _p[1]           = _q[1];                                \
611                 _p[2]           = _q[2];                                \
612                 _p[3]           = _q[3];                                \
613                 _p[4]           = _q[4];                                \
614                 _p[5]           = _q[5];                                \
615                 _p[6]           = _q[6];                                \
616                 _p[7]           = _q[7];                                \
617                 (P)             = _p + 8;                               \
618         } while (0)
619 #define WRITE_ADDR64(P,X)       WRITE_WORD64(P,X)
620 #define WRITE_LWORD(P,X)        WRITE_WORD64(P,X)
621 #define WRITE_OFF64(P,X)        WRITE_WORD64(P,X)
622 #define WRITE_SXWORD(P,X)       WRITE_WORD64(P,X)
623 #define WRITE_XWORD(P,X)        WRITE_WORD64(P,X)
624 #define WRITE_IDENT(P,X)        do {                                    \
625                 (void) memcpy((P), (X), sizeof((X)));                   \
626                 (P)             = (P) + EI_NIDENT;                      \
627         } while (0)
630  * C macros to read in various integral values.
632  * Note:
633  * - The source pointer could be unaligned.
634  * - Values are read in native byte order.
635  * - The source pointer is incremented appropriately.
636  */
638 #define READ_BYTE(P,X)  do {                                            \
639                 const unsigned char *const _p =                         \
640                         (const unsigned char *) (P);                    \
641                 (X)             = _p[0];                                \
642                 (P)             = (P) + 1;                              \
643         } while (0)
644 #define READ_HALF(P,X)  do {                                            \
645                 uint16_t _t;                                            \
646                 unsigned char *const _q = (unsigned char *) &_t;        \
647                 const unsigned char *const _p =                         \
648                         (const unsigned char *) (P);                    \
649                 _q[0]           = _p[0];                                \
650                 _q[1]           = _p[1];                                \
651                 (P)             = (P) + 2;                              \
652                 (X)             = _t;                                   \
653         } while (0)
654 #define _READ_WORD(P,X,T) do {                                          \
655                 uint32_t _t;                                            \
656                 unsigned char *const _q = (unsigned char *) &_t;        \
657                 const unsigned char *const _p =                         \
658                         (const unsigned char *) (P);                    \
659                 _q[0]           = _p[0];                                \
660                 _q[1]           = _p[1];                                \
661                 _q[2]           = _p[2];                                \
662                 _q[3]           = _p[3];                                \
663                 (P)             = (P) + 4;                              \
664                 (X)             = (T) _t;                               \
665         } while (0)
666 #define READ_ADDR32(P,X)        _READ_WORD(P, X, Elf32_Addr)
667 #define READ_OFF32(P,X)         _READ_WORD(P, X, Elf32_Off)
668 #define READ_SWORD(P,X)         _READ_WORD(P, X, Elf32_Sword)
669 #define READ_WORD(P,X)          _READ_WORD(P, X, Elf32_Word)
670 #define _READ_WORD64(P,X,T)     do {                                    \
671                 uint64_t _t;                                            \
672                 unsigned char *const _q = (unsigned char *) &_t;        \
673                 const unsigned char *const _p =                         \
674                         (const unsigned char *) (P);                    \
675                 _q[0]           = _p[0];                                \
676                 _q[1]           = _p[1];                                \
677                 _q[2]           = _p[2];                                \
678                 _q[3]           = _p[3];                                \
679                 _q[4]           = _p[4];                                \
680                 _q[5]           = _p[5];                                \
681                 _q[6]           = _p[6];                                \
682                 _q[7]           = _p[7];                                \
683                 (P)             = (P) + 8;                              \
684                 (X)             = (T) _t;                               \
685         } while (0)
686 #define READ_ADDR64(P,X)        _READ_WORD64(P, X, Elf64_Addr)
687 #define READ_LWORD(P,X)         _READ_WORD64(P, X, Elf64_Lword)
688 #define READ_OFF64(P,X)         _READ_WORD64(P, X, Elf64_Off)
689 #define READ_SXWORD(P,X)        _READ_WORD64(P, X, Elf64_Sxword)
690 #define READ_XWORD(P,X)         _READ_WORD64(P, X, Elf64_Xword)
691 #define READ_IDENT(P,X)         do {                                    \
692                 (void) memcpy((X), (P), sizeof((X)));                   \
693                 (P)             = (P) + EI_NIDENT;                      \
694         } while (0)
696 #define ROUNDUP2(V,N)   (V) = ((((V) + (N) - 1)) & ~((N) - 1))
698 /*[*/
699 MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
700 MAKE_VERSION_CONVERTERS(VDEF,Verdef,Verdaux,vd)
701 MAKE_VERSION_CONVERTERS(VNEED,Verneed,Vernaux,vn)
702 /*]*/
705  * Sections of type ELF_T_BYTE are never byteswapped, consequently a
706  * simple memcpy suffices for both directions of conversion.
707  */
709 static int
710 _libelf_cvt_BYTE_tox(unsigned char *dst, size_t dsz, unsigned char *src,
711     size_t count, int byteswap)
713         (void) byteswap;
714         if (dsz < count)
715                 return (0);
716         if (dst != src)
717                 (void) memcpy(dst, src, count);
718         return (1);
722  * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit
723  * words.  Bloom filter data comes next, followed by hash buckets and the
724  * hash chain.
726  * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit
727  * wide on ELFCLASS32 objects.  The other objects in this section are 32
728  * bits wide.
730  * Argument `srcsz' denotes the number of bytes to be converted.  In the
731  * 32-bit case we need to translate `srcsz' to a count of 32-bit words.
732  */
734 static int
735 _libelf_cvt_GNUHASH32_tom(unsigned char *dst, size_t dsz, unsigned char *src,
736     size_t srcsz, int byteswap)
738         return (_libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t),
739                 byteswap));
742 static int
743 _libelf_cvt_GNUHASH32_tof(unsigned char *dst, size_t dsz, unsigned char *src,
744     size_t srcsz, int byteswap)
746         return (_libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t),
747                 byteswap));
750 static int
751 _libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
752     size_t srcsz, int byteswap)
754         size_t sz;
755         uint64_t t64, *bloom64;
756         Elf_GNU_Hash_Header *gh;
757         uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
758         uint32_t *buckets, *chains;
760         sz = 4 * sizeof(uint32_t);      /* File header is 4 words long. */
761         if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
762                 return (0);
764         /* Read in the section header and byteswap if needed. */
765         READ_WORD(src, nbuckets);
766         READ_WORD(src, symndx);
767         READ_WORD(src, maskwords);
768         READ_WORD(src, shift2);
770         srcsz -= sz;
772         if (byteswap) {
773                 SWAP_WORD(nbuckets);
774                 SWAP_WORD(symndx);
775                 SWAP_WORD(maskwords);
776                 SWAP_WORD(shift2);
777         }
779         /* Check source buffer and destination buffer sizes. */
780         sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
781         if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
782                 return (0);
784         gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
785         gh->gh_nbuckets  = nbuckets;
786         gh->gh_symndx    = symndx;
787         gh->gh_maskwords = maskwords;
788         gh->gh_shift2    = shift2;
790         dsz -= sizeof(Elf_GNU_Hash_Header);
791         dst += sizeof(Elf_GNU_Hash_Header);
793         bloom64 = (uint64_t *) (uintptr_t) dst;
795         /* Copy bloom filter data. */
796         for (n = 0; n < maskwords; n++) {
797                 READ_XWORD(src, t64);
798                 if (byteswap)
799                         SWAP_XWORD(t64);
800                 bloom64[n] = t64;
801         }
803         /* The hash buckets follows the bloom filter. */
804         dst += maskwords * sizeof(uint64_t);
805         buckets = (uint32_t *) (uintptr_t) dst;
807         for (n = 0; n < nbuckets; n++) {
808                 READ_WORD(src, t32);
809                 if (byteswap)
810                         SWAP_WORD(t32);
811                 buckets[n] = t32;
812         }
814         dst += nbuckets * sizeof(uint32_t);
816         /* The hash chain follows the hash buckets. */
817         dsz -= sz;
818         srcsz -= sz;
820         if (dsz < srcsz)        /* Destination lacks space. */
821                 return (0);
823         nchains = srcsz / sizeof(uint32_t);
824         chains = (uint32_t *) (uintptr_t) dst;
826         for (n = 0; n < nchains; n++) {
827                 READ_WORD(src, t32);
828                 if (byteswap)
829                         SWAP_WORD(t32);
830                 *chains++ = t32;
831         }
833         return (1);
836 static int
837 _libelf_cvt_GNUHASH64_tof(unsigned char *dst, size_t dsz, unsigned char *src,
838     size_t srcsz, int byteswap)
840         uint32_t *s32;
841         size_t sz, hdrsz;
842         uint64_t *s64, t64;
843         Elf_GNU_Hash_Header *gh;
844         uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32;
846         hdrsz = 4 * sizeof(uint32_t);   /* Header is 4x32 bits. */
847         if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header))
848                 return (0);
850         gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
852         t0 = nbuckets = gh->gh_nbuckets;
853         t1 = gh->gh_symndx;
854         t2 = maskwords = gh->gh_maskwords;
855         t3 = gh->gh_shift2;
857         src   += sizeof(Elf_GNU_Hash_Header);
858         srcsz -= sizeof(Elf_GNU_Hash_Header);
859         dsz   -= hdrsz;
861         sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
862             sizeof(uint64_t);
864         if (srcsz < sz || dsz < sz)
865                 return (0);
867         /* Write out the header. */
868         if (byteswap) {
869                 SWAP_WORD(t0);
870                 SWAP_WORD(t1);
871                 SWAP_WORD(t2);
872                 SWAP_WORD(t3);
873         }
875         WRITE_WORD(dst, t0);
876         WRITE_WORD(dst, t1);
877         WRITE_WORD(dst, t2);
878         WRITE_WORD(dst, t3);
880         /* Copy the bloom filter and the hash table. */
881         s64 = (uint64_t *) (uintptr_t) src;
882         for (n = 0; n < maskwords; n++) {
883                 t64 = *s64++;
884                 if (byteswap)
885                         SWAP_XWORD(t64);
886                 WRITE_WORD64(dst, t64);
887         }
889         s32 = (uint32_t *) s64;
890         for (n = 0; n < nbuckets; n++) {
891                 t32 = *s32++;
892                 if (byteswap)
893                         SWAP_WORD(t32);
894                 WRITE_WORD(dst, t32);
895         }
897         srcsz -= sz;
898         dsz   -= sz;
900         /* Copy out the hash chains. */
901         if (dsz < srcsz)
902                 return (0);
904         nchains = srcsz / sizeof(uint32_t);
905         for (n = 0; n < nchains; n++) {
906                 t32 = *s32++;
907                 if (byteswap)
908                         SWAP_WORD(t32);
909                 WRITE_WORD(dst, t32);
910         }
912         return (1);
916  * Elf_Note structures comprise a fixed size header followed by variable
917  * length strings.  The fixed size header needs to be byte swapped, but
918  * not the strings.
920  * Argument `count' denotes the total number of bytes to be converted.
921  * The destination buffer needs to be at least `count' bytes in size.
922  */
923 static int
924 _libelf_cvt_NOTE_tom(unsigned char *dst, size_t dsz, unsigned char *src,
925     size_t count, int byteswap)
927         uint32_t namesz, descsz, type;
928         Elf_Note *en;
929         size_t sz, hdrsz;
931         if (dsz < count)        /* Destination buffer is too small. */
932                 return (0);
934         hdrsz = 3 * sizeof(uint32_t);
935         if (count < hdrsz)              /* Source too small. */
936                 return (0);
938         if (!byteswap) {
939                 (void) memcpy(dst, src, count);
940                 return (1);
941         }
943         /* Process all notes in the section. */
944         while (count > hdrsz) {
945                 /* Read the note header. */
946                 READ_WORD(src, namesz);
947                 READ_WORD(src, descsz);
948                 READ_WORD(src, type);
950                 /* Translate. */
951                 SWAP_WORD(namesz);
952                 SWAP_WORD(descsz);
953                 SWAP_WORD(type);
955                 /* Copy out the translated note header. */
956                 en = (Elf_Note *) (uintptr_t) dst;
957                 en->n_namesz = namesz;
958                 en->n_descsz = descsz;
959                 en->n_type = type;
961                 dsz -= sizeof(Elf_Note);
962                 dst += sizeof(Elf_Note);
963                 count -= hdrsz;
965                 ROUNDUP2(namesz, 4U);
966                 ROUNDUP2(descsz, 4U);
968                 sz = namesz + descsz;
970                 if (count < sz || dsz < sz)     /* Buffers are too small. */
971                         return (0);
973                 (void) memcpy(dst, src, sz);
975                 src += sz;
976                 dst += sz;
978                 count -= sz;
979                 dsz -= sz;
980         }
982         return (1);
985 static int
986 _libelf_cvt_NOTE_tof(unsigned char *dst, size_t dsz, unsigned char *src,
987     size_t count, int byteswap)
989         uint32_t namesz, descsz, type;
990         Elf_Note *en;
991         size_t sz;
993         if (dsz < count)
994                 return (0);
996         if (!byteswap) {
997                 (void) memcpy(dst, src, count);
998                 return (1);
999         }
1001         while (count > sizeof(Elf_Note)) {
1003                 en = (Elf_Note *) (uintptr_t) src;
1004                 namesz = en->n_namesz;
1005                 descsz = en->n_descsz;
1006                 type = en->n_type;
1008                 sz = namesz;
1009                 ROUNDUP2(sz, 4U);
1010                 sz += descsz;
1011                 ROUNDUP2(sz, 4U);
1013                 SWAP_WORD(namesz);
1014                 SWAP_WORD(descsz);
1015                 SWAP_WORD(type);
1017                 WRITE_WORD(dst, namesz);
1018                 WRITE_WORD(dst, descsz);
1019                 WRITE_WORD(dst, type);
1021                 src += sizeof(Elf_Note);
1022                 count -= sizeof(Elf_Note);
1024                 if (count < sz)
1025                         sz = count;
1027                 (void) memcpy(dst, src, sz);
1029                 src += sz;
1030                 dst += sz;
1031                 count -= sz;
1032         }
1034         return (1);
1037 struct converters {
1038         int     (*tof32)(unsigned char *dst, size_t dsz, unsigned char *src,
1039                     size_t cnt, int byteswap);
1040         int     (*tom32)(unsigned char *dst, size_t dsz, unsigned char *src,
1041                     size_t cnt, int byteswap);
1042         int     (*tof64)(unsigned char *dst, size_t dsz, unsigned char *src,
1043                     size_t cnt, int byteswap);
1044         int     (*tom64)(unsigned char *dst, size_t dsz, unsigned char *src,
1045                     size_t cnt, int byteswap);
1049 static struct converters cvt[ELF_T_NUM] = {
1050         /*[*/
1051 CONVERTER_NAMES(ELF_TYPE_LIST)
1052         /*]*/
1054         /*
1055          * Types that need hand-coded converters follow.
1056          */
1058         [ELF_T_BYTE] = {
1059                 .tof32 = _libelf_cvt_BYTE_tox,
1060                 .tom32 = _libelf_cvt_BYTE_tox,
1061                 .tof64 = _libelf_cvt_BYTE_tox,
1062                 .tom64 = _libelf_cvt_BYTE_tox
1063         },
1065         [ELF_T_NOTE] = {
1066                 .tof32 = _libelf_cvt_NOTE_tof,
1067                 .tom32 = _libelf_cvt_NOTE_tom,
1068                 .tof64 = _libelf_cvt_NOTE_tof,
1069                 .tom64 = _libelf_cvt_NOTE_tom
1070         }
1073 int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
1074  (unsigned char *_dst, size_t dsz, unsigned char *_src, size_t _cnt,
1075   int _byteswap)
1077         assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
1078         assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
1080         if (t >= ELF_T_NUM ||
1081             (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
1082             (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
1083                 return (NULL);
1085         return ((elfclass == ELFCLASS32) ?
1086             (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
1087             (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));