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