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