Home | History | Annotate | Download | only in common
      1  5088  ab196087 /*
      2  5088  ab196087  * CDDL HEADER START
      3  5088  ab196087  *
      4  5088  ab196087  * The contents of this file are subject to the terms of the
      5  5088  ab196087  * Common Development and Distribution License (the "License").
      6  5088  ab196087  * You may not use this file except in compliance with the License.
      7  5088  ab196087  *
      8  5088  ab196087  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  5088  ab196087  * or http://www.opensolaris.org/os/licensing.
     10  5088  ab196087  * See the License for the specific language governing permissions
     11  5088  ab196087  * and limitations under the License.
     12  5088  ab196087  *
     13  5088  ab196087  * When distributing Covered Code, include this CDDL HEADER in each
     14  5088  ab196087  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  5088  ab196087  * If applicable, add the following below this CDDL HEADER, with the
     16  5088  ab196087  * fields enclosed by brackets "[]" replaced with your own identifying
     17  5088  ab196087  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  5088  ab196087  *
     19  5088  ab196087  * CDDL HEADER END
     20  5088  ab196087  */
     21  5088  ab196087 
     22  5088  ab196087 /*
     23  9273       Ali  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  5088  ab196087  * Use is subject to license terms.
     25  5088  ab196087  */
     26  5088  ab196087 
     27  5088  ab196087 #include	<ctype.h>
     28  5088  ab196087 #include	<elfedit.h>
     29  5088  ab196087 #include	<sys/elf_SPARC.h>
     30  5088  ab196087 #include	<strings.h>
     31  5088  ab196087 #include	<debug.h>
     32  5088  ab196087 #include	<conv.h>
     33  5088  ab196087 #include	<dyn_msg.h>
     34  5088  ab196087 
     35  5088  ab196087 
     36  5088  ab196087 /*
     37  5088  ab196087  * Dynamic section
     38  5088  ab196087  */
     39  5088  ab196087 
     40  5088  ab196087 /*
     41  5088  ab196087  * This module uses shared code for several of the commands.
     42  5088  ab196087  * It is sometimes necessary to know which specific command
     43  5088  ab196087  * is active.
     44  5088  ab196087  */
     45  5088  ab196087 typedef enum {
     46  5088  ab196087 	/* Dump command, used as module default to display dynamic section */
     47  5088  ab196087 	DYN_CMD_T_DUMP =	0,	/* dyn:dump */
     48  5088  ab196087 
     49  5088  ab196087 	/* Commands that do not correspond directly to a specific DT tag */
     50  5088  ab196087 	DYN_CMD_T_TAG =		1,	/* dyn:tag */
     51  5088  ab196087 	DYN_CMD_T_VALUE =	2,	/* dyn:value */
     52  5088  ab196087 	DYN_CMD_T_DELETE =	3,	/* dyn:delete */
     53  5088  ab196087 	DYN_CMD_T_MOVE =	4,	/* dyn:shift */
     54  5088  ab196087 
     55  5088  ab196087 	/* Commands that embody tag specific knowledge */
     56  5088  ab196087 	DYN_CMD_T_RUNPATH =	5,	/* dyn:runpath/rpath */
     57  5088  ab196087 	DYN_CMD_T_POSFLAG1 =	6,	/* dyn:posflag1 */
     58  5088  ab196087 	DYN_CMD_T_FLAGS =	7,	/* dyn:flags */
     59  5088  ab196087 	DYN_CMD_T_FLAGS1 =	8,	/* dyn:flags1 */
     60  5088  ab196087 	DYN_CMD_T_FEATURE1 =	9,	/* dyn:feature1 */
     61  6206  ab196087 	DYN_CMD_T_CHECKSUM =	10,	/* dyn:checksum */
     62  6206  ab196087 	DYN_CMD_T_SUNW_LDMACH =	11	/* dyn:sunw_ldmach */
     63  5088  ab196087 } DYN_CMD_T;
     64  5088  ab196087 
     65  5088  ab196087 
     66  5088  ab196087 
     67  5088  ab196087 #ifndef _ELF64
     68  5088  ab196087 /*
     69  5088  ab196087  * We supply this function for the msg module
     70  5088  ab196087  */
     71  5088  ab196087 const char *
     72  5088  ab196087 _dyn_msg(Msg mid)
     73  5088  ab196087 {
     74  5088  ab196087 	return (gettext(MSG_ORIG(mid)));
     75  5088  ab196087 }
     76  5088  ab196087 #endif
     77  5088  ab196087 
     78  5088  ab196087 
     79  5088  ab196087 /*
     80  5088  ab196087  * This function is supplied to elfedit through our elfedit_module_t
     81  5088  ab196087  * definition. It translates the opaque elfedit_i18nhdl_t handles
     82  5088  ab196087  * in our module interface into the actual strings for elfedit to
     83  5088  ab196087  * use.
     84  5088  ab196087  *
     85  5088  ab196087  * note:
     86  5088  ab196087  *	This module uses Msg codes for its i18n handle type.
     87  5088  ab196087  *	So the translation is simply to use MSG_INTL() to turn
     88  5088  ab196087  *	it into a string and return it.
     89  5088  ab196087  */
     90  5088  ab196087 static const char *
     91  5088  ab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
     92  5088  ab196087 {
     93  5088  ab196087 	Msg msg = (Msg)hdl;
     94  5088  ab196087 
     95  5088  ab196087 	return (MSG_INTL(msg));
     96  5088  ab196087 }
     97  5088  ab196087 
     98  5088  ab196087 
     99  5088  ab196087 
    100  5088  ab196087 /*
    101  5088  ab196087  * The dyn_opt_t enum specifies a bit value for every optional
    102  5088  ab196087  * argument allowed by a command in this module.
    103  5088  ab196087  */
    104  5088  ab196087 typedef enum {
    105  5088  ab196087 	DYN_OPT_F_ADD =		1,	/* -add: Add new elt rather than */
    106  5088  ab196087 					/*	modifying an existing one */
    107  5088  ab196087 	DYN_OPT_F_AND =		2,	/* -and: AND (&) values to dest */
    108  5088  ab196087 	DYN_OPT_F_CMP =		4,	/* -cmp: Complement (~) values */
    109  6225  ab196087 	DYN_OPT_F_DYNNDX_ELT =	8,	/* -dynndx: 1st plain arg is tag */
    110  6225  ab196087 					/*	index, not name */
    111  6225  ab196087 	DYN_OPT_F_DYNNDX_VAL =	16,	/* -dynndx ndx: Index is value to */
    112  6225  ab196087 					/*	option rather than 1st plain */
    113  6225  ab196087 					/*	arg. Used for dyn:posflag1 */
    114  6225  ab196087 	DYN_OPT_F_NEEDED =	32,	/* -needed str: Locate DT_POSFLAG_1 */
    115  6225  ab196087 					/*	relative to DT_NEEDED element */
    116  6225  ab196087 	DYN_OPT_F_OR =		64,	/* -or: OR (|) values to dest */
    117  6225  ab196087 	DYN_OPT_F_STRVAL =	128	/* -s: value is string, not integer */
    118  5088  ab196087 } dyn_opt_t;
    119  5088  ab196087 
    120  5088  ab196087 
    121  5088  ab196087 /*
    122  5088  ab196087  * A variable of type ARGSTATE is used by each command to maintain
    123  5088  ab196087  * information about the arguments and related things. It is
    124  5088  ab196087  * initialized by process_args(), and used by the other routines.
    125  5088  ab196087  */
    126  5088  ab196087 typedef struct {
    127  5088  ab196087 	elfedit_obj_state_t	*obj_state;
    128  5088  ab196087 	elfedit_section_t	*strsec;	/* Dynamic string table ref */
    129  5088  ab196087 	struct {
    130  5088  ab196087 		elfedit_section_t *sec;		/* Dynamic section reference */
    131  5088  ab196087 		Dyn	*data;			/* Start dynamic section data */
    132  5088  ab196087 		Word	num;			/* # dynamic elts */
    133  5088  ab196087 		Word	null_ndx;		/* Index of first DT_NULL */
    134  5088  ab196087 		Word	num_null_ndx;		/* # of DT_NULL elements */
    135  5088  ab196087 	} dyn;
    136  5088  ab196087 	dyn_opt_t		optmask;   	/* Mask of options used */
    137  5088  ab196087 	int			argc;		/* # of plain arguments */
    138  5088  ab196087 	const char		**argv;		/* Plain arguments */
    139  6225  ab196087 	const char		*dyn_elt_str;	/* Value string for */
    140  6225  ab196087 						/*	DYN_OPT_F_DYNNDX_VAL */
    141  6225  ab196087 						/*	or DYN_OPT_F_NEEDED */
    142  5088  ab196087 } ARGSTATE;
    143  5088  ab196087 
    144  5088  ab196087 
    145  5088  ab196087 
    146  5088  ab196087 /*
    147  5088  ab196087  * Set argstate null_ndx field for current dynamic area
    148  5088  ab196087  */
    149  5088  ab196087 static void
    150  5088  ab196087 set_null_ndx(ARGSTATE *argstate)
    151  5088  ab196087 {
    152  5088  ab196087 	Word	num, null_ndx;
    153  5088  ab196087 
    154  5088  ab196087 	num = argstate->dyn.num;
    155  5088  ab196087 	argstate->dyn.num_null_ndx = 0;
    156  5088  ab196087 	for (null_ndx = 0; null_ndx < num; null_ndx++)
    157  5088  ab196087 		if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) {
    158  5088  ab196087 			argstate->dyn.num_null_ndx++;
    159  5088  ab196087 			break;
    160  5088  ab196087 		}
    161  5088  ab196087 	argstate->dyn.null_ndx = null_ndx;
    162  5088  ab196087 
    163  5088  ab196087 	/* Count the number of remaining DT_NULL items */
    164  5088  ab196087 	for (; null_ndx < num; null_ndx++)
    165  5088  ab196087 		if (argstate->dyn.data[null_ndx].d_tag == DT_NULL)
    166  5088  ab196087 			argstate->dyn.num_null_ndx++;
    167  5088  ab196087 }
    168  5088  ab196087 
    169  5088  ab196087 
    170  5088  ab196087 /*
    171  5088  ab196087  * Convert the first available DT_NULL slot in the dynamic section
    172  5088  ab196087  * into something else.
    173  5088  ab196087  *
    174  5088  ab196087  * entry:
    175  5088  ab196087  *	argstate - Argument state block
    176  5088  ab196087  *	d_tag, d_val - Values to be set in new element
    177  5088  ab196087  *
    178  5088  ab196087  * exit:
    179  5088  ab196087  *	If an extra DT_NULL slot is available, a debug message is
    180  5088  ab196087  *	issued, the slot is converted to its new use, and the argstate
    181  5088  ab196087  *	block state related to DT_NULL slots is updated.
    182  5088  ab196087  *
    183  5088  ab196087  *	if no extra DT_NULL slot is present, an error is issued and
    184  5088  ab196087  *	this routine does not return to the caller.
    185  5088  ab196087  */
    186  5088  ab196087 static Word
    187  9273       Ali convert_dt_null(ARGSTATE *argstate, Xword d_tag, Xword d_val)
    188  5088  ab196087 {
    189  5088  ab196087 	Conv_inv_buf_t inv_buf;
    190  5088  ab196087 	Word	ndx;
    191  5088  ab196087 	Dyn	*dyn;
    192  9273       Ali 	Ehdr	*ehdr;
    193  5088  ab196087 
    194  5088  ab196087 	/* If we lack an extra element, we can't continue */
    195  5088  ab196087 	if (argstate->dyn.num_null_ndx <= 1)
    196  5088  ab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL),
    197  5088  ab196087 		    EC_WORD(argstate->dyn.sec->sec_shndx),
    198  5088  ab196087 		    argstate->dyn.sec->sec_name);
    199  5088  ab196087 
    200  9273       Ali 	ehdr = argstate->obj_state->os_ehdr;
    201  5088  ab196087 	elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL),
    202  5088  ab196087 	    EC_WORD(argstate->dyn.sec->sec_shndx), argstate->dyn.sec->sec_name,
    203  5088  ab196087 	    EC_WORD(argstate->dyn.null_ndx), conv_dyn_tag(d_tag,
    204  9273       Ali 	    ehdr->e_ident[EI_OSABI], ehdr->e_machine, 0, &inv_buf));
    205  5088  ab196087 
    206  5088  ab196087 	ndx = argstate->dyn.null_ndx;
    207  5088  ab196087 	dyn = &argstate->dyn.data[ndx];
    208  5088  ab196087 	dyn->d_tag = d_tag;
    209  5088  ab196087 	dyn->d_un.d_val = d_val;
    210  5088  ab196087 
    211  5088  ab196087 	/* Recompute the DT_NULL situation */
    212  5088  ab196087 	set_null_ndx(argstate);
    213  5088  ab196087 
    214  5088  ab196087 	return (ndx);
    215  5088  ab196087 }
    216  5088  ab196087 
    217  5088  ab196087 
    218  5088  ab196087 /*
    219  5088  ab196087  * Standard argument processing for dyn module
    220  5088  ab196087  *
    221  5088  ab196087  * entry
    222  5088  ab196087  *	obj_state, argc, argv - Standard command arguments
    223  5088  ab196087  *	argstate - Address of ARGSTATE block to be initialized
    224  5088  ab196087  *
    225  5088  ab196087  * exit:
    226  5088  ab196087  *	On success, *argstate is initialized. On error,
    227  5088  ab196087  *	an error is issued and this routine does not return.
    228  5088  ab196087  */
    229  5088  ab196087 static void
    230  5088  ab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
    231  5088  ab196087     ARGSTATE *argstate)
    232  5088  ab196087 {
    233  5088  ab196087 	elfedit_getopt_state_t	getopt_state;
    234  5088  ab196087 	elfedit_getopt_ret_t	*getopt_ret;
    235  5088  ab196087 
    236  5088  ab196087 	bzero(argstate, sizeof (*argstate));
    237  5088  ab196087 	argstate->obj_state = obj_state;
    238  5088  ab196087 
    239  5088  ab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
    240  5088  ab196087 
    241  5088  ab196087 	/* Add each new option to the options mask */
    242  6225  ab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
    243  5088  ab196087 		argstate->optmask |= getopt_ret->gor_idmask;
    244  6225  ab196087 		switch (getopt_ret->gor_idmask) {
    245  6225  ab196087 		case DYN_OPT_F_DYNNDX_VAL:
    246  6225  ab196087 		case DYN_OPT_F_NEEDED:
    247  6225  ab196087 			argstate->dyn_elt_str = getopt_ret->gor_value;
    248  6225  ab196087 			break;
    249  6225  ab196087 		}
    250  6225  ab196087 	}
    251  5088  ab196087 
    252  5088  ab196087 	/* If there may be an arbitrary amount of output, use a pager */
    253  5088  ab196087 	if (argc == 0)
    254  5088  ab196087 		elfedit_pager_init();
    255  5088  ab196087 
    256  5088  ab196087 	/* Return the updated values of argc/argv */
    257  5088  ab196087 	argstate->argc = argc;
    258  5088  ab196087 	argstate->argv = argv;
    259  5088  ab196087 
    260  5088  ab196087 	/* Locate the dynamic section, and the assocated string table */
    261  5088  ab196087 	argstate->dyn.sec = elfedit_sec_getdyn(obj_state, &argstate->dyn.data,
    262  5088  ab196087 	    &argstate->dyn.num);
    263  5088  ab196087 	argstate->strsec = elfedit_sec_getstr(obj_state,
    264  6225  ab196087 	    argstate->dyn.sec->sec_shdr->sh_link, 0);
    265  5088  ab196087 
    266  5088  ab196087 	/* Index of first DT_NULL */
    267  5088  ab196087 	set_null_ndx(argstate);
    268  5088  ab196087 }
    269  5088  ab196087 
    270  5088  ab196087 /*
    271  5088  ab196087  * Print ELF header values, taking the calling command, and output style
    272  5088  ab196087  * into account.
    273  5088  ab196087  *
    274  5088  ab196087  * entry:
    275  5088  ab196087  *	cmd - DYN_CMD_T_* value giving identify of caller
    276  5088  ab196087  *	autoprint - If True, output is only produced if the elfedit
    277  5088  ab196087  *		autoprint flag is set. If False, output is always produced.
    278  5088  ab196087  *	argstate - Argument state block
    279  5088  ab196087  *	print_type - Specifies which dynamic elements to display.
    280  9273       Ali  *	arg - If print_type is PRINT_DYN_T_NDX, displays the index specified.
    281  5088  ab196087  *		Otherwise ignored.
    282  5088  ab196087  */
    283  5088  ab196087 typedef enum {
    284  5088  ab196087 	PRINT_DYN_T_ALL =	0,	/* Show all indexes */
    285  5088  ab196087 	PRINT_DYN_T_NDX =	1,	/* Show dynamic[arg] only */
    286  5088  ab196087 	PRINT_DYN_T_TAG =	2,	/* Show all elts with tag type */
    287  5088  ab196087 					/*	given by arg */
    288  5088  ab196087 	PRINT_DYN_T_RUNPATH =	3	/* Show all runpath/rpath elts */
    289  5088  ab196087 
    290  5088  ab196087 } PRINT_DYN_T;
    291  5088  ab196087 
    292  5088  ab196087 static void
    293  5088  ab196087 print_dyn(DYN_CMD_T cmd, int autoprint, ARGSTATE *argstate,
    294  5088  ab196087     PRINT_DYN_T print_type, Word arg)
    295  5088  ab196087 {
    296  5088  ab196087 	elfedit_outstyle_t	outstyle;
    297  5088  ab196087 	Conv_fmt_flags_t	flags_fmt_flags;
    298  6635  ab196087 	Word	end_ndx, ndx, printed = 0;
    299  5088  ab196087 	Dyn	*dyn;
    300  5088  ab196087 	int	header_done = 0;
    301  5088  ab196087 	Xword	last_d_val;
    302  6225  ab196087 	int	one_shot;
    303  9273       Ali 	int	osabi_solaris;
    304  5088  ab196087 
    305  5088  ab196087 	if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
    306  5088  ab196087 		return;
    307  9273       Ali 
    308  9273       Ali 	osabi_solaris =
    309  9273       Ali 	    elfedit_test_osabi(argstate->obj_state, ELFOSABI_SOLARIS, 0);
    310  5088  ab196087 
    311  5088  ab196087 	/*
    312  5088  ab196087 	 * Pick an output style. dyn:dump is required to use the default
    313  5088  ab196087 	 * style. The other commands use the current output style.
    314  5088  ab196087 	 */
    315  5088  ab196087 	outstyle = (cmd == DYN_CMD_T_DUMP) ?
    316  5088  ab196087 	    ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
    317  5088  ab196087 
    318  5088  ab196087 	/*
    319  5088  ab196087 	 * When using the simple output style, omit the
    320  5088  ab196087 	 * brackets from around the values.
    321  5088  ab196087 	 */
    322  5088  ab196087 	flags_fmt_flags = (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) ?
    323  5088  ab196087 	    CONV_FMT_NOBKT : 0;
    324  5088  ab196087 
    325  6635  ab196087 	/* Starting index */
    326  5088  ab196087 	if (print_type == PRINT_DYN_T_NDX) {
    327  5088  ab196087 		if (arg >= argstate->dyn.num)
    328  5088  ab196087 			return;		/* Out of range */
    329  5088  ab196087 		ndx = arg;
    330  5088  ab196087 	} else {
    331  5088  ab196087 		ndx = 0;
    332  5088  ab196087 	}
    333  5088  ab196087 
    334  6225  ab196087 	/*
    335  6225  ab196087 	 * one_shot is used by positional elements (e.g. DT_POSFLAG_1)
    336  6225  ab196087 	 * to get the item following them to be shown even if they
    337  6225  ab196087 	 * are not of the desired tag type or the count of elements
    338  6225  ab196087 	 * to be displayed is only 1.
    339  6225  ab196087 	 */
    340  6225  ab196087 	one_shot = 0;
    341  6225  ab196087 
    342  5088  ab196087 	dyn = &argstate->dyn.data[ndx];
    343  6635  ab196087 
    344  6635  ab196087 	/*
    345  6635  ab196087 	 * Loop predicate explanation:
    346  6635  ab196087 	 * Normally, we want to iterate from the starting index
    347  6635  ab196087 	 * to the end. However, in the case of PRINT_DYN_T_NDX, we
    348  6635  ab196087 	 * only want to display one item (ndx == arg) and then quit,
    349  6635  ab196087 	 * with the exception that if we've been through the loop
    350  6635  ab196087 	 * and encountered a one_shot situation, we want to continue
    351  6635  ab196087 	 * iterating until the one-shot situation is cleared.
    352  6635  ab196087 	 */
    353  6635  ab196087 	for (; (ndx < argstate->dyn.num) &&
    354  6635  ab196087 	    ((print_type != PRINT_DYN_T_NDX) || ((ndx == arg) || one_shot));
    355  6635  ab196087 	    dyn++, ndx++) {
    356  5088  ab196087 		union {
    357  6206  ab196087 			Conv_inv_buf_t		inv;
    358  5088  ab196087 			Conv_dyn_flag_buf_t	flag;
    359  5088  ab196087 			Conv_dyn_flag1_buf_t	flag1;
    360  5088  ab196087 			Conv_dyn_posflag1_buf_t	posflag1;
    361  5088  ab196087 			Conv_dyn_feature1_buf_t	feature1;
    362  5088  ab196087 		} c_buf;
    363  5088  ab196087 		const char	*name;
    364  5088  ab196087 
    365  6225  ab196087 		if (one_shot) {
    366  6225  ab196087 			one_shot = 0;
    367  6225  ab196087 		} else {
    368  6225  ab196087 			/*
    369  6225  ab196087 			 * If we are only displaying certain tag types and
    370  6225  ab196087 			 * this isn't one of those, move on to next element.
    371  6225  ab196087 			 */
    372  6225  ab196087 			switch (print_type) {
    373  6225  ab196087 			case PRINT_DYN_T_TAG:
    374  6225  ab196087 				if (dyn->d_tag != arg)
    375  6225  ab196087 					continue;
    376  6225  ab196087 				break;
    377  6225  ab196087 			case PRINT_DYN_T_RUNPATH:
    378  6225  ab196087 				if ((dyn->d_tag != DT_RPATH) &&
    379  6225  ab196087 				    (dyn->d_tag != DT_RUNPATH))
    380  6225  ab196087 					continue;
    381  6225  ab196087 				break;
    382  6225  ab196087 			}
    383  5088  ab196087 		}
    384  5088  ab196087 
    385  5088  ab196087 		/*
    386  5088  ab196087 		 * Print the information numerically, and if possible
    387  5088  ab196087 		 * as a string.
    388  5088  ab196087 		 */
    389  5088  ab196087 		name = NULL;
    390  5088  ab196087 		switch (dyn->d_tag) {
    391  5088  ab196087 		case DT_NULL:
    392  5088  ab196087 			if (!((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) &&
    393  5088  ab196087 			    (print_type == PRINT_DYN_T_ALL) &&
    394  5088  ab196087 			    (dyn->d_un.d_val == 0)))
    395  5088  ab196087 				break;
    396  5088  ab196087 			end_ndx = ndx;
    397  5088  ab196087 			/*
    398  5088  ab196087 			 * Special case: DT_NULLs can come in groups
    399  5088  ab196087 			 * that we prefer to reduce to a single line.
    400  5088  ab196087 			 */
    401  5088  ab196087 			while ((end_ndx < (argstate->dyn.num - 1)) &&
    402  5088  ab196087 			    ((dyn + 1)->d_tag == DT_NULL) &&
    403  5088  ab196087 			    ((dyn + 1)->d_un.d_val == 0)) {
    404  5088  ab196087 				dyn++;
    405  5088  ab196087 				end_ndx++;
    406  5088  ab196087 			}
    407  5088  ab196087 			if (header_done == 0) {
    408  5088  ab196087 				header_done = 1;
    409  5088  ab196087 				Elf_dyn_title(0);
    410  5088  ab196087 			}
    411  5088  ab196087 			Elf_dyn_null_entry(0, dyn, ndx, end_ndx);
    412  5088  ab196087 			ndx = end_ndx;
    413  5088  ab196087 			printed = 1;
    414  5088  ab196087 			last_d_val = dyn->d_un.d_val;
    415  5088  ab196087 			continue;
    416  5088  ab196087 
    417  5088  ab196087 		/*
    418  5088  ab196087 		 * Print the information numerically, and if possible
    419  5088  ab196087 		 * as a string.
    420  5088  ab196087 		 */
    421  5088  ab196087 		case DT_NEEDED:
    422  5088  ab196087 		case DT_SONAME:
    423  5088  ab196087 		case DT_FILTER:
    424  5088  ab196087 		case DT_AUXILIARY:
    425  5088  ab196087 		case DT_CONFIG:
    426  5088  ab196087 		case DT_RPATH:
    427  5088  ab196087 		case DT_RUNPATH:
    428  5088  ab196087 		case DT_USED:
    429  5088  ab196087 		case DT_DEPAUDIT:
    430  5088  ab196087 		case DT_AUDIT:
    431  9273       Ali 			name = elfedit_offset_to_str(argstate->strsec,
    432  9273       Ali 			    dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
    433  9273       Ali 			break;
    434  5088  ab196087 		case DT_SUNW_AUXILIARY:
    435  5088  ab196087 		case DT_SUNW_FILTER:
    436  9273       Ali 			if (osabi_solaris)
    437  9273       Ali 				name = elfedit_offset_to_str(argstate->strsec,
    438  9273       Ali 				    dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
    439  5088  ab196087 			break;
    440  5088  ab196087 
    441  5088  ab196087 		case DT_FLAGS:
    442  5088  ab196087 			name = conv_dyn_flag(dyn->d_un.d_val,
    443  5088  ab196087 			    flags_fmt_flags, &c_buf.flag);
    444  5088  ab196087 			break;
    445  5088  ab196087 		case DT_FLAGS_1:
    446  5088  ab196087 			name = conv_dyn_flag1(dyn->d_un.d_val,
    447  5088  ab196087 			    flags_fmt_flags, &c_buf.flag1);
    448  5088  ab196087 			break;
    449  5088  ab196087 		case DT_POSFLAG_1:
    450  6225  ab196087 			/*
    451  6225  ab196087 			 * If this is dyn:posflag1, and the print_type
    452  6225  ab196087 			 * is PRINT_DYN_T_TAG, and the -needed option is
    453  6225  ab196087 			 * used, then don't show any DT_POSFLAG_1 elements
    454  6225  ab196087 			 * that are not followed by a DT_NEEDED element
    455  6225  ab196087 			 * that matches the -needed string.
    456  6225  ab196087 			 */
    457  6225  ab196087 			if ((cmd == DYN_CMD_T_POSFLAG1) &&
    458  6225  ab196087 			    (print_type == PRINT_DYN_T_TAG) &&
    459  6225  ab196087 			    ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) &&
    460  6225  ab196087 			    ((ndx + 1) < argstate->dyn.num)) {
    461  6225  ab196087 				Dyn *dyn1 = &argstate->dyn.data[ndx + 1];
    462  6225  ab196087 
    463  6225  ab196087 				if (dyn1->d_tag != DT_NEEDED)
    464  6225  ab196087 					continue;
    465  6225  ab196087 				name = elfedit_offset_to_str(argstate->strsec,
    466  6225  ab196087 				    dyn1->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
    467  6225  ab196087 				if (strncmp(name, argstate->dyn_elt_str,
    468  6225  ab196087 				    strlen(argstate->dyn_elt_str)) != 0)
    469  6225  ab196087 					continue;
    470  6225  ab196087 			}
    471  6225  ab196087 
    472  5088  ab196087 			name = conv_dyn_posflag1(dyn->d_un.d_val,
    473  5088  ab196087 			    flags_fmt_flags, &c_buf.posflag1);
    474  6225  ab196087 			/*
    475  6225  ab196087 			 * DT_POSFLAG_1 is a positional element that affects
    476  6225  ab196087 			 * the following item. If using the default output
    477  6225  ab196087 			 * style, then show the following item as well.
    478  6225  ab196087 			 */
    479  6225  ab196087 			one_shot = (outstyle == ELFEDIT_OUTSTYLE_DEFAULT);
    480  5088  ab196087 			break;
    481  5088  ab196087 		case DT_FEATURE_1:
    482  5088  ab196087 			name = conv_dyn_feature1(dyn->d_un.d_val,
    483  5088  ab196087 			    flags_fmt_flags, &c_buf.feature1);
    484  5088  ab196087 			break;
    485  5088  ab196087 		case DT_DEPRECATED_SPARC_REGISTER:
    486  5088  ab196087 			name = MSG_INTL(MSG_STR_DEPRECATED);
    487  6206  ab196087 			break;
    488  6206  ab196087 		case DT_SUNW_LDMACH:
    489  9273       Ali 			if (osabi_solaris)
    490  9273       Ali 				name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0,
    491  9273       Ali 				    &c_buf.inv);
    492  5088  ab196087 			break;
    493  5088  ab196087 		}
    494  5088  ab196087 
    495  5088  ab196087 		if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
    496  9273       Ali 			Ehdr	*ehdr;
    497  9273       Ali 
    498  5088  ab196087 			if (header_done == 0) {
    499  5088  ab196087 				header_done = 1;
    500  5088  ab196087 				Elf_dyn_title(0);
    501  5088  ab196087 			}
    502  5088  ab196087 			if (name == NULL)
    503  5088  ab196087 				name = MSG_ORIG(MSG_STR_EMPTY);
    504  9273       Ali 			ehdr = argstate->obj_state->os_ehdr;
    505  5088  ab196087 			Elf_dyn_entry(0, dyn, ndx, name,
    506  9273       Ali 			    ehdr->e_ident[EI_OSABI], ehdr->e_machine);
    507  5088  ab196087 		} else {
    508  5088  ab196087 			/*
    509  5088  ab196087 			 * In simple or numeric mode under a print type
    510  5088  ab196087 			 * that is based on tag type rather than on index,
    511  8368       Ali 			 * if there are more than one qualifying tag, we
    512  8368       Ali 			 * want to skip printing redundant information.
    513  5088  ab196087 			 */
    514  5088  ab196087 			switch (print_type) {
    515  5088  ab196087 			case PRINT_DYN_T_TAG:
    516  8368       Ali 				switch (dyn->d_tag) {
    517  8368       Ali 				case DT_NEEDED:
    518  8368       Ali 					/* Multiple NEEDED entries are normal */
    519  8368       Ali 					break;
    520  8368       Ali 				case DT_POSFLAG_1:
    521  8368       Ali 					/*
    522  8368       Ali 					 * Positional flags don't count,
    523  8368       Ali 					 * because each one affects a different
    524  8368       Ali 					 * item. Don't skip those even if they
    525  8368       Ali 					 * have duplicate values.
    526  8368       Ali 					 */
    527  8368       Ali 					break;
    528  8368       Ali 				default:
    529  8368       Ali 					/*
    530  8368       Ali 					 * Anything else: If we've already
    531  8368       Ali 					 * printed this value, don't print
    532  8368       Ali 					 * it again.
    533  8368       Ali 					 */
    534  8368       Ali 					if (printed &&
    535  8368       Ali 					    (last_d_val == dyn->d_un.d_val))
    536  8368       Ali 						continue;
    537  8368       Ali 				}
    538  8368       Ali 				break;
    539  8368       Ali 			case PRINT_DYN_T_RUNPATH:
    540  6225  ab196087 				/*
    541  8368       Ali 				 * If we've already printed this value,
    542  8368       Ali 				 * don't print it again. This commonly
    543  8368       Ali 				 * happens when both DT_RPATH and DT_RUNPATH
    544  8368       Ali 				 * are present with the same value.
    545  6225  ab196087 				 */
    546  5088  ab196087 				if (printed && (last_d_val == dyn->d_un.d_val))
    547  5088  ab196087 					continue;
    548  6225  ab196087 				break;
    549  5088  ab196087 			}
    550  5088  ab196087 
    551  5088  ab196087 			if ((name != NULL) &&
    552  5088  ab196087 			    (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) {
    553  5088  ab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name);
    554  5088  ab196087 			} else {
    555  5088  ab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL),
    556  5088  ab196087 				    dyn->d_un.d_val);
    557  5088  ab196087 			}
    558  5088  ab196087 		}
    559  5088  ab196087 		printed = 1;
    560  5088  ab196087 		last_d_val = dyn->d_un.d_val;
    561  5088  ab196087 	}
    562  5088  ab196087 
    563  5088  ab196087 	/*
    564  5088  ab196087 	 * If nothing was output under the print types that are
    565  5088  ab196087 	 * based on tag type, issue an error saying it doesn't exist.
    566  5088  ab196087 	 */
    567  5088  ab196087 	if (!printed) {
    568  5088  ab196087 		if (print_type == PRINT_DYN_T_TAG) {
    569  9273       Ali 			Conv_inv_buf_t	inv_buf;
    570  9273       Ali 			Ehdr		*ehdr = argstate->obj_state->os_ehdr;
    571  5088  ab196087 
    572  5088  ab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
    573  5088  ab196087 			    MSG_INTL(MSG_ERR_NODYNELT),
    574  5088  ab196087 			    EC_WORD(argstate->dyn.sec->sec_shndx),
    575  5088  ab196087 			    argstate->dyn.sec->sec_name, conv_dyn_tag(arg,
    576  9273       Ali 			    ehdr->e_ident[EI_OSABI], ehdr->e_machine,
    577  5088  ab196087 			    0, &inv_buf));
    578  5088  ab196087 		}
    579  5088  ab196087 
    580  5088  ab196087 		if (print_type == PRINT_DYN_T_RUNPATH)
    581  5088  ab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
    582  5088  ab196087 			    MSG_INTL(MSG_ERR_NORUNPATH),
    583  5088  ab196087 			    EC_WORD(argstate->dyn.sec->sec_shndx),
    584  5088  ab196087 			    argstate->dyn.sec->sec_name);
    585  5088  ab196087 	}
    586  5088  ab196087 }
    587  5088  ab196087 
    588  5088  ab196087 
    589  5088  ab196087 /*
    590  6225  ab196087  * Determine the index(s) of the dynamic element(s) to be displayed and/or
    591  6225  ab196087  * manipulated.
    592  5088  ab196087  *
    593  5088  ab196087  * entry:
    594  5088  ab196087  *	argstate - Argument state block
    595  6225  ab196087  *	arg - If the command being called accepts a first plain argument
    596  6225  ab196087  *		named 'elt' which is used to specify the dynamic element,
    597  6225  ab196087  *		arg is the value of argv[0] for that command. If the
    598  6225  ab196087  *		command does not accept an 'elt' argument and instead
    599  6225  ab196087  *		implicitly assumes a tag type, arg is the constant string
    600  6225  ab196087  *		for that type (e.g. "DT_POSFLAG_1").
    601  5088  ab196087  *	print_request - True if the command is to print the current
    602  5088  ab196087  *		value(s) and return without changing anything.
    603  5088  ab196087  *	print_type - Address of variable containing PRINT_DYN_T_
    604  5088  ab196087  *		code specifying how the elements will be displayed.
    605  5088  ab196087  *
    606  5088  ab196087  * exit:
    607  6225  ab196087  *	If print_request is False: This routine always returns the index
    608  6225  ab196087  *	of a single dynamic element. *print_type is set to PRINT_DYN_T_NDX.
    609  6225  ab196087  *	The 'elt' argument as well as any modifier options (-dynndx, -needed)
    610  6225  ab196087  *	are examined to determine this index. If there are no modifier options,
    611  6225  ab196087  *	the dynamic section contains no element of the desired type, and there
    612  6225  ab196087  *	is an extra DT_NULL element in the section, then a new element of
    613  6225  ab196087  *	the desired type is created and its index returned. Otherwise an
    614  6225  ab196087  *	error is issued.
    615  5088  ab196087  *
    616  6225  ab196087  *	If print_request is True: If a modifier (-dynndx, -needed) was used,
    617  6225  ab196087  *	*print_type is set to PRINT_DYN_T_NDX and the index of the
    618  6225  ab196087  *	corresponding single dynamic element is returned. If no modifier
    619  6225  ab196087  *	was used, *print_type is set to PRINT_DYN_T_TAG, and the tag
    620  6225  ab196087  *	type code is returned.
    621  5088  ab196087  */
    622  5088  ab196087 static Word
    623  6225  ab196087 arg_to_index(ARGSTATE *argstate, const char *arg,
    624  5088  ab196087     int print_request, PRINT_DYN_T *print_type)
    625  5088  ab196087 {
    626  9273       Ali 	Word	ndx;
    627  9273       Ali 	Xword	dt_value;
    628  6225  ab196087 	Dyn	*dyn;
    629  5088  ab196087 
    630  5088  ab196087 
    631  5088  ab196087 	/* Assume we are returning an index, alter as needed below */
    632  5088  ab196087 	*print_type = PRINT_DYN_T_NDX;
    633  5088  ab196087 
    634  6225  ab196087 	/*
    635  6225  ab196087 	 * All the commands that accept the DYN_OPT_F_DYNNDX_ELT form
    636  6225  ab196087 	 * of -dynndx require a plain argument named 'elt' as their first
    637  6225  ab196087 	 * argument. -dynndx is a modifier that means that 'elt' is a
    638  6225  ab196087 	 * simple numeric section index. Routines that accept this form
    639  6225  ab196087 	 * of -dynndx are willing to handle any tag type, so all we need
    640  6225  ab196087 	 * to check is that the value is in range.
    641  6225  ab196087 	 */
    642  6225  ab196087 	if ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0)
    643  6225  ab196087 		return ((Word) elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_ELT),
    644  6225  ab196087 		    0, argstate->dyn.num - 1, NULL));
    645  5088  ab196087 
    646  6225  ab196087 	/* arg is a DT_ tag type, not a numeric index */
    647  5088  ab196087 	dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT);
    648  6225  ab196087 
    649  6225  ab196087 	/*
    650  6225  ab196087 	 * Commands that accept the DYN_OPT_F_DYNNDX_VAL form  of
    651  6225  ab196087 	 * dynndx do not accept the 'elt' argument. The index is a
    652  6225  ab196087 	 * value that follows the option, and was saved in argstate by
    653  6225  ab196087 	 * process_args(). Routines that accept this form of -dynndx
    654  6225  ab196087 	 * require the specified element to have a specific tag type,
    655  6225  ab196087 	 * so we test for this as well as for the index being in range.
    656  6225  ab196087 	 */
    657  6225  ab196087 	if ((argstate->optmask & DYN_OPT_F_DYNNDX_VAL) != 0) {
    658  6225  ab196087 		ndx = ((Word) elfedit_atoui_range(argstate->dyn_elt_str,
    659  6225  ab196087 		    MSG_ORIG(MSG_STR_INDEX), 0, argstate->dyn.num - 1, NULL));
    660  6225  ab196087 		if (argstate->dyn.data[ndx].d_tag != dt_value) {
    661  9273       Ali 			Ehdr	*ehdr = argstate->obj_state->os_ehdr;
    662  9273       Ali 			uchar_t	osabi = ehdr->e_ident[EI_OSABI];
    663  9273       Ali 			Half	mach = ehdr->e_machine;
    664  6225  ab196087 			Conv_inv_buf_t	is, want;
    665  6225  ab196087 
    666  6225  ab196087 			elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_WRONGTAG),
    667  6225  ab196087 			    EC_WORD(argstate->dyn.sec->sec_shndx),
    668  6225  ab196087 			    argstate->dyn.sec->sec_name, ndx,
    669  9273       Ali 			    conv_dyn_tag(dt_value, osabi, mach, 0, &want),
    670  9273       Ali 			    conv_dyn_tag(argstate->dyn.data[ndx].d_tag,
    671  9273       Ali 			    osabi, mach, 0, &is));
    672  6225  ab196087 		}
    673  6225  ab196087 		return (ndx);
    674  6225  ab196087 	}
    675  5088  ab196087 
    676  5088  ab196087 	/*
    677  5088  ab196087 	 * If this is a printing request, then we let print_dyn() show
    678  5088  ab196087 	 * all the items with this tag type.
    679  5088  ab196087 	 */
    680  5088  ab196087 	if (print_request) {
    681  5088  ab196087 		*print_type = PRINT_DYN_T_TAG;
    682  5088  ab196087 		return (dt_value);
    683  6225  ab196087 	}
    684  6225  ab196087 
    685  6225  ab196087 	/*
    686  6225  ab196087 	 * Commands that accept -needed are looking for the dt_value element
    687  6225  ab196087 	 * (usually DT_POSFLAG_1) that immediately preceeds the DT_NEEDED
    688  6225  ab196087 	 * element with the string given by argstate->dyn_elt_str.
    689  6225  ab196087 	 */
    690  6225  ab196087 	if ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) {
    691  6225  ab196087 		Word	retndx = argstate->dyn.num;	/* Out of range value */
    692  6225  ab196087 		const char	*name;
    693  6225  ab196087 		size_t		len;
    694  6225  ab196087 
    695  6225  ab196087 		len = strlen(argstate->dyn_elt_str);
    696  6225  ab196087 		for (ndx = 0, dyn = argstate->dyn.data;
    697  6225  ab196087 		    ndx < argstate->dyn.num; dyn++, ndx++) {
    698  6225  ab196087 			/*
    699  6225  ab196087 			 * If the immediately preceeding item has the
    700  6225  ab196087 			 * tag type we're looking for, and the current item
    701  6225  ab196087 			 * is a DT_NEEDED with a string that matches,
    702  6225  ab196087 			 * then the preceeding item is the one we want.
    703  6225  ab196087 			 */
    704  6225  ab196087 			if ((dyn->d_tag == DT_NEEDED) &&
    705  6225  ab196087 			    (ndx > 0) && (retndx == (ndx - 1))) {
    706  6225  ab196087 				name = elfedit_offset_to_str(argstate->strsec,
    707  6225  ab196087 				    dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
    708  6225  ab196087 
    709  6225  ab196087 				if (strncmp(name,
    710  6225  ab196087 				    argstate->dyn_elt_str, len) == 0)
    711  6225  ab196087 					return (retndx);
    712  6225  ab196087 				continue;
    713  6225  ab196087 			}
    714  6225  ab196087 
    715  6225  ab196087 			/*
    716  6225  ab196087 			 * If the current item has the tag type we're
    717  6225  ab196087 			 * looking for, make it our current candidate.
    718  6225  ab196087 			 * If the next item is a DT_NEEDED with the right
    719  6225  ab196087 			 * string value, we'll use it then.
    720  6225  ab196087 			 */
    721  6225  ab196087 			if (dyn->d_tag == dt_value)
    722  6225  ab196087 				retndx = ndx;
    723  6225  ab196087 		}
    724  6225  ab196087 
    725  6225  ab196087 		/* If we get here, no matching DT_NEEDED was found */
    726  6225  ab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEDNOMATCH),
    727  6225  ab196087 		    EC_WORD(argstate->dyn.sec->sec_shndx),
    728  6225  ab196087 		    argstate->dyn.sec->sec_name, argstate->dyn_elt_str);
    729  5088  ab196087 	}
    730  5088  ab196087 
    731  5088  ab196087 	/* Locate the first entry with the given tag type */
    732  5088  ab196087 	for (ndx = 0; ndx < argstate->dyn.num; ndx++) {
    733  5088  ab196087 		if (argstate->dyn.data[ndx].d_tag == dt_value) {
    734  5088  ab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
    735  5088  ab196087 			    MSG_INTL(MSG_DEBUG_DT2NDX),
    736  5088  ab196087 			    EC_WORD(argstate->dyn.sec->sec_shndx),
    737  5088  ab196087 			    argstate->dyn.sec->sec_name, EC_WORD(ndx), arg);
    738  5088  ab196087 			return (ndx);
    739  5088  ab196087 		}
    740  5088  ab196087 	}
    741  5088  ab196087 
    742  5088  ab196087 	/* Not found. Can we create one? */
    743  5088  ab196087 	if (argstate->dyn.num_null_ndx > 1)
    744  5088  ab196087 		return (convert_dt_null(argstate, dt_value, 0));
    745  5088  ab196087 
    746  5088  ab196087 	/* No room to create one, so we're out of options and must fail */
    747  5088  ab196087 	elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT),
    748  5088  ab196087 	    EC_WORD(argstate->dyn.sec->sec_shndx),
    749  5088  ab196087 	    argstate->dyn.sec->sec_name, arg);
    750  5088  ab196087 
    751  5088  ab196087 	/*NOTREACHED*/
    752  5088  ab196087 	return (0);		/* For lint */
    753  5088  ab196087 }
    754  5088  ab196087 
    755  5088  ab196087 
    756  5088  ab196087 /*
    757  5088  ab196087  * Called by cmd_body() for dyn:value. Implements the core functionality
    758  5088  ab196087  * for that command.
    759  5088  ab196087  *
    760  5088  ab196087  * This routine expects that both the index and value arguments are
    761  5088  ab196087  * present.
    762  5088  ab196087  */
    763  5088  ab196087 static elfedit_cmdret_t
    764  5088  ab196087 cmd_body_value(ARGSTATE *argstate, Word *ret_ndx)
    765  5088  ab196087 {
    766  5088  ab196087 	elfedit_section_t	*dynsec = argstate->dyn.sec;
    767  5088  ab196087 	elfedit_section_t	*strsec = argstate->strsec;
    768  5088  ab196087 	elfedit_dyn_elt_t	strpad_elt;
    769  5088  ab196087 	Word	i;
    770  5088  ab196087 	Dyn	*dyn = argstate->dyn.data;
    771  5088  ab196087 	Word	numdyn = argstate->dyn.num;
    772  6225  ab196087 	int	minus_add, minus_s, minus_dynndx;
    773  9273       Ali 	Word	tmp_val;
    774  9273       Ali 	Xword	arg1, arg2;
    775  5088  ab196087 	int	arg2_known = 1;
    776  5088  ab196087 
    777  6225  ab196087 	minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0);
    778  6225  ab196087 	minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0);
    779  6225  ab196087 	minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0);
    780  5088  ab196087 
    781  5088  ab196087 	elfedit_dyn_elt_init(&strpad_elt);
    782  5088  ab196087 
    783  5088  ab196087 	/*
    784  5088  ab196087 	 * The first argument is an index if -dynndx is used, and is a
    785  5088  ab196087 	 * tag value otherwise.
    786  5088  ab196087 	 */
    787  5088  ab196087 	arg1 = minus_dynndx ?
    788  5088  ab196087 	    elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT),
    789  5088  ab196087 	    0, numdyn - 1, NULL) :
    790  5088  ab196087 	    elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT);
    791  5088  ab196087 
    792  5088  ab196087 	if (minus_s) {
    793  5088  ab196087 		/*
    794  5088  ab196087 		 * Don't allow the user to specify -s when manipulating a
    795  5088  ab196087 		 * DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to
    796  5088  ab196087 		 * manage the extra space used for strings, this would break
    797  5088  ab196087 		 * our ability to add the string.
    798  5088  ab196087 		 */
    799  5088  ab196087 		if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) ||
    800  5088  ab196087 		    (minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD)))
    801  5088  ab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
    802  5088  ab196087 			    MSG_INTL(MSG_ERR_STRPADSTRVAL),
    803  5088  ab196087 			    EC_WORD(dynsec->sec_shndx), dynsec->sec_name);
    804  5088  ab196087 
    805  5088  ab196087 		/* Locate DT_SUNW_STRPAD element if present */
    806  5088  ab196087 		strpad_elt.dn_dyn.d_un.d_val = 0;
    807  9273       Ali 		(void) elfedit_dynstr_getpad(argstate->obj_state,
    808  9273       Ali 		    argstate->dyn.sec, &strpad_elt);
    809  5088  ab196087 
    810  5088  ab196087 		/*
    811  5088  ab196087 		 * Look up the string: If the user specified the -dynndx
    812  5088  ab196087 		 * -option, then we will insert it if possible, and
    813  5088  ab196087 		 * fail with an error if not. However, if they did not
    814  5088  ab196087 		 * specify -dynndx, we want to look up the string if it is
    815  5088  ab196087 		 * already there, but defer the insertion. The reason for
    816  5088  ab196087 		 * this is that we may have to grab an unused DT_NULL element
    817  5088  ab196087 		 * below, and if there are none available, we won't want
    818  5088  ab196087 		 * to have modified the string table.
    819  5088  ab196087 		 *
    820  5088  ab196087 		 * This isn't a problem, because if the string isn't
    821  5088  ab196087 		 * in the string table, it can't be used by a dynamic element.
    822  5088  ab196087 		 * Hence, we don't need to insert it to know that there is
    823  5088  ab196087 		 * no match.
    824  5088  ab196087 		 */
    825  5088  ab196087 		if (minus_dynndx == 0) {
    826  5088  ab196087 			if (elfedit_sec_findstr(strsec,
    827  5088  ab196087 			    strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1],
    828  5088  ab196087 			    &tmp_val) == 0) {
    829  5088  ab196087 				arg2_known = 0;
    830  5088  ab196087 			} else {
    831  5088  ab196087 				arg2 = tmp_val;
    832  5088  ab196087 			}
    833  5088  ab196087 		} else {
    834  5088  ab196087 			arg2 = elfedit_dynstr_insert(dynsec, strsec,
    835  5088  ab196087 			    &strpad_elt, argstate->argv[1]);
    836  5088  ab196087 		}
    837  5088  ab196087 	} else {		/* Argument 2 is an integer */
    838  5088  ab196087 		arg2 = elfedit_atoui(argstate->argv[1], NULL);
    839  5088  ab196087 	}
    840  5088  ab196087 
    841  5088  ab196087 
    842  5088  ab196087 	if (!minus_dynndx && !(minus_add && !arg2_known)) {
    843  5088  ab196087 		/*
    844  5088  ab196087 		 * Search the dynamic section and see if an item with the
    845  5088  ab196087 		 * specified tag value already exists. We can reduce this
    846  5088  ab196087 		 * to a simple update of an existing value if -add is not
    847  5088  ab196087 		 * specified or the existing d_un value matches the new one.
    848  5088  ab196087 		 *
    849  5088  ab196087 		 * In either of these cases, we will change arg1 to be the
    850  5088  ab196087 		 * index, and set minus_dynndx, causing the simple update to
    851  5088  ab196087 		 * happen immediately below.
    852  5088  ab196087 		 */
    853  5088  ab196087 		for (i = 0; i < numdyn; i++) {
    854  5088  ab196087 			if ((dyn[i].d_tag == arg1) &&
    855  5088  ab196087 			    (!minus_add || (dyn[i].d_un.d_val == arg2))) {
    856  5088  ab196087 				arg1 = i;
    857  5088  ab196087 				minus_dynndx = 1;
    858  5088  ab196087 				break;
    859  5088  ab196087 			}
    860  5088  ab196087 		}
    861  5088  ab196087 	}
    862  5088  ab196087 
    863  5088  ab196087 	/*
    864  5088  ab196087 	 * If -dynndx is used, then this is a relatively simple
    865  5088  ab196087 	 * operation, as we simply write over the specified index.
    866  5088  ab196087 	 */
    867  5088  ab196087 	if (minus_dynndx) {
    868  5088  ab196087 		/*
    869  5088  ab196087 		 * If we held back from inserting a new string into
    870  5088  ab196087 		 * the dynstr above, we insert it now, because we
    871  5088  ab196087 		 * have a slot in the dynamic section, and we need
    872  5088  ab196087 		 * the string offset ot finish.
    873  5088  ab196087 		 */
    874  5088  ab196087 		if (!arg2_known)
    875  5088  ab196087 			arg2 = elfedit_dynstr_insert(dynsec, strsec,
    876  5088  ab196087 			    &strpad_elt, argstate->argv[1]);
    877  5088  ab196087 
    878  5088  ab196087 		*ret_ndx = arg1;
    879  5088  ab196087 		if (dyn[arg1].d_un.d_val == arg2) {
    880  5088  ab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
    881  5088  ab196087 			    MSG_INTL(MSG_DEBUG_X_OK),
    882  5088  ab196087 			    dynsec->sec_shndx, dynsec->sec_name,
    883  5088  ab196087 			    EC_WORD(arg1), EC_XWORD(arg2));
    884  5088  ab196087 			return (ELFEDIT_CMDRET_NONE);
    885  5088  ab196087 		} else {
    886  5088  ab196087 			/* Warn if setting DT_NULL value to non-zero */
    887  5088  ab196087 			if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0))
    888  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
    889  5088  ab196087 				    MSG_INTL(MSG_DEBUG_DTNULLVALUE),
    890  5088  ab196087 				    dynsec->sec_shndx, dynsec->sec_name,
    891  5088  ab196087 				    EC_WORD(arg1), EC_XWORD(arg2));
    892  5088  ab196087 
    893  5088  ab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
    894  5088  ab196087 			    MSG_INTL(MSG_DEBUG_X_CHG),
    895  5088  ab196087 			    dynsec->sec_shndx, dynsec->sec_name,
    896  5088  ab196087 			    EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val),
    897  5088  ab196087 			    EC_XWORD(arg2));
    898  5088  ab196087 			dyn[arg1].d_un.d_val = arg2;
    899  5088  ab196087 			return (ELFEDIT_CMDRET_MOD);
    900  5088  ab196087 		}
    901  5088  ab196087 	}
    902  5088  ab196087 
    903  5088  ab196087 	/*
    904  5088  ab196087 	 * We need a new slot in the dynamic section. If we can't have
    905  5088  ab196087 	 * one, then we fail.
    906  5088  ab196087 	 */
    907  5088  ab196087 	if (argstate->dyn.num_null_ndx <= 1)
    908  5088  ab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL),
    909  5088  ab196087 		    EC_WORD(dynsec->sec_shndx), dynsec->sec_name);
    910  5088  ab196087 
    911  5088  ab196087 	/*
    912  5088  ab196087 	 * If we still need to insert a new string into the dynstr,
    913  5088  ab196087 	 * then it is safe now, because if we succeed, we know that
    914  5088  ab196087 	 * there is an available slot to receive it. If we fail, we
    915  5088  ab196087 	 * haven't claimed the extra slot yet, and it will be unharmed.
    916  5088  ab196087 	 */
    917  5088  ab196087 	if (!arg2_known)
    918  5088  ab196087 		arg2 = elfedit_dynstr_insert(dynsec, strsec,
    919  5088  ab196087 		    &strpad_elt, argstate->argv[1]);
    920  5088  ab196087 
    921  5088  ab196087 	/* Use an extra DT_NULL slot and enter the new element */
    922  5088  ab196087 	*ret_ndx = convert_dt_null(argstate, arg1, arg2);
    923  5088  ab196087 	return (ELFEDIT_CMDRET_MOD);
    924  5088  ab196087 }
    925  5088  ab196087 
    926  5088  ab196087 
    927  5088  ab196087 
    928  5088  ab196087 /*
    929  5088  ab196087  * Called by cmd_body() for dyn:runpath. Implements the core functionality
    930  5088  ab196087  * for that command.
    931  5088  ab196087  *
    932  5088  ab196087  * History Lesson And Strategy:
    933  5088  ab196087  *
    934  5088  ab196087  * This routine handles both DT_RPATH and DT_RUNPATH entries, altering
    935  5088  ab196087  * either or both if they are present.
    936  5088  ab196087  *
    937  5088  ab196087  * The original SYSV ABI only had DT_RPATH, and the runtime loader used
    938  5088  ab196087  * it to search for things in the following order:
    939  5088  ab196087  *
    940  5088  ab196087  *	DT_RPATH, LD_LIBRARY_PATH, defaults
    941  5088  ab196087  *
    942  5088  ab196087  * Solaris did not follow this rule, an extremely rare deviation from
    943  5088  ab196087  * the ABI. Environment variables should supercede everything else,
    944  5088  ab196087  * otherwise they are not very useful. This decision was made at the
    945  5088  ab196087  * very beginning of the SunOS 5.x development, so we have always
    946  5088  ab196087  * deviated from the ABI and and instead search in the order
    947  5088  ab196087  *
    948  5088  ab196087  *	LD_LIBRARY_PATH, DT_RPATH, defaults
    949  5088  ab196087  *
    950  5088  ab196087  * Other Unix variants initially followed the ABI, but in recent years
    951  5088  ab196087  * have come to agree with the early Solaris folks that it was a mistake.
    952  5088  ab196087  * Hence, DT_RUNPATH was invented, with the search order:
    953  5088  ab196087  *
    954  5088  ab196087  *	LD_LIBRARY_PATH, DT_RUNPATH, defaults
    955  5088  ab196087  *
    956  5088  ab196087  * So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both
    957  5088  ab196087  * are present (which does happen), we set them both to the new
    958  5088  ab196087  * value. If either one is present, we set that one. If neither is
    959  5088  ab196087  * present, and we have a spare DT_NULL slot, we create a DT_RUNPATH, but
    960  5088  ab196087  * not a DT_RPATH, to conserve available slots for other uses.
    961  5088  ab196087  */
    962  5088  ab196087 static elfedit_cmdret_t
    963  5088  ab196087 cmd_body_runpath(ARGSTATE *argstate)
    964  5088  ab196087 {
    965  5088  ab196087 	elfedit_section_t	*dynsec = argstate->dyn.sec;
    966  5088  ab196087 	elfedit_section_t	*strsec = argstate->strsec;
    967  5088  ab196087 	elfedit_dyn_elt_t	rpath_elt;
    968  5088  ab196087 	elfedit_dyn_elt_t	runpath_elt;
    969  5088  ab196087 	elfedit_dyn_elt_t	strpad_elt;
    970  5088  ab196087 	Word			i;
    971  5088  ab196087 	Dyn			*dyn = argstate->dyn.data;
    972  5088  ab196087 	Word			numdyn = argstate->dyn.num;
    973  5088  ab196087 
    974  5088  ab196087 	/* Go through the tags and gather what we need */
    975  5088  ab196087 	elfedit_dyn_elt_init(&rpath_elt);
    976  5088  ab196087 	elfedit_dyn_elt_init(&runpath_elt);
    977  5088  ab196087 	elfedit_dyn_elt_init(&strpad_elt);
    978  5088  ab196087 	for (i = 0; i < numdyn; i++) {
    979  5088  ab196087 		switch (dyn[i].d_tag) {
    980  5088  ab196087 		case DT_RPATH:
    981  5088  ab196087 			elfedit_dyn_elt_save(&rpath_elt, i, &dyn[i]);
    982  5088  ab196087 			break;
    983  5088  ab196087 
    984  5088  ab196087 		case DT_RUNPATH:
    985  5088  ab196087 			elfedit_dyn_elt_save(&runpath_elt, i, &dyn[i]);
    986  5088  ab196087 			break;
    987  5088  ab196087 
    988  5088  ab196087 		case DT_SUNW_STRPAD:
    989  9273       Ali 			if (elfedit_test_osabi(argstate->obj_state,
    990  9273       Ali 			    ELFOSABI_SOLARIS, 0))
    991  9273       Ali 				elfedit_dyn_elt_save(&strpad_elt, i, &dyn[i]);
    992  5088  ab196087 			break;
    993  5088  ab196087 		}
    994  5088  ab196087 	}
    995  5088  ab196087 
    996  5088  ab196087 	/*  Do we have an available dynamic section entry to use? */
    997  5088  ab196087 	if (rpath_elt.dn_seen || runpath_elt.dn_seen) {
    998  5088  ab196087 		/*
    999  5088  ab196087 		 * We have seen a DT_RPATH, or a DT_RUNPATH, or both.
   1000  5088  ab196087 		 * If all of these have the same string as the desired
   1001  5088  ab196087 		 * new value, then we don't need to alter anything and can
   1002  5088  ab196087 		 * simply return. Otherwise, we'll modify them all to have
   1003  5088  ab196087 		 * the new string (below).
   1004  5088  ab196087 		 */
   1005  5088  ab196087 		if ((!rpath_elt.dn_seen ||
   1006  5088  ab196087 		    (strcmp(elfedit_dyn_offset_to_str(strsec, &rpath_elt),
   1007  5088  ab196087 		    argstate->argv[0]) == 0)) &&
   1008  5088  ab196087 		    (!runpath_elt.dn_seen ||
   1009  5088  ab196087 		    (strcmp(elfedit_dyn_offset_to_str(strsec, &runpath_elt),
   1010  5088  ab196087 		    argstate->argv[0]) == 0))) {
   1011  5088  ab196087 			if (rpath_elt.dn_seen)
   1012  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1013  5088  ab196087 				    MSG_INTL(MSG_DEBUG_OLDRPATHOK),
   1014  5088  ab196087 				    EC_WORD(dynsec->sec_shndx),
   1015  5088  ab196087 				    dynsec->sec_name, EC_WORD(rpath_elt.dn_ndx),
   1016  5088  ab196087 				    elfedit_atoconst_value_to_str(
   1017  5088  ab196087 				    ELFEDIT_CONST_DT, DT_RPATH, 1));
   1018  5088  ab196087 			if (runpath_elt.dn_seen)
   1019  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1020  5088  ab196087 				    MSG_INTL(MSG_DEBUG_OLDRPATHOK),
   1021  5088  ab196087 				    EC_WORD(dynsec->sec_shndx),
   1022  5088  ab196087 				    dynsec->sec_name,
   1023  5088  ab196087 				    EC_WORD(runpath_elt.dn_ndx),
   1024  5088  ab196087 				    elfedit_atoconst_value_to_str(
   1025  5088  ab196087 				    ELFEDIT_CONST_DT, DT_RUNPATH, 1));
   1026  5088  ab196087 			return (ELFEDIT_CMDRET_NONE);
   1027  5088  ab196087 		}
   1028  5088  ab196087 	} else if (argstate->dyn.num_null_ndx <= 1) {
   1029  5088  ab196087 		/*
   1030  5088  ab196087 		 * There is no DT_RPATH or DT_RUNPATH in the dynamic array,
   1031  5088  ab196087 		 * and there are no extra DT_NULL entries that we can
   1032  5088  ab196087 		 * convert into one. We cannot proceed.
   1033  5088  ab196087 		 */
   1034  5088  ab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL),
   1035  5088  ab196087 		    EC_WORD(dynsec->sec_shndx), dynsec->sec_name);
   1036  5088  ab196087 	}
   1037  5088  ab196087 
   1038  5088  ab196087 	/* Does the string exist in the table already, or can we add it? */
   1039  5088  ab196087 	rpath_elt.dn_dyn.d_un.d_val = runpath_elt.dn_dyn.d_un.d_val =
   1040  5088  ab196087 	    elfedit_dynstr_insert(dynsec, strsec, &strpad_elt,
   1041  5088  ab196087 	    argstate->argv[0]);
   1042  5088  ab196087 
   1043  5088  ab196087 	/* Update DT_RPATH entry if present */
   1044  5088  ab196087 	if (rpath_elt.dn_seen) {
   1045  5088  ab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_PREVRPATH),
   1046  5088  ab196087 		    EC_WORD(dynsec->sec_shndx), dynsec->sec_name,
   1047  5088  ab196087 		    EC_WORD(rpath_elt.dn_ndx),
   1048  5088  ab196087 		    elfedit_atoconst_value_to_str(
   1049  5088  ab196087 		    ELFEDIT_CONST_DT, DT_RPATH, 1),
   1050  5088  ab196087 		    elfedit_dyn_offset_to_str(strsec, &rpath_elt));
   1051  5088  ab196087 		dyn[rpath_elt.dn_ndx] = rpath_elt.dn_dyn;
   1052  5088  ab196087 	}
   1053  5088  ab196087 
   1054  5088  ab196087 	/*
   1055  5088  ab196087 	 * Update the DT_RUNPATH entry in the dynamic section, if present.
   1056  5088  ab196087 	 * If one is not present, and there is also no DT_RPATH, then
   1057  5088  ab196087 	 * we use a spare DT_NULL entry to create a new DT_RUNPATH.
   1058  5088  ab196087 	 */
   1059  5088  ab196087 	if (runpath_elt.dn_seen || !rpath_elt.dn_seen) {
   1060  5088  ab196087 		if (runpath_elt.dn_seen) {
   1061  5088  ab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
   1062  5088  ab196087 			    MSG_INTL(MSG_DEBUG_PREVRPATH),
   1063  5088  ab196087 			    EC_WORD(dynsec->sec_shndx), dynsec->sec_name,
   1064  5088  ab196087 			    EC_WORD(runpath_elt.dn_ndx),
   1065  5088  ab196087 			    elfedit_atoconst_value_to_str(
   1066  5088  ab196087 			    ELFEDIT_CONST_DT, DT_RUNPATH, 1),
   1067  5088  ab196087 			    elfedit_dyn_offset_to_str(strsec, &runpath_elt));
   1068  5088  ab196087 			dyn[runpath_elt.dn_ndx] = runpath_elt.dn_dyn;
   1069  5088  ab196087 		} else {	/* Using a spare DT_NULL entry */
   1070  5088  ab196087 			(void) convert_dt_null(argstate, DT_RUNPATH,
   1071  5088  ab196087 			    runpath_elt.dn_dyn.d_un.d_val);
   1072  5088  ab196087 		}
   1073  5088  ab196087 	}
   1074  5088  ab196087 
   1075  5088  ab196087 	return (ELFEDIT_CMDRET_MOD);
   1076  5088  ab196087 }
   1077  5088  ab196087 
   1078  5088  ab196087 
   1079  5088  ab196087 
   1080  5088  ab196087 /*
   1081  5088  ab196087  * Argument processing for the bitmask commands. Convert the arguments
   1082  5088  ab196087  * to integer form, apply -and/-cmp/-or, and return the resulting value.
   1083  5088  ab196087  *
   1084  5088  ab196087  * entry:
   1085  5088  ab196087  *	argstate - Argument state block
   1086  5088  ab196087  *	orig - Value of original bitmask
   1087  5088  ab196087  *	const_type - ELFEDIT_CONST_* value for type of constants
   1088  5088  ab196087  */
   1089  5088  ab196087 static Word
   1090  5088  ab196087 flag_bitop(ARGSTATE *argstate, Word orig, elfedit_const_t const_type)
   1091  5088  ab196087 {
   1092  5088  ab196087 	Word flags = 0;
   1093  5088  ab196087 	int i;
   1094  5088  ab196087 
   1095  5088  ab196087 	/* Collect the arguments */
   1096  5088  ab196087 	for (i = 0; i < argstate->argc; i++)
   1097  5088  ab196087 		flags |= (Word) elfedit_atoconst(argstate->argv[i], const_type);
   1098  5088  ab196087 
   1099  5088  ab196087 	/* Complement the value? */
   1100  5088  ab196087 	if (argstate->optmask & DYN_OPT_F_CMP)
   1101  5088  ab196087 		flags = ~flags;
   1102  5088  ab196087 
   1103  5088  ab196087 	/* Perform any requested bit operations */
   1104  5088  ab196087 	if (argstate->optmask & DYN_OPT_F_AND)
   1105  5088  ab196087 		flags &= orig;
   1106  5088  ab196087 	else if (argstate->optmask & DYN_OPT_F_OR)
   1107  5088  ab196087 		flags |= orig;
   1108  5088  ab196087 
   1109  5088  ab196087 	return (flags);
   1110  5088  ab196087 }
   1111  5088  ab196087 
   1112  5088  ab196087 
   1113  5088  ab196087 
   1114  5088  ab196087 /*
   1115  5088  ab196087  * Common body for the dyn: module commands. These commands
   1116  5088  ab196087  * share a large amount of common behavior, so it is convenient
   1117  5088  ab196087  * to centralize things and use the cmd argument to handle the
   1118  5088  ab196087  * small differences.
   1119  5088  ab196087  *
   1120  5088  ab196087  * entry:
   1121  5088  ab196087  *	cmd - One of the DYN_CMD_T_* constants listed above, specifying
   1122  5088  ab196087  *		which command to implement.
   1123  5088  ab196087  *	obj_state, argc, argv - Standard command arguments
   1124  5088  ab196087  */
   1125  5088  ab196087 static elfedit_cmdret_t
   1126  5088  ab196087 cmd_body(DYN_CMD_T cmd, elfedit_obj_state_t *obj_state,
   1127  5088  ab196087     int argc, const char *argv[])
   1128  5088  ab196087 {
   1129  5088  ab196087 	ARGSTATE		argstate;
   1130  5088  ab196087 	Dyn			*dyn;
   1131  5088  ab196087 	const char		*dyn_name;
   1132  5088  ab196087 	Word			dyn_ndx, dyn_num, null_ndx;
   1133  5088  ab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
   1134  5088  ab196087 	PRINT_DYN_T		print_type = PRINT_DYN_T_ALL;
   1135  5088  ab196087 	Word			ndx;
   1136  5088  ab196087 	int			print_only = 0;
   1137  5088  ab196087 	int			do_autoprint = 1;
   1138  5088  ab196087 
   1139  5088  ab196087 	/* Process the optional arguments */
   1140  5088  ab196087 	process_args(obj_state, argc, argv, &argstate);
   1141  5088  ab196087 
   1142  5088  ab196087 	dyn = argstate.dyn.data;
   1143  5088  ab196087 	dyn_num = argstate.dyn.num;
   1144  5088  ab196087 	dyn_name = argstate.dyn.sec->sec_name;
   1145  5088  ab196087 	dyn_ndx = argstate.dyn.sec->sec_shndx;
   1146  5088  ab196087 
   1147  5088  ab196087 	/* Check number of arguments, gather information */
   1148  5088  ab196087 	switch (cmd) {
   1149  5088  ab196087 	case DYN_CMD_T_DUMP:
   1150  5088  ab196087 		/* dyn:dump can accept an optional index argument */
   1151  5088  ab196087 		if (argstate.argc > 1)
   1152  5088  ab196087 			elfedit_command_usage();
   1153  5088  ab196087 		print_only = 1;
   1154  5088  ab196087 		if (argstate.argc == 1)
   1155  5088  ab196087 			ndx = arg_to_index(&argstate, argstate.argv[0],
   1156  6225  ab196087 			    print_only, &print_type);
   1157  5088  ab196087 		break;
   1158  5088  ab196087 
   1159  5088  ab196087 	case DYN_CMD_T_TAG:
   1160  5088  ab196087 		print_only = (argstate.argc != 2);
   1161  5088  ab196087 		if (argstate.argc > 0) {
   1162  5088  ab196087 			if (argstate.argc > 2)
   1163  5088  ab196087 				elfedit_command_usage();
   1164  5088  ab196087 			ndx = arg_to_index(&argstate, argstate.argv[0],
   1165  6225  ab196087 			    print_only, &print_type);
   1166  5088  ab196087 		}
   1167  5088  ab196087 		break;
   1168  5088  ab196087 
   1169  5088  ab196087 	case DYN_CMD_T_VALUE:
   1170  5088  ab196087 		print_only = (argstate.argc != 2);
   1171  5088  ab196087 		if (argstate.argc > 2)
   1172  5088  ab196087 			elfedit_command_usage();
   1173  5088  ab196087 		if (argstate.argc > 0) {
   1174  5088  ab196087 			if (print_only) {
   1175  5088  ab196087 				ndx = arg_to_index(&argstate, argstate.argv[0],
   1176  5088  ab196087 				    print_only, &print_type);
   1177  5088  ab196087 			} else {
   1178  5088  ab196087 				print_type = PRINT_DYN_T_NDX;
   1179  5088  ab196087 			}
   1180  5088  ab196087 		}
   1181  5088  ab196087 		break;
   1182  5088  ab196087 
   1183  5088  ab196087 	case DYN_CMD_T_DELETE:
   1184  5088  ab196087 		if ((argstate.argc < 1) || (argstate.argc > 2))
   1185  5088  ab196087 			elfedit_command_usage();
   1186  5088  ab196087 		ndx = arg_to_index(&argstate, argstate.argv[0],
   1187  5088  ab196087 		    0, &print_type);
   1188  5088  ab196087 		do_autoprint = 0;
   1189  5088  ab196087 		break;
   1190  5088  ab196087 
   1191  5088  ab196087 	case DYN_CMD_T_MOVE:
   1192  5088  ab196087 		if ((argstate.argc < 2) || (argstate.argc > 3))
   1193  5088  ab196087 			elfedit_command_usage();
   1194  5088  ab196087 		ndx = arg_to_index(&argstate, argstate.argv[0],
   1195  6225  ab196087 		    0, &print_type);
   1196  5088  ab196087 		do_autoprint = 0;
   1197  5088  ab196087 		break;
   1198  5088  ab196087 
   1199  5088  ab196087 	case DYN_CMD_T_RUNPATH:
   1200  5088  ab196087 		if (argstate.argc > 1)
   1201  5088  ab196087 			elfedit_command_usage();
   1202  5088  ab196087 		/*
   1203  5088  ab196087 		 * dyn:runpath does not accept an explicit index
   1204  5088  ab196087 		 * argument, so we implicitly only show the DT_RPATH and
   1205  5088  ab196087 		 * DT_RUNPATH elements.
   1206  5088  ab196087 		 */
   1207  5088  ab196087 		print_type = PRINT_DYN_T_RUNPATH;
   1208  5088  ab196087 		print_only = (argstate.argc == 0);
   1209  5088  ab196087 		break;
   1210  5088  ab196087 
   1211  5088  ab196087 	case DYN_CMD_T_POSFLAG1:
   1212  5088  ab196087 		print_only = (argstate.argc == 0);
   1213  5088  ab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
   1214  5088  ab196087 		    ELFEDIT_CONST_DT, DT_POSFLAG_1, 1),
   1215  6225  ab196087 		    print_only, &print_type);
   1216  5088  ab196087 		break;
   1217  5088  ab196087 
   1218  5088  ab196087 	case DYN_CMD_T_FLAGS:
   1219  5088  ab196087 		print_only = (argstate.argc == 0);
   1220  5088  ab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
   1221  5088  ab196087 		    ELFEDIT_CONST_DT, DT_FLAGS, 1),
   1222  6225  ab196087 		    print_only, &print_type);
   1223  5088  ab196087 		break;
   1224  5088  ab196087 
   1225  5088  ab196087 	case DYN_CMD_T_FLAGS1:
   1226  5088  ab196087 		print_only = (argstate.argc == 0);
   1227  5088  ab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
   1228  5088  ab196087 		    ELFEDIT_CONST_DT, DT_FLAGS_1, 1),
   1229  6225  ab196087 		    print_only, &print_type);
   1230  5088  ab196087 		break;
   1231  5088  ab196087 
   1232  5088  ab196087 	case DYN_CMD_T_FEATURE1:
   1233  5088  ab196087 		print_only = (argstate.argc == 0);
   1234  5088  ab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
   1235  5088  ab196087 		    ELFEDIT_CONST_DT, DT_FEATURE_1, 1),
   1236  6225  ab196087 		    print_only, &print_type);
   1237  5088  ab196087 		break;
   1238  5088  ab196087 
   1239  5088  ab196087 	case DYN_CMD_T_CHECKSUM:
   1240  5088  ab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
   1241  5088  ab196087 		    ELFEDIT_CONST_DT, DT_CHECKSUM, 1),
   1242  6225  ab196087 		    print_only, &print_type);
   1243  5088  ab196087 		break;
   1244  5088  ab196087 
   1245  6206  ab196087 	case DYN_CMD_T_SUNW_LDMACH:
   1246  6206  ab196087 		if (argstate.argc > 1)
   1247  6206  ab196087 			elfedit_command_usage();
   1248  9273       Ali 		/* DT_SUNW_LDMACH is an ELFOSABI_SOLARIS feature */
   1249  9273       Ali 		(void) elfedit_test_osabi(argstate.obj_state,
   1250  9273       Ali 		    ELFOSABI_SOLARIS, 1);
   1251  6206  ab196087 		print_only = (argstate.argc == 0);
   1252  6206  ab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
   1253  6206  ab196087 		    ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1),
   1254  6225  ab196087 		    print_only, &print_type);
   1255  6206  ab196087 		break;
   1256  6206  ab196087 
   1257  5088  ab196087 	default:
   1258  5088  ab196087 		/* Note expected: All commands should have been caught above */
   1259  5088  ab196087 		elfedit_command_usage();
   1260  5088  ab196087 		break;
   1261  5088  ab196087 	}
   1262  5088  ab196087 
   1263  5088  ab196087 
   1264  5088  ab196087 	/* If this is a request to print current values, do it and return */
   1265  5088  ab196087 	if (print_only) {
   1266  5088  ab196087 		print_dyn(cmd, 0, &argstate, print_type, ndx);
   1267  5088  ab196087 		return (ELFEDIT_CMDRET_NONE);
   1268  5088  ab196087 	}
   1269  5088  ab196087 
   1270  5088  ab196087 
   1271  5088  ab196087 	switch (cmd) {
   1272  5088  ab196087 		/*
   1273  5088  ab196087 		 * DYN_CMD_T_DUMP can't get here: It is a print-only
   1274  5088  ab196087 		 * command.
   1275  5088  ab196087 		 */
   1276  5088  ab196087 
   1277  5088  ab196087 	case DYN_CMD_T_TAG:
   1278  5088  ab196087 		{
   1279  9273       Ali 			Ehdr		*ehdr = argstate.obj_state->os_ehdr;
   1280  9273       Ali 			uchar_t		osabi = ehdr->e_ident[EI_OSABI];
   1281  9273       Ali 			Half		mach = ehdr->e_machine;
   1282  5088  ab196087 			Conv_inv_buf_t	inv_buf1, inv_buf2;
   1283  9273       Ali 			Xword d_tag = (Xword) elfedit_atoconst(argstate.argv[1],
   1284  5088  ab196087 			    ELFEDIT_CONST_DT);
   1285  5088  ab196087 
   1286  5088  ab196087 			if (dyn[ndx].d_tag == d_tag) {
   1287  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1288  9273       Ali 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, dyn_name,
   1289  9273       Ali 				    EC_WORD(ndx), conv_dyn_tag(d_tag, osabi,
   1290  9273       Ali 				    mach, 0, &inv_buf1));
   1291  5088  ab196087 			} else {
   1292  9273       Ali 				Xword orig_d_tag = dyn[ndx].d_tag;
   1293  5088  ab196087 
   1294  5088  ab196087 				ret = ELFEDIT_CMDRET_MOD;
   1295  5088  ab196087 				dyn[ndx].d_tag = d_tag;
   1296  5088  ab196087 
   1297  5088  ab196087 				/*
   1298  5088  ab196087 				 * Update null termination index. Warn if we
   1299  5088  ab196087 				 * just clobbered the only DT_NULL termination
   1300  5088  ab196087 				 * for the array.
   1301  5088  ab196087 				 */
   1302  5088  ab196087 				null_ndx = argstate.dyn.null_ndx;
   1303  5088  ab196087 				set_null_ndx(&argstate);
   1304  5088  ab196087 				if ((argstate.dyn.null_ndx >=
   1305  5088  ab196087 				    argstate.dyn.num) &&
   1306  5088  ab196087 				    (null_ndx != argstate.dyn.null_ndx))
   1307  5088  ab196087 					elfedit_msg(ELFEDIT_MSG_DEBUG,
   1308  5088  ab196087 					    MSG_INTL(MSG_DEBUG_NULLTERM),
   1309  5088  ab196087 					    dyn_ndx, dyn_name,
   1310  9273       Ali 					    EC_WORD(ndx), conv_dyn_tag(d_tag,
   1311  9273       Ali 					    osabi, mach, 0, &inv_buf1));
   1312  5088  ab196087 
   1313  5088  ab196087 				/*
   1314  5088  ab196087 				 * Warning if
   1315  5088  ab196087 				 *	- Inserting a DT_NULL cuts off following
   1316  5088  ab196087 				 *		non-null elements.
   1317  5088  ab196087 				 *	- Inserting a non-DT_NULL after the
   1318  5088  ab196087 				 *		first null element, will be
   1319  5088  ab196087 				 *		ignored by rtld.
   1320  5088  ab196087 				 */
   1321  5088  ab196087 				if (d_tag == DT_NULL) {
   1322  5088  ab196087 					if ((ndx + 1) < null_ndx)
   1323  5088  ab196087 						elfedit_msg(ELFEDIT_MSG_DEBUG,
   1324  5088  ab196087 						    MSG_INTL(MSG_DEBUG_NULCLIP),
   1325  5088  ab196087 						    dyn_ndx, dyn_name,
   1326  5088  ab196087 						    EC_WORD(ndx),
   1327  9273       Ali 						    conv_dyn_tag(d_tag, osabi,
   1328  9273       Ali 						    mach, 0, &inv_buf1));
   1329  5088  ab196087 				} else {
   1330  5088  ab196087 					if ((ndx + 1) > argstate.dyn.null_ndx)
   1331  5088  ab196087 						elfedit_msg(ELFEDIT_MSG_DEBUG,
   1332  5088  ab196087 						    MSG_INTL(MSG_DEBUG_NULHIDE),
   1333  5088  ab196087 						    dyn_ndx, dyn_name,
   1334  5088  ab196087 						    EC_WORD(ndx),
   1335  9273       Ali 						    conv_dyn_tag(d_tag, osabi,
   1336  9273       Ali 						    mach, 0, &inv_buf1));
   1337  5088  ab196087 				}
   1338  5088  ab196087 
   1339  5088  ab196087 				/* Debug message that we changed it */
   1340  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1341  5088  ab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
   1342  5088  ab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
   1343  9273       Ali 				    conv_dyn_tag(orig_d_tag, osabi, mach, 0,
   1344  5088  ab196087 				    &inv_buf1),
   1345  9273       Ali 				    conv_dyn_tag(d_tag, osabi, mach, 0,
   1346  9273       Ali 				    &inv_buf2));
   1347  5088  ab196087 			}
   1348  5088  ab196087 		}
   1349  5088  ab196087 		break;
   1350  5088  ab196087 
   1351  5088  ab196087 	case DYN_CMD_T_VALUE:
   1352  5088  ab196087 		ret = cmd_body_value(&argstate, &ndx);
   1353  5088  ab196087 		break;
   1354  5088  ab196087 
   1355  5088  ab196087 	case DYN_CMD_T_DELETE:
   1356  5088  ab196087 		{
   1357  5088  ab196087 			Word cnt = (argstate.argc == 1) ? 1 :
   1358  5088  ab196087 			    (Word) elfedit_atoui_range(argstate.argv[1],
   1359  5088  ab196087 			    MSG_ORIG(MSG_STR_COUNT), 1, dyn_num - ndx, NULL);
   1360  5088  ab196087 			const char *msg_prefix =
   1361  5088  ab196087 			    elfedit_sec_msgprefix(argstate.dyn.sec);
   1362  5088  ab196087 
   1363  5088  ab196087 			elfedit_array_elts_delete(msg_prefix, argstate.dyn.data,
   1364  5088  ab196087 			    sizeof (Dyn), dyn_num, ndx, cnt);
   1365  5088  ab196087 			ret = ELFEDIT_CMDRET_MOD;
   1366  5088  ab196087 		}
   1367  5088  ab196087 		break;
   1368  5088  ab196087 
   1369  5088  ab196087 	case DYN_CMD_T_MOVE:
   1370  5088  ab196087 		{
   1371  5088  ab196087 			Dyn	save;
   1372  5088  ab196087 			Word	cnt;
   1373  5088  ab196087 			Word	dstndx;
   1374  5088  ab196087 			const char *msg_prefix =
   1375  5088  ab196087 			    elfedit_sec_msgprefix(argstate.dyn.sec);
   1376  5088  ab196087 
   1377  5088  ab196087 			dstndx = (Word)
   1378  5088  ab196087 			    elfedit_atoui_range(argstate.argv[1],
   1379  5088  ab196087 			    MSG_ORIG(MSG_STR_DST_INDEX), 0, dyn_num - 1,
   1380  5088  ab196087 			    NULL);
   1381  5088  ab196087 			if (argstate.argc == 2) {
   1382  5088  ab196087 				cnt = 1;
   1383  5088  ab196087 			} else {
   1384  5088  ab196087 				cnt = (Word) elfedit_atoui_range(
   1385  5088  ab196087 				    argstate.argv[2], MSG_ORIG(MSG_STR_COUNT),
   1386  5088  ab196087 				    1, dyn_num, NULL);
   1387  5088  ab196087 			}
   1388  5088  ab196087 			elfedit_array_elts_move(msg_prefix, argstate.dyn.data,
   1389  5088  ab196087 			    sizeof (save), dyn_num, ndx, dstndx, cnt, &save);
   1390  5088  ab196087 			ret = ELFEDIT_CMDRET_MOD;
   1391  5088  ab196087 		}
   1392  5088  ab196087 		break;
   1393  5088  ab196087 
   1394  5088  ab196087 
   1395  5088  ab196087 	case DYN_CMD_T_RUNPATH:
   1396  5088  ab196087 		ret = cmd_body_runpath(&argstate);
   1397  5088  ab196087 		break;
   1398  5088  ab196087 
   1399  5088  ab196087 	case DYN_CMD_T_POSFLAG1:
   1400  5088  ab196087 		{
   1401  5088  ab196087 			Conv_dyn_posflag1_buf_t buf1, buf2;
   1402  5088  ab196087 			Word flags;
   1403  5088  ab196087 
   1404  5088  ab196087 			flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
   1405  5088  ab196087 			    ELFEDIT_CONST_DF_P1);
   1406  5088  ab196087 
   1407  5088  ab196087 			/* Set the value */
   1408  5088  ab196087 			if (dyn[ndx].d_un.d_val == flags) {
   1409  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1410  5088  ab196087 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
   1411  5088  ab196087 				    dyn_name, EC_WORD(ndx),
   1412  5088  ab196087 				    conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0,
   1413  5088  ab196087 				    &buf1));
   1414  5088  ab196087 			} else {
   1415  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1416  5088  ab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
   1417  5088  ab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
   1418  5088  ab196087 				    conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0,
   1419  5088  ab196087 				    &buf1),
   1420  5088  ab196087 				    conv_dyn_posflag1(flags, 0, &buf2));
   1421  5088  ab196087 				ret = ELFEDIT_CMDRET_MOD;
   1422  5088  ab196087 				dyn[ndx].d_un.d_val = flags;
   1423  5088  ab196087 			}
   1424  5088  ab196087 		}
   1425  5088  ab196087 		break;
   1426  5088  ab196087 
   1427  5088  ab196087 	case DYN_CMD_T_FLAGS:
   1428  5088  ab196087 		{
   1429  5088  ab196087 			Conv_dyn_flag_buf_t buf1, buf2;
   1430  5088  ab196087 			Word flags;
   1431  5088  ab196087 
   1432  5088  ab196087 			flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
   1433  5088  ab196087 			    ELFEDIT_CONST_DF);
   1434  5088  ab196087 
   1435  5088  ab196087 			/* Set the value */
   1436  5088  ab196087 			if (dyn[ndx].d_un.d_val == flags) {
   1437  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1438  5088  ab196087 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
   1439  5088  ab196087 				    dyn_name, EC_WORD(ndx),
   1440  5088  ab196087 				    conv_dyn_flag(dyn[ndx].d_un.d_val, 0,
   1441  5088  ab196087 				    &buf1));
   1442  5088  ab196087 			} else {
   1443  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1444  5088  ab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
   1445  5088  ab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
   1446  5088  ab196087 				    conv_dyn_flag(dyn[ndx].d_un.d_val, 0,
   1447  5088  ab196087 				    &buf1),
   1448  5088  ab196087 				    conv_dyn_flag(flags, 0, &buf2));
   1449  5088  ab196087 				ret = ELFEDIT_CMDRET_MOD;
   1450  5088  ab196087 				dyn[ndx].d_un.d_val = flags;
   1451  5088  ab196087 			}
   1452  5088  ab196087 		}
   1453  5088  ab196087 		break;
   1454  5088  ab196087 
   1455  5088  ab196087 	case DYN_CMD_T_FLAGS1:
   1456  5088  ab196087 		{
   1457  5088  ab196087 			Conv_dyn_flag1_buf_t buf1, buf2;
   1458  5088  ab196087 			Word flags1;
   1459  5088  ab196087 
   1460  5088  ab196087 			flags1 = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
   1461  5088  ab196087 			    ELFEDIT_CONST_DF_1);
   1462  5088  ab196087 
   1463  5088  ab196087 			/* Set the value */
   1464  5088  ab196087 			if (dyn[ndx].d_un.d_val == flags1) {
   1465  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1466  5088  ab196087 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
   1467  5088  ab196087 				    dyn_name, EC_WORD(ndx),
   1468  5088  ab196087 				    conv_dyn_flag1(dyn[ndx].d_un.d_val,
   1469  5088  ab196087 				    0, &buf1));
   1470  5088  ab196087 			} else {
   1471  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1472  5088  ab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
   1473  5088  ab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
   1474  5088  ab196087 				    conv_dyn_flag1(dyn[ndx].d_un.d_val,
   1475  5088  ab196087 				    0, &buf1),
   1476  5088  ab196087 				    conv_dyn_flag1(flags1, 0, &buf2));
   1477  5088  ab196087 				ret = ELFEDIT_CMDRET_MOD;
   1478  5088  ab196087 				dyn[ndx].d_un.d_val = flags1;
   1479  5088  ab196087 			}
   1480  5088  ab196087 		}
   1481  5088  ab196087 		break;
   1482  5088  ab196087 
   1483  5088  ab196087 	case DYN_CMD_T_FEATURE1:
   1484  5088  ab196087 		{
   1485  5088  ab196087 			Conv_dyn_feature1_buf_t buf1, buf2;
   1486  5088  ab196087 			Word flags;
   1487  5088  ab196087 
   1488  5088  ab196087 			flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
   1489  5088  ab196087 			    ELFEDIT_CONST_DTF_1);
   1490  5088  ab196087 
   1491  5088  ab196087 			/* Set the value */
   1492  5088  ab196087 			if (dyn[ndx].d_un.d_val == flags) {
   1493  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1494  5088  ab196087 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
   1495  5088  ab196087 				    dyn_name, EC_WORD(ndx),
   1496  5088  ab196087 				    conv_dyn_feature1(dyn[ndx].d_un.d_val, 0,
   1497  5088  ab196087 				    &buf1));
   1498  5088  ab196087 			} else {
   1499  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1500  5088  ab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
   1501  5088  ab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
   1502  5088  ab196087 				    conv_dyn_feature1(dyn[ndx].d_un.d_val, 0,
   1503  5088  ab196087 				    &buf1),
   1504  5088  ab196087 				    conv_dyn_feature1(flags, 0, &buf2));
   1505  5088  ab196087 				ret = ELFEDIT_CMDRET_MOD;
   1506  5088  ab196087 				dyn[ndx].d_un.d_val = flags;
   1507  5088  ab196087 			}
   1508  5088  ab196087 		}
   1509  5088  ab196087 		break;
   1510  5088  ab196087 
   1511  5088  ab196087 	case DYN_CMD_T_CHECKSUM:
   1512  5088  ab196087 		{
   1513  5088  ab196087 			long checksum = elf_checksum(obj_state->os_elf);
   1514  5088  ab196087 
   1515  5088  ab196087 			/* Set the value */
   1516  5088  ab196087 			if (dyn[ndx].d_un.d_val == checksum) {
   1517  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1518  5088  ab196087 				    MSG_INTL(MSG_DEBUG_X_OK), dyn_ndx,
   1519  5088  ab196087 				    dyn_name, EC_WORD(ndx), EC_XWORD(checksum));
   1520  5088  ab196087 			} else {
   1521  5088  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1522  5088  ab196087 				    MSG_INTL(MSG_DEBUG_X_CHG),
   1523  5088  ab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
   1524  5088  ab196087 				    EC_XWORD(dyn[ndx].d_un.d_val),
   1525  5088  ab196087 				    EC_XWORD(checksum));
   1526  5088  ab196087 				ret = ELFEDIT_CMDRET_MOD;
   1527  5088  ab196087 				dyn[ndx].d_un.d_val = checksum;
   1528  5088  ab196087 			}
   1529  5088  ab196087 
   1530  5088  ab196087 		}
   1531  6206  ab196087 		break;
   1532  6206  ab196087 
   1533  6206  ab196087 	case DYN_CMD_T_SUNW_LDMACH:
   1534  6206  ab196087 		{
   1535  6206  ab196087 			Conv_inv_buf_t buf1, buf2;
   1536  6206  ab196087 			Half ldmach;
   1537  6206  ab196087 
   1538  6206  ab196087 			ldmach = (Half) elfedit_atoconst(argstate.argv[0],
   1539  6206  ab196087 			    ELFEDIT_CONST_EM);
   1540  6206  ab196087 
   1541  6206  ab196087 			/* Set the value */
   1542  6206  ab196087 			if (dyn[ndx].d_un.d_val == ldmach) {
   1543  6206  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1544  6206  ab196087 				    MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
   1545  6206  ab196087 				    dyn_name, EC_WORD(ndx),
   1546  6206  ab196087 				    conv_ehdr_mach(dyn[ndx].d_un.d_val, 0,
   1547  6206  ab196087 				    &buf1));
   1548  6206  ab196087 			} else {
   1549  6206  ab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
   1550  6206  ab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
   1551  6206  ab196087 				    dyn_ndx, dyn_name, EC_WORD(ndx),
   1552  6206  ab196087 				    conv_ehdr_mach(dyn[ndx].d_un.d_val, 0,
   1553  6206  ab196087 				    &buf1),
   1554  6206  ab196087 				    conv_ehdr_mach(ldmach, 0, &buf2));
   1555  6206  ab196087 				ret = ELFEDIT_CMDRET_MOD;
   1556  6206  ab196087 				dyn[ndx].d_un.d_val = ldmach;
   1557  6206  ab196087 			}
   1558  6206  ab196087 		}
   1559  6206  ab196087 		break;
   1560  6206  ab196087 
   1561  5088  ab196087 	}
   1562  5088  ab196087 
   1563  5088  ab196087 	/*
   1564  5088  ab196087 	 * If we modified the dynamic section header, tell libelf.
   1565  5088  ab196087 	 */
   1566  5088  ab196087 	if (ret == ELFEDIT_CMDRET_MOD)
   1567  5088  ab196087 		elfedit_modified_data(argstate.dyn.sec);
   1568  5088  ab196087 
   1569  5088  ab196087 	/* Do autoprint */
   1570  5088  ab196087 	if (do_autoprint)
   1571  5088  ab196087 		print_dyn(cmd, 1, &argstate, print_type, ndx);
   1572  5088  ab196087 
   1573  5088  ab196087 	return (ret);
   1574  5088  ab196087 }
   1575  5088  ab196087 
   1576  5088  ab196087 
   1577  5088  ab196087 
   1578  5088  ab196087 /*
   1579  5088  ab196087  * Command completion functions for the commands
   1580  5088  ab196087  */
   1581  5088  ab196087 
   1582  5088  ab196087 /*
   1583  5088  ab196087  * Command completion for the first argument, which specifies
   1584  5088  ab196087  * the dynamic element to use. Examines the options to see if
   1585  5088  ab196087  * -dynndx is present, and if not, supplies the completion
   1586  5088  ab196087  * strings for argument 1.
   1587  5088  ab196087  */
   1588  5088  ab196087 /*ARGSUSED*/
   1589  5088  ab196087 static void
   1590  5088  ab196087 cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
   1591  5088  ab196087     const char *argv[], int num_opt)
   1592  5088  ab196087 {
   1593  5088  ab196087 	elfedit_section_t	*cache;
   1594  5088  ab196087 	Dyn			*dyn;
   1595  5088  ab196087 	Word			i;
   1596  5088  ab196087 	const char		*s;
   1597  5088  ab196087 	char			*s2;
   1598  5088  ab196087 	char			buf[128];
   1599  5088  ab196087 
   1600  5088  ab196087 	/* Make sure it's the first argument */
   1601  5088  ab196087 	if ((argc - num_opt) != 1)
   1602  5088  ab196087 		return;
   1603  5088  ab196087 
   1604  5088  ab196087 	/* Is -dynndx present? If so, we don't complete tag types */
   1605  5088  ab196087 	for (i = 0; i < num_opt; i++)
   1606  5088  ab196087 		if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0)
   1607  5088  ab196087 			return;
   1608  5088  ab196087 
   1609  5088  ab196087 	/*
   1610  5088  ab196087 	 * If there is no object, or if there is no dynamic section,
   1611  5088  ab196087 	 * then supply all possible names.
   1612  5088  ab196087 	 */
   1613  5088  ab196087 	if ((obj_state == NULL) || (obj_state->os_dynndx == SHN_UNDEF)) {
   1614  5088  ab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT);
   1615  5088  ab196087 		return;
   1616  5088  ab196087 	}
   1617  5088  ab196087 
   1618  5088  ab196087 	/* Supply completions for the tags present in the dynamic section */
   1619  5088  ab196087 	cache = &obj_state->os_secarr[obj_state->os_dynndx];
   1620  5088  ab196087 	dyn = (Dyn *) cache->sec_data->d_buf;
   1621  5088  ab196087 	i = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize;
   1622  5088  ab196087 	for (; i-- > 0; dyn++) {
   1623  5088  ab196087 		s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_DT,
   1624  5088  ab196087 		    dyn->d_tag, 0);
   1625  5088  ab196087 		if (s == NULL)
   1626  5088  ab196087 			continue;
   1627  5088  ab196087 		elfedit_cpl_match(cpldata, s, 1);
   1628  5088  ab196087 
   1629  5088  ab196087 		/*
   1630  5088  ab196087 		 * To get the informal tag names that are lowercase
   1631  5088  ab196087 		 * and lack the leading DT_, we copy the string we
   1632  5088  ab196087 		 * have into a buffer and process it.
   1633  5088  ab196087 		 */
   1634  5088  ab196087 		if (strlen(s) < 3)
   1635  5088  ab196087 			continue;
   1636  5088  ab196087 		(void) strlcpy(buf, s + 3, sizeof (buf));
   1637  5088  ab196087 		for (s2 = buf; *s2 != '\0'; s2++)
   1638  5088  ab196087 			if (isupper(*s2))
   1639  5088  ab196087 				*s2 = tolower(*s2);
   1640  5088  ab196087 		elfedit_cpl_match(cpldata, buf, 1);
   1641  5088  ab196087 	}
   1642  5088  ab196087 }
   1643  5088  ab196087 
   1644  5088  ab196087 
   1645  5088  ab196087 /*ARGSUSED*/
   1646  5088  ab196087 static void
   1647  5088  ab196087 cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
   1648  5088  ab196087     const char *argv[], int num_opt)
   1649  5088  ab196087 {
   1650  5088  ab196087 	/* First argument */
   1651  5088  ab196087 	if ((argc - num_opt) == 1) {
   1652  5088  ab196087 		cpl_eltarg(obj_state, cpldata, argc, argv, num_opt);
   1653  5088  ab196087 		return;
   1654  5088  ab196087 	}
   1655  5088  ab196087 
   1656  5088  ab196087 	/* The second argument is always a tag value */
   1657  5088  ab196087 	if ((argc - num_opt) == 2)
   1658  5088  ab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT);
   1659  5088  ab196087 }
   1660  5088  ab196087 
   1661  5088  ab196087 /*ARGSUSED*/
   1662  5088  ab196087 static void
   1663  5088  ab196087 cpl_posflag1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
   1664  5088  ab196087     const char *argv[], int num_opt)
   1665  5088  ab196087 {
   1666  6225  ab196087 	/*
   1667  6225  ab196087 	 * dyn:posflag1 accepts two mutually exclusive options that have
   1668  6225  ab196087 	 * a corresponding value argument: -dynndx and -needed. If we
   1669  6225  ab196087 	 * are being called to supply options for the value, handle that here.
   1670  6225  ab196087 	 */
   1671  6225  ab196087 	if ((num_opt > 1) && (argc == num_opt)) {
   1672  6225  ab196087 		elfedit_section_t	*dynsec, *strsec;
   1673  6225  ab196087 		const char		*opt = argv[num_opt - 2];
   1674  6225  ab196087 		dyn_opt_t		type;
   1675  6225  ab196087 		Dyn			*dyn;
   1676  6225  ab196087 		Word			i, num;
   1677  6225  ab196087 
   1678  6225  ab196087 		/*
   1679  6225  ab196087 		 * If there is no object available, or if the object has no
   1680  6225  ab196087 		 * dynamic section, then there is nothing to report.
   1681  6225  ab196087 		 */
   1682  6225  ab196087 		if ((obj_state == NULL) || obj_state->os_dynndx == SHN_UNDEF)
   1683  6225  ab196087 			return;
   1684  6225  ab196087 
   1685  6225  ab196087 		/*
   1686  6225  ab196087 		 * Determine which option it is, bail if it isn't one of
   1687  6225  ab196087 		 * the ones we are concerned with.
   1688  6225  ab196087 		 */
   1689  6225  ab196087 		if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_NEEDED)) == 0))
   1690  6225  ab196087 			type = DYN_OPT_F_NEEDED;
   1691  6225  ab196087 		else if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0))
   1692  6225  ab196087 			type = DYN_OPT_F_DYNNDX_VAL;
   1693  6225  ab196087 		else
   1694  6225  ab196087 			return;
   1695  6225  ab196087 
   1696  6225  ab196087 		dynsec = elfedit_sec_getdyn(obj_state, &dyn, &num);
   1697  6225  ab196087 		switch (type) {
   1698  6225  ab196087 		case DYN_OPT_F_NEEDED:
   1699  6225  ab196087 			strsec = elfedit_sec_getstr(obj_state,
   1700  6225  ab196087 			    dynsec->sec_shdr->sh_link, 0);
   1701  6225  ab196087 			for (; num-- > 0; dyn++)
   1702  6225  ab196087 				if (dyn->d_tag == DT_NEEDED)
   1703  6225  ab196087 					elfedit_cpl_match(cpldata,
   1704  6225  ab196087 					    elfedit_offset_to_str(strsec,
   1705  6225  ab196087 					    dyn->d_un.d_val, ELFEDIT_MSG_DEBUG,
   1706  6225  ab196087 					    0), 0);
   1707  6225  ab196087 			break;
   1708  6225  ab196087 
   1709  6225  ab196087 		case DYN_OPT_F_DYNNDX_VAL:
   1710  6225  ab196087 			for (i = 0; i < num; i++, dyn++)
   1711  6225  ab196087 				if (dyn->d_tag == DT_POSFLAG_1)
   1712  6225  ab196087 					elfedit_cpl_ndx(cpldata, i);
   1713  6225  ab196087 			break;
   1714  6225  ab196087 		}
   1715  6225  ab196087 		return;
   1716  6225  ab196087 	}
   1717  6225  ab196087 
   1718  5088  ab196087 	/* This routine allows multiple flags to be specified */
   1719  5088  ab196087 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_P1);
   1720  5088  ab196087 }
   1721  5088  ab196087 
   1722  5088  ab196087 /*ARGSUSED*/
   1723  5088  ab196087 static void
   1724  5088  ab196087 cpl_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
   1725  5088  ab196087     const char *argv[], int num_opt)
   1726  5088  ab196087 {
   1727  5088  ab196087 	/* This routine allows multiple flags to be specified */
   1728  5088  ab196087 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF);
   1729  5088  ab196087 }
   1730  5088  ab196087 
   1731  5088  ab196087 /*ARGSUSED*/
   1732  5088  ab196087 static void
   1733  5088  ab196087 cpl_flags1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
   1734  5088  ab196087     const char *argv[], int num_opt)
   1735  5088  ab196087 {
   1736  5088  ab196087 	/* This routine allows multiple flags to be specified */
   1737  5088  ab196087 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_1);
   1738  5088  ab196087 }
   1739  5088  ab196087 
   1740  5088  ab196087 /*ARGSUSED*/
   1741  5088  ab196087 static void
   1742  5088  ab196087 cpl_feature1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
   1743  5088  ab196087     const char *argv[], int num_opt)
   1744  5088  ab196087 {
   1745  5088  ab196087 	/* This routine allows multiple flags to be specified */
   1746  5088  ab196087 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1);
   1747  6206  ab196087 }
   1748  6206  ab196087 
   1749  6206  ab196087 /*ARGSUSED*/
   1750  6206  ab196087 static void
   1751  6206  ab196087 cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
   1752  6206  ab196087     const char *argv[], int num_opt)
   1753  6206  ab196087 {
   1754  6206  ab196087 	/*
   1755  6206  ab196087 	 * This command doesn't accept options, so num_opt should be
   1756  6206  ab196087 	 * 0. This is a defensive measure, in case that should change.
   1757  6206  ab196087 	 */
   1758  6206  ab196087 	argc -= num_opt;
   1759  6206  ab196087 	argv += num_opt;
   1760  6206  ab196087 
   1761  6206  ab196087 	if (argc == 1)
   1762  6206  ab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM);
   1763  5088  ab196087 }
   1764  5088  ab196087 
   1765  5088  ab196087 
   1766  5088  ab196087 /*
   1767  5088  ab196087  * Implementation functions for the commands
   1768  5088  ab196087  */
   1769  5088  ab196087 static elfedit_cmdret_t
   1770  5088  ab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1771  5088  ab196087 {
   1772  5088  ab196087 	return (cmd_body(DYN_CMD_T_DUMP, obj_state, argc, argv));
   1773  5088  ab196087 }
   1774  5088  ab196087 
   1775  5088  ab196087 static elfedit_cmdret_t
   1776  5088  ab196087 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1777  5088  ab196087 {
   1778  5088  ab196087 	return (cmd_body(DYN_CMD_T_TAG, obj_state, argc, argv));
   1779  5088  ab196087 }
   1780  5088  ab196087 
   1781  5088  ab196087 static elfedit_cmdret_t
   1782  5088  ab196087 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1783  5088  ab196087 {
   1784  5088  ab196087 	return (cmd_body(DYN_CMD_T_VALUE, obj_state, argc, argv));
   1785  5088  ab196087 }
   1786  5088  ab196087 
   1787  5088  ab196087 static elfedit_cmdret_t
   1788  5088  ab196087 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1789  5088  ab196087 {
   1790  5088  ab196087 	return (cmd_body(DYN_CMD_T_DELETE, obj_state, argc, argv));
   1791  5088  ab196087 }
   1792  5088  ab196087 
   1793  5088  ab196087 static elfedit_cmdret_t
   1794  5088  ab196087 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1795  5088  ab196087 {
   1796  5088  ab196087 	return (cmd_body(DYN_CMD_T_MOVE, obj_state, argc, argv));
   1797  5088  ab196087 }
   1798  5088  ab196087 
   1799  5088  ab196087 static elfedit_cmdret_t
   1800  5088  ab196087 cmd_runpath(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1801  5088  ab196087 {
   1802  5088  ab196087 	return (cmd_body(DYN_CMD_T_RUNPATH, obj_state, argc, argv));
   1803  5088  ab196087 }
   1804  5088  ab196087 
   1805  5088  ab196087 static elfedit_cmdret_t
   1806  5088  ab196087 cmd_posflag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1807  5088  ab196087 {
   1808  5088  ab196087 	return (cmd_body(DYN_CMD_T_POSFLAG1, obj_state, argc, argv));
   1809  5088  ab196087 }
   1810  5088  ab196087 
   1811  5088  ab196087 static elfedit_cmdret_t
   1812  5088  ab196087 cmd_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1813  5088  ab196087 {
   1814  5088  ab196087 	return (cmd_body(DYN_CMD_T_FLAGS, obj_state, argc, argv));
   1815  5088  ab196087 }
   1816  5088  ab196087 
   1817  5088  ab196087 static elfedit_cmdret_t
   1818  5088  ab196087 cmd_flags1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1819  5088  ab196087 {
   1820  5088  ab196087 	return (cmd_body(DYN_CMD_T_FLAGS1, obj_state, argc, argv));
   1821  5088  ab196087 }
   1822  5088  ab196087 
   1823  5088  ab196087 static elfedit_cmdret_t
   1824  5088  ab196087 cmd_feature1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1825  5088  ab196087 {
   1826  5088  ab196087 	return (cmd_body(DYN_CMD_T_FEATURE1, obj_state, argc, argv));
   1827  5088  ab196087 }
   1828  5088  ab196087 
   1829  5088  ab196087 static elfedit_cmdret_t
   1830  5088  ab196087 cmd_checksum(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1831  5088  ab196087 {
   1832  5088  ab196087 	return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv));
   1833  6206  ab196087 }
   1834  6206  ab196087 
   1835  6206  ab196087 static elfedit_cmdret_t
   1836  6206  ab196087 cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
   1837  6206  ab196087 {
   1838  6206  ab196087 	return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv));
   1839  5088  ab196087 }
   1840  5088  ab196087 
   1841  5088  ab196087 
   1842  5088  ab196087 
   1843  5088  ab196087 /*ARGSUSED*/
   1844  5088  ab196087 elfedit_module_t *
   1845  5088  ab196087 elfedit_init(elfedit_module_version_t version)
   1846  5088  ab196087 {
   1847  5088  ab196087 	/* For commands that only accept -o */
   1848  5088  ab196087 	static elfedit_cmd_optarg_t opt_ostyle[] = {
   1849  5088  ab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
   1850  5088  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
   1851  5088  ab196087 		{ NULL }
   1852  5088  ab196087 	};
   1853  5088  ab196087 
   1854  5088  ab196087 	/* For commands that only accept -and, -cmp, -o, -or */
   1855  5088  ab196087 	static elfedit_cmd_optarg_t opt_ostyle_bitop[] = {
   1856  5088  ab196087 		{ ELFEDIT_STDOA_OPT_AND, NULL,
   1857  5088  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR },
   1858  5088  ab196087 		{ ELFEDIT_STDOA_OPT_CMP, NULL,
   1859  5088  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 },
   1860  5088  ab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
   1861  5088  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
   1862  5088  ab196087 		{ ELFEDIT_STDOA_OPT_OR, NULL,
   1863  5088  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND },
   1864  5088  ab196087 		{ NULL }
   1865  5088  ab196087 	};
   1866  5088  ab196087 
   1867  5088  ab196087 	/* For commands that only accept -dynndx */
   1868  5088  ab196087 	static elfedit_cmd_optarg_t opt_minus_dynndx[] = {
   1869  5088  ab196087 		{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
   1870  6225  ab196087 		    /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */
   1871  6225  ab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0,
   1872  6225  ab196087 		    DYN_OPT_F_DYNNDX_ELT, 0 },
   1873  5088  ab196087 		{ NULL }
   1874  5088  ab196087 	};
   1875  5088  ab196087 
   1876  5088  ab196087 	/* dyn:dump */
   1877  5088  ab196087 	static const char *name_dump[] = {
   1878  5088  ab196087 	    MSG_ORIG(MSG_CMD_DUMP),
   1879  5088  ab196087 	    MSG_ORIG(MSG_STR_EMPTY),	/* "" makes this the default command */
   1880  5088  ab196087 	    NULL
   1881  5088  ab196087 	};
   1882  5088  ab196087 	static elfedit_cmd_optarg_t arg_dump[] = {
   1883  5088  ab196087 		{ MSG_ORIG(MSG_STR_ELT),
   1884  5088  ab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
   1885  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
   1886  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT },
   1887  5088  ab196087 		{ NULL }
   1888  5088  ab196087 	};
   1889  5088  ab196087 
   1890  5088  ab196087 
   1891  5088  ab196087 	/* dyn:tag */
   1892  5088  ab196087 	static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL };
   1893  5088  ab196087 	static elfedit_cmd_optarg_t opt_tag[] = {
   1894  5088  ab196087 		{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
   1895  6225  ab196087 		    /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */
   1896  6225  ab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0,
   1897  6225  ab196087 		    DYN_OPT_F_DYNNDX_ELT, 0 },
   1898  5088  ab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
   1899  5088  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
   1900  5088  ab196087 		{ NULL }
   1901  5088  ab196087 	};
   1902  5088  ab196087 	static elfedit_cmd_optarg_t arg_tag[] = {
   1903  5088  ab196087 		{ MSG_ORIG(MSG_STR_ELT),
   1904  5088  ab196087 		    /* MSG_INTL(MSG_A1_TAG_ELT) */
   1905  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A1_TAG_ELT),
   1906  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT },
   1907  5088  ab196087 		{ MSG_ORIG(MSG_STR_VALUE),
   1908  5088  ab196087 		    /* MSG_INTL(MSG_A2_TAG_VALUE) */
   1909  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE),
   1910  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT },
   1911  5088  ab196087 		{ NULL }
   1912  5088  ab196087 	};
   1913  5088  ab196087 
   1914  5088  ab196087 
   1915  5088  ab196087 	/* dyn:value */
   1916  5088  ab196087 	static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL };
   1917  5088  ab196087 	static elfedit_cmd_optarg_t opt_value[] = {
   1918  5088  ab196087 		{ MSG_ORIG(MSG_STR_MINUS_ADD),
   1919  5088  ab196087 		    /* MSG_INTL(MSG_OPTDESC_ADD) */
   1920  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_ADD), 0,
   1921  6225  ab196087 		    DYN_OPT_F_ADD, DYN_OPT_F_DYNNDX_ELT },
   1922  5088  ab196087 		{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
   1923  6225  ab196087 		    /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */
   1924  6225  ab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0,
   1925  6225  ab196087 		    DYN_OPT_F_DYNNDX_ELT, DYN_OPT_F_ADD },
   1926  5088  ab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
   1927  5088  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
   1928  5088  ab196087 		{ MSG_ORIG(MSG_STR_MINUS_S),
   1929  5088  ab196087 		    /* MSG_INTL(MSG_OPTDESC_S) */
   1930  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0,
   1931  5088  ab196087 		    DYN_OPT_F_STRVAL, 0 },
   1932  5088  ab196087 		{ NULL }
   1933  5088  ab196087 	};
   1934  5088  ab196087 	static elfedit_cmd_optarg_t arg_value[] = {
   1935  5088  ab196087 		{ MSG_ORIG(MSG_STR_ELT),
   1936  5088  ab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
   1937  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
   1938  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT },
   1939  5088  ab196087 		{ MSG_ORIG(MSG_STR_VALUE),
   1940  5088  ab196087 		    /* MSG_INTL(MSG_A2_VALUE_VALUE) */
   1941  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE),
   1942  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT },
   1943  5088  ab196087 		{ NULL }
   1944  5088  ab196087 	};
   1945  5088  ab196087 
   1946  5088  ab196087 	/* dyn:delete */
   1947  5088  ab196087 	static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL };
   1948  5088  ab196087 	static elfedit_cmd_optarg_t arg_delete[] = {
   1949  5088  ab196087 		{ MSG_ORIG(MSG_STR_ELT),
   1950  5088  ab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
   1951  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
   1952  5088  ab196087 		    0 },
   1953  5088  ab196087 		{ MSG_ORIG(MSG_STR_COUNT),
   1954  5088  ab196087 		    /* MSG_INTL(MSG_A2_DELETE_COUNT) */
   1955  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT),
   1956  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT },
   1957  5088  ab196087 		{ NULL }
   1958  5088  ab196087 	};
   1959  5088  ab196087 
   1960  5088  ab196087 	/* dyn:move */
   1961  5088  ab196087 	static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL };
   1962  5088  ab196087 	static elfedit_cmd_optarg_t arg_move[] = {
   1963  5088  ab196087 		{ MSG_ORIG(MSG_STR_ELT),
   1964  5088  ab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
   1965  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
   1966  5088  ab196087 		    0 },
   1967  5088  ab196087 		{ MSG_ORIG(MSG_STR_DST_INDEX),
   1968  5088  ab196087 		    /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */
   1969  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX),
   1970  5088  ab196087 		    0 },
   1971  5088  ab196087 		{ MSG_ORIG(MSG_STR_COUNT),
   1972  5088  ab196087 		    /* MSG_INTL(MSG_A3_MOVE_COUNT) */
   1973  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT),
   1974  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT },
   1975  5088  ab196087 		{ NULL }
   1976  5088  ab196087 	};
   1977  5088  ab196087 
   1978  5088  ab196087 	/* dyn:runpath / dyn:rpath */
   1979  5088  ab196087 	static const char *name_runpath[] = { MSG_ORIG(MSG_CMD_RUNPATH),
   1980  5088  ab196087 	    MSG_ORIG(MSG_CMD_RUNPATH_A1), NULL };
   1981  5088  ab196087 	static elfedit_cmd_optarg_t arg_runpath[] = {
   1982  5088  ab196087 		{ MSG_ORIG(MSG_STR_NEWPATH),
   1983  5088  ab196087 		    /* MSG_INTL(MSG_A1_RUNPATH_NEWPATH) */
   1984  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A1_RUNPATH_NEWPATH),
   1985  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT },
   1986  5088  ab196087 		{ NULL }
   1987  5088  ab196087 	};
   1988  5088  ab196087 
   1989  5088  ab196087 	/* dyn:posflag1 */
   1990  5088  ab196087 	static const char *name_posflag1[] = { MSG_ORIG(MSG_CMD_POSFLAG1),
   1991  5088  ab196087 	    NULL };
   1992  6225  ab196087 	static elfedit_cmd_optarg_t opt_posflag1[] = {
   1993  6225  ab196087 		{ ELFEDIT_STDOA_OPT_AND, NULL,
   1994  6225  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR },
   1995  6225  ab196087 		{ ELFEDIT_STDOA_OPT_CMP, NULL,
   1996  6225  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 },
   1997  6225  ab196087 		{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
   1998  6225  ab196087 		    /* MSG_INTL(MSG_OPTDESC_DYNNDX_VAL) */
   1999  6225  ab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_VAL),
   2000  6225  ab196087 		    ELFEDIT_CMDOA_F_VALUE,
   2001  6225  ab196087 		    DYN_OPT_F_DYNNDX_VAL, DYN_OPT_F_NEEDED },
   2002  6225  ab196087 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 },
   2003  6225  ab196087 		{ MSG_ORIG(MSG_STR_MINUS_NEEDED),
   2004  6225  ab196087 		    /* MSG_INTL(MSG_OPTDESC_NEEDED) */
   2005  6225  ab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_NEEDED),
   2006  6225  ab196087 		    ELFEDIT_CMDOA_F_VALUE,
   2007  6225  ab196087 		    DYN_OPT_F_NEEDED, DYN_OPT_F_DYNNDX_VAL },
   2008  6225  ab196087 		{ MSG_ORIG(MSG_STR_PREFIX), NULL, 0, 0 },
   2009  6225  ab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
   2010  6225  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
   2011  6225  ab196087 		{ ELFEDIT_STDOA_OPT_OR, NULL,
   2012  6225  ab196087 		    ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND },
   2013  6225  ab196087 		{ NULL }
   2014  6225  ab196087 	};
   2015  5088  ab196087 	static elfedit_cmd_optarg_t arg_posflag1[] = {
   2016  5088  ab196087 		{ MSG_ORIG(MSG_STR_VALUE),
   2017  5088  ab196087 		    /* MSG_INTL(MSG_A1_POSFLAG1_VALUE) */
   2018  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A1_POSFLAG1_VALUE),
   2019  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
   2020  5088  ab196087 		{ NULL }
   2021  5088  ab196087 	};
   2022  5088  ab196087 
   2023  5088  ab196087 	/* dyn:flags */
   2024  5088  ab196087 	static const char *name_flags[] = { MSG_ORIG(MSG_CMD_FLAGS), NULL };
   2025  5088  ab196087 	static elfedit_cmd_optarg_t arg_flags[] = {
   2026  5088  ab196087 		{ MSG_ORIG(MSG_STR_VALUE),
   2027  5088  ab196087 		    /* MSG_INTL(MSG_A1_FLAGS_VALUE) */
   2028  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A1_FLAGS_VALUE),
   2029  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
   2030  5088  ab196087 		{ NULL }
   2031  5088  ab196087 	};
   2032  5088  ab196087 
   2033  5088  ab196087 	/* dyn:flags1 */
   2034  5088  ab196087 	static const char *name_flags1[] = { MSG_ORIG(MSG_CMD_FLAGS1), NULL };
   2035  5088  ab196087 	static elfedit_cmd_optarg_t arg_flags1[] = {
   2036  5088  ab196087 		{ MSG_ORIG(MSG_STR_VALUE),
   2037  5088  ab196087 		    /* MSG_INTL(MSG_A1_FLAGS1_VALUE) */
   2038  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A1_FLAGS1_VALUE),
   2039  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
   2040  5088  ab196087 		{ NULL }
   2041  5088  ab196087 	};
   2042  5088  ab196087 
   2043  5088  ab196087 	/* dyn:feature1 */
   2044  5088  ab196087 	static const char *name_feature1[] = { MSG_ORIG(MSG_CMD_FEATURE1),
   2045  5088  ab196087 	    NULL };
   2046  5088  ab196087 	static elfedit_cmd_optarg_t arg_feature1[] = {
   2047  5088  ab196087 		{ MSG_ORIG(MSG_STR_VALUE),
   2048  5088  ab196087 		    /* MSG_INTL(MSG_A1_FEATURE1_VALUE) */
   2049  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_A1_FEATURE1_VALUE),
   2050  5088  ab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
   2051  5088  ab196087 		{ NULL }
   2052  5088  ab196087 	};
   2053  5088  ab196087 
   2054  5088  ab196087 	/* dyn:checksum */
   2055  5088  ab196087 	static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM),
   2056  5088  ab196087 	    NULL };
   2057  5088  ab196087 
   2058  6206  ab196087 	/* dyn:sunw_ldmach */
   2059  6206  ab196087 	static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH),
   2060  6206  ab196087 	    NULL };
   2061  6206  ab196087 	static elfedit_cmd_optarg_t arg_sunw_ldmach[] = {
   2062  6206  ab196087 		{ MSG_ORIG(MSG_STR_VALUE),
   2063  6206  ab196087 		    /* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */
   2064  6206  ab196087 		    ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE),
   2065  6206  ab196087 		    ELFEDIT_CMDOA_F_OPT },
   2066  6206  ab196087 		{ NULL }
   2067  6206  ab196087 	};
   2068  6206  ab196087 
   2069  5088  ab196087 
   2070  5088  ab196087 
   2071  5088  ab196087 	static elfedit_cmd_t cmds[] = {
   2072  5088  ab196087 		/* dyn:dump */
   2073  5088  ab196087 		{ cmd_dump, cpl_eltarg, name_dump,
   2074  5088  ab196087 		    /* MSG_INTL(MSG_DESC_DUMP) */
   2075  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_DUMP),
   2076  5088  ab196087 		    /* MSG_INTL(MSG_HELP_DUMP) */
   2077  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_DUMP),
   2078  5088  ab196087 		    opt_minus_dynndx, arg_dump },
   2079  5088  ab196087 
   2080  5088  ab196087 		/* dyn:tag */
   2081  5088  ab196087 		{ cmd_tag, cpl_tag, name_tag,
   2082  5088  ab196087 		    /* MSG_INTL(MSG_DESC_TAG) */
   2083  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_TAG),
   2084  5088  ab196087 		    /* MSG_INTL(MSG_HELP_TAG) */
   2085  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_TAG),
   2086  5088  ab196087 		    opt_tag, arg_tag },
   2087  5088  ab196087 
   2088  5088  ab196087 		/* dyn:value */
   2089  5088  ab196087 		{ cmd_value, cpl_eltarg, name_value,
   2090  5088  ab196087 		    /* MSG_INTL(MSG_DESC_VALUE) */
   2091  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_VALUE),
   2092  5088  ab196087 		    /* MSG_INTL(MSG_HELP_VALUE) */
   2093  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_VALUE),
   2094  5088  ab196087 		    opt_value, arg_value },
   2095  5088  ab196087 
   2096  5088  ab196087 		/* dyn:delete */
   2097  5088  ab196087 		{ cmd_delete, cpl_eltarg, name_delete,
   2098  5088  ab196087 		    /* MSG_INTL(MSG_DESC_DELETE) */
   2099  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_DELETE),
   2100  5088  ab196087 		    /* MSG_INTL(MSG_HELP_DELETE) */
   2101  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_DELETE),
   2102  5088  ab196087 		    opt_minus_dynndx, arg_delete },
   2103  5088  ab196087 
   2104  5088  ab196087 		/* dyn:move */
   2105  5088  ab196087 		{ cmd_move, cpl_eltarg, name_move,
   2106  5088  ab196087 		    /* MSG_INTL(MSG_DESC_MOVE) */
   2107  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_MOVE),
   2108  5088  ab196087 		    /* MSG_INTL(MSG_HELP_MOVE) */
   2109  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_MOVE),
   2110  5088  ab196087 		    opt_minus_dynndx, arg_move },
   2111  5088  ab196087 
   2112  5088  ab196087 		/* dyn:runpath */
   2113  5088  ab196087 		{ cmd_runpath, NULL, name_runpath,
   2114  5088  ab196087 		    /* MSG_INTL(MSG_DESC_RUNPATH) */
   2115  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_RUNPATH),
   2116  5088  ab196087 		    /* MSG_INTL(MSG_HELP_RUNPATH) */
   2117  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_RUNPATH),
   2118  5088  ab196087 		    opt_ostyle, arg_runpath },
   2119  5088  ab196087 
   2120  5088  ab196087 		/* dyn:posflag1 */
   2121  5088  ab196087 		{ cmd_posflag1, cpl_posflag1, name_posflag1,
   2122  5088  ab196087 		    /* MSG_INTL(MSG_DESC_POSFLAG1) */
   2123  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_POSFLAG1),
   2124  5088  ab196087 		    /* MSG_INTL(MSG_HELP_POSFLAG1) */
   2125  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_POSFLAG1),
   2126  6225  ab196087 		    opt_posflag1, arg_posflag1 },
   2127  5088  ab196087 
   2128  5088  ab196087 		/* dyn:flags */
   2129  5088  ab196087 		{ cmd_flags, cpl_flags, name_flags,
   2130  5088  ab196087 		    /* MSG_INTL(MSG_DESC_FLAGS) */
   2131  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_FLAGS),
   2132  5088  ab196087 		    /* MSG_INTL(MSG_HELP_FLAGS) */
   2133  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_FLAGS),
   2134  5088  ab196087 		    opt_ostyle_bitop, arg_flags },
   2135  5088  ab196087 
   2136  5088  ab196087 		/* dyn:flags1 */
   2137  5088  ab196087 		{ cmd_flags1, cpl_flags1, name_flags1,
   2138  5088  ab196087 		    /* MSG_INTL(MSG_DESC_FLAGS1) */
   2139  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_FLAGS1),
   2140  5088  ab196087 		    /* MSG_INTL(MSG_HELP_FLAGS1) */
   2141  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_FLAGS1),
   2142  5088  ab196087 		    opt_ostyle_bitop, arg_flags1 },
   2143  5088  ab196087 
   2144  5088  ab196087 		/* dyn:feature1 */
   2145  5088  ab196087 		{ cmd_feature1, cpl_feature1, name_feature1,
   2146  5088  ab196087 		    /* MSG_INTL(MSG_DESC_FEATURE1) */
   2147  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_FEATURE1),
   2148  5088  ab196087 		    /* MSG_INTL(MSG_HELP_FEATURE1) */
   2149  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_FEATURE1),
   2150  5088  ab196087 		    opt_ostyle_bitop, arg_feature1 },
   2151  5088  ab196087 
   2152  5088  ab196087 		/* dyn:checksum */
   2153  5088  ab196087 		{ cmd_checksum, NULL, name_checksum,
   2154  5088  ab196087 		    /* MSG_INTL(MSG_DESC_CHECKSUM) */
   2155  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_CHECKSUM),
   2156  5088  ab196087 		    /* MSG_INTL(MSG_HELP_CHECKSUM) */
   2157  5088  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM),
   2158  5088  ab196087 		    NULL, NULL },
   2159  5088  ab196087 
   2160  6206  ab196087 		/* dyn:sunw_ldmach */
   2161  6206  ab196087 		{ cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach,
   2162  6206  ab196087 		    /* MSG_INTL(MSG_DESC_SUNW_LDMACH) */
   2163  6206  ab196087 		    ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH),
   2164  6206  ab196087 		    /* MSG_INTL(MSG_HELP_SUNW_LDMACH) */
   2165  6206  ab196087 		    ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH),
   2166  6206  ab196087 		    opt_ostyle, arg_sunw_ldmach },
   2167  6206  ab196087 
   2168  5088  ab196087 		{ NULL }
   2169  5088  ab196087 	};
   2170  5088  ab196087 
   2171  5088  ab196087 	static elfedit_module_t module = {
   2172  5088  ab196087 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
   2173  5088  ab196087 	    /* MSG_INTL(MSG_MOD_DESC) */
   2174  5088  ab196087 	    ELFEDIT_I18NHDL(MSG_MOD_DESC), cmds, mod_i18nhdl_to_str };
   2175  5088  ab196087 
   2176  5088  ab196087 	return (&module);
   2177  5088  ab196087 }
   2178