elf_update.c revision 210326
10SN/A/*-
22362SN/A * Copyright (c) 2006-2008 Joseph Koshy
30SN/A * All rights reserved.
40SN/A *
50SN/A * Redistribution and use in source and binary forms, with or without
60SN/A * modification, are permitted provided that the following conditions
72362SN/A * are met:
80SN/A * 1. Redistributions of source code must retain the above copyright
92362SN/A *    notice, this list of conditions and the following disclaimer.
100SN/A * 2. Redistributions in binary form must reproduce the above copyright
110SN/A *    notice, this list of conditions and the following disclaimer in the
120SN/A *    documentation and/or other materials provided with the distribution.
130SN/A *
140SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
150SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
160SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
170SN/A * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
180SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
190SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
200SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212362SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222362SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232362SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
240SN/A * SUCH DAMAGE.
250SN/A */
260SN/A
270SN/A#include <sys/cdefs.h>
280SN/A__FBSDID("$FreeBSD: head/lib/libelf/elf_update.c 210326 2010-07-21 09:20:40Z kaiw $");
290SN/A
300SN/A#include <sys/mman.h>
311245SN/A#include <sys/param.h>
3211407Ssherman
330SN/A#include <assert.h>
341245SN/A#include <errno.h>
350SN/A#include <gelf.h>
360SN/A#include <libelf.h>
370SN/A#include <stdlib.h>
380SN/A#include <string.h>
390SN/A#include <unistd.h>
400SN/A
410SN/A#include "_libelf.h"
420SN/A
430SN/A/*
440SN/A * Update the internal data structures associated with an ELF object.
450SN/A * Returns the size in bytes the ELF object would occupy in its file
460SN/A * representation.
470SN/A *
480SN/A * After a successful call to this function, the following structures
490SN/A * are updated:
500SN/A *
510SN/A * - The ELF header is updated.
521245SN/A * - All sections are sorted in order of ascending addresses and their
531245SN/A *   section header table entries updated.   An error is signalled
541245SN/A *   if an overlap was detected among sections.
551245SN/A * - All data descriptors associated with a section are sorted in order
561245SN/A *   of ascending addresses.  Overlaps, if detected, are signalled as
570SN/A *   errors.  Other sanity checks for alignments, section types etc. are
580SN/A *   made.
590SN/A *
601245SN/A * After a resync_elf() successfully returns, the ELF descriptor is
610SN/A * ready for being handed over to _libelf_write_elf().
620SN/A *
631245SN/A * File alignments:
641245SN/A * PHDR - Addr
651245SN/A * SHDR - Addr
660SN/A *
671245SN/A * XXX: how do we handle 'flags'.
681245SN/A */
690SN/A
701245SN/A/*
711245SN/A * Compute the extents of a section, by looking at the data
721245SN/A * descriptors associated with it.  The function returns zero if an
731245SN/A * error was detected.  `*rc' holds the maximum file extent seen so
741245SN/A * far.
751245SN/A */
760SN/Astatic int
771245SN/A_libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc)
781245SN/A{
791245SN/A	int ec;
801245SN/A	Elf_Data *d, *td;
811245SN/A	unsigned int elftype;
821245SN/A	uint32_t sh_type;
830SN/A	uint64_t d_align;
841245SN/A	uint64_t sh_align, sh_entsize, sh_offset, sh_size;
851245SN/A	uint64_t scn_size, scn_alignment;
861245SN/A
871245SN/A	/*
881245SN/A	 * We need to recompute library private data structures if one
891245SN/A	 * or more of the following is true:
901245SN/A	 * - The underlying Shdr structure has been marked `dirty'.  Significant
911245SN/A	 *   fields include: `sh_offset', `sh_type', `sh_size', `sh_addralign'.
920SN/A	 * - The Elf_Data structures part of this section have been marked
930SN/A	 *   `dirty'.  Affected members include `d_align', `d_offset', `d_type',
94	 *   and `d_size'.
95	 * - The section as a whole is `dirty', e.g., it has been allocated
96	 *   using elf_newscn(), or if a new Elf_Data structure was added using
97	 *   elf_newdata().
98	 *
99	 * Each of these conditions would result in the ELF_F_DIRTY bit being
100	 * set on the section descriptor's `s_flags' field.
101	 */
102
103	ec = e->e_class;
104
105	if (ec == ELFCLASS32) {
106		sh_type    = s->s_shdr.s_shdr32.sh_type;
107		sh_align   = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
108		sh_entsize = (uint64_t) s->s_shdr.s_shdr32.sh_entsize;
109		sh_offset  = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
110		sh_size    = (uint64_t) s->s_shdr.s_shdr32.sh_size;
111	} else {
112		sh_type    = s->s_shdr.s_shdr64.sh_type;
113		sh_align   = s->s_shdr.s_shdr64.sh_addralign;
114		sh_entsize = s->s_shdr.s_shdr64.sh_entsize;
115		sh_offset  = s->s_shdr.s_shdr64.sh_offset;
116		sh_size    = s->s_shdr.s_shdr64.sh_size;
117	}
118
119	if (sh_type == SHT_NULL || sh_type == SHT_NOBITS)
120		return (1);
121
122	if ((s->s_flags & ELF_F_DIRTY) == 0) {
123		if ((size_t) *rc < sh_offset + sh_size)
124			*rc = sh_offset + sh_size;
125		return (1);
126	}
127
128	elftype = _libelf_xlate_shtype(sh_type);
129	if (elftype > ELF_T_LAST) {
130		LIBELF_SET_ERROR(SECTION, 0);
131		return (0);
132	}
133
134	/*
135	 * Compute the extent of the data descriptors associated with
136	 * this section.
137	 */
138	scn_alignment = 0;
139	if (sh_align == 0)
140		sh_align = _libelf_falign(elftype, ec);
141
142	/* Compute the section alignment. */
143	STAILQ_FOREACH(d, &s->s_data, d_next)  {
144		if (d->d_type != elftype) {
145			LIBELF_SET_ERROR(DATA, 0);
146			return (0);
147		}
148		if (d->d_version != e->e_version) {
149			LIBELF_SET_ERROR(VERSION, 0);
150			return (0);
151		}
152		if ((d_align = d->d_align) % sh_align) {
153			LIBELF_SET_ERROR(LAYOUT, 0);
154			return (0);
155		}
156		if (d_align == 0 || (d_align & (d_align - 1))) {
157			LIBELF_SET_ERROR(DATA, 0);
158			return (0);
159		}
160		if (d_align > scn_alignment)
161			scn_alignment = d_align;
162	}
163
164	scn_size = 0L;
165
166	STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
167		if (e->e_flags & ELF_F_LAYOUT) {
168			if ((uint64_t) d->d_off + d->d_size > scn_size)
169				scn_size = d->d_off + d->d_size;
170		} else {
171			scn_size = roundup2(scn_size, scn_alignment);
172			d->d_off = scn_size;
173			scn_size += d->d_size;
174		}
175	}
176
177	/*
178	 * If the application is requesting full control over the layout
179	 * of the section, check its values for sanity.
180	 */
181	if (e->e_flags & ELF_F_LAYOUT) {
182		if (scn_alignment > sh_align || sh_offset % sh_align ||
183		    sh_size < scn_size) {
184			LIBELF_SET_ERROR(LAYOUT, 0);
185			return (0);
186		}
187	} else {
188		/*
189		 * Otherwise compute the values in the section header.
190		 */
191
192		if (scn_alignment > sh_align)
193			sh_align = scn_alignment;
194
195		/*
196		 * If the section entry size is zero, try and fill in an
197		 * appropriate entry size.  Per the elf(5) manual page
198		 * sections without fixed-size entries should have their
199		 * 'sh_entsize' field set to zero.
200		 */
201		if (sh_entsize == 0 &&
202		    (sh_entsize = _libelf_fsize(elftype, ec, e->e_version,
203		    (size_t) 1)) == 1)
204			sh_entsize = 0;
205
206		sh_size = scn_size;
207		sh_offset = roundup(*rc, sh_align);
208
209		if (ec == ELFCLASS32) {
210			s->s_shdr.s_shdr32.sh_addralign = (uint32_t) sh_align;
211			s->s_shdr.s_shdr32.sh_entsize   = (uint32_t) sh_entsize;
212			s->s_shdr.s_shdr32.sh_offset    = (uint32_t) sh_offset;
213			s->s_shdr.s_shdr32.sh_size      = (uint32_t) sh_size;
214		} else {
215			s->s_shdr.s_shdr64.sh_addralign = sh_align;
216			s->s_shdr.s_shdr64.sh_entsize   = sh_entsize;
217			s->s_shdr.s_shdr64.sh_offset    = sh_offset;
218			s->s_shdr.s_shdr64.sh_size      = sh_size;
219		}
220	}
221
222	if ((size_t) *rc < sh_offset + sh_size)
223		*rc = sh_offset + sh_size;
224
225	s->s_size = sh_size;
226	s->s_offset = sh_offset;
227	return (1);
228}
229
230
231/*
232 * Insert a section in ascending order in the list
233 */
234
235static int
236_libelf_insert_section(Elf *e, Elf_Scn *s)
237{
238	Elf_Scn *t, *prevt;
239	uint64_t smax, smin, tmax, tmin;
240
241	smin = s->s_offset;
242	smax = smin + s->s_size;
243
244	prevt = NULL;
245	STAILQ_FOREACH(t, &e->e_u.e_elf.e_scn, s_next) {
246		tmin = t->s_offset;
247		tmax = tmin + t->s_size;
248
249		if (tmax <= smin) {
250			/*
251			 * 't' lies entirely before 's': ...| t |...| s |...
252			 */
253			prevt = t;
254			continue;
255		} else if (smax <= tmin)
256			/*
257			 * 's' lies entirely before 't', and after 'prevt':
258			 *      ...| prevt |...| s |...| t |...
259			 */
260			break;
261		else {	/* 's' and 't' overlap. */
262			LIBELF_SET_ERROR(LAYOUT, 0);
263			return (0);
264		}
265	}
266
267	if (prevt)
268		STAILQ_INSERT_AFTER(&e->e_u.e_elf.e_scn, prevt, s, s_next);
269	else
270		STAILQ_INSERT_HEAD(&e->e_u.e_elf.e_scn, s, s_next);
271	return (1);
272}
273
274static off_t
275_libelf_resync_sections(Elf *e, off_t rc)
276{
277	int ec;
278	off_t nrc;
279	size_t sh_type, shdr_start, shdr_end;
280	Elf_Scn *s, *ts;
281
282	ec = e->e_class;
283
284	/*
285	 * Make a pass through sections, computing the extent of each
286	 * section. Order in increasing order of addresses.
287	 */
288
289	nrc = rc;
290	STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next)
291		if (_libelf_compute_section_extents(e, s, &nrc) == 0)
292			return ((off_t) -1);
293
294	STAILQ_FOREACH_SAFE(s, &e->e_u.e_elf.e_scn, s_next, ts) {
295		if (ec == ELFCLASS32)
296			sh_type = s->s_shdr.s_shdr32.sh_type;
297		else
298			sh_type = s->s_shdr.s_shdr64.sh_type;
299
300		if (sh_type == SHT_NOBITS || sh_type == SHT_NULL)
301			continue;
302
303		if (s->s_offset < (uint64_t) rc) {
304			if (s->s_offset + s->s_size < (uint64_t) rc) {
305				/*
306				 * Try insert this section in the
307				 * correct place in the list,
308				 * detecting overlaps if any.
309				 */
310				STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn,
311				    s_next);
312				if (_libelf_insert_section(e, s) == 0)
313					return ((off_t) -1);
314			} else {
315				LIBELF_SET_ERROR(LAYOUT, 0);
316				return ((off_t) -1);
317			}
318		} else
319			rc = s->s_offset + s->s_size;
320	}
321
322	/*
323	 * If the application is controlling file layout, check for an
324	 * overlap between this section's extents and the SHDR table.
325	 */
326	if (e->e_flags & ELF_F_LAYOUT) {
327
328		if (e->e_class == ELFCLASS32)
329			shdr_start = e->e_u.e_elf.e_ehdr.e_ehdr32->e_shoff;
330		else
331			shdr_start = e->e_u.e_elf.e_ehdr.e_ehdr64->e_shoff;
332
333		shdr_end = shdr_start + _libelf_fsize(ELF_T_SHDR, e->e_class,
334		    e->e_version, e->e_u.e_elf.e_nscn);
335
336		STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) {
337			if (s->s_offset >= shdr_end ||
338			    s->s_offset + s->s_size <= shdr_start)
339				continue;
340			LIBELF_SET_ERROR(LAYOUT, 0);
341			return ((off_t) -1);
342		}
343	}
344
345	assert(nrc == rc);
346
347	return (rc);
348}
349
350static off_t
351_libelf_resync_elf(Elf *e)
352{
353	int ec, eh_class, eh_type;
354	unsigned int eh_byteorder, eh_version;
355	size_t align, fsz;
356	size_t phnum, shnum;
357	off_t rc, phoff, shoff;
358	void *ehdr;
359	Elf32_Ehdr *eh32;
360	Elf64_Ehdr *eh64;
361
362	rc = 0;
363
364	ec = e->e_class;
365
366	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
367
368	/*
369	 * Prepare the EHDR.
370	 */
371	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
372		return ((off_t) -1);
373
374	eh32 = ehdr;
375	eh64 = ehdr;
376
377	if (ec == ELFCLASS32) {
378		eh_byteorder = eh32->e_ident[EI_DATA];
379		eh_class     = eh32->e_ident[EI_CLASS];
380		phoff        = (uint64_t) eh32->e_phoff;
381		shoff        = (uint64_t) eh32->e_shoff;
382		eh_type      = eh32->e_type;
383		eh_version   = eh32->e_version;
384	} else {
385		eh_byteorder = eh64->e_ident[EI_DATA];
386		eh_class     = eh64->e_ident[EI_CLASS];
387		phoff        = eh64->e_phoff;
388		shoff        = eh64->e_shoff;
389		eh_type      = eh64->e_type;
390		eh_version   = eh64->e_version;
391	}
392
393	if (eh_version == EV_NONE)
394		eh_version = EV_CURRENT;
395
396	if (eh_version != e->e_version) {	/* always EV_CURRENT */
397		LIBELF_SET_ERROR(VERSION, 0);
398		return ((off_t) -1);
399	}
400
401	if (eh_class != e->e_class) {
402		LIBELF_SET_ERROR(CLASS, 0);
403		return ((off_t) -1);
404	}
405
406	if (e->e_cmd != ELF_C_WRITE && eh_byteorder != e->e_byteorder) {
407		LIBELF_SET_ERROR(HEADER, 0);
408		return ((off_t) -1);
409	}
410
411	shnum = e->e_u.e_elf.e_nscn;
412	phnum = e->e_u.e_elf.e_nphdr;
413
414	e->e_byteorder = eh_byteorder;
415
416#define	INITIALIZE_EHDR(E,EC,V)	do {					\
417		(E)->e_ident[EI_MAG0] = ELFMAG0;			\
418		(E)->e_ident[EI_MAG1] = ELFMAG1;			\
419		(E)->e_ident[EI_MAG2] = ELFMAG2;			\
420		(E)->e_ident[EI_MAG3] = ELFMAG3;			\
421		(E)->e_ident[EI_CLASS] = (EC);				\
422		(E)->e_ident[EI_VERSION] = (V);				\
423		(E)->e_ehsize = _libelf_fsize(ELF_T_EHDR, (EC), (V),	\
424		    (size_t) 1);					\
425		(E)->e_phentsize = (phnum == 0) ? 0 : _libelf_fsize(	\
426		    ELF_T_PHDR, (EC), (V), (size_t) 1);			\
427		(E)->e_shentsize = _libelf_fsize(ELF_T_SHDR, (EC), (V),	\
428		    (size_t) 1);					\
429	} while (0)
430
431	if (ec == ELFCLASS32)
432		INITIALIZE_EHDR(eh32, ec, eh_version);
433	else
434		INITIALIZE_EHDR(eh64, ec, eh_version);
435
436	(void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY);
437
438	rc += _libelf_fsize(ELF_T_EHDR, ec, eh_version, (size_t) 1);
439
440	/*
441	 * Compute the layout the program header table, if one is
442	 * present.  The program header table needs to be aligned to a
443	 * `natural' boundary.
444	 */
445	if (phnum) {
446		fsz = _libelf_fsize(ELF_T_PHDR, ec, eh_version, phnum);
447		align = _libelf_falign(ELF_T_PHDR, ec);
448
449		if (e->e_flags & ELF_F_LAYOUT) {
450			/*
451			 * Check offsets for sanity.
452			 */
453			if (rc > phoff) {
454				LIBELF_SET_ERROR(HEADER, 0);
455				return ((off_t) -1);
456			}
457
458			if (phoff % align) {
459				LIBELF_SET_ERROR(LAYOUT, 0);
460				return ((off_t) -1);
461			}
462
463		} else
464			phoff = roundup(rc, align);
465
466		rc = phoff + fsz;
467	} else
468		phoff = 0;
469
470	/*
471	 * Compute the layout of the sections associated with the
472	 * file.
473	 */
474
475	if ((rc = _libelf_resync_sections(e, rc)) < 0)
476		return ((off_t) -1);
477
478	/*
479	 * Compute the space taken up by the section header table, if
480	 * one is needed.  If ELF_F_LAYOUT is asserted, the
481	 * application may have placed the section header table in
482	 * between existing sections, so the net size of the file need
483	 * not increase due to the presence of the section header
484	 * table.
485	 */
486	if (shnum) {
487		fsz = _libelf_fsize(ELF_T_SHDR, ec, eh_version, (size_t) 1);
488		align = _libelf_falign(ELF_T_SHDR, ec);
489
490		if (e->e_flags & ELF_F_LAYOUT) {
491			if (shoff % align) {
492				LIBELF_SET_ERROR(LAYOUT, 0);
493				return ((off_t) -1);
494			}
495		} else
496			shoff = roundup(rc, align);
497
498		if (shoff + fsz * shnum > (size_t) rc)
499			rc = shoff + fsz * shnum;
500	} else
501		shoff = 0;
502
503	/*
504	 * Set the fields of the Executable Header that could potentially use
505	 * extended numbering.
506	 */
507	_libelf_setphnum(e, ehdr, ec, phnum);
508	_libelf_setshnum(e, ehdr, ec, shnum);
509
510	/*
511	 * Update the `e_phoff' and `e_shoff' fields if the library is
512	 * doing the layout.
513	 */
514	if ((e->e_flags & ELF_F_LAYOUT) == 0) {
515		if (ec == ELFCLASS32) {
516			eh32->e_phoff = (uint32_t) phoff;
517			eh32->e_shoff = (uint32_t) shoff;
518		} else {
519			eh64->e_phoff = (uint64_t) phoff;
520			eh64->e_shoff = (uint64_t) shoff;
521		}
522	}
523
524	return (rc);
525}
526
527/*
528 * Write out the contents of a section.
529 */
530
531static off_t
532_libelf_write_scn(Elf *e, char *nf, Elf_Scn *s, off_t rc)
533{
534	int ec;
535	size_t fsz, msz, nobjects;
536	uint32_t sh_type;
537	uint64_t sh_off;
538	int elftype;
539	Elf_Data *d, dst;
540
541	if ((ec = e->e_class) == ELFCLASS32)
542		sh_type = s->s_shdr.s_shdr32.sh_type;
543	else
544		sh_type = s->s_shdr.s_shdr64.sh_type;
545
546	/*
547	 * Ignore sections that do not allocate space in the file.
548	 */
549	if (sh_type == SHT_NOBITS || sh_type == SHT_NULL)
550		return (rc);
551
552
553	elftype = _libelf_xlate_shtype(sh_type);
554	assert(elftype >= ELF_T_FIRST && elftype <= ELF_T_LAST);
555
556	msz = _libelf_msize(elftype, ec, e->e_version);
557
558	sh_off = s->s_offset;
559	assert(sh_off % _libelf_falign(elftype, ec) == 0);
560
561	/*
562	 * If the section has a `rawdata' descriptor, and the section
563	 * contents have not been modified, use its contents directly.
564	 * The `s_rawoff' member contains the offset into the original
565	 * file, while `s_offset' contains its new location in the
566	 * destination.
567	 */
568
569	if (STAILQ_EMPTY(&s->s_data)) {
570
571		if ((d = elf_rawdata(s, NULL)) == NULL)
572			return ((off_t) -1);
573
574		STAILQ_FOREACH(d, &s->s_rawdata, d_next) {
575			if ((uint64_t) rc < sh_off + d->d_off)
576				(void) memset(nf + rc,
577				    LIBELF_PRIVATE(fillchar), sh_off +
578				    d->d_off - rc);
579			rc = sh_off + d->d_off;
580
581			assert(d->d_buf != NULL);
582			assert(d->d_type == ELF_T_BYTE);
583			assert(d->d_version == e->e_version);
584
585			(void) memcpy(nf + rc,
586			    e->e_rawfile + s->s_rawoff + d->d_off, d->d_size);
587
588			rc += d->d_size;
589		}
590
591		return (rc);
592	}
593
594	/*
595	 * Iterate over the set of data descriptors for this section.
596	 * The prior call to _libelf_resync_elf() would have setup the
597	 * descriptors for this step.
598	 */
599
600	dst.d_version = e->e_version;
601
602	STAILQ_FOREACH(d, &s->s_data, d_next) {
603
604		if ((uint64_t) rc < sh_off + d->d_off)
605			(void) memset(nf + rc,
606			    LIBELF_PRIVATE(fillchar), sh_off + d->d_off - rc);
607
608		rc = sh_off + d->d_off;
609
610		assert(d->d_buf != NULL);
611		assert(d->d_type == (Elf_Type) elftype);
612		assert(d->d_version == e->e_version);
613		assert(d->d_size % msz == 0);
614
615		nobjects = d->d_size / msz;
616
617		fsz = _libelf_fsize(elftype, ec, e->e_version, nobjects);
618
619		dst.d_buf    = nf + rc;
620		dst.d_size   = fsz;
621
622		if (_libelf_xlate(&dst, d, e->e_byteorder, ec, ELF_TOFILE) ==
623		    NULL)
624			return ((off_t) -1);
625
626		rc += fsz;
627	}
628
629	return ((off_t) rc);
630}
631
632/*
633 * Write out the file image.
634 *
635 * The original file could have been mapped in with an ELF_C_RDWR
636 * command and the application could have added new content or
637 * re-arranged its sections before calling elf_update().  Consequently
638 * its not safe to work `in place' on the original file.  So we
639 * malloc() the required space for the updated ELF object and build
640 * the object there and write it out to the underlying file at the
641 * end.  Note that the application may have opened the underlying file
642 * in ELF_C_RDWR and only retrieved/modified a few sections.  We take
643 * care to avoid translating file sections unnecessarily.
644 *
645 * Gaps in the coverage of the file by the file's sections will be
646 * filled with the fill character set by elf_fill(3).
647 */
648
649static off_t
650_libelf_write_elf(Elf *e, off_t newsize)
651{
652	int ec;
653	off_t maxrc, rc;
654	size_t fsz, msz, phnum, shnum;
655	uint64_t phoff, shoff;
656	void *ehdr;
657	char *newfile;
658	Elf_Data dst, src;
659	Elf_Scn *scn, *tscn;
660	Elf32_Ehdr *eh32;
661	Elf64_Ehdr *eh64;
662
663	assert(e->e_kind == ELF_K_ELF);
664	assert(e->e_cmd != ELF_C_READ);
665	assert(e->e_fd >= 0);
666
667	if ((newfile = malloc((size_t) newsize)) == NULL) {
668		LIBELF_SET_ERROR(RESOURCE, errno);
669		return ((off_t) -1);
670	}
671
672	ec = e->e_class;
673
674	ehdr = _libelf_ehdr(e, ec, 0);
675	assert(ehdr != NULL);
676
677	phnum = e->e_u.e_elf.e_nphdr;
678
679	if (ec == ELFCLASS32) {
680		eh32 = (Elf32_Ehdr *) ehdr;
681
682		phoff = (uint64_t) eh32->e_phoff;
683		shnum = eh32->e_shnum;
684		shoff = (uint64_t) eh32->e_shoff;
685	} else {
686		eh64 = (Elf64_Ehdr *) ehdr;
687
688		phoff = eh64->e_phoff;
689		shnum = eh64->e_shnum;
690		shoff = eh64->e_shoff;
691	}
692
693	fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
694	msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version);
695
696	(void) memset(&dst, 0, sizeof(dst));
697	(void) memset(&src, 0, sizeof(src));
698
699	src.d_buf     = ehdr;
700	src.d_size    = msz;
701	src.d_type    = ELF_T_EHDR;
702	src.d_version = dst.d_version = e->e_version;
703
704	rc = 0;
705
706	dst.d_buf     = newfile + rc;
707	dst.d_size    = fsz;
708
709	if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) ==
710	    NULL)
711		goto error;
712
713	rc += fsz;
714
715	/*
716	 * Write the program header table if present.
717	 */
718
719	if (phnum != 0 && phoff != 0) {
720		assert((unsigned) rc <= phoff);
721
722		fsz = _libelf_fsize(ELF_T_PHDR, ec, e->e_version, phnum);
723
724		assert(phoff % _libelf_falign(ELF_T_PHDR, ec) == 0);
725		assert(fsz > 0);
726
727		src.d_version = dst.d_version = e->e_version;
728		src.d_type = ELF_T_PHDR;
729
730		if (ec == ELFCLASS32)
731			src.d_buf = e->e_u.e_elf.e_phdr.e_phdr32;
732		else
733			src.d_buf = e->e_u.e_elf.e_phdr.e_phdr64;
734
735		src.d_size = phnum * _libelf_msize(ELF_T_PHDR, ec,
736		    e->e_version);
737
738		dst.d_size = fsz;
739
740		if ((uint64_t) rc < phoff)
741			(void) memset(newfile + rc,
742			    LIBELF_PRIVATE(fillchar), phoff - rc);
743
744		dst.d_buf = newfile + rc;
745
746		if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) ==
747		    NULL)
748			goto error;
749
750		rc = phoff + fsz;
751	}
752
753	/*
754	 * Write out individual sections.
755	 */
756
757	STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next)
758 		if ((rc = _libelf_write_scn(e, newfile, scn, rc)) < 0)
759			goto error;
760
761	/*
762	 * Write out the section header table, if required.  Note that
763	 * if flag ELF_F_LAYOUT has been set the section header table
764	 * could reside in between byte ranges mapped by section
765	 * descriptors.
766	 */
767	if (shnum != 0 && shoff != 0) {
768		if ((uint64_t) rc < shoff)
769			(void) memset(newfile + rc,
770			    LIBELF_PRIVATE(fillchar), shoff - rc);
771
772		maxrc = rc;
773		rc = shoff;
774
775		assert(rc % _libelf_falign(ELF_T_SHDR, ec) == 0);
776
777		src.d_type = ELF_T_SHDR;
778		src.d_size = _libelf_msize(ELF_T_SHDR, ec, e->e_version);
779		src.d_version = dst.d_version = e->e_version;
780
781		fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
782
783		STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) {
784			if (ec == ELFCLASS32)
785				src.d_buf = &scn->s_shdr.s_shdr32;
786			else
787				src.d_buf = &scn->s_shdr.s_shdr64;
788
789			dst.d_size = fsz;
790			dst.d_buf = newfile + rc + scn->s_ndx * fsz;
791
792			if (_libelf_xlate(&dst, &src, e->e_byteorder, ec,
793				ELF_TOFILE) != &dst)
794				goto error;
795		}
796
797		rc += e->e_u.e_elf.e_nscn * fsz;
798		if (maxrc > rc)
799			rc = maxrc;
800	}
801
802	assert(rc == newsize);
803
804	/*
805	 * Write out the constructed contents and remap the file in
806	 * read-only.
807	 */
808
809	if (e->e_rawfile && munmap(e->e_rawfile, e->e_rawsize) < 0) {
810		LIBELF_SET_ERROR(IO, errno);
811		goto error;
812	}
813
814	if (write(e->e_fd, newfile, (size_t) newsize) != newsize ||
815	    lseek(e->e_fd, (off_t) 0, SEEK_SET) < 0) {
816		LIBELF_SET_ERROR(IO, errno);
817		goto error;
818	}
819
820	if (e->e_cmd != ELF_C_WRITE) {
821		if ((e->e_rawfile = mmap(NULL, (size_t) newsize, PROT_READ,
822		    MAP_PRIVATE, e->e_fd, (off_t) 0)) == MAP_FAILED) {
823			LIBELF_SET_ERROR(IO, errno);
824			goto error;
825		}
826		e->e_rawsize = newsize;
827	}
828
829	/*
830	 * Reset flags, remove existing section descriptors and
831	 * {E,P}HDR pointers so that a subsequent elf_get{e,p}hdr()
832	 * and elf_getscn() will function correctly.
833	 */
834
835	e->e_flags &= ~ELF_F_DIRTY;
836
837	STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn)
838		_libelf_release_scn(scn);
839
840	if (ec == ELFCLASS32) {
841		free(e->e_u.e_elf.e_ehdr.e_ehdr32);
842		if (e->e_u.e_elf.e_phdr.e_phdr32)
843			free(e->e_u.e_elf.e_phdr.e_phdr32);
844
845		e->e_u.e_elf.e_ehdr.e_ehdr32 = NULL;
846		e->e_u.e_elf.e_phdr.e_phdr32 = NULL;
847	} else {
848		free(e->e_u.e_elf.e_ehdr.e_ehdr64);
849		if (e->e_u.e_elf.e_phdr.e_phdr64)
850			free(e->e_u.e_elf.e_phdr.e_phdr64);
851
852		e->e_u.e_elf.e_ehdr.e_ehdr64 = NULL;
853		e->e_u.e_elf.e_phdr.e_phdr64 = NULL;
854	}
855
856	return (rc);
857
858 error:
859	if (newfile)
860		free(newfile);
861	return ((off_t) -1);
862}
863
864off_t
865elf_update(Elf *e, Elf_Cmd c)
866{
867	int ec;
868	off_t rc;
869
870	rc = (off_t) -1;
871
872	if (e == NULL || e->e_kind != ELF_K_ELF ||
873	    (c != ELF_C_NULL && c != ELF_C_WRITE)) {
874		LIBELF_SET_ERROR(ARGUMENT, 0);
875		return (rc);
876	}
877
878	if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) {
879		LIBELF_SET_ERROR(CLASS, 0);
880		return (rc);
881	}
882
883	if (e->e_version == EV_NONE)
884		e->e_version = EV_CURRENT;
885
886	if (c == ELF_C_WRITE && e->e_cmd == ELF_C_READ) {
887		LIBELF_SET_ERROR(MODE, 0);
888		return (rc);
889	}
890
891	if ((rc = _libelf_resync_elf(e)) < 0)
892		return (rc);
893
894	if (c == ELF_C_NULL)
895		return (rc);
896
897	if (e->e_cmd == ELF_C_READ) {
898		/*
899		 * This descriptor was opened in read-only mode or by
900		 * elf_memory().
901		 */
902		if (e->e_fd)
903			LIBELF_SET_ERROR(MODE, 0);
904		else
905			LIBELF_SET_ERROR(ARGUMENT, 0);
906		return ((off_t) -1);
907	}
908
909	if (e->e_fd < 0) {
910		LIBELF_SET_ERROR(SEQUENCE, 0);
911		return ((off_t) -1);
912	}
913
914	return (_libelf_write_elf(e, rc));
915}
916