source: rtems-tools/rtemstoolkit/elftoolchain/libelf/libelf_convert.m4 @ 0c5db2d

5
Last change on this file since 0c5db2d was 0c5db2d, checked in by Chris Johns <chrisj@…>, on 04/29/18 at 01:55:37

rtemstoolkit: Update elftoolchain to the latest code.

The update is taken from https://github.com/elftoolchain/elftoolchain.

Update #3417

  • Property mode set to 100644
File size: 27.0 KB
Line 
1/*-
2 * Copyright (c) 2006-2011 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
29#include <assert.h>
30#include <libelf.h>
31#include <string.h>
32
33#include "_libelf.h"
34
35LIBELF_VCSID("$Id$");
36
37/* WARNING: GENERATED FROM __file__. */
38
39divert(-1)
40
41# Generate conversion routines for converting between in-memory and
42# file representations of Elf data structures.
43#
44# These conversions use the type information defined in `elf_types.m4'.
45
46include(SRCDIR`/elf_types.m4')
47
48# For the purposes of generating conversion code, ELF types may be
49# classified according to the following characteristics:
50#
51# 1. Whether the ELF type can be directly mapped to an integral C
52#    language type.  For example, the ELF_T_WORD type maps directly to
53#    a 'uint32_t', but ELF_T_GNUHASH lacks a matching C type.
54#
55# 2. Whether the type has word size dependent variants.  For example,
56#    ELT_T_EHDR is represented using C types Elf32_Ehdr and El64_Ehdr,
57#    and the ELF_T_ADDR and ELF_T_OFF types have integral C types that
58#    can be 32- or 64- bit wide.
59#
60# 3. Whether the ELF types has a fixed representation or not.  For
61#    example, the ELF_T_SYM type has a fixed size file representation,
62#    some types like ELF_T_NOTE and ELF_T_GNUHASH use a variable size
63#    representation.
64#
65# We use m4 macros to generate conversion code for ELF types that have
66# a fixed size representation.  Conversion functions for the remaining
67# types are coded by hand.
68#
69#* Handling File and Memory Representations
70#
71# `In-memory' representations of an Elf data structure use natural
72# alignments and native byte ordering.  This allows pointer arithmetic
73# and casting to work as expected.  On the other hand, the `file'
74# representation of an ELF data structure could possibly be packed
75# tighter than its `in-memory' representation, and could be of a
76# differing byte order.  Reading ELF objects that are members of `ar'
77# archives present an additional complication: `ar' pads file data to
78# even addresses, so file data structures in an archive member
79# residing inside an `ar' archive could be at misaligned memory
80# addresses when brought into memory.
81#
82# In summary, casting the `char *' pointers that point to memory
83# representations (i.e., source pointers for the *_tof() functions and
84# the destination pointers for the *_tom() functions), is safe, as
85# these pointers should be correctly aligned for the memory type
86# already.  However, pointers to file representations have to be
87# treated as being potentially unaligned and no casting can be done.
88
89# NOCVT(TYPE) -- Do not generate the cvt[] structure entry for TYPE
90define(`NOCVT',`define(`NOCVT_'$1,1)')
91
92# NOFUNC(TYPE) -- Do not generate a conversion function for TYPE
93define(`NOFUNC',`define(`NOFUNC_'$1,1)')
94
95# IGNORE(TYPE) -- Completely ignore the type.
96define(`IGNORE',`NOCVT($1)NOFUNC($1)')
97
98# Mark ELF types that should not be processed by the M4 macros below.
99
100# Types for which we use functions with non-standard names.
101IGNORE(`BYTE')                  # Uses a wrapper around memcpy().
102IGNORE(`NOTE')                  # Not a fixed size type.
103
104# Types for which we supply hand-coded functions.
105NOFUNC(`GNUHASH')               # A type with complex internal structure.
106NOFUNC(`VDEF')                  # See MAKE_VERSION_CONVERTERS below.
107NOFUNC(`VNEED')                 # ..
108
109# Unimplemented types.
110IGNORE(`MOVEP')
111
112# ELF types that don't exist in a 32-bit world.
113NOFUNC(`XWORD32')
114NOFUNC(`SXWORD32')
115
116# `Primitive' ELF types are those that are an alias for an integral
117# type.  As they have no internal structure, they can be copied using
118# a `memcpy()', and byteswapped in straightforward way.
119#
120# Mark all ELF types that directly map to integral C types.
121define(`PRIM_ADDR',     1)
122define(`PRIM_BYTE',     1)
123define(`PRIM_HALF',     1)
124define(`PRIM_LWORD',    1)
125define(`PRIM_OFF',      1)
126define(`PRIM_SWORD',    1)
127define(`PRIM_SXWORD',   1)
128define(`PRIM_WORD',     1)
129define(`PRIM_XWORD',    1)
130
131# Note the primitive types that are size-dependent.
132define(`SIZEDEP_ADDR',  1)
133define(`SIZEDEP_OFF',   1)
134
135# Generate conversion functions for primitive types.
136#
137# Macro use: MAKEPRIMFUNCS(ELFTYPE,CTYPE,TYPESIZE,SYMSIZE)
138# `$1': Name of the ELF type.
139# `$2': C structure name suffix.
140# `$3': ELF class specifier for types, one of [`32', `64'].
141# `$4': Additional ELF class specifier, one of [`', `32', `64'].
142#
143# Generates a pair of conversion functions.
144define(`MAKEPRIMFUNCS',`
145static int
146libelf_cvt_$1$4_tof(char *dst, size_t dsz, char *src, size_t count,
147    int byteswap)
148{
149        Elf$3_$2 t, *s = (Elf$3_$2 *) (uintptr_t) src;
150        size_t c;
151
152        (void) dsz;
153
154        if (!byteswap) {
155                (void) memcpy(dst, src, count * sizeof(*s));
156                return (1);
157        }
158
159        for (c = 0; c < count; c++) {
160                t = *s++;
161                SWAP_$1$4(t);
162                WRITE_$1$4(dst,t);
163        }
164
165        return (1);
166}
167
168static int
169libelf_cvt_$1$4_tom(char *dst, size_t dsz, char *src, size_t count,
170    int byteswap)
171{
172        Elf$3_$2 t, *d = (Elf$3_$2 *) (uintptr_t) dst;
173        size_t c;
174
175        if (dsz < count * sizeof(Elf$3_$2))
176                return (0);
177
178        if (!byteswap) {
179                (void) memcpy(dst, src, count * sizeof(*d));
180                return (1);
181        }
182
183        for (c = 0; c < count; c++) {
184                READ_$1$4(src,t);
185                SWAP_$1$4(t);
186                *d++ = t;
187        }
188
189        return (1);
190}
191')
192
193#
194# Handling composite ELF types
195#
196
197# SWAP_FIELD(FIELDNAME,ELFTYPE) -- Generate code to swap one field.
198define(`SWAP_FIELD',
199  `ifdef(`SIZEDEP_'$2,
200    `SWAP_$2'SZ()`(t.$1);
201                        ',
202    `SWAP_$2(t.$1);
203                        ')')
204
205# SWAP_MEMBERS(STRUCT) -- Iterate over a structure definition.
206define(`SWAP_MEMBERS',
207  `ifelse($#,1,`/**/',
208     `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')')
209
210# SWAP_STRUCT(CTYPE,SIZE) -- Generate code to swap an ELF structure.
211define(`SWAP_STRUCT',
212  `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */
213                        SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
214
215# WRITE_FIELD(ELFTYPE,FIELDNAME) -- Generate code to write one field.
216define(`WRITE_FIELD',
217  `ifdef(`SIZEDEP_'$2,
218    `WRITE_$2'SZ()`(dst,t.$1);
219                ',
220    `WRITE_$2(dst,t.$1);
221                ')')
222
223# WRITE_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
224define(`WRITE_MEMBERS',
225  `ifelse($#,1,`/**/',
226    `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')')
227
228# WRITE_STRUCT(CTYPE,SIZE) -- Generate code to write out an ELF structure.
229define(`WRITE_STRUCT',
230  `pushdef(`SZ',$2)/* Write an Elf$2_$1 */
231                WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
232
233# READ_FIELD(ELFTYPE,CTYPE) -- Generate code to read one field.
234define(`READ_FIELD',
235  `ifdef(`SIZEDEP_'$2,
236    `READ_$2'SZ()`(s,t.$1);
237                ',
238    `READ_$2(s,t.$1);
239                ')')
240
241# READ_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition.
242define(`READ_MEMBERS',
243  `ifelse($#,1,`/**/',
244    `READ_FIELD($1)READ_MEMBERS(shift($@))')')
245
246# READ_STRUCT(CTYPE,SIZE) -- Generate code to read an ELF structure.
247define(`READ_STRUCT',
248  `pushdef(`SZ',$2)/* Read an Elf$2_$1 */
249                READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')')
250
251
252# MAKECOMPFUNCS -- Generate converters for composite ELF structures.
253#
254# When converting data to file representation, the source pointer will
255# be naturally aligned for a data structure's in-memory
256# representation.  When converting data to memory, the destination
257# pointer will be similarly aligned.
258#
259# For in-place conversions, when converting to file representations,
260# the source buffer is large enough to hold `file' data.  When
261# converting from file to memory, we need to be careful to work
262# `backwards', to avoid overwriting unconverted data.
263#
264# Macro use:
265# `$1': Name of the ELF type.
266# `$2': C structure name suffix.
267# `$3': ELF class specifier, one of [`', `32', `64']
268define(`MAKECOMPFUNCS', `ifdef(`NOFUNC_'$1$3,`',`
269static int
270libelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count,
271    int byteswap)
272{
273        Elf$3_$2        t, *s;
274        size_t c;
275
276        (void) dsz;
277
278        s = (Elf$3_$2 *) (uintptr_t) src;
279        for (c = 0; c < count; c++) {
280                t = *s++;
281                if (byteswap) {
282                        SWAP_STRUCT($2,$3)
283                }
284                WRITE_STRUCT($2,$3)
285        }
286
287        return (1);
288}
289
290static int
291libelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count,
292    int byteswap)
293{
294        Elf$3_$2         t, *d;
295        char            *s,*s0;
296        size_t          fsz;
297
298        fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT);
299        d   = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1);
300        s0  = (char *) src + (count - 1) * fsz;
301
302        if (dsz < count * sizeof(Elf$3_$2))
303                return (0);
304
305        while (count--) {
306                s = s0;
307                READ_STRUCT($2,$3)
308                if (byteswap) {
309                        SWAP_STRUCT($2,$3)
310                }
311                *d-- = t; s0 -= fsz;
312        }
313
314        return (1);
315}
316')')
317
318# MAKE_TYPE_CONVERTER(ELFTYPE,CTYPE)
319#
320# Make type convertor functions from the type definition
321# of the ELF type:
322# - Skip convertors marked as `NOFUNC'.
323# - Invoke `MAKEPRIMFUNCS' or `MAKECOMPFUNCS' as appropriate.
324define(`MAKE_TYPE_CONVERTER',
325  `ifdef(`NOFUNC_'$1,`',
326    `ifdef(`PRIM_'$1,
327      `ifdef(`SIZEDEP_'$1,
328        `MAKEPRIMFUNCS($1,$2,32,32)dnl
329         MAKEPRIMFUNCS($1,$2,64,64)',
330        `MAKEPRIMFUNCS($1,$2,64)')',
331      `MAKECOMPFUNCS($1,$2,32)dnl
332       MAKECOMPFUNCS($1,$2,64)')')')
333
334# MAKE_TYPE_CONVERTERS(ELFTYPELIST) -- Generate conversion functions.
335define(`MAKE_TYPE_CONVERTERS',
336  `ifelse($#,1,`',
337    `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')')
338
339
340#
341# Macros to generate entries for the table of convertors.
342#
343
344# CONV(ELFTYPE,SIZE,DIRECTION)
345#
346# Generate the name of a convertor function.
347define(`CONV',
348  `ifdef(`NOFUNC_'$1$2,
349    `.$3$2 = NULL',
350    `ifdef(`PRIM_'$1,
351      `ifdef(`SIZEDEP_'$1,
352        `.$3$2 = libelf_cvt_$1$2_$3',
353        `.$3$2 = libelf_cvt_$1_$3')',
354      `.$3$2 = libelf_cvt_$1$2_$3')')')
355
356# CONVERTER_NAME(ELFTYPE)
357#
358# Generate the contents of one `struct cvt' instance.
359define(`CONVERTER_NAME',
360  `ifdef(`NOCVT_'$1,`',
361    `   [ELF_T_$1] = {
362                CONV($1,32,tof),
363                CONV($1,32,tom),
364                CONV($1,64,tof),
365                CONV($1,64,tom)
366        },
367
368')')
369
370# CONVERTER_NAMES(ELFTYPELIST)
371#
372# Generate the `struct cvt[]' array.
373define(`CONVERTER_NAMES',
374  `ifelse($#,1,`',
375    `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')')
376
377#
378# Handling ELF version sections.
379#
380
381# _FSZ(FIELD,BASETYPE) - return the file size for a field.
382define(`_FSZ',
383  `ifelse($2,`HALF',2,
384     $2,`WORD',4)')
385
386# FSZ(STRUCT) - determine the file size of a structure.
387define(`FSZ',
388  `ifelse($#,1,0,
389    `eval(_FSZ($1) + FSZ(shift($@)))')')
390
391# MAKE_VERSION_CONVERTERS(TYPE,BASE,AUX,PFX) -- Generate conversion
392# functions for versioning structures.
393define(`MAKE_VERSION_CONVERTERS',
394  `MAKE_VERSION_CONVERTER($1,$2,$3,$4,32)
395   MAKE_VERSION_CONVERTER($1,$2,$3,$4,64)')
396
397# MAKE_VERSION_CONVERTOR(TYPE,CBASE,CAUX,PFX,SIZE) -- Generate a
398# conversion function.
399define(`MAKE_VERSION_CONVERTER',`
400static int
401libelf_cvt_$1$5_tof(char *dst, size_t dsz, char *src, size_t count,
402    int byteswap)
403{
404        Elf$5_$2        t;
405        Elf$5_$3        a;
406        const size_t    verfsz = FSZ(Elf$5_$2_DEF);
407        const size_t    auxfsz = FSZ(Elf$5_$3_DEF);
408        const size_t    vermsz = sizeof(Elf$5_$2);
409        const size_t    auxmsz = sizeof(Elf$5_$3);
410        char * const    dstend = dst + dsz;
411        char * const    srcend = src + count;
412        char            *dtmp, *dstaux, *srcaux;
413        Elf$5_Word      aux, anext, cnt, vnext;
414
415        for (dtmp = dst, vnext = ~0;
416             vnext != 0 && dtmp + verfsz <= dstend && src + vermsz <= srcend;
417             dtmp += vnext, src += vnext) {
418
419                /* Read in an Elf$5_$2 structure. */
420                t = *((Elf$5_$2 *) (uintptr_t) src);
421
422                aux = t.$4_aux;
423                cnt = t.$4_cnt;
424                vnext = t.$4_next;
425
426                if (byteswap) {
427                        SWAP_STRUCT($2, $5)
428                }
429
430                dst = dtmp;
431                WRITE_STRUCT($2, $5)
432
433                if (aux < verfsz)
434                        return (0);
435
436                /* Process AUX entries. */
437                for (anext = ~0, dstaux = dtmp + aux, srcaux = src + aux;
438                     cnt != 0 && anext != 0 && dstaux + auxfsz <= dstend &&
439                        srcaux + auxmsz <= srcend;
440                     dstaux += anext, srcaux += anext, cnt--) {
441
442                        /* Read in an Elf$5_$3 structure. */
443                        a = *((Elf$5_$3 *) (uintptr_t) srcaux);
444                        anext = a.$4a_next;
445
446                        if (byteswap) {
447                                pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
448                        }
449
450                        dst = dstaux;
451                        pushdef(`t',`a')WRITE_STRUCT($3, $5)popdef(`t')
452                }
453
454                if (anext || cnt)
455                        return (0);
456        }
457
458        if (vnext)
459                return (0);
460
461        return (1);
462}
463
464static int
465libelf_cvt_$1$5_tom(char *dst, size_t dsz, char *src, size_t count,
466    int byteswap)
467{
468        Elf$5_$2        t, *dp;
469        Elf$5_$3        a, *ap;
470        const size_t    verfsz = FSZ(Elf$5_$2_DEF);
471        const size_t    auxfsz = FSZ(Elf$5_$3_DEF);
472        const size_t    vermsz = sizeof(Elf$5_$2);
473        const size_t    auxmsz = sizeof(Elf$5_$3);
474        char * const    dstend = dst + dsz;
475        char * const    srcend = src + count;
476        char            *dstaux, *s, *srcaux, *stmp;
477        Elf$5_Word      aux, anext, cnt, vnext;
478
479        for (stmp = src, vnext = ~0;
480             vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend;
481             stmp += vnext, dst += vnext) {
482
483                /* Read in a $1 structure. */
484                s = stmp;
485                READ_STRUCT($2, $5)
486                if (byteswap) {
487                        SWAP_STRUCT($2, $5)
488                }
489
490                dp = (Elf$5_$2 *) (uintptr_t) dst;
491                *dp = t;
492
493                aux = t.$4_aux;
494                cnt = t.$4_cnt;
495                vnext = t.$4_next;
496
497                if (aux < vermsz)
498                        return (0);
499
500                /* Process AUX entries. */
501                for (anext = ~0, dstaux = dst + aux, srcaux = stmp + aux;
502                     cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend &&
503                        srcaux + auxfsz <= srcend;
504                     dstaux += anext, srcaux += anext, cnt--) {
505
506                        s = srcaux;
507                        pushdef(`t',`a')READ_STRUCT($3, $5)popdef(`t')
508
509                        if (byteswap) {
510                                pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t')
511                        }
512
513                        anext = a.$4a_next;
514
515                        ap = ((Elf$5_$3 *) (uintptr_t) dstaux);
516                        *ap = a;
517                }
518
519                if (anext || cnt)
520                        return (0);
521        }
522
523        if (vnext)
524                return (0);
525
526        return (1);
527}')
528
529divert(0)
530
531/*
532 * C macros to byte swap integral quantities.
533 */
534
535#define SWAP_BYTE(X)    do { (void) (X); } while (0)
536#define SWAP_IDENT(X)   do { (void) (X); } while (0)
537#define SWAP_HALF(X)    do {                                            \
538                uint16_t _x = (uint16_t) (X);                           \
539                uint16_t _t = _x & 0xFF;                                \
540                _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
541                (X) = _t;                                               \
542        } while (0)
543#define SWAP_WORD(X)    do {                                            \
544                uint32_t _x = (uint32_t) (X);                           \
545                uint32_t _t = _x & 0xFF;                                \
546                _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
547                _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
548                _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
549                (X) = _t;                                               \
550        } while (0)
551#define SWAP_ADDR32(X)  SWAP_WORD(X)
552#define SWAP_OFF32(X)   SWAP_WORD(X)
553#define SWAP_SWORD(X)   SWAP_WORD(X)
554#define SWAP_WORD64(X)  do {                                            \
555                uint64_t _x = (uint64_t) (X);                           \
556                uint64_t _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;                    \
563                _t <<= 8; _x >>= 8; _t |= _x & 0xFF;                    \
564                (X) = _t;                                               \
565        } while (0)
566#define SWAP_ADDR64(X)  SWAP_WORD64(X)
567#define SWAP_LWORD(X)   SWAP_WORD64(X)
568#define SWAP_OFF64(X)   SWAP_WORD64(X)
569#define SWAP_SXWORD(X)  SWAP_WORD64(X)
570#define SWAP_XWORD(X)   SWAP_WORD64(X)
571
572/*
573 * C macros to write out various integral values.
574 *
575 * Note:
576 * - The destination pointer could be unaligned.
577 * - Values are written out in native byte order.
578 * - The destination pointer is incremented after the write.
579 */
580#define WRITE_BYTE(P,X) do {                                            \
581                char *const _p = (char *) (P);  \
582                _p[0]           = (char) (X);                   \
583                (P)             = _p + 1;                               \
584        } while (0)
585#define WRITE_HALF(P,X) do {                                            \
586                uint16_t _t     = (X);                                  \
587                char *const _p  = (char *) (P); \
588                const char *const _q = (char *) &_t;    \
589                _p[0]           = _q[0];                                \
590                _p[1]           = _q[1];                                \
591                (P)             = _p + 2;                               \
592        } while (0)
593#define WRITE_WORD(P,X) do {                                            \
594                uint32_t _t     = (X);                                  \
595                char *const _p  = (char *) (P); \
596                const char *const _q = (char *) &_t;    \
597                _p[0]           = _q[0];                                \
598                _p[1]           = _q[1];                                \
599                _p[2]           = _q[2];                                \
600                _p[3]           = _q[3];                                \
601                (P)             = _p + 4;                               \
602        } while (0)
603#define WRITE_ADDR32(P,X)       WRITE_WORD(P,X)
604#define WRITE_OFF32(P,X)        WRITE_WORD(P,X)
605#define WRITE_SWORD(P,X)        WRITE_WORD(P,X)
606#define WRITE_WORD64(P,X)       do {                                    \
607                uint64_t _t     = (X);                                  \
608                char *const _p  = (char *) (P); \
609                const char *const _q = (char *) &_t;    \
610                _p[0]           = _q[0];                                \
611                _p[1]           = _q[1];                                \
612                _p[2]           = _q[2];                                \
613                _p[3]           = _q[3];                                \
614                _p[4]           = _q[4];                                \
615                _p[5]           = _q[5];                                \
616                _p[6]           = _q[6];                                \
617                _p[7]           = _q[7];                                \
618                (P)             = _p + 8;                               \
619        } while (0)
620#define WRITE_ADDR64(P,X)       WRITE_WORD64(P,X)
621#define WRITE_LWORD(P,X)        WRITE_WORD64(P,X)
622#define WRITE_OFF64(P,X)        WRITE_WORD64(P,X)
623#define WRITE_SXWORD(P,X)       WRITE_WORD64(P,X)
624#define WRITE_XWORD(P,X)        WRITE_WORD64(P,X)
625#define WRITE_IDENT(P,X)        do {                                    \
626                (void) memcpy((P), (X), sizeof((X)));                   \
627                (P)             = (P) + EI_NIDENT;                      \
628        } while (0)
629
630/*
631 * C macros to read in various integral values.
632 *
633 * Note:
634 * - The source pointer could be unaligned.
635 * - Values are read in native byte order.
636 * - The source pointer is incremented appropriately.
637 */
638
639#define READ_BYTE(P,X)  do {                                            \
640                const char *const _p =                          \
641                        (const char *) (P);                     \
642                (X)             = _p[0];                                \
643                (P)             = (P) + 1;                              \
644        } while (0)
645#define READ_HALF(P,X)  do {                                            \
646                uint16_t _t;                                            \
647                char *const _q = (char *) &_t;  \
648                const char *const _p =                          \
649                        (const char *) (P);                     \
650                _q[0]           = _p[0];                                \
651                _q[1]           = _p[1];                                \
652                (P)             = (P) + 2;                              \
653                (X)             = _t;                                   \
654        } while (0)
655#define READ_WORD(P,X)  do {                                            \
656                uint32_t _t;                                            \
657                char *const _q = (char *) &_t;  \
658                const char *const _p =                          \
659                        (const char *) (P);                     \
660                _q[0]           = _p[0];                                \
661                _q[1]           = _p[1];                                \
662                _q[2]           = _p[2];                                \
663                _q[3]           = _p[3];                                \
664                (P)             = (P) + 4;                              \
665                (X)             = _t;                                   \
666        } while (0)
667#define READ_ADDR32(P,X)        READ_WORD(P,X)
668#define READ_OFF32(P,X)         READ_WORD(P,X)
669#define READ_SWORD(P,X)         READ_WORD(P,X)
670#define READ_WORD64(P,X)        do {                                    \
671                uint64_t _t;                                            \
672                char *const _q = (char *) &_t;  \
673                const char *const _p =                          \
674                        (const char *) (P);                     \
675                _q[0]           = _p[0];                                \
676                _q[1]           = _p[1];                                \
677                _q[2]           = _p[2];                                \
678                _q[3]           = _p[3];                                \
679                _q[4]           = _p[4];                                \
680                _q[5]           = _p[5];                                \
681                _q[6]           = _p[6];                                \
682                _q[7]           = _p[7];                                \
683                (P)             = (P) + 8;                              \
684                (X)             = _t;                                   \
685        } while (0)
686#define READ_ADDR64(P,X)        READ_WORD64(P,X)
687#define READ_LWORD(P,X)         READ_WORD64(P,X)
688#define READ_OFF64(P,X)         READ_WORD64(P,X)
689#define READ_SXWORD(P,X)        READ_WORD64(P,X)
690#define READ_XWORD(P,X)         READ_WORD64(P,X)
691#define READ_IDENT(P,X)         do {                                    \
692                (void) memcpy((X), (P), sizeof((X)));                   \
693                (P)             = (P) + EI_NIDENT;                      \
694        } while (0)
695
696#define ROUNDUP2(V,N)   (V) = ((((V) + (N) - 1)) & ~((N) - 1))
697
698/*[*/
699MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST)
700MAKE_VERSION_CONVERTERS(VDEF,Verdef,Verdaux,vd)
701MAKE_VERSION_CONVERTERS(VNEED,Verneed,Vernaux,vn)
702/*]*/
703
704/*
705 * Sections of type ELF_T_BYTE are never byteswapped, consequently a
706 * simple memcpy suffices for both directions of conversion.
707 */
708
709static int
710libelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count,
711    int byteswap)
712{
713        (void) byteswap;
714        if (dsz < count)
715                return (0);
716        if (dst != src)
717                (void) memcpy(dst, src, count);
718        return (1);
719}
720
721/*
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
724 * hash chain.
725 *
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
728 * bits wide.
729 *
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.
732 */
733
734static int
735libelf_cvt_GNUHASH32_tom(char *dst, size_t dsz, char *src, size_t srcsz,
736    int byteswap)
737{
738        return (libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t),
739                byteswap));
740}
741
742static int
743libelf_cvt_GNUHASH32_tof(char *dst, size_t dsz, char *src, size_t srcsz,
744    int byteswap)
745{
746        return (libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t),
747                byteswap));
748}
749
750static int
751libelf_cvt_GNUHASH64_tom(char *dst, size_t dsz, char *src, size_t srcsz,
752    int byteswap)
753{
754        size_t sz;
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;
759
760        sz = 4 * sizeof(uint32_t);      /* File header is 4 words long. */
761        if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz)
762                return (0);
763
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);
769
770        srcsz -= sz;
771
772        if (byteswap) {
773                SWAP_WORD(nbuckets);
774                SWAP_WORD(symndx);
775                SWAP_WORD(maskwords);
776                SWAP_WORD(shift2);
777        }
778
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))
782                return (0);
783
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;
789
790        dsz -= sizeof(Elf_GNU_Hash_Header);
791        dst += sizeof(Elf_GNU_Hash_Header);
792
793        bloom64 = (uint64_t *) (uintptr_t) dst;
794
795        /* Copy bloom filter data. */
796        for (n = 0; n < maskwords; n++) {
797                READ_XWORD(src, t64);
798                if (byteswap)
799                        SWAP_XWORD(t64);
800                bloom64[n] = t64;
801        }
802
803        /* The hash buckets follows the bloom filter. */
804        dst += maskwords * sizeof(uint64_t);
805        buckets = (uint32_t *) (uintptr_t) dst;
806
807        for (n = 0; n < nbuckets; n++) {
808                READ_WORD(src, t32);
809                if (byteswap)
810                        SWAP_WORD(t32);
811                buckets[n] = t32;
812        }
813
814        dst += nbuckets * sizeof(uint32_t);
815
816        /* The hash chain follows the hash buckets. */
817        dsz -= sz;
818        srcsz -= sz;
819
820        if (dsz < srcsz)        /* Destination lacks space. */
821                return (0);
822
823        nchains = srcsz / sizeof(uint32_t);
824        chains = (uint32_t *) (uintptr_t) dst;
825
826        for (n = 0; n < nchains; n++) {
827                READ_WORD(src, t32);
828                if (byteswap)
829                        SWAP_WORD(t32);
830                *chains++ = t32;
831        }
832
833        return (1);
834}
835
836static int
837libelf_cvt_GNUHASH64_tof(char *dst, size_t dsz, char *src, size_t srcsz,
838    int byteswap)
839{
840        uint32_t *s32;
841        size_t sz, hdrsz;
842        uint64_t *s64, t64;
843        Elf_GNU_Hash_Header *gh;
844        uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32;
845
846        hdrsz = 4 * sizeof(uint32_t);   /* Header is 4x32 bits. */
847        if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header))
848                return (0);
849
850        gh = (Elf_GNU_Hash_Header *) (uintptr_t) src;
851
852        t0 = nbuckets = gh->gh_nbuckets;
853        t1 = gh->gh_symndx;
854        t2 = maskwords = gh->gh_maskwords;
855        t3 = gh->gh_shift2;
856
857        src   += sizeof(Elf_GNU_Hash_Header);
858        srcsz -= sizeof(Elf_GNU_Hash_Header);
859        dsz   -= hdrsz;
860
861        sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords *
862            sizeof(uint64_t);
863
864        if (srcsz < sz || dsz < sz)
865                return (0);
866
867        /* Write out the header. */
868        if (byteswap) {
869                SWAP_WORD(t0);
870                SWAP_WORD(t1);
871                SWAP_WORD(t2);
872                SWAP_WORD(t3);
873        }
874
875        WRITE_WORD(dst, t0);
876        WRITE_WORD(dst, t1);
877        WRITE_WORD(dst, t2);
878        WRITE_WORD(dst, t3);
879
880        /* Copy the bloom filter and the hash table. */
881        s64 = (uint64_t *) (uintptr_t) src;
882        for (n = 0; n < maskwords; n++) {
883                t64 = *s64++;
884                if (byteswap)
885                        SWAP_XWORD(t64);
886                WRITE_WORD64(dst, t64);
887        }
888
889        s32 = (uint32_t *) s64;
890        for (n = 0; n < nbuckets; n++) {
891                t32 = *s32++;
892                if (byteswap)
893                        SWAP_WORD(t32);
894                WRITE_WORD(dst, t32);
895        }
896
897        srcsz -= sz;
898        dsz   -= sz;
899
900        /* Copy out the hash chains. */
901        if (dsz < srcsz)
902                return (0);
903
904        nchains = srcsz / sizeof(uint32_t);
905        for (n = 0; n < nchains; n++) {
906                t32 = *s32++;
907                if (byteswap)
908                        SWAP_WORD(t32);
909                WRITE_WORD(dst, t32);
910        }
911
912        return (1);
913}
914
915/*
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
918 * not the strings.
919 *
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.
922 */
923static int
924libelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count,
925    int byteswap)
926{
927        uint32_t namesz, descsz, type;
928        Elf_Note *en;
929        size_t sz, hdrsz;
930
931        if (dsz < count)        /* Destination buffer is too small. */
932                return (0);
933
934        hdrsz = 3 * sizeof(uint32_t);
935        if (count < hdrsz)              /* Source too small. */
936                return (0);
937
938        if (!byteswap) {
939                (void) memcpy(dst, src, count);
940                return (1);
941        }
942
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);
949
950                /* Translate. */
951                SWAP_WORD(namesz);
952                SWAP_WORD(descsz);
953                SWAP_WORD(type);
954
955                /* Copy out the translated note header. */
956                en = (Elf_Note *) (uintptr_t) dst;
957                en->n_namesz = namesz;
958                en->n_descsz = descsz;
959                en->n_type = type;
960
961                dsz -= sizeof(Elf_Note);
962                dst += sizeof(Elf_Note);
963                count -= hdrsz;
964
965                ROUNDUP2(namesz, 4);
966                ROUNDUP2(descsz, 4);
967
968                sz = namesz + descsz;
969
970                if (count < sz || dsz < sz)     /* Buffers are too small. */
971                        return (0);
972
973                (void) memcpy(dst, src, sz);
974
975                src += sz;
976                dst += sz;
977
978                count -= sz;
979                dsz -= sz;
980        }
981
982        return (1);
983}
984
985static int
986libelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count,
987    int byteswap)
988{
989        uint32_t namesz, descsz, type;
990        Elf_Note *en;
991        size_t sz;
992
993        if (dsz < count)
994                return (0);
995
996        if (!byteswap) {
997                (void) memcpy(dst, src, count);
998                return (1);
999        }
1000
1001        while (count > sizeof(Elf_Note)) {
1002
1003                en = (Elf_Note *) (uintptr_t) src;
1004                namesz = en->n_namesz;
1005                descsz = en->n_descsz;
1006                type = en->n_type;
1007
1008                SWAP_WORD(namesz);
1009                SWAP_WORD(descsz);
1010                SWAP_WORD(type);
1011
1012                WRITE_WORD(dst, namesz);
1013                WRITE_WORD(dst, descsz);
1014                WRITE_WORD(dst, type);
1015
1016                src += sizeof(Elf_Note);
1017
1018                ROUNDUP2(namesz, 4);
1019                ROUNDUP2(descsz, 4);
1020
1021                sz = namesz + descsz;
1022
1023                if (count < sz)
1024                        sz = count;
1025
1026                (void) memcpy(dst, src, sz);
1027
1028                src += sz;
1029                dst += sz;
1030                count -= sz;
1031        }
1032
1033        return (1);
1034}
1035
1036struct converters {
1037        int     (*tof32)(char *dst, size_t dsz, char *src, size_t cnt,
1038                    int byteswap);
1039        int     (*tom32)(char *dst, size_t dsz, char *src, size_t cnt,
1040                    int byteswap);
1041        int     (*tof64)(char *dst, size_t dsz, char *src, size_t cnt,
1042                    int byteswap);
1043        int     (*tom64)(char *dst, size_t dsz, char *src, size_t cnt,
1044                    int byteswap);
1045};
1046
1047
1048static struct converters cvt[ELF_T_NUM] = {
1049        /*[*/
1050CONVERTER_NAMES(ELF_TYPE_LIST)
1051        /*]*/
1052
1053        /*
1054         * Types that need hand-coded converters follow.
1055         */
1056
1057        [ELF_T_BYTE] = {
1058                .tof32 = libelf_cvt_BYTE_tox,
1059                .tom32 = libelf_cvt_BYTE_tox,
1060                .tof64 = libelf_cvt_BYTE_tox,
1061                .tom64 = libelf_cvt_BYTE_tox
1062        },
1063
1064        [ELF_T_NOTE] = {
1065                .tof32 = libelf_cvt_NOTE_tof,
1066                .tom32 = libelf_cvt_NOTE_tom,
1067                .tof64 = libelf_cvt_NOTE_tof,
1068                .tom64 = libelf_cvt_NOTE_tom
1069        }
1070};
1071
1072int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))
1073 (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap)
1074{
1075        assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
1076        assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
1077
1078        if (t >= ELF_T_NUM ||
1079            (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
1080            (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
1081                return (NULL);
1082
1083        return ((elfclass == ELFCLASS32) ?
1084            (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) :
1085            (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64));
1086}
Note: See TracBrowser for help on using the repository browser.