1 /* $NetBSD: elf_update.c,v 1.2 2009/12/19 05:55:37 thorpej Exp $ */
4 * Copyright (c) 2006-2008 Joseph Koshy
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 /* __FBSDID("$FreeBSD: src/lib/libelf/elf_update.c,v 1.5.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $"); */
33 #include <sys/param.h>
46 * Update the internal data structures associated with an ELF object.
47 * Returns the size in bytes the ELF object would occupy in its file
50 * After a successful call to this function, the following structures
53 * - The ELF header is updated.
54 * - All sections are sorted in order of ascending addresses and their
55 * section header table entries updated. An error is signalled
56 * if an overlap was detected among sections.
57 * - All data descriptors associated with a section are sorted in order
58 * of ascending addresses. Overlaps, if detected, are signalled as
59 * errors. Other sanity checks for alignments, section types etc. are
62 * After a resync_elf() successfully returns, the ELF descriptor is
63 * ready for being handed over to _libelf_write_elf().
69 * XXX: how do we handle 'flags'.
73 * Compute the extents of a section, by looking at the data
74 * descriptors associated with it. The function returns zero if an
75 * error was detected. `*rc' holds the maximum file extent seen so
79 _libelf_compute_section_extents(Elf
*e
, Elf_Scn
*s
, off_t
*rc
)
86 uint64_t sh_align
, sh_entsize
, sh_offset
, sh_size
;
87 uint64_t scn_size
, scn_alignment
;
90 * We need to recompute library private data structures if one
91 * or more of the following is true:
92 * - The underlying Shdr structure has been marked `dirty'. Significant
93 * fields include: `sh_offset', `sh_type', `sh_size', `sh_addralign'.
94 * - The Elf_Data structures part of this section have been marked
95 * `dirty'. Affected members include `d_align', `d_offset', `d_type',
97 * - The section as a whole is `dirty', e.g., it has been allocated
98 * using elf_newscn(), or if a new Elf_Data structure was added using
101 * Each of these conditions would result in the ELF_F_DIRTY bit being
102 * set on the section descriptor's `s_flags' field.
107 if (ec
== ELFCLASS32
) {
108 sh_type
= s
->s_shdr
.s_shdr32
.sh_type
;
109 sh_align
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_addralign
;
110 sh_entsize
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_entsize
;
111 sh_offset
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_offset
;
112 sh_size
= (uint64_t) s
->s_shdr
.s_shdr32
.sh_size
;
114 sh_type
= s
->s_shdr
.s_shdr64
.sh_type
;
115 sh_align
= s
->s_shdr
.s_shdr64
.sh_addralign
;
116 sh_entsize
= s
->s_shdr
.s_shdr64
.sh_entsize
;
117 sh_offset
= s
->s_shdr
.s_shdr64
.sh_offset
;
118 sh_size
= s
->s_shdr
.s_shdr64
.sh_size
;
121 if (sh_type
== SHT_NULL
|| sh_type
== SHT_NOBITS
)
124 if ((s
->s_flags
& ELF_F_DIRTY
) == 0) {
125 if ((size_t) *rc
< sh_offset
+ sh_size
)
126 *rc
= sh_offset
+ sh_size
;
130 elftype
= _libelf_xlate_shtype(sh_type
);
131 if (elftype
> ELF_T_LAST
) {
132 LIBELF_SET_ERROR(SECTION
, 0);
137 * Compute the extent of the data descriptors associated with
142 sh_align
= _libelf_falign(elftype
, ec
);
144 /* Compute the section alignment. */
145 STAILQ_FOREACH(d
, &s
->s_data
, d_next
) {
146 if (d
->d_type
!= elftype
) {
147 LIBELF_SET_ERROR(DATA
, 0);
150 if (d
->d_version
!= e
->e_version
) {
151 LIBELF_SET_ERROR(VERSION
, 0);
154 if ((d_align
= d
->d_align
) % sh_align
) {
155 LIBELF_SET_ERROR(LAYOUT
, 0);
158 if (d_align
== 0 || (d_align
& (d_align
- 1))) {
159 LIBELF_SET_ERROR(DATA
, 0);
162 if (d_align
> scn_alignment
)
163 scn_alignment
= d_align
;
168 STAILQ_FOREACH_SAFE(d
, &s
->s_data
, d_next
, td
) {
169 if (e
->e_flags
& ELF_F_LAYOUT
) {
170 if ((uint64_t) d
->d_off
+ d
->d_size
> scn_size
)
171 scn_size
= d
->d_off
+ d
->d_size
;
173 scn_size
= roundup2(scn_size
, scn_alignment
);
175 scn_size
+= d
->d_size
;
180 * If the application is requesting full control over the layout
181 * of the section, check its values for sanity.
183 if (e
->e_flags
& ELF_F_LAYOUT
) {
184 if (scn_alignment
> sh_align
|| sh_offset
% sh_align
||
185 sh_size
< scn_size
) {
186 LIBELF_SET_ERROR(LAYOUT
, 0);
191 * Otherwise compute the values in the section header.
194 if (scn_alignment
> sh_align
)
195 sh_align
= scn_alignment
;
198 * If the section entry size is zero, try and fill in an
199 * appropriate entry size. Per the elf(5) manual page
200 * sections without fixed-size entries should have their
201 * 'sh_entsize' field set to zero.
203 if (sh_entsize
== 0 &&
204 (sh_entsize
= _libelf_fsize(elftype
, ec
, e
->e_version
,
209 sh_offset
= roundup(*rc
, sh_align
);
211 if (ec
== ELFCLASS32
) {
212 s
->s_shdr
.s_shdr32
.sh_addralign
= (uint32_t) sh_align
;
213 s
->s_shdr
.s_shdr32
.sh_entsize
= (uint32_t) sh_entsize
;
214 s
->s_shdr
.s_shdr32
.sh_offset
= (uint32_t) sh_offset
;
215 s
->s_shdr
.s_shdr32
.sh_size
= (uint32_t) sh_size
;
217 s
->s_shdr
.s_shdr64
.sh_addralign
= sh_align
;
218 s
->s_shdr
.s_shdr64
.sh_entsize
= sh_entsize
;
219 s
->s_shdr
.s_shdr64
.sh_offset
= sh_offset
;
220 s
->s_shdr
.s_shdr64
.sh_size
= sh_size
;
224 if ((size_t) *rc
< sh_offset
+ sh_size
)
225 *rc
= sh_offset
+ sh_size
;
228 s
->s_offset
= sh_offset
;
234 * Insert a section in ascending order in the list
238 _libelf_insert_section(Elf
*e
, Elf_Scn
*s
)
241 uint64_t smax
, smin
, tmax
, tmin
;
244 smax
= smin
+ s
->s_size
;
247 STAILQ_FOREACH(t
, &e
->e_u
.e_elf
.e_scn
, s_next
) {
249 tmax
= tmin
+ t
->s_size
;
253 * 't' lies entirely before 's': ...| t |...| s |...
257 } else if (smax
<= tmin
)
259 * 's' lies entirely before 't', and after 'prevt':
260 * ...| prevt |...| s |...| t |...
263 else { /* 's' and 't' overlap. */
264 LIBELF_SET_ERROR(LAYOUT
, 0);
270 STAILQ_INSERT_AFTER(&e
->e_u
.e_elf
.e_scn
, prevt
, s
, s_next
);
272 STAILQ_INSERT_HEAD(&e
->e_u
.e_elf
.e_scn
, s
, s_next
);
277 _libelf_resync_sections(Elf
*e
, off_t rc
)
281 size_t sh_type
, shdr_start
, shdr_end
;
287 * Make a pass through sections, computing the extent of each
288 * section. Order in increasing order of addresses.
292 STAILQ_FOREACH(s
, &e
->e_u
.e_elf
.e_scn
, s_next
)
293 if (_libelf_compute_section_extents(e
, s
, &nrc
) == 0)
296 STAILQ_FOREACH_SAFE(s
, &e
->e_u
.e_elf
.e_scn
, s_next
, ts
) {
297 if (ec
== ELFCLASS32
)
298 sh_type
= s
->s_shdr
.s_shdr32
.sh_type
;
300 sh_type
= s
->s_shdr
.s_shdr64
.sh_type
;
302 /* XXX Do we need the 'size' field of an SHT_NOBITS section */
303 if (sh_type
== SHT_NOBITS
|| sh_type
== SHT_NULL
)
306 if (s
->s_offset
< (uint64_t) rc
) {
307 if (s
->s_offset
+ s
->s_size
< (uint64_t) rc
) {
309 * Try insert this section in the
310 * correct place in the list,
311 * detecting overlaps if any.
313 STAILQ_REMOVE(&e
->e_u
.e_elf
.e_scn
, s
, _Elf_Scn
,
315 if (_libelf_insert_section(e
, s
) == 0)
318 LIBELF_SET_ERROR(LAYOUT
, 0);
322 rc
= s
->s_offset
+ s
->s_size
;
326 * If the application is controlling file layout, check for an
327 * overlap between this section's extents and the SHDR table.
329 if (e
->e_flags
& ELF_F_LAYOUT
) {
331 if (e
->e_class
== ELFCLASS32
)
332 shdr_start
= e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
->e_shoff
;
334 shdr_start
= e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
->e_shoff
;
336 shdr_end
= shdr_start
+ _libelf_fsize(ELF_T_SHDR
, e
->e_class
,
337 e
->e_version
, e
->e_u
.e_elf
.e_nscn
);
339 STAILQ_FOREACH(s
, &e
->e_u
.e_elf
.e_scn
, s_next
) {
340 if (s
->s_offset
>= shdr_end
||
341 s
->s_offset
+ s
->s_size
<= shdr_start
)
343 LIBELF_SET_ERROR(LAYOUT
, 0);
354 _libelf_resync_elf(Elf
*e
)
356 int ec
, eh_class
, eh_type
;
357 unsigned int eh_byteorder
, eh_version
;
360 off_t rc
, phoff
, shoff
;
369 assert(ec
== ELFCLASS32
|| ec
== ELFCLASS64
);
374 if ((ehdr
= _libelf_ehdr(e
, ec
, 0)) == NULL
)
380 if (ec
== ELFCLASS32
) {
381 eh_byteorder
= eh32
->e_ident
[EI_DATA
];
382 eh_class
= eh32
->e_ident
[EI_CLASS
];
383 phoff
= (uint64_t) eh32
->e_phoff
;
384 shoff
= (uint64_t) eh32
->e_shoff
;
385 eh_type
= eh32
->e_type
;
386 eh_version
= eh32
->e_version
;
388 eh_byteorder
= eh64
->e_ident
[EI_DATA
];
389 eh_class
= eh64
->e_ident
[EI_CLASS
];
390 phoff
= eh64
->e_phoff
;
391 shoff
= eh64
->e_shoff
;
392 eh_type
= eh64
->e_type
;
393 eh_version
= eh64
->e_version
;
396 if (eh_version
== EV_NONE
)
397 eh_version
= EV_CURRENT
;
399 if (eh_version
!= e
->e_version
) { /* always EV_CURRENT */
400 LIBELF_SET_ERROR(VERSION
, 0);
404 if (eh_class
!= e
->e_class
) {
405 LIBELF_SET_ERROR(CLASS
, 0);
409 if (e
->e_cmd
!= ELF_C_WRITE
&& eh_byteorder
!= e
->e_byteorder
) {
410 LIBELF_SET_ERROR(HEADER
, 0);
414 shnum
= e
->e_u
.e_elf
.e_nscn
;
415 phnum
= e
->e_u
.e_elf
.e_nphdr
;
417 e
->e_byteorder
= eh_byteorder
;
419 #define INITIALIZE_EHDR(E,EC,V) do { \
420 (E)->e_ident[EI_MAG0] = ELFMAG0; \
421 (E)->e_ident[EI_MAG1] = ELFMAG1; \
422 (E)->e_ident[EI_MAG2] = ELFMAG2; \
423 (E)->e_ident[EI_MAG3] = ELFMAG3; \
424 (E)->e_ident[EI_CLASS] = (EC); \
425 (E)->e_ident[EI_VERSION] = (V); \
426 (E)->e_ehsize = _libelf_fsize(ELF_T_EHDR, (EC), (V), \
428 (E)->e_phentsize = _libelf_fsize(ELF_T_PHDR, (EC), (V), \
430 (E)->e_shentsize = _libelf_fsize(ELF_T_SHDR, (EC), (V), \
432 } while (/*CONSTCOND*/0)
434 if (ec
== ELFCLASS32
)
435 INITIALIZE_EHDR(eh32
, ec
, eh_version
);
437 INITIALIZE_EHDR(eh64
, ec
, eh_version
);
439 (void) elf_flagehdr(e
, ELF_C_SET
, ELF_F_DIRTY
);
441 rc
+= _libelf_fsize(ELF_T_EHDR
, ec
, eh_version
, (size_t) 1);
444 * Compute the layout the program header table, if one is
445 * present. The program header table needs to be aligned to a
446 * `natural' boundary.
449 fsz
= _libelf_fsize(ELF_T_PHDR
, ec
, eh_version
, phnum
);
450 align
= _libelf_falign(ELF_T_PHDR
, ec
);
452 if (e
->e_flags
& ELF_F_LAYOUT
) {
454 * Check offsets for sanity.
457 LIBELF_SET_ERROR(HEADER
, 0);
462 LIBELF_SET_ERROR(LAYOUT
, 0);
467 phoff
= roundup(rc
, align
);
474 * Compute the layout of the sections associated with the
478 if ((rc
= _libelf_resync_sections(e
, rc
)) < 0)
482 * Compute the space taken up by the section header table, if
483 * one is needed. If ELF_F_LAYOUT is asserted, the
484 * application may have placed the section header table in
485 * between existing sections, so the net size of the file need
486 * not increase due to the presence of the section header
490 fsz
= _libelf_fsize(ELF_T_SHDR
, ec
, eh_version
, (size_t) 1);
491 align
= _libelf_falign(ELF_T_SHDR
, ec
);
493 if (e
->e_flags
& ELF_F_LAYOUT
) {
495 LIBELF_SET_ERROR(LAYOUT
, 0);
499 shoff
= roundup(rc
, align
);
501 if (shoff
+ fsz
* shnum
> (size_t) rc
)
502 rc
= shoff
+ fsz
* shnum
;
507 * Set the fields of the Executable Header that could potentially use
508 * extended numbering.
510 _libelf_setphnum(e
, ehdr
, ec
, phnum
);
511 _libelf_setshnum(e
, ehdr
, ec
, shnum
);
514 * Update the `e_phoff' and `e_shoff' fields if the library is
517 if ((e
->e_flags
& ELF_F_LAYOUT
) == 0) {
518 if (ec
== ELFCLASS32
) {
519 eh32
->e_phoff
= (uint32_t) phoff
;
520 eh32
->e_shoff
= (uint32_t) shoff
;
522 eh64
->e_phoff
= (uint64_t) phoff
;
523 eh64
->e_shoff
= (uint64_t) shoff
;
531 * Write out the contents of a section.
535 _libelf_write_scn(Elf
*e
, char *nf
, Elf_Scn
*s
, off_t rc
)
538 size_t fsz
, msz
, nobjects
;
544 if ((ec
= e
->e_class
) == ELFCLASS32
)
545 sh_type
= s
->s_shdr
.s_shdr32
.sh_type
;
547 sh_type
= s
->s_shdr
.s_shdr64
.sh_type
;
550 * Ignore sections that do not allocate space in the file.
552 if (sh_type
== SHT_NOBITS
|| sh_type
== SHT_NULL
)
556 elftype
= _libelf_xlate_shtype(sh_type
);
557 assert(elftype
>= ELF_T_FIRST
&& elftype
<= ELF_T_LAST
);
559 msz
= _libelf_msize(elftype
, ec
, e
->e_version
);
561 sh_off
= s
->s_offset
;
562 assert(sh_off
% _libelf_falign(elftype
, ec
) == 0);
565 * If the section has a `rawdata' descriptor, and the section
566 * contents have not been modified, use its contents directly.
567 * The `s_rawoff' member contains the offset into the original
568 * file, while `s_offset' contains its new location in the
572 if (STAILQ_EMPTY(&s
->s_data
)) {
574 if ((d
= elf_rawdata(s
, NULL
)) == NULL
)
577 STAILQ_FOREACH(d
, &s
->s_rawdata
, d_next
) {
578 if ((uint64_t) rc
< sh_off
+ d
->d_off
)
579 (void) memset(nf
+ rc
,
580 LIBELF_PRIVATE(fillchar
), sh_off
+
582 rc
= sh_off
+ d
->d_off
;
584 assert(d
->d_buf
!= NULL
);
585 assert(d
->d_type
== ELF_T_BYTE
);
586 assert(d
->d_version
== e
->e_version
);
588 (void) memcpy(nf
+ rc
,
589 e
->e_rawfile
+ s
->s_rawoff
+ d
->d_off
, d
->d_size
);
598 * Iterate over the set of data descriptors for this section.
599 * The prior call to _libelf_resync_elf() would have setup the
600 * descriptors for this step.
603 dst
.d_version
= e
->e_version
;
605 STAILQ_FOREACH(d
, &s
->s_data
, d_next
) {
607 if ((uint64_t) rc
< sh_off
+ d
->d_off
)
608 (void) memset(nf
+ rc
,
609 LIBELF_PRIVATE(fillchar
), sh_off
+ d
->d_off
- rc
);
611 rc
= sh_off
+ d
->d_off
;
613 assert(d
->d_buf
!= NULL
);
614 assert(d
->d_type
== (Elf_Type
) elftype
);
615 assert(d
->d_version
== e
->e_version
);
616 assert(d
->d_size
% msz
== 0);
618 nobjects
= d
->d_size
/ msz
;
620 fsz
= _libelf_fsize(elftype
, ec
, e
->e_version
, nobjects
);
625 if (_libelf_xlate(&dst
, d
, e
->e_byteorder
, ec
, ELF_TOFILE
) ==
636 * Write out the file image.
638 * The original file could have been mapped in with an ELF_C_RDWR
639 * command and the application could have added new content or
640 * re-arranged its sections before calling elf_update(). Consequently
641 * its not safe to work `in place' on the original file. So we
642 * malloc() the required space for the updated ELF object and build
643 * the object there and write it out to the underlying file at the
644 * end. Note that the application may have opened the underlying file
645 * in ELF_C_RDWR and only retrieved/modified a few sections. We take
646 * care to avoid translating file sections unnecessarily.
648 * Gaps in the coverage of the file by the file's sections will be
649 * filled with the fill character set by elf_fill(3).
653 _libelf_write_elf(Elf
*e
, off_t newsize
)
657 size_t fsz
, msz
, phnum
, shnum
;
658 uint64_t phoff
, shoff
;
666 assert(e
->e_kind
== ELF_K_ELF
);
667 assert(e
->e_cmd
!= ELF_C_READ
);
668 assert(e
->e_fd
>= 0);
670 if ((newfile
= malloc((size_t) newsize
)) == NULL
) {
671 LIBELF_SET_ERROR(RESOURCE
, errno
);
677 ehdr
= _libelf_ehdr(e
, ec
, 0);
678 assert(ehdr
!= NULL
);
680 phnum
= e
->e_u
.e_elf
.e_nphdr
;
682 if (ec
== ELFCLASS32
) {
683 eh32
= (Elf32_Ehdr
*) ehdr
;
685 phoff
= (uint64_t) eh32
->e_phoff
;
686 shnum
= eh32
->e_shnum
;
687 shoff
= (uint64_t) eh32
->e_shoff
;
689 eh64
= (Elf64_Ehdr
*) ehdr
;
691 phoff
= eh64
->e_phoff
;
692 shnum
= eh64
->e_shnum
;
693 shoff
= eh64
->e_shoff
;
696 fsz
= _libelf_fsize(ELF_T_EHDR
, ec
, e
->e_version
, (size_t) 1);
697 msz
= _libelf_msize(ELF_T_EHDR
, ec
, e
->e_version
);
699 (void) memset(&dst
, 0, sizeof(dst
));
700 (void) memset(&src
, 0, sizeof(src
));
704 src
.d_type
= ELF_T_EHDR
;
705 src
.d_version
= dst
.d_version
= e
->e_version
;
709 dst
.d_buf
= newfile
+ rc
;
712 if (_libelf_xlate(&dst
, &src
, e
->e_byteorder
, ec
, ELF_TOFILE
) ==
719 * Write the program header table if present.
722 if (phnum
!= 0 && phoff
!= 0) {
723 assert((unsigned) rc
<= phoff
);
725 fsz
= _libelf_fsize(ELF_T_PHDR
, ec
, e
->e_version
, phnum
);
727 assert(phoff
% _libelf_falign(ELF_T_PHDR
, ec
) == 0);
730 src
.d_version
= dst
.d_version
= e
->e_version
;
731 src
.d_type
= ELF_T_PHDR
;
733 if (ec
== ELFCLASS32
)
734 src
.d_buf
= e
->e_u
.e_elf
.e_phdr
.e_phdr32
;
736 src
.d_buf
= e
->e_u
.e_elf
.e_phdr
.e_phdr64
;
738 src
.d_size
= phnum
* _libelf_msize(ELF_T_PHDR
, ec
,
743 if ((uint64_t) rc
< phoff
)
744 (void) memset(newfile
+ rc
,
745 LIBELF_PRIVATE(fillchar
), phoff
- rc
);
747 dst
.d_buf
= newfile
+ rc
;
749 if (_libelf_xlate(&dst
, &src
, e
->e_byteorder
, ec
, ELF_TOFILE
) ==
757 * Write out individual sections.
760 STAILQ_FOREACH(scn
, &e
->e_u
.e_elf
.e_scn
, s_next
)
761 if ((rc
= _libelf_write_scn(e
, newfile
, scn
, rc
)) < 0)
765 * Write out the section header table, if required. Note that
766 * if flag ELF_F_LAYOUT has been set the section header table
767 * could reside in between byte ranges mapped by section
770 if (shnum
!= 0 && shoff
!= 0) {
771 if ((uint64_t) rc
< shoff
)
772 (void) memset(newfile
+ rc
,
773 LIBELF_PRIVATE(fillchar
), shoff
- rc
);
778 assert(rc
% _libelf_falign(ELF_T_SHDR
, ec
) == 0);
780 src
.d_type
= ELF_T_SHDR
;
781 src
.d_size
= _libelf_msize(ELF_T_SHDR
, ec
, e
->e_version
);
782 src
.d_version
= dst
.d_version
= e
->e_version
;
784 fsz
= _libelf_fsize(ELF_T_SHDR
, ec
, e
->e_version
, (size_t) 1);
786 STAILQ_FOREACH(scn
, &e
->e_u
.e_elf
.e_scn
, s_next
) {
787 if (ec
== ELFCLASS32
)
788 src
.d_buf
= &scn
->s_shdr
.s_shdr32
;
790 src
.d_buf
= &scn
->s_shdr
.s_shdr64
;
793 dst
.d_buf
= newfile
+ rc
+ scn
->s_ndx
* fsz
;
795 if (_libelf_xlate(&dst
, &src
, e
->e_byteorder
, ec
,
800 rc
+= e
->e_u
.e_elf
.e_nscn
* fsz
;
805 assert(rc
== newsize
);
808 * Write out the constructed contents and remap the file in
812 if (e
->e_rawfile
&& munmap(e
->e_rawfile
, e
->e_rawsize
) < 0) {
813 LIBELF_SET_ERROR(IO
, errno
);
817 if (write(e
->e_fd
, newfile
, (size_t) newsize
) != newsize
||
818 lseek(e
->e_fd
, (off_t
) 0, SEEK_SET
) < 0) {
819 LIBELF_SET_ERROR(IO
, errno
);
823 if (e
->e_cmd
!= ELF_C_WRITE
) {
824 if ((e
->e_rawfile
= mmap(NULL
, (size_t) newsize
, PROT_READ
,
825 MAP_PRIVATE
, e
->e_fd
, (off_t
) 0)) == MAP_FAILED
) {
826 LIBELF_SET_ERROR(IO
, errno
);
829 e
->e_rawsize
= newsize
;
833 * Reset flags, remove existing section descriptors and
834 * {E,P}HDR pointers so that a subsequent elf_get{e,p}hdr()
835 * and elf_getscn() will function correctly.
838 e
->e_flags
&= ~ELF_F_DIRTY
;
840 STAILQ_FOREACH_SAFE(scn
, &e
->e_u
.e_elf
.e_scn
, s_next
, tscn
)
841 _libelf_release_scn(scn
);
843 if (ec
== ELFCLASS32
) {
844 free(e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
);
845 if (e
->e_u
.e_elf
.e_phdr
.e_phdr32
)
846 free(e
->e_u
.e_elf
.e_phdr
.e_phdr32
);
848 e
->e_u
.e_elf
.e_ehdr
.e_ehdr32
= NULL
;
849 e
->e_u
.e_elf
.e_phdr
.e_phdr32
= NULL
;
851 free(e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
);
852 if (e
->e_u
.e_elf
.e_phdr
.e_phdr64
)
853 free(e
->e_u
.e_elf
.e_phdr
.e_phdr64
);
855 e
->e_u
.e_elf
.e_ehdr
.e_ehdr64
= NULL
;
856 e
->e_u
.e_elf
.e_phdr
.e_phdr64
= NULL
;
868 elf_update(Elf
*e
, Elf_Cmd c
)
875 if (e
== NULL
|| e
->e_kind
!= ELF_K_ELF
||
876 (c
!= ELF_C_NULL
&& c
!= ELF_C_WRITE
)) {
877 LIBELF_SET_ERROR(ARGUMENT
, 0);
881 if ((ec
= e
->e_class
) != ELFCLASS32
&& ec
!= ELFCLASS64
) {
882 LIBELF_SET_ERROR(CLASS
, 0);
886 if (e
->e_version
== EV_NONE
)
887 e
->e_version
= EV_CURRENT
;
889 if (c
== ELF_C_WRITE
&& e
->e_cmd
== ELF_C_READ
) {
890 LIBELF_SET_ERROR(MODE
, 0);
894 if ((rc
= _libelf_resync_elf(e
)) < 0)
900 if (e
->e_cmd
== ELF_C_READ
) {
902 * This descriptor was opened in read-only mode or by
906 LIBELF_SET_ERROR(MODE
, 0);
908 LIBELF_SET_ERROR(ARGUMENT
, 0);
913 LIBELF_SET_ERROR(SEQUENCE
, 0);
917 return (_libelf_write_elf(e
, rc
));