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