Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include	<ctype.h>
     28 #include	<elfedit.h>
     29 #include	<sys/elf_SPARC.h>
     30 #include	<strings.h>
     31 #include	<debug.h>
     32 #include	<conv.h>
     33 #include	<cap_msg.h>
     34 
     35 
     36 /*
     37  * Capabilities section
     38  */
     39 
     40 
     41 
     42 
     43 /*
     44  * This module uses shared code for several of the commands.
     45  * It is sometimes necessary to know which specific command
     46  * is active.
     47  */
     48 typedef enum {
     49 	/* Dump command, used as module default to display dynamic section */
     50 	CAP_CMD_T_DUMP =	0,	/* cap:dump */
     51 
     52 	/* Commands that do not correspond directly to a specific DT tag */
     53 	CAP_CMD_T_TAG =		1,	/* cap:tag */
     54 	CAP_CMD_T_VALUE =	2,	/* cap:value */
     55 	CAP_CMD_T_DELETE =	3,	/* cap:delete */
     56 	CAP_CMD_T_MOVE =	4,	/* cap:shift */
     57 
     58 	/* Commands that embody tag specific knowledge */
     59 	CAP_CMD_T_HW1 =		5,	/* cap:hw1 */
     60 	CAP_CMD_T_SF1 =		6,	/* cap:sf1 */
     61 } CAP_CMD_T;
     62 
     63 
     64 
     65 #ifndef _ELF64
     66 /*
     67  * We supply this function for the msg module
     68  */
     69 const char *
     70 _cap_msg(Msg mid)
     71 {
     72 	return (gettext(MSG_ORIG(mid)));
     73 }
     74 #endif
     75 
     76 
     77 /*
     78  * This function is supplied to elfedit through our elfedit_module_t
     79  * definition. It translates the opaque elfedit_i18nhdl_t handles
     80  * in our module interface into the actual strings for elfedit to
     81  * use.
     82  *
     83  * note:
     84  *	This module uses Msg codes for its i18n handle type.
     85  *	So the translation is simply to use MSG_INTL() to turn
     86  *	it into a string and return it.
     87  */
     88 static const char *
     89 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
     90 {
     91 	Msg msg = (Msg)hdl;
     92 
     93 	return (MSG_INTL(msg));
     94 }
     95 
     96 
     97 
     98 /*
     99  * The cap_opt_t enum specifies a bit value for every optional
    100  * argument allowed by a command in this module.
    101  */
    102 typedef enum {
    103 	CAP_OPT_F_AND =		1,	/* -and: AND (&) values to dest */
    104 	CAP_OPT_F_CMP =		2,	/* -cmp: Complement (~) values */
    105 	CAP_OPT_F_CAPNDX =	4,	/* -capndx: elt is tag index, */
    106 					/*	not name */
    107 	CAP_OPT_F_OR =		8,	/* -or: OR (|) values to dest */
    108 } cap_opt_t;
    109 
    110 
    111 /*
    112  * A variable of type ARGSTATE is used by each command to maintain
    113  * information about the arguments and related things. It is
    114  * initialized by process_args(), and used by the other routines.
    115  */
    116 typedef struct {
    117 	elfedit_obj_state_t	*obj_state;
    118 	struct {
    119 		elfedit_section_t *sec;	/* Capabilities section reference */
    120 		Cap	*data;		/* Start of capabilities section data */
    121 		Word	num;		/* # Capabilities elts */
    122 	} cap;
    123 	cap_opt_t	optmask;   	/* Mask of options used */
    124 	int		argc;		/* # of plain arguments */
    125 	const char	**argv;		/* Plain arguments */
    126 } ARGSTATE;
    127 
    128 
    129 
    130 /*
    131  * Standard argument processing for cap module
    132  *
    133  * entry
    134  *	obj_state, argc, argv - Standard command arguments
    135  *	argstate - Address of ARGSTATE block to be initialized
    136  *
    137  * exit:
    138  *	On success, *argstate is initialized. On error,
    139  *	an error is issued and this routine does not return.
    140  */
    141 static void
    142 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
    143     ARGSTATE *argstate)
    144 {
    145 	elfedit_getopt_state_t	getopt_state;
    146 	elfedit_getopt_ret_t	*getopt_ret;
    147 
    148 	bzero(argstate, sizeof (*argstate));
    149 	argstate->obj_state = obj_state;
    150 
    151 	elfedit_getopt_init(&getopt_state, &argc, &argv);
    152 
    153 	/* Add each new option to the options mask */
    154 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL)
    155 		argstate->optmask |= getopt_ret->gor_idmask;
    156 
    157 	/* If there may be an arbitrary amount of output, use a pager */
    158 	if (argc == 0)
    159 		elfedit_pager_init();
    160 
    161 	/* Return the updated values of argc/argv */
    162 	argstate->argc = argc;
    163 	argstate->argv = argv;
    164 
    165 	/* Locate the capabilities section */
    166 	argstate->cap.sec = elfedit_sec_getcap(obj_state, &argstate->cap.data,
    167 	    &argstate->cap.num);
    168 }
    169 
    170 
    171 
    172 /*
    173  * Print ELF capabilities values, taking the calling command, and output style
    174  * into account.
    175  *
    176  * entry:
    177  *	cmd - CAP_CMD_T_* value giving identify of caller
    178  *	autoprint - If True, output is only produced if the elfedit
    179  *		autoprint flag is set. If False, output is always produced.
    180  *	argstate - Argument state block
    181  *	print_type - Specifies which capabilities elements to display.
    182  *	ndx = If print_type is PRINT_CAP_T_NDX, displays the index specified.
    183  *		Otherwise ignored.
    184  */
    185 typedef enum {
    186 	PRINT_CAP_T_ALL =	0,	/* Show all indexes */
    187 	PRINT_CAP_T_NDX =	1,	/* Show capabilities[arg] only */
    188 	PRINT_CAP_T_TAG =	2	/* Show all elts with tag type */
    189 					/*	given by arg */
    190 } PRINT_CAP_T;
    191 
    192 static void
    193 print_cap(CAP_CMD_T cmd, int autoprint, ARGSTATE *argstate,
    194     PRINT_CAP_T print_type, Word arg)
    195 {
    196 	elfedit_outstyle_t	outstyle;
    197 	Word	cnt, ndx, printed = 0;
    198 	Cap	*cap;
    199 	int	header_done = 0;
    200 	Xword	last_c_val = 0;
    201 
    202 	if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
    203 		return;
    204 
    205 	/*
    206 	 * Pick an output style. cap:dump is required to use the default
    207 	 * style. The other commands use the current output style.
    208 	 */
    209 	outstyle = (cmd == CAP_CMD_T_DUMP) ?
    210 	    ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
    211 
    212 	/* How many elements do we examine? */
    213 	if (print_type == PRINT_CAP_T_NDX) {
    214 		if (arg >= argstate->cap.num)
    215 			return;		/* Out of range */
    216 		ndx = arg;
    217 		cnt = 1;
    218 	} else {
    219 		ndx = 0;
    220 		cnt = argstate->cap.num;
    221 	}
    222 
    223 	cap = &argstate->cap.data[ndx];
    224 	for (; cnt--; cap++, ndx++) {
    225 		/*
    226 		 * If we are only displaying certain tag types and
    227 		 * this isn't one of those, move on to next element.
    228 		 */
    229 		if ((print_type == PRINT_CAP_T_TAG) && (cap->c_tag != arg))
    230 			continue;
    231 
    232 		if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
    233 			if (header_done == 0) {
    234 				header_done = 1;
    235 				Elf_cap_title(0);
    236 			}
    237 			Elf_cap_entry(NULL, cap, ndx,
    238 			    argstate->obj_state->os_ehdr->e_machine);
    239 		} else {
    240 			/*
    241 			 * In simple or numeric mode under a print type
    242 			 * that is based on tag type rather than on index,
    243 			 * quietly: If we've already printed this value,
    244 			 * don't print it again. A common example of this
    245 			 * is PRINT_CAP_T_RUNPATH when both CA_RPATH and
    246 			 * CA_RUNPATH are present with the same value.
    247 			 */
    248 			if ((print_type == PRINT_CAP_T_TAG) && printed &&
    249 			    (last_c_val == cap->c_un.c_val))
    250 				continue;
    251 
    252 			if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
    253 				union {
    254 					Conv_cap_val_hw1_buf_t	hw1;
    255 					Conv_cap_val_sf1_buf_t	sf1;
    256 				} c_buf;
    257 
    258 				switch (cap->c_tag) {
    259 				case CA_SUNW_HW_1:
    260 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
    261 					    conv_cap_val_hw1(cap->c_un.c_val,
    262 					    argstate->obj_state->os_ehdr->
    263 					    e_machine,
    264 					    CONV_FMT_NOBKT, &c_buf.hw1));
    265 					printed = 1;
    266 					continue;
    267 				case CA_SUNW_SF_1:
    268 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
    269 					    conv_cap_val_sf1(cap->c_un.c_val,
    270 					    argstate->obj_state->os_ehdr->
    271 					    e_machine,
    272 					    CONV_FMT_NOBKT, &c_buf.sf1));
    273 					printed = 1;
    274 					continue;
    275 				}
    276 			}
    277 			elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL),
    278 			    cap->c_un.c_val);
    279 		}
    280 		printed = 1;
    281 		last_c_val = cap->c_un.c_val;
    282 	}
    283 
    284 	/*
    285 	 * If nothing was output under the print types that are
    286 	 * based on tag type, issue an error saying it doesn't exist.
    287 	 */
    288 	if (!printed && (print_type == PRINT_CAP_T_TAG)) {
    289 		Conv_inv_buf_t inv_buf;
    290 
    291 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT),
    292 		    EC_WORD(argstate->cap.sec->sec_shndx),
    293 		    argstate->cap.sec->sec_name,
    294 		    conv_cap_tag(arg, 0, &inv_buf));
    295 	}
    296 }
    297 
    298 
    299 /*
    300  * Process the elt argument: This will be a tag type if -capndx is
    301  * not present and this is a print request. It will be an index otherwise.
    302  *
    303  * entry:
    304  *	argstate - Argument state block
    305  *	arg - Argument string to be converted into an index
    306  *	argname - String giving the name by which the argument is
    307  *		referred in the online help for the command.
    308  *	print_request - True if the command is to print the current
    309  *		value(s) and return without changing anything.
    310  *	print_type - Address of variable containing PRINT_CAP_T_
    311  *		code specifying how the elements will be displayed.
    312  *
    313  * exit:
    314  *	If print_request is False: arg is converted into an integer value.
    315  *	If -capndx was used, we convert it into an integer. If it was not
    316  *	used, then arg is a tag name --- we find the first capabilities entry
    317  *	that matches. If no entry matches, and there is an extra CA_NULL,
    318  *	it is added. Otherwise an error is issued. *print_type is set
    319  *	to PRINT_CAP_T_NDX.
    320  *
    321  *	If print_request is True: If -capndx was used, arg is converted into
    322  *	an integer value, *print_type is set to PRINT_CAP_T_NDX, and
    323  *	the value is returned. If -capndx was not used, *print_type is set to
    324  *	PRINT_CAP_T_TAG, and the tag value is returned.
    325  */
    326 static Word
    327 arg_to_index(ARGSTATE *argstate, const char *arg, const char *argname,
    328     int print_request, PRINT_CAP_T *print_type)
    329 {
    330 	Word	ndx, ca_value;
    331 
    332 
    333 	/* Assume we are returning an index, alter as needed below */
    334 	*print_type = PRINT_CAP_T_NDX;
    335 
    336 	/* If -capndx was used, this is a simple numeric index */
    337 	if ((argstate->optmask & CAP_OPT_F_CAPNDX) != 0)
    338 		return ((Word) elfedit_atoui_range(arg, argname, 0,
    339 		    argstate->cap.num - 1, NULL));
    340 
    341 	/* The argument is a CA_ tag type, not a numeric index */
    342 	ca_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_CA);
    343 
    344 	/*
    345 	 * If this is a printing request, then we let print_cap() show
    346 	 * all the items with this tag type.
    347 	 */
    348 	if (print_request) {
    349 		*print_type = PRINT_CAP_T_TAG;
    350 		return (ca_value);
    351 	}
    352 
    353 	/* Locate the first entry with the given tag type */
    354 	for (ndx = 0; ndx < argstate->cap.num; ndx++) {
    355 		if (argstate->cap.data[ndx].c_tag == ca_value) {
    356 			elfedit_msg(ELFEDIT_MSG_DEBUG,
    357 			    MSG_INTL(MSG_DEBUG_CA2NDX),
    358 			    EC_WORD(argstate->cap.sec->sec_shndx),
    359 			    argstate->cap.sec->sec_name, EC_WORD(ndx), arg);
    360 			return (ndx);
    361 		}
    362 	}
    363 
    364 	/* No room to create one, so we're out of options and must fail */
    365 	elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT),
    366 	    EC_WORD(argstate->cap.sec->sec_shndx),
    367 	    argstate->cap.sec->sec_name, arg);
    368 
    369 	/*NOTREACHED*/
    370 	return (0);		/* For lint */
    371 }
    372 
    373 
    374 /*
    375  * Argument processing for the bitmask commands. Convert the arguments
    376  * to integer form, apply -and/-cmp/-or, and return the resulting value.
    377  *
    378  * entry:
    379  *	argstate - Argument state block
    380  *	orig - Value of original bitmask
    381  *	const_sym - NULL, or array of name->integer mappings for
    382  *		applicable symbolic constant names.
    383  */
    384 static Word
    385 flag_bitop(ARGSTATE *argstate, Word orig, const elfedit_atoui_sym_t *const_sym)
    386 {
    387 	Word flags = 0;
    388 	int i;
    389 
    390 	/* Collect the arguments */
    391 	for (i = 0; i < argstate->argc; i++)
    392 		flags |= (Word) elfedit_atoui(argstate->argv[i], const_sym);
    393 
    394 	/* Complement the value? */
    395 	if (argstate->optmask & CAP_OPT_F_CMP)
    396 		flags = ~flags;
    397 
    398 	/* Perform any requested bit operations */
    399 	if (argstate->optmask & CAP_OPT_F_AND)
    400 		flags &= orig;
    401 	else if (argstate->optmask & CAP_OPT_F_OR)
    402 		flags |= orig;
    403 
    404 	return (flags);
    405 }
    406 
    407 
    408 
    409 /*
    410  * Common body for the cap: module commands. These commands
    411  * share a large amount of common behavior, so it is convenient
    412  * to centralize things and use the cmd argument to handle the
    413  * small differences.
    414  *
    415  * entry:
    416  *	cmd - One of the CAP_CMD_T_* constants listed above, specifying
    417  *		which command to implement.
    418  *	obj_state, argc, argv - Standard command arguments
    419  */
    420 static elfedit_cmdret_t
    421 cmd_body(CAP_CMD_T cmd, elfedit_obj_state_t *obj_state,
    422     int argc, const char *argv[])
    423 {
    424 	ARGSTATE		argstate;
    425 	Cap			*cap;
    426 	const char		*cap_name;
    427 	Word			cap_ndx, cap_num;
    428 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
    429 	PRINT_CAP_T		print_type = PRINT_CAP_T_ALL;
    430 	Word			ndx;
    431 	int			print_only = 0;
    432 	int			do_autoprint = 1;
    433 
    434 	/* Process the optional arguments */
    435 	process_args(obj_state, argc, argv, &argstate);
    436 
    437 	cap = argstate.cap.data;
    438 	cap_num = argstate.cap.num;
    439 	cap_name = argstate.cap.sec->sec_name;
    440 	cap_ndx = argstate.cap.sec->sec_shndx;
    441 
    442 	/* Check number of arguments, gather information */
    443 	switch (cmd) {
    444 	case CAP_CMD_T_DUMP:
    445 		/* cap:dump can accept an optional index argument */
    446 		if (argstate.argc > 1)
    447 			elfedit_command_usage();
    448 		print_only = 1;
    449 		if (argstate.argc == 1)
    450 			ndx = arg_to_index(&argstate, argstate.argv[0],
    451 			    MSG_ORIG(MSG_STR_ELT), print_only, &print_type);
    452 		break;
    453 
    454 	case CAP_CMD_T_TAG:
    455 	case CAP_CMD_T_VALUE:
    456 		print_only = (argstate.argc != 2);
    457 		if (argstate.argc > 0) {
    458 			if (argstate.argc > 2)
    459 				elfedit_command_usage();
    460 			ndx = arg_to_index(&argstate, argstate.argv[0],
    461 			    MSG_ORIG(MSG_STR_ELT), print_only, &print_type);
    462 		}
    463 		break;
    464 
    465 	case CAP_CMD_T_DELETE:
    466 		if ((argstate.argc < 1) || (argstate.argc > 2))
    467 			elfedit_command_usage();
    468 		ndx = arg_to_index(&argstate, argstate.argv[0],
    469 		    MSG_ORIG(MSG_STR_ELT),
    470 		    0, &print_type);
    471 		do_autoprint = 0;
    472 		break;
    473 
    474 	case CAP_CMD_T_MOVE:
    475 		if ((argstate.argc < 2) || (argstate.argc > 3))
    476 			elfedit_command_usage();
    477 		ndx = arg_to_index(&argstate, argstate.argv[0],
    478 		    MSG_ORIG(MSG_STR_ELT), 0, &print_type);
    479 		do_autoprint = 0;
    480 		break;
    481 
    482 	case CAP_CMD_T_HW1:
    483 		print_only = (argstate.argc == 0);
    484 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
    485 		    ELFEDIT_CONST_CA, CA_SUNW_HW_1, 1),
    486 		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
    487 		break;
    488 
    489 	case CAP_CMD_T_SF1:
    490 		print_only = (argstate.argc == 0);
    491 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
    492 		    ELFEDIT_CONST_CA, CA_SUNW_SF_1, 1),
    493 		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
    494 		break;
    495 
    496 	default:
    497 		/* Note expected: All commands should have been caught above */
    498 		elfedit_command_usage();
    499 		break;
    500 	}
    501 
    502 
    503 	/* If this is a request to print current values, do it and return */
    504 	if (print_only) {
    505 		print_cap(cmd, 0, &argstate, print_type, ndx);
    506 		return (ELFEDIT_CMDRET_NONE);
    507 	}
    508 
    509 
    510 	switch (cmd) {
    511 		/*
    512 		 * CAP_CMD_T_DUMP can't get here: It is a print-only
    513 		 * command.
    514 		 */
    515 
    516 	case CAP_CMD_T_TAG:
    517 		{
    518 			Conv_inv_buf_t	inv_buf1, inv_buf2;
    519 			Word c_tag = (Word) elfedit_atoconst(argstate.argv[1],
    520 			    ELFEDIT_CONST_CA);
    521 
    522 			if (cap[ndx].c_tag == c_tag) {
    523 				elfedit_msg(ELFEDIT_MSG_DEBUG,
    524 				    MSG_INTL(MSG_DEBUG_S_OK),
    525 				    cap_ndx, cap_name, EC_WORD(ndx),
    526 				    conv_cap_tag(c_tag, 0, &inv_buf1));
    527 			} else {
    528 				elfedit_msg(ELFEDIT_MSG_DEBUG,
    529 				    MSG_INTL(MSG_DEBUG_S_CHG),
    530 				    cap_ndx, cap_name, EC_WORD(ndx),
    531 				    conv_cap_tag(cap[ndx].c_tag, 0, &inv_buf1),
    532 				    conv_cap_tag(c_tag, 0, &inv_buf2));
    533 				cap[ndx].c_tag = c_tag;
    534 				ret = ELFEDIT_CMDRET_MOD;
    535 			}
    536 		}
    537 		break;
    538 
    539 	case CAP_CMD_T_VALUE:
    540 		{
    541 			Xword c_val = (Xword)
    542 			    elfedit_atoui(argstate.argv[1], NULL);
    543 
    544 			if (cap[ndx].c_un.c_val == c_val) {
    545 				elfedit_msg(ELFEDIT_MSG_DEBUG,
    546 				    MSG_INTL(MSG_DEBUG_X_OK),
    547 				    argstate.cap.sec->sec_shndx,
    548 				    argstate.cap.sec->sec_name,
    549 				    EC_WORD(ndx), EC_XWORD(c_val));
    550 			} else {
    551 				elfedit_msg(ELFEDIT_MSG_DEBUG,
    552 				    MSG_INTL(MSG_DEBUG_X_CHG),
    553 				    argstate.cap.sec->sec_shndx,
    554 				    argstate.cap.sec->sec_name,
    555 				    EC_WORD(ndx), EC_XWORD(cap[ndx].c_un.c_val),
    556 				    EC_XWORD(c_val));
    557 				cap[ndx].c_un.c_val = c_val;
    558 				ret = ELFEDIT_CMDRET_MOD;
    559 			}
    560 		}
    561 		break;
    562 
    563 	case CAP_CMD_T_DELETE:
    564 		{
    565 			Word cnt = (argstate.argc == 1) ? 1 :
    566 			    (Word) elfedit_atoui_range(argstate.argv[1],
    567 			    MSG_ORIG(MSG_STR_COUNT), 1, cap_num - ndx, NULL);
    568 			const char *msg_prefix =
    569 			    elfedit_sec_msgprefix(argstate.cap.sec);
    570 
    571 			elfedit_array_elts_delete(msg_prefix, argstate.cap.data,
    572 			    sizeof (Cap), cap_num, ndx, cnt);
    573 			ret = ELFEDIT_CMDRET_MOD;
    574 		}
    575 		break;
    576 
    577 	case CAP_CMD_T_MOVE:
    578 		{
    579 			Cap	save;
    580 			Word	cnt;
    581 			Word	dstndx;
    582 			const char *msg_prefix =
    583 			    elfedit_sec_msgprefix(argstate.cap.sec);
    584 
    585 			dstndx = (Word)
    586 			    elfedit_atoui_range(argstate.argv[1],
    587 			    MSG_ORIG(MSG_STR_DST_INDEX), 0, cap_num - 1,
    588 			    NULL);
    589 			if (argstate.argc == 2) {
    590 				cnt = 1;
    591 			} else {
    592 				cnt = (Word) elfedit_atoui_range(
    593 				    argstate.argv[2], MSG_ORIG(MSG_STR_COUNT),
    594 				    1, cap_num, NULL);
    595 			}
    596 			elfedit_array_elts_move(msg_prefix, argstate.cap.data,
    597 			    sizeof (save), cap_num, ndx, dstndx, cnt, &save);
    598 			ret = ELFEDIT_CMDRET_MOD;
    599 		}
    600 		break;
    601 
    602 
    603 	case CAP_CMD_T_HW1:
    604 		{
    605 			Conv_cap_val_hw1_buf_t buf1, buf2;
    606 			Half	mach = argstate.obj_state->os_ehdr->e_machine;
    607 			Xword	hw1;
    608 
    609 			hw1 = flag_bitop(&argstate, cap[ndx].c_un.c_val,
    610 			    elfedit_const_to_atoui(ELFEDIT_CONST_AV));
    611 
    612 			/* Set the value */
    613 			if (cap[ndx].c_un.c_val == hw1) {
    614 				elfedit_msg(ELFEDIT_MSG_DEBUG,
    615 				    MSG_INTL(MSG_DEBUG_BSB_OK), cap_ndx,
    616 				    cap_name, EC_WORD(ndx),
    617 				    conv_cap_val_hw1(cap[ndx].c_un.c_val, mach,
    618 				    CONV_FMT_NOBKT, &buf1));
    619 			} else {
    620 				elfedit_msg(ELFEDIT_MSG_DEBUG,
    621 				    MSG_INTL(MSG_DEBUG_BSB_CHG),
    622 				    cap_ndx, cap_name, EC_WORD(ndx),
    623 				    conv_cap_val_hw1(cap[ndx].c_un.c_val, mach,
    624 				    CONV_FMT_NOBKT, &buf1),
    625 				    conv_cap_val_hw1(hw1, mach,
    626 				    CONV_FMT_NOBKT, &buf2));
    627 				ret = ELFEDIT_CMDRET_MOD;
    628 				cap[ndx].c_un.c_val = hw1;
    629 			}
    630 		}
    631 		break;
    632 
    633 	case CAP_CMD_T_SF1:
    634 		{
    635 			Conv_cap_val_sf1_buf_t buf1, buf2;
    636 			Half	mach = argstate.obj_state->os_ehdr->e_machine;
    637 			Xword	sf1;
    638 
    639 			sf1 = flag_bitop(&argstate, cap[ndx].c_un.c_val,
    640 			    elfedit_const_to_atoui(ELFEDIT_CONST_SF1_SUNW));
    641 
    642 			/* Set the value */
    643 			if (cap[ndx].c_un.c_val == sf1) {
    644 				elfedit_msg(ELFEDIT_MSG_DEBUG,
    645 				    MSG_INTL(MSG_DEBUG_BSB_OK), cap_ndx,
    646 				    cap_name, EC_WORD(ndx),
    647 				    conv_cap_val_sf1(cap[ndx].c_un.c_val, mach,
    648 				    CONV_FMT_NOBKT, &buf1));
    649 			} else {
    650 				elfedit_msg(ELFEDIT_MSG_DEBUG,
    651 				    MSG_INTL(MSG_DEBUG_BSB_CHG),
    652 				    cap_ndx, cap_name, EC_WORD(ndx),
    653 				    conv_cap_val_sf1(cap[ndx].c_un.c_val, mach,
    654 				    CONV_FMT_NOBKT, &buf1),
    655 				    conv_cap_val_sf1(sf1, mach,
    656 				    CONV_FMT_NOBKT, &buf2));
    657 				ret = ELFEDIT_CMDRET_MOD;
    658 				cap[ndx].c_un.c_val = sf1;
    659 			}
    660 		}
    661 		break;
    662 	}
    663 
    664 	/*
    665 	 * If we modified the capabilities section header, tell libelf.
    666 	 */
    667 	if (ret == ELFEDIT_CMDRET_MOD)
    668 		elfedit_modified_data(argstate.cap.sec);
    669 
    670 	/* Do autoprint */
    671 	if (do_autoprint)
    672 		print_cap(cmd, 1, &argstate, print_type, ndx);
    673 
    674 	return (ret);
    675 }
    676 
    677 
    678 
    679 /*
    680  * Command completion functions for the commands
    681  */
    682 
    683 /*
    684  * Command completion for the first argument, which specifies
    685  * the capabilities element to use. Examines the options to see if
    686  * -capndx is present, and if not, supplies the completion
    687  * strings for argument 1.
    688  */
    689 /*ARGSUSED*/
    690 static void
    691 cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
    692     const char *argv[], int num_opt)
    693 {
    694 	Word			i;
    695 
    696 	/* Make sure it's the first argument */
    697 	if ((argc - num_opt) != 1)
    698 		return;
    699 
    700 	/* Is -capndx present? If so, we don't complete tag types */
    701 	for (i = 0; i < num_opt; i++)
    702 		if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_CAPNDX)) == 0)
    703 			return;
    704 
    705 	/*
    706 	 * Supply capability tag names. There are very few of these, so
    707 	 * rather than worry about whether a given tag exists in the
    708 	 * file or not, we simply serve up all the possibilities.
    709 	 */
    710 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_CA);
    711 }
    712 
    713 
    714 /*ARGSUSED*/
    715 static void
    716 cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
    717     const char *argv[], int num_opt)
    718 {
    719 	/* First argument */
    720 	if ((argc - num_opt) == 1) {
    721 		cpl_eltarg(obj_state, cpldata, argc, argv, num_opt);
    722 		return;
    723 	}
    724 
    725 	/* The second argument is always a tag value */
    726 	if ((argc - num_opt) == 2)
    727 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_CA);
    728 }
    729 
    730 /*ARGSUSED*/
    731 static void
    732 cpl_hw1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
    733     const char *argv[], int num_opt)
    734 {
    735 	/* This routine allows multiple flags to be specified */
    736 
    737 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_AV);
    738 }
    739 
    740 /*ARGSUSED*/
    741 static void
    742 cpl_sf1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
    743     const char *argv[], int num_opt)
    744 {
    745 	/* This routine allows multiple flags to be specified */
    746 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SF1_SUNW);
    747 }
    748 
    749 
    750 /*
    751  * Implementation functions for the commands
    752  */
    753 static elfedit_cmdret_t
    754 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
    755 {
    756 	return (cmd_body(CAP_CMD_T_DUMP, obj_state, argc, argv));
    757 }
    758 
    759 static elfedit_cmdret_t
    760 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
    761 {
    762 	return (cmd_body(CAP_CMD_T_TAG, obj_state, argc, argv));
    763 }
    764 
    765 static elfedit_cmdret_t
    766 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
    767 {
    768 	return (cmd_body(CAP_CMD_T_VALUE, obj_state, argc, argv));
    769 }
    770 
    771 static elfedit_cmdret_t
    772 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
    773 {
    774 	return (cmd_body(CAP_CMD_T_DELETE, obj_state, argc, argv));
    775 }
    776 
    777 static elfedit_cmdret_t
    778 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
    779 {
    780 	return (cmd_body(CAP_CMD_T_MOVE, obj_state, argc, argv));
    781 }
    782 
    783 static elfedit_cmdret_t
    784 cmd_hw1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
    785 {
    786 	return (cmd_body(CAP_CMD_T_HW1, obj_state, argc, argv));
    787 }
    788 
    789 static elfedit_cmdret_t
    790 cmd_sf1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
    791 {
    792 	return (cmd_body(CAP_CMD_T_SF1, obj_state, argc, argv));
    793 }
    794 
    795 
    796 
    797 /*ARGSUSED*/
    798 elfedit_module_t *
    799 elfedit_init(elfedit_module_version_t version)
    800 {
    801 	/* For commands that only accept -and, -cmp, -o, and -or */
    802 	static elfedit_cmd_optarg_t opt_ostyle_bitop[] = {
    803 		{ ELFEDIT_STDOA_OPT_AND, NULL,
    804 		    ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_AND, CAP_OPT_F_OR },
    805 		{ ELFEDIT_STDOA_OPT_CMP, NULL,
    806 		    ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_CMP, 0 },
    807 		{ ELFEDIT_STDOA_OPT_O, NULL,
    808 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
    809 		{ ELFEDIT_STDOA_OPT_OR, NULL,
    810 		    ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_OR, CAP_OPT_F_AND },
    811 		{ NULL }
    812 	};
    813 
    814 	/* For commands that only accept -capndx */
    815 	static elfedit_cmd_optarg_t opt_capndx[] = {
    816 		{ MSG_ORIG(MSG_STR_MINUS_CAPNDX),
    817 		    /* MSG_INTL(MSG_OPTDESC_CAPNDX) */
    818 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0,
    819 		    CAP_OPT_F_CAPNDX, 0 },
    820 		{ NULL }
    821 	};
    822 
    823 	/* For commands thataccept -capndx and output styles */
    824 	static elfedit_cmd_optarg_t opt_ostyle_capndx[] = {
    825 		{ MSG_ORIG(MSG_STR_MINUS_CAPNDX),
    826 		    /* MSG_INTL(MSG_OPTDESC_CAPNDX) */
    827 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0,
    828 		    CAP_OPT_F_CAPNDX, 0 },
    829 		{ ELFEDIT_STDOA_OPT_O, NULL,
    830 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
    831 		{ NULL }
    832 	};
    833 
    834 
    835 	/* cap:dump */
    836 	static const char *name_dump[] = {
    837 	    MSG_ORIG(MSG_CMD_DUMP),
    838 	    MSG_ORIG(MSG_STR_EMPTY),	/* "" makes this the default command */
    839 	    NULL
    840 	};
    841 	static elfedit_cmd_optarg_t arg_dump[] = {
    842 		{ MSG_ORIG(MSG_STR_ELT),
    843 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
    844 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
    845 		    ELFEDIT_CMDOA_F_OPT },
    846 		{ NULL }
    847 	};
    848 
    849 
    850 	/* cap:tag */
    851 	static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL };
    852 	static elfedit_cmd_optarg_t arg_tag[] = {
    853 		{ MSG_ORIG(MSG_STR_ELT),
    854 		    /* MSG_INTL(MSG_A1_TAG_ELT) */
    855 		    ELFEDIT_I18NHDL(MSG_A1_TAG_ELT),
    856 		    ELFEDIT_CMDOA_F_OPT },
    857 		{ MSG_ORIG(MSG_STR_VALUE),
    858 		    /* MSG_INTL(MSG_A2_TAG_VALUE) */
    859 		    ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE),
    860 		    ELFEDIT_CMDOA_F_OPT },
    861 		{ NULL }
    862 	};
    863 
    864 
    865 	/* cap:value */
    866 	static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL };
    867 	static elfedit_cmd_optarg_t arg_value[] = {
    868 		{ MSG_ORIG(MSG_STR_ELT),
    869 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
    870 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
    871 		    ELFEDIT_CMDOA_F_OPT },
    872 		{ MSG_ORIG(MSG_STR_VALUE),
    873 		    /* MSG_INTL(MSG_A2_VALUE_VALUE) */
    874 		    ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE),
    875 		    ELFEDIT_CMDOA_F_OPT },
    876 		{ NULL }
    877 	};
    878 
    879 	/* cap:delete */
    880 	static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL };
    881 	static elfedit_cmd_optarg_t arg_delete[] = {
    882 		{ MSG_ORIG(MSG_STR_ELT),
    883 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
    884 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
    885 		    0 },
    886 		{ MSG_ORIG(MSG_STR_COUNT),
    887 		    /* MSG_INTL(MSG_A2_DELETE_COUNT) */
    888 		    ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT),
    889 		    ELFEDIT_CMDOA_F_OPT },
    890 		{ NULL }
    891 	};
    892 
    893 	/* cap:move */
    894 	static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL };
    895 	static elfedit_cmd_optarg_t arg_move[] = {
    896 		{ MSG_ORIG(MSG_STR_ELT),
    897 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
    898 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
    899 		    0 },
    900 		{ MSG_ORIG(MSG_STR_DST_INDEX),
    901 		    /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */
    902 		    ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX),
    903 		    0 },
    904 		{ MSG_ORIG(MSG_STR_COUNT),
    905 		    /* MSG_INTL(MSG_A3_MOVE_COUNT) */
    906 		    ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT),
    907 		    ELFEDIT_CMDOA_F_OPT },
    908 		{ NULL }
    909 	};
    910 
    911 	/* cap:hw1 */
    912 	static const char *name_hw1[] = { MSG_ORIG(MSG_CMD_HW1), NULL };
    913 	static elfedit_cmd_optarg_t arg_hw1[] = {
    914 		{ MSG_ORIG(MSG_STR_VALUE),
    915 		    /* MSG_INTL(MSG_A1_HW1_VALUE) */
    916 		    ELFEDIT_I18NHDL(MSG_A1_HW1_VALUE),
    917 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
    918 		{ NULL }
    919 	};
    920 
    921 	/* cap:sf1 */
    922 	static const char *name_sf1[] = { MSG_ORIG(MSG_CMD_SF1), NULL };
    923 	static elfedit_cmd_optarg_t arg_sf1[] = {
    924 		{ MSG_ORIG(MSG_STR_VALUE),
    925 		    /* MSG_INTL(MSG_A1_SF1_VALUE) */
    926 		    ELFEDIT_I18NHDL(MSG_A1_SF1_VALUE),
    927 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
    928 		{ NULL }
    929 	};
    930 
    931 
    932 
    933 
    934 	static elfedit_cmd_t cmds[] = {
    935 		/* cap:dump */
    936 		{ cmd_dump, cpl_eltarg, name_dump,
    937 		    /* MSG_INTL(MSG_DESC_DUMP) */
    938 		    ELFEDIT_I18NHDL(MSG_DESC_DUMP),
    939 		    /* MSG_INTL(MSG_HELP_DUMP) */
    940 		    ELFEDIT_I18NHDL(MSG_HELP_DUMP),
    941 		    opt_capndx, arg_dump },
    942 
    943 		/* cap:tag */
    944 		{ cmd_tag, cpl_tag, name_tag,
    945 		    /* MSG_INTL(MSG_DESC_TAG) */
    946 		    ELFEDIT_I18NHDL(MSG_DESC_TAG),
    947 		    /* MSG_INTL(MSG_HELP_TAG) */
    948 		    ELFEDIT_I18NHDL(MSG_HELP_TAG),
    949 		    opt_ostyle_capndx, arg_tag },
    950 
    951 		/* cap:value */
    952 		{ cmd_value, cpl_eltarg, name_value,
    953 		    /* MSG_INTL(MSG_DESC_VALUE) */
    954 		    ELFEDIT_I18NHDL(MSG_DESC_VALUE),
    955 		    /* MSG_INTL(MSG_HELP_VALUE) */
    956 		    ELFEDIT_I18NHDL(MSG_HELP_VALUE),
    957 		    opt_ostyle_capndx, arg_value },
    958 
    959 		/* cap:delete */
    960 		{ cmd_delete, cpl_eltarg, name_delete,
    961 		    /* MSG_INTL(MSG_DESC_DELETE) */
    962 		    ELFEDIT_I18NHDL(MSG_DESC_DELETE),
    963 		    /* MSG_INTL(MSG_HELP_DELETE) */
    964 		    ELFEDIT_I18NHDL(MSG_HELP_DELETE),
    965 		    opt_capndx, arg_delete },
    966 
    967 		/* cap:move */
    968 		{ cmd_move, cpl_eltarg, name_move,
    969 		    /* MSG_INTL(MSG_DESC_MOVE) */
    970 		    ELFEDIT_I18NHDL(MSG_DESC_MOVE),
    971 		    /* MSG_INTL(MSG_HELP_MOVE) */
    972 		    ELFEDIT_I18NHDL(MSG_HELP_MOVE),
    973 		    opt_capndx, arg_move },
    974 
    975 		/* cap:hw1 */
    976 		{ cmd_hw1, cpl_hw1, name_hw1,
    977 		    /* MSG_INTL(MSG_DESC_HW1) */
    978 		    ELFEDIT_I18NHDL(MSG_DESC_HW1),
    979 		    /* MSG_INTL(MSG_HELP_HW1) */
    980 		    ELFEDIT_I18NHDL(MSG_HELP_HW1),
    981 		    opt_ostyle_bitop, arg_hw1 },
    982 
    983 		/* cap:sf1 */
    984 		{ cmd_sf1, cpl_sf1, name_sf1,
    985 		    /* MSG_INTL(MSG_DESC_SF1) */
    986 		    ELFEDIT_I18NHDL(MSG_DESC_SF1),
    987 		    /* MSG_INTL(MSG_HELP_SF1) */
    988 		    ELFEDIT_I18NHDL(MSG_HELP_SF1),
    989 		    opt_ostyle_bitop, arg_sf1 },
    990 
    991 		{ NULL }
    992 	};
    993 
    994 	static elfedit_module_t module = {
    995 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
    996 	    /* MSG_INTL(MSG_MOD_DESC) */
    997 	    ELFEDIT_I18NHDL(MSG_MOD_DESC),
    998 	    cmds, mod_i18nhdl_to_str };
    999 
   1000 	return (&module);
   1001 }
   1002