1 /* $NetBSD: libelf_convert.m4,v 1.2 2014/03/09 16:58:04 christos Exp $ */
4 * Copyright (c) 2006-2011 Joseph Koshy
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #if HAVE_NBTOOL_CONFIG_H
30 # include "nbtool_config.h"
33 #include <sys/cdefs.h>
41 __RCSID("$NetBSD: libelf_convert.m4,v 1.2 2014/03/09 16:58:04 christos Exp $");
42 ELFTC_VCSID("Id: libelf_convert.m4 2361 2011-12-28 12:03:05Z jkoshy ");
44 /* WARNING: GENERATED FROM __file__. */
48 # Generate conversion routines for converting between in-memory and
49 # file representations of Elf data structures.
51 # These conversions use the type information defined in `elf_types.m4'.
53 include(SRCDIR`/elf_types.m4')
55 # For the purposes of generating conversion code, ELF types may be
56 # classified according to the following characteristics:
58 # 1. Whether the ELF type can be directly mapped to an integral C
59 # language type. For example, the ELF_T_WORD type maps directly to
60 # a 'uint32_t', but ELF_T_GNUHASH lacks a matching C type.
62 # 2. Whether the type has word size dependent variants. For example,
63 # ELT_T_EHDR is represented using C types Elf32_Ehdr and El64_Ehdr,
64 # and the ELF_T_ADDR and ELF_T_OFF types have integral C types that
65 # can be 32- or 64- bit wide.
67 # 3. Whether the ELF types has a fixed representation or not. For
68 # example, the ELF_T_SYM type has a fixed size file representation,
69 # some types like ELF_T_NOTE and ELF_T_GNUHASH use a variable size
72 # We use m4 macros to generate conversion code for ELF types that have
73 # a fixed size representation. Conversion functions for the remaining
74 # types are coded by hand.
76 #* Handling File and Memory Representations
78 # `In-memory' representations of an Elf data structure use natural
79 # alignments and native byte ordering. This allows pointer arithmetic
80 # and casting to work as expected. On the other hand, the `file'
81 # representation of an ELF data structure could possibly be packed
82 # tighter than its `in-memory' representation, and could be of a
83 # differing byte order. Reading ELF objects that are members of `ar'
84 # archives present an additional complication: `ar' pads file data to
85 # even addresses, so file data structures in an archive member
86 # residing inside an `ar' archive could be at misaligned memory
87 # addresses when brought into memory.
89 # In summary, casting the `char *' pointers that point to memory
90 # representations (i.e., source pointers for the *_tof() functions and
91 # the destination pointers for the *_tom() functions), is safe, as
92 # these pointers should be correctly aligned for the memory type
93 # already. However, pointers to file representations have to be
94 # treated as being potentially unaligned and no casting can be done.
96 # NOCVT(TYPE) -- Do not generate the cvt[] structure entry for TYPE
97 define(`NOCVT',`define(`NOCVT_'$1,1)')
99 # NOFUNC(TYPE) -- Do not generate a conversion function for TYPE
100 define(`NOFUNC',`define(`NOFUNC_'$1,1)')
102 # IGNORE(TYPE) -- Completely ignore the type.
103 define(`IGNORE',`NOCVT($1)NOFUNC($1)')
105 # Mark ELF types that should not be processed by the M4 macros below.
107 # Types for which we use functions with non-standard names.
108 IGNORE(`BYTE') # Uses a wrapper around memcpy().
109 IGNORE(`NOTE') # Not a fixed size type.
111 # Types for which we supply hand-coded functions.
112 NOFUNC(`GNUHASH') # A type with complex internal structure.
113 NOFUNC(`VDEF') # See MAKE_VERSION_CONVERTERS below.
116 # Unimplemented types.
119 # ELF types that don't exist in a 32-bit world.
123 # `Primitive' ELF types are those that are an alias for an integral
124 # type. As they have no internal structure, they can be copied using
125 # a `memcpy()', and byteswapped in straightforward way.
127 # Mark all ELF types that directly map to integral C types.
128 define(`PRIM_ADDR', 1)
129 define(`PRIM_BYTE', 1)
130 define(`PRIM_HALF', 1)
131 define(`PRIM_LWORD', 1)
132 define(`PRIM_OFF', 1)
133 define(`PRIM_SWORD', 1)
134 define(`PRIM_SXWORD', 1)
135 define(`PRIM_WORD', 1)
136 define(`PRIM_XWORD', 1)
138 # Note the primitive types that are size-dependent.
139 define(`SIZEDEP_ADDR', 1)
140 define(`SIZEDEP_OFF', 1)
142 # Generate conversion functions for primitive types.
144 # Macro use: MAKEPRIMFUNCS(ELFTYPE,CTYPE,TYPESIZE,SYMSIZE)
145 # `$1': Name of the ELF type.
146 # `$2': C structure name suffix.
147 # `$3': ELF class specifier for types, one of [`32', `64'].
148 # `$4': Additional ELF class specifier, one of [`', `32', `64'].
150 # Generates a pair of conversion functions.
151 define(`MAKEPRIMFUNCS',`
153 _libelf_cvt_$1$4_tof(char *dst, size_t dsz, char *src, size_t count,
156 Elf$3_$2 t, *s = (Elf$3_$2 *) (uintptr_t) src;
162 (void) memcpy(dst, src, count * sizeof(*s));
166 for (c = 0; c < count; c++) {
176 _libelf_cvt_$1$4_tom(char *dst, size_t dsz, char *src, size_t count,
179 Elf$3_$2 t, *d = (Elf$3_$2 *) (uintptr_t) dst;
182 if (dsz < count * sizeof(Elf$3_$2))
186 (void) memcpy(dst, src, count * sizeof(*d));
190 for (c = 0; c < count; c++) {
201 # Handling composite ELF types
204 # SWAP_FIELD(FIELDNAME,ELFTYPE) -- Generate code to swap one field.
207 `SWAP_$2'SZ()`(t.$1);
212 # SWAP_MEMBERS(STRUCT) -- Iterate over a structure definition.
213 define(`SWAP_MEMBERS',
215 `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
217 # SWAP_STRUCT(CTYPE,SIZE) -- Generate code to swap an ELF structure.
218 define(`SWAP_STRUCT',
219 `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
220 SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
222 # WRITE_FIELD(ELFTYPE,FIELDNAME) -- Generate code to write one field.
223 define(`WRITE_FIELD',
225 `WRITE_$2'SZ()`(dst,t.$1);
230 # WRITE_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
231 define(`WRITE_MEMBERS',
233 `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
235 # WRITE_STRUCT(CTYPE,SIZE) -- Generate code to write out an ELF structure.
236 define(`WRITE_STRUCT',
237 `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
238 WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
240 # READ_FIELD(ELFTYPE,CTYPE) -- Generate code to read one field.
243 `READ_$2'SZ()`(s,t.$1);
248 # READ_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
249 define(`READ_MEMBERS',
251 `READ_FIELD($1)READ_MEMBERS(shift($@))')')
253 # READ_STRUCT(CTYPE,SIZE) -- Generate code to read an ELF structure.
254 define(`READ_STRUCT',
255 `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
256 READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
259 # MAKECOMPFUNCS -- Generate converters for composite ELF structures.
261 # When converting data to file representation, the source pointer will
262 # be naturally aligned for a data structure's in-memory
263 # representation. When converting data to memory, the destination
264 # pointer will be similarly aligned.
266 # For in-place conversions, when converting to file representations,
267 # the source buffer is large enough to hold `file' data. When
268 # converting from file to memory, we need to be careful to work
269 # `backwards', to avoid overwriting unconverted data.
272 # `$1': Name of the ELF type.
273 # `$2': C structure name suffix.
274 # `$3': ELF class specifier, one of [`', `32', `64']
275 define(`MAKECOMPFUNCS', `ifdef(`NOFUNC_'$1$3,`',`
277 _libelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count,
285 s = (Elf$3_$2 *) (uintptr_t) src;
286 for (c = 0; c < count; c++) {
298 _libelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count,
305 fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
306 d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
307 s0 = (char *) src + (count - 1) * fsz;
309 if (dsz < count * sizeof(Elf$3_$2))
325 # MAKE_TYPE_CONVERTER(ELFTYPE,CTYPE)
327 # Make type convertor functions from the type definition
329 # - Skip convertors marked as `NOFUNC'.
330 # - Invoke `MAKEPRIMFUNCS' or `MAKECOMPFUNCS' as appropriate.
331 define(`MAKE_TYPE_CONVERTER',
332 `ifdef(`NOFUNC_'$1,`',
335 `MAKEPRIMFUNCS($1,$2,32,32)dnl
336 MAKEPRIMFUNCS($1,$2,64,64)',
337 `MAKEPRIMFUNCS($1,$2,64)')',
338 `MAKECOMPFUNCS($1,$2,32)dnl
339 MAKECOMPFUNCS($1,$2,64)')')')
341 # MAKE_TYPE_CONVERTERS(ELFTYPELIST) -- Generate conversion functions.
342 define(`MAKE_TYPE_CONVERTERS',
344 `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
348 # Macros to generate entries for the table of convertors.
351 # CONV(ELFTYPE,SIZE,DIRECTION)
353 # Generate the name of a convertor function.
355 `ifdef(`NOFUNC_'$1$2,
359 `.$3$2 = _libelf_cvt_$1$2_$3',
360 `.$3$2 = _libelf_cvt_$1_$3')',
361 `.$3$2 = _libelf_cvt_$1$2_$3')')')
363 # CONVERTER_NAME(ELFTYPE)
365 # Generate the contents of one `struct cvt' instance.
366 define(`CONVERTER_NAME',
367 `ifdef(`NOCVT_'$1,`',
377 # CONVERTER_NAMES(ELFTYPELIST)
379 # Generate the `struct cvt[]' array.
380 define(`CONVERTER_NAMES',
382 `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
385 # Handling ELF version sections.
388 # _FSZ(FIELD,BASETYPE) - return the file size for a field.
393 # FSZ(STRUCT) - determine the file size of a structure.
396 `eval(_FSZ($1) + FSZ(shift($@)))')')
398 # MAKE_VERSION_CONVERTERS(TYPE,BASE,AUX,PFX) -- Generate conversion
399 # functions for versioning structures.
400 define(`MAKE_VERSION_CONVERTERS',
401 `MAKE_VERSION_CONVERTER($1,$2,$3,$4,32)
402 MAKE_VERSION_CONVERTER($1,$2,$3,$4,64)')
404 # MAKE_VERSION_CONVERTOR(TYPE,CBASE,CAUX,PFX,SIZE) -- Generate a
405 # conversion function.
406 define(`MAKE_VERSION_CONVERTER',`
408 _libelf_cvt_$1$5_tof(char *dst, size_t dsz, char *src, size_t count,
413 const size_t verfsz = FSZ(Elf$5_$2_DEF);
414 const size_t auxfsz = FSZ(Elf$5_$3_DEF);
415 const size_t vermsz = sizeof(Elf$5_$2);
416 const size_t auxmsz = sizeof(Elf$5_$3);
417 char * const dstend = dst + dsz;
418 char * const srcend = src + count;
419 char *dtmp, *dstaux, *srcaux;
420 Elf$5_Word aux, anext, cnt, vnext;
422 for (dtmp = dst, vnext = ~0;
423 vnext != 0 && dtmp + verfsz <= dstend && src + vermsz <= srcend;
424 dtmp += vnext, src += vnext) {
426 /* Read in an Elf$5_$2 structure. */
427 t = *((Elf$5_$2 *) (uintptr_t) src);
443 /* Process AUX entries. */
444 for (anext = ~0, dstaux = dtmp + aux, srcaux = src + aux;
445 cnt != 0 && anext != 0 && dstaux + auxfsz <= dstend &&
446 srcaux + auxmsz <= srcend;
447 dstaux += anext, srcaux += anext, cnt--) {
449 /* Read in an Elf$5_$3 structure. */
450 a = *((Elf$5_$3 *) (uintptr_t) srcaux);
454 pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
458 pushdef(`t',`a')WRITE_STRUCT($3, $5)popdef(`t')
472 _libelf_cvt_$1$5_tom(char *dst, size_t dsz, char *src, size_t count,
477 const size_t verfsz = FSZ(Elf$5_$2_DEF);
478 const size_t auxfsz = FSZ(Elf$5_$3_DEF);
479 const size_t vermsz = sizeof(Elf$5_$2);
480 const size_t auxmsz = sizeof(Elf$5_$3);
481 char * const dstend = dst + dsz;
482 char * const srcend = src + count;
483 char *dstaux, *s, *srcaux, *stmp;
484 Elf$5_Word aux, anext, cnt, vnext;
486 for (stmp = src, vnext = ~0;
487 vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
488 stmp += vnext, dst += vnext) {
490 /* Read in a $1 structure. */
497 dp = (Elf$5_$2 *) (uintptr_t) dst;
507 /* Process AUX entries. */
508 for (anext = ~0, dstaux = dst + aux, srcaux = stmp + aux;
509 cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
510 srcaux + auxfsz <= srcend;
511 dstaux += anext, srcaux += anext, cnt--) {
514 pushdef(`t',`a')READ_STRUCT($3, $5)popdef(`t')
517 pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
522 ap = ((Elf$5_$3 *) (uintptr_t) dstaux);
539 * C macros to byte swap integral quantities.
542 #define SWAP_BYTE(X) do { (void) (X); } while (0)
543 #define SWAP_IDENT(X) do { (void) (X); } while (0)
544 #define SWAP_HALF(X) do { \
545 uint16_t _x = (uint16_t) (X); \
546 uint32_t _t = _x & 0xFF; \
547 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
549 } while (/*CONSTCOND*/0)
550 #define SWAP_WORD(X) do { \
551 uint32_t _x = (uint32_t) (X); \
552 uint32_t _t = _x & 0xFF; \
553 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
554 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
555 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
557 } while (/*CONSTCOND*/0)
558 #define SWAP_ADDR32(X) SWAP_WORD(X)
559 #define SWAP_OFF32(X) SWAP_WORD(X)
560 #define SWAP_SWORD(X) SWAP_WORD(X)
561 #define SWAP_WORD64(X) do { \
562 uint64_t _x = (uint64_t) (X); \
563 uint64_t _t = _x & 0xFF; \
564 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
565 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
566 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
567 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
568 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
569 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
570 _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \
572 } while (/*CONSTCOND*/0)
573 #define SWAP_ADDR64(X) SWAP_WORD64(X)
574 #define SWAP_LWORD(X) SWAP_WORD64(X)
575 #define SWAP_OFF64(X) SWAP_WORD64(X)
576 #define SWAP_SXWORD(X) SWAP_WORD64(X)
577 #define SWAP_XWORD(X) SWAP_WORD64(X)
580 * C macros to write out various integral values.
583 * - The destination pointer could be unaligned.
584 * - Values are written out in native byte order.
585 * - The destination pointer is incremented after the write.
587 #define WRITE_BYTE(P,X) do { \
588 char *const _p = (void *) (P); \
589 _p[0] = (char) (X); \
590 (P) = (void *)(_p + 1); \
591 } while (/*CONSTCOND*/0)
592 #define WRITE_HALF(P,X) do { \
597 unsigned char *const _p = (void *) (P); \
599 _p[0] = _t.bytes[0]; \
600 _p[1] = _t.bytes[1]; \
601 (P) = (void *)(_p + 2); \
602 } while (/*CONSTCOND*/0)
603 #define WRITE_WORD(P,X) do { \
608 unsigned char *const _p = (void *) (P); \
610 _p[0] = _t.bytes[0]; \
611 _p[1] = _t.bytes[1]; \
612 _p[2] = _t.bytes[2]; \
613 _p[3] = _t.bytes[3]; \
614 (P) = (void *)(_p + 4); \
615 } while (/*CONSTCOND*/0)
616 #define WRITE_ADDR32(P,X) WRITE_WORD(P,X)
617 #define WRITE_OFF32(P,X) WRITE_WORD(P,X)
618 #define WRITE_SWORD(P,X) WRITE_WORD(P,X)
619 #define WRITE_WORD64(P,X) do { \
624 unsigned char *const _p = (void *) (P); \
626 _p[0] = _t.bytes[0]; \
627 _p[1] = _t.bytes[1]; \
628 _p[2] = _t.bytes[2]; \
629 _p[3] = _t.bytes[3]; \
630 _p[4] = _t.bytes[4]; \
631 _p[5] = _t.bytes[5]; \
632 _p[6] = _t.bytes[6]; \
633 _p[7] = _t.bytes[7]; \
634 (P) = (void *)(_p + 8); \
635 } while (/*CONSTCOND*/0)
636 #define WRITE_ADDR64(P,X) WRITE_WORD64(P,X)
637 #define WRITE_LWORD(P,X) WRITE_WORD64(P,X)
638 #define WRITE_OFF64(P,X) WRITE_WORD64(P,X)
639 #define WRITE_SXWORD(P,X) WRITE_WORD64(P,X)
640 #define WRITE_XWORD(P,X) WRITE_WORD64(P,X)
641 #define WRITE_IDENT(P,X) do { \
642 (void) memcpy((P), (X), sizeof((X))); \
643 (P) = (P) + EI_NIDENT; \
644 } while (/*CONSTCOND*/0)
647 * C macros to read in various integral values.
650 * - The source pointer could be unaligned.
651 * - Values are read in native byte order.
652 * - The source pointer is incremented appropriately.
655 #define READ_BYTE(P,X) do { \
656 const char *const _p = \
657 (const void *) (P); \
660 } while (/*CONSTCOND*/0)
661 #define READ_HALF(P,X) do { \
663 char *const _q = (char *) &_t; \
664 const char *const _p = \
665 (const char *) (P); \
670 } while (/*CONSTCOND*/0)
671 #define READ_WORD(P,X) do { \
673 char *const _q = (void *) &_t; \
674 const char *const _p = \
675 (const void *) (P); \
682 } while (/*CONSTCOND*/0)
683 #define READ_ADDR32(P,X) READ_WORD(P,X)
684 #define READ_OFF32(P,X) READ_WORD(P,X)
685 #define READ_SWORD(P,X) READ_WORD(P,X)
686 #define READ_WORD64(P,X) do { \
688 char *const _q = (void *) &_t; \
689 const char *const _p = \
690 (const void *) (P); \
701 } while (/*CONSTCOND*/0)
702 #define READ_ADDR64(P,X) READ_WORD64(P,X)
703 #define READ_LWORD(P,X) READ_WORD64(P,X)
704 #define READ_OFF64(P,X) READ_WORD64(P,X)
705 #define READ_SXWORD(P,X) READ_WORD64(P,X)
706 #define READ_XWORD(P,X) READ_WORD64(P,X)
707 #define READ_IDENT(P,X) do { \
708 (void) memcpy((X), (P), sizeof((X))); \
709 (P) = (P) + EI_NIDENT; \
710 } while (/*CONSTCOND*/0)
712 #define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1))
715 MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
716 MAKE_VERSION_CONVERTERS(VDEF,Verdef,Verdaux,vd)
717 MAKE_VERSION_CONVERTERS(VNEED,Verneed,Vernaux,vn)
721 * Sections of type ELF_T_BYTE are never byteswapped, consequently a
722 * simple memcpy suffices for both directions of conversion.
727 _libelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count,
734 (void) memcpy(dst, src, count);
739 * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit
740 * words. Bloom filter data comes next, followed by hash buckets and the
743 * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit
744 * wide on ELFCLASS32 objects. The other objects in this section are 32
747 * Argument `srcsz' denotes the number of bytes to be converted. In the
748 * 32-bit case we need to translate `srcsz' to a count of 32-bit words.
752 _libelf_cvt_GNUHASH32_tom(char *dst, size_t dsz, char *src, size_t srcsz,
755 return (_libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t),
760 _libelf_cvt_GNUHASH32_tof(char *dst, size_t dsz, char *src, size_t srcsz,
763 return (_libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t),
768 _libelf_cvt_GNUHASH64_tom(char *dst, size_t dsz, char *src, size_t srcsz,
772 uint64_t t64, *bloom64;
773 Elf_GNU_Hash_Header *gh;
774 uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32;
775 uint32_t *buckets, *chains;
777 sz = 4 * sizeof(uint32_t); /* File header is 4 words long. */
778 if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
781 /* Read in the section header and byteswap if needed. */
782 READ_WORD(src, nbuckets);
783 READ_WORD(src, symndx);
784 READ_WORD(src, maskwords);
785 READ_WORD(src, shift2);
792 SWAP_WORD(maskwords);
796 /* Check source buffer and destination buffer sizes. */
797 sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t);
798 if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header))
801 gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst;
802 gh->gh_nbuckets = nbuckets;
803 gh->gh_symndx = symndx;
804 gh->gh_maskwords = maskwords;
805 gh->gh_shift2 = shift2;
807 dsz -= sizeof(Elf_GNU_Hash_Header);
808 dst += sizeof(Elf_GNU_Hash_Header);
810 bloom64 = (uint64_t *) (uintptr_t) dst;
812 /* Copy bloom filter data. */
813 for (n = 0; n < maskwords; n++) {
814 READ_XWORD(src, t64);
820 /* The hash buckets follows the bloom filter. */
821 dst += maskwords * sizeof(uint64_t);
822 buckets = (uint32_t *) (uintptr_t) dst;
824 for (n = 0; n < nbuckets; n++) {
831 dst += nbuckets * sizeof(uint32_t);
833 /* The hash chain follows the hash buckets. */
837 if (dsz < srcsz) /* Destination lacks space. */
840 nchains = srcsz / sizeof(uint32_t);
841 chains = (uint32_t *) (uintptr_t) dst;
843 for (n = 0; n < nchains; n++) {
854 _libelf_cvt_GNUHASH64_tof(char *dst, size_t dsz, char *src, size_t srcsz,
860 Elf_GNU_Hash_Header *gh;
861 uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32;
863 hdrsz = 4 * sizeof(uint32_t); /* Header is 4x32 bits. */
864 if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header))
867 gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
869 t0 = nbuckets = gh->gh_nbuckets;
871 t2 = maskwords = gh->gh_maskwords;
874 src += sizeof(Elf_GNU_Hash_Header);
875 srcsz -= sizeof(Elf_GNU_Hash_Header);
878 sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
881 if (srcsz < sz || dsz < sz)
884 /* Write out the header. */
897 /* Copy the bloom filter and the hash table. */
898 s64 = (uint64_t *) (uintptr_t) src;
899 for (n = 0; n < maskwords; n++) {
903 WRITE_WORD64(dst, t64);
906 s32 = (uint32_t *) s64;
907 for (n = 0; n < nbuckets; n++) {
911 WRITE_WORD(dst, t32);
917 /* Copy out the hash chains. */
921 nchains = srcsz / sizeof(uint32_t);
922 for (n = 0; n < nchains; n++) {
926 WRITE_WORD(dst, t32);
933 * Elf note structures comprise a fixed size header followed by variable
934 * length strings. The fixed size header needs to be byte swapped, but
937 * Argument `count' denotes the total number of bytes to be converted.
938 * The destination buffer needs to be at least `count' bytes in size.
941 _libelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count,
944 uint32_t namesz, descsz, type;
948 if (dsz < count) /* Destination buffer is too small. */
951 hdrsz = 3 * sizeof(uint32_t);
952 if (count < hdrsz) /* Source too small. */
956 (void) memcpy(dst, src, count);
960 /* Process all notes in the section. */
961 while (count > hdrsz) {
962 /* Read the note header. */
963 READ_WORD(src, namesz);
964 READ_WORD(src, descsz);
965 READ_WORD(src, type);
972 /* Copy out the translated note header. */
973 en = (Elf_Note *) (uintptr_t) dst;
974 en->n_namesz = namesz;
975 en->n_descsz = descsz;
978 dsz -= sizeof(Elf_Note);
979 dst += sizeof(Elf_Note);
985 sz = namesz + descsz;
987 if (count < sz || dsz < sz) /* Buffers are too small. */
990 (void) memcpy(dst, src, sz);
1003 _libelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count,
1006 uint32_t namesz, descsz, type;
1014 (void) memcpy(dst, src, count);
1018 while (count > sizeof(Elf_Note)) {
1020 en = (Elf_Note *) (uintptr_t) src;
1021 namesz = en->n_namesz;
1022 descsz = en->n_descsz;
1029 WRITE_WORD(dst, namesz);
1030 WRITE_WORD(dst, descsz);
1031 WRITE_WORD(dst, type);
1033 src += sizeof(Elf_Note);
1035 ROUNDUP2(namesz, 4);
1036 ROUNDUP2(descsz, 4);
1038 sz = namesz + descsz;
1043 (void) memcpy(dst, src, sz);
1054 int (*tof32)(char *dst, size_t dsz, char *src, size_t cnt,
1056 int (*tom32)(char *dst, size_t dsz, char *src, size_t cnt,
1058 int (*tof64)(char *dst, size_t dsz, char *src, size_t cnt,
1060 int (*tom64)(char *dst, size_t dsz, char *src, size_t cnt,
1065 static struct converters cvt[ELF_T_NUM] = {
1067 CONVERTER_NAMES(ELF_TYPE_LIST)
1071 * Types that need hand-coded converters follow.
1075 .tof32 = _libelf_cvt_BYTE_tox,
1076 .tom32 = _libelf_cvt_BYTE_tox,
1077 .tof64 = _libelf_cvt_BYTE_tox,
1078 .tom64 = _libelf_cvt_BYTE_tox
1082 .tof32 = _libelf_cvt_NOTE_tof,
1083 .tom32 = _libelf_cvt_NOTE_tom,
1084 .tof64 = _libelf_cvt_NOTE_tof,
1085 .tom64 = _libelf_cvt_NOTE_tom
1089 int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
1090 (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap)
1092 assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
1093 assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
1095 if (t >= ELF_T_NUM ||
1096 (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
1097 (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
1100 return ((elfclass == ELFCLASS32) ?
1101 (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
1102 (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));