xref: /onnv-gate/usr/src/cmd/sgs/elfedit/modules/common/dyn.c (revision 6225:e6305f16e938)
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 /*
236206Sab196087  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
245088Sab196087  * Use is subject to license terms.
255088Sab196087  */
265088Sab196087 #pragma ident	"%Z%%M%	%I%	%E% SMI"
275088Sab196087 
285088Sab196087 #include	<ctype.h>
295088Sab196087 #include	<elfedit.h>
305088Sab196087 #include	<sys/elf_SPARC.h>
315088Sab196087 #include	<strings.h>
325088Sab196087 #include	<debug.h>
335088Sab196087 #include	<conv.h>
345088Sab196087 #include	<dyn_msg.h>
355088Sab196087 
365088Sab196087 
375088Sab196087 /*
385088Sab196087  * Dynamic section
395088Sab196087  */
405088Sab196087 
415088Sab196087 
425088Sab196087 
435088Sab196087 
445088Sab196087 /*
455088Sab196087  * This module uses shared code for several of the commands.
465088Sab196087  * It is sometimes necessary to know which specific command
475088Sab196087  * is active.
485088Sab196087  */
495088Sab196087 typedef enum {
505088Sab196087 	/* Dump command, used as module default to display dynamic section */
515088Sab196087 	DYN_CMD_T_DUMP =	0,	/* dyn:dump */
525088Sab196087 
535088Sab196087 	/* Commands that do not correspond directly to a specific DT tag */
545088Sab196087 	DYN_CMD_T_TAG =		1,	/* dyn:tag */
555088Sab196087 	DYN_CMD_T_VALUE =	2,	/* dyn:value */
565088Sab196087 	DYN_CMD_T_DELETE =	3,	/* dyn:delete */
575088Sab196087 	DYN_CMD_T_MOVE =	4,	/* dyn:shift */
585088Sab196087 
595088Sab196087 	/* Commands that embody tag specific knowledge */
605088Sab196087 	DYN_CMD_T_RUNPATH =	5,	/* dyn:runpath/rpath */
615088Sab196087 	DYN_CMD_T_POSFLAG1 =	6,	/* dyn:posflag1 */
625088Sab196087 	DYN_CMD_T_FLAGS =	7,	/* dyn:flags */
635088Sab196087 	DYN_CMD_T_FLAGS1 =	8,	/* dyn:flags1 */
645088Sab196087 	DYN_CMD_T_FEATURE1 =	9,	/* dyn:feature1 */
656206Sab196087 	DYN_CMD_T_CHECKSUM =	10,	/* dyn:checksum */
666206Sab196087 	DYN_CMD_T_SUNW_LDMACH =	11	/* dyn:sunw_ldmach */
675088Sab196087 } DYN_CMD_T;
685088Sab196087 
695088Sab196087 
705088Sab196087 
715088Sab196087 #ifndef _ELF64
725088Sab196087 /*
735088Sab196087  * We supply this function for the msg module
745088Sab196087  */
755088Sab196087 const char *
765088Sab196087 _dyn_msg(Msg mid)
775088Sab196087 {
785088Sab196087 	return (gettext(MSG_ORIG(mid)));
795088Sab196087 }
805088Sab196087 #endif
815088Sab196087 
825088Sab196087 
835088Sab196087 /*
845088Sab196087  * This function is supplied to elfedit through our elfedit_module_t
855088Sab196087  * definition. It translates the opaque elfedit_i18nhdl_t handles
865088Sab196087  * in our module interface into the actual strings for elfedit to
875088Sab196087  * use.
885088Sab196087  *
895088Sab196087  * note:
905088Sab196087  *	This module uses Msg codes for its i18n handle type.
915088Sab196087  *	So the translation is simply to use MSG_INTL() to turn
925088Sab196087  *	it into a string and return it.
935088Sab196087  */
945088Sab196087 static const char *
955088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
965088Sab196087 {
975088Sab196087 	Msg msg = (Msg)hdl;
985088Sab196087 
995088Sab196087 	return (MSG_INTL(msg));
1005088Sab196087 }
1015088Sab196087 
1025088Sab196087 
1035088Sab196087 
1045088Sab196087 /*
1055088Sab196087  * The dyn_opt_t enum specifies a bit value for every optional
1065088Sab196087  * argument allowed by a command in this module.
1075088Sab196087  */
1085088Sab196087 typedef enum {
1095088Sab196087 	DYN_OPT_F_ADD =		1,	/* -add: Add new elt rather than */
1105088Sab196087 					/*	modifying an existing one */
1115088Sab196087 	DYN_OPT_F_AND =		2,	/* -and: AND (&) values to dest */
1125088Sab196087 	DYN_OPT_F_CMP =		4,	/* -cmp: Complement (~) values */
113*6225Sab196087 	DYN_OPT_F_DYNNDX_ELT =	8,	/* -dynndx: 1st plain arg is tag */
114*6225Sab196087 					/*	index, not name */
115*6225Sab196087 	DYN_OPT_F_DYNNDX_VAL =	16,	/* -dynndx ndx: Index is value to */
116*6225Sab196087 					/*	option rather than 1st plain */
117*6225Sab196087 					/*	arg. Used for dyn:posflag1 */
118*6225Sab196087 	DYN_OPT_F_NEEDED =	32,	/* -needed str: Locate DT_POSFLAG_1 */
119*6225Sab196087 					/*	relative to DT_NEEDED element */
120*6225Sab196087 	DYN_OPT_F_OR =		64,	/* -or: OR (|) values to dest */
121*6225Sab196087 	DYN_OPT_F_STRVAL =	128	/* -s: value is string, not integer */
1225088Sab196087 } dyn_opt_t;
1235088Sab196087 
1245088Sab196087 
1255088Sab196087 /*
1265088Sab196087  * A variable of type ARGSTATE is used by each command to maintain
1275088Sab196087  * information about the arguments and related things. It is
1285088Sab196087  * initialized by process_args(), and used by the other routines.
1295088Sab196087  */
1305088Sab196087 typedef struct {
1315088Sab196087 	elfedit_obj_state_t	*obj_state;
1325088Sab196087 	elfedit_section_t	*strsec;	/* Dynamic string table ref */
1335088Sab196087 	struct {
1345088Sab196087 		elfedit_section_t *sec;		/* Dynamic section reference */
1355088Sab196087 		Dyn	*data;			/* Start dynamic section data */
1365088Sab196087 		Word	num;			/* # dynamic elts */
1375088Sab196087 		Word	null_ndx;		/* Index of first DT_NULL */
1385088Sab196087 		Word	num_null_ndx;		/* # of DT_NULL elements */
1395088Sab196087 	} dyn;
1405088Sab196087 	dyn_opt_t		optmask;   	/* Mask of options used */
1415088Sab196087 	int			argc;		/* # of plain arguments */
1425088Sab196087 	const char		**argv;		/* Plain arguments */
143*6225Sab196087 	const char		*dyn_elt_str;	/* Value string for */
144*6225Sab196087 						/*	DYN_OPT_F_DYNNDX_VAL */
145*6225Sab196087 						/*	or DYN_OPT_F_NEEDED */
1465088Sab196087 } ARGSTATE;
1475088Sab196087 
1485088Sab196087 
1495088Sab196087 
1505088Sab196087 /*
1515088Sab196087  * Set argstate null_ndx field for current dynamic area
1525088Sab196087  */
1535088Sab196087 static void
1545088Sab196087 set_null_ndx(ARGSTATE *argstate)
1555088Sab196087 {
1565088Sab196087 	Word	num, null_ndx;
1575088Sab196087 
1585088Sab196087 	num = argstate->dyn.num;
1595088Sab196087 	argstate->dyn.num_null_ndx = 0;
1605088Sab196087 	for (null_ndx = 0; null_ndx < num; null_ndx++)
1615088Sab196087 		if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) {
1625088Sab196087 			argstate->dyn.num_null_ndx++;
1635088Sab196087 			break;
1645088Sab196087 		}
1655088Sab196087 	argstate->dyn.null_ndx = null_ndx;
1665088Sab196087 
1675088Sab196087 	/* Count the number of remaining DT_NULL items */
1685088Sab196087 	for (; null_ndx < num; null_ndx++)
1695088Sab196087 		if (argstate->dyn.data[null_ndx].d_tag == DT_NULL)
1705088Sab196087 			argstate->dyn.num_null_ndx++;
1715088Sab196087 }
1725088Sab196087 
1735088Sab196087 
1745088Sab196087 /*
1755088Sab196087  * Convert the first available DT_NULL slot in the dynamic section
1765088Sab196087  * into something else.
1775088Sab196087  *
1785088Sab196087  * entry:
1795088Sab196087  *	argstate - Argument state block
1805088Sab196087  *	d_tag, d_val - Values to be set in new element
1815088Sab196087  *
1825088Sab196087  * exit:
1835088Sab196087  *	If an extra DT_NULL slot is available, a debug message is
1845088Sab196087  *	issued, the slot is converted to its new use, and the argstate
1855088Sab196087  *	block state related to DT_NULL slots is updated.
1865088Sab196087  *
1875088Sab196087  *	if no extra DT_NULL slot is present, an error is issued and
1885088Sab196087  *	this routine does not return to the caller.
1895088Sab196087  */
1905088Sab196087 static Word
1915088Sab196087 convert_dt_null(ARGSTATE *argstate, Word d_tag, Xword d_val)
1925088Sab196087 {
1935088Sab196087 	Conv_inv_buf_t inv_buf;
1945088Sab196087 	Word	ndx;
1955088Sab196087 	Dyn	*dyn;
1965088Sab196087 
1975088Sab196087 	/* If we lack an extra element, we can't continue */
1985088Sab196087 	if (argstate->dyn.num_null_ndx <= 1)
1995088Sab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL),
2005088Sab196087 		    EC_WORD(argstate->dyn.sec->sec_shndx),
2015088Sab196087 		    argstate->dyn.sec->sec_name);
2025088Sab196087 
2035088Sab196087 	elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL),
2045088Sab196087 	    EC_WORD(argstate->dyn.sec->sec_shndx), argstate->dyn.sec->sec_name,
2055088Sab196087 	    EC_WORD(argstate->dyn.null_ndx), conv_dyn_tag(d_tag,
2065088Sab196087 	    argstate->obj_state->os_ehdr->e_machine, 0, &inv_buf));
2075088Sab196087 
2085088Sab196087 	ndx = argstate->dyn.null_ndx;
2095088Sab196087 	dyn = &argstate->dyn.data[ndx];
2105088Sab196087 	dyn->d_tag = d_tag;
2115088Sab196087 	dyn->d_un.d_val = d_val;
2125088Sab196087 
2135088Sab196087 	/* Recompute the DT_NULL situation */
2145088Sab196087 	set_null_ndx(argstate);
2155088Sab196087 
2165088Sab196087 	return (ndx);
2175088Sab196087 }
2185088Sab196087 
2195088Sab196087 
2205088Sab196087 /*
2215088Sab196087  * Standard argument processing for dyn module
2225088Sab196087  *
2235088Sab196087  * entry
2245088Sab196087  *	obj_state, argc, argv - Standard command arguments
2255088Sab196087  *	argstate - Address of ARGSTATE block to be initialized
2265088Sab196087  *
2275088Sab196087  * exit:
2285088Sab196087  *	On success, *argstate is initialized. On error,
2295088Sab196087  *	an error is issued and this routine does not return.
2305088Sab196087  */
2315088Sab196087 static void
2325088Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
2335088Sab196087     ARGSTATE *argstate)
2345088Sab196087 {
2355088Sab196087 	elfedit_getopt_state_t	getopt_state;
2365088Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
2375088Sab196087 
2385088Sab196087 	bzero(argstate, sizeof (*argstate));
2395088Sab196087 	argstate->obj_state = obj_state;
2405088Sab196087 
2415088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
2425088Sab196087 
2435088Sab196087 	/* Add each new option to the options mask */
244*6225Sab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
2455088Sab196087 		argstate->optmask |= getopt_ret->gor_idmask;
246*6225Sab196087 		switch (getopt_ret->gor_idmask) {
247*6225Sab196087 		case DYN_OPT_F_DYNNDX_VAL:
248*6225Sab196087 		case DYN_OPT_F_NEEDED:
249*6225Sab196087 			argstate->dyn_elt_str = getopt_ret->gor_value;
250*6225Sab196087 			break;
251*6225Sab196087 		}
252*6225Sab196087 	}
2535088Sab196087 
2545088Sab196087 	/* If there may be an arbitrary amount of output, use a pager */
2555088Sab196087 	if (argc == 0)
2565088Sab196087 		elfedit_pager_init();
2575088Sab196087 
2585088Sab196087 	/* Return the updated values of argc/argv */
2595088Sab196087 	argstate->argc = argc;
2605088Sab196087 	argstate->argv = argv;
2615088Sab196087 
2625088Sab196087 	/* Locate the dynamic section, and the assocated string table */
2635088Sab196087 	argstate->dyn.sec = elfedit_sec_getdyn(obj_state, &argstate->dyn.data,
2645088Sab196087 	    &argstate->dyn.num);
2655088Sab196087 	argstate->strsec = elfedit_sec_getstr(obj_state,
266*6225Sab196087 	    argstate->dyn.sec->sec_shdr->sh_link, 0);
2675088Sab196087 
2685088Sab196087 	/* Index of first DT_NULL */
2695088Sab196087 	set_null_ndx(argstate);
2705088Sab196087 }
2715088Sab196087 
2725088Sab196087 
2735088Sab196087 
2745088Sab196087 /*
2755088Sab196087  * Print ELF header values, taking the calling command, and output style
2765088Sab196087  * into account.
2775088Sab196087  *
2785088Sab196087  * entry:
2795088Sab196087  *	cmd - DYN_CMD_T_* value giving identify of caller
2805088Sab196087  *	autoprint - If True, output is only produced if the elfedit
2815088Sab196087  *		autoprint flag is set. If False, output is always produced.
2825088Sab196087  *	argstate - Argument state block
2835088Sab196087  *	print_type - Specifies which dynamic elements to display.
2845088Sab196087  *	ndx = If print_type is PRINT_DYN_T_NDX, displays the index specified.
2855088Sab196087  *		Otherwise ignored.
2865088Sab196087  */
2875088Sab196087 typedef enum {
2885088Sab196087 	PRINT_DYN_T_ALL =	0,	/* Show all indexes */
2895088Sab196087 	PRINT_DYN_T_NDX =	1,	/* Show dynamic[arg] only */
2905088Sab196087 	PRINT_DYN_T_TAG =	2,	/* Show all elts with tag type */
2915088Sab196087 					/*	given by arg */
2925088Sab196087 	PRINT_DYN_T_RUNPATH =	3	/* Show all runpath/rpath elts */
2935088Sab196087 
2945088Sab196087 } PRINT_DYN_T;
2955088Sab196087 
2965088Sab196087 static void
2975088Sab196087 print_dyn(DYN_CMD_T cmd, int autoprint, ARGSTATE *argstate,
2985088Sab196087     PRINT_DYN_T print_type, Word arg)
2995088Sab196087 {
3005088Sab196087 	elfedit_outstyle_t	outstyle;
3015088Sab196087 	Conv_fmt_flags_t	flags_fmt_flags;
3025088Sab196087 	Word	end_ndx, cnt, ndx, printed = 0;
3035088Sab196087 	Dyn	*dyn;
3045088Sab196087 	int	header_done = 0;
3055088Sab196087 	Xword	last_d_val;
306*6225Sab196087 	int	one_shot;
3075088Sab196087 
3085088Sab196087 	if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
3095088Sab196087 		return;
3105088Sab196087 
3115088Sab196087 	/*
3125088Sab196087 	 * Pick an output style. dyn:dump is required to use the default
3135088Sab196087 	 * style. The other commands use the current output style.
3145088Sab196087 	 */
3155088Sab196087 	outstyle = (cmd == DYN_CMD_T_DUMP) ?
3165088Sab196087 	    ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
3175088Sab196087 
3185088Sab196087 	/*
3195088Sab196087 	 * When using the simple output style, omit the
3205088Sab196087 	 * brackets from around the values.
3215088Sab196087 	 */
3225088Sab196087 	flags_fmt_flags = (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) ?
3235088Sab196087 	    CONV_FMT_NOBKT : 0;
3245088Sab196087 
3255088Sab196087 	/* How many elements do we examine? */
3265088Sab196087 	if (print_type == PRINT_DYN_T_NDX) {
3275088Sab196087 		if (arg >= argstate->dyn.num)
3285088Sab196087 			return;		/* Out of range */
3295088Sab196087 		ndx = arg;
3305088Sab196087 		cnt = 1;
3315088Sab196087 	} else {
3325088Sab196087 		ndx = 0;
3335088Sab196087 		cnt = argstate->dyn.num;
3345088Sab196087 	}
3355088Sab196087 
336*6225Sab196087 	/*
337*6225Sab196087 	 * one_shot is used by positional elements (e.g. DT_POSFLAG_1)
338*6225Sab196087 	 * to get the item following them to be shown even if they
339*6225Sab196087 	 * are not of the desired tag type or the count of elements
340*6225Sab196087 	 * to be displayed is only 1.
341*6225Sab196087 	 */
342*6225Sab196087 	one_shot = 0;
343*6225Sab196087 
3445088Sab196087 	dyn = &argstate->dyn.data[ndx];
345*6225Sab196087 	for (; (one_shot && (ndx < argstate->dyn.num)) || cnt--; dyn++, ndx++) {
3465088Sab196087 		union {
3476206Sab196087 			Conv_inv_buf_t		inv;
3485088Sab196087 			Conv_dyn_flag_buf_t	flag;
3495088Sab196087 			Conv_dyn_flag1_buf_t	flag1;
3505088Sab196087 			Conv_dyn_posflag1_buf_t	posflag1;
3515088Sab196087 			Conv_dyn_feature1_buf_t	feature1;
3525088Sab196087 		} c_buf;
3535088Sab196087 		const char	*name;
3545088Sab196087 
355*6225Sab196087 		if (one_shot) {
356*6225Sab196087 			one_shot = 0;
357*6225Sab196087 		} else {
358*6225Sab196087 			/*
359*6225Sab196087 			 * If we are only displaying certain tag types and
360*6225Sab196087 			 * this isn't one of those, move on to next element.
361*6225Sab196087 			 */
362*6225Sab196087 			switch (print_type) {
363*6225Sab196087 			case PRINT_DYN_T_TAG:
364*6225Sab196087 				if (dyn->d_tag != arg)
365*6225Sab196087 					continue;
366*6225Sab196087 				break;
367*6225Sab196087 			case PRINT_DYN_T_RUNPATH:
368*6225Sab196087 				if ((dyn->d_tag != DT_RPATH) &&
369*6225Sab196087 				    (dyn->d_tag != DT_RUNPATH))
370*6225Sab196087 					continue;
371*6225Sab196087 				break;
372*6225Sab196087 			}
3735088Sab196087 		}
3745088Sab196087 
3755088Sab196087 		/*
3765088Sab196087 		 * Print the information numerically, and if possible
3775088Sab196087 		 * as a string.
3785088Sab196087 		 */
3795088Sab196087 		name = NULL;
3805088Sab196087 		switch (dyn->d_tag) {
3815088Sab196087 		case DT_NULL:
3825088Sab196087 			if (!((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) &&
3835088Sab196087 			    (print_type == PRINT_DYN_T_ALL) &&
3845088Sab196087 			    (dyn->d_un.d_val == 0)))
3855088Sab196087 				break;
3865088Sab196087 			end_ndx = ndx;
3875088Sab196087 			/*
3885088Sab196087 			 * Special case: DT_NULLs can come in groups
3895088Sab196087 			 * that we prefer to reduce to a single line.
3905088Sab196087 			 */
3915088Sab196087 			while ((end_ndx < (argstate->dyn.num - 1)) &&
3925088Sab196087 			    ((dyn + 1)->d_tag == DT_NULL) &&
3935088Sab196087 			    ((dyn + 1)->d_un.d_val == 0)) {
3945088Sab196087 				dyn++;
3955088Sab196087 				end_ndx++;
3965088Sab196087 				cnt--;
3975088Sab196087 			}
3985088Sab196087 			if (header_done == 0) {
3995088Sab196087 				header_done = 1;
4005088Sab196087 				Elf_dyn_title(0);
4015088Sab196087 			}
4025088Sab196087 			Elf_dyn_null_entry(0, dyn, ndx, end_ndx);
4035088Sab196087 			ndx = end_ndx;
4045088Sab196087 			printed = 1;
4055088Sab196087 			last_d_val = dyn->d_un.d_val;
4065088Sab196087 			continue;
4075088Sab196087 
4085088Sab196087 		/*
4095088Sab196087 		 * Print the information numerically, and if possible
4105088Sab196087 		 * as a string.
4115088Sab196087 		 */
4125088Sab196087 		case DT_NEEDED:
4135088Sab196087 		case DT_SONAME:
4145088Sab196087 		case DT_FILTER:
4155088Sab196087 		case DT_AUXILIARY:
4165088Sab196087 		case DT_CONFIG:
4175088Sab196087 		case DT_RPATH:
4185088Sab196087 		case DT_RUNPATH:
4195088Sab196087 		case DT_USED:
4205088Sab196087 		case DT_DEPAUDIT:
4215088Sab196087 		case DT_AUDIT:
4225088Sab196087 		case DT_SUNW_AUXILIARY:
4235088Sab196087 		case DT_SUNW_FILTER:
4245088Sab196087 			name = elfedit_offset_to_str(argstate->strsec,
4255088Sab196087 			    dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
4265088Sab196087 			break;
4275088Sab196087 
4285088Sab196087 		case DT_FLAGS:
4295088Sab196087 			name = conv_dyn_flag(dyn->d_un.d_val,
4305088Sab196087 			    flags_fmt_flags, &c_buf.flag);
4315088Sab196087 			break;
4325088Sab196087 		case DT_FLAGS_1:
4335088Sab196087 			name = conv_dyn_flag1(dyn->d_un.d_val,
4345088Sab196087 			    flags_fmt_flags, &c_buf.flag1);
4355088Sab196087 			break;
4365088Sab196087 		case DT_POSFLAG_1:
437*6225Sab196087 			/*
438*6225Sab196087 			 * If this is dyn:posflag1, and the print_type
439*6225Sab196087 			 * is PRINT_DYN_T_TAG, and the -needed option is
440*6225Sab196087 			 * used, then don't show any DT_POSFLAG_1 elements
441*6225Sab196087 			 * that are not followed by a DT_NEEDED element
442*6225Sab196087 			 * that matches the -needed string.
443*6225Sab196087 			 */
444*6225Sab196087 			if ((cmd == DYN_CMD_T_POSFLAG1) &&
445*6225Sab196087 			    (print_type == PRINT_DYN_T_TAG) &&
446*6225Sab196087 			    ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) &&
447*6225Sab196087 			    ((ndx + 1) < argstate->dyn.num)) {
448*6225Sab196087 				Dyn *dyn1 = &argstate->dyn.data[ndx + 1];
449*6225Sab196087 
450*6225Sab196087 				if (dyn1->d_tag != DT_NEEDED)
451*6225Sab196087 					continue;
452*6225Sab196087 				name = elfedit_offset_to_str(argstate->strsec,
453*6225Sab196087 				    dyn1->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
454*6225Sab196087 				if (strncmp(name, argstate->dyn_elt_str,
455*6225Sab196087 				    strlen(argstate->dyn_elt_str)) != 0)
456*6225Sab196087 					continue;
457*6225Sab196087 			}
458*6225Sab196087 
4595088Sab196087 			name = conv_dyn_posflag1(dyn->d_un.d_val,
4605088Sab196087 			    flags_fmt_flags, &c_buf.posflag1);
461*6225Sab196087 			/*
462*6225Sab196087 			 * DT_POSFLAG_1 is a positional element that affects
463*6225Sab196087 			 * the following item. If using the default output
464*6225Sab196087 			 * style, then show the following item as well.
465*6225Sab196087 			 */
466*6225Sab196087 			one_shot = (outstyle == ELFEDIT_OUTSTYLE_DEFAULT);
4675088Sab196087 			break;
4685088Sab196087 		case DT_FEATURE_1:
4695088Sab196087 			name = conv_dyn_feature1(dyn->d_un.d_val,
4705088Sab196087 			    flags_fmt_flags, &c_buf.feature1);
4715088Sab196087 			break;
4725088Sab196087 		case DT_DEPRECATED_SPARC_REGISTER:
4735088Sab196087 			name = MSG_INTL(MSG_STR_DEPRECATED);
4745088Sab196087 			break;
4756206Sab196087 		case DT_SUNW_LDMACH:
4766206Sab196087 			name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0,
4776206Sab196087 			    &c_buf.inv);
4786206Sab196087 			break;
4795088Sab196087 		}
4805088Sab196087 
4815088Sab196087 		if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
4825088Sab196087 			if (header_done == 0) {
4835088Sab196087 				header_done = 1;
4845088Sab196087 				Elf_dyn_title(0);
4855088Sab196087 			}
4865088Sab196087 			if (name == NULL)
4875088Sab196087 				name = MSG_ORIG(MSG_STR_EMPTY);
4885088Sab196087 			Elf_dyn_entry(0, dyn, ndx, name,
4895088Sab196087 			    argstate->obj_state->os_ehdr->e_machine);
4905088Sab196087 		} else {
4915088Sab196087 			/*
4925088Sab196087 			 * In simple or numeric mode under a print type
4935088Sab196087 			 * that is based on tag type rather than on index,
4945088Sab196087 			 * quietly: If we've already printed this value,
4955088Sab196087 			 * don't print it again. A common example of this
4965088Sab196087 			 * is PRINT_DYN_T_RUNPATH when both DT_RPATH and
4975088Sab196087 			 * DT_RUNPATH are present with the same value.
4985088Sab196087 			 */
4995088Sab196087 			switch (print_type) {
5005088Sab196087 			case PRINT_DYN_T_TAG:
501*6225Sab196087 				/*
502*6225Sab196087 				 * Positional flags don't count, because
503*6225Sab196087 				 * each one affects a different item. So don't
504*6225Sab196087 				 * skip those.
505*6225Sab196087 				 */
506*6225Sab196087 				if (dyn->d_tag != DT_POSFLAG_1)
507*6225Sab196087 					continue;
508*6225Sab196087 				break;
509*6225Sab196087 
5105088Sab196087 			case PRINT_DYN_T_RUNPATH:
5115088Sab196087 				if (printed && (last_d_val == dyn->d_un.d_val))
5125088Sab196087 					continue;
513*6225Sab196087 				break;
5145088Sab196087 			}
5155088Sab196087 
5165088Sab196087 			if ((name != NULL) &&
5175088Sab196087 			    (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) {
5185088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name);
5195088Sab196087 			} else {
5205088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL),
5215088Sab196087 				    dyn->d_un.d_val);
5225088Sab196087 			}
5235088Sab196087 		}
5245088Sab196087 		printed = 1;
5255088Sab196087 		last_d_val = dyn->d_un.d_val;
5265088Sab196087 	}
5275088Sab196087 
5285088Sab196087 	/*
5295088Sab196087 	 * If nothing was output under the print types that are
5305088Sab196087 	 * based on tag type, issue an error saying it doesn't exist.
5315088Sab196087 	 */
5325088Sab196087 	if (!printed) {
5335088Sab196087 		if (print_type == PRINT_DYN_T_TAG) {
5345088Sab196087 			Conv_inv_buf_t inv_buf;
5355088Sab196087 
5365088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
5375088Sab196087 			    MSG_INTL(MSG_ERR_NODYNELT),
5385088Sab196087 			    EC_WORD(argstate->dyn.sec->sec_shndx),
5395088Sab196087 			    argstate->dyn.sec->sec_name, conv_dyn_tag(arg,
5405088Sab196087 			    argstate->obj_state->os_ehdr->e_machine,
5415088Sab196087 			    0, &inv_buf));
5425088Sab196087 		}
5435088Sab196087 
5445088Sab196087 		if (print_type == PRINT_DYN_T_RUNPATH)
5455088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
5465088Sab196087 			    MSG_INTL(MSG_ERR_NORUNPATH),
5475088Sab196087 			    EC_WORD(argstate->dyn.sec->sec_shndx),
5485088Sab196087 			    argstate->dyn.sec->sec_name);
5495088Sab196087 	}
5505088Sab196087 }
5515088Sab196087 
5525088Sab196087 
5535088Sab196087 /*
554*6225Sab196087  * Determine the index(s) of the dynamic element(s) to be displayed and/or
555*6225Sab196087  * manipulated.
5565088Sab196087  *
5575088Sab196087  * entry:
5585088Sab196087  *	argstate - Argument state block
559*6225Sab196087  *	arg - If the command being called accepts a first plain argument
560*6225Sab196087  *		named 'elt' which is used to specify the dynamic element,
561*6225Sab196087  *		arg is the value of argv[0] for that command. If the
562*6225Sab196087  *		command does not accept an 'elt' argument and instead
563*6225Sab196087  *		implicitly assumes a tag type, arg is the constant string
564*6225Sab196087  *		for that type (e.g. "DT_POSFLAG_1").
5655088Sab196087  *	print_request - True if the command is to print the current
5665088Sab196087  *		value(s) and return without changing anything.
5675088Sab196087  *	print_type - Address of variable containing PRINT_DYN_T_
5685088Sab196087  *		code specifying how the elements will be displayed.
5695088Sab196087  *
5705088Sab196087  * exit:
571*6225Sab196087  *	If print_request is False: This routine always returns the index
572*6225Sab196087  *	of a single dynamic element. *print_type is set to PRINT_DYN_T_NDX.
573*6225Sab196087  *	The 'elt' argument as well as any modifier options (-dynndx, -needed)
574*6225Sab196087  *	are examined to determine this index. If there are no modifier options,
575*6225Sab196087  *	the dynamic section contains no element of the desired type, and there
576*6225Sab196087  *	is an extra DT_NULL element in the section, then a new element of
577*6225Sab196087  *	the desired type is created and its index returned. Otherwise an
578*6225Sab196087  *	error is issued.
5795088Sab196087  *
580*6225Sab196087  *	If print_request is True: If a modifier (-dynndx, -needed) was used,
581*6225Sab196087  *	*print_type is set to PRINT_DYN_T_NDX and the index of the
582*6225Sab196087  *	corresponding single dynamic element is returned. If no modifier
583*6225Sab196087  *	was used, *print_type is set to PRINT_DYN_T_TAG, and the tag
584*6225Sab196087  *	type code is returned.
5855088Sab196087  */
5865088Sab196087 static Word
587*6225Sab196087 arg_to_index(ARGSTATE *argstate, const char *arg,
5885088Sab196087     int print_request, PRINT_DYN_T *print_type)
5895088Sab196087 {
5905088Sab196087 	Word	ndx, dt_value;
591*6225Sab196087 	Dyn	*dyn;
5925088Sab196087 
5935088Sab196087 
5945088Sab196087 	/* Assume we are returning an index, alter as needed below */
5955088Sab196087 	*print_type = PRINT_DYN_T_NDX;
5965088Sab196087 
597*6225Sab196087 	/*
598*6225Sab196087 	 * All the commands that accept the DYN_OPT_F_DYNNDX_ELT form
599*6225Sab196087 	 * of -dynndx require a plain argument named 'elt' as their first
600*6225Sab196087 	 * argument. -dynndx is a modifier that means that 'elt' is a
601*6225Sab196087 	 * simple numeric section index. Routines that accept this form
602*6225Sab196087 	 * of -dynndx are willing to handle any tag type, so all we need
603*6225Sab196087 	 * to check is that the value is in range.
604*6225Sab196087 	 */
605*6225Sab196087 	if ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0)
606*6225Sab196087 		return ((Word) elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_ELT),
607*6225Sab196087 		    0, argstate->dyn.num - 1, NULL));
608*6225Sab196087 
609*6225Sab196087 	/* arg is a DT_ tag type, not a numeric index */
610*6225Sab196087 	dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT);
6115088Sab196087 
612*6225Sab196087 	/*
613*6225Sab196087 	 * Commands that accept the DYN_OPT_F_DYNNDX_VAL form  of
614*6225Sab196087 	 * dynndx do not accept the 'elt' argument. The index is a
615*6225Sab196087 	 * value that follows the option, and was saved in argstate by
616*6225Sab196087 	 * process_args(). Routines that accept this form of -dynndx
617*6225Sab196087 	 * require the specified element to have a specific tag type,
618*6225Sab196087 	 * so we test for this as well as for the index being in range.
619*6225Sab196087 	 */
620*6225Sab196087 	if ((argstate->optmask & DYN_OPT_F_DYNNDX_VAL) != 0) {
621*6225Sab196087 		ndx = ((Word) elfedit_atoui_range(argstate->dyn_elt_str,
622*6225Sab196087 		    MSG_ORIG(MSG_STR_INDEX), 0, argstate->dyn.num - 1, NULL));
623*6225Sab196087 		if (argstate->dyn.data[ndx].d_tag != dt_value) {
624*6225Sab196087 			Half	mach = argstate->obj_state->os_ehdr->e_machine;
625*6225Sab196087 			Conv_inv_buf_t	is, want;
626*6225Sab196087 
627*6225Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_WRONGTAG),
628*6225Sab196087 			    EC_WORD(argstate->dyn.sec->sec_shndx),
629*6225Sab196087 			    argstate->dyn.sec->sec_name, ndx,
630*6225Sab196087 			    conv_dyn_tag(dt_value, mach, 0, &want),
631*6225Sab196087 			    conv_dyn_tag(argstate->dyn.data[ndx].d_tag, mach,
632*6225Sab196087 			    0, &is));
633*6225Sab196087 		}
634*6225Sab196087 		return (ndx);
635*6225Sab196087 	}
6365088Sab196087 
6375088Sab196087 	/*
6385088Sab196087 	 * If this is a printing request, then we let print_dyn() show
6395088Sab196087 	 * all the items with this tag type.
6405088Sab196087 	 */
6415088Sab196087 	if (print_request) {
6425088Sab196087 		*print_type = PRINT_DYN_T_TAG;
6435088Sab196087 		return (dt_value);
6445088Sab196087 	}
6455088Sab196087 
646*6225Sab196087 	/*
647*6225Sab196087 	 * Commands that accept -needed are looking for the dt_value element
648*6225Sab196087 	 * (usually DT_POSFLAG_1) that immediately preceeds the DT_NEEDED
649*6225Sab196087 	 * element with the string given by argstate->dyn_elt_str.
650*6225Sab196087 	 */
651*6225Sab196087 	if ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) {
652*6225Sab196087 		Word	retndx = argstate->dyn.num;	/* Out of range value */
653*6225Sab196087 		const char	*name;
654*6225Sab196087 		size_t		len;
655*6225Sab196087 
656*6225Sab196087 		len = strlen(argstate->dyn_elt_str);
657*6225Sab196087 		for (ndx = 0, dyn = argstate->dyn.data;
658*6225Sab196087 		    ndx < argstate->dyn.num; dyn++, ndx++) {
659*6225Sab196087 			/*
660*6225Sab196087 			 * If the immediately preceeding item has the
661*6225Sab196087 			 * tag type we're looking for, and the current item
662*6225Sab196087 			 * is a DT_NEEDED with a string that matches,
663*6225Sab196087 			 * then the preceeding item is the one we want.
664*6225Sab196087 			 */
665*6225Sab196087 			if ((dyn->d_tag == DT_NEEDED) &&
666*6225Sab196087 			    (ndx > 0) && (retndx == (ndx - 1))) {
667*6225Sab196087 				name = elfedit_offset_to_str(argstate->strsec,
668*6225Sab196087 				    dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
669*6225Sab196087 
670*6225Sab196087 				if (strncmp(name,
671*6225Sab196087 				    argstate->dyn_elt_str, len) == 0)
672*6225Sab196087 					return (retndx);
673*6225Sab196087 				continue;
674*6225Sab196087 			}
675*6225Sab196087 
676*6225Sab196087 			/*
677*6225Sab196087 			 * If the current item has the tag type we're
678*6225Sab196087 			 * looking for, make it our current candidate.
679*6225Sab196087 			 * If the next item is a DT_NEEDED with the right
680*6225Sab196087 			 * string value, we'll use it then.
681*6225Sab196087 			 */
682*6225Sab196087 			if (dyn->d_tag == dt_value)
683*6225Sab196087 				retndx = ndx;
684*6225Sab196087 		}
685*6225Sab196087 
686*6225Sab196087 		/* If we get here, no matching DT_NEEDED was found */
687*6225Sab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEDNOMATCH),
688*6225Sab196087 		    EC_WORD(argstate->dyn.sec->sec_shndx),
689*6225Sab196087 		    argstate->dyn.sec->sec_name, argstate->dyn_elt_str);
690*6225Sab196087 	}
691*6225Sab196087 
6925088Sab196087 	/* Locate the first entry with the given tag type */
6935088Sab196087 	for (ndx = 0; ndx < argstate->dyn.num; ndx++) {
6945088Sab196087 		if (argstate->dyn.data[ndx].d_tag == dt_value) {
6955088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
6965088Sab196087 			    MSG_INTL(MSG_DEBUG_DT2NDX),
6975088Sab196087 			    EC_WORD(argstate->dyn.sec->sec_shndx),
6985088Sab196087 			    argstate->dyn.sec->sec_name, EC_WORD(ndx), arg);
6995088Sab196087 			return (ndx);
7005088Sab196087 		}
7015088Sab196087 	}
7025088Sab196087 
7035088Sab196087 	/* Not found. Can we create one? */
7045088Sab196087 	if (argstate->dyn.num_null_ndx > 1)
7055088Sab196087 		return (convert_dt_null(argstate, dt_value, 0));
7065088Sab196087 
7075088Sab196087 	/* No room to create one, so we're out of options and must fail */
7085088Sab196087 	elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT),
7095088Sab196087 	    EC_WORD(argstate->dyn.sec->sec_shndx),
7105088Sab196087 	    argstate->dyn.sec->sec_name, arg);
7115088Sab196087 
7125088Sab196087 	/*NOTREACHED*/
7135088Sab196087 	return (0);		/* For lint */
7145088Sab196087 }
7155088Sab196087 
7165088Sab196087 
7175088Sab196087 /*
7185088Sab196087  * Called by cmd_body() for dyn:value. Implements the core functionality
7195088Sab196087  * for that command.
7205088Sab196087  *
7215088Sab196087  * This routine expects that both the index and value arguments are
7225088Sab196087  * present.
7235088Sab196087  */
7245088Sab196087 static elfedit_cmdret_t
7255088Sab196087 cmd_body_value(ARGSTATE *argstate, Word *ret_ndx)
7265088Sab196087 {
7275088Sab196087 	elfedit_section_t	*dynsec = argstate->dyn.sec;
7285088Sab196087 	elfedit_section_t	*strsec = argstate->strsec;
7295088Sab196087 	elfedit_dyn_elt_t	strpad_elt;
7305088Sab196087 	Word	i;
7315088Sab196087 	Dyn	*dyn = argstate->dyn.data;
7325088Sab196087 	Word	numdyn = argstate->dyn.num;
733*6225Sab196087 	int	minus_add, minus_s, minus_dynndx;
7345088Sab196087 	Word	arg1, tmp_val;
7355088Sab196087 	Xword	arg2;
7365088Sab196087 	int	arg2_known = 1;
7375088Sab196087 
738*6225Sab196087 	minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0);
739*6225Sab196087 	minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0);
740*6225Sab196087 	minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0);
7415088Sab196087 
7425088Sab196087 	elfedit_dyn_elt_init(&strpad_elt);
7435088Sab196087 
7445088Sab196087 	/*
7455088Sab196087 	 * The first argument is an index if -dynndx is used, and is a
7465088Sab196087 	 * tag value otherwise.
7475088Sab196087 	 */
7485088Sab196087 	arg1 = minus_dynndx ?
7495088Sab196087 	    elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT),
7505088Sab196087 	    0, numdyn - 1, NULL) :
7515088Sab196087 	    elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT);
7525088Sab196087 
7535088Sab196087 	if (minus_s) {
7545088Sab196087 		/*
7555088Sab196087 		 * Don't allow the user to specify -s when manipulating a
7565088Sab196087 		 * DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to
7575088Sab196087 		 * manage the extra space used for strings, this would break
7585088Sab196087 		 * our ability to add the string.
7595088Sab196087 		 */
7605088Sab196087 		if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) ||
7615088Sab196087 		    (minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD)))
7625088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
7635088Sab196087 			    MSG_INTL(MSG_ERR_STRPADSTRVAL),
7645088Sab196087 			    EC_WORD(dynsec->sec_shndx), dynsec->sec_name);
7655088Sab196087 
7665088Sab196087 		/* Locate DT_SUNW_STRPAD element if present */
7675088Sab196087 		strpad_elt.dn_dyn.d_un.d_val = 0;
7685088Sab196087 		(void) elfedit_dynstr_getpad(argstate->dyn.sec, &strpad_elt);
7695088Sab196087 
7705088Sab196087 		/*
7715088Sab196087 		 * Look up the string: If the user specified the -dynndx
7725088Sab196087 		 * -option, then we will insert it if possible, and
7735088Sab196087 		 * fail with an error if not. However, if they did not
7745088Sab196087 		 * specify -dynndx, we want to look up the string if it is
7755088Sab196087 		 * already there, but defer the insertion. The reason for
7765088Sab196087 		 * this is that we may have to grab an unused DT_NULL element
7775088Sab196087 		 * below, and if there are none available, we won't want
7785088Sab196087 		 * to have modified the string table.
7795088Sab196087 		 *
7805088Sab196087 		 * This isn't a problem, because if the string isn't
7815088Sab196087 		 * in the string table, it can't be used by a dynamic element.
7825088Sab196087 		 * Hence, we don't need to insert it to know that there is
7835088Sab196087 		 * no match.
7845088Sab196087 		 */
7855088Sab196087 		if (minus_dynndx == 0) {
7865088Sab196087 			if (elfedit_sec_findstr(strsec,
7875088Sab196087 			    strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1],
7885088Sab196087 			    &tmp_val) == 0) {
7895088Sab196087 				arg2_known = 0;
7905088Sab196087 			} else {
7915088Sab196087 				arg2 = tmp_val;
7925088Sab196087 			}
7935088Sab196087 		} else {
7945088Sab196087 			arg2 = elfedit_dynstr_insert(dynsec, strsec,
7955088Sab196087 			    &strpad_elt, argstate->argv[1]);
7965088Sab196087 		}
7975088Sab196087 	} else {		/* Argument 2 is an integer */
7985088Sab196087 		arg2 = elfedit_atoui(argstate->argv[1], NULL);
7995088Sab196087 	}
8005088Sab196087 
8015088Sab196087 
8025088Sab196087 	if (!minus_dynndx && !(minus_add && !arg2_known)) {
8035088Sab196087 		/*
8045088Sab196087 		 * Search the dynamic section and see if an item with the
8055088Sab196087 		 * specified tag value already exists. We can reduce this
8065088Sab196087 		 * to a simple update of an existing value if -add is not
8075088Sab196087 		 * specified or the existing d_un value matches the new one.
8085088Sab196087 		 *
8095088Sab196087 		 * In either of these cases, we will change arg1 to be the
8105088Sab196087 		 * index, and set minus_dynndx, causing the simple update to
8115088Sab196087 		 * happen immediately below.
8125088Sab196087 		 */
8135088Sab196087 		for (i = 0; i < numdyn; i++) {
8145088Sab196087 			if ((dyn[i].d_tag == arg1) &&
8155088Sab196087 			    (!minus_add || (dyn[i].d_un.d_val == arg2))) {
8165088Sab196087 				arg1 = i;
8175088Sab196087 				minus_dynndx = 1;
8185088Sab196087 				break;
8195088Sab196087 			}
8205088Sab196087 		}
8215088Sab196087 	}
8225088Sab196087 
8235088Sab196087 	/*
8245088Sab196087 	 * If -dynndx is used, then this is a relatively simple
8255088Sab196087 	 * operation, as we simply write over the specified index.
8265088Sab196087 	 */
8275088Sab196087 	if (minus_dynndx) {
8285088Sab196087 		/*
8295088Sab196087 		 * If we held back from inserting a new string into
8305088Sab196087 		 * the dynstr above, we insert it now, because we
8315088Sab196087 		 * have a slot in the dynamic section, and we need
8325088Sab196087 		 * the string offset ot finish.
8335088Sab196087 		 */
8345088Sab196087 		if (!arg2_known)
8355088Sab196087 			arg2 = elfedit_dynstr_insert(dynsec, strsec,
8365088Sab196087 			    &strpad_elt, argstate->argv[1]);
8375088Sab196087 
8385088Sab196087 		*ret_ndx = arg1;
8395088Sab196087 		if (dyn[arg1].d_un.d_val == arg2) {
8405088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
8415088Sab196087 			    MSG_INTL(MSG_DEBUG_X_OK),
8425088Sab196087 			    dynsec->sec_shndx, dynsec->sec_name,
8435088Sab196087 			    EC_WORD(arg1), EC_XWORD(arg2));
8445088Sab196087 			return (ELFEDIT_CMDRET_NONE);
8455088Sab196087 		} else {
8465088Sab196087 			/* Warn if setting DT_NULL value to non-zero */
8475088Sab196087 			if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0))
8485088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
8495088Sab196087 				    MSG_INTL(MSG_DEBUG_DTNULLVALUE),
8505088Sab196087 				    dynsec->sec_shndx, dynsec->sec_name,
8515088Sab196087 				    EC_WORD(arg1), EC_XWORD(arg2));
8525088Sab196087 
8535088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
8545088Sab196087 			    MSG_INTL(MSG_DEBUG_X_CHG),
8555088Sab196087 			    dynsec->sec_shndx, dynsec->sec_name,
8565088Sab196087 			    EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val),
8575088Sab196087 			    EC_XWORD(arg2));
8585088Sab196087 			dyn[arg1].d_un.d_val = arg2;
8595088Sab196087 			return (ELFEDIT_CMDRET_MOD);
8605088Sab196087 		}
8615088Sab196087 	}
8625088Sab196087 
8635088Sab196087 	/*
8645088Sab196087 	 * We need a new slot in the dynamic section. If we can't have
8655088Sab196087 	 * one, then we fail.
8665088Sab196087 	 */
8675088Sab196087 	if (argstate->dyn.num_null_ndx <= 1)
8685088Sab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL),
8695088Sab196087 		    EC_WORD(dynsec->sec_shndx), dynsec->sec_name);
8705088Sab196087 
8715088Sab196087 	/*
8725088Sab196087 	 * If we still need to insert a new string into the dynstr,
8735088Sab196087 	 * then it is safe now, because if we succeed, we know that
8745088Sab196087 	 * there is an available slot to receive it. If we fail, we
8755088Sab196087 	 * haven't claimed the extra slot yet, and it will be unharmed.
8765088Sab196087 	 */
8775088Sab196087 	if (!arg2_known)
8785088Sab196087 		arg2 = elfedit_dynstr_insert(dynsec, strsec,
8795088Sab196087 		    &strpad_elt, argstate->argv[1]);
8805088Sab196087 
8815088Sab196087 	/* Use an extra DT_NULL slot and enter the new element */
8825088Sab196087 	*ret_ndx = convert_dt_null(argstate, arg1, arg2);
8835088Sab196087 	return (ELFEDIT_CMDRET_MOD);
8845088Sab196087 }
8855088Sab196087 
8865088Sab196087 
8875088Sab196087 
8885088Sab196087 /*
8895088Sab196087  * Called by cmd_body() for dyn:runpath. Implements the core functionality
8905088Sab196087  * for that command.
8915088Sab196087  *
8925088Sab196087  * History Lesson And Strategy:
8935088Sab196087  *
8945088Sab196087  * This routine handles both DT_RPATH and DT_RUNPATH entries, altering
8955088Sab196087  * either or both if they are present.
8965088Sab196087  *
8975088Sab196087  * The original SYSV ABI only had DT_RPATH, and the runtime loader used
8985088Sab196087  * it to search for things in the following order:
8995088Sab196087  *
9005088Sab196087  *	DT_RPATH, LD_LIBRARY_PATH, defaults
9015088Sab196087  *
9025088Sab196087  * Solaris did not follow this rule, an extremely rare deviation from
9035088Sab196087  * the ABI. Environment variables should supercede everything else,
9045088Sab196087  * otherwise they are not very useful. This decision was made at the
9055088Sab196087  * very beginning of the SunOS 5.x development, so we have always
9065088Sab196087  * deviated from the ABI and and instead search in the order
9075088Sab196087  *
9085088Sab196087  *	LD_LIBRARY_PATH, DT_RPATH, defaults
9095088Sab196087  *
9105088Sab196087  * Other Unix variants initially followed the ABI, but in recent years
9115088Sab196087  * have come to agree with the early Solaris folks that it was a mistake.
9125088Sab196087  * Hence, DT_RUNPATH was invented, with the search order:
9135088Sab196087  *
9145088Sab196087  *	LD_LIBRARY_PATH, DT_RUNPATH, defaults
9155088Sab196087  *
9165088Sab196087  * So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both
9175088Sab196087  * are present (which does happen), we set them both to the new
9185088Sab196087  * value. If either one is present, we set that one. If neither is
9195088Sab196087  * present, and we have a spare DT_NULL slot, we create a DT_RUNPATH, but
9205088Sab196087  * not a DT_RPATH, to conserve available slots for other uses.
9215088Sab196087  */
9225088Sab196087 static elfedit_cmdret_t
9235088Sab196087 cmd_body_runpath(ARGSTATE *argstate)
9245088Sab196087 {
9255088Sab196087 	elfedit_section_t	*dynsec = argstate->dyn.sec;
9265088Sab196087 	elfedit_section_t	*strsec = argstate->strsec;
9275088Sab196087 	elfedit_dyn_elt_t	rpath_elt;
9285088Sab196087 	elfedit_dyn_elt_t	runpath_elt;
9295088Sab196087 	elfedit_dyn_elt_t	strpad_elt;
9305088Sab196087 	Word			i;
9315088Sab196087 	Dyn			*dyn = argstate->dyn.data;
9325088Sab196087 	Word			numdyn = argstate->dyn.num;
9335088Sab196087 
9345088Sab196087 	/* Go through the tags and gather what we need */
9355088Sab196087 	elfedit_dyn_elt_init(&rpath_elt);
9365088Sab196087 	elfedit_dyn_elt_init(&runpath_elt);
9375088Sab196087 	elfedit_dyn_elt_init(&strpad_elt);
9385088Sab196087 	for (i = 0; i < numdyn; i++) {
9395088Sab196087 		switch (dyn[i].d_tag) {
9405088Sab196087 		case DT_RPATH:
9415088Sab196087 			elfedit_dyn_elt_save(&rpath_elt, i, &dyn[i]);
9425088Sab196087 			break;
9435088Sab196087 
9445088Sab196087 		case DT_RUNPATH:
9455088Sab196087 			elfedit_dyn_elt_save(&runpath_elt, i, &dyn[i]);
9465088Sab196087 			break;
9475088Sab196087 
9485088Sab196087 		case DT_SUNW_STRPAD:
9495088Sab196087 			elfedit_dyn_elt_save(&strpad_elt, i, &dyn[i]);
9505088Sab196087 			break;
9515088Sab196087 		}
9525088Sab196087 	}
9535088Sab196087 
9545088Sab196087 	/*  Do we have an available dynamic section entry to use? */
9555088Sab196087 	if (rpath_elt.dn_seen || runpath_elt.dn_seen) {
9565088Sab196087 		/*
9575088Sab196087 		 * We have seen a DT_RPATH, or a DT_RUNPATH, or both.
9585088Sab196087 		 * If all of these have the same string as the desired
9595088Sab196087 		 * new value, then we don't need to alter anything and can
9605088Sab196087 		 * simply return. Otherwise, we'll modify them all to have
9615088Sab196087 		 * the new string (below).
9625088Sab196087 		 */
9635088Sab196087 		if ((!rpath_elt.dn_seen ||
9645088Sab196087 		    (strcmp(elfedit_dyn_offset_to_str(strsec, &rpath_elt),
9655088Sab196087 		    argstate->argv[0]) == 0)) &&
9665088Sab196087 		    (!runpath_elt.dn_seen ||
9675088Sab196087 		    (strcmp(elfedit_dyn_offset_to_str(strsec, &runpath_elt),
9685088Sab196087 		    argstate->argv[0]) == 0))) {
9695088Sab196087 			if (rpath_elt.dn_seen)
9705088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
9715088Sab196087 				    MSG_INTL(MSG_DEBUG_OLDRPATHOK),
9725088Sab196087 				    EC_WORD(dynsec->sec_shndx),
9735088Sab196087 				    dynsec->sec_name, EC_WORD(rpath_elt.dn_ndx),
9745088Sab196087 				    elfedit_atoconst_value_to_str(
9755088Sab196087 				    ELFEDIT_CONST_DT, DT_RPATH, 1));
9765088Sab196087 			if (runpath_elt.dn_seen)
9775088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
9785088Sab196087 				    MSG_INTL(MSG_DEBUG_OLDRPATHOK),
9795088Sab196087 				    EC_WORD(dynsec->sec_shndx),
9805088Sab196087 				    dynsec->sec_name,
9815088Sab196087 				    EC_WORD(runpath_elt.dn_ndx),
9825088Sab196087 				    elfedit_atoconst_value_to_str(
9835088Sab196087 				    ELFEDIT_CONST_DT, DT_RUNPATH, 1));
9845088Sab196087 			return (ELFEDIT_CMDRET_NONE);
9855088Sab196087 		}
9865088Sab196087 	} else if (argstate->dyn.num_null_ndx <= 1) {
9875088Sab196087 		/*
9885088Sab196087 		 * There is no DT_RPATH or DT_RUNPATH in the dynamic array,
9895088Sab196087 		 * and there are no extra DT_NULL entries that we can
9905088Sab196087 		 * convert into one. We cannot proceed.
9915088Sab196087 		 */
9925088Sab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL),
9935088Sab196087 		    EC_WORD(dynsec->sec_shndx), dynsec->sec_name);
9945088Sab196087 	}
9955088Sab196087 
9965088Sab196087 	/* Does the string exist in the table already, or can we add it? */
9975088Sab196087 	rpath_elt.dn_dyn.d_un.d_val = runpath_elt.dn_dyn.d_un.d_val =
9985088Sab196087 	    elfedit_dynstr_insert(dynsec, strsec, &strpad_elt,
9995088Sab196087 	    argstate->argv[0]);
10005088Sab196087 
10015088Sab196087 	/* Update DT_RPATH entry if present */
10025088Sab196087 	if (rpath_elt.dn_seen) {
10035088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_PREVRPATH),
10045088Sab196087 		    EC_WORD(dynsec->sec_shndx), dynsec->sec_name,
10055088Sab196087 		    EC_WORD(rpath_elt.dn_ndx),
10065088Sab196087 		    elfedit_atoconst_value_to_str(
10075088Sab196087 		    ELFEDIT_CONST_DT, DT_RPATH, 1),
10085088Sab196087 		    elfedit_dyn_offset_to_str(strsec, &rpath_elt));
10095088Sab196087 		dyn[rpath_elt.dn_ndx] = rpath_elt.dn_dyn;
10105088Sab196087 	}
10115088Sab196087 
10125088Sab196087 	/*
10135088Sab196087 	 * Update the DT_RUNPATH entry in the dynamic section, if present.
10145088Sab196087 	 * If one is not present, and there is also no DT_RPATH, then
10155088Sab196087 	 * we use a spare DT_NULL entry to create a new DT_RUNPATH.
10165088Sab196087 	 */
10175088Sab196087 	if (runpath_elt.dn_seen || !rpath_elt.dn_seen) {
10185088Sab196087 		if (runpath_elt.dn_seen) {
10195088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
10205088Sab196087 			    MSG_INTL(MSG_DEBUG_PREVRPATH),
10215088Sab196087 			    EC_WORD(dynsec->sec_shndx), dynsec->sec_name,
10225088Sab196087 			    EC_WORD(runpath_elt.dn_ndx),
10235088Sab196087 			    elfedit_atoconst_value_to_str(
10245088Sab196087 			    ELFEDIT_CONST_DT, DT_RUNPATH, 1),
10255088Sab196087 			    elfedit_dyn_offset_to_str(strsec, &runpath_elt));
10265088Sab196087 			dyn[runpath_elt.dn_ndx] = runpath_elt.dn_dyn;
10275088Sab196087 		} else {	/* Using a spare DT_NULL entry */
10285088Sab196087 			(void) convert_dt_null(argstate, DT_RUNPATH,
10295088Sab196087 			    runpath_elt.dn_dyn.d_un.d_val);
10305088Sab196087 		}
10315088Sab196087 	}
10325088Sab196087 
10335088Sab196087 	return (ELFEDIT_CMDRET_MOD);
10345088Sab196087 }
10355088Sab196087 
10365088Sab196087 
10375088Sab196087 
10385088Sab196087 /*
10395088Sab196087  * Argument processing for the bitmask commands. Convert the arguments
10405088Sab196087  * to integer form, apply -and/-cmp/-or, and return the resulting value.
10415088Sab196087  *
10425088Sab196087  * entry:
10435088Sab196087  *	argstate - Argument state block
10445088Sab196087  *	orig - Value of original bitmask
10455088Sab196087  *	const_type - ELFEDIT_CONST_* value for type of constants
10465088Sab196087  */
10475088Sab196087 static Word
10485088Sab196087 flag_bitop(ARGSTATE *argstate, Word orig, elfedit_const_t const_type)
10495088Sab196087 {
10505088Sab196087 	Word flags = 0;
10515088Sab196087 	int i;
10525088Sab196087 
10535088Sab196087 	/* Collect the arguments */
10545088Sab196087 	for (i = 0; i < argstate->argc; i++)
10555088Sab196087 		flags |= (Word) elfedit_atoconst(argstate->argv[i], const_type);
10565088Sab196087 
10575088Sab196087 	/* Complement the value? */
10585088Sab196087 	if (argstate->optmask & DYN_OPT_F_CMP)
10595088Sab196087 		flags = ~flags;
10605088Sab196087 
10615088Sab196087 	/* Perform any requested bit operations */
10625088Sab196087 	if (argstate->optmask & DYN_OPT_F_AND)
10635088Sab196087 		flags &= orig;
10645088Sab196087 	else if (argstate->optmask & DYN_OPT_F_OR)
10655088Sab196087 		flags |= orig;
10665088Sab196087 
10675088Sab196087 	return (flags);
10685088Sab196087 }
10695088Sab196087 
10705088Sab196087 
10715088Sab196087 
10725088Sab196087 /*
10735088Sab196087  * Common body for the dyn: module commands. These commands
10745088Sab196087  * share a large amount of common behavior, so it is convenient
10755088Sab196087  * to centralize things and use the cmd argument to handle the
10765088Sab196087  * small differences.
10775088Sab196087  *
10785088Sab196087  * entry:
10795088Sab196087  *	cmd - One of the DYN_CMD_T_* constants listed above, specifying
10805088Sab196087  *		which command to implement.
10815088Sab196087  *	obj_state, argc, argv - Standard command arguments
10825088Sab196087  */
10835088Sab196087 static elfedit_cmdret_t
10845088Sab196087 cmd_body(DYN_CMD_T cmd, elfedit_obj_state_t *obj_state,
10855088Sab196087     int argc, const char *argv[])
10865088Sab196087 {
10875088Sab196087 	ARGSTATE		argstate;
10885088Sab196087 	Dyn			*dyn;
10895088Sab196087 	const char		*dyn_name;
10905088Sab196087 	Word			dyn_ndx, dyn_num, null_ndx;
10915088Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
10925088Sab196087 	PRINT_DYN_T		print_type = PRINT_DYN_T_ALL;
10935088Sab196087 	Word			ndx;
10945088Sab196087 	int			print_only = 0;
10955088Sab196087 	int			do_autoprint = 1;
10965088Sab196087 
10975088Sab196087 	/* Process the optional arguments */
10985088Sab196087 	process_args(obj_state, argc, argv, &argstate);
10995088Sab196087 
11005088Sab196087 	dyn = argstate.dyn.data;
11015088Sab196087 	dyn_num = argstate.dyn.num;
11025088Sab196087 	dyn_name = argstate.dyn.sec->sec_name;
11035088Sab196087 	dyn_ndx = argstate.dyn.sec->sec_shndx;
11045088Sab196087 
11055088Sab196087 	/* Check number of arguments, gather information */
11065088Sab196087 	switch (cmd) {
11075088Sab196087 	case DYN_CMD_T_DUMP:
11085088Sab196087 		/* dyn:dump can accept an optional index argument */
11095088Sab196087 		if (argstate.argc > 1)
11105088Sab196087 			elfedit_command_usage();
11115088Sab196087 		print_only = 1;
11125088Sab196087 		if (argstate.argc == 1)
11135088Sab196087 			ndx = arg_to_index(&argstate, argstate.argv[0],
1114*6225Sab196087 			    print_only, &print_type);
11155088Sab196087 		break;
11165088Sab196087 
11175088Sab196087 	case DYN_CMD_T_TAG:
11185088Sab196087 		print_only = (argstate.argc != 2);
11195088Sab196087 		if (argstate.argc > 0) {
11205088Sab196087 			if (argstate.argc > 2)
11215088Sab196087 				elfedit_command_usage();
11225088Sab196087 			ndx = arg_to_index(&argstate, argstate.argv[0],
1123*6225Sab196087 			    print_only, &print_type);
11245088Sab196087 		}
11255088Sab196087 		break;
11265088Sab196087 
11275088Sab196087 	case DYN_CMD_T_VALUE:
11285088Sab196087 		print_only = (argstate.argc != 2);
11295088Sab196087 		if (argstate.argc > 2)
11305088Sab196087 			elfedit_command_usage();
11315088Sab196087 		if (argstate.argc > 0) {
11325088Sab196087 			if (print_only) {
11335088Sab196087 				ndx = arg_to_index(&argstate, argstate.argv[0],
11345088Sab196087 				    print_only, &print_type);
11355088Sab196087 			} else {
11365088Sab196087 				print_type = PRINT_DYN_T_NDX;
11375088Sab196087 			}
11385088Sab196087 		}
11395088Sab196087 		break;
11405088Sab196087 
11415088Sab196087 	case DYN_CMD_T_DELETE:
11425088Sab196087 		if ((argstate.argc < 1) || (argstate.argc > 2))
11435088Sab196087 			elfedit_command_usage();
11445088Sab196087 		ndx = arg_to_index(&argstate, argstate.argv[0],
11455088Sab196087 		    0, &print_type);
11465088Sab196087 		do_autoprint = 0;
11475088Sab196087 		break;
11485088Sab196087 
11495088Sab196087 	case DYN_CMD_T_MOVE:
11505088Sab196087 		if ((argstate.argc < 2) || (argstate.argc > 3))
11515088Sab196087 			elfedit_command_usage();
11525088Sab196087 		ndx = arg_to_index(&argstate, argstate.argv[0],
1153*6225Sab196087 		    0, &print_type);
11545088Sab196087 		do_autoprint = 0;
11555088Sab196087 		break;
11565088Sab196087 
11575088Sab196087 	case DYN_CMD_T_RUNPATH:
11585088Sab196087 		if (argstate.argc > 1)
11595088Sab196087 			elfedit_command_usage();
11605088Sab196087 		/*
11615088Sab196087 		 * dyn:runpath does not accept an explicit index
11625088Sab196087 		 * argument, so we implicitly only show the DT_RPATH and
11635088Sab196087 		 * DT_RUNPATH elements.
11645088Sab196087 		 */
11655088Sab196087 		print_type = PRINT_DYN_T_RUNPATH;
11665088Sab196087 		print_only = (argstate.argc == 0);
11675088Sab196087 		break;
11685088Sab196087 
11695088Sab196087 	case DYN_CMD_T_POSFLAG1:
11705088Sab196087 		print_only = (argstate.argc == 0);
11715088Sab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
11725088Sab196087 		    ELFEDIT_CONST_DT, DT_POSFLAG_1, 1),
1173*6225Sab196087 		    print_only, &print_type);
11745088Sab196087 		break;
11755088Sab196087 
11765088Sab196087 	case DYN_CMD_T_FLAGS:
11775088Sab196087 		print_only = (argstate.argc == 0);
11785088Sab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
11795088Sab196087 		    ELFEDIT_CONST_DT, DT_FLAGS, 1),
1180*6225Sab196087 		    print_only, &print_type);
11815088Sab196087 		break;
11825088Sab196087 
11835088Sab196087 	case DYN_CMD_T_FLAGS1:
11845088Sab196087 		print_only = (argstate.argc == 0);
11855088Sab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
11865088Sab196087 		    ELFEDIT_CONST_DT, DT_FLAGS_1, 1),
1187*6225Sab196087 		    print_only, &print_type);
11885088Sab196087 		break;
11895088Sab196087 
11905088Sab196087 	case DYN_CMD_T_FEATURE1:
11915088Sab196087 		print_only = (argstate.argc == 0);
11925088Sab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
11935088Sab196087 		    ELFEDIT_CONST_DT, DT_FEATURE_1, 1),
1194*6225Sab196087 		    print_only, &print_type);
11955088Sab196087 		break;
11965088Sab196087 
11975088Sab196087 	case DYN_CMD_T_CHECKSUM:
11985088Sab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
11995088Sab196087 		    ELFEDIT_CONST_DT, DT_CHECKSUM, 1),
1200*6225Sab196087 		    print_only, &print_type);
12015088Sab196087 		break;
12025088Sab196087 
12036206Sab196087 	case DYN_CMD_T_SUNW_LDMACH:
12046206Sab196087 		if (argstate.argc > 1)
12056206Sab196087 			elfedit_command_usage();
12066206Sab196087 		print_only = (argstate.argc == 0);
12076206Sab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
12086206Sab196087 		    ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1),
1209*6225Sab196087 		    print_only, &print_type);
12106206Sab196087 		break;
12116206Sab196087 
12125088Sab196087 	default:
12135088Sab196087 		/* Note expected: All commands should have been caught above */
12145088Sab196087 		elfedit_command_usage();
12155088Sab196087 		break;
12165088Sab196087 	}
12175088Sab196087 
12185088Sab196087 
12195088Sab196087 	/* If this is a request to print current values, do it and return */
12205088Sab196087 	if (print_only) {
12215088Sab196087 		print_dyn(cmd, 0, &argstate, print_type, ndx);
12225088Sab196087 		return (ELFEDIT_CMDRET_NONE);
12235088Sab196087 	}
12245088Sab196087 
12255088Sab196087 
12265088Sab196087 	switch (cmd) {
12275088Sab196087 		/*
12285088Sab196087 		 * DYN_CMD_T_DUMP can't get here: It is a print-only
12295088Sab196087 		 * command.
12305088Sab196087 		 */
12315088Sab196087 
12325088Sab196087 	case DYN_CMD_T_TAG:
12335088Sab196087 		{
12345088Sab196087 			Conv_inv_buf_t	inv_buf1, inv_buf2;
12355088Sab196087 			Half	mach = argstate.obj_state->os_ehdr->e_machine;
12365088Sab196087 			Word d_tag = (Word) elfedit_atoconst(argstate.argv[1],
12375088Sab196087 			    ELFEDIT_CONST_DT);
12385088Sab196087 
12395088Sab196087 			if (dyn[ndx].d_tag == d_tag) {
12405088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
12415088Sab196087 				    MSG_INTL(MSG_DEBUG_S_OK),
12425088Sab196087 				    dyn_ndx,
12435088Sab196087 				    dyn_name, EC_WORD(ndx),
12445088Sab196087 				    conv_dyn_tag(d_tag, mach, 0, &inv_buf1));
12455088Sab196087 			} else {
12465088Sab196087 				Word orig_d_tag = dyn[ndx].d_tag;
12475088Sab196087 
12485088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
12495088Sab196087 				dyn[ndx].d_tag = d_tag;
12505088Sab196087 
12515088Sab196087 				/*
12525088Sab196087 				 * Update null termination index. Warn if we
12535088Sab196087 				 * just clobbered the only DT_NULL termination
12545088Sab196087 				 * for the array.
12555088Sab196087 				 */
12565088Sab196087 				null_ndx = argstate.dyn.null_ndx;
12575088Sab196087 				set_null_ndx(&argstate);
12585088Sab196087 				if ((argstate.dyn.null_ndx >=
12595088Sab196087 				    argstate.dyn.num) &&
12605088Sab196087 				    (null_ndx != argstate.dyn.null_ndx))
12615088Sab196087 					elfedit_msg(ELFEDIT_MSG_DEBUG,
12625088Sab196087 					    MSG_INTL(MSG_DEBUG_NULLTERM),
12635088Sab196087 					    dyn_ndx, dyn_name,
12645088Sab196087 					    EC_WORD(ndx),
12655088Sab196087 					    conv_dyn_tag(d_tag, mach,
12665088Sab196087 					    0, &inv_buf1));
12675088Sab196087 
12685088Sab196087 				/*
12695088Sab196087 				 * Warning if
12705088Sab196087 				 *	- Inserting a DT_NULL cuts off following
12715088Sab196087 				 *		non-null elements.
12725088Sab196087 				 *	- Inserting a non-DT_NULL after the
12735088Sab196087 				 *		first null element, will be
12745088Sab196087 				 *		ignored by rtld.
12755088Sab196087 				 */
12765088Sab196087 				if (d_tag == DT_NULL) {
12775088Sab196087 					if ((ndx + 1) < null_ndx)
12785088Sab196087 						elfedit_msg(ELFEDIT_MSG_DEBUG,
12795088Sab196087 						    MSG_INTL(MSG_DEBUG_NULCLIP),
12805088Sab196087 						    dyn_ndx, dyn_name,
12815088Sab196087 						    EC_WORD(ndx),
12825088Sab196087 						    conv_dyn_tag(d_tag, mach,
12835088Sab196087 						    0, &inv_buf1));
12845088Sab196087 				} else {
12855088Sab196087 					if ((ndx + 1) > argstate.dyn.null_ndx)
12865088Sab196087 						elfedit_msg(ELFEDIT_MSG_DEBUG,
12875088Sab196087 						    MSG_INTL(MSG_DEBUG_NULHIDE),
12885088Sab196087 						    dyn_ndx, dyn_name,
12895088Sab196087 						    EC_WORD(ndx),
12905088Sab196087 						    conv_dyn_tag(d_tag, mach,
12915088Sab196087 						    0, &inv_buf1));
12925088Sab196087 				}
12935088Sab196087 
12945088Sab196087 				/* Debug message that we changed it */
12955088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
12965088Sab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
12975088Sab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
12985088Sab196087 				    conv_dyn_tag(orig_d_tag, mach, 0,
12995088Sab196087 				    &inv_buf1),
13005088Sab196087 				    conv_dyn_tag(d_tag, mach, 0, &inv_buf2));
13015088Sab196087 			}
13025088Sab196087 		}
13035088Sab196087 		break;
13045088Sab196087 
13055088Sab196087 	case DYN_CMD_T_VALUE:
13065088Sab196087 		ret = cmd_body_value(&argstate, &ndx);
13075088Sab196087 		break;
13085088Sab196087 
13095088Sab196087 	case DYN_CMD_T_DELETE:
13105088Sab196087 		{
13115088Sab196087 			Word cnt = (argstate.argc == 1) ? 1 :
13125088Sab196087 			    (Word) elfedit_atoui_range(argstate.argv[1],
13135088Sab196087 			    MSG_ORIG(MSG_STR_COUNT), 1, dyn_num - ndx, NULL);
13145088Sab196087 			const char *msg_prefix =
13155088Sab196087 			    elfedit_sec_msgprefix(argstate.dyn.sec);
13165088Sab196087 
13175088Sab196087 			elfedit_array_elts_delete(msg_prefix, argstate.dyn.data,
13185088Sab196087 			    sizeof (Dyn), dyn_num, ndx, cnt);
13195088Sab196087 			ret = ELFEDIT_CMDRET_MOD;
13205088Sab196087 		}
13215088Sab196087 		break;
13225088Sab196087 
13235088Sab196087 	case DYN_CMD_T_MOVE:
13245088Sab196087 		{
13255088Sab196087 			Dyn	save;
13265088Sab196087 			Word	cnt;
13275088Sab196087 			Word	dstndx;
13285088Sab196087 			const char *msg_prefix =
13295088Sab196087 			    elfedit_sec_msgprefix(argstate.dyn.sec);
13305088Sab196087 
13315088Sab196087 			dstndx = (Word)
13325088Sab196087 			    elfedit_atoui_range(argstate.argv[1],
13335088Sab196087 			    MSG_ORIG(MSG_STR_DST_INDEX), 0, dyn_num - 1,
13345088Sab196087 			    NULL);
13355088Sab196087 			if (argstate.argc == 2) {
13365088Sab196087 				cnt = 1;
13375088Sab196087 			} else {
13385088Sab196087 				cnt = (Word) elfedit_atoui_range(
13395088Sab196087 				    argstate.argv[2], MSG_ORIG(MSG_STR_COUNT),
13405088Sab196087 				    1, dyn_num, NULL);
13415088Sab196087 			}
13425088Sab196087 			elfedit_array_elts_move(msg_prefix, argstate.dyn.data,
13435088Sab196087 			    sizeof (save), dyn_num, ndx, dstndx, cnt, &save);
13445088Sab196087 			ret = ELFEDIT_CMDRET_MOD;
13455088Sab196087 		}
13465088Sab196087 		break;
13475088Sab196087 
13485088Sab196087 
13495088Sab196087 	case DYN_CMD_T_RUNPATH:
13505088Sab196087 		ret = cmd_body_runpath(&argstate);
13515088Sab196087 		break;
13525088Sab196087 
13535088Sab196087 	case DYN_CMD_T_POSFLAG1:
13545088Sab196087 		{
13555088Sab196087 			Conv_dyn_posflag1_buf_t buf1, buf2;
13565088Sab196087 			Word flags;
13575088Sab196087 
13585088Sab196087 			flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
13595088Sab196087 			    ELFEDIT_CONST_DF_P1);
13605088Sab196087 
13615088Sab196087 			/* Set the value */
13625088Sab196087 			if (dyn[ndx].d_un.d_val == flags) {
13635088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
13645088Sab196087 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
13655088Sab196087 				    dyn_name, EC_WORD(ndx),
13665088Sab196087 				    conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0,
13675088Sab196087 				    &buf1));
13685088Sab196087 			} else {
13695088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
13705088Sab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
13715088Sab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
13725088Sab196087 				    conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0,
13735088Sab196087 				    &buf1),
13745088Sab196087 				    conv_dyn_posflag1(flags, 0, &buf2));
13755088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
13765088Sab196087 				dyn[ndx].d_un.d_val = flags;
13775088Sab196087 			}
13785088Sab196087 		}
13795088Sab196087 		break;
13805088Sab196087 
13815088Sab196087 	case DYN_CMD_T_FLAGS:
13825088Sab196087 		{
13835088Sab196087 			Conv_dyn_flag_buf_t buf1, buf2;
13845088Sab196087 			Word flags;
13855088Sab196087 
13865088Sab196087 			flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
13875088Sab196087 			    ELFEDIT_CONST_DF);
13885088Sab196087 
13895088Sab196087 			/* Set the value */
13905088Sab196087 			if (dyn[ndx].d_un.d_val == flags) {
13915088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
13925088Sab196087 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
13935088Sab196087 				    dyn_name, EC_WORD(ndx),
13945088Sab196087 				    conv_dyn_flag(dyn[ndx].d_un.d_val, 0,
13955088Sab196087 				    &buf1));
13965088Sab196087 			} else {
13975088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
13985088Sab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
13995088Sab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
14005088Sab196087 				    conv_dyn_flag(dyn[ndx].d_un.d_val, 0,
14015088Sab196087 				    &buf1),
14025088Sab196087 				    conv_dyn_flag(flags, 0, &buf2));
14035088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
14045088Sab196087 				dyn[ndx].d_un.d_val = flags;
14055088Sab196087 			}
14065088Sab196087 		}
14075088Sab196087 		break;
14085088Sab196087 
14095088Sab196087 	case DYN_CMD_T_FLAGS1:
14105088Sab196087 		{
14115088Sab196087 			Conv_dyn_flag1_buf_t buf1, buf2;
14125088Sab196087 			Word flags1;
14135088Sab196087 
14145088Sab196087 			flags1 = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
14155088Sab196087 			    ELFEDIT_CONST_DF_1);
14165088Sab196087 
14175088Sab196087 			/* Set the value */
14185088Sab196087 			if (dyn[ndx].d_un.d_val == flags1) {
14195088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
14205088Sab196087 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
14215088Sab196087 				    dyn_name, EC_WORD(ndx),
14225088Sab196087 				    conv_dyn_flag1(dyn[ndx].d_un.d_val,
14235088Sab196087 				    0, &buf1));
14245088Sab196087 			} else {
14255088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
14265088Sab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
14275088Sab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
14285088Sab196087 				    conv_dyn_flag1(dyn[ndx].d_un.d_val,
14295088Sab196087 				    0, &buf1),
14305088Sab196087 				    conv_dyn_flag1(flags1, 0, &buf2));
14315088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
14325088Sab196087 				dyn[ndx].d_un.d_val = flags1;
14335088Sab196087 			}
14345088Sab196087 		}
14355088Sab196087 		break;
14365088Sab196087 
14375088Sab196087 	case DYN_CMD_T_FEATURE1:
14385088Sab196087 		{
14395088Sab196087 			Conv_dyn_feature1_buf_t buf1, buf2;
14405088Sab196087 			Word flags;
14415088Sab196087 
14425088Sab196087 			flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
14435088Sab196087 			    ELFEDIT_CONST_DTF_1);
14445088Sab196087 
14455088Sab196087 			/* Set the value */
14465088Sab196087 			if (dyn[ndx].d_un.d_val == flags) {
14475088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
14485088Sab196087 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
14495088Sab196087 				    dyn_name, EC_WORD(ndx),
14505088Sab196087 				    conv_dyn_feature1(dyn[ndx].d_un.d_val, 0,
14515088Sab196087 				    &buf1));
14525088Sab196087 			} else {
14535088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
14545088Sab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
14555088Sab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
14565088Sab196087 				    conv_dyn_feature1(dyn[ndx].d_un.d_val, 0,
14575088Sab196087 				    &buf1),
14585088Sab196087 				    conv_dyn_feature1(flags, 0, &buf2));
14595088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
14605088Sab196087 				dyn[ndx].d_un.d_val = flags;
14615088Sab196087 			}
14625088Sab196087 		}
14635088Sab196087 		break;
14645088Sab196087 
14655088Sab196087 	case DYN_CMD_T_CHECKSUM:
14665088Sab196087 		{
14675088Sab196087 			long checksum = elf_checksum(obj_state->os_elf);
14685088Sab196087 
14695088Sab196087 			/* Set the value */
14705088Sab196087 			if (dyn[ndx].d_un.d_val == checksum) {
14715088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
14725088Sab196087 				    MSG_INTL(MSG_DEBUG_X_OK), dyn_ndx,
14735088Sab196087 				    dyn_name, EC_WORD(ndx), EC_XWORD(checksum));
14745088Sab196087 			} else {
14755088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
14765088Sab196087 				    MSG_INTL(MSG_DEBUG_X_CHG),
14775088Sab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
14785088Sab196087 				    EC_XWORD(dyn[ndx].d_un.d_val),
14795088Sab196087 				    EC_XWORD(checksum));
14805088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
14815088Sab196087 				dyn[ndx].d_un.d_val = checksum;
14825088Sab196087 			}
14835088Sab196087 
14845088Sab196087 		}
14856206Sab196087 		break;
14866206Sab196087 
14876206Sab196087 	case DYN_CMD_T_SUNW_LDMACH:
14886206Sab196087 		{
14896206Sab196087 			Conv_inv_buf_t buf1, buf2;
14906206Sab196087 			Half ldmach;
14916206Sab196087 
14926206Sab196087 			ldmach = (Half) elfedit_atoconst(argstate.argv[0],
14936206Sab196087 			    ELFEDIT_CONST_EM);
14946206Sab196087 
14956206Sab196087 			/* Set the value */
14966206Sab196087 			if (dyn[ndx].d_un.d_val == ldmach) {
14976206Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
14986206Sab196087 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
14996206Sab196087 				    dyn_name, EC_WORD(ndx),
15006206Sab196087 				    conv_ehdr_mach(dyn[ndx].d_un.d_val, 0,
15016206Sab196087 				    &buf1));
15026206Sab196087 			} else {
15036206Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
15046206Sab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
15056206Sab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
15066206Sab196087 				    conv_ehdr_mach(dyn[ndx].d_un.d_val, 0,
15076206Sab196087 				    &buf1),
15086206Sab196087 				    conv_ehdr_mach(ldmach, 0, &buf2));
15096206Sab196087 				ret = ELFEDIT_CMDRET_MOD;
15106206Sab196087 				dyn[ndx].d_un.d_val = ldmach;
15116206Sab196087 			}
15126206Sab196087 		}
15136206Sab196087 		break;
15146206Sab196087 
15155088Sab196087 	}
15165088Sab196087 
15175088Sab196087 	/*
15185088Sab196087 	 * If we modified the dynamic section header, tell libelf.
15195088Sab196087 	 */
15205088Sab196087 	if (ret == ELFEDIT_CMDRET_MOD)
15215088Sab196087 		elfedit_modified_data(argstate.dyn.sec);
15225088Sab196087 
15235088Sab196087 	/* Do autoprint */
15245088Sab196087 	if (do_autoprint)
15255088Sab196087 		print_dyn(cmd, 1, &argstate, print_type, ndx);
15265088Sab196087 
15275088Sab196087 	return (ret);
15285088Sab196087 }
15295088Sab196087 
15305088Sab196087 
15315088Sab196087 
15325088Sab196087 /*
15335088Sab196087  * Command completion functions for the commands
15345088Sab196087  */
15355088Sab196087 
15365088Sab196087 /*
15375088Sab196087  * Command completion for the first argument, which specifies
15385088Sab196087  * the dynamic element to use. Examines the options to see if
15395088Sab196087  * -dynndx is present, and if not, supplies the completion
15405088Sab196087  * strings for argument 1.
15415088Sab196087  */
15425088Sab196087 /*ARGSUSED*/
15435088Sab196087 static void
15445088Sab196087 cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
15455088Sab196087     const char *argv[], int num_opt)
15465088Sab196087 {
15475088Sab196087 	elfedit_section_t	*cache;
15485088Sab196087 	Dyn			*dyn;
15495088Sab196087 	Word			i;
15505088Sab196087 	const char		*s;
15515088Sab196087 	char			*s2;
15525088Sab196087 	char			buf[128];
15535088Sab196087 
15545088Sab196087 	/* Make sure it's the first argument */
15555088Sab196087 	if ((argc - num_opt) != 1)
15565088Sab196087 		return;
15575088Sab196087 
15585088Sab196087 	/* Is -dynndx present? If so, we don't complete tag types */
15595088Sab196087 	for (i = 0; i < num_opt; i++)
15605088Sab196087 		if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0)
15615088Sab196087 			return;
15625088Sab196087 
15635088Sab196087 	/*
15645088Sab196087 	 * If there is no object, or if there is no dynamic section,
15655088Sab196087 	 * then supply all possible names.
15665088Sab196087 	 */
15675088Sab196087 	if ((obj_state == NULL) || (obj_state->os_dynndx == SHN_UNDEF)) {
15685088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT);
15695088Sab196087 		return;
15705088Sab196087 	}
15715088Sab196087 
15725088Sab196087 	/* Supply completions for the tags present in the dynamic section */
15735088Sab196087 	cache = &obj_state->os_secarr[obj_state->os_dynndx];
15745088Sab196087 	dyn = (Dyn *) cache->sec_data->d_buf;
15755088Sab196087 	i = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize;
15765088Sab196087 	for (; i-- > 0; dyn++) {
15775088Sab196087 		s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_DT,
15785088Sab196087 		    dyn->d_tag, 0);
15795088Sab196087 		if (s == NULL)
15805088Sab196087 			continue;
15815088Sab196087 		elfedit_cpl_match(cpldata, s, 1);
15825088Sab196087 
15835088Sab196087 		/*
15845088Sab196087 		 * To get the informal tag names that are lowercase
15855088Sab196087 		 * and lack the leading DT_, we copy the string we
15865088Sab196087 		 * have into a buffer and process it.
15875088Sab196087 		 */
15885088Sab196087 		if (strlen(s) < 3)
15895088Sab196087 			continue;
15905088Sab196087 		(void) strlcpy(buf, s + 3, sizeof (buf));
15915088Sab196087 		for (s2 = buf; *s2 != '\0'; s2++)
15925088Sab196087 			if (isupper(*s2))
15935088Sab196087 				*s2 = tolower(*s2);
15945088Sab196087 		elfedit_cpl_match(cpldata, buf, 1);
15955088Sab196087 	}
15965088Sab196087 }
15975088Sab196087 
15985088Sab196087 
15995088Sab196087 /*ARGSUSED*/
16005088Sab196087 static void
16015088Sab196087 cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
16025088Sab196087     const char *argv[], int num_opt)
16035088Sab196087 {
16045088Sab196087 	/* First argument */
16055088Sab196087 	if ((argc - num_opt) == 1) {
16065088Sab196087 		cpl_eltarg(obj_state, cpldata, argc, argv, num_opt);
16075088Sab196087 		return;
16085088Sab196087 	}
16095088Sab196087 
16105088Sab196087 	/* The second argument is always a tag value */
16115088Sab196087 	if ((argc - num_opt) == 2)
16125088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT);
16135088Sab196087 }
16145088Sab196087 
16155088Sab196087 /*ARGSUSED*/
16165088Sab196087 static void
16175088Sab196087 cpl_posflag1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
16185088Sab196087     const char *argv[], int num_opt)
16195088Sab196087 {
1620*6225Sab196087 	/*
1621*6225Sab196087 	 * dyn:posflag1 accepts two mutually exclusive options that have
1622*6225Sab196087 	 * a corresponding value argument: -dynndx and -needed. If we
1623*6225Sab196087 	 * are being called to supply options for the value, handle that here.
1624*6225Sab196087 	 */
1625*6225Sab196087 	if ((num_opt > 1) && (argc == num_opt)) {
1626*6225Sab196087 		elfedit_section_t	*dynsec, *strsec;
1627*6225Sab196087 		const char		*opt = argv[num_opt - 2];
1628*6225Sab196087 		dyn_opt_t		type;
1629*6225Sab196087 		Dyn			*dyn;
1630*6225Sab196087 		Word			i, num;
1631*6225Sab196087 
1632*6225Sab196087 		/*
1633*6225Sab196087 		 * If there is no object available, or if the object has no
1634*6225Sab196087 		 * dynamic section, then there is nothing to report.
1635*6225Sab196087 		 */
1636*6225Sab196087 		if ((obj_state == NULL) || obj_state->os_dynndx == SHN_UNDEF)
1637*6225Sab196087 			return;
1638*6225Sab196087 
1639*6225Sab196087 		/*
1640*6225Sab196087 		 * Determine which option it is, bail if it isn't one of
1641*6225Sab196087 		 * the ones we are concerned with.
1642*6225Sab196087 		 */
1643*6225Sab196087 		if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_NEEDED)) == 0))
1644*6225Sab196087 			type = DYN_OPT_F_NEEDED;
1645*6225Sab196087 		else if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0))
1646*6225Sab196087 			type = DYN_OPT_F_DYNNDX_VAL;
1647*6225Sab196087 		else
1648*6225Sab196087 			return;
1649*6225Sab196087 
1650*6225Sab196087 		dynsec = elfedit_sec_getdyn(obj_state, &dyn, &num);
1651*6225Sab196087 		switch (type) {
1652*6225Sab196087 		case DYN_OPT_F_NEEDED:
1653*6225Sab196087 			strsec = elfedit_sec_getstr(obj_state,
1654*6225Sab196087 			    dynsec->sec_shdr->sh_link, 0);
1655*6225Sab196087 			for (; num-- > 0; dyn++)
1656*6225Sab196087 				if (dyn->d_tag == DT_NEEDED)
1657*6225Sab196087 					elfedit_cpl_match(cpldata,
1658*6225Sab196087 					    elfedit_offset_to_str(strsec,
1659*6225Sab196087 					    dyn->d_un.d_val, ELFEDIT_MSG_DEBUG,
1660*6225Sab196087 					    0), 0);
1661*6225Sab196087 			break;
1662*6225Sab196087 
1663*6225Sab196087 		case DYN_OPT_F_DYNNDX_VAL:
1664*6225Sab196087 			for (i = 0; i < num; i++, dyn++)
1665*6225Sab196087 				if (dyn->d_tag == DT_POSFLAG_1)
1666*6225Sab196087 					elfedit_cpl_ndx(cpldata, i);
1667*6225Sab196087 			break;
1668*6225Sab196087 		}
1669*6225Sab196087 		return;
1670*6225Sab196087 	}
1671*6225Sab196087 
16725088Sab196087 	/* This routine allows multiple flags to be specified */
16735088Sab196087 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_P1);
16745088Sab196087 }
16755088Sab196087 
16765088Sab196087 /*ARGSUSED*/
16775088Sab196087 static void
16785088Sab196087 cpl_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
16795088Sab196087     const char *argv[], int num_opt)
16805088Sab196087 {
16815088Sab196087 	/* This routine allows multiple flags to be specified */
16825088Sab196087 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF);
16835088Sab196087 }
16845088Sab196087 
16855088Sab196087 /*ARGSUSED*/
16865088Sab196087 static void
16875088Sab196087 cpl_flags1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
16885088Sab196087     const char *argv[], int num_opt)
16895088Sab196087 {
16905088Sab196087 	/* This routine allows multiple flags to be specified */
16915088Sab196087 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_1);
16925088Sab196087 }
16935088Sab196087 
16945088Sab196087 /*ARGSUSED*/
16955088Sab196087 static void
16965088Sab196087 cpl_feature1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
16975088Sab196087     const char *argv[], int num_opt)
16985088Sab196087 {
16995088Sab196087 	/* This routine allows multiple flags to be specified */
17005088Sab196087 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1);
17015088Sab196087 }
17025088Sab196087 
17036206Sab196087 /*ARGSUSED*/
17046206Sab196087 static void
17056206Sab196087 cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
17066206Sab196087     const char *argv[], int num_opt)
17076206Sab196087 {
17086206Sab196087 	/*
17096206Sab196087 	 * This command doesn't accept options, so num_opt should be
17106206Sab196087 	 * 0. This is a defensive measure, in case that should change.
17116206Sab196087 	 */
17126206Sab196087 	argc -= num_opt;
17136206Sab196087 	argv += num_opt;
17146206Sab196087 
17156206Sab196087 	if (argc == 1)
17166206Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM);
17176206Sab196087 }
17186206Sab196087 
17195088Sab196087 
17205088Sab196087 /*
17215088Sab196087  * Implementation functions for the commands
17225088Sab196087  */
17235088Sab196087 static elfedit_cmdret_t
17245088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17255088Sab196087 {
17265088Sab196087 	return (cmd_body(DYN_CMD_T_DUMP, obj_state, argc, argv));
17275088Sab196087 }
17285088Sab196087 
17295088Sab196087 static elfedit_cmdret_t
17305088Sab196087 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17315088Sab196087 {
17325088Sab196087 	return (cmd_body(DYN_CMD_T_TAG, obj_state, argc, argv));
17335088Sab196087 }
17345088Sab196087 
17355088Sab196087 static elfedit_cmdret_t
17365088Sab196087 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17375088Sab196087 {
17385088Sab196087 	return (cmd_body(DYN_CMD_T_VALUE, obj_state, argc, argv));
17395088Sab196087 }
17405088Sab196087 
17415088Sab196087 static elfedit_cmdret_t
17425088Sab196087 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17435088Sab196087 {
17445088Sab196087 	return (cmd_body(DYN_CMD_T_DELETE, obj_state, argc, argv));
17455088Sab196087 }
17465088Sab196087 
17475088Sab196087 static elfedit_cmdret_t
17485088Sab196087 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17495088Sab196087 {
17505088Sab196087 	return (cmd_body(DYN_CMD_T_MOVE, obj_state, argc, argv));
17515088Sab196087 }
17525088Sab196087 
17535088Sab196087 static elfedit_cmdret_t
17545088Sab196087 cmd_runpath(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17555088Sab196087 {
17565088Sab196087 	return (cmd_body(DYN_CMD_T_RUNPATH, obj_state, argc, argv));
17575088Sab196087 }
17585088Sab196087 
17595088Sab196087 static elfedit_cmdret_t
17605088Sab196087 cmd_posflag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17615088Sab196087 {
17625088Sab196087 	return (cmd_body(DYN_CMD_T_POSFLAG1, obj_state, argc, argv));
17635088Sab196087 }
17645088Sab196087 
17655088Sab196087 static elfedit_cmdret_t
17665088Sab196087 cmd_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17675088Sab196087 {
17685088Sab196087 	return (cmd_body(DYN_CMD_T_FLAGS, obj_state, argc, argv));
17695088Sab196087 }
17705088Sab196087 
17715088Sab196087 static elfedit_cmdret_t
17725088Sab196087 cmd_flags1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17735088Sab196087 {
17745088Sab196087 	return (cmd_body(DYN_CMD_T_FLAGS1, obj_state, argc, argv));
17755088Sab196087 }
17765088Sab196087 
17775088Sab196087 static elfedit_cmdret_t
17785088Sab196087 cmd_feature1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17795088Sab196087 {
17805088Sab196087 	return (cmd_body(DYN_CMD_T_FEATURE1, obj_state, argc, argv));
17815088Sab196087 }
17825088Sab196087 
17835088Sab196087 static elfedit_cmdret_t
17845088Sab196087 cmd_checksum(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17855088Sab196087 {
17865088Sab196087 	return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv));
17875088Sab196087 }
17885088Sab196087 
17896206Sab196087 static elfedit_cmdret_t
17906206Sab196087 cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
17916206Sab196087 {
17926206Sab196087 	return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv));
17936206Sab196087 }
17946206Sab196087 
17955088Sab196087 
17965088Sab196087 
17975088Sab196087 /*ARGSUSED*/
17985088Sab196087 elfedit_module_t *
17995088Sab196087 elfedit_init(elfedit_module_version_t version)
18005088Sab196087 {
18015088Sab196087 	/* For commands that only accept -o */
18025088Sab196087 	static elfedit_cmd_optarg_t opt_ostyle[] = {
18035088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
18045088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
18055088Sab196087 		{ NULL }
18065088Sab196087 	};
18075088Sab196087 
18085088Sab196087 	/* For commands that only accept -and, -cmp, -o, -or */
18095088Sab196087 	static elfedit_cmd_optarg_t opt_ostyle_bitop[] = {
18105088Sab196087 		{ ELFEDIT_STDOA_OPT_AND, NULL,
18115088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR },
18125088Sab196087 		{ ELFEDIT_STDOA_OPT_CMP, NULL,
18135088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 },
18145088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
18155088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
18165088Sab196087 		{ ELFEDIT_STDOA_OPT_OR, NULL,
18175088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND },
18185088Sab196087 		{ NULL }
18195088Sab196087 	};
18205088Sab196087 
18215088Sab196087 	/* For commands that only accept -dynndx */
18225088Sab196087 	static elfedit_cmd_optarg_t opt_minus_dynndx[] = {
18235088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
1824*6225Sab196087 		    /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */
1825*6225Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0,
1826*6225Sab196087 		    DYN_OPT_F_DYNNDX_ELT, 0 },
18275088Sab196087 		{ NULL }
18285088Sab196087 	};
18295088Sab196087 
18305088Sab196087 	/* dyn:dump */
18315088Sab196087 	static const char *name_dump[] = {
18325088Sab196087 	    MSG_ORIG(MSG_CMD_DUMP),
18335088Sab196087 	    MSG_ORIG(MSG_STR_EMPTY),	/* "" makes this the default command */
18345088Sab196087 	    NULL
18355088Sab196087 	};
18365088Sab196087 	static elfedit_cmd_optarg_t arg_dump[] = {
18375088Sab196087 		{ MSG_ORIG(MSG_STR_ELT),
18385088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
18395088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
18405088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18415088Sab196087 		{ NULL }
18425088Sab196087 	};
18435088Sab196087 
18445088Sab196087 
18455088Sab196087 	/* dyn:tag */
18465088Sab196087 	static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL };
18475088Sab196087 	static elfedit_cmd_optarg_t opt_tag[] = {
18485088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
1849*6225Sab196087 		    /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */
1850*6225Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0,
1851*6225Sab196087 		    DYN_OPT_F_DYNNDX_ELT, 0 },
18525088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
18535088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
18545088Sab196087 		{ NULL }
18555088Sab196087 	};
18565088Sab196087 	static elfedit_cmd_optarg_t arg_tag[] = {
18575088Sab196087 		{ MSG_ORIG(MSG_STR_ELT),
18585088Sab196087 		    /* MSG_INTL(MSG_A1_TAG_ELT) */
18595088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_TAG_ELT),
18605088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18615088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
18625088Sab196087 		    /* MSG_INTL(MSG_A2_TAG_VALUE) */
18635088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE),
18645088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18655088Sab196087 		{ NULL }
18665088Sab196087 	};
18675088Sab196087 
18685088Sab196087 
18695088Sab196087 	/* dyn:value */
18705088Sab196087 	static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL };
18715088Sab196087 	static elfedit_cmd_optarg_t opt_value[] = {
18725088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_ADD),
18735088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_ADD) */
18745088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_ADD), 0,
1875*6225Sab196087 		    DYN_OPT_F_ADD, DYN_OPT_F_DYNNDX_ELT },
18765088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
1877*6225Sab196087 		    /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */
1878*6225Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0,
1879*6225Sab196087 		    DYN_OPT_F_DYNNDX_ELT, DYN_OPT_F_ADD },
18805088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
18815088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
18825088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_S),
18835088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_S) */
18845088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0,
18855088Sab196087 		    DYN_OPT_F_STRVAL, 0 },
18865088Sab196087 		{ NULL }
18875088Sab196087 	};
18885088Sab196087 	static elfedit_cmd_optarg_t arg_value[] = {
18895088Sab196087 		{ MSG_ORIG(MSG_STR_ELT),
18905088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
18915088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
18925088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18935088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
18945088Sab196087 		    /* MSG_INTL(MSG_A2_VALUE_VALUE) */
18955088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE),
18965088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18975088Sab196087 		{ NULL }
18985088Sab196087 	};
18995088Sab196087 
19005088Sab196087 	/* dyn:delete */
19015088Sab196087 	static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL };
19025088Sab196087 	static elfedit_cmd_optarg_t arg_delete[] = {
19035088Sab196087 		{ MSG_ORIG(MSG_STR_ELT),
19045088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
19055088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
19065088Sab196087 		    0 },
19075088Sab196087 		{ MSG_ORIG(MSG_STR_COUNT),
19085088Sab196087 		    /* MSG_INTL(MSG_A2_DELETE_COUNT) */
19095088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT),
19105088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
19115088Sab196087 		{ NULL }
19125088Sab196087 	};
19135088Sab196087 
19145088Sab196087 	/* dyn:move */
19155088Sab196087 	static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL };
19165088Sab196087 	static elfedit_cmd_optarg_t arg_move[] = {
19175088Sab196087 		{ MSG_ORIG(MSG_STR_ELT),
19185088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
19195088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
19205088Sab196087 		    0 },
19215088Sab196087 		{ MSG_ORIG(MSG_STR_DST_INDEX),
19225088Sab196087 		    /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */
19235088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX),
19245088Sab196087 		    0 },
19255088Sab196087 		{ MSG_ORIG(MSG_STR_COUNT),
19265088Sab196087 		    /* MSG_INTL(MSG_A3_MOVE_COUNT) */
19275088Sab196087 		    ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT),
19285088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
19295088Sab196087 		{ NULL }
19305088Sab196087 	};
19315088Sab196087 
19325088Sab196087 	/* dyn:runpath / dyn:rpath */
19335088Sab196087 	static const char *name_runpath[] = { MSG_ORIG(MSG_CMD_RUNPATH),
19345088Sab196087 	    MSG_ORIG(MSG_CMD_RUNPATH_A1), NULL };
19355088Sab196087 	static elfedit_cmd_optarg_t arg_runpath[] = {
19365088Sab196087 		{ MSG_ORIG(MSG_STR_NEWPATH),
19375088Sab196087 		    /* MSG_INTL(MSG_A1_RUNPATH_NEWPATH) */
19385088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_RUNPATH_NEWPATH),
19395088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
19405088Sab196087 		{ NULL }
19415088Sab196087 	};
19425088Sab196087 
19435088Sab196087 	/* dyn:posflag1 */
19445088Sab196087 	static const char *name_posflag1[] = { MSG_ORIG(MSG_CMD_POSFLAG1),
19455088Sab196087 	    NULL };
1946*6225Sab196087 	static elfedit_cmd_optarg_t opt_posflag1[] = {
1947*6225Sab196087 		{ ELFEDIT_STDOA_OPT_AND, NULL,
1948*6225Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR },
1949*6225Sab196087 		{ ELFEDIT_STDOA_OPT_CMP, NULL,
1950*6225Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 },
1951*6225Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
1952*6225Sab196087 		    /* MSG_INTL(MSG_OPTDESC_DYNNDX_VAL) */
1953*6225Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_VAL),
1954*6225Sab196087 		    ELFEDIT_CMDOA_F_VALUE,
1955*6225Sab196087 		    DYN_OPT_F_DYNNDX_VAL, DYN_OPT_F_NEEDED },
1956*6225Sab196087 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 },
1957*6225Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_NEEDED),
1958*6225Sab196087 		    /* MSG_INTL(MSG_OPTDESC_NEEDED) */
1959*6225Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_NEEDED),
1960*6225Sab196087 		    ELFEDIT_CMDOA_F_VALUE,
1961*6225Sab196087 		    DYN_OPT_F_NEEDED, DYN_OPT_F_DYNNDX_VAL },
1962*6225Sab196087 		{ MSG_ORIG(MSG_STR_PREFIX), NULL, 0, 0 },
1963*6225Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
1964*6225Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1965*6225Sab196087 		{ ELFEDIT_STDOA_OPT_OR, NULL,
1966*6225Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND },
1967*6225Sab196087 		{ NULL }
1968*6225Sab196087 	};
19695088Sab196087 	static elfedit_cmd_optarg_t arg_posflag1[] = {
19705088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
19715088Sab196087 		    /* MSG_INTL(MSG_A1_POSFLAG1_VALUE) */
19725088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_POSFLAG1_VALUE),
19735088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
19745088Sab196087 		{ NULL }
19755088Sab196087 	};
19765088Sab196087 
19775088Sab196087 	/* dyn:flags */
19785088Sab196087 	static const char *name_flags[] = { MSG_ORIG(MSG_CMD_FLAGS), NULL };
19795088Sab196087 	static elfedit_cmd_optarg_t arg_flags[] = {
19805088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
19815088Sab196087 		    /* MSG_INTL(MSG_A1_FLAGS_VALUE) */
19825088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_FLAGS_VALUE),
19835088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
19845088Sab196087 		{ NULL }
19855088Sab196087 	};
19865088Sab196087 
19875088Sab196087 	/* dyn:flags1 */
19885088Sab196087 	static const char *name_flags1[] = { MSG_ORIG(MSG_CMD_FLAGS1), NULL };
19895088Sab196087 	static elfedit_cmd_optarg_t arg_flags1[] = {
19905088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
19915088Sab196087 		    /* MSG_INTL(MSG_A1_FLAGS1_VALUE) */
19925088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_FLAGS1_VALUE),
19935088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
19945088Sab196087 		{ NULL }
19955088Sab196087 	};
19965088Sab196087 
19975088Sab196087 	/* dyn:feature1 */
19985088Sab196087 	static const char *name_feature1[] = { MSG_ORIG(MSG_CMD_FEATURE1),
19995088Sab196087 	    NULL };
20005088Sab196087 	static elfedit_cmd_optarg_t arg_feature1[] = {
20015088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
20025088Sab196087 		    /* MSG_INTL(MSG_A1_FEATURE1_VALUE) */
20035088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_FEATURE1_VALUE),
20045088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
20055088Sab196087 		{ NULL }
20065088Sab196087 	};
20075088Sab196087 
20085088Sab196087 	/* dyn:checksum */
20095088Sab196087 	static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM),
20105088Sab196087 	    NULL };
20115088Sab196087 
20126206Sab196087 	/* dyn:sunw_ldmach */
20136206Sab196087 	static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH),
20146206Sab196087 	    NULL };
20156206Sab196087 	static elfedit_cmd_optarg_t arg_sunw_ldmach[] = {
20166206Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
20176206Sab196087 		    /* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */
20186206Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE),
20196206Sab196087 		    ELFEDIT_CMDOA_F_OPT },
20206206Sab196087 		{ NULL }
20216206Sab196087 	};
20226206Sab196087 
20235088Sab196087 
20245088Sab196087 
20255088Sab196087 	static elfedit_cmd_t cmds[] = {
20265088Sab196087 		/* dyn:dump */
20275088Sab196087 		{ cmd_dump, cpl_eltarg, name_dump,
20285088Sab196087 		    /* MSG_INTL(MSG_DESC_DUMP) */
20295088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_DUMP),
20305088Sab196087 		    /* MSG_INTL(MSG_HELP_DUMP) */
20315088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_DUMP),
20325088Sab196087 		    opt_minus_dynndx, arg_dump },
20335088Sab196087 
20345088Sab196087 		/* dyn:tag */
20355088Sab196087 		{ cmd_tag, cpl_tag, name_tag,
20365088Sab196087 		    /* MSG_INTL(MSG_DESC_TAG) */
20375088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_TAG),
20385088Sab196087 		    /* MSG_INTL(MSG_HELP_TAG) */
20395088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_TAG),
20405088Sab196087 		    opt_tag, arg_tag },
20415088Sab196087 
20425088Sab196087 		/* dyn:value */
20435088Sab196087 		{ cmd_value, cpl_eltarg, name_value,
20445088Sab196087 		    /* MSG_INTL(MSG_DESC_VALUE) */
20455088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_VALUE),
20465088Sab196087 		    /* MSG_INTL(MSG_HELP_VALUE) */
20475088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_VALUE),
20485088Sab196087 		    opt_value, arg_value },
20495088Sab196087 
20505088Sab196087 		/* dyn:delete */
20515088Sab196087 		{ cmd_delete, cpl_eltarg, name_delete,
20525088Sab196087 		    /* MSG_INTL(MSG_DESC_DELETE) */
20535088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_DELETE),
20545088Sab196087 		    /* MSG_INTL(MSG_HELP_DELETE) */
20555088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_DELETE),
20565088Sab196087 		    opt_minus_dynndx, arg_delete },
20575088Sab196087 
20585088Sab196087 		/* dyn:move */
20595088Sab196087 		{ cmd_move, cpl_eltarg, name_move,
20605088Sab196087 		    /* MSG_INTL(MSG_DESC_MOVE) */
20615088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_MOVE),
20625088Sab196087 		    /* MSG_INTL(MSG_HELP_MOVE) */
20635088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_MOVE),
20645088Sab196087 		    opt_minus_dynndx, arg_move },
20655088Sab196087 
20665088Sab196087 		/* dyn:runpath */
20675088Sab196087 		{ cmd_runpath, NULL, name_runpath,
20685088Sab196087 		    /* MSG_INTL(MSG_DESC_RUNPATH) */
20695088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_RUNPATH),
20705088Sab196087 		    /* MSG_INTL(MSG_HELP_RUNPATH) */
20715088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_RUNPATH),
20725088Sab196087 		    opt_ostyle, arg_runpath },
20735088Sab196087 
20745088Sab196087 		/* dyn:posflag1 */
20755088Sab196087 		{ cmd_posflag1, cpl_posflag1, name_posflag1,
20765088Sab196087 		    /* MSG_INTL(MSG_DESC_POSFLAG1) */
20775088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_POSFLAG1),
20785088Sab196087 		    /* MSG_INTL(MSG_HELP_POSFLAG1) */
20795088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_POSFLAG1),
2080*6225Sab196087 		    opt_posflag1, arg_posflag1 },
20815088Sab196087 
20825088Sab196087 		/* dyn:flags */
20835088Sab196087 		{ cmd_flags, cpl_flags, name_flags,
20845088Sab196087 		    /* MSG_INTL(MSG_DESC_FLAGS) */
20855088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_FLAGS),
20865088Sab196087 		    /* MSG_INTL(MSG_HELP_FLAGS) */
20875088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_FLAGS),
20885088Sab196087 		    opt_ostyle_bitop, arg_flags },
20895088Sab196087 
20905088Sab196087 		/* dyn:flags1 */
20915088Sab196087 		{ cmd_flags1, cpl_flags1, name_flags1,
20925088Sab196087 		    /* MSG_INTL(MSG_DESC_FLAGS1) */
20935088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_FLAGS1),
20945088Sab196087 		    /* MSG_INTL(MSG_HELP_FLAGS1) */
20955088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_FLAGS1),
20965088Sab196087 		    opt_ostyle_bitop, arg_flags1 },
20975088Sab196087 
20985088Sab196087 		/* dyn:feature1 */
20995088Sab196087 		{ cmd_feature1, cpl_feature1, name_feature1,
21005088Sab196087 		    /* MSG_INTL(MSG_DESC_FEATURE1) */
21015088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_FEATURE1),
21025088Sab196087 		    /* MSG_INTL(MSG_HELP_FEATURE1) */
21035088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_FEATURE1),
21045088Sab196087 		    opt_ostyle_bitop, arg_feature1 },
21055088Sab196087 
21065088Sab196087 		/* dyn:checksum */
21075088Sab196087 		{ cmd_checksum, NULL, name_checksum,
21085088Sab196087 		    /* MSG_INTL(MSG_DESC_CHECKSUM) */
21095088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_CHECKSUM),
21105088Sab196087 		    /* MSG_INTL(MSG_HELP_CHECKSUM) */
21115088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM),
21125088Sab196087 		    NULL, NULL },
21135088Sab196087 
21146206Sab196087 		/* dyn:sunw_ldmach */
21156206Sab196087 		{ cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach,
21166206Sab196087 		    /* MSG_INTL(MSG_DESC_SUNW_LDMACH) */
21176206Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH),
21186206Sab196087 		    /* MSG_INTL(MSG_HELP_SUNW_LDMACH) */
21196206Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH),
21206206Sab196087 		    opt_ostyle, arg_sunw_ldmach },
21216206Sab196087 
21225088Sab196087 		{ NULL }
21235088Sab196087 	};
21245088Sab196087 
21255088Sab196087 	static elfedit_module_t module = {
21265088Sab196087 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
21275088Sab196087 	    /* MSG_INTL(MSG_MOD_DESC) */
21285088Sab196087 	    ELFEDIT_I18NHDL(MSG_MOD_DESC), cmds, mod_i18nhdl_to_str };
21295088Sab196087 
21305088Sab196087 	return (&module);
21315088Sab196087 }
2132