Bug Summary

File:src/lib/libelf/elf_update.c
Warning:line 1048, column 2
Value stored to 'nrc' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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