2 * Copyright (c) 2006-2011 Joseph Koshy
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
33 ELFTC_VCSID("$Id: libelf_convert.m4 3429 2016-03-12 04:12:39Z emaste $");
35 /* WARNING: GENERATED FROM __file__. */
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
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.
107 # Unimplemented types.
110 # ELF types that don't exist in a 32-bit world.
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',`
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;
153 (void) memcpy(dst, src, count * sizeof(*s));
157 for (c = 0; c < count; c++) {
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;
173 if (dsz < count * sizeof(Elf$3_$2))
177 (void) memcpy(dst, src, count * sizeof(*d));
181 for (c = 0; c < count; c++) {
192 # Handling composite ELF types
195 # SWAP_FIELD(FIELDNAME,ELFTYPE) -- Generate code to swap one field.
198 `SWAP_$2'SZ()`(t.$1);
203 # SWAP_MEMBERS(STRUCT) -- Iterate over a structure definition.
204 define(`SWAP_MEMBERS',
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',
216 `WRITE_$2'SZ()`(dst,t.$1);
221 # WRITE_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
222 define(`WRITE_MEMBERS',
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.
234 `READ_$2'SZ()`(s,t.$1);
239 # READ_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
240 define(`READ_MEMBERS',
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.
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,`',`
268 _libelf_cvt_$1$3_tof(unsigned char *dst, size_t dsz, unsigned char *src,
269 size_t count, int byteswap)
276 s = (Elf$3_$2 *) (uintptr_t) src;
277 for (c = 0; c < count; c++) {
289 _libelf_cvt_$1$3_tom(unsigned char *dst, size_t dsz, unsigned char *src,
290 size_t count, int byteswap)
293 unsigned char *s,*s0;
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))
316 # MAKE_TYPE_CONVERTER(ELFTYPE,CTYPE)
318 # Make type convertor functions from the type definition
320 # - Skip convertors marked as `NOFUNC'.
321 # - Invoke `MAKEPRIMFUNCS' or `MAKECOMPFUNCS' as appropriate.
322 define(`MAKE_TYPE_CONVERTER',
323 `ifdef(`NOFUNC_'$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',
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.
346 `ifdef(`NOFUNC_'$1$2,
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,`',
368 # CONVERTER_NAMES(ELFTYPELIST)
370 # Generate the `struct cvt[]' array.
371 define(`CONVERTER_NAMES',
373 `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
376 # Handling ELF version sections.
379 # _FSZ(FIELD,BASETYPE) - return the file size for a field.
384 # FSZ(STRUCT) - determine the file size of a structure.
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',`
399 _libelf_cvt_$1$5_tof(unsigned char *dst, size_t dsz, unsigned char *src,
400 size_t count, int byteswap)
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);
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);
445 pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
449 pushdef(`t',`a')WRITE_STRUCT($3, $5)popdef(`t')
463 _libelf_cvt_$1$5_tom(unsigned char *dst, size_t dsz, unsigned char *src,
464 size_t count, int byteswap)
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. */
488 dp = (Elf$5_$2 *) (uintptr_t) dst;
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--) {
505 pushdef(`t',`a')READ_STRUCT($3, $5)popdef(`t')
508 pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
513 ap = ((Elf$5_$3 *) (uintptr_t) dstaux);
530 * C macros to byte swap integral quantities.
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; \
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; \
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; \
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.
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.
579 #define WRITE_BYTE(P,X) do { \
580 unsigned char *const _p = (unsigned char *) (P); \
581 _p[0] = (unsigned char) (X); \
584 #define WRITE_HALF(P,X) do { \
586 unsigned char *const _p = (unsigned char *) (P); \
587 const unsigned char *const _q = (unsigned char *) &_t; \
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; \
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; \
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; \
630 * C macros to read in various integral values.
633 * - The source pointer could be unaligned.
634 * - Values are read in native byte order.
635 * - The source pointer is incremented appropriately.
638 #define READ_BYTE(P,X) do { \
639 const unsigned char *const _p = \
640 (const unsigned char *) (P); \
644 #define READ_HALF(P,X) do { \
646 unsigned char *const _q = (unsigned char *) &_t; \
647 const unsigned char *const _p = \
648 (const unsigned char *) (P); \
654 #define _READ_WORD(P,X,T) do { \
656 unsigned char *const _q = (unsigned char *) &_t; \
657 const unsigned char *const _p = \
658 (const unsigned char *) (P); \
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 { \
672 unsigned char *const _q = (unsigned char *) &_t; \
673 const unsigned char *const _p = \
674 (const unsigned char *) (P); \
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; \
696 #define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1))
699 MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
700 MAKE_VERSION_CONVERTERS(VDEF,Verdef,Verdaux,vd)
701 MAKE_VERSION_CONVERTERS(VNEED,Verneed,Vernaux,vn)
705 * Sections of type ELF_T_BYTE are never byteswapped, consequently a
706 * simple memcpy suffices for both directions of conversion.
710 _libelf_cvt_BYTE_tox(unsigned char *dst, size_t dsz, unsigned char *src,
711 size_t count, int byteswap)
717 (void) memcpy(dst, src, count);
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
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
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.
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),
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),
751 _libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
752 size_t srcsz, int byteswap)
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)
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);
775 SWAP_WORD(maskwords);
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))
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);
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++) {
814 dst += nbuckets * sizeof(uint32_t);
816 /* The hash chain follows the hash buckets. */
820 if (dsz < srcsz) /* Destination lacks space. */
823 nchains = srcsz / sizeof(uint32_t);
824 chains = (uint32_t *) (uintptr_t) dst;
826 for (n = 0; n < nchains; n++) {
837 _libelf_cvt_GNUHASH64_tof(unsigned char *dst, size_t dsz, unsigned char *src,
838 size_t srcsz, int byteswap)
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))
850 gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
852 t0 = nbuckets = gh->gh_nbuckets;
854 t2 = maskwords = gh->gh_maskwords;
857 src += sizeof(Elf_GNU_Hash_Header);
858 srcsz -= sizeof(Elf_GNU_Hash_Header);
861 sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
864 if (srcsz < sz || dsz < sz)
867 /* Write out the header. */
880 /* Copy the bloom filter and the hash table. */
881 s64 = (uint64_t *) (uintptr_t) src;
882 for (n = 0; n < maskwords; n++) {
886 WRITE_WORD64(dst, t64);
889 s32 = (uint32_t *) s64;
890 for (n = 0; n < nbuckets; n++) {
894 WRITE_WORD(dst, t32);
900 /* Copy out the hash chains. */
904 nchains = srcsz / sizeof(uint32_t);
905 for (n = 0; n < nchains; n++) {
909 WRITE_WORD(dst, t32);
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
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.
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;
931 if (dsz < count) /* Destination buffer is too small. */
934 hdrsz = 3 * sizeof(uint32_t);
935 if (count < hdrsz) /* Source too small. */
939 (void) memcpy(dst, src, count);
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);
955 /* Copy out the translated note header. */
956 en = (Elf_Note *) (uintptr_t) dst;
957 en->n_namesz = namesz;
958 en->n_descsz = descsz;
961 dsz -= sizeof(Elf_Note);
962 dst += sizeof(Elf_Note);
965 ROUNDUP2(namesz, 4U);
966 ROUNDUP2(descsz, 4U);
968 sz = namesz + descsz;
970 if (count < sz || dsz < sz) /* Buffers are too small. */
973 (void) memcpy(dst, src, sz);
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;
997 (void) memcpy(dst, src, count);
1001 while (count > sizeof(Elf_Note)) {
1003 en = (Elf_Note *) (uintptr_t) src;
1004 namesz = en->n_namesz;
1005 descsz = en->n_descsz;
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);
1027 (void) memcpy(dst, src, sz);
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] = {
1051 CONVERTER_NAMES(ELF_TYPE_LIST)
1055 * Types that need hand-coded converters follow.
1059 .tof32 = _libelf_cvt_BYTE_tox,
1060 .tom32 = _libelf_cvt_BYTE_tox,
1061 .tof64 = _libelf_cvt_BYTE_tox,
1062 .tom64 = _libelf_cvt_BYTE_tox
1066 .tof32 = _libelf_cvt_NOTE_tof,
1067 .tom32 = _libelf_cvt_NOTE_tom,
1068 .tof64 = _libelf_cvt_NOTE_tof,
1069 .tom64 = _libelf_cvt_NOTE_tom
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,
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))
1085 return ((elfclass == ELFCLASS32) ?
1086 (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
1087 (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));