1d29b2c44Sab /*
2d29b2c44Sab  * CDDL HEADER START
3d29b2c44Sab  *
4d29b2c44Sab  * The contents of this file are subject to the terms of the
5d29b2c44Sab  * Common Development and Distribution License (the "License").
6d29b2c44Sab  * You may not use this file except in compliance with the License.
7d29b2c44Sab  *
8d29b2c44Sab  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d29b2c44Sab  * or http://www.opensolaris.org/os/licensing.
10d29b2c44Sab  * See the License for the specific language governing permissions
11d29b2c44Sab  * and limitations under the License.
12d29b2c44Sab  *
13d29b2c44Sab  * When distributing Covered Code, include this CDDL HEADER in each
14d29b2c44Sab  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d29b2c44Sab  * If applicable, add the following below this CDDL HEADER, with the
16d29b2c44Sab  * fields enclosed by brackets "[]" replaced with your own identifying
17d29b2c44Sab  * information: Portions Copyright [yyyy] [name of copyright owner]
18d29b2c44Sab  *
19d29b2c44Sab  * CDDL HEADER END
20d29b2c44Sab  */
21d29b2c44Sab 
22d29b2c44Sab /*
23*ba2be530Sab  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24d29b2c44Sab  * Use is subject to license terms.
25d29b2c44Sab  */
26d29b2c44Sab #pragma ident	"%Z%%M%	%I%	%E% SMI"
27d29b2c44Sab 
28d29b2c44Sab /*
29d29b2c44Sab  * ELFCLASS specific code for elfedit, built once for each class
30d29b2c44Sab  */
31d29b2c44Sab #include	<stdlib.h>
32d29b2c44Sab #include	<stdio.h>
33d29b2c44Sab #include	<unistd.h>
34*ba2be530Sab #include	<_machelf.h>
35d29b2c44Sab #include	<libelf.h>
36d29b2c44Sab #include	<strings.h>
37d29b2c44Sab #include	<sgs.h>
38d29b2c44Sab #include	"msg.h"
39d29b2c44Sab #include	"_elfedit.h"
40d29b2c44Sab 
41d29b2c44Sab 
42d29b2c44Sab 
43d29b2c44Sab /*
44d29b2c44Sab  * Look up the elfedit_symtab_t that corresponds to the symbol table
45d29b2c44Sab  * referenced by the sh_link field of the given auxiliary section.
46d29b2c44Sab  *
47d29b2c44Sab  * entry:
48d29b2c44Sab  *	obj_state - Partially constructed object state from
49d29b2c44Sab  *		elfedit_init_obj_state().
50d29b2c44Sab  *	auxsec - Section that is associated with the symbol table section
51d29b2c44Sab  *
52d29b2c44Sab  * exit:
53d29b2c44Sab  *	Returns the pointer to the elfedit_symtab_t entry that is
54d29b2c44Sab  *	referenced by the auxiliary section. If not found,
55d29b2c44Sab  *	outputs a debug message, and returns NULL.
56d29b2c44Sab  */
57d29b2c44Sab static elfedit_symtab_t *
58d29b2c44Sab get_symtab(elfedit_obj_state_t *obj_state, elfedit_section_t *auxsec)
59d29b2c44Sab {
60d29b2c44Sab 	elfedit_symtab_t *symtab = obj_state->os_symtab;
61d29b2c44Sab 	Word	sh_link = auxsec->sec_shdr->sh_link;
62d29b2c44Sab 	Word	i;
63d29b2c44Sab 
64d29b2c44Sab 	for (i = 0; i < obj_state->os_symtabnum; i++, symtab++)
65d29b2c44Sab 		if (symtab->symt_shndx == sh_link)
66d29b2c44Sab 			return (symtab);
67d29b2c44Sab 
68d29b2c44Sab 	/*
69d29b2c44Sab 	 * If we don't return above, it doesn't reference a valid
70d29b2c44Sab 	 * symbol table. Issue warning.
71d29b2c44Sab 	 */
72d29b2c44Sab 	elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_AUX_LINK),
73d29b2c44Sab 	    EC_WORD(auxsec->sec_shndx), auxsec->sec_name,
74d29b2c44Sab 	    EC_WORD(sh_link));
75d29b2c44Sab 
76d29b2c44Sab 	return (NULL);
77d29b2c44Sab }
78d29b2c44Sab 
79d29b2c44Sab 
80d29b2c44Sab /*
81d29b2c44Sab  * Fill in state.elf.obj_state with a a dynamically allocated
82d29b2c44Sab  * elfedit_obj_state_t struct of the appropriate ELFCLASS.
83d29b2c44Sab  * This pre-chewed form is fed to each command, reducing the amount
84d29b2c44Sab  * of ELF boilerplate code each command needs to contain.
85d29b2c44Sab  *
86d29b2c44Sab  * entry:
87d29b2c44Sab  *	file - Name of file to process
88d29b2c44Sab  *	fd - Descriptor of open file which has been successfully
89d29b2c44Sab  *		processed by elf_begin().
90d29b2c44Sab  *	elf - Elf handle returned by elf_begin
91d29b2c44Sab  *
92d29b2c44Sab  * exit:
93d29b2c44Sab  *	An elfedit_obj_state_t struct of the appropriate ELFCLASS has
94d29b2c44Sab  *	been dynamically allocated, and state.elf.obj_state references it.
95d29b2c44Sab  *	On failure, this routine does not return to the caller.
96d29b2c44Sab  *
97d29b2c44Sab  * note: The resulting elfedit_obj_state_t is allocated from a single
98d29b2c44Sab  *	piece of memory, such that a single call to free() suffices
99d29b2c44Sab  *	to release it as well as any memory it references.
100d29b2c44Sab  */
101d29b2c44Sab #ifdef _ELF64
102d29b2c44Sab void
103d29b2c44Sab elfedit64_init_obj_state(const char *file, int fd, Elf *elf)
104d29b2c44Sab #else
105d29b2c44Sab void
106d29b2c44Sab elfedit32_init_obj_state(const char *file, int fd, Elf *elf)
107d29b2c44Sab #endif
108d29b2c44Sab {
109d29b2c44Sab #define	INITIAL_SYMTABNDX_ALLOC	5
110d29b2c44Sab 
111d29b2c44Sab 	/*
112d29b2c44Sab 	 * This macro is used to call functions from libelf, all of which
113d29b2c44Sab 	 * return NULL for failure and something else for success. On error,
114d29b2c44Sab 	 * libelf_fail_name is set and execution jumps to the libelf_failure
115d29b2c44Sab 	 * label for handling. Otherwise, the results of the call are ready
116d29b2c44Sab 	 * for use by the caller.
117d29b2c44Sab 	 */
118d29b2c44Sab #define	LIBELF(_libelf_expr, _name) \
119d29b2c44Sab 	if ((_libelf_expr) == NULL) { \
120d29b2c44Sab 		libelf_fail_name = _name; \
121d29b2c44Sab 		goto libelf_failure; \
122d29b2c44Sab 	}
123d29b2c44Sab 
124d29b2c44Sab 	const char *libelf_fail_name;	/* Used for LIBELF errors */
125d29b2c44Sab 
126d29b2c44Sab 	Elf_Scn			*scn;
127d29b2c44Sab 	Elf_Data		*data;
128d29b2c44Sab 	uint_t			ndx;
129d29b2c44Sab 	size_t			len, os_size, secarr_size;
130d29b2c44Sab 	char			*names = 0;
131d29b2c44Sab 	size_t			names_len;
132d29b2c44Sab 	elfedit_section_t	*_cache;
133d29b2c44Sab 	elfedit_obj_state_t	tstate;
134d29b2c44Sab 	elfedit_obj_state_t	*obj_state = NULL;
135d29b2c44Sab 	Word			*symtabndx = NULL;
136d29b2c44Sab 	Word			symtabndx_size = 0;
137d29b2c44Sab 	elfedit_symtab_t	*symtab;
138d29b2c44Sab 
139d29b2c44Sab 	tstate.os_file = file;
140d29b2c44Sab 	tstate.os_fd = fd;
141d29b2c44Sab 	tstate.os_elf = elf;
142d29b2c44Sab 	tstate.os_dynndx = SHN_UNDEF;
143d29b2c44Sab 	tstate.os_symtabnum = 0;
144d29b2c44Sab 
145d29b2c44Sab 	LIBELF(tstate.os_ehdr = elf_getehdr(tstate.os_elf),
146d29b2c44Sab 	    MSG_ORIG(MSG_ELF_GETEHDR))
147d29b2c44Sab 
148d29b2c44Sab 	/* Program header array count and address */
149d29b2c44Sab 	LIBELF(elf_getphnum(tstate.os_elf, &tstate.os_phnum),
150d29b2c44Sab 	    MSG_ORIG(MSG_ELF_GETPHNUM))
151d29b2c44Sab 	if (tstate.os_phnum > 0) {
152d29b2c44Sab 		LIBELF((tstate.os_phdr = elf_getphdr(tstate.os_elf)),
153d29b2c44Sab 		    MSG_ORIG(MSG_ELF_GETPHDR))
154d29b2c44Sab 	} else {
155d29b2c44Sab 		tstate.os_phdr = NULL;
156d29b2c44Sab 	}
157d29b2c44Sab 
158d29b2c44Sab 
159d29b2c44Sab 	LIBELF(elf_getshnum(tstate.os_elf, &tstate.os_shnum),
160d29b2c44Sab 	    MSG_ORIG(MSG_ELF_GETSHNUM))
161d29b2c44Sab 
162d29b2c44Sab 
163d29b2c44Sab 	/*
164d29b2c44Sab 	 * Obtain the .shstrtab data buffer to provide the required section
165d29b2c44Sab 	 * name strings.
166d29b2c44Sab 	 */
167d29b2c44Sab 	LIBELF(elf_getshstrndx(tstate.os_elf, &tstate.os_shstrndx),
168d29b2c44Sab 	    MSG_ORIG(MSG_ELF_GETSHSTRNDX))
169d29b2c44Sab 	LIBELF((scn = elf_getscn(tstate.os_elf, tstate.os_shstrndx)),
170d29b2c44Sab 	    MSG_ORIG(MSG_ELF_GETSCN))
171d29b2c44Sab 	LIBELF((data = elf_getdata(scn, NULL)), MSG_ORIG(MSG_ELF_GETDATA))
172d29b2c44Sab 	names = data->d_buf;
173d29b2c44Sab 	names_len = (names == NULL) ? 0 : data->d_size;
174d29b2c44Sab 
175d29b2c44Sab 	/*
176d29b2c44Sab 	 * Count the number of symbol tables and capture their indexes.
177d29b2c44Sab 	 * Find the dynamic section.
178d29b2c44Sab 	 */
179d29b2c44Sab 	for (ndx = 1, scn = NULL; scn = elf_nextscn(tstate.os_elf, scn);
180d29b2c44Sab 	    ndx++) {
181d29b2c44Sab 		Shdr *shdr;
182d29b2c44Sab 
183d29b2c44Sab 		LIBELF(shdr = elf_getshdr(scn), MSG_ORIG(MSG_ELF_GETSHDR));
184d29b2c44Sab 
185d29b2c44Sab 		switch (shdr->sh_type) {
186d29b2c44Sab 		case SHT_DYNAMIC:
187d29b2c44Sab 			/* Save index of dynamic section for use below */
188d29b2c44Sab 			tstate.os_dynndx = ndx;
189d29b2c44Sab 			break;
190d29b2c44Sab 
191d29b2c44Sab 		case SHT_SYMTAB:
192d29b2c44Sab 		case SHT_DYNSYM:
193d29b2c44Sab 		case SHT_SUNW_LDYNSYM:
194d29b2c44Sab 			if (symtabndx_size <= tstate.os_symtabnum) {
195d29b2c44Sab 				symtabndx_size = (symtabndx_size == 0) ?
196d29b2c44Sab 				    INITIAL_SYMTABNDX_ALLOC :
197d29b2c44Sab 				    (symtabndx_size * 2);
198d29b2c44Sab 				symtabndx = elfedit_realloc(
199d29b2c44Sab 				    MSG_INTL(MSG_ALLOC_SYMTABOS), symtabndx,
200d29b2c44Sab 				    symtabndx_size * sizeof (symtabndx[0]));
201d29b2c44Sab 			}
202d29b2c44Sab 			symtabndx[tstate.os_symtabnum++] = ndx;
203d29b2c44Sab 			break;
204d29b2c44Sab 		}
205d29b2c44Sab 	}
206d29b2c44Sab 
207d29b2c44Sab 	/*
208d29b2c44Sab 	 * Allocate space to hold the state. We allocate space for everything
209d29b2c44Sab 	 * in one chunk to make releasing it easy:
210d29b2c44Sab 	 *	(1) elfedit_obj_state_t struct
211d29b2c44Sab 	 *	(2) The array of elfedit_section_t items referenced from
212d29b2c44Sab 	 *		the elfedit_obj_state_t struct.
213d29b2c44Sab 	 *	(3) The array of elfedit_symtab_t items referenced from
214d29b2c44Sab 	 *		the elfedit_obj_state_t struct.
215d29b2c44Sab 	 *	(4) The file name.
216d29b2c44Sab 	 *
217d29b2c44Sab 	 * Note that we round up the size of (1) and (2) to a double boundary
218d29b2c44Sab 	 * to ensure proper alignment of (2) and (3). (4) can align on any
219d29b2c44Sab 	 * boundary.
220d29b2c44Sab 	 */
221d29b2c44Sab 	os_size = S_DROUND(sizeof (tstate));
222d29b2c44Sab 	secarr_size = (tstate.os_shnum * sizeof (elfedit_section_t));
223d29b2c44Sab 	secarr_size = S_DROUND(secarr_size);
224d29b2c44Sab 	len = strlen(tstate.os_file) + 1;
225d29b2c44Sab 	obj_state = elfedit_malloc(MSG_INTL(MSG_ALLOC_OBJSTATE),
226d29b2c44Sab 	    os_size + secarr_size +
227d29b2c44Sab 	    (tstate.os_symtabnum * sizeof (elfedit_symtab_t)) + len);
228d29b2c44Sab 	*obj_state = tstate;
229d29b2c44Sab 
230d29b2c44Sab 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
231d29b2c44Sab 	obj_state->os_secarr = (elfedit_section_t *)
232d29b2c44Sab 	    ((char *)obj_state + os_size);
233d29b2c44Sab 	if (obj_state->os_symtabnum == 0)
234d29b2c44Sab 		obj_state->os_symtab = NULL;
235d29b2c44Sab 	else
236d29b2c44Sab 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
237d29b2c44Sab 		obj_state->os_symtab = (elfedit_symtab_t *)
238d29b2c44Sab 		    ((char *)obj_state->os_secarr + secarr_size);
239d29b2c44Sab 	obj_state->os_file =
240d29b2c44Sab 	    (char *)(obj_state->os_symtab + tstate.os_symtabnum);
241d29b2c44Sab 	(void) strncpy((char *)obj_state->os_file, tstate.os_file, len);
242d29b2c44Sab 
243d29b2c44Sab 	/*
244d29b2c44Sab 	 * Fill in obj_state->os_secarr with information for each section.
245d29b2c44Sab 	 * At the same time, fill in obj_state->os_symtab with the symbol
246d29b2c44Sab 	 * table related data.
247d29b2c44Sab 	 */
248d29b2c44Sab 	bzero(obj_state->os_secarr, sizeof (obj_state->os_secarr[0]));
249d29b2c44Sab 	_cache = obj_state->os_secarr;
250d29b2c44Sab 	LIBELF(scn = elf_getscn(tstate.os_elf, 0),
251d29b2c44Sab 	    MSG_ORIG(MSG_ELF_GETSCN));
252d29b2c44Sab 	_cache->sec_scn = scn;
253d29b2c44Sab 	LIBELF(_cache->sec_shdr = elf_getshdr(scn), MSG_ORIG(MSG_ELF_GETSHDR));
254d29b2c44Sab 	_cache->sec_name = (_cache->sec_shdr->sh_name < names_len) ?
255d29b2c44Sab 	    (names + _cache->sec_shdr->sh_name) : MSG_INTL(MSG_UNKNOWNSECNAM);
256d29b2c44Sab 	_cache++;
257d29b2c44Sab 
258d29b2c44Sab 	if (obj_state->os_symtab != NULL) {
259d29b2c44Sab 		bzero(obj_state->os_symtab,
260d29b2c44Sab 		    sizeof (obj_state->os_symtab[0]) * obj_state->os_symtabnum);
261d29b2c44Sab 		for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++)
262d29b2c44Sab 			obj_state->os_symtab[ndx].symt_shndx = symtabndx[ndx];
263d29b2c44Sab 		free(symtabndx);
264d29b2c44Sab 	}
265d29b2c44Sab 
266d29b2c44Sab 	for (ndx = 1, scn = NULL; scn = elf_nextscn(tstate.os_elf, scn);
267d29b2c44Sab 	    ndx++, _cache++) {
268d29b2c44Sab 		_cache->sec_shndx = ndx;
269d29b2c44Sab 		_cache->sec_scn = scn;
270d29b2c44Sab 		LIBELF(_cache->sec_shdr = elf_getshdr(scn),
271d29b2c44Sab 		    MSG_ORIG(MSG_ELF_GETSHDR))
272d29b2c44Sab 		_cache->sec_data = elf_getdata(scn, NULL);
273d29b2c44Sab 		_cache->sec_name = (_cache->sec_shdr->sh_name < names_len) ?
274d29b2c44Sab 		    (names + _cache->sec_shdr->sh_name) :
275d29b2c44Sab 		    MSG_INTL(MSG_UNKNOWNSECNAM);
276d29b2c44Sab 
277d29b2c44Sab 		switch (_cache->sec_shdr->sh_type) {
278d29b2c44Sab 		case SHT_SYMTAB_SHNDX:
279d29b2c44Sab 			symtab = get_symtab(obj_state, _cache);
280d29b2c44Sab 			symtab->symt_xshndx = ndx;
281d29b2c44Sab 			break;
282d29b2c44Sab 
283d29b2c44Sab 		case SHT_SUNW_syminfo:
284d29b2c44Sab 			symtab = get_symtab(obj_state, _cache);
285d29b2c44Sab 			symtab->symt_syminfo = ndx;
286d29b2c44Sab 			break;
287d29b2c44Sab 
288d29b2c44Sab 		case SHT_SUNW_versym:
289d29b2c44Sab 			symtab = get_symtab(obj_state, _cache);
290d29b2c44Sab 			symtab->symt_versym = ndx;
291d29b2c44Sab 			break;
292d29b2c44Sab 		}
293d29b2c44Sab 	}
294d29b2c44Sab 
295d29b2c44Sab 	/*
296d29b2c44Sab 	 * Sanity check the symbol tables, and discard any auxiliary
297d29b2c44Sab 	 * sections without enough elements.
298d29b2c44Sab 	 */
299d29b2c44Sab 	symtab = obj_state->os_symtab;
300d29b2c44Sab 	for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) {
301d29b2c44Sab 		elfedit_section_t	*symsec;
302d29b2c44Sab 		Word			symsec_cnt, aux_cnt;
303d29b2c44Sab 
304d29b2c44Sab 		symsec = &obj_state->os_secarr[symtab->symt_shndx];
305d29b2c44Sab 		symsec_cnt = symsec->sec_shdr->sh_size / sizeof (Sym);
306d29b2c44Sab 
307d29b2c44Sab 		/* Extended section indexes */
308d29b2c44Sab 		if (symtab->symt_xshndx != SHN_UNDEF) {
309d29b2c44Sab 			_cache = &obj_state->os_secarr[symtab->symt_xshndx];
310d29b2c44Sab 			aux_cnt = _cache->sec_shdr->sh_size / sizeof (Word);
311d29b2c44Sab 			if (symsec_cnt > aux_cnt)
312d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
313d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_AUX_SIZE),
314d29b2c44Sab 				    EC_WORD(ndx), _cache->sec_name,
315d29b2c44Sab 				    EC_WORD(aux_cnt),
316d29b2c44Sab 				    EC_WORD(symsec->sec_shndx),
317d29b2c44Sab 				    symsec->sec_name, EC_WORD(aux_cnt));
318d29b2c44Sab 		}
319d29b2c44Sab 
320d29b2c44Sab 		/* Syminfo */
321d29b2c44Sab 		if (symtab->symt_syminfo != SHN_UNDEF) {
322d29b2c44Sab 			_cache = &obj_state->os_secarr[symtab->symt_syminfo];
323d29b2c44Sab 			aux_cnt = _cache->sec_shdr->sh_size / sizeof (Syminfo);
324d29b2c44Sab 			if (symsec_cnt > aux_cnt)
325d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
326d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_AUX_SIZE),
327d29b2c44Sab 				    EC_WORD(ndx), _cache->sec_name,
328d29b2c44Sab 				    EC_WORD(aux_cnt),
329d29b2c44Sab 				    EC_WORD(symsec->sec_shndx),
330d29b2c44Sab 				    symsec->sec_name, EC_WORD(aux_cnt));
331d29b2c44Sab 		}
332d29b2c44Sab 
333d29b2c44Sab 		/* Versym */
334d29b2c44Sab 		if (symtab->symt_versym != SHN_UNDEF) {
335d29b2c44Sab 			_cache = &obj_state->os_secarr[symtab->symt_versym];
336d29b2c44Sab 			aux_cnt = _cache->sec_shdr->sh_size / sizeof (Versym);
337d29b2c44Sab 			if (symsec_cnt > aux_cnt)
338d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
339d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_AUX_SIZE),
340d29b2c44Sab 				    EC_WORD(ndx), _cache->sec_name,
341d29b2c44Sab 				    EC_WORD(aux_cnt),
342d29b2c44Sab 				    EC_WORD(symsec->sec_shndx),
343d29b2c44Sab 				    symsec->sec_name, EC_WORD(aux_cnt));
344d29b2c44Sab 		}
345d29b2c44Sab 	}
346d29b2c44Sab 
347d29b2c44Sab 	/*
348d29b2c44Sab 	 * If this object has a dynsym section with a FLAGS_1 field,
349d29b2c44Sab 	 * then set the DF_1_EDITED bit. elfedit allows changes that
350d29b2c44Sab 	 * can break the resulting program, so knowing that a file was
351d29b2c44Sab 	 * edited can be helpful when encountering a core file or other
352d29b2c44Sab 	 * unexpected failure in the field. A single bit can't tell you
353d29b2c44Sab 	 * what was changed, but it will alert you to the possibility that
354d29b2c44Sab 	 * some additional questions might be in order.
355d29b2c44Sab 	 */
356d29b2c44Sab 	if (obj_state->os_dynndx != SHN_UNDEF) {
357d29b2c44Sab 		Word			i;
358d29b2c44Sab 		Word			numdyn;
359d29b2c44Sab 		elfedit_section_t	*dynsec;
360d29b2c44Sab 		elfedit_dyn_elt_t	flags_1_elt;
361d29b2c44Sab 		elfedit_dyn_elt_t	null_elt;
362d29b2c44Sab 		Dyn			*dyn;
363d29b2c44Sab 
364d29b2c44Sab 		dynsec = &obj_state->os_secarr[obj_state->os_dynndx];
365d29b2c44Sab 		dyn = (Dyn *) dynsec->sec_data->d_buf;
366d29b2c44Sab 		numdyn = dynsec->sec_shdr->sh_size /
367d29b2c44Sab 		    dynsec->sec_shdr->sh_entsize;
368d29b2c44Sab 		elfedit_dyn_elt_init(&flags_1_elt);
369d29b2c44Sab 		elfedit_dyn_elt_init(&null_elt);
370d29b2c44Sab 		for (i = 0; i < numdyn; i++) {
371d29b2c44Sab 
372d29b2c44Sab 			switch (dyn[i].d_tag) {
373d29b2c44Sab 			case DT_NULL:
374d29b2c44Sab 				/*
375d29b2c44Sab 				 * Remember state of the first DT_NULL. If there
376d29b2c44Sab 				 * are more than one (i.e. the first one is not
377d29b2c44Sab 				 * in the final spot), and there is no flags1,
378d29b2c44Sab 				 * then we will turn the first one into a
379d29b2c44Sab 				 * DT_FLAGS_1.
380d29b2c44Sab 				 */
381d29b2c44Sab 				if (!null_elt.dn_seen)
382d29b2c44Sab 					elfedit_dyn_elt_save(&null_elt, i,
383d29b2c44Sab 					    &dyn[i]);
384d29b2c44Sab 				break;
385d29b2c44Sab 
386d29b2c44Sab 			case DT_FLAGS_1:
387d29b2c44Sab 				elfedit_dyn_elt_save(&flags_1_elt, i, &dyn[i]);
388d29b2c44Sab 				break;
389d29b2c44Sab 			}
390d29b2c44Sab 		}
391d29b2c44Sab 		/* If don't have a flags1 field, can we make one from a NULL? */
392d29b2c44Sab 		if (!flags_1_elt.dn_seen && null_elt.dn_seen &&
393d29b2c44Sab 		    (null_elt.dn_ndx < (numdyn - 1))) {
394d29b2c44Sab 			elfedit_msg(ELFEDIT_MSG_DEBUG,
395d29b2c44Sab 			    MSG_INTL(MSG_DEBUG_NULL2DYNFL1),
396d29b2c44Sab 			    EC_WORD(obj_state->os_dynndx),
397d29b2c44Sab 			    dynsec->sec_name, EC_WORD(null_elt.dn_ndx));
398d29b2c44Sab 			flags_1_elt.dn_seen = 1;
399d29b2c44Sab 			flags_1_elt.dn_ndx = null_elt.dn_ndx;
400d29b2c44Sab 			flags_1_elt.dn_dyn.d_tag = DT_FLAGS_1;
401d29b2c44Sab 			flags_1_elt.dn_dyn.d_un.d_val = 0;
402d29b2c44Sab 		}
403d29b2c44Sab 		/*
404d29b2c44Sab 		 * If there is a flags 1 field, add the edit flag if
405d29b2c44Sab 		 * it is not present, and report it's presence otherwise.
406d29b2c44Sab 		 */
407d29b2c44Sab 		if (flags_1_elt.dn_seen) {
408d29b2c44Sab 			if (flags_1_elt.dn_dyn.d_un.d_val & DF_1_EDITED) {
409d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
410d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_SEEDYNFLG),
411d29b2c44Sab 				    EC_WORD(obj_state->os_dynndx),
412d29b2c44Sab 				    dynsec->sec_name,
413d29b2c44Sab 				    EC_WORD(flags_1_elt.dn_ndx));
414d29b2c44Sab 			} else {
415d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
416d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_ADDDYNFLG),
417d29b2c44Sab 				    EC_WORD(obj_state->os_dynndx),
418d29b2c44Sab 				    dynsec->sec_name,
419d29b2c44Sab 				    EC_WORD(flags_1_elt.dn_ndx));
420d29b2c44Sab 				flags_1_elt.dn_dyn.d_un.d_val |= DF_1_EDITED;
421d29b2c44Sab 				dyn[flags_1_elt.dn_ndx] = flags_1_elt.dn_dyn;
422d29b2c44Sab 				elfedit_modified_data(dynsec);
423d29b2c44Sab 			}
424d29b2c44Sab 		}
425d29b2c44Sab 	}
426d29b2c44Sab 
427d29b2c44Sab #ifdef _ELF64
428d29b2c44Sab 	state.elf.obj_state.s64 = obj_state;
429d29b2c44Sab #else
430d29b2c44Sab 	state.elf.obj_state.s32 = obj_state;
431d29b2c44Sab #endif
432d29b2c44Sab 	return;
433d29b2c44Sab 
434d29b2c44Sab libelf_failure:
435d29b2c44Sab 	/*
436d29b2c44Sab 	 * Control comes here if there is an error with LIBELF.
437d29b2c44Sab 	 *
438d29b2c44Sab 	 * entry:
439d29b2c44Sab 	 *	libelf_fail_name - Name of failing libelf function
440d29b2c44Sab 	 *	tstate.os_file - Name of ELF file being processed
441d29b2c44Sab 	 *	tstate.os_fd - Descriptor of open ELF file
442d29b2c44Sab 	 *
443d29b2c44Sab 	 * exit:
444d29b2c44Sab 	 *	- dynamic memory is released if necessary
445d29b2c44Sab 	 *	- The error issued
446d29b2c44Sab 	 */
447d29b2c44Sab 	if (obj_state != NULL)
448d29b2c44Sab 		free(obj_state);
449d29b2c44Sab 	(void) close(tstate.os_fd);
450d29b2c44Sab 	elfedit_elferr(tstate.os_file, libelf_fail_name);
451d29b2c44Sab #undef LIBELF_FAILURE
452d29b2c44Sab #undef INITIAL_SYMTABNDX_ALLOC
453d29b2c44Sab }
454