2 * Copyright (c) 2006-2008 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
27 #include <sys/cdefs.h>
37 /* WARNING: GENERATED FROM __file__. */
40 * Macros to swap various integral quantities.
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; \
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; \
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; \
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.
83 #define WRITE_BYTE(P,X) do { \
84 char *const _p = (char *) (P); \
88 #define WRITE_HALF(P,X) do { \
90 char *const _p = (char *) (P); \
91 const char *const _q = (char *) &_t; \
96 #define WRITE_WORD(P,X) do { \
98 char *const _p = (char *) (P); \
99 const char *const _q = (char *) &_t; \
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 { \
111 char *const _p = (char *) (P); \
112 const char *const _q = (char *) &_t; \
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; \
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.
139 #define READ_BYTE(P,X) do { \
140 const char *const _p = \
141 (const char *) (P); \
145 #define READ_HALF(P,X) do { \
147 char *const _q = (char *) &_t; \
148 const char *const _p = \
149 (const char *) (P); \
155 #define READ_WORD(P,X) do { \
157 char *const _q = (char *) &_t; \
158 const char *const _p = \
159 (const char *) (P); \
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 { \
172 char *const _q = (char *) &_t; \
173 const char *const _p = \
174 (const char *) (P); \
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; \
196 #define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 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.
221 include(SRCDIR`/elf_types.m4')
224 * `IGNORE'_* flags turn off generation of template code.
228 `define(IGNORE_$1`'32, 1)
229 define(IGNORE_$1`'64, 1)')
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
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.
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.
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']
274 define(`MAKEPRIM_TO_F',`
276 libelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count,
279 Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src;
285 (void) memcpy(dst, src, count * sizeof(*s));
289 for (c = 0; c < count; c++) {
299 define(`MAKEPRIM_TO_M',`
301 libelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count,
304 Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst;
307 if (dsz < count * sizeof(Elf$4_$2))
311 (void) memcpy(dst, src, count * sizeof(*d));
315 for (c = 0; c < count; c++) {
326 `ifdef(`IGNORE_'$2,`',
332 `SWAP_$2'SZ()`(t.$1);
334 define(`SWAP_MEMBERS',
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',
349 `WRITE_$2'SZ()`(dst,t.$1);
351 define(`WRITE_MEMBERS',
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')')
366 `READ_$2'SZ()`(s,t.$1);
369 define(`READ_MEMBERS',
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.
391 * `$1': Name of the ELF type.
392 * `$2': C structure name suffix.
393 * `$3': ELF class specifier, one of [`', `32', `64']
397 `ifdef(`IGNORE_'$1$3,`',`
399 libelf_cvt$3_$1_tof(char *dst, size_t dsz, char *src, size_t count,
407 s = (Elf$3_$2 *) (uintptr_t) src;
408 for (c = 0; c < count; c++) {
421 `ifdef(`IGNORE_'$1$3,`',`
423 libelf_cvt$3_$1_tom(char *dst, size_t dsz, char *src, size_t count,
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))
451 * Make type convertor functions from the type definition
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.
463 define(`MAKE_TYPE_CONVERTER',
465 `ifdef(`IGNORE_'$1,`',
466 `MAKEPRIM_TO_F($1,$2,`',64)
467 MAKEPRIM_TO_M($1,$2,`',64)')',
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',
481 `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
486 * Sections of type ELF_T_BYTE are never byteswapped, consequently a
487 * simple memcpy suffices for both directions of conversion.
491 libelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count,
498 (void) memcpy(dst, src, count);
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
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
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.
518 libelf_cvt32_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz,
521 return (libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t),
526 libelf_cvt32_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz,
529 return (libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t),
534 libelf_cvt64_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz,
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)
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);
558 SWAP_WORD(maskwords);
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))
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;
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);
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++) {
597 dst += nbuckets * sizeof(uint32_t);
599 /* The hash chain follows the hash buckets. */
603 if (dsz < srcsz) /* Destination lacks space. */
606 nchains = srcsz / sizeof(uint32_t);
607 chains = (uint32_t *) (uintptr_t) dst;
609 for (n = 0; n < nchains; n++) {
620 libelf_cvt64_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz,
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))
633 gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
635 t0 = nbuckets = gh->gh_nbuckets;
637 t2 = maskwords = gh->gh_maskwords;
640 src += sizeof(Elf_GNU_Hash_Header);
641 srcsz -= sizeof(Elf_GNU_Hash_Header);
644 sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
647 if (srcsz < sz || dsz < sz)
650 /* Write out the header. */
663 /* Copy the bloom filter and the hash table. */
664 s64 = (uint64_t *) (uintptr_t) src;
665 for (n = 0; n < maskwords; n++) {
669 WRITE_WORD64(dst, t64);
672 s32 = (uint32_t *) s64;
673 for (n = 0; n < nbuckets; n++) {
677 WRITE_WORD(dst, t32);
683 /* Copy out the hash chains. */
687 nchains = srcsz / sizeof(uint32_t);
688 for (n = 0; n < nchains; n++) {
692 WRITE_WORD(dst, t32);
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
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.
707 libelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count,
710 uint32_t namesz, descsz, type;
714 if (dsz < count) /* Destination buffer is too small. */
717 hdrsz = 3 * sizeof(uint32_t);
718 if (count < hdrsz) /* Source too small. */
722 (void) memcpy(dst, src, count);
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);
738 /* Copy out the translated note header. */
739 en = (Elf_Note *) (uintptr_t) dst;
740 en->n_namesz = namesz;
741 en->n_descsz = descsz;
744 dsz -= sizeof(Elf_Note);
745 dst += sizeof(Elf_Note);
751 sz = namesz + descsz;
753 if (count < sz || dsz < sz) /* Buffers are too small. */
756 (void) memcpy(dst, src, sz);
769 libelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count,
772 uint32_t namesz, descsz, type;
780 (void) memcpy(dst, src, count);
784 while (count > sizeof(Elf_Note)) {
786 en = (Elf_Note *) (uintptr_t) src;
787 namesz = en->n_namesz;
788 descsz = en->n_descsz;
795 WRITE_WORD(dst, namesz);
796 WRITE_WORD(dst, descsz);
797 WRITE_WORD(dst, type);
799 src += sizeof(Elf_Note);
804 sz = namesz + descsz;
809 (void) memcpy(dst, src, sz);
820 int (*tof32)(char *dst, size_t dsz, char *src, size_t cnt,
822 int (*tom32)(char *dst, size_t dsz, char *src, size_t cnt,
824 int (*tof64)(char *dst, size_t dsz, char *src, size_t cnt,
826 int (*tom64)(char *dst, size_t dsz, char *src, size_t cnt,
832 `ifdef(`IGNORE_'$1$2,
835 `.$3$2 = libelf_cvt_$1_$3',
837 `.$3$2 = libelf_cvt_$1$2_$3',
838 `.$3$2 = libelf_cvt$2_$1_$3')')')')
840 define(`CONVERTER_NAME',
841 `ifdef(`IGNORE_'$1,`',
843 CONV($1,32,tof), CONV($1,32,tom),
844 CONV($1,64,tof), CONV($1,64,tom) },
847 define(`CONVERTER_NAMES',
849 `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
851 undefine(`IGNORE_BYTE32', `IGNORE_BYTE64')
854 static struct converters cvt[ELF_T_NUM] = {
855 CONVERTER_NAMES(ELF_TYPE_LIST)
858 * Types that needs hand-coded converters follow.
862 .tof32 = libelf_cvt_BYTE_tox,
863 .tom32 = libelf_cvt_BYTE_tox,
864 .tof64 = libelf_cvt_BYTE_tox,
865 .tom64 = libelf_cvt_BYTE_tox
869 .tof32 = libelf_cvt32_GNUHASH_tof,
870 .tom32 = libelf_cvt32_GNUHASH_tom,
871 .tof64 = libelf_cvt64_GNUHASH_tof,
872 .tom64 = libelf_cvt64_GNUHASH_tom
876 .tof32 = libelf_cvt_NOTE_tof,
877 .tom32 = libelf_cvt_NOTE_tom,
878 .tof64 = libelf_cvt_NOTE_tof,
879 .tom64 = libelf_cvt_NOTE_tom
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))
894 return ((elfclass == ELFCLASS32) ?
895 (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
896 (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));