source: rtems-tools/rtemstoolkit/elftoolchain/libelf/elf_update.c @ 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.1 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/mman.h>
28
29#include <assert.h>
30#include <errno.h>
31#include <gelf.h>
32#include <libelf.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36
37#include "_libelf.h"
38
39LIBELF_VCSID("$Id$");
40
41/*
42 * Layout strategy:
43 *
44 * - Case 1: ELF_F_LAYOUT is asserted
45 *     In this case the application has full control over where the
46 *     section header table, program header table, and section data
47 *     will reside.   The library only perform error checks.
48 *
49 * - Case 2: ELF_F_LAYOUT is not asserted
50 *
51 *     The library will do the object layout using the following
52 *     ordering:
53 *     - The executable header is placed first, are required by the
54 *       ELF specification.
55 *     - The program header table is placed immediately following the
56 *       executable header.
57 *     - Section data, if any, is placed after the program header
58 *       table, aligned appropriately.
59 *     - The section header table, if needed, is placed last.
60 *
61 *     There are two sub-cases to be taken care of:
62 *
63 *     - Case 2a: e->e_cmd == ELF_C_READ or ELF_C_RDWR
64 *
65 *       In this sub-case, the underlying ELF object may already have
66 *       content in it, which the application may have modified.  The
67 *       library will retrieve content from the existing object as
68 *       needed.
69 *
70 *     - Case 2b: e->e_cmd == ELF_C_WRITE
71 *
72 *       The ELF object is being created afresh in this sub-case;
73 *       there is no pre-existing content in the underlying ELF
74 *       object.
75 */
76
77/*
78 * The types of extents in an ELF object.
79 */
80enum elf_extent {
81        ELF_EXTENT_EHDR,
82        ELF_EXTENT_PHDR,
83        ELF_EXTENT_SECTION,
84        ELF_EXTENT_SHDR
85};
86
87/*
88 * A extent descriptor, used when laying out an ELF object.
89 */
90struct _Elf_Extent {
91        SLIST_ENTRY(_Elf_Extent) ex_next;
92        uint64_t        ex_start; /* Start of the region. */
93        uint64_t        ex_size;  /* The size of the region. */
94        enum elf_extent ex_type;  /* Type of region. */
95        void            *ex_desc; /* Associated descriptor. */
96};
97
98SLIST_HEAD(_Elf_Extent_List, _Elf_Extent);
99
100/*
101 * Compute the extents of a section, by looking at the data
102 * descriptors associated with it.  The function returns 1
103 * if successful, or zero if an error was detected.
104 */
105static int
106_libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
107{
108        int ec;
109        size_t fsz, msz;
110        Elf_Data *d;
111        Elf32_Shdr *shdr32;
112        Elf64_Shdr *shdr64;
113        uint32_t sh_type;
114        uint64_t d_align;
115        unsigned int elftype;
116        uint64_t scn_size, scn_alignment;
117        uint64_t sh_align, sh_entsize, sh_offset, sh_size;
118
119        ec = e->e_class;
120
121        shdr32 = &s->s_shdr.s_shdr32;
122        shdr64 = &s->s_shdr.s_shdr64;
123        if (ec == ELFCLASS32) {
124                sh_type    = shdr32->sh_type;
125                sh_align   = (uint64_t) shdr32->sh_addralign;
126                sh_entsize = (uint64_t) shdr32->sh_entsize;
127                sh_offset  = (uint64_t) shdr32->sh_offset;
128                sh_size    = (uint64_t) shdr32->sh_size;
129        } else {
130                sh_type    = shdr64->sh_type;
131                sh_align   = shdr64->sh_addralign;
132                sh_entsize = shdr64->sh_entsize;
133                sh_offset  = shdr64->sh_offset;
134                sh_size    = shdr64->sh_size;
135        }
136
137        assert(sh_type != SHT_NULL && sh_type != SHT_NOBITS);
138
139        elftype = _libelf_xlate_shtype(sh_type);
140        if (elftype > ELF_T_LAST) {
141                LIBELF_SET_ERROR(SECTION, 0);
142                return (0);
143        }
144
145        if (sh_align == 0)
146                sh_align = _libelf_falign(elftype, ec);
147
148        /*
149         * Compute the section's size and alignment using the data
150         * descriptors associated with the section.
151         */
152        if (STAILQ_EMPTY(&s->s_data)) {
153                /*
154                 * The section's content (if any) has not been read in
155                 * yet.  If section is not dirty marked dirty, we can
156                 * reuse the values in the 'sh_size' and 'sh_offset'
157                 * fields of the section header.
158                 */
159                if ((s->s_flags & ELF_F_DIRTY) == 0) {
160                        /*
161                         * If the library is doing the layout, then we
162                         * compute the new start offset for the
163                         * section based on the current offset and the
164                         * section's alignment needs.
165                         *
166                         * If the application is doing the layout, we
167                         * can use the value in the 'sh_offset' field
168                         * in the section header directly.
169                         */
170                        if (e->e_flags & ELF_F_LAYOUT)
171                                goto updatedescriptor;
172                        else
173                                goto computeoffset;
174                }
175
176                /*
177                 * Otherwise, we need to bring in the section's data
178                 * from the underlying ELF object.
179                 */
180                if (e->e_cmd != ELF_C_WRITE && elf_getdata(s, NULL) == NULL)
181                        return (0);
182        }
183
184        /*
185         * Loop through the section's data descriptors.
186         */
187        scn_size = 0L;
188        scn_alignment = 0;
189        STAILQ_FOREACH(d, &s->s_data, d_next)  {
190
191                /*
192                 * The data buffer's type is known.
193                 */
194                if (d->d_type >= ELF_T_NUM) {
195                        LIBELF_SET_ERROR(DATA, 0);
196                        return (0);
197                }
198
199                /*
200                 * The data buffer's version is supported.
201                 */
202                if (d->d_version != e->e_version) {
203                        LIBELF_SET_ERROR(VERSION, 0);
204                        return (0);
205                }
206
207                /*
208                 * The buffer's alignment is non-zero and a power of
209                 * two.
210                 */
211                if ((d_align = d->d_align) == 0 ||
212                    (d_align & (d_align - 1))) {
213                        LIBELF_SET_ERROR(DATA, 0);
214                        return (0);
215                }
216
217                /*
218                 * The buffer's size should be a multiple of the
219                 * memory size of the underlying type.
220                 */
221                msz = _libelf_msize(d->d_type, ec, e->e_version);
222                if (d->d_size % msz) {
223                        LIBELF_SET_ERROR(DATA, 0);
224                        return (0);
225                }
226
227                /*
228                 * If the application is controlling layout, then the
229                 * d_offset field should be compatible with the
230                 * buffer's specified alignment.
231                 */
232                if ((e->e_flags & ELF_F_LAYOUT) &&
233                    (d->d_off & (d_align - 1))) {
234                        LIBELF_SET_ERROR(LAYOUT, 0);
235                        return (0);
236                }
237
238                /*
239                 * Compute the section's size.
240                 */
241                if (e->e_flags & ELF_F_LAYOUT) {
242                        if ((uint64_t) d->d_off + d->d_size > scn_size)
243                                scn_size = d->d_off + d->d_size;
244                } else {
245                        scn_size = roundup2(scn_size, d->d_align);
246                        d->d_off = scn_size;
247                        fsz = _libelf_fsize(d->d_type, ec, d->d_version,
248                            d->d_size / msz);
249                        scn_size += fsz;
250                }
251
252                /*
253                 * The section's alignment is the maximum alignment
254                 * needed for its data buffers.
255                 */
256                if (d_align > scn_alignment)
257                        scn_alignment = d_align;
258        }
259
260
261        /*
262         * If the application is requesting full control over the
263         * layout of the section, check the section's specified size,
264         * offsets and alignment for sanity.
265         */
266        if (e->e_flags & ELF_F_LAYOUT) {
267                if (scn_alignment > sh_align || sh_offset % sh_align ||
268                    sh_size < scn_size) {
269                        LIBELF_SET_ERROR(LAYOUT, 0);
270                        return (0);
271                }
272                goto updatedescriptor;
273        }
274
275        /*
276         * Otherwise, compute the values in the section header.
277         *
278         * The section alignment is the maximum alignment for any of
279         * its contained data descriptors.
280         */
281        if (scn_alignment > sh_align)
282                sh_align = scn_alignment;
283
284        /*
285         * If the section entry size is zero, try and fill in an
286         * appropriate entry size.  Per the elf(5) manual page
287         * sections without fixed-size entries should have their
288         * 'sh_entsize' field set to zero.
289         */
290        if (sh_entsize == 0 &&
291            (sh_entsize = _libelf_fsize(elftype, ec, e->e_version,
292                (size_t) 1)) == 1)
293                sh_entsize = 0;
294
295        sh_size = scn_size;
296
297computeoffset:
298        /*
299         * Compute the new offset for the section based on
300         * the section's alignment needs.
301         */
302        sh_offset = roundup(rc, sh_align);
303
304        /*
305         * Update the section header.
306         */
307        if (ec == ELFCLASS32) {
308                shdr32->sh_addralign = (uint32_t) sh_align;
309                shdr32->sh_entsize   = (uint32_t) sh_entsize;
310                shdr32->sh_offset    = (uint32_t) sh_offset;
311                shdr32->sh_size      = (uint32_t) sh_size;
312        } else {
313                shdr64->sh_addralign = sh_align;
314                shdr64->sh_entsize   = sh_entsize;
315                shdr64->sh_offset    = sh_offset;
316                shdr64->sh_size      = sh_size;
317        }
318
319updatedescriptor:
320        /*
321         * Update the section descriptor.
322         */
323        s->s_size = sh_size;
324        s->s_offset = sh_offset;
325
326        return (1);
327}
328
329/*
330 * Free a list of extent descriptors.
331 */
332
333static void
334_libelf_release_extents(struct _Elf_Extent_List *extents)
335{
336        struct _Elf_Extent *ex;
337
338        while ((ex = SLIST_FIRST(extents)) != NULL) {
339                SLIST_REMOVE_HEAD(extents, ex_next);
340                free(ex);
341        }
342}
343
344/*
345 * Check if an extent 's' defined by [start..start+size) is free.
346 * This routine assumes that the given extent list is sorted in order
347 * of ascending extent offsets.
348 */
349
350static int
351_libelf_extent_is_unused(struct _Elf_Extent_List *extents,
352    const uint64_t start, const uint64_t size, struct _Elf_Extent **prevt)
353{
354        uint64_t tmax, tmin;
355        struct _Elf_Extent *t, *pt;
356        const uint64_t smax = start + size;
357
358        /* First, look for overlaps with existing extents. */
359        pt = NULL;
360        SLIST_FOREACH(t, extents, ex_next) {
361                tmin = t->ex_start;
362                tmax = tmin + t->ex_size;
363
364                if (tmax <= start) {
365                        /*
366                         * 't' lies entirely before 's': ...| t |...| s |...
367                         */
368                        pt = t;
369                        continue;
370                } else if (smax <= tmin) {
371                        /*
372                         * 's' lies entirely before 't', and after 'pt':
373                         *      ...| pt |...| s |...| t |...
374                         */
375                        assert(pt == NULL ||
376                            pt->ex_start + pt->ex_size <= start);
377                        break;
378                } else
379                        /* 's' and 't' overlap. */
380                        return (0);
381        }
382
383        if (prevt)
384                *prevt = pt;
385        return (1);
386}
387
388/*
389 * Insert an extent into the list of extents.
390 */
391
392static int
393_libelf_insert_extent(struct _Elf_Extent_List *extents, int type,
394    uint64_t start, uint64_t size, void *desc)
395{
396        struct _Elf_Extent *ex, *prevt;
397
398        assert(type >= ELF_EXTENT_EHDR && type <= ELF_EXTENT_SHDR);
399
400        prevt = NULL;
401
402        /*
403         * If the requested range overlaps with an existing extent,
404         * signal an error.
405         */
406        if (!_libelf_extent_is_unused(extents, start, size, &prevt)) {
407                LIBELF_SET_ERROR(LAYOUT, 0);
408                return (0);
409        }
410
411        /* Allocate and fill in a new extent descriptor. */
412        if ((ex = malloc(sizeof(struct _Elf_Extent))) == NULL) {
413                LIBELF_SET_ERROR(RESOURCE, errno);
414                return (0);
415        }
416        ex->ex_start = start;
417        ex->ex_size = size;
418        ex->ex_desc = desc;
419        ex->ex_type = type;
420
421        /* Insert the region descriptor into the list. */
422        if (prevt)
423                SLIST_INSERT_AFTER(prevt, ex, ex_next);
424        else
425                SLIST_INSERT_HEAD(extents, ex, ex_next);
426        return (1);
427}
428
429/*
430 * Recompute section layout.
431 */
432
433static off_t
434_libelf_resync_sections(Elf *e, off_t rc, struct _Elf_Extent_List *extents)
435{
436        int ec;
437        Elf_Scn *s;
438        size_t sh_type;
439
440        ec = e->e_class;
441
442        /*
443         * Make a pass through sections, computing the extent of each
444         * section.
445         */
446        STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) {
447                if (ec == ELFCLASS32)
448                        sh_type = s->s_shdr.s_shdr32.sh_type;
449                else
450                        sh_type = s->s_shdr.s_shdr64.sh_type;
451
452                if (sh_type == SHT_NOBITS || sh_type == SHT_NULL)
453                        continue;
454
455                if (_libelf_compute_section_extents(e, s, rc) == 0)
456                        return ((off_t) -1);
457
458                if (s->s_size == 0)
459                        continue;
460
461                if (!_libelf_insert_extent(extents, ELF_EXTENT_SECTION,
462                    s->s_offset, s->s_size, s))
463                        return ((off_t) -1);
464
465                if ((size_t) rc < s->s_offset + s->s_size)
466                        rc = s->s_offset + s->s_size;
467        }
468
469        return (rc);
470}
471
472/*
473 * Recompute the layout of the ELF object and update the internal data
474 * structures associated with the ELF descriptor.
475 *
476 * Returns the size in bytes the ELF object would occupy in its file
477 * representation.
478 *
479 * After a successful call to this function, the following structures
480 * are updated:
481 *
482 * - The ELF header is updated.
483 * - All extents in the ELF object are sorted in order of ascending
484 *   addresses.  Sections have their section header table entries
485 *   updated.  An error is signalled if an overlap was detected among
486 *   extents.
487 * - Data descriptors associated with sections are checked for valid
488 *   types, offsets and alignment.
489 *
490 * After a resync_elf() successfully returns, the ELF descriptor is
491 * ready for being handed over to _libelf_write_elf().
492 */
493
494static off_t
495_libelf_resync_elf(Elf *e, struct _Elf_Extent_List *extents)
496{
497        int ec, eh_class, eh_type;
498        unsigned int eh_byteorder, eh_version;
499        size_t align, fsz;
500        size_t phnum, shnum;
501        off_t rc, phoff, shoff;
502        void *ehdr, *phdr;
503        Elf32_Ehdr *eh32;
504        Elf64_Ehdr *eh64;
505
506        rc = 0;
507
508        ec = e->e_class;
509
510        assert(ec == ELFCLASS32 || ec == ELFCLASS64);
511
512        /*
513         * Prepare the EHDR.
514         */
515        if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
516                return ((off_t) -1);
517
518        eh32 = ehdr;
519        eh64 = ehdr;
520
521        if (ec == ELFCLASS32) {
522                eh_byteorder = eh32->e_ident[EI_DATA];
523                eh_class     = eh32->e_ident[EI_CLASS];
524                phoff        = (uint64_t) eh32->e_phoff;
525                shoff        = (uint64_t) eh32->e_shoff;
526                eh_type      = eh32->e_type;
527                eh_version   = eh32->e_version;
528        } else {
529                eh_byteorder = eh64->e_ident[EI_DATA];
530                eh_class     = eh64->e_ident[EI_CLASS];
531                phoff        = eh64->e_phoff;
532                shoff        = eh64->e_shoff;
533                eh_type      = eh64->e_type;
534                eh_version   = eh64->e_version;
535        }
536
537        if (eh_version == EV_NONE)
538                eh_version = EV_CURRENT;
539
540        if (eh_version != e->e_version) {       /* always EV_CURRENT */
541                LIBELF_SET_ERROR(VERSION, 0);
542                return ((off_t) -1);
543        }
544
545        if (eh_class != e->e_class) {
546                LIBELF_SET_ERROR(CLASS, 0);
547                return ((off_t) -1);
548        }
549
550        if (e->e_cmd != ELF_C_WRITE && eh_byteorder != e->e_byteorder) {
551                LIBELF_SET_ERROR(HEADER, 0);
552                return ((off_t) -1);
553        }
554
555        shnum = e->e_u.e_elf.e_nscn;
556        phnum = e->e_u.e_elf.e_nphdr;
557
558        e->e_byteorder = eh_byteorder;
559
560#define INITIALIZE_EHDR(E,EC,V) do {                                    \
561                (E)->e_ident[EI_MAG0] = ELFMAG0;                        \
562                (E)->e_ident[EI_MAG1] = ELFMAG1;                        \
563                (E)->e_ident[EI_MAG2] = ELFMAG2;                        \
564                (E)->e_ident[EI_MAG3] = ELFMAG3;                        \
565                (E)->e_ident[EI_CLASS] = (EC);                          \
566                (E)->e_ident[EI_VERSION] = (V);                         \
567                (E)->e_ehsize = _libelf_fsize(ELF_T_EHDR, (EC), (V),    \
568                    (size_t) 1);                                        \
569                (E)->e_phentsize = (phnum == 0) ? 0 : _libelf_fsize(    \
570                    ELF_T_PHDR, (EC), (V), (size_t) 1);                 \
571                (E)->e_shentsize = _libelf_fsize(ELF_T_SHDR, (EC), (V), \
572                    (size_t) 1);                                        \
573        } while (0)
574
575        if (ec == ELFCLASS32)
576                INITIALIZE_EHDR(eh32, ec, eh_version);
577        else
578                INITIALIZE_EHDR(eh64, ec, eh_version);
579
580        (void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY);
581
582        rc += _libelf_fsize(ELF_T_EHDR, ec, eh_version, (size_t) 1);
583
584        if (!_libelf_insert_extent(extents, ELF_EXTENT_EHDR, 0, rc, ehdr))
585                return ((off_t) -1);
586
587        /*
588         * Compute the layout the program header table, if one is
589         * present.  The program header table needs to be aligned to a
590         * `natural' boundary.
591         */
592        if (phnum) {
593                fsz = _libelf_fsize(ELF_T_PHDR, ec, eh_version, phnum);
594                align = _libelf_falign(ELF_T_PHDR, ec);
595
596                if (e->e_flags & ELF_F_LAYOUT) {
597                        /*
598                         * Check offsets for sanity.
599                         */
600                        if (rc > phoff) {
601                                LIBELF_SET_ERROR(LAYOUT, 0);
602                                return ((off_t) -1);
603                        }
604
605                        if (phoff % align) {
606                                LIBELF_SET_ERROR(LAYOUT, 0);
607                                return ((off_t) -1);
608                        }
609
610                } else
611                        phoff = roundup(rc, align);
612
613                rc = phoff + fsz;
614
615                phdr = _libelf_getphdr(e, ec);
616
617                if (!_libelf_insert_extent(extents, ELF_EXTENT_PHDR, phoff,
618                        fsz, phdr))
619                        return ((off_t) -1);
620        } else
621                phoff = 0;
622
623        /*
624         * Compute the layout of the sections associated with the
625         * file.
626         */
627
628        if (e->e_cmd != ELF_C_WRITE &&
629            (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 &&
630            _libelf_load_section_headers(e, ehdr) == 0)
631                return ((off_t) -1);
632
633        if ((rc = _libelf_resync_sections(e, rc, extents)) < 0)
634                return ((off_t) -1);
635
636        /*
637         * Compute the space taken up by the section header table, if
638         * one is needed.
639         *
640         * If ELF_F_LAYOUT has been asserted, the application may have
641         * placed the section header table in between existing
642         * sections, so the net size of the file need not increase due
643         * to the presence of the section header table.
644         *
645         * If the library is responsible for laying out the object,
646         * the section header table is placed after section data.
647         */
648        if (shnum) {
649                fsz = _libelf_fsize(ELF_T_SHDR, ec, eh_version, shnum);
650                align = _libelf_falign(ELF_T_SHDR, ec);
651
652                if (e->e_flags & ELF_F_LAYOUT) {
653                        if (shoff % align) {
654                                LIBELF_SET_ERROR(LAYOUT, 0);
655                                return ((off_t) -1);
656                        }
657                } else
658                        shoff = roundup(rc, align);
659
660                if (shoff + fsz > (size_t) rc)
661                        rc = shoff + fsz;
662
663                if (!_libelf_insert_extent(extents, ELF_EXTENT_SHDR, shoff,
664                    fsz, NULL))
665                        return ((off_t) -1);
666        } else
667                shoff = 0;
668
669        /*
670         * Set the fields of the Executable Header that could potentially use
671         * extended numbering.
672         */
673        _libelf_setphnum(e, ehdr, ec, phnum);
674        _libelf_setshnum(e, ehdr, ec, shnum);
675
676        /*
677         * Update the `e_phoff' and `e_shoff' fields if the library is
678         * doing the layout.
679         */
680        if ((e->e_flags & ELF_F_LAYOUT) == 0) {
681                if (ec == ELFCLASS32) {
682                        eh32->e_phoff = (uint32_t) phoff;
683                        eh32->e_shoff = (uint32_t) shoff;
684                } else {
685                        eh64->e_phoff = (uint64_t) phoff;
686                        eh64->e_shoff = (uint64_t) shoff;
687                }
688        }
689
690        return (rc);
691}
692
693/*
694 * Write out the contents of an ELF section.
695 */
696
697static size_t
698_libelf_write_scn(Elf *e, char *nf, struct _Elf_Extent *ex)
699{
700        int ec;
701        size_t fsz, msz, nobjects, rc;
702        uint32_t sh_type;
703        uint64_t sh_off, sh_size;
704        int elftype;
705        Elf_Scn *s;
706        Elf_Data *d, dst;
707
708        assert(ex->ex_type == ELF_EXTENT_SECTION);
709
710        s = ex->ex_desc;
711        rc = ex->ex_start;
712
713        if ((ec = e->e_class) == ELFCLASS32) {
714                sh_type = s->s_shdr.s_shdr32.sh_type;
715                sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
716        } else {
717                sh_type = s->s_shdr.s_shdr64.sh_type;
718                sh_size = s->s_shdr.s_shdr64.sh_size;
719        }
720
721        /*
722         * Ignore sections that do not allocate space in the file.
723         */
724        if (sh_type == SHT_NOBITS || sh_type == SHT_NULL || sh_size == 0)
725                return (rc);
726
727        elftype = _libelf_xlate_shtype(sh_type);
728        assert(elftype >= ELF_T_FIRST && elftype <= ELF_T_LAST);
729
730        sh_off = s->s_offset;
731        assert(sh_off % _libelf_falign(elftype, ec) == 0);
732
733        /*
734         * If the section has a `rawdata' descriptor, and the section
735         * contents have not been modified, use its contents directly.
736         * The `s_rawoff' member contains the offset into the original
737         * file, while `s_offset' contains its new location in the
738         * destination.
739         */
740
741        if (STAILQ_EMPTY(&s->s_data)) {
742
743                if ((d = elf_rawdata(s, NULL)) == NULL)
744                        return ((off_t) -1);
745
746                STAILQ_FOREACH(d, &s->s_rawdata, d_next) {
747                        if ((uint64_t) rc < sh_off + d->d_off)
748                                (void) memset(nf + rc,
749                                    LIBELF_PRIVATE(fillchar), sh_off +
750                                    d->d_off - rc);
751                        rc = sh_off + d->d_off;
752
753                        assert(d->d_buf != NULL);
754                        assert(d->d_type == ELF_T_BYTE);
755                        assert(d->d_version == e->e_version);
756
757                        (void) memcpy(nf + rc,
758                            e->e_rawfile + s->s_rawoff + d->d_off, d->d_size);
759
760                        rc += d->d_size;
761                }
762
763                return (rc);
764        }
765
766        /*
767         * Iterate over the set of data descriptors for this section.
768         * The prior call to _libelf_resync_elf() would have setup the
769         * descriptors for this step.
770         */
771
772        dst.d_version = e->e_version;
773
774        STAILQ_FOREACH(d, &s->s_data, d_next) {
775
776                msz = _libelf_msize(d->d_type, ec, e->e_version);
777
778                if ((uint64_t) rc < sh_off + d->d_off)
779                        (void) memset(nf + rc,
780                            LIBELF_PRIVATE(fillchar), sh_off + d->d_off - rc);
781
782                rc = sh_off + d->d_off;
783
784                assert(d->d_buf != NULL);
785                assert(d->d_version == e->e_version);
786                assert(d->d_size % msz == 0);
787
788                nobjects = d->d_size / msz;
789
790                fsz = _libelf_fsize(d->d_type, ec, e->e_version, nobjects);
791
792                dst.d_buf    = nf + rc;
793                dst.d_size   = fsz;
794
795                if (_libelf_xlate(&dst, d, e->e_byteorder, ec, ELF_TOFILE) ==
796                    NULL)
797                        return ((off_t) -1);
798
799                rc += fsz;
800        }
801
802        return ((off_t) rc);
803}
804
805/*
806 * Write out an ELF Executable Header.
807 */
808
809static off_t
810_libelf_write_ehdr(Elf *e, char *nf, struct _Elf_Extent *ex)
811{
812        int ec;
813        void *ehdr;
814        size_t fsz, msz;
815        Elf_Data dst, src;
816
817        assert(ex->ex_type == ELF_EXTENT_EHDR);
818        assert(ex->ex_start == 0); /* Ehdr always comes first. */
819
820        ec = e->e_class;
821
822        ehdr = _libelf_ehdr(e, ec, 0);
823        assert(ehdr != NULL);
824
825        fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
826        msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version);
827
828        (void) memset(&dst, 0, sizeof(dst));
829        (void) memset(&src, 0, sizeof(src));
830
831        src.d_buf     = ehdr;
832        src.d_size    = msz;
833        src.d_type    = ELF_T_EHDR;
834        src.d_version = dst.d_version = e->e_version;
835
836        dst.d_buf     = nf;
837        dst.d_size    = fsz;
838
839        if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) ==
840            NULL)
841                return ((off_t) -1);
842
843        return ((off_t) fsz);
844}
845
846/*
847 * Write out an ELF program header table.
848 */
849
850static off_t
851_libelf_write_phdr(Elf *e, char *nf, struct _Elf_Extent *ex)
852{
853        int ec;
854        void *ehdr;
855        Elf32_Ehdr *eh32;
856        Elf64_Ehdr *eh64;
857        Elf_Data dst, src;
858        size_t fsz, phnum;
859        uint64_t phoff;
860
861        assert(ex->ex_type == ELF_EXTENT_PHDR);
862
863        ec = e->e_class;
864        ehdr = _libelf_ehdr(e, ec, 0);
865        phnum = e->e_u.e_elf.e_nphdr;
866
867        assert(phnum > 0);
868
869        if (ec == ELFCLASS32) {
870                eh32 = (Elf32_Ehdr *) ehdr;
871                phoff = (uint64_t) eh32->e_phoff;
872        } else {
873                eh64 = (Elf64_Ehdr *) ehdr;
874                phoff = eh64->e_phoff;
875        }
876
877        assert(phoff > 0);
878        assert(ex->ex_start == phoff);
879        assert(phoff % _libelf_falign(ELF_T_PHDR, ec) == 0);
880
881        (void) memset(&dst, 0, sizeof(dst));
882        (void) memset(&src, 0, sizeof(src));
883
884        fsz = _libelf_fsize(ELF_T_PHDR, ec, e->e_version, phnum);
885        assert(fsz > 0);
886
887        src.d_buf = _libelf_getphdr(e, ec);
888        src.d_version = dst.d_version = e->e_version;
889        src.d_type = ELF_T_PHDR;
890        src.d_size = phnum * _libelf_msize(ELF_T_PHDR, ec,
891            e->e_version);
892
893        dst.d_size = fsz;
894        dst.d_buf = nf + ex->ex_start;
895
896        if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) ==
897            NULL)
898                return ((off_t) -1);
899
900        return (phoff + fsz);
901}
902
903/*
904 * Write out an ELF section header table.
905 */
906
907static off_t
908_libelf_write_shdr(Elf *e, char *nf, struct _Elf_Extent *ex)
909{
910        int ec;
911        void *ehdr;
912        Elf_Scn *scn;
913        uint64_t shoff;
914        Elf32_Ehdr *eh32;
915        Elf64_Ehdr *eh64;
916        size_t fsz, nscn;
917        Elf_Data dst, src;
918
919        assert(ex->ex_type == ELF_EXTENT_SHDR);
920
921        ec = e->e_class;
922        ehdr = _libelf_ehdr(e, ec, 0);
923        nscn = e->e_u.e_elf.e_nscn;
924
925        if (ec == ELFCLASS32) {
926                eh32 = (Elf32_Ehdr *) ehdr;
927                shoff = (uint64_t) eh32->e_shoff;
928        } else {
929                eh64 = (Elf64_Ehdr *) ehdr;
930                shoff = eh64->e_shoff;
931        }
932
933        assert(nscn > 0);
934        assert(shoff % _libelf_falign(ELF_T_SHDR, ec) == 0);
935        assert(ex->ex_start == shoff);
936
937        (void) memset(&dst, 0, sizeof(dst));
938        (void) memset(&src, 0, sizeof(src));
939
940        src.d_type = ELF_T_SHDR;
941        src.d_size = _libelf_msize(ELF_T_SHDR, ec, e->e_version);
942        src.d_version = dst.d_version = e->e_version;
943
944        fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
945
946        STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) {
947                if (ec == ELFCLASS32)
948                        src.d_buf = &scn->s_shdr.s_shdr32;
949                else
950                        src.d_buf = &scn->s_shdr.s_shdr64;
951
952                dst.d_size = fsz;
953                dst.d_buf = nf + ex->ex_start + scn->s_ndx * fsz;
954
955                if (_libelf_xlate(&dst, &src, e->e_byteorder, ec,
956                    ELF_TOFILE) == NULL)
957                        return ((off_t) -1);
958        }
959
960        return (ex->ex_start + nscn * fsz);
961}
962
963/*
964 * Write out the file image.
965 *
966 * The original file could have been mapped in with an ELF_C_RDWR
967 * command and the application could have added new content or
968 * re-arranged its sections before calling elf_update().  Consequently
969 * its not safe to work `in place' on the original file.  So we
970 * malloc() the required space for the updated ELF object and build
971 * the object there and write it out to the underlying file at the
972 * end.  Note that the application may have opened the underlying file
973 * in ELF_C_RDWR and only retrieved/modified a few sections.  We take
974 * care to avoid translating file sections unnecessarily.
975 *
976 * Gaps in the coverage of the file by the file's sections will be
977 * filled with the fill character set by elf_fill(3).
978 */
979
980static off_t
981_libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
982{
983        off_t nrc, rc;
984        char *newfile;
985        Elf_Scn *scn, *tscn;
986        struct _Elf_Extent *ex;
987
988        assert(e->e_kind == ELF_K_ELF);
989        assert(e->e_cmd != ELF_C_READ);
990        assert(e->e_fd >= 0);
991
992        if ((newfile = malloc((size_t) newsize)) == NULL) {
993                LIBELF_SET_ERROR(RESOURCE, errno);
994                return ((off_t) -1);
995        }
996
997        nrc = rc = 0;
998        SLIST_FOREACH(ex, extents, ex_next) {
999
1000                /* Fill inter-extent gaps. */
1001                if (ex->ex_start > (size_t) rc)
1002                        (void) memset(newfile + rc, LIBELF_PRIVATE(fillchar),
1003                            ex->ex_start - rc);
1004
1005                switch (ex->ex_type) {
1006                case ELF_EXTENT_EHDR:
1007                        if ((nrc = _libelf_write_ehdr(e, newfile, ex)) < 0)
1008                                goto error;
1009                        break;
1010
1011                case ELF_EXTENT_PHDR:
1012                        if ((nrc = _libelf_write_phdr(e, newfile, ex)) < 0)
1013                                goto error;
1014                        break;
1015
1016                case ELF_EXTENT_SECTION:
1017                        if ((nrc = _libelf_write_scn(e, newfile, ex)) < 0)
1018                                goto error;
1019                        break;
1020
1021                case ELF_EXTENT_SHDR:
1022                        if ((nrc = _libelf_write_shdr(e, newfile, ex)) < 0)
1023                                goto error;
1024                        break;
1025
1026                default:
1027                        assert(0);
1028                        break;
1029                }
1030
1031                assert(ex->ex_start + ex->ex_size == (size_t) nrc);
1032                assert(rc < nrc);
1033
1034                rc = nrc;
1035        }
1036
1037        assert(rc == newsize);
1038
1039        /*
1040         * Write out the constructed contents and remap the file in
1041         * read-only.
1042         */
1043
1044        if (e->e_rawfile && munmap(e->e_rawfile, e->e_rawsize) < 0) {
1045                LIBELF_SET_ERROR(IO, errno);
1046                goto error;
1047        }
1048
1049        if (write(e->e_fd, newfile, (size_t) newsize) != newsize ||
1050            lseek(e->e_fd, (off_t) 0, SEEK_SET) < 0) {
1051                LIBELF_SET_ERROR(IO, errno);
1052                goto error;
1053        }
1054
1055        if (e->e_cmd != ELF_C_WRITE) {
1056
1057                if (e->e_rawsize > (size_t) newsize &&
1058                    ftruncate(e->e_fd, newsize) < 0) {
1059                        LIBELF_SET_ERROR(IO, errno);
1060                        goto error;
1061                }
1062
1063                if ((e->e_rawfile = mmap(NULL, (size_t) newsize, PROT_READ,
1064                    MAP_PRIVATE, e->e_fd, (off_t) 0)) == MAP_FAILED) {
1065                        LIBELF_SET_ERROR(IO, errno);
1066                        goto error;
1067                }
1068                e->e_rawsize = newsize;
1069        }
1070
1071        /*
1072         * Reset flags, remove existing section descriptors and
1073         * {E,P}HDR pointers so that a subsequent elf_get{e,p}hdr()
1074         * and elf_getscn() will function correctly.
1075         */
1076
1077        e->e_flags &= ~ELF_F_DIRTY;
1078
1079        STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn)
1080                _libelf_release_scn(scn);
1081
1082        if (e->e_class == ELFCLASS32) {
1083                free(e->e_u.e_elf.e_ehdr.e_ehdr32);
1084                if (e->e_u.e_elf.e_phdr.e_phdr32)
1085                        free(e->e_u.e_elf.e_phdr.e_phdr32);
1086
1087                e->e_u.e_elf.e_ehdr.e_ehdr32 = NULL;
1088                e->e_u.e_elf.e_phdr.e_phdr32 = NULL;
1089        } else {
1090                free(e->e_u.e_elf.e_ehdr.e_ehdr64);
1091                if (e->e_u.e_elf.e_phdr.e_phdr64)
1092                        free(e->e_u.e_elf.e_phdr.e_phdr64);
1093
1094                e->e_u.e_elf.e_ehdr.e_ehdr64 = NULL;
1095                e->e_u.e_elf.e_phdr.e_phdr64 = NULL;
1096        }
1097
1098        free(newfile);
1099
1100        return (rc);
1101
1102 error:
1103        free(newfile);
1104
1105        return ((off_t) -1);
1106}
1107
1108/*
1109 * Update an ELF object.
1110 */
1111
1112off_t
1113elf_update(Elf *e, Elf_Cmd c)
1114{
1115        int ec;
1116        off_t rc;
1117        struct _Elf_Extent_List extents;
1118
1119        rc = (off_t) -1;
1120
1121        if (e == NULL || e->e_kind != ELF_K_ELF ||
1122            (c != ELF_C_NULL && c != ELF_C_WRITE)) {
1123                LIBELF_SET_ERROR(ARGUMENT, 0);
1124                return (rc);
1125        }
1126
1127        if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) {
1128                LIBELF_SET_ERROR(CLASS, 0);
1129                return (rc);
1130        }
1131
1132        if (e->e_version == EV_NONE)
1133                e->e_version = EV_CURRENT;
1134
1135        if (c == ELF_C_WRITE && e->e_cmd == ELF_C_READ) {
1136                LIBELF_SET_ERROR(MODE, 0);
1137                return (rc);
1138        }
1139
1140        SLIST_INIT(&extents);
1141
1142        if ((rc = _libelf_resync_elf(e, &extents)) < 0)
1143                goto done;
1144
1145        if (c == ELF_C_NULL)
1146                goto done;
1147
1148        if (e->e_fd < 0) {
1149                rc = (off_t) -1;
1150                LIBELF_SET_ERROR(SEQUENCE, 0);
1151                goto done;
1152        }
1153
1154        return (_libelf_write_elf(e, rc, &extents));
1155
1156done:
1157        _libelf_release_extents(&extents);
1158        return (rc);
1159}
Note: See TracBrowser for help on using the repository browser.