update.c revision 1682:79d68fa5aedd
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 *	Copyright (c) 1988 AT&T
24 *	  All Rights Reserved
25 *
26 *
27 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
28 * Use is subject to license terms.
29 */
30
31#pragma ident	"%Z%%M%	%I%	%E% SMI"
32
33#if !defined(_ELF64)
34#pragma weak elf_update = _elf_update
35#endif
36
37#include "syn.h"
38#include <memory.h>
39#include <malloc.h>
40#include <limits.h>
41
42#include <sgs.h>
43#include "decl.h"
44#include "msg.h"
45
46/*
47 * This module is compiled twice, the second time having
48 * -D_ELF64 defined.  The following set of macros, along
49 * with machelf.h, represent the differences between the
50 * two compilations.  Be careful *not* to add any class-
51 * dependent code (anything that has elf32 or elf64 in the
52 * name) to this code without hiding it behind a switch-
53 * able macro like these.
54 */
55#if	defined(_ELF64)
56
57#define	FSZ_LONG	ELF64_FSZ_XWORD
58#define	ELFCLASS	ELFCLASS64
59#define	_elf_snode_init	_elf64_snode_init
60#define	_elfxx_cookscn	_elf64_cookscn
61#define	_elf_upd_lib	_elf64_upd_lib
62#define	elf_fsize	elf64_fsize
63#define	_elf_entsz	_elf64_entsz
64#define	_elf_msize	_elf64_msize
65#define	_elf_upd_usr	_elf64_upd_usr
66#define	wrt		wrt64
67#define	elf_xlatetof	elf64_xlatetof
68#define	_elfxx_update	_elf64_update
69
70#else	/* ELF32 */
71
72#define	FSZ_LONG	ELF32_FSZ_WORD
73#define	ELFCLASS	ELFCLASS32
74#define	_elf_snode_init	_elf32_snode_init
75#define	_elfxx_cookscn	_elf32_cookscn
76#define	_elf_upd_lib	_elf32_upd_lib
77#define	elf_fsize	elf32_fsize
78#define	_elf_entsz	_elf32_entsz
79#define	_elf_msize	_elf32_msize
80#define	_elf_upd_usr	_elf32_upd_usr
81#define	wrt		wrt32
82#define	elf_xlatetof	elf32_xlatetof
83#define	_elfxx_update	_elf32_update
84
85#endif /* ELF64 */
86
87
88/*
89 * Output file update
90 *	These functions walk an Elf structure, update its information,
91 *	and optionally write the output file.  Because the application
92 *	may control of the output file layout, two upd_... routines
93 *	exist.  They're similar but too different to merge cleanly.
94 *
95 *	The library defines a "dirty" bit to force parts of the file
96 *	to be written on update.  These routines ignore the dirty bit
97 *	and do everything.  A minimal update routine might be useful
98 *	someday.
99 */
100
101static size_t
102_elf_upd_lib(Elf * elf)
103{
104	NOTE(ASSUMING_PROTECTED(*elf))
105	Lword		hi;
106	Lword		hibit;
107	Elf_Scn *	s;
108	register Xword	sz;
109	Ehdr *		eh = elf->ed_ehdr;
110	unsigned	ver = eh->e_version;
111	register char	*p = (char *)eh->e_ident;
112	size_t		scncnt;
113
114	/*
115	 * Ehdr and Phdr table go first
116	 */
117	p[EI_MAG0] = ELFMAG0;
118	p[EI_MAG1] = ELFMAG1;
119	p[EI_MAG2] = ELFMAG2;
120	p[EI_MAG3] = ELFMAG3;
121	p[EI_CLASS] = ELFCLASS;
122	/* LINTED */
123	p[EI_VERSION] = (Byte)ver;
124	hi = elf_fsize(ELF_T_EHDR, 1, ver);
125	/* LINTED */
126	eh->e_ehsize = (Half)hi;
127	if (eh->e_phnum != 0) {
128		/* LINTED */
129		eh->e_phentsize = (Half)elf_fsize(ELF_T_PHDR, 1, ver);
130		/* LINTED */
131		eh->e_phoff = (Off)hi;
132		hi += eh->e_phentsize * eh->e_phnum;
133	} else {
134		eh->e_phoff = 0;
135		eh->e_phentsize = 0;
136	}
137
138	/*
139	 * Obtain the first section header.  Typically, this section has NULL
140	 * contents, however in the case of Extended ELF Sections this section
141	 * is used to hold an alternative e_shnum, e_shstrndx and e_phnum.
142	 * On initial allocation (see _elf_snode) the elements of this section
143	 * would have been zeroed.  The e_shnum is initialized later, after the
144	 * section header count has been determined.  The e_shstrndx and
145	 * e_phnum may have already been initialized by the caller (for example,
146	 * gelf_update_shdr() in mcs(1)).
147	 */
148	if ((s = elf->ed_hdscn) == 0) {
149		eh->e_shnum = 0;
150		scncnt = 0;
151	} else {
152		s = s->s_next;
153		scncnt = 1;
154	}
155
156	/*
157	 * Loop through sections.  Compute section size before changing hi.
158	 * Allow null buffers for NOBITS.
159	 */
160	hibit = 0;
161	for (; s != 0; s = s->s_next) {
162		register Dnode	*d;
163		register Lword	fsz, j;
164		Shdr *sh = s->s_shdr;
165
166		scncnt++;
167		if (sh->sh_type == SHT_NULL) {
168			*sh = _elf_snode_init.sb_shdr;
169			continue;
170		}
171
172		if ((s->s_myflags & SF_READY) == 0)
173			(void) _elfxx_cookscn(s);
174
175		sh->sh_addralign = 1;
176		if ((sz = (Xword)_elf_entsz(sh->sh_type, ver)) != 0)
177			/* LINTED */
178			sh->sh_entsize = (Half)sz;
179		sz = 0;
180		for (d = s->s_hdnode; d != 0; d = d->db_next) {
181			if ((fsz = elf_fsize(d->db_data.d_type,
182			    1, ver)) == 0)
183				return (0);
184
185			j = _elf_msize(d->db_data.d_type, ver);
186			fsz *= (d->db_data.d_size / j);
187			d->db_osz = (size_t)fsz;
188			if ((j = d->db_data.d_align) > 1) {
189				if (j > sh->sh_addralign)
190					sh->sh_addralign = (Xword)j;
191
192				if (sz % j != 0)
193					sz += j - sz % j;
194			}
195			d->db_data.d_off = (off_t)sz;
196			d->db_xoff = sz;
197			sz += (Xword)fsz;
198		}
199
200		sh->sh_size = sz;
201		/*
202		 * We want to take into account the offsets for NOBITS
203		 * sections and let the "sh_offsets" point to where
204		 * the section would 'conceptually' fit within
205		 * the file (as required by the ABI).
206		 *
207		 * But - we must also make sure that the NOBITS does
208		 * not take up any actual space in the file.  We preserve
209		 * the actual offset into the file in the 'hibit' variable.
210		 * When we come to the first non-NOBITS section after a
211		 * encountering a NOBITS section the hi counter is restored
212		 * to its proper place in the file.
213		 */
214		if (sh->sh_type == SHT_NOBITS) {
215			if (hibit == 0)
216				hibit = hi;
217		} else {
218			if (hibit) {
219				hi = hibit;
220				hibit = 0;
221			}
222		}
223		j = sh->sh_addralign;
224		if ((fsz = hi % j) != 0)
225			hi += j - fsz;
226
227		/* LINTED */
228		sh->sh_offset = (Off)hi;
229		hi += sz;
230	}
231
232	/*
233	 * if last section was a 'NOBITS' section then we need to
234	 * restore the 'hi' counter to point to the end of the last
235	 * non 'NOBITS' section.
236	 */
237	if (hibit) {
238		hi = hibit;
239		hibit = 0;
240	}
241
242	/*
243	 * Shdr table last
244	 */
245	if (scncnt != 0) {
246		if (hi % FSZ_LONG != 0)
247			hi += FSZ_LONG - hi % FSZ_LONG;
248		/* LINTED */
249		eh->e_shoff = (Off)hi;
250		/*
251		 * If we are using 'extended sections' then the
252		 * e_shnum is stored in the sh_size field of the
253		 * first section header.
254		 *
255		 * NOTE: we set e_shnum to '0' because it's specified
256		 * this way in the gABI, and in the hopes that
257		 * this will cause less problems to unaware
258		 * tools then if we'd set it to SHN_XINDEX (0xffff).
259		 */
260		if (scncnt < SHN_LORESERVE)
261			eh->e_shnum = scncnt;
262		else {
263			Shdr	*sh;
264			sh = (Shdr *)elf->ed_hdscn->s_shdr;
265			sh->sh_size = scncnt;
266			eh->e_shnum = 0;
267		}
268		/* LINTED */
269		eh->e_shentsize = (Half)elf_fsize(ELF_T_SHDR, 1, ver);
270		hi += eh->e_shentsize * scncnt;
271	} else {
272		eh->e_shoff = 0;
273		eh->e_shentsize = 0;
274	}
275
276#if	!(defined(_LP64) && defined(_ELF64))
277	if (hi > INT_MAX) {
278		_elf_seterr(EFMT_FBIG, 0);
279		return (0);
280	}
281#endif
282
283	return ((size_t)hi);
284}
285
286
287
288static size_t
289_elf_upd_usr(Elf * elf)
290{
291	NOTE(ASSUMING_PROTECTED(*elf))
292	Lword		hi;
293	Elf_Scn *	s;
294	register Xword	sz;
295	Ehdr *		eh = elf->ed_ehdr;
296	unsigned	ver = eh->e_version;
297	register char	*p = (char *)eh->e_ident;
298
299
300	/*
301	 * Ehdr and Phdr table go first
302	 */
303	p[EI_MAG0] = ELFMAG0;
304	p[EI_MAG1] = ELFMAG1;
305	p[EI_MAG2] = ELFMAG2;
306	p[EI_MAG3] = ELFMAG3;
307	p[EI_CLASS] = ELFCLASS;
308	/* LINTED */
309	p[EI_VERSION] = (Byte)ver;
310	hi = elf_fsize(ELF_T_EHDR, 1, ver);
311	/* LINTED */
312	eh->e_ehsize = (Half)hi;
313
314	/*
315	 * If phnum is zero, phoff "should" be zero too,
316	 * but the application is responsible for it.
317	 * Allow a non-zero value here and update the
318	 * hi water mark accordingly.
319	 */
320
321	if (eh->e_phnum != 0)
322		/* LINTED */
323		eh->e_phentsize = (Half)elf_fsize(ELF_T_PHDR, 1, ver);
324	else
325		eh->e_phentsize = 0;
326	if ((sz = eh->e_phoff + eh->e_phentsize * eh->e_phnum) > hi)
327		hi = sz;
328
329	/*
330	 * Loop through sections, skipping index zero.
331	 * Compute section size before changing hi.
332	 * Allow null buffers for NOBITS.
333	 */
334
335	if ((s = elf->ed_hdscn) == 0)
336		eh->e_shnum = 0;
337	else {
338		eh->e_shnum = 1;
339		*(Shdr*)s->s_shdr = _elf_snode_init.sb_shdr;
340		s = s->s_next;
341	}
342	for (; s != 0; s = s->s_next) {
343		register Dnode	*d;
344		register Xword	fsz, j;
345		Shdr *sh = s->s_shdr;
346
347		if ((s->s_myflags & SF_READY) == 0)
348			(void) _elfxx_cookscn(s);
349
350		++eh->e_shnum;
351		sz = 0;
352		for (d = s->s_hdnode; d != 0; d = d->db_next) {
353			if ((fsz = (Xword)elf_fsize(d->db_data.d_type, 1,
354			    ver)) == 0)
355				return (0);
356			j = (Xword)_elf_msize(d->db_data.d_type, ver);
357			fsz *= (Xword)(d->db_data.d_size / j);
358			d->db_osz = (size_t)fsz;
359
360			if ((sh->sh_type != SHT_NOBITS) &&
361			((j = (Xword)(d->db_data.d_off + d->db_osz)) > sz))
362				sz = j;
363		}
364		if (sh->sh_size < sz) {
365			_elf_seterr(EFMT_SCNSZ, 0);
366			return (0);
367		}
368		if ((sh->sh_type != SHT_NOBITS) &&
369		    (hi < sh->sh_offset + sh->sh_size))
370			hi = sh->sh_offset + sh->sh_size;
371	}
372
373	/*
374	 * Shdr table last.  Comment above for phnum/phoff applies here.
375	 */
376	if (eh->e_shnum != 0)
377		/* LINTED */
378		eh->e_shentsize = (Half)elf_fsize(ELF_T_SHDR, 1, ver);
379	else
380		eh->e_shentsize = 0;
381
382	if ((sz = eh->e_shoff + eh->e_shentsize * eh->e_shnum) > hi)
383		hi = sz;
384
385#if	!(defined(_LP64) && defined(_ELF64))
386	if (hi > INT_MAX) {
387		_elf_seterr(EFMT_FBIG, 0);
388		return (0);
389	}
390#endif
391
392	return ((size_t)hi);
393}
394
395
396static size_t
397wrt(Elf * elf, Xword outsz, unsigned fill, int update_cmd)
398{
399	NOTE(ASSUMING_PROTECTED(*elf))
400	Elf_Data	dst, src;
401	unsigned	flag;
402	Xword		hi, sz;
403	char		*image;
404	Elf_Scn		*s;
405	Ehdr		*eh = elf->ed_ehdr;
406	unsigned	ver = eh->e_version;
407	unsigned	encode = eh->e_ident[EI_DATA];
408	int		byte;
409
410	/*
411	 * Two issues can cause trouble for the output file.
412	 * First, begin() with ELF_C_RDWR opens a file for both
413	 * read and write.  On the write update(), the library
414	 * has to read everything it needs before truncating
415	 * the file.  Second, using mmap for both read and write
416	 * is too tricky.  Consequently, the library disables mmap
417	 * on the read side.  Using mmap for the output saves swap
418	 * space, because that mapping is SHARED, not PRIVATE.
419	 *
420	 * If the file is write-only, there can be nothing of
421	 * interest to bother with.
422	 *
423	 * The following reads the entire file, which might be
424	 * more than necessary.  Better safe than sorry.
425	 */
426
427	if ((elf->ed_myflags & EDF_READ) &&
428	    (_elf_vm(elf, (size_t)0, elf->ed_fsz) != OK_YES))
429		return (0);
430
431	flag = elf->ed_myflags & EDF_WRALLOC;
432	if ((image = _elf_outmap(elf->ed_fd, outsz, &flag)) == 0)
433		return (0);
434
435	if (flag == 0)
436		elf->ed_myflags |= EDF_IMALLOC;
437
438	/*
439	 * If an error occurs below, a "dirty" bit may be cleared
440	 * improperly.  To save a second pass through the file,
441	 * this code sets the dirty bit on the elf descriptor
442	 * when an error happens, assuming that will "cover" any
443	 * accidents.
444	 */
445
446	/*
447	 * Hi is needed only when 'fill' is non-zero.
448	 * Fill is non-zero only when the library
449	 * calculates file/section/data buffer offsets.
450	 * The lib guarantees they increase monotonically.
451	 * That guarantees proper filling below.
452	 */
453
454
455	/*
456	 * Ehdr first
457	 */
458
459	src.d_buf = (Elf_Void *)eh;
460	src.d_type = ELF_T_EHDR;
461	src.d_size = sizeof (Ehdr);
462	src.d_version = EV_CURRENT;
463	dst.d_buf = (Elf_Void *)image;
464	dst.d_size = eh->e_ehsize;
465	dst.d_version = ver;
466	if (elf_xlatetof(&dst, &src, encode) == 0)
467		return (0);
468	elf->ed_ehflags &= ~ELF_F_DIRTY;
469	hi = eh->e_ehsize;
470
471	/*
472	 * Phdr table if one exists
473	 */
474
475	if (eh->e_phnum != 0) {
476		unsigned	work;
477		/*
478		 * Unlike other library data, phdr table is
479		 * in the user version.  Change src buffer
480		 * version here, fix it after translation.
481		 */
482
483		src.d_buf = (Elf_Void *)elf->ed_phdr;
484		src.d_type = ELF_T_PHDR;
485		src.d_size = elf->ed_phdrsz;
486		ELFACCESSDATA(work, _elf_work)
487		src.d_version = work;
488		dst.d_buf = (Elf_Void *)(image + eh->e_phoff);
489		dst.d_size = eh->e_phnum * eh->e_phentsize;
490		hi = (Xword)(eh->e_phoff + dst.d_size);
491		if (elf_xlatetof(&dst, &src, encode) == 0) {
492			elf->ed_uflags |= ELF_F_DIRTY;
493			return (0);
494		}
495		elf->ed_phflags &= ~ELF_F_DIRTY;
496		src.d_version = EV_CURRENT;
497	}
498
499	/*
500	 * Loop through sections
501	 */
502
503	ELFACCESSDATA(byte, _elf_byte);
504	for (s = elf->ed_hdscn; s != 0; s = s->s_next) {
505		register Dnode	*d, *prevd;
506		Xword		off = 0;
507		Shdr		*sh = s->s_shdr;
508		char		*start = image + sh->sh_offset;
509		char		*here;
510
511		/*
512		 * Just "clean" DIRTY flag for "empty" sections.  Even if
513		 * NOBITS needs padding, the next thing in the
514		 * file will provide it.  (And if this NOBITS is
515		 * the last thing in the file, no padding needed.)
516		 */
517		if ((sh->sh_type == SHT_NOBITS) ||
518		    (sh->sh_type == SHT_NULL)) {
519			d = s->s_hdnode, prevd = 0;
520			for (; d != 0; prevd = d, d = d->db_next)
521				d->db_uflags &= ~ELF_F_DIRTY;
522			continue;
523		}
524		/*
525		 * Clear out the memory between the end of the last
526		 * section and the begining of this section.
527		 */
528		if (fill && (sh->sh_offset > hi)) {
529			sz = sh->sh_offset - hi;
530			(void) memset(start - sz, byte, sz);
531		}
532
533
534		for (d = s->s_hdnode, prevd = 0;
535		    d != 0; prevd = d, d = d->db_next) {
536			d->db_uflags &= ~ELF_F_DIRTY;
537			here = start + d->db_data.d_off;
538
539			/*
540			 * Clear out the memory between the end of the
541			 * last update and the start of this data buffer.
542			 */
543			if (fill && (d->db_data.d_off > off)) {
544				sz = (Xword)(d->db_data.d_off - off);
545				(void) memset(here - sz, byte, sz);
546			}
547
548			if ((d->db_myflags & DBF_READY) == 0) {
549				SCNLOCK(s);
550				if (_elf_locked_getdata(s, &prevd->db_data) !=
551				    &d->db_data) {
552					elf->ed_uflags |= ELF_F_DIRTY;
553					SCNUNLOCK(s);
554					return (0);
555				}
556				SCNUNLOCK(s);
557			}
558			dst.d_buf = (Elf_Void *)here;
559			dst.d_size = d->db_osz;
560
561			/*
562			 * Copy the translated bits out to the destination
563			 * image.
564			 */
565			if (elf_xlatetof(&dst, &d->db_data, encode) == 0) {
566				elf->ed_uflags |= ELF_F_DIRTY;
567				return (0);
568			}
569
570			off = (Xword)(d->db_data.d_off + dst.d_size);
571		}
572		hi = sh->sh_offset + sh->sh_size;
573	}
574
575	/*
576	 * Shdr table last
577	 */
578
579	if (fill && (eh->e_shoff > hi)) {
580		sz = eh->e_shoff - hi;
581		(void) memset(image + hi, byte, sz);
582	}
583
584	src.d_type = ELF_T_SHDR;
585	src.d_size = sizeof (Shdr);
586	dst.d_buf = (Elf_Void *)(image + eh->e_shoff);
587	dst.d_size = eh->e_shentsize;
588	for (s = elf->ed_hdscn; s != 0; s = s->s_next) {
589		assert((uintptr_t)dst.d_buf < ((uintptr_t)image + outsz));
590		s->s_shflags &= ~ELF_F_DIRTY;
591		s->s_uflags &= ~ELF_F_DIRTY;
592		src.d_buf = s->s_shdr;
593
594		if (elf_xlatetof(&dst, &src, encode) == 0) {
595			elf->ed_uflags |= ELF_F_DIRTY;
596			return (0);
597		}
598
599		dst.d_buf = (char *)dst.d_buf + eh->e_shentsize;
600	}
601	/*
602	 * ELF_C_WRIMAGE signifyes that we build the memory image, but
603	 * that we do not actually write it to disk.  This is used
604	 * by ld(1) to build up a full image of an elf file and then
605	 * to process the file before it's actually written out to
606	 * disk.  This saves ld(1) the overhead of having to write
607	 * the image out to disk twice.
608	 */
609	if (update_cmd == ELF_C_WRIMAGE) {
610		elf->ed_uflags &= ~ELF_F_DIRTY;
611		elf->ed_wrimage = image;
612		elf->ed_wrimagesz = outsz;
613		return (outsz);
614	}
615
616	if (_elf_outsync(elf->ed_fd, image, outsz,
617	    ((elf->ed_myflags & EDF_IMALLOC) ? 0 : 1)) != 0) {
618		elf->ed_uflags &= ~ELF_F_DIRTY;
619		elf->ed_myflags &= ~EDF_IMALLOC;
620		return (outsz);
621	}
622
623	elf->ed_uflags |= ELF_F_DIRTY;
624	return (0);
625}
626
627
628
629
630/*
631 * The following is a private interface between the linkers (ld & ld.so.1)
632 * and libelf:
633 *
634 * elf_update(elf, ELF_C_WRIMAGE)
635 *	This will cause full image representing the elf file
636 *	described by the elf pointer to be built in memory.  If the
637 *	elf pointer has a valid file descriptor associated with it
638 *	we will attempt to build the memory image from mmap()'ed
639 *	storage.  If the elf descriptor does not have a valid
640 *	file descriptor (opened with elf_begin(0, ELF_C_IMAGE, 0))
641 *	then the image will be allocated from dynamic memory (malloc()).
642 *
643 *	elf_update() will return the size of the memory image built
644 *	when sucessful.
645 *
646 *	When a subsequent call to elf_update() with ELF_C_WRITE as
647 *	the command is performed it will sync the image created
648 *	by ELF_C_WRIMAGE to disk (if fd available) and
649 *	free the memory allocated.
650 */
651
652off_t
653_elfxx_update(Elf * elf, Elf_Cmd cmd)
654{
655	size_t		sz;
656	unsigned	u;
657	Ehdr		*eh = elf->ed_ehdr;
658
659	if (elf == 0)
660		return (-1);
661
662	ELFWLOCK(elf)
663	switch (cmd) {
664	default:
665		_elf_seterr(EREQ_UPDATE, 0);
666		ELFUNLOCK(elf)
667		return (-1);
668
669	case ELF_C_WRIMAGE:
670		if ((elf->ed_myflags & EDF_WRITE) == 0) {
671			_elf_seterr(EREQ_UPDWRT, 0);
672			ELFUNLOCK(elf)
673			return (-1);
674		}
675		break;
676	case ELF_C_WRITE:
677		if ((elf->ed_myflags & EDF_WRITE) == 0) {
678			_elf_seterr(EREQ_UPDWRT, 0);
679			ELFUNLOCK(elf)
680			return (-1);
681		}
682		if (elf->ed_wrimage) {
683			if (elf->ed_myflags & EDF_WRALLOC) {
684				free(elf->ed_wrimage);
685				/*
686				 * The size is still returned even
687				 * though nothing is actually written
688				 * out.  This is just to be consistant
689				 * with the rest of the interface.
690				 */
691				sz = elf->ed_wrimagesz;
692				elf->ed_wrimage = 0;
693				elf->ed_wrimagesz = 0;
694				ELFUNLOCK(elf);
695				return ((off_t)sz);
696			}
697			sz = _elf_outsync(elf->ed_fd, elf->ed_wrimage,
698				elf->ed_wrimagesz,
699				(elf->ed_myflags & EDF_IMALLOC ? 0 : 1));
700			elf->ed_myflags &= ~EDF_IMALLOC;
701			elf->ed_wrimage = 0;
702			elf->ed_wrimagesz = 0;
703			ELFUNLOCK(elf);
704			return ((off_t)sz);
705		}
706		/* FALLTHROUGH */
707	case ELF_C_NULL:
708		break;
709	}
710
711	if (eh == 0) {
712		_elf_seterr(ESEQ_EHDR, 0);
713		ELFUNLOCK(elf)
714		return (-1);
715	}
716
717	if ((u = eh->e_version) > EV_CURRENT) {
718		_elf_seterr(EREQ_VER, 0);
719		ELFUNLOCK(elf)
720		return (-1);
721	}
722
723	if (u == EV_NONE)
724		eh->e_version = EV_CURRENT;
725
726	if ((u = eh->e_ident[EI_DATA]) == ELFDATANONE) {
727		unsigned	encode;
728
729		ELFACCESSDATA(encode, _elf_encode)
730		if (encode == ELFDATANONE) {
731			_elf_seterr(EREQ_ENCODE, 0);
732			ELFUNLOCK(elf)
733			return (-1);
734		}
735		/* LINTED */
736		eh->e_ident[EI_DATA] = (Byte)encode;
737	}
738
739	u = 1;
740	if (elf->ed_uflags & ELF_F_LAYOUT) {
741		sz = _elf_upd_usr(elf);
742		u = 0;
743	} else
744		sz = _elf_upd_lib(elf);
745
746	if ((sz != 0) && ((cmd == ELF_C_WRITE) || (cmd == ELF_C_WRIMAGE)))
747		sz = wrt(elf, (Xword)sz, u, cmd);
748
749	if (sz == 0) {
750		ELFUNLOCK(elf)
751		return (-1);
752	}
753
754	ELFUNLOCK(elf)
755	return ((off_t)sz);
756}
757
758
759#ifndef _ELF64
760/* class-independent, only needs to be compiled once */
761
762off_t
763elf_update(Elf *elf, Elf_Cmd cmd)
764{
765	if (elf == 0)
766		return (-1);
767
768	if (elf->ed_class == ELFCLASS32)
769		return (_elf32_update(elf, cmd));
770	else if (elf->ed_class == ELFCLASS64) {
771		return (_elf64_update(elf, cmd));
772	}
773
774	_elf_seterr(EREQ_CLASS, 0);
775	return (-1);
776}
777
778/*
779 * 4106312, 4106398, This is an ad-hoc means for the 32-bit
780 * Elf64 version of libld.so.3 to get around the limitation
781 * of a 32-bit d_off field.  This is only intended to be
782 * used by libld to relocate symbols in large NOBITS sections.
783 */
784Elf64_Off
785_elf_getxoff(Elf_Data * d)
786{
787	return (((Dnode *)d)->db_xoff);
788}
789#endif /* !_ELF64 */
790