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