xref: /titanic_41/usr/src/cmd/sgs/libelf/common/update.c (revision 63360950109af2ce85a962ca61f40b8782f11100)
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 
101 static 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 
288 static 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 
396 static size_t
397 wrt(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 
652 off_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 
762 off_t
763 elf_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  */
784 Elf64_Off
785 _elf_getxoff(Elf_Data * d)
786 {
787 	return (((Dnode *)d)->db_xoff);
788 }
789 #endif /* !_ELF64 */
790