1*d29b2c44Sab /*
2*d29b2c44Sab  * CDDL HEADER START
3*d29b2c44Sab  *
4*d29b2c44Sab  * The contents of this file are subject to the terms of the
5*d29b2c44Sab  * Common Development and Distribution License (the "License").
6*d29b2c44Sab  * You may not use this file except in compliance with the License.
7*d29b2c44Sab  *
8*d29b2c44Sab  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*d29b2c44Sab  * or http://www.opensolaris.org/os/licensing.
10*d29b2c44Sab  * See the License for the specific language governing permissions
11*d29b2c44Sab  * and limitations under the License.
12*d29b2c44Sab  *
13*d29b2c44Sab  * When distributing Covered Code, include this CDDL HEADER in each
14*d29b2c44Sab  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*d29b2c44Sab  * If applicable, add the following below this CDDL HEADER, with the
16*d29b2c44Sab  * fields enclosed by brackets "[]" replaced with your own identifying
17*d29b2c44Sab  * information: Portions Copyright [yyyy] [name of copyright owner]
18*d29b2c44Sab  *
19*d29b2c44Sab  * CDDL HEADER END
20*d29b2c44Sab  */
21*d29b2c44Sab 
22*d29b2c44Sab /*
23*d29b2c44Sab  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24*d29b2c44Sab  * Use is subject to license terms.
25*d29b2c44Sab  */
26*d29b2c44Sab #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*d29b2c44Sab 
28*d29b2c44Sab #define	ELF_TARGET_AMD64	/* SHN_AMD64_LCOMMON */
29*d29b2c44Sab 
30*d29b2c44Sab #include	<stdio.h>
31*d29b2c44Sab #include	<unistd.h>
32*d29b2c44Sab #include	<machdep.h>
33*d29b2c44Sab #include	<elfedit.h>
34*d29b2c44Sab #include	<strings.h>
35*d29b2c44Sab #include	<debug.h>
36*d29b2c44Sab #include	<conv.h>
37*d29b2c44Sab #include	<sym_msg.h>
38*d29b2c44Sab 
39*d29b2c44Sab 
40*d29b2c44Sab 
41*d29b2c44Sab 
42*d29b2c44Sab #define	MAXNDXSIZE	10
43*d29b2c44Sab 
44*d29b2c44Sab 
45*d29b2c44Sab 
46*d29b2c44Sab /*
47*d29b2c44Sab  * This module uses shared code for several of the commands.
48*d29b2c44Sab  * It is sometimes necessary to know which specific command
49*d29b2c44Sab  * is active.
50*d29b2c44Sab  */
51*d29b2c44Sab typedef enum {
52*d29b2c44Sab 	SYM_CMD_T_DUMP =		0,	/* sym:dump */
53*d29b2c44Sab 
54*d29b2c44Sab 	SYM_CMD_T_ST_BIND =		1,	/* sym:st_bind */
55*d29b2c44Sab 	SYM_CMD_T_ST_INFO =		2,	/* sym:st_info */
56*d29b2c44Sab 	SYM_CMD_T_ST_NAME =		3,	/* sym:st_name */
57*d29b2c44Sab 	SYM_CMD_T_ST_OTHER =		4,	/* sym:st_other */
58*d29b2c44Sab 	SYM_CMD_T_ST_SHNDX =		5,	/* sym:st_shndx */
59*d29b2c44Sab 	SYM_CMD_T_ST_SIZE =		6,	/* sym:st_size */
60*d29b2c44Sab 	SYM_CMD_T_ST_TYPE =		7,	/* sym:st_type */
61*d29b2c44Sab 	SYM_CMD_T_ST_VALUE =		8,	/* sym:st_value */
62*d29b2c44Sab 	SYM_CMD_T_ST_VISIBILITY =	9	/* sym:st_visibility */
63*d29b2c44Sab } SYM_CMD_T;
64*d29b2c44Sab 
65*d29b2c44Sab 
66*d29b2c44Sab 
67*d29b2c44Sab /*
68*d29b2c44Sab  * ELFCLASS-specific definitions
69*d29b2c44Sab  */
70*d29b2c44Sab #ifdef _ELF64
71*d29b2c44Sab 
72*d29b2c44Sab #define	MSG_FMT_XWORDVALNL MSG_FMT_XWORDVALNL_64
73*d29b2c44Sab 
74*d29b2c44Sab #else
75*d29b2c44Sab 
76*d29b2c44Sab #define	MSG_FMT_XWORDVALNL MSG_FMT_XWORDVALNL_32
77*d29b2c44Sab 
78*d29b2c44Sab /*
79*d29b2c44Sab  * We supply this function for the msg module. Only one copy is needed.
80*d29b2c44Sab  */
81*d29b2c44Sab const char *
82*d29b2c44Sab _sym_msg(Msg mid)
83*d29b2c44Sab {
84*d29b2c44Sab 	return (gettext(MSG_ORIG(mid)));
85*d29b2c44Sab }
86*d29b2c44Sab 
87*d29b2c44Sab #endif
88*d29b2c44Sab 
89*d29b2c44Sab 
90*d29b2c44Sab 
91*d29b2c44Sab /*
92*d29b2c44Sab  * This function is supplied to elfedit through our elfedit_module_t
93*d29b2c44Sab  * definition. It translates the opaque elfedit_i18nhdl_t handles
94*d29b2c44Sab  * in our module interface into the actual strings for elfedit to
95*d29b2c44Sab  * use.
96*d29b2c44Sab  *
97*d29b2c44Sab  * note:
98*d29b2c44Sab  *	This module uses Msg codes for its i18n handle type.
99*d29b2c44Sab  *	So the translation is simply to use MSG_INTL() to turn
100*d29b2c44Sab  *	it into a string and return it.
101*d29b2c44Sab  */
102*d29b2c44Sab static const char *
103*d29b2c44Sab mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
104*d29b2c44Sab {
105*d29b2c44Sab 	Msg msg = (Msg)hdl;
106*d29b2c44Sab 
107*d29b2c44Sab 	return (MSG_INTL(msg));
108*d29b2c44Sab }
109*d29b2c44Sab 
110*d29b2c44Sab 
111*d29b2c44Sab 
112*d29b2c44Sab /*
113*d29b2c44Sab  * The sym_opt_t enum specifies a bit value for every optional
114*d29b2c44Sab  * argument allowed by a command in this module.
115*d29b2c44Sab  */
116*d29b2c44Sab typedef enum {
117*d29b2c44Sab 	SYM_OPT_F_XSHINDEX =	1,	/* -e: Force shndx update to extended */
118*d29b2c44Sab 					/*	 index section */
119*d29b2c44Sab 	SYM_OPT_F_NAMOFFSET =	2,	/* -name_offset: sym:st_name name arg */
120*d29b2c44Sab 					/*	is numeric offset */
121*d29b2c44Sab 					/* 	rather than ASCII string */
122*d29b2c44Sab 	SYM_OPT_F_SECSHNDX =	4,	/* -secshndx: Section arg is */
123*d29b2c44Sab 					/*	section index, not name */
124*d29b2c44Sab 	SYM_OPT_F_SECSHTYP =	8,	/* -secshtyp: Section arg is */
125*d29b2c44Sab 					/*	section type, not name */
126*d29b2c44Sab 	SYM_OPT_F_SHNAME =	16,	/* -shnam name: section spec. by name */
127*d29b2c44Sab 	SYM_OPT_F_SHNDX =	32,	/* -shndx ndx: section spec. by index */
128*d29b2c44Sab 	SYM_OPT_F_SHTYP =	64,	/* -shtyp type: section spec. by type */
129*d29b2c44Sab 	SYM_OPT_F_SYMNDX =	128	/* -symndx: Sym specified by index */
130*d29b2c44Sab } sym_opt_t;
131*d29b2c44Sab 
132*d29b2c44Sab 
133*d29b2c44Sab /*
134*d29b2c44Sab  * A variable of type ARGSTATE is used by each command to maintain
135*d29b2c44Sab  * the overall state for a given set of arguments and the symbol tables
136*d29b2c44Sab  * being managed.
137*d29b2c44Sab  *
138*d29b2c44Sab  * The state for each symbol table and the auxiliary sections that are
139*d29b2c44Sab  * related to it are kept in a SYMSTATE sub-struct.
140*d29b2c44Sab  *
141*d29b2c44Sab  * One benefit of ARGSTATE is that it helps us to ensure that we only
142*d29b2c44Sab  * fetch each section a single time:
143*d29b2c44Sab  *	- More efficient
144*d29b2c44Sab  *	- Prevents multiple ELFEDIT_MSG_DEBUG messages from
145*d29b2c44Sab  *	  being produced for a given section.
146*d29b2c44Sab  *
147*d29b2c44Sab  * note: The symstate array in ARGSTATE is defined as having one
148*d29b2c44Sab  *	element, but in reality, we allocate enough room for
149*d29b2c44Sab  *	the number of elements defined in the numsymstate field.
150*d29b2c44Sab  */
151*d29b2c44Sab typedef struct {
152*d29b2c44Sab 	Word ndx;	/* If argstate.argc > 0, this is the table index */
153*d29b2c44Sab 	struct {				/* Symbol table */
154*d29b2c44Sab 		elfedit_section_t	*sec;
155*d29b2c44Sab 		Sym			*data;
156*d29b2c44Sab 		Word			n;
157*d29b2c44Sab 	} sym;
158*d29b2c44Sab 	struct {				/* String table */
159*d29b2c44Sab 		elfedit_section_t	*sec;
160*d29b2c44Sab 	} str;
161*d29b2c44Sab 	struct {				/* Versym */
162*d29b2c44Sab 		Word			shndx;
163*d29b2c44Sab 		elfedit_section_t	*sec;
164*d29b2c44Sab 		Versym			*data;
165*d29b2c44Sab 		Word			n;
166*d29b2c44Sab 	} versym;
167*d29b2c44Sab 	struct {				/* Extended section indices */
168*d29b2c44Sab 		Word			shndx;
169*d29b2c44Sab 		elfedit_section_t	*sec;
170*d29b2c44Sab 		Word			*data;
171*d29b2c44Sab 		Word			n;
172*d29b2c44Sab 	} xshndx;
173*d29b2c44Sab } SYMSTATE;
174*d29b2c44Sab typedef struct {
175*d29b2c44Sab 	elfedit_obj_state_t	*obj_state;
176*d29b2c44Sab 	sym_opt_t		optmask;   	/* Mask of options used */
177*d29b2c44Sab 	int			argc;		/* # of plain arguments */
178*d29b2c44Sab 	const char		**argv;		/* Plain arguments */
179*d29b2c44Sab 	int			numsymstate;	/* # of items in symstate[] */
180*d29b2c44Sab 	SYMSTATE		symstate[1];	/* Symbol tables to process */
181*d29b2c44Sab } ARGSTATE;
182*d29b2c44Sab 
183*d29b2c44Sab 
184*d29b2c44Sab /*
185*d29b2c44Sab  * We maintain the state of each symbol table and related associated
186*d29b2c44Sab  * sections in a SYMSTATE structure . We don't look those auxiliary
187*d29b2c44Sab  * things up unless we actually need them, both to be efficient,
188*d29b2c44Sab  * and to prevent duplicate ELFEDIT_MSG_DEBUG messages from being
189*d29b2c44Sab  * issued as they are located. Hence, process_args() is used to
190*d29b2c44Sab  * initialize the state block with just the symbol table, and then one
191*d29b2c44Sab  * of the argstate_add_XXX() functions is used as needed
192*d29b2c44Sab  * to fetch the additional sections.
193*d29b2c44Sab  *
194*d29b2c44Sab  * entry:
195*d29b2c44Sab  *	argstate - Overall state block
196*d29b2c44Sab  *	symstate - State block for current symbol table.
197*d29b2c44Sab  *
198*d29b2c44Sab  * exit:
199*d29b2c44Sab  *	If the needed auxiliary section is not found, an error is
200*d29b2c44Sab  *	issued and the argstate_add_XXX() routine does not return.
201*d29b2c44Sab  *	Otherwise, the fields in argstate have been filled in, ready
202*d29b2c44Sab  *	for use.
203*d29b2c44Sab  *
204*d29b2c44Sab  */
205*d29b2c44Sab static void
206*d29b2c44Sab symstate_add_str(ARGSTATE *argstate, SYMSTATE *symstate)
207*d29b2c44Sab {
208*d29b2c44Sab 	if (symstate->str.sec != NULL)
209*d29b2c44Sab 		return;
210*d29b2c44Sab 
211*d29b2c44Sab 	symstate->str.sec = elfedit_sec_getstr(argstate->obj_state,
212*d29b2c44Sab 	    symstate->sym.sec->sec_shdr->sh_link);
213*d29b2c44Sab }
214*d29b2c44Sab static void
215*d29b2c44Sab symstate_add_versym(ARGSTATE *argstate, SYMSTATE *symstate)
216*d29b2c44Sab {
217*d29b2c44Sab 	if (symstate->versym.sec != NULL)
218*d29b2c44Sab 		return;
219*d29b2c44Sab 
220*d29b2c44Sab 	symstate->versym.sec = elfedit_sec_getversym(argstate->obj_state,
221*d29b2c44Sab 	    symstate->sym.sec, &symstate->versym.data, &symstate->versym.n);
222*d29b2c44Sab }
223*d29b2c44Sab static void
224*d29b2c44Sab symstate_add_xshndx(ARGSTATE *argstate, SYMSTATE *symstate)
225*d29b2c44Sab {
226*d29b2c44Sab 	if (symstate->xshndx.sec != NULL)
227*d29b2c44Sab 		return;
228*d29b2c44Sab 
229*d29b2c44Sab 	symstate->xshndx.sec = elfedit_sec_getxshndx(argstate->obj_state,
230*d29b2c44Sab 	    symstate->sym.sec, &symstate->xshndx.data, &symstate->xshndx.n);
231*d29b2c44Sab }
232*d29b2c44Sab 
233*d29b2c44Sab 
234*d29b2c44Sab 
235*d29b2c44Sab /*
236*d29b2c44Sab  * Display symbol table entries in the style used by elfdump.
237*d29b2c44Sab  *
238*d29b2c44Sab  * entry:
239*d29b2c44Sab  *	argstate - Overall state block
240*d29b2c44Sab  *	symstate - State block for current symbol table.
241*d29b2c44Sab  *	ndx - Index of first symbol to display
242*d29b2c44Sab  *	cnt - Number of symbols to display
243*d29b2c44Sab  */
244*d29b2c44Sab static void
245*d29b2c44Sab dump_symtab(ARGSTATE *argstate, SYMSTATE *symstate, Word ndx, Word cnt)
246*d29b2c44Sab {
247*d29b2c44Sab 	char			index[MAXNDXSIZE];
248*d29b2c44Sab 	Word			shndx;
249*d29b2c44Sab 	const char		*shndx_name;
250*d29b2c44Sab 	elfedit_section_t	*symsec;
251*d29b2c44Sab 	elfedit_section_t	*strsec;
252*d29b2c44Sab 	Sym			*sym;
253*d29b2c44Sab 	elfedit_obj_state_t	*obj_state = argstate->obj_state;
254*d29b2c44Sab 	Half			mach = obj_state->os_ehdr->e_machine;
255*d29b2c44Sab 	const char		*symname;
256*d29b2c44Sab 	Versym			versym;
257*d29b2c44Sab 
258*d29b2c44Sab 	symsec = symstate->sym.sec;
259*d29b2c44Sab 	sym = symstate->sym.data + ndx;
260*d29b2c44Sab 
261*d29b2c44Sab 	symstate_add_str(argstate, symstate);
262*d29b2c44Sab 	strsec = symstate->str.sec;
263*d29b2c44Sab 
264*d29b2c44Sab 	/* If there is a versym index section, fetch it */
265*d29b2c44Sab 	if (symstate->versym.shndx != SHN_UNDEF)
266*d29b2c44Sab 		symstate_add_versym(argstate, symstate);
267*d29b2c44Sab 
268*d29b2c44Sab 	/* If there is an extended index section, fetch it */
269*d29b2c44Sab 	if (symstate->xshndx.shndx != SHN_UNDEF)
270*d29b2c44Sab 		symstate_add_xshndx(argstate, symstate);
271*d29b2c44Sab 
272*d29b2c44Sab 	elfedit_printf(MSG_INTL(MSG_FMT_SYMTAB), symsec->sec_name);
273*d29b2c44Sab 	Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
274*d29b2c44Sab 	for (; cnt-- > 0; ndx++, sym++) {
275*d29b2c44Sab 		(void) snprintf(index, MAXNDXSIZE,
276*d29b2c44Sab 		    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(ndx));
277*d29b2c44Sab 		versym = (symstate->versym.sec == NULL) ? 0 :
278*d29b2c44Sab 		    symstate->versym.data[ndx];
279*d29b2c44Sab 		symname = elfedit_offset_to_str(strsec, sym->st_name,
280*d29b2c44Sab 		    ELFEDIT_MSG_DEBUG, 0);
281*d29b2c44Sab 		shndx = sym->st_shndx;
282*d29b2c44Sab 		if ((shndx == SHN_XINDEX) && (symstate->xshndx.sec != NULL))
283*d29b2c44Sab 			shndx = symstate->xshndx.data[ndx];
284*d29b2c44Sab 		shndx_name = elfedit_shndx_to_name(obj_state, shndx);
285*d29b2c44Sab 		Elf_syms_table_entry(NULL, ELF_DBG_ELFDUMP, index, mach,
286*d29b2c44Sab 		    sym, versym, 0, shndx_name, symname);
287*d29b2c44Sab 	}
288*d29b2c44Sab }
289*d29b2c44Sab 
290*d29b2c44Sab 
291*d29b2c44Sab 
292*d29b2c44Sab /*
293*d29b2c44Sab  * Called by print_sym() to determine if a given symbol has the same
294*d29b2c44Sab  * display value for the current command in every symbol table.
295*d29b2c44Sab  *
296*d29b2c44Sab  * entry:
297*d29b2c44Sab  *	cmd - SYM_CMD_T_* value giving identify of caller
298*d29b2c44Sab  *	argstate - Overall state block
299*d29b2c44Sab  *	outstyle - Output style to use
300*d29b2c44Sab  */
301*d29b2c44Sab static int
302*d29b2c44Sab all_same(SYM_CMD_T cmd, ARGSTATE *argstate, elfedit_outstyle_t outstyle)
303*d29b2c44Sab {
304*d29b2c44Sab 	Word			tblndx;
305*d29b2c44Sab 	SYMSTATE		*symstate1, *symstate2;
306*d29b2c44Sab 	Sym			*sym1, *sym2;
307*d29b2c44Sab 
308*d29b2c44Sab 	symstate1 = argstate->symstate;
309*d29b2c44Sab 	for (tblndx = 0; tblndx < (argstate->numsymstate - 1);
310*d29b2c44Sab 	    tblndx++, symstate1++) {
311*d29b2c44Sab 		symstate2 = symstate1 + 1;
312*d29b2c44Sab 		sym1 = &symstate1->sym.data[symstate1->ndx];
313*d29b2c44Sab 		sym2 = &symstate2->sym.data[symstate2->ndx];
314*d29b2c44Sab 
315*d29b2c44Sab 		switch (cmd) {
316*d29b2c44Sab 		case SYM_CMD_T_DUMP:
317*d29b2c44Sab 			/* sym:dump should always show everything */
318*d29b2c44Sab 			return (0);
319*d29b2c44Sab 
320*d29b2c44Sab 		case SYM_CMD_T_ST_BIND:
321*d29b2c44Sab 			if (ELF_ST_BIND(sym1->st_info) !=
322*d29b2c44Sab 			    ELF_ST_BIND(sym2->st_info))
323*d29b2c44Sab 				return (0);
324*d29b2c44Sab 			break;
325*d29b2c44Sab 
326*d29b2c44Sab 		case SYM_CMD_T_ST_INFO:
327*d29b2c44Sab 			if (sym1->st_info !=  sym2->st_info)
328*d29b2c44Sab 				return (0);
329*d29b2c44Sab 			break;
330*d29b2c44Sab 
331*d29b2c44Sab 		case SYM_CMD_T_ST_NAME:
332*d29b2c44Sab 			/*
333*d29b2c44Sab 			 * In simple output mode, we show the string. In
334*d29b2c44Sab 			 * numeric mode, we show the string table offset.
335*d29b2c44Sab 			 */
336*d29b2c44Sab 			if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
337*d29b2c44Sab 				const char *n1, *n2;
338*d29b2c44Sab 
339*d29b2c44Sab 				symstate_add_str(argstate, symstate1);
340*d29b2c44Sab 				symstate_add_str(argstate, symstate2);
341*d29b2c44Sab 				n1 = elfedit_offset_to_str(symstate1->str.sec,
342*d29b2c44Sab 				    sym1->st_name, ELFEDIT_MSG_DEBUG, 0);
343*d29b2c44Sab 				n2 = elfedit_offset_to_str(symstate2->str.sec,
344*d29b2c44Sab 				    sym2->st_name, ELFEDIT_MSG_DEBUG, 0);
345*d29b2c44Sab 				if (strcmp(n1, n2) != 0)
346*d29b2c44Sab 					return (0);
347*d29b2c44Sab 			} else {
348*d29b2c44Sab 				if (sym1->st_name !=  sym2->st_name)
349*d29b2c44Sab 					return (0);
350*d29b2c44Sab 			}
351*d29b2c44Sab 			break;
352*d29b2c44Sab 
353*d29b2c44Sab 		case SYM_CMD_T_ST_OTHER:
354*d29b2c44Sab 			if (sym1->st_other !=  sym2->st_other)
355*d29b2c44Sab 				return (0);
356*d29b2c44Sab 			break;
357*d29b2c44Sab 
358*d29b2c44Sab 		case SYM_CMD_T_ST_SHNDX:
359*d29b2c44Sab 			{
360*d29b2c44Sab 				Word	ndx1, ndx2;
361*d29b2c44Sab 
362*d29b2c44Sab 				ndx1 = sym1->st_shndx;
363*d29b2c44Sab 				if ((ndx1 == SHN_XINDEX) &&
364*d29b2c44Sab 				    (symstate1->xshndx.shndx != SHN_UNDEF)) {
365*d29b2c44Sab 					symstate_add_xshndx(argstate,
366*d29b2c44Sab 					    symstate1);
367*d29b2c44Sab 					ndx1 = symstate1->xshndx.
368*d29b2c44Sab 					    data[symstate1->ndx];
369*d29b2c44Sab 				}
370*d29b2c44Sab 				ndx2 = sym2->st_shndx;
371*d29b2c44Sab 				if ((ndx2 == SHN_XINDEX) &&
372*d29b2c44Sab 				    (symstate2->xshndx.shndx != SHN_UNDEF)) {
373*d29b2c44Sab 					symstate_add_xshndx(argstate,
374*d29b2c44Sab 					    symstate2);
375*d29b2c44Sab 					ndx2 = symstate2->xshndx.
376*d29b2c44Sab 					    data[symstate2->ndx];
377*d29b2c44Sab 				}
378*d29b2c44Sab 				if (ndx1 !=  ndx2)
379*d29b2c44Sab 					return (0);
380*d29b2c44Sab 			}
381*d29b2c44Sab 			break;
382*d29b2c44Sab 
383*d29b2c44Sab 		case SYM_CMD_T_ST_SIZE:
384*d29b2c44Sab 			if (sym1->st_size !=  sym2->st_size)
385*d29b2c44Sab 				return (0);
386*d29b2c44Sab 			break;
387*d29b2c44Sab 
388*d29b2c44Sab 		case SYM_CMD_T_ST_TYPE:
389*d29b2c44Sab 			if (ELF_ST_TYPE(sym1->st_info) !=
390*d29b2c44Sab 			    ELF_ST_TYPE(sym2->st_info))
391*d29b2c44Sab 				return (0);
392*d29b2c44Sab 			break;
393*d29b2c44Sab 
394*d29b2c44Sab 		case SYM_CMD_T_ST_VALUE:
395*d29b2c44Sab 			if (sym1->st_value !=  sym2->st_value)
396*d29b2c44Sab 				return (0);
397*d29b2c44Sab 			break;
398*d29b2c44Sab 
399*d29b2c44Sab 		case SYM_CMD_T_ST_VISIBILITY:
400*d29b2c44Sab 			if (ELF_ST_VISIBILITY(sym1->st_info) !=
401*d29b2c44Sab 			    ELF_ST_VISIBILITY(sym2->st_info))
402*d29b2c44Sab 				return (0);
403*d29b2c44Sab 			break;
404*d29b2c44Sab 		}
405*d29b2c44Sab 	}
406*d29b2c44Sab 
407*d29b2c44Sab 	/* If we got here, there are no differences (or maybe only 1 table */
408*d29b2c44Sab 	return (1);
409*d29b2c44Sab }
410*d29b2c44Sab 
411*d29b2c44Sab 
412*d29b2c44Sab /*
413*d29b2c44Sab  * Called by print_sym() to display values for a single symbol table.
414*d29b2c44Sab  *
415*d29b2c44Sab  * entry:
416*d29b2c44Sab  *	autoprint - If True, output is only produced if the elfedit
417*d29b2c44Sab  *		autoprint flag is set. If False, output is always produced.
418*d29b2c44Sab  *	cmd - SYM_CMD_T_* value giving identify of caller
419*d29b2c44Sab  *	argstate - Overall state block
420*d29b2c44Sab  *	symstate - State block for current symbol table.
421*d29b2c44Sab  *	ndx - Index of first symbol to display
422*d29b2c44Sab  *	cnt - Number of symbols to display
423*d29b2c44Sab  */
424*d29b2c44Sab static void
425*d29b2c44Sab print_symstate(SYM_CMD_T cmd, ARGSTATE *argstate, SYMSTATE *symstate,
426*d29b2c44Sab     elfedit_outstyle_t outstyle, Word ndx, Word cnt)
427*d29b2c44Sab {
428*d29b2c44Sab 	Word	value;
429*d29b2c44Sab 	Sym	*sym;
430*d29b2c44Sab 
431*d29b2c44Sab 	/*
432*d29b2c44Sab 	 * If doing default output, use elfdump style where we
433*d29b2c44Sab 	 * show all symbol attributes. In this case, the command
434*d29b2c44Sab 	 * that called us doesn't matter
435*d29b2c44Sab 	 */
436*d29b2c44Sab 	if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
437*d29b2c44Sab 		dump_symtab(argstate, symstate, ndx, cnt);
438*d29b2c44Sab 		return;
439*d29b2c44Sab 	}
440*d29b2c44Sab 
441*d29b2c44Sab 	sym = symstate->sym.data;
442*d29b2c44Sab 
443*d29b2c44Sab 	switch (cmd) {
444*d29b2c44Sab 	case SYM_CMD_T_ST_BIND:
445*d29b2c44Sab 		{
446*d29b2c44Sab 			Conv_inv_buf_t inv_buf;
447*d29b2c44Sab 
448*d29b2c44Sab 			for (sym += ndx; cnt--; sym++) {
449*d29b2c44Sab 				value = ELF_ST_BIND(sym->st_info);
450*d29b2c44Sab 				if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
451*d29b2c44Sab 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
452*d29b2c44Sab 					    conv_sym_info_bind(value,
453*d29b2c44Sab 					    CONV_FMT_ALT_FULLNAME, &inv_buf));
454*d29b2c44Sab 				} else {
455*d29b2c44Sab 					elfedit_printf(
456*d29b2c44Sab 					    MSG_ORIG(MSG_FMT_WORDVALNL),
457*d29b2c44Sab 					    EC_WORD(value));
458*d29b2c44Sab 				}
459*d29b2c44Sab 			}
460*d29b2c44Sab 		}
461*d29b2c44Sab 		return;
462*d29b2c44Sab 
463*d29b2c44Sab 	case SYM_CMD_T_ST_INFO:
464*d29b2c44Sab 		for (sym += ndx; cnt-- > 0; sym++)
465*d29b2c44Sab 			elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
466*d29b2c44Sab 			    EC_WORD(sym->st_info));
467*d29b2c44Sab 		return;
468*d29b2c44Sab 
469*d29b2c44Sab 	case SYM_CMD_T_ST_NAME:
470*d29b2c44Sab 		/*
471*d29b2c44Sab 		 * In simple output mode, we show the string. In numeric
472*d29b2c44Sab 		 * mode, we show the string table offset.
473*d29b2c44Sab 		 */
474*d29b2c44Sab 		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
475*d29b2c44Sab 			symstate_add_str(argstate, symstate);
476*d29b2c44Sab 			for (sym += ndx; cnt--; sym++) {
477*d29b2c44Sab 				elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
478*d29b2c44Sab 				    elfedit_offset_to_str(symstate->str.sec,
479*d29b2c44Sab 				    sym->st_name, ELFEDIT_MSG_ERR, 0));
480*d29b2c44Sab 			}
481*d29b2c44Sab 		} else {
482*d29b2c44Sab 			for (; cnt--; sym++)
483*d29b2c44Sab 				elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
484*d29b2c44Sab 				    EC_WORD(sym->st_name));
485*d29b2c44Sab 		}
486*d29b2c44Sab 		return;
487*d29b2c44Sab 
488*d29b2c44Sab 	case SYM_CMD_T_ST_OTHER:
489*d29b2c44Sab 		for (sym += ndx; cnt-- > 0; sym++)
490*d29b2c44Sab 			elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
491*d29b2c44Sab 			    EC_WORD(sym->st_other));
492*d29b2c44Sab 		return;
493*d29b2c44Sab 
494*d29b2c44Sab 	case SYM_CMD_T_ST_SHNDX:
495*d29b2c44Sab 		/* If there is an extended index section, fetch it */
496*d29b2c44Sab 		if (symstate->xshndx.shndx != SHN_UNDEF)
497*d29b2c44Sab 			symstate_add_xshndx(argstate, symstate);
498*d29b2c44Sab 
499*d29b2c44Sab 		for (; cnt--; ndx++) {
500*d29b2c44Sab 			value = sym[ndx].st_shndx;
501*d29b2c44Sab 			if ((value == SHN_XINDEX) &&
502*d29b2c44Sab 			    (symstate->xshndx.sec != NULL))
503*d29b2c44Sab 				value = symstate->xshndx.data[ndx];
504*d29b2c44Sab 
505*d29b2c44Sab 			if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
506*d29b2c44Sab 				elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
507*d29b2c44Sab 				    elfedit_shndx_to_name(argstate->obj_state,
508*d29b2c44Sab 				    value));
509*d29b2c44Sab 			} else {
510*d29b2c44Sab 				elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
511*d29b2c44Sab 				    EC_WORD(value));
512*d29b2c44Sab 			}
513*d29b2c44Sab 		}
514*d29b2c44Sab 		return;
515*d29b2c44Sab 
516*d29b2c44Sab 	case SYM_CMD_T_ST_SIZE:
517*d29b2c44Sab 		/*
518*d29b2c44Sab 		 * machine word width integers displayed in fixed width
519*d29b2c44Sab 		 * 0-filled hex format.
520*d29b2c44Sab 		 */
521*d29b2c44Sab 		for (sym += ndx; cnt--; sym++)
522*d29b2c44Sab 			elfedit_printf(MSG_ORIG(MSG_FMT_XWORDVALNL),
523*d29b2c44Sab 			    sym->st_size);
524*d29b2c44Sab 		return;
525*d29b2c44Sab 
526*d29b2c44Sab 	case SYM_CMD_T_ST_TYPE:
527*d29b2c44Sab 		{
528*d29b2c44Sab 			Half mach = argstate->obj_state->os_ehdr->e_machine;
529*d29b2c44Sab 			Conv_inv_buf_t inv_buf;
530*d29b2c44Sab 
531*d29b2c44Sab 			for (sym += ndx; cnt--; sym++) {
532*d29b2c44Sab 				value = ELF_ST_TYPE(sym->st_info);
533*d29b2c44Sab 				if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
534*d29b2c44Sab 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
535*d29b2c44Sab 					    conv_sym_info_type(mach, value,
536*d29b2c44Sab 					    CONV_FMT_ALT_FULLNAME, &inv_buf));
537*d29b2c44Sab 				} else {
538*d29b2c44Sab 					elfedit_printf(
539*d29b2c44Sab 					    MSG_ORIG(MSG_FMT_WORDVALNL),
540*d29b2c44Sab 					    EC_WORD(value));
541*d29b2c44Sab 				}
542*d29b2c44Sab 			}
543*d29b2c44Sab 		}
544*d29b2c44Sab 		return;
545*d29b2c44Sab 
546*d29b2c44Sab 	case SYM_CMD_T_ST_VALUE:
547*d29b2c44Sab 		/*
548*d29b2c44Sab 		 * machine word width integers displayed in fixed width
549*d29b2c44Sab 		 * 0-filled hex format.
550*d29b2c44Sab 		 */
551*d29b2c44Sab 		for (sym += ndx; cnt--; sym++)
552*d29b2c44Sab 			elfedit_printf(MSG_ORIG(MSG_FMT_XWORDVALNL),
553*d29b2c44Sab 			    sym->st_value);
554*d29b2c44Sab 		return;
555*d29b2c44Sab 
556*d29b2c44Sab 	case SYM_CMD_T_ST_VISIBILITY:
557*d29b2c44Sab 		{
558*d29b2c44Sab 			Conv_inv_buf_t inv_buf;
559*d29b2c44Sab 
560*d29b2c44Sab 			for (sym += ndx; cnt--; sym++) {
561*d29b2c44Sab 				value = ELF_ST_VISIBILITY(sym->st_other);
562*d29b2c44Sab 				if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
563*d29b2c44Sab 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
564*d29b2c44Sab 					    conv_sym_other_vis(value,
565*d29b2c44Sab 					    CONV_FMT_ALT_FULLNAME, &inv_buf));
566*d29b2c44Sab 				} else {
567*d29b2c44Sab 					elfedit_printf(
568*d29b2c44Sab 					    MSG_ORIG(MSG_FMT_WORDVALNL),
569*d29b2c44Sab 					    EC_WORD(value));
570*d29b2c44Sab 				}
571*d29b2c44Sab 			}
572*d29b2c44Sab 		}
573*d29b2c44Sab 		return;
574*d29b2c44Sab 
575*d29b2c44Sab 	}
576*d29b2c44Sab }
577*d29b2c44Sab 
578*d29b2c44Sab 
579*d29b2c44Sab /*
580*d29b2c44Sab  * Print symbol values, taking the calling command, and output style
581*d29b2c44Sab  * into account.
582*d29b2c44Sab  *
583*d29b2c44Sab  * entry:
584*d29b2c44Sab  *	autoprint - If True, output is only produced if the elfedit
585*d29b2c44Sab  *		autoprint flag is set. If False, output is always produced.
586*d29b2c44Sab  *	cmd - SYM_CMD_T_* value giving identify of caller
587*d29b2c44Sab  *	argstate - Overall state block
588*d29b2c44Sab  *	symstate - State block for current symbol table.
589*d29b2c44Sab  *	ndx - Index of first symbol to display
590*d29b2c44Sab  *	cnt - Number of symbols to display
591*d29b2c44Sab  */
592*d29b2c44Sab static void
593*d29b2c44Sab print_sym(SYM_CMD_T cmd, int autoprint, ARGSTATE *argstate)
594*d29b2c44Sab {
595*d29b2c44Sab 	Word			ndx, tblndx;
596*d29b2c44Sab 	Word			cnt;
597*d29b2c44Sab 	elfedit_outstyle_t	outstyle;
598*d29b2c44Sab 	SYMSTATE		*symstate;
599*d29b2c44Sab 	int			only_one;
600*d29b2c44Sab 
601*d29b2c44Sab 	if ((autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)))
602*d29b2c44Sab 		return;
603*d29b2c44Sab 
604*d29b2c44Sab 	/*
605*d29b2c44Sab 	 * Pick an output style. sym:dump is required to use the default
606*d29b2c44Sab 	 * style. The other commands use the current output style.
607*d29b2c44Sab 	 */
608*d29b2c44Sab 	outstyle = (cmd == SYM_CMD_T_DUMP) ?
609*d29b2c44Sab 	    ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
610*d29b2c44Sab 
611*d29b2c44Sab 	/*
612*d29b2c44Sab 	 * This is a nicity: Force any needed auxiliary sections to be
613*d29b2c44Sab 	 * fetched here before any output is produced. This will put all
614*d29b2c44Sab 	 * of the debug messages right at the top in a single cluster.
615*d29b2c44Sab 	 */
616*d29b2c44Sab 	symstate = argstate->symstate;
617*d29b2c44Sab 	for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) {
618*d29b2c44Sab 		if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
619*d29b2c44Sab 			symstate_add_str(argstate, symstate);
620*d29b2c44Sab 			if (symstate->versym.shndx != SHN_UNDEF)
621*d29b2c44Sab 				symstate_add_versym(argstate, symstate);
622*d29b2c44Sab 			if (symstate->xshndx.shndx != SHN_UNDEF)
623*d29b2c44Sab 				symstate_add_xshndx(argstate, symstate);
624*d29b2c44Sab 			continue;
625*d29b2c44Sab 		}
626*d29b2c44Sab 
627*d29b2c44Sab 		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
628*d29b2c44Sab 			switch (cmd) {
629*d29b2c44Sab 			case SYM_CMD_T_ST_NAME:
630*d29b2c44Sab 				symstate_add_str(argstate, symstate);
631*d29b2c44Sab 				break;
632*d29b2c44Sab 
633*d29b2c44Sab 			case SYM_CMD_T_ST_SHNDX:
634*d29b2c44Sab 				if (symstate->xshndx.shndx != SHN_UNDEF)
635*d29b2c44Sab 					symstate_add_xshndx(argstate, symstate);
636*d29b2c44Sab 				break;
637*d29b2c44Sab 			}
638*d29b2c44Sab 		}
639*d29b2c44Sab 	}
640*d29b2c44Sab 
641*d29b2c44Sab 	/*
642*d29b2c44Sab 	 * If there is more than one table, we are displaying a single
643*d29b2c44Sab 	 * item, we are not using the default "elfdump" style, and all
644*d29b2c44Sab 	 * the symbols have the same value for the thing we intend to
645*d29b2c44Sab 	 * display, then we only want to display it once.
646*d29b2c44Sab 	 */
647*d29b2c44Sab 	only_one = (argstate->numsymstate > 1) && (argstate->argc > 0) &&
648*d29b2c44Sab 	    (outstyle != ELFEDIT_OUTSTYLE_DEFAULT) &&
649*d29b2c44Sab 	    all_same(cmd, argstate, outstyle);
650*d29b2c44Sab 
651*d29b2c44Sab 	/* Run through the tables and display from each one */
652*d29b2c44Sab 	symstate = argstate->symstate;
653*d29b2c44Sab 	for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) {
654*d29b2c44Sab 		if (argstate->argc == 0) {
655*d29b2c44Sab 			ndx = 0;
656*d29b2c44Sab 			cnt = symstate->sym.n;
657*d29b2c44Sab 		} else {
658*d29b2c44Sab 			ndx = symstate->ndx;
659*d29b2c44Sab 			cnt = 1;
660*d29b2c44Sab 		}
661*d29b2c44Sab 
662*d29b2c44Sab 		if ((tblndx > 0) && ((argstate->argc == 0) ||
663*d29b2c44Sab 		    (outstyle == ELFEDIT_OUTSTYLE_DEFAULT)))
664*d29b2c44Sab 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
665*d29b2c44Sab 
666*d29b2c44Sab 		print_symstate(cmd, argstate, symstate, outstyle, ndx, cnt);
667*d29b2c44Sab 		if (only_one)
668*d29b2c44Sab 			break;
669*d29b2c44Sab 	}
670*d29b2c44Sab }
671*d29b2c44Sab 
672*d29b2c44Sab 
673*d29b2c44Sab /*
674*d29b2c44Sab  * The cmd_body_set_st_XXX() functions are for use by cmd_body().
675*d29b2c44Sab  * They handle the case where the second plain argument is
676*d29b2c44Sab  * a value to be stored in the symbol.
677*d29b2c44Sab  *
678*d29b2c44Sab  * entry:
679*d29b2c44Sab  *	argstate - Overall state block
680*d29b2c44Sab  *	symstate - State block for current symbol table.
681*d29b2c44Sab  */
682*d29b2c44Sab static elfedit_cmdret_t
683*d29b2c44Sab cmd_body_set_st_bind(ARGSTATE *argstate, SYMSTATE *symstate)
684*d29b2c44Sab {
685*d29b2c44Sab 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
686*d29b2c44Sab 	Sym			*sym = &symstate->sym.data[symstate->ndx];
687*d29b2c44Sab 	Word			gbl_ndx;
688*d29b2c44Sab 	uchar_t			bind, type, old_bind;
689*d29b2c44Sab 	Word			symndx;
690*d29b2c44Sab 	Conv_inv_buf_t		inv_buf1, inv_buf2;
691*d29b2c44Sab 
692*d29b2c44Sab 	/*
693*d29b2c44Sab 	 * Use the ELF_ST_BIND() macro to access the defined bits
694*d29b2c44Sab 	 * of the st_info field related to symbol binding.
695*d29b2c44Sab 	 * Accepts STB_ symbolic names as well as integers.
696*d29b2c44Sab 	 */
697*d29b2c44Sab 	bind = elfedit_atoconst_range(argstate->argv[1],
698*d29b2c44Sab 	    MSG_INTL(MSG_ARG_SYMBIND), 0, 15, ELFEDIT_CONST_STB);
699*d29b2c44Sab 	old_bind = ELF_ST_BIND(sym->st_info);
700*d29b2c44Sab 	type = ELF_ST_TYPE(sym->st_info);
701*d29b2c44Sab 
702*d29b2c44Sab 	if (old_bind == bind) {
703*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK),
704*d29b2c44Sab 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
705*d29b2c44Sab 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_BIND),
706*d29b2c44Sab 		    conv_sym_info_bind(bind, CONV_FMT_ALT_FULLNAME, &inv_buf1));
707*d29b2c44Sab 	} else {
708*d29b2c44Sab 		/*
709*d29b2c44Sab 		 * The sh_info field of the symbol table section header
710*d29b2c44Sab 		 * gives the index of the first non-local symbol in
711*d29b2c44Sab 		 * the table. Issue warnings if the binding we set
712*d29b2c44Sab 		 * contradicts this.
713*d29b2c44Sab 		 */
714*d29b2c44Sab 		gbl_ndx = symstate->sym.sec->sec_shdr->sh_info;
715*d29b2c44Sab 		symndx = symstate->sym.sec->sec_shndx;
716*d29b2c44Sab 		if ((bind == STB_LOCAL) && (symstate->ndx >= gbl_ndx))
717*d29b2c44Sab 			elfedit_msg(ELFEDIT_MSG_DEBUG,
718*d29b2c44Sab 			    MSG_INTL(MSG_DEBUG_LBINDGSYM),
719*d29b2c44Sab 			    EC_WORD(symndx), symstate->sym.sec->sec_name,
720*d29b2c44Sab 			    symstate->ndx, EC_WORD(symndx), gbl_ndx);
721*d29b2c44Sab 		if ((bind != STB_LOCAL) && (symstate->ndx < gbl_ndx))
722*d29b2c44Sab 			elfedit_msg(ELFEDIT_MSG_DEBUG,
723*d29b2c44Sab 			    MSG_INTL(MSG_DEBUG_GBINDLSYM),
724*d29b2c44Sab 			    EC_WORD(symndx), symstate->sym.sec->sec_name,
725*d29b2c44Sab 			    symstate->ndx, EC_WORD(symndx), gbl_ndx);
726*d29b2c44Sab 
727*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG),
728*d29b2c44Sab 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
729*d29b2c44Sab 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_BIND),
730*d29b2c44Sab 		    conv_sym_info_bind(old_bind, CONV_FMT_ALT_FULLNAME,
731*d29b2c44Sab 		    &inv_buf1),
732*d29b2c44Sab 		    conv_sym_info_bind(bind, CONV_FMT_ALT_FULLNAME, &inv_buf2));
733*d29b2c44Sab 		ret = ELFEDIT_CMDRET_MOD;
734*d29b2c44Sab 		sym->st_info = ELF_ST_INFO(bind, type);
735*d29b2c44Sab 	}
736*d29b2c44Sab 
737*d29b2c44Sab 	return (ret);
738*d29b2c44Sab }
739*d29b2c44Sab 
740*d29b2c44Sab static elfedit_cmdret_t
741*d29b2c44Sab cmd_body_set_st_name(ARGSTATE *argstate, SYMSTATE *symstate)
742*d29b2c44Sab {
743*d29b2c44Sab 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
744*d29b2c44Sab 	Sym			*sym = &symstate->sym.data[symstate->ndx];
745*d29b2c44Sab 	Word	str_offset;
746*d29b2c44Sab 
747*d29b2c44Sab 	/*
748*d29b2c44Sab 	 * If -n was specified, this is an offset into the string
749*d29b2c44Sab 	 * table. Otherwise it is a string we need to turn into
750*d29b2c44Sab 	 * an offset
751*d29b2c44Sab 	 */
752*d29b2c44Sab 	symstate_add_str(argstate, symstate);
753*d29b2c44Sab 	if (argstate->optmask & SYM_OPT_F_NAMOFFSET) {
754*d29b2c44Sab 		str_offset = elfedit_atoui(argstate->argv[1], NULL);
755*d29b2c44Sab 		/* Warn if the offset is out of range */
756*d29b2c44Sab 		(void) elfedit_offset_to_str(symstate->str.sec,
757*d29b2c44Sab 		    str_offset, ELFEDIT_MSG_DEBUG, 1);
758*d29b2c44Sab 	} else {
759*d29b2c44Sab 		str_offset = elfedit_strtab_insert(argstate->obj_state,
760*d29b2c44Sab 		    symstate->str.sec, NULL, argstate->argv[1]);
761*d29b2c44Sab 	}
762*d29b2c44Sab 
763*d29b2c44Sab 	if (sym->st_name == str_offset) {
764*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_D_OK),
765*d29b2c44Sab 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
766*d29b2c44Sab 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_NAME),
767*d29b2c44Sab 		    EC_WORD(sym->st_name));
768*d29b2c44Sab 	} else {
769*d29b2c44Sab 		/*
770*d29b2c44Sab 		 * Warn the user: Changing the name of a symbol in the dynsym
771*d29b2c44Sab 		 * will break the hash table in this object.
772*d29b2c44Sab 		 */
773*d29b2c44Sab 		if (symstate->sym.sec->sec_shdr->sh_type == SHT_DYNSYM)
774*d29b2c44Sab 			elfedit_msg(ELFEDIT_MSG_DEBUG,
775*d29b2c44Sab 			    MSG_INTL(MSG_DEBUG_DYNSYMNAMCHG),
776*d29b2c44Sab 			    EC_WORD(symstate->sym.sec->sec_shndx),
777*d29b2c44Sab 			    symstate->sym.sec->sec_name,
778*d29b2c44Sab 			    EC_WORD(symstate->ndx));
779*d29b2c44Sab 
780*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_D_CHG),
781*d29b2c44Sab 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
782*d29b2c44Sab 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_NAME),
783*d29b2c44Sab 		    EC_WORD(sym->st_name),
784*d29b2c44Sab 		    EC_WORD(str_offset));
785*d29b2c44Sab 		ret = ELFEDIT_CMDRET_MOD;
786*d29b2c44Sab 		sym->st_name = str_offset;
787*d29b2c44Sab 	}
788*d29b2c44Sab 
789*d29b2c44Sab 	return (ret);
790*d29b2c44Sab }
791*d29b2c44Sab 
792*d29b2c44Sab static elfedit_cmdret_t
793*d29b2c44Sab cmd_body_set_st_shndx(ARGSTATE *argstate, SYMSTATE *symstate)
794*d29b2c44Sab {
795*d29b2c44Sab 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
796*d29b2c44Sab 	Sym			*sym = &symstate->sym.data[symstate->ndx];
797*d29b2c44Sab 	Word	shndx, st_shndx, xshndx;
798*d29b2c44Sab 	int	use_xshndx;
799*d29b2c44Sab 	int	shndx_chg, xshndx_chg;
800*d29b2c44Sab 
801*d29b2c44Sab 
802*d29b2c44Sab 	/*
803*d29b2c44Sab 	 * By default, the sec argument is a section name. If -secshndx was
804*d29b2c44Sab 	 * specified, it is a section index, and if -secshtyp is specified,
805*d29b2c44Sab 	 * it is a section type.
806*d29b2c44Sab 	 */
807*d29b2c44Sab 	if (argstate->optmask & SYM_OPT_F_SECSHNDX)
808*d29b2c44Sab 		shndx = elfedit_atoshndx(argstate->argv[1],
809*d29b2c44Sab 		    argstate->obj_state->os_shnum);
810*d29b2c44Sab 	else if (argstate->optmask & SYM_OPT_F_SECSHTYP)
811*d29b2c44Sab 		shndx = elfedit_type_to_shndx(argstate->obj_state,
812*d29b2c44Sab 		    elfedit_atoconst(argstate->argv[1], ELFEDIT_CONST_SHT));
813*d29b2c44Sab 	else
814*d29b2c44Sab 		shndx = elfedit_name_to_shndx(argstate->obj_state,
815*d29b2c44Sab 		    argstate->argv[1]);
816*d29b2c44Sab 
817*d29b2c44Sab 	/*
818*d29b2c44Sab 	 * We want to use an extended index section if the index is too
819*d29b2c44Sab 	 * large to be represented otherwise, or if the caller specified
820*d29b2c44Sab 	 * the -e option to make us do it anyway. However, we cannot
821*d29b2c44Sab 	 * do this if the index is in the special reserved range between
822*d29b2c44Sab 	 * SHN_LORESERVE and SHN_HIRESERVE.
823*d29b2c44Sab 	 */
824*d29b2c44Sab 	use_xshndx = (shndx > SHN_HIRESERVE) ||
825*d29b2c44Sab 	    ((shndx < SHN_LORESERVE) &&
826*d29b2c44Sab 	    (argstate->optmask & SYM_OPT_F_XSHINDEX));
827*d29b2c44Sab 
828*d29b2c44Sab 	/*
829*d29b2c44Sab 	 * There are two cases where we have to touch the extended
830*d29b2c44Sab 	 * index section:
831*d29b2c44Sab 	 *
832*d29b2c44Sab 	 *	1) We have determined that we need to, as determined above.
833*d29b2c44Sab 	 *	2) We do not require it, but the file has an extended
834*d29b2c44Sab 	 *		index section, in which case we should set the slot
835*d29b2c44Sab 	 *		in that extended section to SHN_UNDEF (0).
836*d29b2c44Sab 	 *
837*d29b2c44Sab 	 * Fetch the extended section as required, and determine the values
838*d29b2c44Sab 	 * for st_shndx and the extended section slot.
839*d29b2c44Sab 	 */
840*d29b2c44Sab 	if (use_xshndx) {
841*d29b2c44Sab 		/* We must have an extended index section, or error out */
842*d29b2c44Sab 		symstate_add_xshndx(argstate, symstate);
843*d29b2c44Sab 
844*d29b2c44Sab 		/* Set symbol to SHN_XINDEX, put index in the extended sec. */
845*d29b2c44Sab 		st_shndx = SHN_XINDEX;
846*d29b2c44Sab 		xshndx = shndx;
847*d29b2c44Sab 	} else {
848*d29b2c44Sab 		st_shndx = shndx;
849*d29b2c44Sab 		xshndx = SHN_UNDEF;
850*d29b2c44Sab 		if (symstate->xshndx.shndx != SHN_UNDEF)
851*d29b2c44Sab 			use_xshndx = 1;
852*d29b2c44Sab 	}
853*d29b2c44Sab 	if (use_xshndx)
854*d29b2c44Sab 		symstate_add_xshndx(argstate, symstate);
855*d29b2c44Sab 	shndx_chg = (sym->st_shndx != st_shndx);
856*d29b2c44Sab 	xshndx_chg = use_xshndx &&
857*d29b2c44Sab 	    (symstate->xshndx.data[symstate->ndx] != xshndx);
858*d29b2c44Sab 
859*d29b2c44Sab 
860*d29b2c44Sab 	/* If anything is going to change, issue appropiate warnings */
861*d29b2c44Sab 	if (shndx_chg || xshndx_chg) {
862*d29b2c44Sab 		/*
863*d29b2c44Sab 		 * Setting the first symbol to anything other than SHN_UNDEF
864*d29b2c44Sab 		 * produces a bad ELF file.
865*d29b2c44Sab 		 */
866*d29b2c44Sab 		if ((symstate->ndx == 0) && (shndx != SHN_UNDEF))
867*d29b2c44Sab 			elfedit_msg(ELFEDIT_MSG_DEBUG,
868*d29b2c44Sab 			    MSG_INTL(MSG_DEBUG_SHNDX_UNDEF0));
869*d29b2c44Sab 
870*d29b2c44Sab 		/*
871*d29b2c44Sab 		 * Setting SHN_XINDEX directly, instead of providing
872*d29b2c44Sab 		 * an extended index and letting us decide to use
873*d29b2c44Sab 		 * SHN_XINDEX to implement it, is probably a mistake.
874*d29b2c44Sab 		 * Issue a warning, but go ahead and follow the directions
875*d29b2c44Sab 		 * we've been given.
876*d29b2c44Sab 		 */
877*d29b2c44Sab 		if (shndx == SHN_XINDEX)
878*d29b2c44Sab 			elfedit_msg(ELFEDIT_MSG_DEBUG,
879*d29b2c44Sab 			    MSG_INTL(MSG_DEBUG_SHNDX_XINDEX));
880*d29b2c44Sab 
881*d29b2c44Sab 		/*
882*d29b2c44Sab 		 * If the section index can fit in the symbol, but
883*d29b2c44Sab 		 * -e is being used to force it into the extended
884*d29b2c44Sab 		 * index section, issue a warning.
885*d29b2c44Sab 		 */
886*d29b2c44Sab 		if (use_xshndx && (shndx < SHN_LORESERVE) &&
887*d29b2c44Sab 		    (st_shndx == SHN_XINDEX))
888*d29b2c44Sab 			elfedit_msg(ELFEDIT_MSG_DEBUG,
889*d29b2c44Sab 			    MSG_INTL(MSG_DEBUG_SHNDX_EFORCE),
890*d29b2c44Sab 			    EC_WORD(symstate->sym.sec->sec_shndx),
891*d29b2c44Sab 			    symstate->sym.sec->sec_name, EC_WORD(symstate->ndx),
892*d29b2c44Sab 			    EC_WORD(shndx));
893*d29b2c44Sab 	}
894*d29b2c44Sab 
895*d29b2c44Sab 	if (shndx_chg) {
896*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG),
897*d29b2c44Sab 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
898*d29b2c44Sab 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_SHNDX),
899*d29b2c44Sab 		    elfedit_shndx_to_name(argstate->obj_state,
900*d29b2c44Sab 		    sym->st_shndx),
901*d29b2c44Sab 		    elfedit_shndx_to_name(argstate->obj_state, st_shndx));
902*d29b2c44Sab 		ret = ELFEDIT_CMDRET_MOD;
903*d29b2c44Sab 		sym->st_shndx = st_shndx;
904*d29b2c44Sab 	} else {
905*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK),
906*d29b2c44Sab 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
907*d29b2c44Sab 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_SHNDX),
908*d29b2c44Sab 		    elfedit_shndx_to_name(argstate->obj_state, st_shndx));
909*d29b2c44Sab 	}
910*d29b2c44Sab 
911*d29b2c44Sab 	if (use_xshndx) {
912*d29b2c44Sab 		if (xshndx_chg) {
913*d29b2c44Sab 			elfedit_msg(ELFEDIT_MSG_DEBUG,
914*d29b2c44Sab 			    MSG_INTL(MSG_DEBUG_EXT_S_CHG),
915*d29b2c44Sab 			    symstate->xshndx.sec->sec_shndx,
916*d29b2c44Sab 			    symstate->xshndx.sec->sec_name,
917*d29b2c44Sab 			    EC_WORD(symstate->ndx),
918*d29b2c44Sab 			    elfedit_shndx_to_name(argstate->obj_state,
919*d29b2c44Sab 			    symstate->xshndx.data[symstate->ndx]),
920*d29b2c44Sab 			    elfedit_shndx_to_name(argstate->obj_state, xshndx));
921*d29b2c44Sab 			ret = ELFEDIT_CMDRET_MOD;
922*d29b2c44Sab 			symstate->xshndx.data[symstate->ndx] = xshndx;
923*d29b2c44Sab 			elfedit_modified_data(symstate->xshndx.sec);
924*d29b2c44Sab 		} else {
925*d29b2c44Sab 			elfedit_msg(ELFEDIT_MSG_DEBUG,
926*d29b2c44Sab 			    MSG_INTL(MSG_DEBUG_EXT_S_OK),
927*d29b2c44Sab 			    symstate->xshndx.sec->sec_shndx,
928*d29b2c44Sab 			    symstate->xshndx.sec->sec_name,
929*d29b2c44Sab 			    EC_WORD(symstate->ndx),
930*d29b2c44Sab 			    elfedit_shndx_to_name(argstate->obj_state, xshndx));
931*d29b2c44Sab 		}
932*d29b2c44Sab 	}
933*d29b2c44Sab 
934*d29b2c44Sab 	return (ret);
935*d29b2c44Sab }
936*d29b2c44Sab 
937*d29b2c44Sab static elfedit_cmdret_t
938*d29b2c44Sab cmd_body_set_st_type(ARGSTATE *argstate, SYMSTATE *symstate)
939*d29b2c44Sab {
940*d29b2c44Sab 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
941*d29b2c44Sab 	Conv_inv_buf_t	inv_buf1, inv_buf2;
942*d29b2c44Sab 	Half		mach = argstate->obj_state->os_ehdr->e_machine;
943*d29b2c44Sab 	Sym		*sym = &symstate->sym.data[symstate->ndx];
944*d29b2c44Sab 	uchar_t		bind, type, old_type;
945*d29b2c44Sab 
946*d29b2c44Sab 	/*
947*d29b2c44Sab 	 * Use the ELF_ST_TYPE() macro to access the defined bits
948*d29b2c44Sab 	 * of the st_info field related to symbol type.
949*d29b2c44Sab 	 * Accepts STT_ symbolic names as well as integers.
950*d29b2c44Sab 	 */
951*d29b2c44Sab 	bind = ELF_ST_BIND(sym->st_info);
952*d29b2c44Sab 	type = elfedit_atoconst_range(argstate->argv[1],
953*d29b2c44Sab 	    MSG_INTL(MSG_ARG_SYMBIND), 0, 15, ELFEDIT_CONST_STT);
954*d29b2c44Sab 	old_type = ELF_ST_TYPE(sym->st_info);
955*d29b2c44Sab 
956*d29b2c44Sab 	if (old_type == type) {
957*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK),
958*d29b2c44Sab 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
959*d29b2c44Sab 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_TYPE),
960*d29b2c44Sab 		    conv_sym_info_type(mach, type, CONV_FMT_ALT_FULLNAME,
961*d29b2c44Sab 		    &inv_buf1));
962*d29b2c44Sab 	} else {
963*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG),
964*d29b2c44Sab 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
965*d29b2c44Sab 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_TYPE),
966*d29b2c44Sab 		    conv_sym_info_type(mach, old_type, CONV_FMT_ALT_FULLNAME,
967*d29b2c44Sab 		    &inv_buf1),
968*d29b2c44Sab 		    conv_sym_info_type(mach, type, CONV_FMT_ALT_FULLNAME,
969*d29b2c44Sab 		    &inv_buf2));
970*d29b2c44Sab 		ret = ELFEDIT_CMDRET_MOD;
971*d29b2c44Sab 		sym->st_info = ELF_ST_INFO(bind, type);
972*d29b2c44Sab 	}
973*d29b2c44Sab 
974*d29b2c44Sab 	return (ret);
975*d29b2c44Sab }
976*d29b2c44Sab 
977*d29b2c44Sab static elfedit_cmdret_t
978*d29b2c44Sab cmd_body_set_st_visibility(ARGSTATE *argstate, SYMSTATE *symstate)
979*d29b2c44Sab {
980*d29b2c44Sab 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
981*d29b2c44Sab 	Conv_inv_buf_t	inv_buf1, inv_buf2;
982*d29b2c44Sab 	Sym		*sym = &symstate->sym.data[symstate->ndx];
983*d29b2c44Sab 	uchar_t		st_other = sym->st_other;
984*d29b2c44Sab 	uchar_t		vis, old_vis;
985*d29b2c44Sab 
986*d29b2c44Sab 	/*
987*d29b2c44Sab 	 * Use the ELF_ST_VISIBILITY() macro to access the
988*d29b2c44Sab 	 * defined bits of the st_other field related to symbol
989*d29b2c44Sab 	 * visibility. Accepts STV_ symbolic names as well as integers.
990*d29b2c44Sab 	 */
991*d29b2c44Sab 	vis = elfedit_atoconst_range(argstate->argv[1],
992*d29b2c44Sab 	    MSG_INTL(MSG_ARG_SYMVIS), 0, STV_PROTECTED, ELFEDIT_CONST_STV);
993*d29b2c44Sab 	old_vis = st_other & MSK_SYM_VISIBILITY;
994*d29b2c44Sab 
995*d29b2c44Sab 	if (old_vis == vis) {
996*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK),
997*d29b2c44Sab 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
998*d29b2c44Sab 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_VISIBILITY),
999*d29b2c44Sab 		    conv_sym_other_vis(old_vis, CONV_FMT_ALT_FULLNAME,
1000*d29b2c44Sab 		    &inv_buf1));
1001*d29b2c44Sab 	} else {
1002*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG),
1003*d29b2c44Sab 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
1004*d29b2c44Sab 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_VISIBILITY),
1005*d29b2c44Sab 		    conv_sym_other_vis(old_vis, CONV_FMT_ALT_FULLNAME,
1006*d29b2c44Sab 		    &inv_buf1),
1007*d29b2c44Sab 		    conv_sym_other_vis(vis, CONV_FMT_ALT_FULLNAME, &inv_buf2));
1008*d29b2c44Sab 		ret = ELFEDIT_CMDRET_MOD;
1009*d29b2c44Sab 		st_other = (st_other & ~MSK_SYM_VISIBILITY) |
1010*d29b2c44Sab 		    ELF_ST_VISIBILITY(vis);
1011*d29b2c44Sab 		sym->st_other = st_other;
1012*d29b2c44Sab 	}
1013*d29b2c44Sab 
1014*d29b2c44Sab 	return (ret);
1015*d29b2c44Sab }
1016*d29b2c44Sab 
1017*d29b2c44Sab 
1018*d29b2c44Sab /*
1019*d29b2c44Sab  * Standard argument processing for sym module
1020*d29b2c44Sab  *
1021*d29b2c44Sab  * entry
1022*d29b2c44Sab  *	obj_state, argc, argv - Standard command arguments
1023*d29b2c44Sab  *	optmask - Mask of allowed optional arguments.
1024*d29b2c44Sab  *	symstate - State block for current symbol table.
1025*d29b2c44Sab  *	argstate - Address of ARGSTATE block to be initialized
1026*d29b2c44Sab  *
1027*d29b2c44Sab  * exit:
1028*d29b2c44Sab  *	On success, *argstate is initialized. On error,
1029*d29b2c44Sab  *	an error is issued and this routine does not return.
1030*d29b2c44Sab  *
1031*d29b2c44Sab  * note:
1032*d29b2c44Sab  *	Only the basic symbol table is initially referenced by
1033*d29b2c44Sab  *	argstate. Use the argstate_add_XXX() routines below to
1034*d29b2c44Sab  *	access any auxiliary sections needed.
1035*d29b2c44Sab  */
1036*d29b2c44Sab static ARGSTATE *
1037*d29b2c44Sab process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
1038*d29b2c44Sab     SYM_CMD_T cmd)
1039*d29b2c44Sab {
1040*d29b2c44Sab 	/*
1041*d29b2c44Sab 	 * We reuse this same argstate, resizing it to the required
1042*d29b2c44Sab 	 * number of symbol tables on the first call, and as necessary.
1043*d29b2c44Sab 	 */
1044*d29b2c44Sab 	static ARGSTATE *argstate;
1045*d29b2c44Sab 	static int argstate_size = 0;
1046*d29b2c44Sab 
1047*d29b2c44Sab 	elfedit_getopt_state_t	getopt_state;
1048*d29b2c44Sab 	elfedit_getopt_ret_t	*getopt_ret;
1049*d29b2c44Sab 	elfedit_symtab_t	*symtab;
1050*d29b2c44Sab 	int		explicit = 0;
1051*d29b2c44Sab 	int		got_sym = 0;
1052*d29b2c44Sab 	Word		index;
1053*d29b2c44Sab 	Word		tblndx;
1054*d29b2c44Sab 	size_t		size;
1055*d29b2c44Sab 	SYMSTATE	*symstate;
1056*d29b2c44Sab 
1057*d29b2c44Sab 	/* If there are no symbol tables, we can't do a thing */
1058*d29b2c44Sab 	if (obj_state->os_symtabnum == 0)
1059*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMTAB));
1060*d29b2c44Sab 
1061*d29b2c44Sab 	/* Calulate required size of argstate and realloc as necessary */
1062*d29b2c44Sab 	size = sizeof (ARGSTATE) +
1063*d29b2c44Sab 	    ((obj_state->os_symtabnum - 1) * sizeof (SYMSTATE));
1064*d29b2c44Sab 	if (argstate_size != size) {
1065*d29b2c44Sab 		argstate = elfedit_realloc(MSG_INTL(MSG_ALLOC_ARGSTATE),
1066*d29b2c44Sab 		    argstate, size);
1067*d29b2c44Sab 		argstate_size = size;
1068*d29b2c44Sab 	}
1069*d29b2c44Sab 	bzero(argstate, argstate_size);
1070*d29b2c44Sab 	argstate->obj_state = obj_state;
1071*d29b2c44Sab 
1072*d29b2c44Sab 	elfedit_getopt_init(&getopt_state, &argc, &argv);
1073*d29b2c44Sab 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
1074*d29b2c44Sab 		argstate->optmask |= getopt_ret->gor_idmask;
1075*d29b2c44Sab 		switch (getopt_ret->gor_idmask) {
1076*d29b2c44Sab 		case SYM_OPT_F_SHNAME:		/* -shnam name */
1077*d29b2c44Sab 			index = elfedit_name_to_shndx(obj_state,
1078*d29b2c44Sab 			    getopt_ret->gor_value);
1079*d29b2c44Sab 			explicit = 1;
1080*d29b2c44Sab 			break;
1081*d29b2c44Sab 
1082*d29b2c44Sab 		case SYM_OPT_F_SHNDX:		/* -shndx index */
1083*d29b2c44Sab 			index = elfedit_atoui_range(getopt_ret->gor_value,
1084*d29b2c44Sab 			    MSG_INTL(MSG_ARG_SECNDX), 1,
1085*d29b2c44Sab 			    obj_state->os_shnum - 1, NULL);
1086*d29b2c44Sab 			explicit = 1;
1087*d29b2c44Sab 			break;
1088*d29b2c44Sab 
1089*d29b2c44Sab 		case SYM_OPT_F_SHTYP:		/* -shtyp type */
1090*d29b2c44Sab 			index = elfedit_type_to_shndx(obj_state,
1091*d29b2c44Sab 			    elfedit_atoconst(getopt_ret->gor_value,
1092*d29b2c44Sab 			    ELFEDIT_CONST_SHT));
1093*d29b2c44Sab 			explicit = 1;
1094*d29b2c44Sab 			break;
1095*d29b2c44Sab 		}
1096*d29b2c44Sab 	}
1097*d29b2c44Sab 
1098*d29b2c44Sab 	/*
1099*d29b2c44Sab 	 * Usage error if there are too many plain arguments. sym:dump accepts
1100*d29b2c44Sab 	 * a single argument, while the others accept 2.
1101*d29b2c44Sab 	 */
1102*d29b2c44Sab 	if (((cmd == SYM_CMD_T_DUMP) && (argc > 1)) || (argc > 2))
1103*d29b2c44Sab 		elfedit_command_usage();
1104*d29b2c44Sab 
1105*d29b2c44Sab 	/*
1106*d29b2c44Sab 	 * If the -symndx option was specified, the sym arg is an index
1107*d29b2c44Sab 	 * into the symbol table. In this case, the symbol table must be
1108*d29b2c44Sab 	 * explicitly specified (-shnam, -shndx, or -shtype).
1109*d29b2c44Sab 	 */
1110*d29b2c44Sab 	if ((argstate->optmask & SYM_OPT_F_SYMNDX) && !explicit)
1111*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEXPSYMTAB));
1112*d29b2c44Sab 
1113*d29b2c44Sab 	/*
1114*d29b2c44Sab 	 * If a section was explicitly specified, it needs
1115*d29b2c44Sab 	 * be a symbol table.
1116*d29b2c44Sab 	 */
1117*d29b2c44Sab 	if (explicit)
1118*d29b2c44Sab 		(void) elfedit_sec_issymtab(&obj_state->os_secarr[index],
1119*d29b2c44Sab 		    1, NULL);
1120*d29b2c44Sab 
1121*d29b2c44Sab 	/* If there may be an arbitrary amount of output, use a pager */
1122*d29b2c44Sab 	if (argc == 0)
1123*d29b2c44Sab 		elfedit_pager_init();
1124*d29b2c44Sab 
1125*d29b2c44Sab 	/* Return the updated values of argc/argv */
1126*d29b2c44Sab 	argstate->argc = argc;
1127*d29b2c44Sab 	argstate->argv = argv;
1128*d29b2c44Sab 
1129*d29b2c44Sab 	/*
1130*d29b2c44Sab 	 * Decide which symbol table(s) to use. Set up the symstate
1131*d29b2c44Sab 	 * array to contain them:
1132*d29b2c44Sab 	 *	- If a symbol table was explicitly specified, we use
1133*d29b2c44Sab 	 *		it, and only it.
1134*d29b2c44Sab 	 *	- If no symbol table is explicitly specified, and the symbol
1135*d29b2c44Sab 	 *		is given by name, we use all symbol tables that
1136*d29b2c44Sab 	 *		contain a symbol with that name, throwing an error
1137*d29b2c44Sab 	 *		if there isn't at least 1 such table.
1138*d29b2c44Sab 	 *	- If no symbol table is specified, and no symbol is specified,
1139*d29b2c44Sab 	 *		we use all the tables.
1140*d29b2c44Sab 	 */
1141*d29b2c44Sab 	symtab = obj_state->os_symtab;
1142*d29b2c44Sab 	symstate = argstate->symstate;
1143*d29b2c44Sab 	for (tblndx = 0; tblndx < obj_state->os_symtabnum;
1144*d29b2c44Sab 	    tblndx++, symtab++) {
1145*d29b2c44Sab 		/* If explicit table specified, only that table is considered */
1146*d29b2c44Sab 		if (explicit && (symtab->symt_shndx != index))
1147*d29b2c44Sab 			continue;
1148*d29b2c44Sab 
1149*d29b2c44Sab 		symstate->sym.sec = elfedit_sec_getsymtab(obj_state, 1,
1150*d29b2c44Sab 		    symtab->symt_shndx, NULL, &symstate->sym.data,
1151*d29b2c44Sab 		    &symstate->sym.n, &symtab);
1152*d29b2c44Sab 		symstate->versym.shndx = symtab->symt_versym;
1153*d29b2c44Sab 		symstate->xshndx.shndx = symtab->symt_xshndx;
1154*d29b2c44Sab 		if (argc > 0) {
1155*d29b2c44Sab 			if (argstate->optmask & SYM_OPT_F_SYMNDX) {
1156*d29b2c44Sab 				symstate->ndx = elfedit_atoui_range(
1157*d29b2c44Sab 				    argstate->argv[0], MSG_INTL(MSG_ARG_SYM), 0,
1158*d29b2c44Sab 				    symstate->sym.n - 1, NULL);
1159*d29b2c44Sab 			} else {
1160*d29b2c44Sab 				/*
1161*d29b2c44Sab 				 * arg is a symbol name. Use the index of
1162*d29b2c44Sab 				 * the first symbol that matches
1163*d29b2c44Sab 				 */
1164*d29b2c44Sab 
1165*d29b2c44Sab 				/*
1166*d29b2c44Sab 				 * We will use debug messages for failure up
1167*d29b2c44Sab 				 * until we run out of symbol tables. If we
1168*d29b2c44Sab 				 * don't find a table with the desired symbol
1169*d29b2c44Sab 				 * before the last table, we switch to error
1170*d29b2c44Sab 				 * messages. Hence, we will jump with an error
1171*d29b2c44Sab 				 * if no table will work.
1172*d29b2c44Sab 				 */
1173*d29b2c44Sab 				int err_type = (!got_sym &&
1174*d29b2c44Sab 				    ((tblndx + 1) == obj_state->os_symtabnum)) ?
1175*d29b2c44Sab 				    ELFEDIT_MSG_ERR : ELFEDIT_MSG_DEBUG;
1176*d29b2c44Sab 
1177*d29b2c44Sab 				symstate_add_str(argstate, symstate);
1178*d29b2c44Sab 
1179*d29b2c44Sab 				/*
1180*d29b2c44Sab 				 * If the symbol table doesn't have this
1181*d29b2c44Sab 				 * symbol, then forget it.
1182*d29b2c44Sab 				 */
1183*d29b2c44Sab 				if (elfedit_name_to_symndx(symstate->sym.sec,
1184*d29b2c44Sab 				    symstate->str.sec, argstate->argv[0],
1185*d29b2c44Sab 				    err_type, &symstate->ndx) == 0) {
1186*d29b2c44Sab 					bzero(symstate, sizeof (*symstate));
1187*d29b2c44Sab 					continue;
1188*d29b2c44Sab 				}
1189*d29b2c44Sab 			}
1190*d29b2c44Sab 		}
1191*d29b2c44Sab 		argstate->numsymstate++;
1192*d29b2c44Sab 		symstate++;
1193*d29b2c44Sab 		/*
1194*d29b2c44Sab 		 * If the symbol table was given explicitly, and
1195*d29b2c44Sab 		 * we've just taken it, then there is no reason to
1196*d29b2c44Sab 		 * continue searching.
1197*d29b2c44Sab 		 */
1198*d29b2c44Sab 		if (explicit)
1199*d29b2c44Sab 			break;
1200*d29b2c44Sab 	}
1201*d29b2c44Sab 
1202*d29b2c44Sab 	return (argstate);
1203*d29b2c44Sab }
1204*d29b2c44Sab 
1205*d29b2c44Sab 
1206*d29b2c44Sab 
1207*d29b2c44Sab /*
1208*d29b2c44Sab  * Called by cmd_body() to handle the value change for a single
1209*d29b2c44Sab  * symbol table.
1210*d29b2c44Sab  *
1211*d29b2c44Sab  * entry:
1212*d29b2c44Sab  *	cmd - One of the SYM_CMD_T_* constants listed above, specifying
1213*d29b2c44Sab  *		which command to implement.
1214*d29b2c44Sab  *	argstate - Overall state block
1215*d29b2c44Sab  *	symstate - State block for current symbol table.
1216*d29b2c44Sab  */
1217*d29b2c44Sab static elfedit_cmdret_t
1218*d29b2c44Sab symstate_cmd_body(SYM_CMD_T cmd, ARGSTATE *argstate, SYMSTATE *symstate)
1219*d29b2c44Sab {
1220*d29b2c44Sab 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
1221*d29b2c44Sab 	Sym			*sym = &symstate->sym.data[symstate->ndx];
1222*d29b2c44Sab 
1223*d29b2c44Sab 	/* You're not supposed to change the value of symbol [0] */
1224*d29b2c44Sab 	if (symstate->ndx == 0)
1225*d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSYMELT0),
1226*d29b2c44Sab 		    EC_WORD(symstate->sym.sec->sec_shndx),
1227*d29b2c44Sab 		    symstate->sym.sec->sec_name, EC_WORD(symstate->ndx));
1228*d29b2c44Sab 
1229*d29b2c44Sab 	/* The second value is an integer giving a new value */
1230*d29b2c44Sab 	switch (cmd) {
1231*d29b2c44Sab 		/*
1232*d29b2c44Sab 		 * SYM_CMD_T_DUMP can't get here: It never has more than
1233*d29b2c44Sab 		 * one argument, and is handled above.
1234*d29b2c44Sab 		 */
1235*d29b2c44Sab 
1236*d29b2c44Sab 	case SYM_CMD_T_ST_BIND:
1237*d29b2c44Sab 		ret = cmd_body_set_st_bind(argstate, symstate);
1238*d29b2c44Sab 		break;
1239*d29b2c44Sab 
1240*d29b2c44Sab 	case SYM_CMD_T_ST_INFO:
1241*d29b2c44Sab 		{
1242*d29b2c44Sab 			/* Treat st_info as a raw integer field */
1243*d29b2c44Sab 			uchar_t st_info =
1244*d29b2c44Sab 			    elfedit_atoui(argstate->argv[1], NULL);
1245*d29b2c44Sab 
1246*d29b2c44Sab 			if (sym->st_info == st_info) {
1247*d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
1248*d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_D_OK),
1249*d29b2c44Sab 				    symstate->sym.sec->sec_shndx,
1250*d29b2c44Sab 				    symstate->sym.sec->sec_name,
1251*d29b2c44Sab 				    EC_WORD(symstate->ndx),
1252*d29b2c44Sab 				    MSG_ORIG(MSG_CMD_ST_INFO),
1253*d29b2c44Sab 				    EC_WORD(sym->st_info));
1254*d29b2c44Sab 			} else {
1255*d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
1256*d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_D_CHG),
1257*d29b2c44Sab 				    symstate->sym.sec->sec_shndx,
1258*d29b2c44Sab 				    symstate->sym.sec->sec_name,
1259*d29b2c44Sab 				    EC_WORD(symstate->ndx),
1260*d29b2c44Sab 				    MSG_ORIG(MSG_CMD_ST_INFO),
1261*d29b2c44Sab 				    EC_WORD(sym->st_info), EC_WORD(st_info));
1262*d29b2c44Sab 				ret = ELFEDIT_CMDRET_MOD;
1263*d29b2c44Sab 				sym->st_info = st_info;
1264*d29b2c44Sab 			}
1265*d29b2c44Sab 		}
1266*d29b2c44Sab 	break;
1267*d29b2c44Sab 
1268*d29b2c44Sab 	case SYM_CMD_T_ST_NAME:
1269*d29b2c44Sab 		ret = cmd_body_set_st_name(argstate, symstate);
1270*d29b2c44Sab 		break;
1271*d29b2c44Sab 
1272*d29b2c44Sab 	case SYM_CMD_T_ST_OTHER:
1273*d29b2c44Sab 		{
1274*d29b2c44Sab 			/* Treat st_other as a raw integer field */
1275*d29b2c44Sab 			uchar_t st_other =
1276*d29b2c44Sab 			    elfedit_atoui(argstate->argv[1], NULL);
1277*d29b2c44Sab 
1278*d29b2c44Sab 			if (sym->st_other == st_other) {
1279*d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
1280*d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_D_OK),
1281*d29b2c44Sab 				    symstate->sym.sec->sec_shndx,
1282*d29b2c44Sab 				    symstate->sym.sec->sec_name,
1283*d29b2c44Sab 				    EC_WORD(symstate->ndx),
1284*d29b2c44Sab 				    MSG_ORIG(MSG_CMD_ST_OTHER),
1285*d29b2c44Sab 				    EC_WORD(sym->st_other));
1286*d29b2c44Sab 			} else {
1287*d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
1288*d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_D_CHG),
1289*d29b2c44Sab 				    symstate->sym.sec->sec_shndx,
1290*d29b2c44Sab 				    symstate->sym.sec->sec_name,
1291*d29b2c44Sab 				    EC_WORD(symstate->ndx),
1292*d29b2c44Sab 				    MSG_ORIG(MSG_CMD_ST_OTHER),
1293*d29b2c44Sab 				    EC_WORD(sym->st_other), EC_WORD(st_other));
1294*d29b2c44Sab 				ret = ELFEDIT_CMDRET_MOD;
1295*d29b2c44Sab 				sym->st_other = st_other;
1296*d29b2c44Sab 			}
1297*d29b2c44Sab 		}
1298*d29b2c44Sab 		break;
1299*d29b2c44Sab 
1300*d29b2c44Sab 	case SYM_CMD_T_ST_SHNDX:
1301*d29b2c44Sab 		ret = cmd_body_set_st_shndx(argstate, symstate);
1302*d29b2c44Sab 		break;
1303*d29b2c44Sab 
1304*d29b2c44Sab 	case SYM_CMD_T_ST_SIZE:
1305*d29b2c44Sab 		{
1306*d29b2c44Sab 			Xword st_size = elfedit_atoui(argstate->argv[1], NULL);
1307*d29b2c44Sab 
1308*d29b2c44Sab 			if (sym->st_size == st_size) {
1309*d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
1310*d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_LLX_OK),
1311*d29b2c44Sab 				    symstate->sym.sec->sec_shndx,
1312*d29b2c44Sab 				    symstate->sym.sec->sec_name,
1313*d29b2c44Sab 				    EC_WORD(symstate->ndx),
1314*d29b2c44Sab 				    MSG_ORIG(MSG_CMD_ST_SIZE),
1315*d29b2c44Sab 				    EC_XWORD(sym->st_size));
1316*d29b2c44Sab 			} else {
1317*d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
1318*d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_LLX_CHG),
1319*d29b2c44Sab 				    symstate->sym.sec->sec_shndx,
1320*d29b2c44Sab 				    symstate->sym.sec->sec_name,
1321*d29b2c44Sab 				    EC_WORD(symstate->ndx),
1322*d29b2c44Sab 				    MSG_ORIG(MSG_CMD_ST_SIZE),
1323*d29b2c44Sab 				    EC_XWORD(sym->st_size), EC_XWORD(st_size));
1324*d29b2c44Sab 				ret = ELFEDIT_CMDRET_MOD;
1325*d29b2c44Sab 				sym->st_size = st_size;
1326*d29b2c44Sab 			}
1327*d29b2c44Sab 		}
1328*d29b2c44Sab 		break;
1329*d29b2c44Sab 
1330*d29b2c44Sab 	case SYM_CMD_T_ST_TYPE:
1331*d29b2c44Sab 		ret = cmd_body_set_st_type(argstate, symstate);
1332*d29b2c44Sab 		break;
1333*d29b2c44Sab 
1334*d29b2c44Sab 	case SYM_CMD_T_ST_VALUE:
1335*d29b2c44Sab 		{
1336*d29b2c44Sab 			Addr st_value = elfedit_atoui(argstate->argv[1], NULL);
1337*d29b2c44Sab 
1338*d29b2c44Sab 			if (sym->st_value == st_value) {
1339*d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
1340*d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_LLX_OK),
1341*d29b2c44Sab 				    symstate->sym.sec->sec_shndx,
1342*d29b2c44Sab 				    symstate->sym.sec->sec_name,
1343*d29b2c44Sab 				    EC_WORD(symstate->ndx),
1344*d29b2c44Sab 				    MSG_ORIG(MSG_CMD_ST_VALUE),
1345*d29b2c44Sab 				    EC_ADDR(sym->st_value));
1346*d29b2c44Sab 			} else {
1347*d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
1348*d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_LLX_CHG),
1349*d29b2c44Sab 				    symstate->sym.sec->sec_shndx,
1350*d29b2c44Sab 				    symstate->sym.sec->sec_name,
1351*d29b2c44Sab 				    EC_WORD(symstate->ndx),
1352*d29b2c44Sab 				    MSG_ORIG(MSG_CMD_ST_VALUE),
1353*d29b2c44Sab 				    EC_ADDR(sym->st_value),
1354*d29b2c44Sab 				    EC_ADDR(st_value));
1355*d29b2c44Sab 				ret = ELFEDIT_CMDRET_MOD;
1356*d29b2c44Sab 				ret = ELFEDIT_CMDRET_MOD;
1357*d29b2c44Sab 				sym->st_value = st_value;
1358*d29b2c44Sab 			}
1359*d29b2c44Sab 		}
1360*d29b2c44Sab 		break;
1361*d29b2c44Sab 
1362*d29b2c44Sab 	case SYM_CMD_T_ST_VISIBILITY:
1363*d29b2c44Sab 		ret = cmd_body_set_st_visibility(argstate, symstate);
1364*d29b2c44Sab 		break;
1365*d29b2c44Sab 	}
1366*d29b2c44Sab 
1367*d29b2c44Sab 	/*
1368*d29b2c44Sab 	 * If we modified the symbol table, tell libelf.
1369*d29b2c44Sab 	 * Any other modified sections are the responsibility
1370*d29b2c44Sab 	 * of the cmd_body_set_st_*() function that did it, but
1371*d29b2c44Sab 	 * everyone modifies the table itself, so we handle that here.
1372*d29b2c44Sab 	 */
1373*d29b2c44Sab 	if (ret == ELFEDIT_CMDRET_MOD)
1374*d29b2c44Sab 		elfedit_modified_data(symstate->sym.sec);
1375*d29b2c44Sab 
1376*d29b2c44Sab 	return (ret);
1377*d29b2c44Sab }
1378*d29b2c44Sab 
1379*d29b2c44Sab 
1380*d29b2c44Sab 
1381*d29b2c44Sab 
1382*d29b2c44Sab /*
1383*d29b2c44Sab  * Common body for the sym: module commands. These commands
1384*d29b2c44Sab  * share a large amount of common behavior, so it is convenient
1385*d29b2c44Sab  * to centralize things and use the cmd argument to handle the
1386*d29b2c44Sab  * small differences.
1387*d29b2c44Sab  *
1388*d29b2c44Sab  * entry:
1389*d29b2c44Sab  *	cmd - One of the SYM_CMD_T_* constants listed above, specifying
1390*d29b2c44Sab  *		which command to implement.
1391*d29b2c44Sab  *	obj_state, argc, argv - Standard command arguments
1392*d29b2c44Sab  */
1393*d29b2c44Sab static elfedit_cmdret_t
1394*d29b2c44Sab cmd_body(SYM_CMD_T cmd, elfedit_obj_state_t *obj_state,
1395*d29b2c44Sab     int argc, const char *argv[])
1396*d29b2c44Sab {
1397*d29b2c44Sab 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
1398*d29b2c44Sab 	ARGSTATE		*argstate;
1399*d29b2c44Sab 	SYMSTATE		*symstate;
1400*d29b2c44Sab 	Word			tblndx;
1401*d29b2c44Sab 
1402*d29b2c44Sab 	argstate = process_args(obj_state, argc, argv, cmd);
1403*d29b2c44Sab 
1404*d29b2c44Sab 	/*
1405*d29b2c44Sab 	 * If there are not 2 arguments, then this is a display request.
1406*d29b2c44Sab 	 * If no arguments are present, the full table (or tables) is
1407*d29b2c44Sab 	 * dumped. If there is one argument, then the specified item is shown.
1408*d29b2c44Sab 	 */
1409*d29b2c44Sab 	if (argstate->argc < 2) {
1410*d29b2c44Sab 		print_sym(cmd, 0, argstate);
1411*d29b2c44Sab 		return (ELFEDIT_CMDRET_NONE);
1412*d29b2c44Sab 	}
1413*d29b2c44Sab 
1414*d29b2c44Sab 	/*
1415*d29b2c44Sab 	 * When processing multiple symbol tables, it is important that
1416*d29b2c44Sab 	 * any failure happen before anything is changed. Otherwise, you
1417*d29b2c44Sab 	 * can end up in a situation where things are left in an inconsistent
1418*d29b2c44Sab 	 * half done state. sym:st_name has that issue when the -name_offset
1419*d29b2c44Sab 	 * option is used, because the string may be insertable into some
1420*d29b2c44Sab 	 * (dynstr) string tables, but not all of them. So, do the tests
1421*d29b2c44Sab 	 * up front, and refuse to continue if any string insertions would
1422*d29b2c44Sab 	 * fail.
1423*d29b2c44Sab 	 */
1424*d29b2c44Sab 	if ((cmd == SYM_CMD_T_ST_NAME) && (argstate->numsymstate > 1) &&
1425*d29b2c44Sab 	    ((argstate->optmask & SYM_OPT_F_NAMOFFSET) == 0)) {
1426*d29b2c44Sab 		symstate = argstate->symstate;
1427*d29b2c44Sab 		for (tblndx = 0; tblndx < argstate->numsymstate;
1428*d29b2c44Sab 		    tblndx++, symstate++)
1429*d29b2c44Sab 			elfedit_strtab_insert_test(obj_state, symstate->str.sec,
1430*d29b2c44Sab 			    NULL, argstate->argv[1]);
1431*d29b2c44Sab 	}
1432*d29b2c44Sab 
1433*d29b2c44Sab 
1434*d29b2c44Sab 	/* Loop over the table(s) and make the specified value change */
1435*d29b2c44Sab 	symstate = argstate->symstate;
1436*d29b2c44Sab 	for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++)
1437*d29b2c44Sab 		if (symstate_cmd_body(cmd, argstate, symstate) ==
1438*d29b2c44Sab 		    ELFEDIT_CMDRET_MOD)
1439*d29b2c44Sab 			ret = ELFEDIT_CMDRET_MOD;
1440*d29b2c44Sab 
1441*d29b2c44Sab 	/* Do autoprint */
1442*d29b2c44Sab 	print_sym(cmd, 1, argstate);
1443*d29b2c44Sab 
1444*d29b2c44Sab 	return (ret);
1445*d29b2c44Sab }
1446*d29b2c44Sab 
1447*d29b2c44Sab 
1448*d29b2c44Sab 
1449*d29b2c44Sab 
1450*d29b2c44Sab /*
1451*d29b2c44Sab  * Command completion functions for the various commands
1452*d29b2c44Sab  */
1453*d29b2c44Sab 
1454*d29b2c44Sab /*
1455*d29b2c44Sab  * Handle filling in the values for -shnam, -shndx, and -shtyp options.
1456*d29b2c44Sab  */
1457*d29b2c44Sab /*ARGSUSED*/
1458*d29b2c44Sab static void
1459*d29b2c44Sab cpl_sh_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1460*d29b2c44Sab     const char *argv[], int num_opt)
1461*d29b2c44Sab {
1462*d29b2c44Sab 	enum { NAME, INDEX, TYPE }	op;
1463*d29b2c44Sab 	elfedit_symtab_t		*symtab;
1464*d29b2c44Sab 	Word 	tblndx;
1465*d29b2c44Sab 
1466*d29b2c44Sab 	if ((argc != num_opt) || (argc < 2))
1467*d29b2c44Sab 		return;
1468*d29b2c44Sab 
1469*d29b2c44Sab 	if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) {
1470*d29b2c44Sab 		op = NAME;
1471*d29b2c44Sab 	} else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) {
1472*d29b2c44Sab 		op = INDEX;
1473*d29b2c44Sab 
1474*d29b2c44Sab 	} else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) {
1475*d29b2c44Sab 		op = TYPE;
1476*d29b2c44Sab 		if (obj_state == NULL)	 /* No object available */
1477*d29b2c44Sab 			elfedit_cpl_atoconst(cpldata,
1478*d29b2c44Sab 			    ELFEDIT_CONST_SHT_ALLSYMTAB);
1479*d29b2c44Sab 	} else {
1480*d29b2c44Sab 		return;
1481*d29b2c44Sab 	}
1482*d29b2c44Sab 
1483*d29b2c44Sab 	if (obj_state == NULL)	 /* No object available */
1484*d29b2c44Sab 		return;
1485*d29b2c44Sab 
1486*d29b2c44Sab 	/*
1487*d29b2c44Sab 	 * Loop over the symbol tables and supply command completion
1488*d29b2c44Sab 	 * for the items in the file.
1489*d29b2c44Sab 	 */
1490*d29b2c44Sab 	symtab = obj_state->os_symtab;
1491*d29b2c44Sab 	for (tblndx = 0; tblndx < obj_state->os_symtabnum;
1492*d29b2c44Sab 	    tblndx++, symtab++) {
1493*d29b2c44Sab 		elfedit_section_t *sec =
1494*d29b2c44Sab 		    &obj_state->os_secarr[symtab->symt_shndx];
1495*d29b2c44Sab 
1496*d29b2c44Sab 		switch (op) {
1497*d29b2c44Sab 		case NAME:
1498*d29b2c44Sab 			elfedit_cpl_match(cpldata, sec->sec_name, 0);
1499*d29b2c44Sab 			break;
1500*d29b2c44Sab 		case INDEX:
1501*d29b2c44Sab 			{
1502*d29b2c44Sab 				char index[MAXNDXSIZE];
1503*d29b2c44Sab 
1504*d29b2c44Sab 				(void) snprintf(index, sizeof (index),
1505*d29b2c44Sab 				    MSG_ORIG(MSG_FMT_WORDVAL),
1506*d29b2c44Sab 				    symtab->symt_shndx);
1507*d29b2c44Sab 				elfedit_cpl_match(cpldata, index, 1);
1508*d29b2c44Sab 			}
1509*d29b2c44Sab 			break;
1510*d29b2c44Sab 		case TYPE:
1511*d29b2c44Sab 			{
1512*d29b2c44Sab 				elfedit_atoui_sym_t *cpl_list;
1513*d29b2c44Sab 
1514*d29b2c44Sab 				(void) elfedit_sec_issymtab(sec, 1, &cpl_list);
1515*d29b2c44Sab 				elfedit_cpl_atoui(cpldata, cpl_list);
1516*d29b2c44Sab 			}
1517*d29b2c44Sab 			break;
1518*d29b2c44Sab 		}
1519*d29b2c44Sab 	}
1520*d29b2c44Sab }
1521*d29b2c44Sab 
1522*d29b2c44Sab /*ARGSUSED*/
1523*d29b2c44Sab static void
1524*d29b2c44Sab cpl_st_bind(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1525*d29b2c44Sab     const char *argv[], int num_opt)
1526*d29b2c44Sab {
1527*d29b2c44Sab 	/* Handle -shXXX options */
1528*d29b2c44Sab 	cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt);
1529*d29b2c44Sab 
1530*d29b2c44Sab 	/* The second argument can be an STB_ value */
1531*d29b2c44Sab 	if (argc == (num_opt + 2))
1532*d29b2c44Sab 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STB);
1533*d29b2c44Sab }
1534*d29b2c44Sab 
1535*d29b2c44Sab /*ARGSUSED*/
1536*d29b2c44Sab static void
1537*d29b2c44Sab cpl_st_shndx(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1538*d29b2c44Sab     const char *argv[], int num_opt)
1539*d29b2c44Sab {
1540*d29b2c44Sab 	elfedit_section_t *sec;
1541*d29b2c44Sab 	enum { NAME, INDEX, TYPE } op;
1542*d29b2c44Sab 	Word ndx;
1543*d29b2c44Sab 
1544*d29b2c44Sab 	/* Handle -shXXX options */
1545*d29b2c44Sab 	cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt);
1546*d29b2c44Sab 
1547*d29b2c44Sab 	/*
1548*d29b2c44Sab 	 * The second argument can be a section name, a section
1549*d29b2c44Sab 	 * index (-secshndx), or a section type (-secshtyp). We
1550*d29b2c44Sab 	 * can do completions for each of these.
1551*d29b2c44Sab 	 */
1552*d29b2c44Sab 	if (argc != (num_opt + 2))
1553*d29b2c44Sab 		return;
1554*d29b2c44Sab 
1555*d29b2c44Sab 	op = NAME;
1556*d29b2c44Sab 	for (ndx = 0; ndx < num_opt; ndx++) {
1557*d29b2c44Sab 		if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SECSHNDX)) == 0)
1558*d29b2c44Sab 			op = INDEX;
1559*d29b2c44Sab 		else if (strcmp(argv[ndx],
1560*d29b2c44Sab 		    MSG_ORIG(MSG_STR_MINUS_SECSHTYP)) == 0)
1561*d29b2c44Sab 			op = TYPE;
1562*d29b2c44Sab 	}
1563*d29b2c44Sab 
1564*d29b2c44Sab 	switch (op) {
1565*d29b2c44Sab 	case NAME:
1566*d29b2c44Sab 		if (obj_state == NULL)
1567*d29b2c44Sab 			break;
1568*d29b2c44Sab 		sec = obj_state->os_secarr;
1569*d29b2c44Sab 		for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++)
1570*d29b2c44Sab 			elfedit_cpl_match(cpldata, sec->sec_name, 0);
1571*d29b2c44Sab 		break;
1572*d29b2c44Sab 
1573*d29b2c44Sab 	case INDEX:
1574*d29b2c44Sab 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHN);
1575*d29b2c44Sab 		break;
1576*d29b2c44Sab 
1577*d29b2c44Sab 	case TYPE:
1578*d29b2c44Sab 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT);
1579*d29b2c44Sab 		break;
1580*d29b2c44Sab 	}
1581*d29b2c44Sab }
1582*d29b2c44Sab 
1583*d29b2c44Sab /*ARGSUSED*/
1584*d29b2c44Sab static void
1585*d29b2c44Sab cpl_st_type(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1586*d29b2c44Sab     const char *argv[], int num_opt)
1587*d29b2c44Sab {
1588*d29b2c44Sab 	/* Handle -shXXX options */
1589*d29b2c44Sab 	cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt);
1590*d29b2c44Sab 
1591*d29b2c44Sab 	/* The second argument can be an STT_ value */
1592*d29b2c44Sab 	if (argc == (num_opt + 2))
1593*d29b2c44Sab 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STT);
1594*d29b2c44Sab }
1595*d29b2c44Sab 
1596*d29b2c44Sab /*ARGSUSED*/
1597*d29b2c44Sab static void
1598*d29b2c44Sab cpl_st_visibility(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1599*d29b2c44Sab     const char *argv[], int num_opt)
1600*d29b2c44Sab {
1601*d29b2c44Sab 	/* Handle -shXXX options */
1602*d29b2c44Sab 	cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt);
1603*d29b2c44Sab 
1604*d29b2c44Sab 	/* The second argument can be an STV_ value */
1605*d29b2c44Sab 	if (argc == (num_opt + 2))
1606*d29b2c44Sab 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STV);
1607*d29b2c44Sab }
1608*d29b2c44Sab 
1609*d29b2c44Sab 
1610*d29b2c44Sab 
1611*d29b2c44Sab /*
1612*d29b2c44Sab  * Implementation functions for the commands
1613*d29b2c44Sab  */
1614*d29b2c44Sab static elfedit_cmdret_t
1615*d29b2c44Sab cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1616*d29b2c44Sab {
1617*d29b2c44Sab 	return (cmd_body(SYM_CMD_T_DUMP, obj_state, argc, argv));
1618*d29b2c44Sab }
1619*d29b2c44Sab 
1620*d29b2c44Sab 
1621*d29b2c44Sab static elfedit_cmdret_t
1622*d29b2c44Sab cmd_st_bind(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1623*d29b2c44Sab {
1624*d29b2c44Sab 	return (cmd_body(SYM_CMD_T_ST_BIND, obj_state, argc, argv));
1625*d29b2c44Sab }
1626*d29b2c44Sab 
1627*d29b2c44Sab 
1628*d29b2c44Sab static elfedit_cmdret_t
1629*d29b2c44Sab cmd_st_info(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1630*d29b2c44Sab {
1631*d29b2c44Sab 	return (cmd_body(SYM_CMD_T_ST_INFO, obj_state, argc, argv));
1632*d29b2c44Sab }
1633*d29b2c44Sab 
1634*d29b2c44Sab static elfedit_cmdret_t
1635*d29b2c44Sab cmd_st_name(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1636*d29b2c44Sab {
1637*d29b2c44Sab 	return (cmd_body(SYM_CMD_T_ST_NAME, obj_state, argc, argv));
1638*d29b2c44Sab }
1639*d29b2c44Sab 
1640*d29b2c44Sab static elfedit_cmdret_t
1641*d29b2c44Sab cmd_st_other(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1642*d29b2c44Sab {
1643*d29b2c44Sab 	return (cmd_body(SYM_CMD_T_ST_OTHER, obj_state, argc, argv));
1644*d29b2c44Sab }
1645*d29b2c44Sab 
1646*d29b2c44Sab static elfedit_cmdret_t
1647*d29b2c44Sab cmd_st_shndx(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1648*d29b2c44Sab {
1649*d29b2c44Sab 	return (cmd_body(SYM_CMD_T_ST_SHNDX, obj_state, argc, argv));
1650*d29b2c44Sab }
1651*d29b2c44Sab 
1652*d29b2c44Sab static elfedit_cmdret_t
1653*d29b2c44Sab cmd_st_size(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1654*d29b2c44Sab {
1655*d29b2c44Sab 	return (cmd_body(SYM_CMD_T_ST_SIZE, obj_state, argc, argv));
1656*d29b2c44Sab }
1657*d29b2c44Sab 
1658*d29b2c44Sab static elfedit_cmdret_t
1659*d29b2c44Sab cmd_st_type(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1660*d29b2c44Sab {
1661*d29b2c44Sab 	return (cmd_body(SYM_CMD_T_ST_TYPE, obj_state, argc, argv));
1662*d29b2c44Sab }
1663*d29b2c44Sab 
1664*d29b2c44Sab static elfedit_cmdret_t
1665*d29b2c44Sab cmd_st_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1666*d29b2c44Sab {
1667*d29b2c44Sab 	return (cmd_body(SYM_CMD_T_ST_VALUE, obj_state, argc, argv));
1668*d29b2c44Sab }
1669*d29b2c44Sab 
1670*d29b2c44Sab static elfedit_cmdret_t
1671*d29b2c44Sab cmd_st_visibility(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1672*d29b2c44Sab {
1673*d29b2c44Sab 	return (cmd_body(SYM_CMD_T_ST_VISIBILITY, obj_state, argc, argv));
1674*d29b2c44Sab }
1675*d29b2c44Sab 
1676*d29b2c44Sab 
1677*d29b2c44Sab 
1678*d29b2c44Sab /*ARGSUSED*/
1679*d29b2c44Sab elfedit_module_t *
1680*d29b2c44Sab elfedit_init(elfedit_module_version_t version)
1681*d29b2c44Sab {
1682*d29b2c44Sab 	/* Multiple commands accept only the standard set of options */
1683*d29b2c44Sab 	static elfedit_cmd_optarg_t opt_std[] = {
1684*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
1685*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
1686*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
1687*d29b2c44Sab 		    SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP },
1688*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0 },
1689*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
1690*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1691*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
1692*d29b2c44Sab 		    SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP },
1693*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
1694*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
1695*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1696*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
1697*d29b2c44Sab 		    SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX },
1698*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
1699*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SYMNDX),
1700*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SYMNDX) */
1701*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, SYM_OPT_F_SYMNDX },
1702*d29b2c44Sab 		{ ELFEDIT_STDOA_OPT_O, NULL,
1703*d29b2c44Sab 		    ELFEDIT_CMDOA_F_INHERIT, 0 },
1704*d29b2c44Sab 		{ NULL }
1705*d29b2c44Sab 	};
1706*d29b2c44Sab 
1707*d29b2c44Sab 	/* sym:dump */
1708*d29b2c44Sab 	static const char *name_dump[] = {
1709*d29b2c44Sab 	    MSG_ORIG(MSG_CMD_DUMP),
1710*d29b2c44Sab 	    MSG_ORIG(MSG_STR_EMPTY),	/* "" makes this the default command */
1711*d29b2c44Sab 	    NULL
1712*d29b2c44Sab 	};
1713*d29b2c44Sab 	static elfedit_cmd_optarg_t opt_dump[] = {
1714*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
1715*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
1716*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
1717*d29b2c44Sab 		    SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP },
1718*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0 },
1719*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
1720*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1721*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
1722*d29b2c44Sab 		    SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP },
1723*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
1724*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
1725*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1726*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
1727*d29b2c44Sab 		    SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX },
1728*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
1729*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SYMNDX),
1730*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SYMNDX) */
1731*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, SYM_OPT_F_SYMNDX },
1732*d29b2c44Sab 		{ NULL }
1733*d29b2c44Sab 	};
1734*d29b2c44Sab 	static elfedit_cmd_optarg_t arg_dump[] = {
1735*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SYM),
1736*d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SYM) */
1737*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
1738*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1739*d29b2c44Sab 		{ NULL }
1740*d29b2c44Sab 	};
1741*d29b2c44Sab 
1742*d29b2c44Sab 	/* sym:st_bind */
1743*d29b2c44Sab 	static const char *name_st_bind[] = {
1744*d29b2c44Sab 	    MSG_ORIG(MSG_CMD_ST_BIND), NULL };
1745*d29b2c44Sab 	static elfedit_cmd_optarg_t arg_st_bind[] = {
1746*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SYM),
1747*d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SYM) */
1748*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
1749*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1750*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1751*d29b2c44Sab 		    /* MSG_INTL(MSG_A2_DESC_ST_BIND) */
1752*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_BIND),
1753*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1754*d29b2c44Sab 		{ NULL }
1755*d29b2c44Sab 	};
1756*d29b2c44Sab 
1757*d29b2c44Sab 	/* sym:st_info */
1758*d29b2c44Sab 	static const char *name_st_info[] = {
1759*d29b2c44Sab 	    MSG_ORIG(MSG_CMD_ST_INFO), NULL };
1760*d29b2c44Sab 	static elfedit_cmd_optarg_t arg_st_info[] = {
1761*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SYM),
1762*d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SYM) */
1763*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
1764*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1765*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1766*d29b2c44Sab 		    /* MSG_INTL(MSG_A2_DESC_ST_INFO) */
1767*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_INFO),
1768*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1769*d29b2c44Sab 		{ NULL }
1770*d29b2c44Sab 	};
1771*d29b2c44Sab 
1772*d29b2c44Sab 	/* sym:st_name */
1773*d29b2c44Sab 	static const char *name_st_name[] = {
1774*d29b2c44Sab 	    MSG_ORIG(MSG_CMD_ST_NAME), NULL };
1775*d29b2c44Sab 	static elfedit_cmd_optarg_t opt_st_name[] = {
1776*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
1777*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
1778*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
1779*d29b2c44Sab 		    SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP },
1780*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0, 0 },
1781*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
1782*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1783*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
1784*d29b2c44Sab 		    SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP },
1785*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 },
1786*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
1787*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1788*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
1789*d29b2c44Sab 		    SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX },
1790*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0, 0 },
1791*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SYMNDX),
1792*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SYMNDX) */
1793*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0,
1794*d29b2c44Sab 		    SYM_OPT_F_SYMNDX, 0 },
1795*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_NAME_OFFSET),
1796*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_NAME_OFFSET) */
1797*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_NAME_OFFSET), 0,
1798*d29b2c44Sab 		    SYM_OPT_F_NAMOFFSET, 0 },
1799*d29b2c44Sab 		{ ELFEDIT_STDOA_OPT_O, NULL,
1800*d29b2c44Sab 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1801*d29b2c44Sab 		{ NULL }
1802*d29b2c44Sab 	};
1803*d29b2c44Sab 	static elfedit_cmd_optarg_t arg_st_name[] = {
1804*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SYM),
1805*d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SYM) */
1806*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
1807*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1808*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_NAME),
1809*d29b2c44Sab 		    /* MSG_INTL(MSG_A2_DESC_ST_NAME) */
1810*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_NAME),
1811*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1812*d29b2c44Sab 		{ NULL }
1813*d29b2c44Sab 	};
1814*d29b2c44Sab 
1815*d29b2c44Sab 	/* sym:st_other */
1816*d29b2c44Sab 	static const char *name_st_other[] = {
1817*d29b2c44Sab 	    MSG_ORIG(MSG_CMD_ST_OTHER), NULL };
1818*d29b2c44Sab 	static elfedit_cmd_optarg_t arg_st_other[] = {
1819*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SYM),
1820*d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SYM) */
1821*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
1822*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1823*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1824*d29b2c44Sab 		    /* MSG_INTL(MSG_A2_DESC_ST_OTHER) */
1825*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_OTHER),
1826*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1827*d29b2c44Sab 		{ NULL }
1828*d29b2c44Sab 	};
1829*d29b2c44Sab 
1830*d29b2c44Sab 	/* sym:st_shndx */
1831*d29b2c44Sab 	static const char *name_st_shndx[] = {
1832*d29b2c44Sab 	    MSG_ORIG(MSG_CMD_ST_SHNDX), NULL };
1833*d29b2c44Sab 	static elfedit_cmd_optarg_t opt_st_shndx[] = {
1834*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_E),
1835*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_E) */
1836*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_E), 0, SYM_OPT_F_XSHINDEX, 0 },
1837*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
1838*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
1839*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
1840*d29b2c44Sab 		    SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP },
1841*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0, 0 },
1842*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
1843*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
1844*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
1845*d29b2c44Sab 		    SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP },
1846*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 },
1847*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
1848*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
1849*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
1850*d29b2c44Sab 		    SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX },
1851*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0, 0 },
1852*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SYMNDX),
1853*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SYMNDX) */
1854*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0,
1855*d29b2c44Sab 		    SYM_OPT_F_SYMNDX, 0 },
1856*d29b2c44Sab 		{ ELFEDIT_STDOA_OPT_O, NULL,
1857*d29b2c44Sab 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
1858*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SECSHNDX),
1859*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SECSHNDX) */
1860*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SECSHNDX),
1861*d29b2c44Sab 		    0, SYM_OPT_F_SECSHNDX, SYM_OPT_F_SECSHTYP },
1862*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_SECSHTYP),
1863*d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_SECSHTYP) */
1864*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SECSHTYP),
1865*d29b2c44Sab 		    0, SYM_OPT_F_SECSHTYP, SYM_OPT_F_SECSHNDX },
1866*d29b2c44Sab 		{ NULL }
1867*d29b2c44Sab 	};
1868*d29b2c44Sab 	static elfedit_cmd_optarg_t arg_st_shndx[] = {
1869*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SYM),
1870*d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SYM) */
1871*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
1872*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1873*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SEC),
1874*d29b2c44Sab 		    /* MSG_INTL(MSG_A2_DESC_ST_SEC) */
1875*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_SEC),
1876*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1877*d29b2c44Sab 		{ NULL }
1878*d29b2c44Sab 	};
1879*d29b2c44Sab 
1880*d29b2c44Sab 	/* sym:st_size */
1881*d29b2c44Sab 	static const char *name_st_size[] = {
1882*d29b2c44Sab 	    MSG_ORIG(MSG_CMD_ST_SIZE), NULL };
1883*d29b2c44Sab 	static elfedit_cmd_optarg_t arg_st_size[] = {
1884*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SYM),
1885*d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SYM) */
1886*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
1887*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1888*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1889*d29b2c44Sab 		    /* MSG_INTL(MSG_A2_DESC_ST_SIZE) */
1890*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_SIZE),
1891*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1892*d29b2c44Sab 		{ NULL }
1893*d29b2c44Sab 	};
1894*d29b2c44Sab 
1895*d29b2c44Sab 	/* sym:st_type */
1896*d29b2c44Sab 	static const char *name_st_type[] = {
1897*d29b2c44Sab 	    MSG_ORIG(MSG_CMD_ST_TYPE), NULL };
1898*d29b2c44Sab 	static elfedit_cmd_optarg_t arg_st_type[] = {
1899*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SYM),
1900*d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SYM) */
1901*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
1902*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1903*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1904*d29b2c44Sab 		    /* MSG_INTL(MSG_A2_DESC_ST_TYPE) */
1905*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_TYPE),
1906*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1907*d29b2c44Sab 		{ NULL }
1908*d29b2c44Sab 	};
1909*d29b2c44Sab 
1910*d29b2c44Sab 	/* sym:st_value */
1911*d29b2c44Sab 	static const char *name_st_value[] = {
1912*d29b2c44Sab 	    MSG_ORIG(MSG_CMD_ST_VALUE), NULL };
1913*d29b2c44Sab 	static elfedit_cmd_optarg_t arg_st_value[] = {
1914*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SYM),
1915*d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SYM) */
1916*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
1917*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1918*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1919*d29b2c44Sab 		    /* MSG_INTL(MSG_A2_DESC_ST_VALUE) */
1920*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_VALUE),
1921*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1922*d29b2c44Sab 		{ NULL }
1923*d29b2c44Sab 	};
1924*d29b2c44Sab 
1925*d29b2c44Sab 	/* sym:st_visibility */
1926*d29b2c44Sab 	static const char *name_st_visibility[] = {
1927*d29b2c44Sab 	    MSG_ORIG(MSG_CMD_ST_VISIBILITY), NULL };
1928*d29b2c44Sab 	static elfedit_cmd_optarg_t arg_st_visibility[] = {
1929*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_SYM),
1930*d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SYM) */
1931*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
1932*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1933*d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1934*d29b2c44Sab 		    /* MSG_INTL(MSG_A2_DESC_ST_VISIBILITY) */
1935*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_VISIBILITY),
1936*d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1937*d29b2c44Sab 		{ NULL }
1938*d29b2c44Sab 	};
1939*d29b2c44Sab 
1940*d29b2c44Sab 	static elfedit_cmd_t cmds[] = {
1941*d29b2c44Sab 		/* sym:dump */
1942*d29b2c44Sab 		{ cmd_dump, cpl_sh_opt, name_dump,
1943*d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_DUMP) */
1944*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_DUMP),
1945*d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_DUMP) */
1946*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_DUMP),
1947*d29b2c44Sab 		    opt_dump, arg_dump },
1948*d29b2c44Sab 
1949*d29b2c44Sab 		/* sym:st_bind */
1950*d29b2c44Sab 		{ cmd_st_bind, cpl_st_bind, name_st_bind,
1951*d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_ST_BIND) */
1952*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_ST_BIND),
1953*d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_ST_BIND) */
1954*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_ST_BIND),
1955*d29b2c44Sab 		    opt_std, arg_st_bind },
1956*d29b2c44Sab 
1957*d29b2c44Sab 		/* sym:st_info */
1958*d29b2c44Sab 		{ cmd_st_info, cpl_sh_opt, name_st_info,
1959*d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_ST_INFO) */
1960*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_ST_INFO),
1961*d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_ST_INFO) */
1962*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_ST_INFO),
1963*d29b2c44Sab 		    opt_std, arg_st_info },
1964*d29b2c44Sab 
1965*d29b2c44Sab 		/* sym:st_name */
1966*d29b2c44Sab 		{ cmd_st_name, cpl_sh_opt, name_st_name,
1967*d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_ST_NAME) */
1968*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_ST_NAME),
1969*d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_ST_NAME) */
1970*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_ST_NAME),
1971*d29b2c44Sab 		    opt_st_name, arg_st_name },
1972*d29b2c44Sab 
1973*d29b2c44Sab 		/* sym:st_other */
1974*d29b2c44Sab 		{ cmd_st_other, cpl_sh_opt, name_st_other,
1975*d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_ST_OTHER) */
1976*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_ST_OTHER),
1977*d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_ST_OTHER) */
1978*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_ST_OTHER),
1979*d29b2c44Sab 		    opt_std, arg_st_other },
1980*d29b2c44Sab 
1981*d29b2c44Sab 		/* sym:st_shndx */
1982*d29b2c44Sab 		{ cmd_st_shndx, cpl_st_shndx, name_st_shndx,
1983*d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_ST_SHNDX) */
1984*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_ST_SHNDX),
1985*d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_ST_SHNDX) */
1986*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_ST_SHNDX),
1987*d29b2c44Sab 		    opt_st_shndx, arg_st_shndx },
1988*d29b2c44Sab 
1989*d29b2c44Sab 		/* sym:st_size */
1990*d29b2c44Sab 		{ cmd_st_size, cpl_sh_opt, name_st_size,
1991*d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_ST_SIZE) */
1992*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_ST_SIZE),
1993*d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_ST_SIZE) */
1994*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_ST_SIZE),
1995*d29b2c44Sab 		    opt_std, arg_st_size },
1996*d29b2c44Sab 
1997*d29b2c44Sab 		/* sym:st_type */
1998*d29b2c44Sab 		{ cmd_st_type, cpl_st_type, name_st_type,
1999*d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_ST_TYPE) */
2000*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_ST_TYPE),
2001*d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_ST_TYPE) */
2002*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_ST_TYPE),
2003*d29b2c44Sab 		    opt_std, arg_st_type },
2004*d29b2c44Sab 
2005*d29b2c44Sab 		/* sym:st_value */
2006*d29b2c44Sab 		{ cmd_st_value, cpl_sh_opt, name_st_value,
2007*d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_ST_VALUE) */
2008*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_ST_VALUE),
2009*d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_ST_VALUE) */
2010*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_ST_VALUE),
2011*d29b2c44Sab 		    opt_std, arg_st_value },
2012*d29b2c44Sab 
2013*d29b2c44Sab 		/* sym:st_visibility */
2014*d29b2c44Sab 		{ cmd_st_visibility, cpl_st_visibility, name_st_visibility,
2015*d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_ST_VISIBILITY) */
2016*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_ST_VISIBILITY),
2017*d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_ST_VISIBILITY) */
2018*d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_ST_VISIBILITY),
2019*d29b2c44Sab 		    opt_std, arg_st_visibility },
2020*d29b2c44Sab 
2021*d29b2c44Sab 		{ NULL }
2022*d29b2c44Sab 	};
2023*d29b2c44Sab 
2024*d29b2c44Sab 	static elfedit_module_t module = {
2025*d29b2c44Sab 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
2026*d29b2c44Sab 	    /* MSG_INTL(MSG_MOD_DESC) */
2027*d29b2c44Sab 	    ELFEDIT_I18NHDL(MSG_MOD_DESC),
2028*d29b2c44Sab 	    cmds, mod_i18nhdl_to_str };
2029*d29b2c44Sab 
2030*d29b2c44Sab 	return (&module);
2031*d29b2c44Sab }
2032