2 * Copyright (c) 2006,2007 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>
28 __FBSDID("$FreeBSD$");
30 #include <sys/types.h>
31 #include <sys/elf32.h>
32 #include <sys/elf64.h>
36 #include <osreldate.h>
41 /* WARNING: GENERATED FROM __file__. */
44 * Macros to swap various integral quantities.
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; \
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; \
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; \
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)
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.
87 #define WRITE_BYTE(P,X) do { \
88 unsigned char *const _p = (unsigned char *) (P); \
89 _p[0] = (unsigned char) (X); \
92 #define WRITE_HALF(P,X) do { \
94 unsigned char *const _p = (unsigned char *) (P); \
95 unsigned const char *const _q = (unsigned char *) &_t; \
100 #define WRITE_WORD(P,X) do { \
102 unsigned char *const _p = (unsigned char *) (P); \
103 unsigned const char *const _q = (unsigned char *) &_t; \
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 { \
115 unsigned char *const _p = (unsigned char *) (P); \
116 unsigned const char *const _q = (unsigned char *) &_t; \
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; \
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.
143 #define READ_BYTE(P,X) do { \
144 const unsigned char *const _p = \
145 (const unsigned char *) (P); \
149 #define READ_HALF(P,X) do { \
151 unsigned char *const _q = (unsigned char *) &_t; \
152 const unsigned char *const _p = \
153 (const unsigned char *) (P); \
159 #define READ_WORD(P,X) do { \
161 unsigned char *const _q = (unsigned char *) &_t; \
162 const unsigned char *const _p = \
163 (const unsigned char *) (P); \
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 { \
176 unsigned char *const _q = (unsigned char *) &_t; \
177 const unsigned char *const _p = \
178 (const unsigned char *) (P); \
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; \
200 #define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1))
205 * Generate conversion routines for converting between in-memory and
206 * file representations of Elf data structures.
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.
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.
225 include(SRCDIR`/elf_types.m4')
228 * `IGNORE'_* flags turn off generation of template code.
232 `define(IGNORE_$1`'32, 1)
233 define(IGNORE_$1`'64, 1)')
238 define(IGNORE_BYTE, 1) /* 'lator, leave 'em bytes alone */
239 define(IGNORE_NOTE, 1)
240 define(IGNORE_SXWORD32, 1)
241 define(IGNORE_XWORD32, 1)
244 * `BASE'_XXX flags cause class agnostic template functions
248 define(`BASE_BYTE', 1)
249 define(`BASE_HALF', 1)
250 define(`BASE_NOTE', 1)
251 define(`BASE_WORD', 1)
252 define(`BASE_LWORD', 1)
253 define(`BASE_SWORD', 1)
254 define(`BASE_XWORD', 1)
255 define(`BASE_SXWORD', 1)
258 * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated
259 * for each primitive type.
262 define(`SIZEDEP_ADDR', 1)
263 define(`SIZEDEP_OFF', 1)
266 * `Primitive' ELF types are those that are an alias for an integral
267 * type. They have no internal structure. These can be copied using
268 * a `memcpy()', and byteswapped in straightforward way.
271 * `$1': Name of the ELF type.
272 * `$2': C structure name suffix
273 * `$3': ELF class specifier for symbols, one of [`', `32', `64']
274 * `$4': ELF class specifier for types, one of [`32', `64']
276 define(`MAKEPRIM_TO_F',`
278 libelf_cvt_$1$3_tof(char *dst, char *src, size_t count, int byteswap)
280 Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src;
283 if (dst == src && !byteswap)
287 (void) memcpy(dst, src, count * sizeof(*s));
291 for (c = 0; c < count; c++) {
299 define(`MAKEPRIM_TO_M',`
301 libelf_cvt_$1$3_tom(char *dst, char *src, size_t count, int byteswap)
303 Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst;
306 if (dst == src && !byteswap)
310 (void) memcpy(dst, src, count * sizeof(*d));
314 for (c = 0; c < count; c++) {
323 `ifdef(`IGNORE_'$2,`',
329 `SWAP_$2'SZ()`(t.$1);
331 define(`SWAP_MEMBERS',
333 `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
335 define(`SWAP_STRUCT',
336 `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
337 SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
339 define(`WRITE_FIELD',
346 `WRITE_$2'SZ()`(dst,t.$1);
348 define(`WRITE_MEMBERS',
350 `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
352 define(`WRITE_STRUCT',
353 `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
354 WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
363 `READ_$2'SZ()`(s,t.$1);
366 define(`READ_MEMBERS',
368 `READ_FIELD($1)READ_MEMBERS(shift($@))')')
370 define(`READ_STRUCT',
371 `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
372 READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
375 * Converters for non-integral ELF data structures.
377 * When converting data to file representation, the source pointer
378 * will be naturally aligned for a data structure's in-memory
379 * representation. When converting data to memory, the destination
380 * pointer will be similarly aligned.
382 * For in-place conversions, when converting to file representations,
383 * the source buffer is large enough to hold `file' data. When
384 * converting from file to memory, we need to be careful to work
385 * `backwards', to avoid overwriting unconverted data.
388 * `$1': Name of the ELF type.
389 * `$2': C structure name suffix.
390 * `$3': ELF class specifier, one of [`', `32', `64']
394 `ifdef(`IGNORE_'$1$3,`',`
396 libelf_cvt$3_$1_tof(char *dst, char *src, size_t count, int byteswap)
401 s = (Elf$3_$2 *) (uintptr_t) src;
402 for (c = 0; c < count; c++) {
413 `ifdef(`IGNORE_'$1$3,`',`
415 libelf_cvt$3_$1_tom(char *dst, char *src, size_t count, int byteswap)
418 unsigned char *s,*s0;
421 fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
422 d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
423 s0 = (unsigned char *) src + (count - 1) * fsz;
437 * Make type convertor functions from the type definition
439 * - if the type is a base (i.e., `primitive') type:
440 * - if it is marked as to be ignored (i.e., `IGNORE_'TYPE)
441 * is defined, we skip the code generation step.
442 * - if the type is declared as `SIZEDEP', then 32 and 64 bit
443 * variants of the conversion functions are generated.
444 * - otherwise a 32 bit variant is generated.
445 * - if the type is a structure type, we generate 32 and 64 bit
446 * variants of the conversion functions.
449 define(`MAKE_TYPE_CONVERTER',
450 `#if __FreeBSD_version >= $3 /* $1 */
452 `ifdef(`IGNORE_'$1,`',
453 `MAKEPRIM_TO_F($1,$2,`',64)
454 MAKEPRIM_TO_M($1,$2,`',64)')',
456 `MAKEPRIM_TO_F($1,$2,32,32)dnl
457 MAKEPRIM_TO_M($1,$2,32,32)dnl
458 MAKEPRIM_TO_F($1,$2,64,64)dnl
459 MAKEPRIM_TO_M($1,$2,64,64)',
460 `MAKE_TO_F($1,$2,32)dnl
461 MAKE_TO_F($1,$2,64)dnl
462 MAKE_TO_M($1,$2,32)dnl
463 MAKE_TO_M($1,$2,64)')')
467 define(`MAKE_TYPE_CONVERTERS',
469 `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
474 * Sections of type ELF_T_BYTE are never byteswapped, consequently a
475 * simple memcpy suffices for both directions of conversion.
479 libelf_cvt_BYTE_tox(char *dst, char *src, size_t count, int byteswap)
483 (void) memcpy(dst, src, count);
487 * Elf_Note structures comprise a fixed size header followed by variable
488 * length strings. The fixed size header needs to be byte swapped, but
491 * Argument `count' denotes the total number of bytes to be converted.
494 libelf_cvt_NOTE_tom(char *dst, char *src, size_t count, int byteswap)
496 uint32_t namesz, descsz, type;
500 if (dst == src && !byteswap)
504 (void) memcpy(dst, src, count);
508 while (count > sizeof(Elf_Note)) {
510 READ_WORD(src, namesz);
511 READ_WORD(src, descsz);
512 READ_WORD(src, type);
520 en = (Elf_Note *) (uintptr_t) dst;
521 en->n_namesz = namesz;
522 en->n_descsz = descsz;
525 dst += sizeof(Elf_Note);
530 sz = namesz + descsz;
535 (void) memcpy(dst, src, sz);
544 libelf_cvt_NOTE_tof(char *dst, char *src, size_t count, int byteswap)
546 uint32_t namesz, descsz, type;
550 if (dst == src && !byteswap)
554 (void) memcpy(dst, src, count);
558 while (count > sizeof(Elf_Note)) {
560 en = (Elf_Note *) (uintptr_t) src;
561 namesz = en->n_namesz;
562 descsz = en->n_descsz;
572 WRITE_WORD(dst, namesz);
573 WRITE_WORD(dst, descsz);
574 WRITE_WORD(dst, type);
576 src += sizeof(Elf_Note);
581 sz = namesz + descsz;
586 (void) memcpy(dst, src, sz);
594 MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
597 void (*tof32)(char *dst, char *src, size_t cnt, int byteswap);
598 void (*tom32)(char *dst, char *src, size_t cnt, int byteswap);
599 void (*tof64)(char *dst, char *src, size_t cnt, int byteswap);
600 void (*tom64)(char *dst, char *src, size_t cnt, int byteswap);
605 `ifdef(`IGNORE_'$1$2,
608 `.$3$2 = libelf_cvt_$1_$3',
610 `.$3$2 = libelf_cvt_$1$2_$3',
611 `.$3$2 = libelf_cvt$2_$1_$3')')')')
613 define(`CONVERTER_NAME',
614 `ifdef(`IGNORE_'$1,`',
615 `#if __FreeBSD_version >= $3
617 CONV($1,32,tof), CONV($1,32,tom),
618 CONV($1,64,tof), CONV($1,64,tom) },
622 define(`CONVERTER_NAMES',
624 `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
626 undefine(`IGNORE_BYTE32', `IGNORE_BYTE64')
629 static struct converters cvt[ELF_T_NUM] = {
630 CONVERTER_NAMES(ELF_TYPE_LIST)
633 * Types that needs hand-coded converters follow.
637 .tof32 = libelf_cvt_BYTE_tox,
638 .tom32 = libelf_cvt_BYTE_tox,
639 .tof64 = libelf_cvt_BYTE_tox,
640 .tom64 = libelf_cvt_BYTE_tox
643 .tof32 = libelf_cvt_NOTE_tof,
644 .tom32 = libelf_cvt_NOTE_tom,
645 .tof64 = libelf_cvt_NOTE_tof,
646 .tom64 = libelf_cvt_NOTE_tom
650 void (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
651 (char *_dst, char *_src, size_t _cnt, int _byteswap)
653 assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
654 assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
656 if (t >= ELF_T_NUM ||
657 (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
658 (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
661 return ((elfclass == ELFCLASS32) ?
662 (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
663 (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));