xref: /onnv-gate/usr/src/cmd/sgs/elfedit/common/elfedit_machelf.c (revision 9900:1b86d65a4f9e)
15088Sab196087 /*
25088Sab196087  * CDDL HEADER START
35088Sab196087  *
45088Sab196087  * The contents of this file are subject to the terms of the
55088Sab196087  * Common Development and Distribution License (the "License").
65088Sab196087  * You may not use this file except in compliance with the License.
75088Sab196087  *
85088Sab196087  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95088Sab196087  * or http://www.opensolaris.org/os/licensing.
105088Sab196087  * See the License for the specific language governing permissions
115088Sab196087  * and limitations under the License.
125088Sab196087  *
135088Sab196087  * When distributing Covered Code, include this CDDL HEADER in each
145088Sab196087  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155088Sab196087  * If applicable, add the following below this CDDL HEADER, with the
165088Sab196087  * fields enclosed by brackets "[]" replaced with your own identifying
175088Sab196087  * information: Portions Copyright [yyyy] [name of copyright owner]
185088Sab196087  *
195088Sab196087  * CDDL HEADER END
205088Sab196087  */
215088Sab196087 
225088Sab196087 /*
23*9900SAli.Bahrami@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245088Sab196087  * Use is subject to license terms.
255088Sab196087  */
265088Sab196087 
275088Sab196087 /*
285088Sab196087  * ELFCLASS specific code for elfedit, built once for each class
295088Sab196087  */
305088Sab196087 #include	<stdlib.h>
315088Sab196087 #include	<stdio.h>
325088Sab196087 #include	<unistd.h>
336206Sab196087 #include	<_machelf.h>
345088Sab196087 #include	<libelf.h>
355088Sab196087 #include	<strings.h>
365088Sab196087 #include	<sgs.h>
375088Sab196087 #include	"msg.h"
385088Sab196087 #include	"_elfedit.h"
395088Sab196087 
405088Sab196087 
415088Sab196087 
425088Sab196087 /*
435088Sab196087  * Look up the elfedit_symtab_t that corresponds to the symbol table
445088Sab196087  * referenced by the sh_link field of the given auxiliary section.
455088Sab196087  *
465088Sab196087  * entry:
475088Sab196087  *	obj_state - Partially constructed object state from
485088Sab196087  *		elfedit_init_obj_state().
495088Sab196087  *	auxsec - Section that is associated with the symbol table section
505088Sab196087  *
515088Sab196087  * exit:
525088Sab196087  *	Returns the pointer to the elfedit_symtab_t entry that is
535088Sab196087  *	referenced by the auxiliary section. If not found,
545088Sab196087  *	outputs a debug message, and returns NULL.
555088Sab196087  */
565088Sab196087 static elfedit_symtab_t *
get_symtab(elfedit_obj_state_t * obj_state,elfedit_section_t * auxsec)575088Sab196087 get_symtab(elfedit_obj_state_t *obj_state, elfedit_section_t *auxsec)
585088Sab196087 {
595088Sab196087 	elfedit_symtab_t *symtab = obj_state->os_symtab;
605088Sab196087 	Word	sh_link = auxsec->sec_shdr->sh_link;
615088Sab196087 	Word	i;
625088Sab196087 
635088Sab196087 	for (i = 0; i < obj_state->os_symtabnum; i++, symtab++)
645088Sab196087 		if (symtab->symt_shndx == sh_link)
655088Sab196087 			return (symtab);
665088Sab196087 
675088Sab196087 	/*
685088Sab196087 	 * If we don't return above, it doesn't reference a valid
695088Sab196087 	 * symbol table. Issue warning.
705088Sab196087 	 */
715088Sab196087 	elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_AUX_LINK),
725088Sab196087 	    EC_WORD(auxsec->sec_shndx), auxsec->sec_name,
735088Sab196087 	    EC_WORD(sh_link));
745088Sab196087 
755088Sab196087 	return (NULL);
765088Sab196087 }
775088Sab196087 
785088Sab196087 
795088Sab196087 /*
805088Sab196087  * Fill in state.elf.obj_state with a a dynamically allocated
815088Sab196087  * elfedit_obj_state_t struct of the appropriate ELFCLASS.
825088Sab196087  * This pre-chewed form is fed to each command, reducing the amount
835088Sab196087  * of ELF boilerplate code each command needs to contain.
845088Sab196087  *
855088Sab196087  * entry:
865088Sab196087  *	file - Name of file to process
875088Sab196087  *	fd - Descriptor of open file which has been successfully
885088Sab196087  *		processed by elf_begin().
895088Sab196087  *	elf - Elf handle returned by elf_begin
905088Sab196087  *
915088Sab196087  * exit:
925088Sab196087  *	An elfedit_obj_state_t struct of the appropriate ELFCLASS has
935088Sab196087  *	been dynamically allocated, and state.elf.obj_state references it.
945088Sab196087  *	On failure, this routine does not return to the caller.
955088Sab196087  *
965088Sab196087  * note: The resulting elfedit_obj_state_t is allocated from a single
975088Sab196087  *	piece of memory, such that a single call to free() suffices
985088Sab196087  *	to release it as well as any memory it references.
995088Sab196087  */
1005088Sab196087 #ifdef _ELF64
1015088Sab196087 void
elfedit64_init_obj_state(const char * file,int fd,Elf * elf)1025088Sab196087 elfedit64_init_obj_state(const char *file, int fd, Elf *elf)
1035088Sab196087 #else
1045088Sab196087 void
1055088Sab196087 elfedit32_init_obj_state(const char *file, int fd, Elf *elf)
1065088Sab196087 #endif
1075088Sab196087 {
1085088Sab196087 #define	INITIAL_SYMTABNDX_ALLOC	5
1095088Sab196087 
1105088Sab196087 	/*
111*9900SAli.Bahrami@Sun.COM 	 * These macros are used to call functions from libelf.
112*9900SAli.Bahrami@Sun.COM 	 *
113*9900SAli.Bahrami@Sun.COM 	 * LIBELF_FAIL encapsulates the common way in which we handle
114*9900SAli.Bahrami@Sun.COM 	 * all of these errors: libelf_fail_name is set and execution
115*9900SAli.Bahrami@Sun.COM 	 * jumps to the libelf_failure label for handling.
116*9900SAli.Bahrami@Sun.COM 	 *
117*9900SAli.Bahrami@Sun.COM 	 * LIBELF is used for the common case in which the function returns
118*9900SAli.Bahrami@Sun.COM 	 * NULL for failure and something else for success.
1195088Sab196087 	 */
120*9900SAli.Bahrami@Sun.COM #define	LIBELF_FAIL(_name) { libelf_fail_name = _name; goto libelf_failure; }
1215088Sab196087 #define	LIBELF(_libelf_expr, _name) \
122*9900SAli.Bahrami@Sun.COM 	if ((_libelf_expr) == NULL) \
123*9900SAli.Bahrami@Sun.COM 		LIBELF_FAIL(_name)
1245088Sab196087 
1255088Sab196087 	const char *libelf_fail_name;	/* Used for LIBELF errors */
1265088Sab196087 
1275088Sab196087 	Elf_Scn			*scn;
1285088Sab196087 	Elf_Data		*data;
1295088Sab196087 	uint_t			ndx;
1305088Sab196087 	size_t			len, os_size, secarr_size;
1315088Sab196087 	char			*names = 0;
1325088Sab196087 	size_t			names_len;
1335088Sab196087 	elfedit_section_t	*_cache;
1345088Sab196087 	elfedit_obj_state_t	tstate;
1355088Sab196087 	elfedit_obj_state_t	*obj_state = NULL;
1365088Sab196087 	Word			*symtabndx = NULL;
1375088Sab196087 	Word			symtabndx_size = 0;
1385088Sab196087 	elfedit_symtab_t	*symtab;
1395088Sab196087 
1405088Sab196087 	tstate.os_file = file;
1415088Sab196087 	tstate.os_fd = fd;
1425088Sab196087 	tstate.os_elf = elf;
1435088Sab196087 	tstate.os_dynndx = SHN_UNDEF;
1445088Sab196087 	tstate.os_symtabnum = 0;
1455088Sab196087 
1465088Sab196087 	LIBELF(tstate.os_ehdr = elf_getehdr(tstate.os_elf),
1475088Sab196087 	    MSG_ORIG(MSG_ELF_GETEHDR))
1485088Sab196087 
1495088Sab196087 	/* Program header array count and address */
150*9900SAli.Bahrami@Sun.COM 	if (elf_getphdrnum(tstate.os_elf, &tstate.os_phnum) == -1)
151*9900SAli.Bahrami@Sun.COM 		LIBELF_FAIL(MSG_ORIG(MSG_ELF_GETPHDRNUM))
1525088Sab196087 	if (tstate.os_phnum > 0) {
1535088Sab196087 		LIBELF((tstate.os_phdr = elf_getphdr(tstate.os_elf)),
1545088Sab196087 		    MSG_ORIG(MSG_ELF_GETPHDR))
1555088Sab196087 	} else {
1565088Sab196087 		tstate.os_phdr = NULL;
1575088Sab196087 	}
1585088Sab196087 
159*9900SAli.Bahrami@Sun.COM 	if (elf_getshdrnum(tstate.os_elf, &tstate.os_shnum) == -1)
160*9900SAli.Bahrami@Sun.COM 		LIBELF_FAIL(MSG_ORIG(MSG_ELF_GETSHDRNUM))
1615088Sab196087 
1625088Sab196087 	/*
1635088Sab196087 	 * Obtain the .shstrtab data buffer to provide the required section
1645088Sab196087 	 * name strings.
1655088Sab196087 	 */
166*9900SAli.Bahrami@Sun.COM 	if (elf_getshdrstrndx(tstate.os_elf, &tstate.os_shstrndx) == -1)
167*9900SAli.Bahrami@Sun.COM 		LIBELF_FAIL(MSG_ORIG(MSG_ELF_GETSHDRSTRNDX))
1685088Sab196087 	LIBELF((scn = elf_getscn(tstate.os_elf, tstate.os_shstrndx)),
1695088Sab196087 	    MSG_ORIG(MSG_ELF_GETSCN))
1705088Sab196087 	LIBELF((data = elf_getdata(scn, NULL)), MSG_ORIG(MSG_ELF_GETDATA))
1715088Sab196087 	names = data->d_buf;
1725088Sab196087 	names_len = (names == NULL) ? 0 : data->d_size;
1735088Sab196087 
1745088Sab196087 	/*
1755088Sab196087 	 * Count the number of symbol tables and capture their indexes.
1765088Sab196087 	 * Find the dynamic section.
1775088Sab196087 	 */
1785088Sab196087 	for (ndx = 1, scn = NULL; scn = elf_nextscn(tstate.os_elf, scn);
1795088Sab196087 	    ndx++) {
1805088Sab196087 		Shdr *shdr;
1815088Sab196087 
1825088Sab196087 		LIBELF(shdr = elf_getshdr(scn), MSG_ORIG(MSG_ELF_GETSHDR));
1835088Sab196087 
1845088Sab196087 		switch (shdr->sh_type) {
1855088Sab196087 		case SHT_DYNAMIC:
1865088Sab196087 			/* Save index of dynamic section for use below */
1875088Sab196087 			tstate.os_dynndx = ndx;
1885088Sab196087 			break;
1895088Sab196087 
1905088Sab196087 		case SHT_SYMTAB:
1915088Sab196087 		case SHT_DYNSYM:
1925088Sab196087 		case SHT_SUNW_LDYNSYM:
1935088Sab196087 			if (symtabndx_size <= tstate.os_symtabnum) {
1945088Sab196087 				symtabndx_size = (symtabndx_size == 0) ?
1955088Sab196087 				    INITIAL_SYMTABNDX_ALLOC :
1965088Sab196087 				    (symtabndx_size * 2);
1975088Sab196087 				symtabndx = elfedit_realloc(
1985088Sab196087 				    MSG_INTL(MSG_ALLOC_SYMTABOS), symtabndx,
1995088Sab196087 				    symtabndx_size * sizeof (symtabndx[0]));
2005088Sab196087 			}
2015088Sab196087 			symtabndx[tstate.os_symtabnum++] = ndx;
2025088Sab196087 			break;
2035088Sab196087 		}
2045088Sab196087 	}
2055088Sab196087 
2065088Sab196087 	/*
2075088Sab196087 	 * Allocate space to hold the state. We allocate space for everything
2085088Sab196087 	 * in one chunk to make releasing it easy:
2095088Sab196087 	 *	(1) elfedit_obj_state_t struct
2105088Sab196087 	 *	(2) The array of elfedit_section_t items referenced from
2115088Sab196087 	 *		the elfedit_obj_state_t struct.
2125088Sab196087 	 *	(3) The array of elfedit_symtab_t items referenced from
2135088Sab196087 	 *		the elfedit_obj_state_t struct.
2145088Sab196087 	 *	(4) The file name.
2155088Sab196087 	 *
2165088Sab196087 	 * Note that we round up the size of (1) and (2) to a double boundary
2175088Sab196087 	 * to ensure proper alignment of (2) and (3). (4) can align on any
2185088Sab196087 	 * boundary.
2195088Sab196087 	 */
2205088Sab196087 	os_size = S_DROUND(sizeof (tstate));
2215088Sab196087 	secarr_size = (tstate.os_shnum * sizeof (elfedit_section_t));
2225088Sab196087 	secarr_size = S_DROUND(secarr_size);
2235088Sab196087 	len = strlen(tstate.os_file) + 1;
2245088Sab196087 	obj_state = elfedit_malloc(MSG_INTL(MSG_ALLOC_OBJSTATE),
2255088Sab196087 	    os_size + secarr_size +
2265088Sab196087 	    (tstate.os_symtabnum * sizeof (elfedit_symtab_t)) + len);
2275088Sab196087 	*obj_state = tstate;
2285088Sab196087 
2295088Sab196087 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
2305088Sab196087 	obj_state->os_secarr = (elfedit_section_t *)
2315088Sab196087 	    ((char *)obj_state + os_size);
2325088Sab196087 	if (obj_state->os_symtabnum == 0)
2335088Sab196087 		obj_state->os_symtab = NULL;
2345088Sab196087 	else
2355088Sab196087 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
2365088Sab196087 		obj_state->os_symtab = (elfedit_symtab_t *)
2375088Sab196087 		    ((char *)obj_state->os_secarr + secarr_size);
2385088Sab196087 	obj_state->os_file =
2395088Sab196087 	    (char *)(obj_state->os_symtab + tstate.os_symtabnum);
2405088Sab196087 	(void) strncpy((char *)obj_state->os_file, tstate.os_file, len);
2415088Sab196087 
2425088Sab196087 	/*
2435088Sab196087 	 * Fill in obj_state->os_secarr with information for each section.
2445088Sab196087 	 * At the same time, fill in obj_state->os_symtab with the symbol
2455088Sab196087 	 * table related data.
2465088Sab196087 	 */
2475088Sab196087 	bzero(obj_state->os_secarr, sizeof (obj_state->os_secarr[0]));
2485088Sab196087 	_cache = obj_state->os_secarr;
2495088Sab196087 	LIBELF(scn = elf_getscn(tstate.os_elf, 0),
2505088Sab196087 	    MSG_ORIG(MSG_ELF_GETSCN));
2515088Sab196087 	_cache->sec_scn = scn;
2525088Sab196087 	LIBELF(_cache->sec_shdr = elf_getshdr(scn), MSG_ORIG(MSG_ELF_GETSHDR));
2535088Sab196087 	_cache->sec_name = (_cache->sec_shdr->sh_name < names_len) ?
2545088Sab196087 	    (names + _cache->sec_shdr->sh_name) : MSG_INTL(MSG_UNKNOWNSECNAM);
2555088Sab196087 	_cache++;
2565088Sab196087 
2575088Sab196087 	if (obj_state->os_symtab != NULL) {
2585088Sab196087 		bzero(obj_state->os_symtab,
2595088Sab196087 		    sizeof (obj_state->os_symtab[0]) * obj_state->os_symtabnum);
2605088Sab196087 		for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++)
2615088Sab196087 			obj_state->os_symtab[ndx].symt_shndx = symtabndx[ndx];
2625088Sab196087 		free(symtabndx);
2635088Sab196087 	}
2645088Sab196087 
2655088Sab196087 	for (ndx = 1, scn = NULL; scn = elf_nextscn(tstate.os_elf, scn);
2665088Sab196087 	    ndx++, _cache++) {
2675088Sab196087 		_cache->sec_shndx = ndx;
2685088Sab196087 		_cache->sec_scn = scn;
2695088Sab196087 		LIBELF(_cache->sec_shdr = elf_getshdr(scn),
2705088Sab196087 		    MSG_ORIG(MSG_ELF_GETSHDR))
2715088Sab196087 		_cache->sec_data = elf_getdata(scn, NULL);
2725088Sab196087 		_cache->sec_name = (_cache->sec_shdr->sh_name < names_len) ?
2735088Sab196087 		    (names + _cache->sec_shdr->sh_name) :
2745088Sab196087 		    MSG_INTL(MSG_UNKNOWNSECNAM);
2755088Sab196087 
2765088Sab196087 		switch (_cache->sec_shdr->sh_type) {
2775088Sab196087 		case SHT_SYMTAB_SHNDX:
2785088Sab196087 			symtab = get_symtab(obj_state, _cache);
2795088Sab196087 			symtab->symt_xshndx = ndx;
2805088Sab196087 			break;
2815088Sab196087 
2825088Sab196087 		case SHT_SUNW_syminfo:
2835088Sab196087 			symtab = get_symtab(obj_state, _cache);
2845088Sab196087 			symtab->symt_syminfo = ndx;
2855088Sab196087 			break;
2865088Sab196087 
2875088Sab196087 		case SHT_SUNW_versym:
2885088Sab196087 			symtab = get_symtab(obj_state, _cache);
2895088Sab196087 			symtab->symt_versym = ndx;
2905088Sab196087 			break;
2915088Sab196087 		}
2925088Sab196087 	}
2935088Sab196087 
2945088Sab196087 	/*
2955088Sab196087 	 * Sanity check the symbol tables, and discard any auxiliary
2965088Sab196087 	 * sections without enough elements.
2975088Sab196087 	 */
2985088Sab196087 	symtab = obj_state->os_symtab;
2995088Sab196087 	for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) {
3005088Sab196087 		elfedit_section_t	*symsec;
3015088Sab196087 		Word			symsec_cnt, aux_cnt;
3025088Sab196087 
3035088Sab196087 		symsec = &obj_state->os_secarr[symtab->symt_shndx];
3045088Sab196087 		symsec_cnt = symsec->sec_shdr->sh_size / sizeof (Sym);
3055088Sab196087 
3065088Sab196087 		/* Extended section indexes */
3075088Sab196087 		if (symtab->symt_xshndx != SHN_UNDEF) {
3085088Sab196087 			_cache = &obj_state->os_secarr[symtab->symt_xshndx];
3095088Sab196087 			aux_cnt = _cache->sec_shdr->sh_size / sizeof (Word);
3105088Sab196087 			if (symsec_cnt > aux_cnt)
3115088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
3125088Sab196087 				    MSG_INTL(MSG_DEBUG_AUX_SIZE),
3135088Sab196087 				    EC_WORD(ndx), _cache->sec_name,
3145088Sab196087 				    EC_WORD(aux_cnt),
3155088Sab196087 				    EC_WORD(symsec->sec_shndx),
3165088Sab196087 				    symsec->sec_name, EC_WORD(aux_cnt));
3175088Sab196087 		}
3185088Sab196087 
3195088Sab196087 		/* Syminfo */
3205088Sab196087 		if (symtab->symt_syminfo != SHN_UNDEF) {
3215088Sab196087 			_cache = &obj_state->os_secarr[symtab->symt_syminfo];
3225088Sab196087 			aux_cnt = _cache->sec_shdr->sh_size / sizeof (Syminfo);
3235088Sab196087 			if (symsec_cnt > aux_cnt)
3245088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
3255088Sab196087 				    MSG_INTL(MSG_DEBUG_AUX_SIZE),
3265088Sab196087 				    EC_WORD(ndx), _cache->sec_name,
3275088Sab196087 				    EC_WORD(aux_cnt),
3285088Sab196087 				    EC_WORD(symsec->sec_shndx),
3295088Sab196087 				    symsec->sec_name, EC_WORD(aux_cnt));
3305088Sab196087 		}
3315088Sab196087 
3325088Sab196087 		/* Versym */
3335088Sab196087 		if (symtab->symt_versym != SHN_UNDEF) {
3345088Sab196087 			_cache = &obj_state->os_secarr[symtab->symt_versym];
3355088Sab196087 			aux_cnt = _cache->sec_shdr->sh_size / sizeof (Versym);
3365088Sab196087 			if (symsec_cnt > aux_cnt)
3375088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
3385088Sab196087 				    MSG_INTL(MSG_DEBUG_AUX_SIZE),
3395088Sab196087 				    EC_WORD(ndx), _cache->sec_name,
3405088Sab196087 				    EC_WORD(aux_cnt),
3415088Sab196087 				    EC_WORD(symsec->sec_shndx),
3425088Sab196087 				    symsec->sec_name, EC_WORD(aux_cnt));
3435088Sab196087 		}
3445088Sab196087 	}
3455088Sab196087 
3465088Sab196087 	/*
3475088Sab196087 	 * If this object has a dynsym section with a FLAGS_1 field,
3485088Sab196087 	 * then set the DF_1_EDITED bit. elfedit allows changes that
3495088Sab196087 	 * can break the resulting program, so knowing that a file was
3505088Sab196087 	 * edited can be helpful when encountering a core file or other
3515088Sab196087 	 * unexpected failure in the field. A single bit can't tell you
3525088Sab196087 	 * what was changed, but it will alert you to the possibility that
3535088Sab196087 	 * some additional questions might be in order.
3545088Sab196087 	 */
3555088Sab196087 	if (obj_state->os_dynndx != SHN_UNDEF) {
3565088Sab196087 		Word			i;
3575088Sab196087 		Word			numdyn;
3585088Sab196087 		elfedit_section_t	*dynsec;
3595088Sab196087 		elfedit_dyn_elt_t	flags_1_elt;
3605088Sab196087 		elfedit_dyn_elt_t	null_elt;
3615088Sab196087 		Dyn			*dyn;
3625088Sab196087 
3635088Sab196087 		dynsec = &obj_state->os_secarr[obj_state->os_dynndx];
3645088Sab196087 		dyn = (Dyn *) dynsec->sec_data->d_buf;
3655088Sab196087 		numdyn = dynsec->sec_shdr->sh_size /
3665088Sab196087 		    dynsec->sec_shdr->sh_entsize;
3675088Sab196087 		elfedit_dyn_elt_init(&flags_1_elt);
3685088Sab196087 		elfedit_dyn_elt_init(&null_elt);
3695088Sab196087 		for (i = 0; i < numdyn; i++) {
3705088Sab196087 
3715088Sab196087 			switch (dyn[i].d_tag) {
3725088Sab196087 			case DT_NULL:
3735088Sab196087 				/*
3745088Sab196087 				 * Remember state of the first DT_NULL. If there
3755088Sab196087 				 * are more than one (i.e. the first one is not
3765088Sab196087 				 * in the final spot), and there is no flags1,
3775088Sab196087 				 * then we will turn the first one into a
3785088Sab196087 				 * DT_FLAGS_1.
3795088Sab196087 				 */
3805088Sab196087 				if (!null_elt.dn_seen)
3815088Sab196087 					elfedit_dyn_elt_save(&null_elt, i,
3825088Sab196087 					    &dyn[i]);
3835088Sab196087 				break;
3845088Sab196087 
3855088Sab196087 			case DT_FLAGS_1:
3865088Sab196087 				elfedit_dyn_elt_save(&flags_1_elt, i, &dyn[i]);
3875088Sab196087 				break;
3885088Sab196087 			}
3895088Sab196087 		}
3905088Sab196087 		/* If don't have a flags1 field, can we make one from a NULL? */
3915088Sab196087 		if (!flags_1_elt.dn_seen && null_elt.dn_seen &&
3925088Sab196087 		    (null_elt.dn_ndx < (numdyn - 1))) {
3935088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
3945088Sab196087 			    MSG_INTL(MSG_DEBUG_NULL2DYNFL1),
3955088Sab196087 			    EC_WORD(obj_state->os_dynndx),
3965088Sab196087 			    dynsec->sec_name, EC_WORD(null_elt.dn_ndx));
3975088Sab196087 			flags_1_elt.dn_seen = 1;
3985088Sab196087 			flags_1_elt.dn_ndx = null_elt.dn_ndx;
3995088Sab196087 			flags_1_elt.dn_dyn.d_tag = DT_FLAGS_1;
4005088Sab196087 			flags_1_elt.dn_dyn.d_un.d_val = 0;
4015088Sab196087 		}
4025088Sab196087 		/*
4035088Sab196087 		 * If there is a flags 1 field, add the edit flag if
4045088Sab196087 		 * it is not present, and report it's presence otherwise.
4055088Sab196087 		 */
4065088Sab196087 		if (flags_1_elt.dn_seen) {
4075088Sab196087 			if (flags_1_elt.dn_dyn.d_un.d_val & DF_1_EDITED) {
4085088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
4095088Sab196087 				    MSG_INTL(MSG_DEBUG_SEEDYNFLG),
4105088Sab196087 				    EC_WORD(obj_state->os_dynndx),
4115088Sab196087 				    dynsec->sec_name,
4125088Sab196087 				    EC_WORD(flags_1_elt.dn_ndx));
4135088Sab196087 			} else {
4145088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
4155088Sab196087 				    MSG_INTL(MSG_DEBUG_ADDDYNFLG),
4165088Sab196087 				    EC_WORD(obj_state->os_dynndx),
4175088Sab196087 				    dynsec->sec_name,
4185088Sab196087 				    EC_WORD(flags_1_elt.dn_ndx));
4195088Sab196087 				flags_1_elt.dn_dyn.d_un.d_val |= DF_1_EDITED;
4205088Sab196087 				dyn[flags_1_elt.dn_ndx] = flags_1_elt.dn_dyn;
4215088Sab196087 				elfedit_modified_data(dynsec);
4225088Sab196087 			}
4235088Sab196087 		}
4245088Sab196087 	}
4255088Sab196087 
4265088Sab196087 #ifdef _ELF64
4275088Sab196087 	state.elf.obj_state.s64 = obj_state;
4285088Sab196087 #else
4295088Sab196087 	state.elf.obj_state.s32 = obj_state;
4305088Sab196087 #endif
4315088Sab196087 	return;
4325088Sab196087 
4335088Sab196087 libelf_failure:
4345088Sab196087 	/*
4355088Sab196087 	 * Control comes here if there is an error with LIBELF.
4365088Sab196087 	 *
4375088Sab196087 	 * entry:
4385088Sab196087 	 *	libelf_fail_name - Name of failing libelf function
4395088Sab196087 	 *	tstate.os_file - Name of ELF file being processed
4405088Sab196087 	 *	tstate.os_fd - Descriptor of open ELF file
4415088Sab196087 	 *
4425088Sab196087 	 * exit:
4435088Sab196087 	 *	- dynamic memory is released if necessary
4445088Sab196087 	 *	- The error issued
4455088Sab196087 	 */
4465088Sab196087 	if (obj_state != NULL)
4475088Sab196087 		free(obj_state);
4485088Sab196087 	(void) close(tstate.os_fd);
4495088Sab196087 	elfedit_elferr(tstate.os_file, libelf_fail_name);
4505088Sab196087 #undef INITIAL_SYMTABNDX_ALLOC
451*9900SAli.Bahrami@Sun.COM #undef LIBELF_FAIL
452*9900SAli.Bahrami@Sun.COM #undef LIBELF
4535088Sab196087 }
454