ldivmod, uldivmod: fix qdivrem calls
[minix.git] / lib / libelf / libelf_convert.m4
blob14359022afe4dd3430f29bebe94d126335a74f1f
1 /*-
2  * Copyright (c) 2006-2008 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 <sys/cdefs.h>
29 #include <assert.h>
30 #include <libelf.h>
31 #include <string.h>
33 #include "_libelf.h"
35 LIBELF_VCSID("$Id$");
37 /* WARNING: GENERATED FROM __file__. */
40  * Macros to swap various integral quantities.
41  */
43 #define SWAP_HALF(X)    do {                                            \
44                 uint16_t _x = (uint16_t) (X);                           \
45                 uint16_t _t = _x & 0xFF;                                \
46                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
47                 (X) = _t;                                               \
48         } while (0)
49 #define SWAP_WORD(X)    do {                                            \
50                 uint32_t _x = (uint32_t) (X);                           \
51                 uint32_t _t = _x & 0xFF;                                \
52                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
53                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
54                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
55                 (X) = _t;                                               \
56         } while (0)
57 #define SWAP_ADDR32(X)  SWAP_WORD(X)
58 #define SWAP_OFF32(X)   SWAP_WORD(X)
59 #define SWAP_SWORD(X)   SWAP_WORD(X)
60 #define SWAP_WORD64(X)  do {                                            \
61                 uint64_t _x = (uint64_t) (X);                           \
62                 uint64_t _t = _x & 0xFF;                                \
63                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
64                 _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
65                 _t <<= 8; _x >>= 8; _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                 (X) = _t;                                               \
71         } while (0)
72 #define SWAP_ADDR64(X)  SWAP_WORD64(X)
73 #define SWAP_LWORD(X)   SWAP_WORD64(X)
74 #define SWAP_OFF64(X)   SWAP_WORD64(X)
75 #define SWAP_SXWORD(X)  SWAP_WORD64(X)
76 #define SWAP_XWORD(X)   SWAP_WORD64(X)
79  * Write out various integral values.  The destination pointer could
80  * be unaligned.  Values are written out in native byte order.  The
81  * destination pointer is incremented after the write.
82  */
83 #define WRITE_BYTE(P,X) do {                                            \
84                 char *const _p = (char *) (P);  \
85                 _p[0]           = (char) (X);                   \
86                 (P)             = _p + 1;                               \
87         } while (0)
88 #define WRITE_HALF(P,X) do {                                            \
89                 uint16_t _t     = (X);                                  \
90                 char *const _p  = (char *) (P); \
91                 const char *const _q = (char *) &_t;    \
92                 _p[0]           = _q[0];                                \
93                 _p[1]           = _q[1];                                \
94                 (P)             = _p + 2;                               \
95         } while (0)
96 #define WRITE_WORD(P,X) do {                                            \
97                 uint32_t _t     = (X);                                  \
98                 char *const _p  = (char *) (P); \
99                 const char *const _q = (char *) &_t;    \
100                 _p[0]           = _q[0];                                \
101                 _p[1]           = _q[1];                                \
102                 _p[2]           = _q[2];                                \
103                 _p[3]           = _q[3];                                \
104                 (P)             = _p + 4;                               \
105         } while (0)
106 #define WRITE_ADDR32(P,X)       WRITE_WORD(P,X)
107 #define WRITE_OFF32(P,X)        WRITE_WORD(P,X)
108 #define WRITE_SWORD(P,X)        WRITE_WORD(P,X)
109 #define WRITE_WORD64(P,X)       do {                                    \
110                 uint64_t _t     = (X);                                  \
111                 char *const _p  = (char *) (P); \
112                 const char *const _q = (char *) &_t;    \
113                 _p[0]           = _q[0];                                \
114                 _p[1]           = _q[1];                                \
115                 _p[2]           = _q[2];                                \
116                 _p[3]           = _q[3];                                \
117                 _p[4]           = _q[4];                                \
118                 _p[5]           = _q[5];                                \
119                 _p[6]           = _q[6];                                \
120                 _p[7]           = _q[7];                                \
121                 (P)             = _p + 8;                               \
122         } while (0)
123 #define WRITE_ADDR64(P,X)       WRITE_WORD64(P,X)
124 #define WRITE_LWORD(P,X)        WRITE_WORD64(P,X)
125 #define WRITE_OFF64(P,X)        WRITE_WORD64(P,X)
126 #define WRITE_SXWORD(P,X)       WRITE_WORD64(P,X)
127 #define WRITE_XWORD(P,X)        WRITE_WORD64(P,X)
128 #define WRITE_IDENT(P,X)        do {                                    \
129                 (void) memcpy((P), (X), sizeof((X)));                   \
130                 (P)             = (P) + EI_NIDENT;                      \
131         } while (0)
134  * Read in various integral values.  The source pointer could be
135  * unaligned.  Values are read in native byte order.  The source
136  * pointer is incremented appropriately.
137  */
139 #define READ_BYTE(P,X)  do {                                            \
140                 const char *const _p =                          \
141                         (const char *) (P);                     \
142                 (X)             = _p[0];                                \
143                 (P)             = (P) + 1;                              \
144         } while (0)
145 #define READ_HALF(P,X)  do {                                            \
146                 uint16_t _t;                                            \
147                 char *const _q = (char *) &_t;  \
148                 const char *const _p =                          \
149                         (const char *) (P);                     \
150                 _q[0]           = _p[0];                                \
151                 _q[1]           = _p[1];                                \
152                 (P)             = (P) + 2;                              \
153                 (X)             = _t;                                   \
154         } while (0)
155 #define READ_WORD(P,X)  do {                                            \
156                 uint32_t _t;                                            \
157                 char *const _q = (char *) &_t;  \
158                 const char *const _p =                          \
159                         (const char *) (P);                     \
160                 _q[0]           = _p[0];                                \
161                 _q[1]           = _p[1];                                \
162                 _q[2]           = _p[2];                                \
163                 _q[3]           = _p[3];                                \
164                 (P)             = (P) + 4;                              \
165                 (X)             = _t;                                   \
166         } while (0)
167 #define READ_ADDR32(P,X)        READ_WORD(P,X)
168 #define READ_OFF32(P,X)         READ_WORD(P,X)
169 #define READ_SWORD(P,X)         READ_WORD(P,X)
170 #define READ_WORD64(P,X)        do {                                    \
171                 uint64_t _t;                                            \
172                 char *const _q = (char *) &_t;  \
173                 const char *const _p =                          \
174                         (const char *) (P);                     \
175                 _q[0]           = _p[0];                                \
176                 _q[1]           = _p[1];                                \
177                 _q[2]           = _p[2];                                \
178                 _q[3]           = _p[3];                                \
179                 _q[4]           = _p[4];                                \
180                 _q[5]           = _p[5];                                \
181                 _q[6]           = _p[6];                                \
182                 _q[7]           = _p[7];                                \
183                 (P)             = (P) + 8;                              \
184                 (X)             = _t;                                   \
185         } while (0)
186 #define READ_ADDR64(P,X)        READ_WORD64(P,X)
187 #define READ_LWORD(P,X)         READ_WORD64(P,X)
188 #define READ_OFF64(P,X)         READ_WORD64(P,X)
189 #define READ_SXWORD(P,X)        READ_WORD64(P,X)
190 #define READ_XWORD(P,X)         READ_WORD64(P,X)
191 #define READ_IDENT(P,X)         do {                                    \
192                 (void) memcpy((X), (P), sizeof((X)));                   \
193                 (P)             = (P) + EI_NIDENT;                      \
194         } while (0)
196 #define ROUNDUP2(V,N)   (V) = ((((V) + (N) - 1)) & ~((N) - 1))
198 divert(-1)
201  * Generate conversion routines for converting between in-memory and
202  * file representations of Elf data structures.
204  * `In-memory' representations of an Elf data structure use natural
205  * alignments and native byte ordering.  This allows arithmetic and
206  * casting to work as expected.  On the other hand the `file'
207  * representation of an ELF data structure could be packed tighter
208  * than its `in-memory' representation, and could be of a differing
209  * byte order.  An additional complication is that `ar' only pads data
210  * to even addresses and so ELF archive member data being read from
211  * inside an `ar' archive could end up at misaligned memory addresses.
213  * Consequently, casting the `char *' pointers that point to memory
214  * representations (i.e., source pointers for the *_tof() functions
215  * and the destination pointers for the *_tom() functions), is safe,
216  * as these pointers should be correctly aligned for the memory type
217  * already.  However, pointers to file representations have to be
218  * treated as being potentially unaligned and no casting can be done.
219  */
221 include(SRCDIR`/elf_types.m4')
224  * `IGNORE'_* flags turn off generation of template code.
225  */
227 define(`IGNORE',
228   `define(IGNORE_$1`'32,        1)
229    define(IGNORE_$1`'64,        1)')
231 IGNORE(MOVEP)
232 IGNORE(NOTE)
233 IGNORE(GNUHASH)
235 define(IGNORE_BYTE,             1)      /* 'lator, leave 'em bytes alone */
236 define(IGNORE_GNUHASH,          1)
237 define(IGNORE_NOTE,             1)
238 define(IGNORE_SXWORD32,         1)
239 define(IGNORE_XWORD32,          1)
242  * `BASE'_XXX flags cause class agnostic template functions
243  * to be generated.
244  */
246 define(`BASE_BYTE',     1)
247 define(`BASE_HALF',     1)
248 define(`BASE_NOTE',     1)
249 define(`BASE_WORD',     1)
250 define(`BASE_LWORD',    1)
251 define(`BASE_SWORD',    1)
252 define(`BASE_XWORD',    1)
253 define(`BASE_SXWORD',   1)
256  * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated
257  * for each primitive type.
258  */
260 define(`SIZEDEP_ADDR',  1)
261 define(`SIZEDEP_OFF',   1)
264  * `Primitive' ELF types are those that are an alias for an integral
265  * type.  They have no internal structure. These can be copied using
266  * a `memcpy()', and byteswapped in straightforward way.
268  * Macro use:
269  * `$1': Name of the ELF type.
270  * `$2': C structure name suffix
271  * `$3': ELF class specifier for symbols, one of [`', `32', `64']
272  * `$4': ELF class specifier for types, one of [`32', `64']
273  */
274 define(`MAKEPRIM_TO_F',`
275 static int
276 libelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count,
277     int byteswap)
279         Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src;
280         size_t c;
282         (void) dsz;
284         if (!byteswap) {
285                 (void) memcpy(dst, src, count * sizeof(*s));
286                 return (1);
287         }
289         for (c = 0; c < count; c++) {
290                 t = *s++;
291                 SWAP_$1$3(t);
292                 WRITE_$1$3(dst,t);
293         }
295         return (1);
299 define(`MAKEPRIM_TO_M',`
300 static int
301 libelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count,
302     int byteswap)
304         Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst;
305         size_t c;
307         if (dsz < count * sizeof(Elf$4_$2))
308                 return (0);
310         if (!byteswap) {
311                 (void) memcpy(dst, src, count * sizeof(*d));
312                 return (1);
313         }
315         for (c = 0; c < count; c++) {
316                 READ_$1$3(src,t);
317                 SWAP_$1$3(t);
318                 *d++ = t;
319         }
321         return (1);
325 define(`SWAP_FIELD',
326   `ifdef(`IGNORE_'$2,`',
327     `ifelse(BASE_$2,1,
328       `SWAP_$2(t.$1);
329                         ',
330       `ifelse($2,BYTE,`',
331         `ifelse($2,IDENT,`',
332           `SWAP_$2'SZ()`(t.$1);
333                         ')')')')')
334 define(`SWAP_MEMBERS',
335   `ifelse($#,1,`/**/',
336      `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
338 define(`SWAP_STRUCT',
339   `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
340                         SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
342 define(`WRITE_FIELD',
343   `ifelse(BASE_$2,1,
344     `WRITE_$2(dst,t.$1);
345                 ',
346     `ifelse($2,IDENT,
347       `WRITE_$2(dst,t.$1);
348                 ',
349       `WRITE_$2'SZ()`(dst,t.$1);
350                 ')')')
351 define(`WRITE_MEMBERS',
352   `ifelse($#,1,`/**/',
353     `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
355 define(`WRITE_STRUCT',
356   `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
357                 WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
359 define(`READ_FIELD',
360   `ifelse(BASE_$2,1,
361     `READ_$2(s,t.$1);
362                 ',
363     `ifelse($2,IDENT,
364       `READ_$2(s,t.$1);
365                 ',
366       `READ_$2'SZ()`(s,t.$1);
367                 ')')')
369 define(`READ_MEMBERS',
370   `ifelse($#,1,`/**/',
371     `READ_FIELD($1)READ_MEMBERS(shift($@))')')
373 define(`READ_STRUCT',
374   `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
375                 READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
378  * Converters for non-integral ELF data structures.
380  * When converting data to file representation, the source pointer
381  * will be naturally aligned for a data structure's in-memory
382  * representation.  When converting data to memory, the destination
383  * pointer will be similarly aligned.
385  * For in-place conversions, when converting to file representations,
386  * the source buffer is large enough to hold `file' data.  When
387  * converting from file to memory, we need to be careful to work
388  * `backwards', to avoid overwriting unconverted data.
390  * Macro use:
391  * `$1': Name of the ELF type.
392  * `$2': C structure name suffix.
393  * `$3': ELF class specifier, one of [`', `32', `64']
394  */
396 define(`MAKE_TO_F',
397   `ifdef(`IGNORE_'$1$3,`',`
398 static int
399 libelf_cvt$3_$1_tof(char *dst, size_t dsz, char *src, size_t count,
400     int byteswap)
402         Elf$3_$2        t, *s;
403         size_t c;
405         (void) dsz;
407         s = (Elf$3_$2 *) (uintptr_t) src;
408         for (c = 0; c < count; c++) {
409                 t = *s++;
410                 if (byteswap) {
411                         SWAP_STRUCT($2,$3)
412                 }
413                 WRITE_STRUCT($2,$3)
414         }
416         return (1);
418 ')')
420 define(`MAKE_TO_M',
421   `ifdef(`IGNORE_'$1$3,`',`
422 static int
423 libelf_cvt$3_$1_tom(char *dst, size_t dsz, char *src, size_t count,
424     int byteswap)
426         Elf$3_$2         t, *d;
427         char            *s,*s0;
428         size_t          fsz;
430         fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
431         d   = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
432         s0  = (char *) src + (count - 1) * fsz;
434         if (dsz < count * sizeof(Elf$3_$2))
435                 return (0);
437         while (count--) {
438                 s = s0;
439                 READ_STRUCT($2,$3)
440                 if (byteswap) {
441                         SWAP_STRUCT($2,$3)
442                 }
443                 *d-- = t; s0 -= fsz;
444         }
446         return (1);
448 ')')
451  * Make type convertor functions from the type definition
452  * of the ELF type:
453  * - if the type is a base (i.e., `primitive') type:
454  *   - if it is marked as to be ignored (i.e., `IGNORE_'TYPE)
455  *     is defined, we skip the code generation step.
456  *   - if the type is declared as `SIZEDEP', then 32 and 64 bit
457  *     variants of the conversion functions are generated.
458  *   - otherwise a 32 bit variant is generated.
459  * - if the type is a structure type, we generate 32 and 64 bit
460  *   variants of the conversion functions.
461  */
463 define(`MAKE_TYPE_CONVERTER',
464   `ifdef(`BASE'_$1,
465     `ifdef(`IGNORE_'$1,`',
466       `MAKEPRIM_TO_F($1,$2,`',64)
467        MAKEPRIM_TO_M($1,$2,`',64)')',
468     `ifdef(`SIZEDEP_'$1,
469       `MAKEPRIM_TO_F($1,$2,32,32)dnl
470        MAKEPRIM_TO_M($1,$2,32,32)dnl
471        MAKEPRIM_TO_F($1,$2,64,64)dnl
472        MAKEPRIM_TO_M($1,$2,64,64)',
473       `MAKE_TO_F($1,$2,32)dnl
474        MAKE_TO_F($1,$2,64)dnl
475        MAKE_TO_M($1,$2,32)dnl
476        MAKE_TO_M($1,$2,64)')')
479 define(`MAKE_TYPE_CONVERTERS',
480   `ifelse($#,1,`',
481     `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
483 divert(0)
486  * Sections of type ELF_T_BYTE are never byteswapped, consequently a
487  * simple memcpy suffices for both directions of conversion.
488  */
490 static int
491 libelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count,
492     int byteswap)
494         (void) byteswap;
495         if (dsz < count)
496                 return (0);
497         if (dst != src)
498                 (void) memcpy(dst, src, count);
499         return (1);
502 MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
505  * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit
506  * words.  Bloom filter data comes next, followed by hash buckets and the
507  * hash chain.
509  * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit
510  * wide on ELFCLASS32 objects.  The other objects in this section are 32
511  * bits wide.
513  * Argument `srcsz' denotes the number of bytes to be converted.  In the
514  * 32-bit case we need to translate `srcsz' to a count of 32-bit words.
515  */
517 static int
518 libelf_cvt32_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz,
519     int byteswap)
521         return (libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t),
522                 byteswap));
525 static int
526 libelf_cvt32_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz,
527     int byteswap)
529         return (libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t),
530                 byteswap));
533 static int
534 libelf_cvt64_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz,
535     int byteswap)
537         size_t sz;
538         uint64_t t64, *bloom64;
539         Elf_GNU_Hash_Header *gh;
540         uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
541         uint32_t *buckets, *chains;
543         sz = 4 * sizeof(uint32_t);      /* File header is 4 words long. */
544         if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
545                 return (0);
547         /* Read in the section header and byteswap if needed. */
548         READ_WORD(src, nbuckets);
549         READ_WORD(src, symndx);
550         READ_WORD(src, maskwords);
551         READ_WORD(src, shift2);
553         srcsz -= sz;
555         if (byteswap) {
556                 SWAP_WORD(nbuckets);
557                 SWAP_WORD(symndx);
558                 SWAP_WORD(maskwords);
559                 SWAP_WORD(shift2);
560         }
562         /* Check source buffer and destination buffer sizes. */
563         sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
564         if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
565                 return (0);
567         gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
568         gh->gh_nbuckets  = nbuckets;
569         gh->gh_symndx    = symndx;
570         gh->gh_maskwords = maskwords;
571         gh->gh_shift2    = shift2;
572         
573         dsz -= sizeof(Elf_GNU_Hash_Header);
574         dst += sizeof(Elf_GNU_Hash_Header);
576         bloom64 = (uint64_t *) (uintptr_t) dst;
578         /* Copy bloom filter data. */
579         for (n = 0; n < maskwords; n++) {
580                 READ_XWORD(src, t64);
581                 if (byteswap)
582                         SWAP_XWORD(t64);
583                 bloom64[n] = t64;
584         }
586         /* The hash buckets follows the bloom filter. */
587         dst += maskwords * sizeof(uint64_t);
588         buckets = (uint32_t *) (uintptr_t) dst;
590         for (n = 0; n < nbuckets; n++) {
591                 READ_WORD(src, t32);
592                 if (byteswap)
593                         SWAP_WORD(t32);
594                 buckets[n] = t32;
595         }
597         dst += nbuckets * sizeof(uint32_t);
599         /* The hash chain follows the hash buckets. */
600         dsz -= sz;
601         srcsz -= sz;
603         if (dsz < srcsz)        /* Destination lacks space. */
604                 return (0);
606         nchains = srcsz / sizeof(uint32_t);
607         chains = (uint32_t *) (uintptr_t) dst;
609         for (n = 0; n < nchains; n++) {
610                 READ_WORD(src, t32);
611                 if (byteswap)
612                         SWAP_WORD(t32);
613                 *chains++ = t32;
614         }
616         return (1);
619 static int
620 libelf_cvt64_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz,
621     int byteswap)
623         uint32_t *s32;
624         size_t sz, hdrsz;
625         uint64_t *s64, t64;
626         Elf_GNU_Hash_Header *gh;
627         uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32;
629         hdrsz = 4 * sizeof(uint32_t);   /* Header is 4x32 bits. */
630         if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header))
631                 return (0);
633         gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
635         t0 = nbuckets = gh->gh_nbuckets;
636         t1 = gh->gh_symndx;
637         t2 = maskwords = gh->gh_maskwords;
638         t3 = gh->gh_shift2;
640         src   += sizeof(Elf_GNU_Hash_Header);
641         srcsz -= sizeof(Elf_GNU_Hash_Header);
642         dsz   -= hdrsz;
644         sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
645             sizeof(uint64_t);
647         if (srcsz < sz || dsz < sz)
648                 return (0);
650         /* Write out the header. */
651         if (byteswap) {
652                 SWAP_WORD(t0);
653                 SWAP_WORD(t1);
654                 SWAP_WORD(t2);
655                 SWAP_WORD(t3);
656         }
658         WRITE_WORD(dst, t0);
659         WRITE_WORD(dst, t1);
660         WRITE_WORD(dst, t2);
661         WRITE_WORD(dst, t3);
663         /* Copy the bloom filter and the hash table. */
664         s64 = (uint64_t *) (uintptr_t) src;
665         for (n = 0; n < maskwords; n++) {
666                 t64 = *s64++;
667                 if (byteswap)
668                         SWAP_XWORD(t64);
669                 WRITE_WORD64(dst, t64);
670         }
672         s32 = (uint32_t *) s64;
673         for (n = 0; n < nbuckets; n++) {
674                 t32 = *s32++;
675                 if (byteswap)
676                         SWAP_WORD(t32);
677                 WRITE_WORD(dst, t32);
678         }
680         srcsz -= sz;
681         dsz   -= sz;
683         /* Copy out the hash chains. */
684         if (dsz < srcsz)
685                 return (0);
687         nchains = srcsz / sizeof(uint32_t);
688         for (n = 0; n < nchains; n++) {
689                 t32 = *s32++;
690                 if (byteswap)
691                         SWAP_WORD(t32);
692                 WRITE_WORD(dst, t32);
693         }
695         return (1);
699  * Elf_Note structures comprise a fixed size header followed by variable
700  * length strings.  The fixed size header needs to be byte swapped, but
701  * not the strings.
703  * Argument `count' denotes the total number of bytes to be converted.
704  * The destination buffer needs to be at least `count' bytes in size.
705  */
706 static int
707 libelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count, 
708     int byteswap)
710         uint32_t namesz, descsz, type;
711         Elf_Note *en;
712         size_t sz, hdrsz;
714         if (dsz < count)        /* Destination buffer is too small. */
715                 return (0);
717         hdrsz = 3 * sizeof(uint32_t);
718         if (count < hdrsz)              /* Source too small. */
719                 return (0);
721         if (!byteswap) {
722                 (void) memcpy(dst, src, count);
723                 return (1);
724         }
726         /* Process all notes in the section. */
727         while (count > hdrsz) {
728                 /* Read the note header. */
729                 READ_WORD(src, namesz);
730                 READ_WORD(src, descsz);
731                 READ_WORD(src, type);
733                 /* Translate. */
734                 SWAP_WORD(namesz);
735                 SWAP_WORD(descsz);
736                 SWAP_WORD(type);
738                 /* Copy out the translated note header. */
739                 en = (Elf_Note *) (uintptr_t) dst;
740                 en->n_namesz = namesz;
741                 en->n_descsz = descsz;
742                 en->n_type = type;
744                 dsz -= sizeof(Elf_Note);
745                 dst += sizeof(Elf_Note);
746                 count -= hdrsz;
748                 ROUNDUP2(namesz, 4);
749                 ROUNDUP2(descsz, 4);
751                 sz = namesz + descsz;
753                 if (count < sz || dsz < sz)     /* Buffers are too small. */
754                         return (0);
756                 (void) memcpy(dst, src, sz);
758                 src += sz;
759                 dst += sz;
761                 count -= sz;
762                 dsz -= sz;
763         }
765         return (1);
768 static int
769 libelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count,
770     int byteswap)
772         uint32_t namesz, descsz, type;
773         Elf_Note *en;
774         size_t sz;
776         if (dsz < count)
777                 return (0);
779         if (!byteswap) {
780                 (void) memcpy(dst, src, count);
781                 return (1);
782         }
784         while (count > sizeof(Elf_Note)) {
786                 en = (Elf_Note *) (uintptr_t) src;
787                 namesz = en->n_namesz;
788                 descsz = en->n_descsz;
789                 type = en->n_type;
791                 SWAP_WORD(namesz);
792                 SWAP_WORD(descsz);
793                 SWAP_WORD(type);
795                 WRITE_WORD(dst, namesz);
796                 WRITE_WORD(dst, descsz);
797                 WRITE_WORD(dst, type);
799                 src += sizeof(Elf_Note);
801                 ROUNDUP2(namesz, 4);
802                 ROUNDUP2(descsz, 4);
804                 sz = namesz + descsz;
806                 if (count < sz)
807                         sz = count;
809                 (void) memcpy(dst, src, sz);
811                 src += sz;
812                 dst += sz;
813                 count -= sz;
814         }
816         return (1);
819 struct converters {
820         int     (*tof32)(char *dst, size_t dsz, char *src, size_t cnt,
821                     int byteswap);
822         int     (*tom32)(char *dst, size_t dsz, char *src, size_t cnt,
823                     int byteswap);
824         int     (*tof64)(char *dst, size_t dsz, char *src, size_t cnt,
825                     int byteswap);
826         int     (*tom64)(char *dst, size_t dsz, char *src, size_t cnt,
827                     int byteswap);
830 divert(-1)
831 define(`CONV',
832   `ifdef(`IGNORE_'$1$2,
833     `.$3$2 = NULL',
834     `ifdef(`BASE_'$1,
835       `.$3$2 = libelf_cvt_$1_$3',
836       `ifdef(`SIZEDEP_'$1,
837         `.$3$2 = libelf_cvt_$1$2_$3',
838         `.$3$2 = libelf_cvt$2_$1_$3')')')')
840 define(`CONVERTER_NAME',
841   `ifdef(`IGNORE_'$1,`',
842     `[ELF_T_$1] = {
843         CONV($1,32,tof), CONV($1,32,tom),
844         CONV($1,64,tof), CONV($1,64,tom) },
845 ')')
847 define(`CONVERTER_NAMES',
848   `ifelse($#,1,`',
849     `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
851 undefine(`IGNORE_BYTE32', `IGNORE_BYTE64')
852 divert(0)
854 static struct converters cvt[ELF_T_NUM] = {
855 CONVERTER_NAMES(ELF_TYPE_LIST)
857         /*
858          * Types that needs hand-coded converters follow.
859          */
861         [ELF_T_BYTE] = {
862                 .tof32 = libelf_cvt_BYTE_tox,
863                 .tom32 = libelf_cvt_BYTE_tox,
864                 .tof64 = libelf_cvt_BYTE_tox,
865                 .tom64 = libelf_cvt_BYTE_tox
866         },
868         [ELF_T_GNUHASH] = {
869                 .tof32 = libelf_cvt32_GNUHASH_tof,
870                 .tom32 = libelf_cvt32_GNUHASH_tom,
871                 .tof64 = libelf_cvt64_GNUHASH_tof,
872                 .tom64 = libelf_cvt64_GNUHASH_tom
873         },
875         [ELF_T_NOTE] = {
876                 .tof32 = libelf_cvt_NOTE_tof,
877                 .tom32 = libelf_cvt_NOTE_tom,
878                 .tof64 = libelf_cvt_NOTE_tof,
879                 .tom64 = libelf_cvt_NOTE_tom
880         }
883 int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
884  (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap)
886         assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
887         assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
889         if (t >= ELF_T_NUM ||
890             (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
891             (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
892                 return (NULL);
894         return ((elfclass == ELFCLASS32) ?
895             (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
896             (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));