xref: /onnv-gate/usr/src/cmd/sgs/elfedit/modules/common/sym.c (revision 9273:9a0603d78ad3)
15088Sab196087 /*
25088Sab196087  * CDDL HEADER START
35088Sab196087  *
45088Sab196087  * The contents of this file are subject to the terms of the
55088Sab196087  * Common Development and Distribution License (the "License").
65088Sab196087  * You may not use this file except in compliance with the License.
75088Sab196087  *
85088Sab196087  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95088Sab196087  * or http://www.opensolaris.org/os/licensing.
105088Sab196087  * See the License for the specific language governing permissions
115088Sab196087  * and limitations under the License.
125088Sab196087  *
135088Sab196087  * When distributing Covered Code, include this CDDL HEADER in each
145088Sab196087  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155088Sab196087  * If applicable, add the following below this CDDL HEADER, with the
165088Sab196087  * fields enclosed by brackets "[]" replaced with your own identifying
175088Sab196087  * information: Portions Copyright [yyyy] [name of copyright owner]
185088Sab196087  *
195088Sab196087  * CDDL HEADER END
205088Sab196087  */
215088Sab196087 
225088Sab196087 /*
23*9273SAli.Bahrami@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245088Sab196087  * Use is subject to license terms.
255088Sab196087  */
265088Sab196087 
275088Sab196087 #define	ELF_TARGET_AMD64	/* SHN_AMD64_LCOMMON */
285088Sab196087 
295088Sab196087 #include	<stdio.h>
305088Sab196087 #include	<unistd.h>
315088Sab196087 #include	<elfedit.h>
325088Sab196087 #include	<strings.h>
335088Sab196087 #include	<debug.h>
345088Sab196087 #include	<conv.h>
355088Sab196087 #include	<sym_msg.h>
365088Sab196087 
375088Sab196087 
385088Sab196087 
395088Sab196087 
405088Sab196087 #define	MAXNDXSIZE	10
415088Sab196087 
425088Sab196087 
435088Sab196087 
445088Sab196087 /*
455088Sab196087  * This module uses shared code for several of the commands.
465088Sab196087  * It is sometimes necessary to know which specific command
475088Sab196087  * is active.
485088Sab196087  */
495088Sab196087 typedef enum {
505088Sab196087 	SYM_CMD_T_DUMP =		0,	/* sym:dump */
515088Sab196087 
525088Sab196087 	SYM_CMD_T_ST_BIND =		1,	/* sym:st_bind */
535088Sab196087 	SYM_CMD_T_ST_INFO =		2,	/* sym:st_info */
545088Sab196087 	SYM_CMD_T_ST_NAME =		3,	/* sym:st_name */
555088Sab196087 	SYM_CMD_T_ST_OTHER =		4,	/* sym:st_other */
565088Sab196087 	SYM_CMD_T_ST_SHNDX =		5,	/* sym:st_shndx */
575088Sab196087 	SYM_CMD_T_ST_SIZE =		6,	/* sym:st_size */
585088Sab196087 	SYM_CMD_T_ST_TYPE =		7,	/* sym:st_type */
595088Sab196087 	SYM_CMD_T_ST_VALUE =		8,	/* sym:st_value */
605088Sab196087 	SYM_CMD_T_ST_VISIBILITY =	9	/* sym:st_visibility */
615088Sab196087 } SYM_CMD_T;
625088Sab196087 
635088Sab196087 
645088Sab196087 
655088Sab196087 /*
665088Sab196087  * ELFCLASS-specific definitions
675088Sab196087  */
685088Sab196087 #ifdef _ELF64
695088Sab196087 
705088Sab196087 #define	MSG_FMT_XWORDVALNL MSG_FMT_XWORDVALNL_64
715088Sab196087 
725088Sab196087 #else
735088Sab196087 
745088Sab196087 #define	MSG_FMT_XWORDVALNL MSG_FMT_XWORDVALNL_32
755088Sab196087 
765088Sab196087 /*
775088Sab196087  * We supply this function for the msg module. Only one copy is needed.
785088Sab196087  */
795088Sab196087 const char *
_sym_msg(Msg mid)805088Sab196087 _sym_msg(Msg mid)
815088Sab196087 {
825088Sab196087 	return (gettext(MSG_ORIG(mid)));
835088Sab196087 }
845088Sab196087 
855088Sab196087 #endif
865088Sab196087 
875088Sab196087 
885088Sab196087 
895088Sab196087 /*
905088Sab196087  * This function is supplied to elfedit through our elfedit_module_t
915088Sab196087  * definition. It translates the opaque elfedit_i18nhdl_t handles
925088Sab196087  * in our module interface into the actual strings for elfedit to
935088Sab196087  * use.
945088Sab196087  *
955088Sab196087  * note:
965088Sab196087  *	This module uses Msg codes for its i18n handle type.
975088Sab196087  *	So the translation is simply to use MSG_INTL() to turn
985088Sab196087  *	it into a string and return it.
995088Sab196087  */
1005088Sab196087 static const char *
mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)1015088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
1025088Sab196087 {
1035088Sab196087 	Msg msg = (Msg)hdl;
1045088Sab196087 
1055088Sab196087 	return (MSG_INTL(msg));
1065088Sab196087 }
1075088Sab196087 
1085088Sab196087 
1095088Sab196087 
1105088Sab196087 /*
1115088Sab196087  * The sym_opt_t enum specifies a bit value for every optional
1125088Sab196087  * argument allowed by a command in this module.
1135088Sab196087  */
1145088Sab196087 typedef enum {
1155088Sab196087 	SYM_OPT_F_XSHINDEX =	1,	/* -e: Force shndx update to extended */
1165088Sab196087 					/*	 index section */
1175088Sab196087 	SYM_OPT_F_NAMOFFSET =	2,	/* -name_offset: sym:st_name name arg */
1185088Sab196087 					/*	is numeric offset */
1195088Sab196087 					/* 	rather than ASCII string */
1205088Sab196087 	SYM_OPT_F_SECSHNDX =	4,	/* -secshndx: Section arg is */
1215088Sab196087 					/*	section index, not name */
1225088Sab196087 	SYM_OPT_F_SECSHTYP =	8,	/* -secshtyp: Section arg is */
1235088Sab196087 					/*	section type, not name */
1245088Sab196087 	SYM_OPT_F_SHNAME =	16,	/* -shnam name: section spec. by name */
1255088Sab196087 	SYM_OPT_F_SHNDX =	32,	/* -shndx ndx: section spec. by index */
1265088Sab196087 	SYM_OPT_F_SHTYP =	64,	/* -shtyp type: section spec. by type */
1275088Sab196087 	SYM_OPT_F_SYMNDX =	128	/* -symndx: Sym specified by index */
1285088Sab196087 } sym_opt_t;
1295088Sab196087 
1305088Sab196087 
1315088Sab196087 /*
1325088Sab196087  * A variable of type ARGSTATE is used by each command to maintain
1335088Sab196087  * the overall state for a given set of arguments and the symbol tables
1345088Sab196087  * being managed.
1355088Sab196087  *
1365088Sab196087  * The state for each symbol table and the auxiliary sections that are
1375088Sab196087  * related to it are kept in a SYMSTATE sub-struct.
1385088Sab196087  *
1395088Sab196087  * One benefit of ARGSTATE is that it helps us to ensure that we only
1405088Sab196087  * fetch each section a single time:
1415088Sab196087  *	- More efficient
1425088Sab196087  *	- Prevents multiple ELFEDIT_MSG_DEBUG messages from
1435088Sab196087  *	  being produced for a given section.
1445088Sab196087  *
1455088Sab196087  * note: The symstate array in ARGSTATE is defined as having one
1465088Sab196087  *	element, but in reality, we allocate enough room for
1475088Sab196087  *	the number of elements defined in the numsymstate field.
1485088Sab196087  */
1495088Sab196087 typedef struct {
1505088Sab196087 	Word ndx;	/* If argstate.argc > 0, this is the table index */
1515088Sab196087 	struct {				/* Symbol table */
1525088Sab196087 		elfedit_section_t	*sec;
1535088Sab196087 		Sym			*data;
1545088Sab196087 		Word			n;
1555088Sab196087 	} sym;
1565088Sab196087 	struct {				/* String table */
1575088Sab196087 		elfedit_section_t	*sec;
1585088Sab196087 	} str;
1595088Sab196087 	struct {				/* Versym */
1605088Sab196087 		Word			shndx;
1615088Sab196087 		elfedit_section_t	*sec;
1625088Sab196087 		Versym			*data;
1635088Sab196087 		Word			n;
1645088Sab196087 	} versym;
1655088Sab196087 	struct {				/* Extended section indices */
1665088Sab196087 		Word			shndx;
1675088Sab196087 		elfedit_section_t	*sec;
1685088Sab196087 		Word			*data;
1695088Sab196087 		Word			n;
1705088Sab196087 	} xshndx;
1715088Sab196087 } SYMSTATE;
1725088Sab196087 typedef struct {
1735088Sab196087 	elfedit_obj_state_t	*obj_state;
1745088Sab196087 	sym_opt_t		optmask;   	/* Mask of options used */
1755088Sab196087 	int			argc;		/* # of plain arguments */
1765088Sab196087 	const char		**argv;		/* Plain arguments */
1775088Sab196087 	int			numsymstate;	/* # of items in symstate[] */
1785088Sab196087 	SYMSTATE		symstate[1];	/* Symbol tables to process */
1795088Sab196087 } ARGSTATE;
1805088Sab196087 
1815088Sab196087 
1825088Sab196087 /*
1835088Sab196087  * We maintain the state of each symbol table and related associated
1845088Sab196087  * sections in a SYMSTATE structure . We don't look those auxiliary
1855088Sab196087  * things up unless we actually need them, both to be efficient,
1865088Sab196087  * and to prevent duplicate ELFEDIT_MSG_DEBUG messages from being
1875088Sab196087  * issued as they are located. Hence, process_args() is used to
1885088Sab196087  * initialize the state block with just the symbol table, and then one
1895088Sab196087  * of the argstate_add_XXX() functions is used as needed
1905088Sab196087  * to fetch the additional sections.
1915088Sab196087  *
1925088Sab196087  * entry:
1935088Sab196087  *	argstate - Overall state block
1945088Sab196087  *	symstate - State block for current symbol table.
1955088Sab196087  *
1965088Sab196087  * exit:
1975088Sab196087  *	If the needed auxiliary section is not found, an error is
1985088Sab196087  *	issued and the argstate_add_XXX() routine does not return.
1995088Sab196087  *	Otherwise, the fields in argstate have been filled in, ready
2005088Sab196087  *	for use.
2015088Sab196087  *
2025088Sab196087  */
2035088Sab196087 static void
symstate_add_str(ARGSTATE * argstate,SYMSTATE * symstate)2045088Sab196087 symstate_add_str(ARGSTATE *argstate, SYMSTATE *symstate)
2055088Sab196087 {
2065088Sab196087 	if (symstate->str.sec != NULL)
2075088Sab196087 		return;
2085088Sab196087 
2095088Sab196087 	symstate->str.sec = elfedit_sec_getstr(argstate->obj_state,
2106225Sab196087 	    symstate->sym.sec->sec_shdr->sh_link, 0);
2115088Sab196087 }
2125088Sab196087 static void
symstate_add_versym(ARGSTATE * argstate,SYMSTATE * symstate)2135088Sab196087 symstate_add_versym(ARGSTATE *argstate, SYMSTATE *symstate)
2145088Sab196087 {
2155088Sab196087 	if (symstate->versym.sec != NULL)
2165088Sab196087 		return;
2175088Sab196087 
2185088Sab196087 	symstate->versym.sec = elfedit_sec_getversym(argstate->obj_state,
2195088Sab196087 	    symstate->sym.sec, &symstate->versym.data, &symstate->versym.n);
2205088Sab196087 }
2215088Sab196087 static void
symstate_add_xshndx(ARGSTATE * argstate,SYMSTATE * symstate)2225088Sab196087 symstate_add_xshndx(ARGSTATE *argstate, SYMSTATE *symstate)
2235088Sab196087 {
2245088Sab196087 	if (symstate->xshndx.sec != NULL)
2255088Sab196087 		return;
2265088Sab196087 
2275088Sab196087 	symstate->xshndx.sec = elfedit_sec_getxshndx(argstate->obj_state,
2285088Sab196087 	    symstate->sym.sec, &symstate->xshndx.data, &symstate->xshndx.n);
2295088Sab196087 }
2305088Sab196087 
2315088Sab196087 
2325088Sab196087 
2335088Sab196087 /*
2345088Sab196087  * Display symbol table entries in the style used by elfdump.
2355088Sab196087  *
2365088Sab196087  * entry:
2375088Sab196087  *	argstate - Overall state block
2385088Sab196087  *	symstate - State block for current symbol table.
2395088Sab196087  *	ndx - Index of first symbol to display
2405088Sab196087  *	cnt - Number of symbols to display
2415088Sab196087  */
2425088Sab196087 static void
dump_symtab(ARGSTATE * argstate,SYMSTATE * symstate,Word ndx,Word cnt)2435088Sab196087 dump_symtab(ARGSTATE *argstate, SYMSTATE *symstate, Word ndx, Word cnt)
2445088Sab196087 {
2455088Sab196087 	char			index[MAXNDXSIZE];
2465088Sab196087 	Word			shndx;
2475088Sab196087 	const char		*shndx_name;
2485088Sab196087 	elfedit_section_t	*symsec;
2495088Sab196087 	elfedit_section_t	*strsec;
2505088Sab196087 	Sym			*sym;
2515088Sab196087 	elfedit_obj_state_t	*obj_state = argstate->obj_state;
252*9273SAli.Bahrami@Sun.COM 	uchar_t			osabi = obj_state->os_ehdr->e_ident[EI_OSABI];
2535088Sab196087 	Half			mach = obj_state->os_ehdr->e_machine;
2545088Sab196087 	const char		*symname;
2555088Sab196087 	Versym			versym;
2565088Sab196087 
2575088Sab196087 	symsec = symstate->sym.sec;
2585088Sab196087 	sym = symstate->sym.data + ndx;
2595088Sab196087 
2605088Sab196087 	symstate_add_str(argstate, symstate);
2615088Sab196087 	strsec = symstate->str.sec;
2625088Sab196087 
2635088Sab196087 	/* If there is a versym index section, fetch it */
2645088Sab196087 	if (symstate->versym.shndx != SHN_UNDEF)
2655088Sab196087 		symstate_add_versym(argstate, symstate);
2665088Sab196087 
2675088Sab196087 	/* If there is an extended index section, fetch it */
2685088Sab196087 	if (symstate->xshndx.shndx != SHN_UNDEF)
2695088Sab196087 		symstate_add_xshndx(argstate, symstate);
2705088Sab196087 
2715088Sab196087 	elfedit_printf(MSG_INTL(MSG_FMT_SYMTAB), symsec->sec_name);
2725088Sab196087 	Elf_syms_table_title(0, ELF_DBG_ELFDUMP);
2735088Sab196087 	for (; cnt-- > 0; ndx++, sym++) {
2745088Sab196087 		(void) snprintf(index, MAXNDXSIZE,
2755088Sab196087 		    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(ndx));
2765088Sab196087 		versym = (symstate->versym.sec == NULL) ? 0 :
2775088Sab196087 		    symstate->versym.data[ndx];
2785088Sab196087 		symname = elfedit_offset_to_str(strsec, sym->st_name,
2795088Sab196087 		    ELFEDIT_MSG_DEBUG, 0);
2805088Sab196087 		shndx = sym->st_shndx;
2815088Sab196087 		if ((shndx == SHN_XINDEX) && (symstate->xshndx.sec != NULL))
2825088Sab196087 			shndx = symstate->xshndx.data[ndx];
2835088Sab196087 		shndx_name = elfedit_shndx_to_name(obj_state, shndx);
284*9273SAli.Bahrami@Sun.COM 		Elf_syms_table_entry(NULL, ELF_DBG_ELFDUMP, index, osabi, mach,
2855088Sab196087 		    sym, versym, 0, shndx_name, symname);
2865088Sab196087 	}
2875088Sab196087 }
2885088Sab196087 
2895088Sab196087 
2905088Sab196087 
2915088Sab196087 /*
2925088Sab196087  * Called by print_sym() to determine if a given symbol has the same
2935088Sab196087  * display value for the current command in every symbol table.
2945088Sab196087  *
2955088Sab196087  * entry:
2965088Sab196087  *	cmd - SYM_CMD_T_* value giving identify of caller
2975088Sab196087  *	argstate - Overall state block
2985088Sab196087  *	outstyle - Output style to use
2995088Sab196087  */
3005088Sab196087 static int
all_same(SYM_CMD_T cmd,ARGSTATE * argstate,elfedit_outstyle_t outstyle)3015088Sab196087 all_same(SYM_CMD_T cmd, ARGSTATE *argstate, elfedit_outstyle_t outstyle)
3025088Sab196087 {
3035088Sab196087 	Word			tblndx;
3045088Sab196087 	SYMSTATE		*symstate1, *symstate2;
3055088Sab196087 	Sym			*sym1, *sym2;
3065088Sab196087 
3075088Sab196087 	symstate1 = argstate->symstate;
3085088Sab196087 	for (tblndx = 0; tblndx < (argstate->numsymstate - 1);
3095088Sab196087 	    tblndx++, symstate1++) {
3105088Sab196087 		symstate2 = symstate1 + 1;
3115088Sab196087 		sym1 = &symstate1->sym.data[symstate1->ndx];
3125088Sab196087 		sym2 = &symstate2->sym.data[symstate2->ndx];
3135088Sab196087 
3145088Sab196087 		switch (cmd) {
3155088Sab196087 		case SYM_CMD_T_DUMP:
3165088Sab196087 			/* sym:dump should always show everything */
3175088Sab196087 			return (0);
3185088Sab196087 
3195088Sab196087 		case SYM_CMD_T_ST_BIND:
3205088Sab196087 			if (ELF_ST_BIND(sym1->st_info) !=
3215088Sab196087 			    ELF_ST_BIND(sym2->st_info))
3225088Sab196087 				return (0);
3235088Sab196087 			break;
3245088Sab196087 
3255088Sab196087 		case SYM_CMD_T_ST_INFO:
3265088Sab196087 			if (sym1->st_info !=  sym2->st_info)
3275088Sab196087 				return (0);
3285088Sab196087 			break;
3295088Sab196087 
3305088Sab196087 		case SYM_CMD_T_ST_NAME:
3315088Sab196087 			/*
3325088Sab196087 			 * In simple output mode, we show the string. In
3335088Sab196087 			 * numeric mode, we show the string table offset.
3345088Sab196087 			 */
3355088Sab196087 			if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
3365088Sab196087 				const char *n1, *n2;
3375088Sab196087 
3385088Sab196087 				symstate_add_str(argstate, symstate1);
3395088Sab196087 				symstate_add_str(argstate, symstate2);
3405088Sab196087 				n1 = elfedit_offset_to_str(symstate1->str.sec,
3415088Sab196087 				    sym1->st_name, ELFEDIT_MSG_DEBUG, 0);
3425088Sab196087 				n2 = elfedit_offset_to_str(symstate2->str.sec,
3435088Sab196087 				    sym2->st_name, ELFEDIT_MSG_DEBUG, 0);
3445088Sab196087 				if (strcmp(n1, n2) != 0)
3455088Sab196087 					return (0);
3465088Sab196087 			} else {
3475088Sab196087 				if (sym1->st_name !=  sym2->st_name)
3485088Sab196087 					return (0);
3495088Sab196087 			}
3505088Sab196087 			break;
3515088Sab196087 
3525088Sab196087 		case SYM_CMD_T_ST_OTHER:
3535088Sab196087 			if (sym1->st_other !=  sym2->st_other)
3545088Sab196087 				return (0);
3555088Sab196087 			break;
3565088Sab196087 
3575088Sab196087 		case SYM_CMD_T_ST_SHNDX:
3585088Sab196087 			{
3595088Sab196087 				Word	ndx1, ndx2;
3605088Sab196087 
3615088Sab196087 				ndx1 = sym1->st_shndx;
3625088Sab196087 				if ((ndx1 == SHN_XINDEX) &&
3635088Sab196087 				    (symstate1->xshndx.shndx != SHN_UNDEF)) {
3645088Sab196087 					symstate_add_xshndx(argstate,
3655088Sab196087 					    symstate1);
3665088Sab196087 					ndx1 = symstate1->xshndx.
3675088Sab196087 					    data[symstate1->ndx];
3685088Sab196087 				}
3695088Sab196087 				ndx2 = sym2->st_shndx;
3705088Sab196087 				if ((ndx2 == SHN_XINDEX) &&
3715088Sab196087 				    (symstate2->xshndx.shndx != SHN_UNDEF)) {
3725088Sab196087 					symstate_add_xshndx(argstate,
3735088Sab196087 					    symstate2);
3745088Sab196087 					ndx2 = symstate2->xshndx.
3755088Sab196087 					    data[symstate2->ndx];
3765088Sab196087 				}
3775088Sab196087 				if (ndx1 !=  ndx2)
3785088Sab196087 					return (0);
3795088Sab196087 			}
3805088Sab196087 			break;
3815088Sab196087 
3825088Sab196087 		case SYM_CMD_T_ST_SIZE:
3835088Sab196087 			if (sym1->st_size !=  sym2->st_size)
3845088Sab196087 				return (0);
3855088Sab196087 			break;
3865088Sab196087 
3875088Sab196087 		case SYM_CMD_T_ST_TYPE:
3885088Sab196087 			if (ELF_ST_TYPE(sym1->st_info) !=
3895088Sab196087 			    ELF_ST_TYPE(sym2->st_info))
3905088Sab196087 				return (0);
3915088Sab196087 			break;
3925088Sab196087 
3935088Sab196087 		case SYM_CMD_T_ST_VALUE:
3945088Sab196087 			if (sym1->st_value !=  sym2->st_value)
3955088Sab196087 				return (0);
3965088Sab196087 			break;
3975088Sab196087 
3985088Sab196087 		case SYM_CMD_T_ST_VISIBILITY:
3995088Sab196087 			if (ELF_ST_VISIBILITY(sym1->st_info) !=
4005088Sab196087 			    ELF_ST_VISIBILITY(sym2->st_info))
4015088Sab196087 				return (0);
4025088Sab196087 			break;
4035088Sab196087 		}
4045088Sab196087 	}
4055088Sab196087 
4065088Sab196087 	/* If we got here, there are no differences (or maybe only 1 table */
4075088Sab196087 	return (1);
4085088Sab196087 }
4095088Sab196087 
4105088Sab196087 
4115088Sab196087 /*
4125088Sab196087  * Called by print_sym() to display values for a single symbol table.
4135088Sab196087  *
4145088Sab196087  * entry:
4155088Sab196087  *	autoprint - If True, output is only produced if the elfedit
4165088Sab196087  *		autoprint flag is set. If False, output is always produced.
4175088Sab196087  *	cmd - SYM_CMD_T_* value giving identify of caller
4185088Sab196087  *	argstate - Overall state block
4195088Sab196087  *	symstate - State block for current symbol table.
4205088Sab196087  *	ndx - Index of first symbol to display
4215088Sab196087  *	cnt - Number of symbols to display
4225088Sab196087  */
4235088Sab196087 static void
print_symstate(SYM_CMD_T cmd,ARGSTATE * argstate,SYMSTATE * symstate,elfedit_outstyle_t outstyle,Word ndx,Word cnt)4245088Sab196087 print_symstate(SYM_CMD_T cmd, ARGSTATE *argstate, SYMSTATE *symstate,
4255088Sab196087     elfedit_outstyle_t outstyle, Word ndx, Word cnt)
4265088Sab196087 {
4275088Sab196087 	Word	value;
4285088Sab196087 	Sym	*sym;
4295088Sab196087 
4305088Sab196087 	/*
4315088Sab196087 	 * If doing default output, use elfdump style where we
4325088Sab196087 	 * show all symbol attributes. In this case, the command
4335088Sab196087 	 * that called us doesn't matter
4345088Sab196087 	 */
4355088Sab196087 	if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
4365088Sab196087 		dump_symtab(argstate, symstate, ndx, cnt);
4375088Sab196087 		return;
4385088Sab196087 	}
4395088Sab196087 
4405088Sab196087 	sym = symstate->sym.data;
4415088Sab196087 
4425088Sab196087 	switch (cmd) {
4435088Sab196087 	case SYM_CMD_T_ST_BIND:
4445088Sab196087 		{
4455088Sab196087 			Conv_inv_buf_t inv_buf;
4465088Sab196087 
4475088Sab196087 			for (sym += ndx; cnt--; sym++) {
4485088Sab196087 				value = ELF_ST_BIND(sym->st_info);
4495088Sab196087 				if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
4505088Sab196087 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
4515088Sab196087 					    conv_sym_info_bind(value,
452*9273SAli.Bahrami@Sun.COM 					    CONV_FMT_ALT_CF, &inv_buf));
4535088Sab196087 				} else {
4545088Sab196087 					elfedit_printf(
4555088Sab196087 					    MSG_ORIG(MSG_FMT_WORDVALNL),
4565088Sab196087 					    EC_WORD(value));
4575088Sab196087 				}
4585088Sab196087 			}
4595088Sab196087 		}
4605088Sab196087 		return;
4615088Sab196087 
4625088Sab196087 	case SYM_CMD_T_ST_INFO:
4635088Sab196087 		for (sym += ndx; cnt-- > 0; sym++)
4645088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
4655088Sab196087 			    EC_WORD(sym->st_info));
4665088Sab196087 		return;
4675088Sab196087 
4685088Sab196087 	case SYM_CMD_T_ST_NAME:
4695088Sab196087 		/*
4705088Sab196087 		 * In simple output mode, we show the string. In numeric
4715088Sab196087 		 * mode, we show the string table offset.
4725088Sab196087 		 */
4735088Sab196087 		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
4745088Sab196087 			symstate_add_str(argstate, symstate);
4755088Sab196087 			for (sym += ndx; cnt--; sym++) {
4765088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
4775088Sab196087 				    elfedit_offset_to_str(symstate->str.sec,
4785088Sab196087 				    sym->st_name, ELFEDIT_MSG_ERR, 0));
4795088Sab196087 			}
4805088Sab196087 		} else {
4815088Sab196087 			for (; cnt--; sym++)
4825088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
4835088Sab196087 				    EC_WORD(sym->st_name));
4845088Sab196087 		}
4855088Sab196087 		return;
4865088Sab196087 
4875088Sab196087 	case SYM_CMD_T_ST_OTHER:
4885088Sab196087 		for (sym += ndx; cnt-- > 0; sym++)
4895088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
4905088Sab196087 			    EC_WORD(sym->st_other));
4915088Sab196087 		return;
4925088Sab196087 
4935088Sab196087 	case SYM_CMD_T_ST_SHNDX:
4945088Sab196087 		/* If there is an extended index section, fetch it */
4955088Sab196087 		if (symstate->xshndx.shndx != SHN_UNDEF)
4965088Sab196087 			symstate_add_xshndx(argstate, symstate);
4975088Sab196087 
4985088Sab196087 		for (; cnt--; ndx++) {
4995088Sab196087 			value = sym[ndx].st_shndx;
5005088Sab196087 			if ((value == SHN_XINDEX) &&
5015088Sab196087 			    (symstate->xshndx.sec != NULL))
5025088Sab196087 				value = symstate->xshndx.data[ndx];
5035088Sab196087 
5045088Sab196087 			if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
5055088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
5065088Sab196087 				    elfedit_shndx_to_name(argstate->obj_state,
5075088Sab196087 				    value));
5085088Sab196087 			} else {
5095088Sab196087 				elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL),
5105088Sab196087 				    EC_WORD(value));
5115088Sab196087 			}
5125088Sab196087 		}
5135088Sab196087 		return;
5145088Sab196087 
5155088Sab196087 	case SYM_CMD_T_ST_SIZE:
5165088Sab196087 		/*
5175088Sab196087 		 * machine word width integers displayed in fixed width
5185088Sab196087 		 * 0-filled hex format.
5195088Sab196087 		 */
5205088Sab196087 		for (sym += ndx; cnt--; sym++)
5215088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_XWORDVALNL),
5225088Sab196087 			    sym->st_size);
5235088Sab196087 		return;
5245088Sab196087 
5255088Sab196087 	case SYM_CMD_T_ST_TYPE:
5265088Sab196087 		{
5275088Sab196087 			Half mach = argstate->obj_state->os_ehdr->e_machine;
5285088Sab196087 			Conv_inv_buf_t inv_buf;
5295088Sab196087 
5305088Sab196087 			for (sym += ndx; cnt--; sym++) {
5315088Sab196087 				value = ELF_ST_TYPE(sym->st_info);
5325088Sab196087 				if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
5335088Sab196087 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
5345088Sab196087 					    conv_sym_info_type(mach, value,
535*9273SAli.Bahrami@Sun.COM 					    CONV_FMT_ALT_CF, &inv_buf));
5365088Sab196087 				} else {
5375088Sab196087 					elfedit_printf(
5385088Sab196087 					    MSG_ORIG(MSG_FMT_WORDVALNL),
5395088Sab196087 					    EC_WORD(value));
5405088Sab196087 				}
5415088Sab196087 			}
5425088Sab196087 		}
5435088Sab196087 		return;
5445088Sab196087 
5455088Sab196087 	case SYM_CMD_T_ST_VALUE:
5465088Sab196087 		/*
5475088Sab196087 		 * machine word width integers displayed in fixed width
5485088Sab196087 		 * 0-filled hex format.
5495088Sab196087 		 */
5505088Sab196087 		for (sym += ndx; cnt--; sym++)
5515088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_XWORDVALNL),
5525088Sab196087 			    sym->st_value);
5535088Sab196087 		return;
5545088Sab196087 
5555088Sab196087 	case SYM_CMD_T_ST_VISIBILITY:
5565088Sab196087 		{
5575088Sab196087 			Conv_inv_buf_t inv_buf;
5585088Sab196087 
5595088Sab196087 			for (sym += ndx; cnt--; sym++) {
5605088Sab196087 				value = ELF_ST_VISIBILITY(sym->st_other);
5615088Sab196087 				if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
5625088Sab196087 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
5635088Sab196087 					    conv_sym_other_vis(value,
564*9273SAli.Bahrami@Sun.COM 					    CONV_FMT_ALT_CF, &inv_buf));
5655088Sab196087 				} else {
5665088Sab196087 					elfedit_printf(
5675088Sab196087 					    MSG_ORIG(MSG_FMT_WORDVALNL),
5685088Sab196087 					    EC_WORD(value));
5695088Sab196087 				}
5705088Sab196087 			}
5715088Sab196087 		}
5725088Sab196087 		return;
5735088Sab196087 
5745088Sab196087 	}
5755088Sab196087 }
5765088Sab196087 
5775088Sab196087 
5785088Sab196087 /*
5795088Sab196087  * Print symbol values, taking the calling command, and output style
5805088Sab196087  * into account.
5815088Sab196087  *
5825088Sab196087  * entry:
5835088Sab196087  *	autoprint - If True, output is only produced if the elfedit
5845088Sab196087  *		autoprint flag is set. If False, output is always produced.
5855088Sab196087  *	cmd - SYM_CMD_T_* value giving identify of caller
5865088Sab196087  *	argstate - Overall state block
5875088Sab196087  *	symstate - State block for current symbol table.
5885088Sab196087  *	ndx - Index of first symbol to display
5895088Sab196087  *	cnt - Number of symbols to display
5905088Sab196087  */
5915088Sab196087 static void
print_sym(SYM_CMD_T cmd,int autoprint,ARGSTATE * argstate)5925088Sab196087 print_sym(SYM_CMD_T cmd, int autoprint, ARGSTATE *argstate)
5935088Sab196087 {
5945088Sab196087 	Word			ndx, tblndx;
5955088Sab196087 	Word			cnt;
5965088Sab196087 	elfedit_outstyle_t	outstyle;
5975088Sab196087 	SYMSTATE		*symstate;
5985088Sab196087 	int			only_one;
5995088Sab196087 
6005088Sab196087 	if ((autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)))
6015088Sab196087 		return;
6025088Sab196087 
6035088Sab196087 	/*
6045088Sab196087 	 * Pick an output style. sym:dump is required to use the default
6055088Sab196087 	 * style. The other commands use the current output style.
6065088Sab196087 	 */
6075088Sab196087 	outstyle = (cmd == SYM_CMD_T_DUMP) ?
6085088Sab196087 	    ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
6095088Sab196087 
6105088Sab196087 	/*
6115088Sab196087 	 * This is a nicity: Force any needed auxiliary sections to be
6125088Sab196087 	 * fetched here before any output is produced. This will put all
6135088Sab196087 	 * of the debug messages right at the top in a single cluster.
6145088Sab196087 	 */
6155088Sab196087 	symstate = argstate->symstate;
6165088Sab196087 	for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) {
6175088Sab196087 		if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
6185088Sab196087 			symstate_add_str(argstate, symstate);
6195088Sab196087 			if (symstate->versym.shndx != SHN_UNDEF)
6205088Sab196087 				symstate_add_versym(argstate, symstate);
6215088Sab196087 			if (symstate->xshndx.shndx != SHN_UNDEF)
6225088Sab196087 				symstate_add_xshndx(argstate, symstate);
6235088Sab196087 			continue;
6245088Sab196087 		}
6255088Sab196087 
6265088Sab196087 		if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
6275088Sab196087 			switch (cmd) {
6285088Sab196087 			case SYM_CMD_T_ST_NAME:
6295088Sab196087 				symstate_add_str(argstate, symstate);
6305088Sab196087 				break;
6315088Sab196087 
6325088Sab196087 			case SYM_CMD_T_ST_SHNDX:
6335088Sab196087 				if (symstate->xshndx.shndx != SHN_UNDEF)
6345088Sab196087 					symstate_add_xshndx(argstate, symstate);
6355088Sab196087 				break;
6365088Sab196087 			}
6375088Sab196087 		}
6385088Sab196087 	}
6395088Sab196087 
6405088Sab196087 	/*
6415088Sab196087 	 * If there is more than one table, we are displaying a single
6425088Sab196087 	 * item, we are not using the default "elfdump" style, and all
6435088Sab196087 	 * the symbols have the same value for the thing we intend to
6445088Sab196087 	 * display, then we only want to display it once.
6455088Sab196087 	 */
6465088Sab196087 	only_one = (argstate->numsymstate > 1) && (argstate->argc > 0) &&
6475088Sab196087 	    (outstyle != ELFEDIT_OUTSTYLE_DEFAULT) &&
6485088Sab196087 	    all_same(cmd, argstate, outstyle);
6495088Sab196087 
6505088Sab196087 	/* Run through the tables and display from each one */
6515088Sab196087 	symstate = argstate->symstate;
6525088Sab196087 	for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) {
6535088Sab196087 		if (argstate->argc == 0) {
6545088Sab196087 			ndx = 0;
6555088Sab196087 			cnt = symstate->sym.n;
6565088Sab196087 		} else {
6575088Sab196087 			ndx = symstate->ndx;
6585088Sab196087 			cnt = 1;
6595088Sab196087 		}
6605088Sab196087 
6615088Sab196087 		if ((tblndx > 0) && ((argstate->argc == 0) ||
6625088Sab196087 		    (outstyle == ELFEDIT_OUTSTYLE_DEFAULT)))
6635088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
6645088Sab196087 
6655088Sab196087 		print_symstate(cmd, argstate, symstate, outstyle, ndx, cnt);
6665088Sab196087 		if (only_one)
6675088Sab196087 			break;
6685088Sab196087 	}
6695088Sab196087 }
6705088Sab196087 
6715088Sab196087 
6725088Sab196087 /*
6735088Sab196087  * The cmd_body_set_st_XXX() functions are for use by cmd_body().
6745088Sab196087  * They handle the case where the second plain argument is
6755088Sab196087  * a value to be stored in the symbol.
6765088Sab196087  *
6775088Sab196087  * entry:
6785088Sab196087  *	argstate - Overall state block
6795088Sab196087  *	symstate - State block for current symbol table.
6805088Sab196087  */
6815088Sab196087 static elfedit_cmdret_t
cmd_body_set_st_bind(ARGSTATE * argstate,SYMSTATE * symstate)6825088Sab196087 cmd_body_set_st_bind(ARGSTATE *argstate, SYMSTATE *symstate)
6835088Sab196087 {
6845088Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
6855088Sab196087 	Sym			*sym = &symstate->sym.data[symstate->ndx];
6865088Sab196087 	Word			gbl_ndx;
6875088Sab196087 	uchar_t			bind, type, old_bind;
6885088Sab196087 	Word			symndx;
6895088Sab196087 	Conv_inv_buf_t		inv_buf1, inv_buf2;
6905088Sab196087 
6915088Sab196087 	/*
6925088Sab196087 	 * Use the ELF_ST_BIND() macro to access the defined bits
6935088Sab196087 	 * of the st_info field related to symbol binding.
6945088Sab196087 	 * Accepts STB_ symbolic names as well as integers.
6955088Sab196087 	 */
6965088Sab196087 	bind = elfedit_atoconst_range(argstate->argv[1],
6975088Sab196087 	    MSG_INTL(MSG_ARG_SYMBIND), 0, 15, ELFEDIT_CONST_STB);
6985088Sab196087 	old_bind = ELF_ST_BIND(sym->st_info);
6995088Sab196087 	type = ELF_ST_TYPE(sym->st_info);
7005088Sab196087 
7015088Sab196087 	if (old_bind == bind) {
7025088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK),
7035088Sab196087 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
7045088Sab196087 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_BIND),
705*9273SAli.Bahrami@Sun.COM 		    conv_sym_info_bind(bind, CONV_FMT_ALT_CF, &inv_buf1));
7065088Sab196087 	} else {
7075088Sab196087 		/*
7085088Sab196087 		 * The sh_info field of the symbol table section header
7095088Sab196087 		 * gives the index of the first non-local symbol in
7105088Sab196087 		 * the table. Issue warnings if the binding we set
7115088Sab196087 		 * contradicts this.
7125088Sab196087 		 */
7135088Sab196087 		gbl_ndx = symstate->sym.sec->sec_shdr->sh_info;
7145088Sab196087 		symndx = symstate->sym.sec->sec_shndx;
7155088Sab196087 		if ((bind == STB_LOCAL) && (symstate->ndx >= gbl_ndx))
7165088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
7175088Sab196087 			    MSG_INTL(MSG_DEBUG_LBINDGSYM),
7185088Sab196087 			    EC_WORD(symndx), symstate->sym.sec->sec_name,
7195088Sab196087 			    symstate->ndx, EC_WORD(symndx), gbl_ndx);
7205088Sab196087 		if ((bind != STB_LOCAL) && (symstate->ndx < gbl_ndx))
7215088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
7225088Sab196087 			    MSG_INTL(MSG_DEBUG_GBINDLSYM),
7235088Sab196087 			    EC_WORD(symndx), symstate->sym.sec->sec_name,
7245088Sab196087 			    symstate->ndx, EC_WORD(symndx), gbl_ndx);
7255088Sab196087 
7265088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG),
7275088Sab196087 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
7285088Sab196087 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_BIND),
729*9273SAli.Bahrami@Sun.COM 		    conv_sym_info_bind(old_bind, CONV_FMT_ALT_CF,
7305088Sab196087 		    &inv_buf1),
731*9273SAli.Bahrami@Sun.COM 		    conv_sym_info_bind(bind, CONV_FMT_ALT_CF, &inv_buf2));
7325088Sab196087 		ret = ELFEDIT_CMDRET_MOD;
7335088Sab196087 		sym->st_info = ELF_ST_INFO(bind, type);
7345088Sab196087 	}
7355088Sab196087 
7365088Sab196087 	return (ret);
7375088Sab196087 }
7385088Sab196087 
7395088Sab196087 static elfedit_cmdret_t
cmd_body_set_st_name(ARGSTATE * argstate,SYMSTATE * symstate)7405088Sab196087 cmd_body_set_st_name(ARGSTATE *argstate, SYMSTATE *symstate)
7415088Sab196087 {
7425088Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
7435088Sab196087 	Sym			*sym = &symstate->sym.data[symstate->ndx];
7445088Sab196087 	Word	str_offset;
7455088Sab196087 
7465088Sab196087 	/*
7475088Sab196087 	 * If -n was specified, this is an offset into the string
7485088Sab196087 	 * table. Otherwise it is a string we need to turn into
7495088Sab196087 	 * an offset
7505088Sab196087 	 */
7515088Sab196087 	symstate_add_str(argstate, symstate);
7525088Sab196087 	if (argstate->optmask & SYM_OPT_F_NAMOFFSET) {
7535088Sab196087 		str_offset = elfedit_atoui(argstate->argv[1], NULL);
7545088Sab196087 		/* Warn if the offset is out of range */
7555088Sab196087 		(void) elfedit_offset_to_str(symstate->str.sec,
7565088Sab196087 		    str_offset, ELFEDIT_MSG_DEBUG, 1);
7575088Sab196087 	} else {
7585088Sab196087 		str_offset = elfedit_strtab_insert(argstate->obj_state,
7595088Sab196087 		    symstate->str.sec, NULL, argstate->argv[1]);
7605088Sab196087 	}
7615088Sab196087 
7625088Sab196087 	if (sym->st_name == str_offset) {
7635088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_D_OK),
7645088Sab196087 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
7655088Sab196087 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_NAME),
7665088Sab196087 		    EC_WORD(sym->st_name));
7675088Sab196087 	} else {
7685088Sab196087 		/*
7695088Sab196087 		 * Warn the user: Changing the name of a symbol in the dynsym
7705088Sab196087 		 * will break the hash table in this object.
7715088Sab196087 		 */
7725088Sab196087 		if (symstate->sym.sec->sec_shdr->sh_type == SHT_DYNSYM)
7735088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
7745088Sab196087 			    MSG_INTL(MSG_DEBUG_DYNSYMNAMCHG),
7755088Sab196087 			    EC_WORD(symstate->sym.sec->sec_shndx),
7765088Sab196087 			    symstate->sym.sec->sec_name,
7775088Sab196087 			    EC_WORD(symstate->ndx));
7785088Sab196087 
7795088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_D_CHG),
7805088Sab196087 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
7815088Sab196087 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_NAME),
7825088Sab196087 		    EC_WORD(sym->st_name),
7835088Sab196087 		    EC_WORD(str_offset));
7845088Sab196087 		ret = ELFEDIT_CMDRET_MOD;
7855088Sab196087 		sym->st_name = str_offset;
7865088Sab196087 	}
7875088Sab196087 
7885088Sab196087 	return (ret);
7895088Sab196087 }
7905088Sab196087 
7915088Sab196087 static elfedit_cmdret_t
cmd_body_set_st_shndx(ARGSTATE * argstate,SYMSTATE * symstate)7925088Sab196087 cmd_body_set_st_shndx(ARGSTATE *argstate, SYMSTATE *symstate)
7935088Sab196087 {
7945088Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
7955088Sab196087 	Sym			*sym = &symstate->sym.data[symstate->ndx];
7965088Sab196087 	Word	shndx, st_shndx, xshndx;
7975088Sab196087 	int	use_xshndx;
7985088Sab196087 	int	shndx_chg, xshndx_chg;
7995088Sab196087 
8005088Sab196087 
8015088Sab196087 	/*
8025088Sab196087 	 * By default, the sec argument is a section name. If -secshndx was
8035088Sab196087 	 * specified, it is a section index, and if -secshtyp is specified,
8045088Sab196087 	 * it is a section type.
8055088Sab196087 	 */
8065088Sab196087 	if (argstate->optmask & SYM_OPT_F_SECSHNDX)
8075088Sab196087 		shndx = elfedit_atoshndx(argstate->argv[1],
8085088Sab196087 		    argstate->obj_state->os_shnum);
8095088Sab196087 	else if (argstate->optmask & SYM_OPT_F_SECSHTYP)
8105088Sab196087 		shndx = elfedit_type_to_shndx(argstate->obj_state,
8115088Sab196087 		    elfedit_atoconst(argstate->argv[1], ELFEDIT_CONST_SHT));
8125088Sab196087 	else
8135088Sab196087 		shndx = elfedit_name_to_shndx(argstate->obj_state,
8145088Sab196087 		    argstate->argv[1]);
8155088Sab196087 
8165088Sab196087 	/*
8175088Sab196087 	 * We want to use an extended index section if the index is too
8185088Sab196087 	 * large to be represented otherwise, or if the caller specified
8195088Sab196087 	 * the -e option to make us do it anyway. However, we cannot
8205088Sab196087 	 * do this if the index is in the special reserved range between
8215088Sab196087 	 * SHN_LORESERVE and SHN_HIRESERVE.
8225088Sab196087 	 */
8235088Sab196087 	use_xshndx = (shndx > SHN_HIRESERVE) ||
8245088Sab196087 	    ((shndx < SHN_LORESERVE) &&
8255088Sab196087 	    (argstate->optmask & SYM_OPT_F_XSHINDEX));
8265088Sab196087 
8275088Sab196087 	/*
8285088Sab196087 	 * There are two cases where we have to touch the extended
8295088Sab196087 	 * index section:
8305088Sab196087 	 *
8315088Sab196087 	 *	1) We have determined that we need to, as determined above.
8325088Sab196087 	 *	2) We do not require it, but the file has an extended
8335088Sab196087 	 *		index section, in which case we should set the slot
8345088Sab196087 	 *		in that extended section to SHN_UNDEF (0).
8355088Sab196087 	 *
8365088Sab196087 	 * Fetch the extended section as required, and determine the values
8375088Sab196087 	 * for st_shndx and the extended section slot.
8385088Sab196087 	 */
8395088Sab196087 	if (use_xshndx) {
8405088Sab196087 		/* We must have an extended index section, or error out */
8415088Sab196087 		symstate_add_xshndx(argstate, symstate);
8425088Sab196087 
8435088Sab196087 		/* Set symbol to SHN_XINDEX, put index in the extended sec. */
8445088Sab196087 		st_shndx = SHN_XINDEX;
8455088Sab196087 		xshndx = shndx;
8465088Sab196087 	} else {
8475088Sab196087 		st_shndx = shndx;
8485088Sab196087 		xshndx = SHN_UNDEF;
8495088Sab196087 		if (symstate->xshndx.shndx != SHN_UNDEF)
8505088Sab196087 			use_xshndx = 1;
8515088Sab196087 	}
8525088Sab196087 	if (use_xshndx)
8535088Sab196087 		symstate_add_xshndx(argstate, symstate);
8545088Sab196087 	shndx_chg = (sym->st_shndx != st_shndx);
8555088Sab196087 	xshndx_chg = use_xshndx &&
8565088Sab196087 	    (symstate->xshndx.data[symstate->ndx] != xshndx);
8575088Sab196087 
8585088Sab196087 
8595088Sab196087 	/* If anything is going to change, issue appropiate warnings */
8605088Sab196087 	if (shndx_chg || xshndx_chg) {
8615088Sab196087 		/*
8625088Sab196087 		 * Setting the first symbol to anything other than SHN_UNDEF
8635088Sab196087 		 * produces a bad ELF file.
8645088Sab196087 		 */
8655088Sab196087 		if ((symstate->ndx == 0) && (shndx != SHN_UNDEF))
8665088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
8675088Sab196087 			    MSG_INTL(MSG_DEBUG_SHNDX_UNDEF0));
8685088Sab196087 
8695088Sab196087 		/*
8705088Sab196087 		 * Setting SHN_XINDEX directly, instead of providing
8715088Sab196087 		 * an extended index and letting us decide to use
8725088Sab196087 		 * SHN_XINDEX to implement it, is probably a mistake.
8735088Sab196087 		 * Issue a warning, but go ahead and follow the directions
8745088Sab196087 		 * we've been given.
8755088Sab196087 		 */
8765088Sab196087 		if (shndx == SHN_XINDEX)
8775088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
8785088Sab196087 			    MSG_INTL(MSG_DEBUG_SHNDX_XINDEX));
8795088Sab196087 
8805088Sab196087 		/*
8815088Sab196087 		 * If the section index can fit in the symbol, but
8825088Sab196087 		 * -e is being used to force it into the extended
8835088Sab196087 		 * index section, issue a warning.
8845088Sab196087 		 */
8855088Sab196087 		if (use_xshndx && (shndx < SHN_LORESERVE) &&
8865088Sab196087 		    (st_shndx == SHN_XINDEX))
8875088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
8885088Sab196087 			    MSG_INTL(MSG_DEBUG_SHNDX_EFORCE),
8895088Sab196087 			    EC_WORD(symstate->sym.sec->sec_shndx),
8905088Sab196087 			    symstate->sym.sec->sec_name, EC_WORD(symstate->ndx),
8915088Sab196087 			    EC_WORD(shndx));
8925088Sab196087 	}
8935088Sab196087 
8945088Sab196087 	if (shndx_chg) {
8955088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG),
8965088Sab196087 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
8975088Sab196087 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_SHNDX),
8985088Sab196087 		    elfedit_shndx_to_name(argstate->obj_state,
8995088Sab196087 		    sym->st_shndx),
9005088Sab196087 		    elfedit_shndx_to_name(argstate->obj_state, st_shndx));
9015088Sab196087 		ret = ELFEDIT_CMDRET_MOD;
9025088Sab196087 		sym->st_shndx = st_shndx;
9035088Sab196087 	} else {
9045088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK),
9055088Sab196087 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
9065088Sab196087 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_SHNDX),
9075088Sab196087 		    elfedit_shndx_to_name(argstate->obj_state, st_shndx));
9085088Sab196087 	}
9095088Sab196087 
9105088Sab196087 	if (use_xshndx) {
9115088Sab196087 		if (xshndx_chg) {
9125088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
9135088Sab196087 			    MSG_INTL(MSG_DEBUG_EXT_S_CHG),
9145088Sab196087 			    symstate->xshndx.sec->sec_shndx,
9155088Sab196087 			    symstate->xshndx.sec->sec_name,
9165088Sab196087 			    EC_WORD(symstate->ndx),
9175088Sab196087 			    elfedit_shndx_to_name(argstate->obj_state,
9185088Sab196087 			    symstate->xshndx.data[symstate->ndx]),
9195088Sab196087 			    elfedit_shndx_to_name(argstate->obj_state, xshndx));
9205088Sab196087 			ret = ELFEDIT_CMDRET_MOD;
9215088Sab196087 			symstate->xshndx.data[symstate->ndx] = xshndx;
9225088Sab196087 			elfedit_modified_data(symstate->xshndx.sec);
9235088Sab196087 		} else {
9245088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
9255088Sab196087 			    MSG_INTL(MSG_DEBUG_EXT_S_OK),
9265088Sab196087 			    symstate->xshndx.sec->sec_shndx,
9275088Sab196087 			    symstate->xshndx.sec->sec_name,
9285088Sab196087 			    EC_WORD(symstate->ndx),
9295088Sab196087 			    elfedit_shndx_to_name(argstate->obj_state, xshndx));
9305088Sab196087 		}
9315088Sab196087 	}
9325088Sab196087 
9335088Sab196087 	return (ret);
9345088Sab196087 }
9355088Sab196087 
9365088Sab196087 static elfedit_cmdret_t
cmd_body_set_st_type(ARGSTATE * argstate,SYMSTATE * symstate)9375088Sab196087 cmd_body_set_st_type(ARGSTATE *argstate, SYMSTATE *symstate)
9385088Sab196087 {
9395088Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
9405088Sab196087 	Conv_inv_buf_t	inv_buf1, inv_buf2;
9415088Sab196087 	Half		mach = argstate->obj_state->os_ehdr->e_machine;
9425088Sab196087 	Sym		*sym = &symstate->sym.data[symstate->ndx];
9435088Sab196087 	uchar_t		bind, type, old_type;
9445088Sab196087 
9455088Sab196087 	/*
9465088Sab196087 	 * Use the ELF_ST_TYPE() macro to access the defined bits
9475088Sab196087 	 * of the st_info field related to symbol type.
9485088Sab196087 	 * Accepts STT_ symbolic names as well as integers.
9495088Sab196087 	 */
9505088Sab196087 	bind = ELF_ST_BIND(sym->st_info);
9515088Sab196087 	type = elfedit_atoconst_range(argstate->argv[1],
9525088Sab196087 	    MSG_INTL(MSG_ARG_SYMBIND), 0, 15, ELFEDIT_CONST_STT);
9535088Sab196087 	old_type = ELF_ST_TYPE(sym->st_info);
9545088Sab196087 
9555088Sab196087 	if (old_type == type) {
9565088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK),
9575088Sab196087 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
9585088Sab196087 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_TYPE),
959*9273SAli.Bahrami@Sun.COM 		    conv_sym_info_type(mach, type, CONV_FMT_ALT_CF,
9605088Sab196087 		    &inv_buf1));
9615088Sab196087 	} else {
9625088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG),
9635088Sab196087 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
9645088Sab196087 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_TYPE),
965*9273SAli.Bahrami@Sun.COM 		    conv_sym_info_type(mach, old_type, CONV_FMT_ALT_CF,
9665088Sab196087 		    &inv_buf1),
967*9273SAli.Bahrami@Sun.COM 		    conv_sym_info_type(mach, type, CONV_FMT_ALT_CF,
9685088Sab196087 		    &inv_buf2));
9695088Sab196087 		ret = ELFEDIT_CMDRET_MOD;
9705088Sab196087 		sym->st_info = ELF_ST_INFO(bind, type);
9715088Sab196087 	}
9725088Sab196087 
9735088Sab196087 	return (ret);
9745088Sab196087 }
9755088Sab196087 
9765088Sab196087 static elfedit_cmdret_t
cmd_body_set_st_visibility(ARGSTATE * argstate,SYMSTATE * symstate)9775088Sab196087 cmd_body_set_st_visibility(ARGSTATE *argstate, SYMSTATE *symstate)
9785088Sab196087 {
9795088Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
9805088Sab196087 	Conv_inv_buf_t	inv_buf1, inv_buf2;
9815088Sab196087 	Sym		*sym = &symstate->sym.data[symstate->ndx];
9825088Sab196087 	uchar_t		st_other = sym->st_other;
9835088Sab196087 	uchar_t		vis, old_vis;
9845088Sab196087 
9855088Sab196087 	/*
9865088Sab196087 	 * Use the ELF_ST_VISIBILITY() macro to access the
9875088Sab196087 	 * defined bits of the st_other field related to symbol
9885088Sab196087 	 * visibility. Accepts STV_ symbolic names as well as integers.
9895088Sab196087 	 */
9905088Sab196087 	vis = elfedit_atoconst_range(argstate->argv[1],
9915220Srie 	    MSG_INTL(MSG_ARG_SYMVIS), 0, STV_ELIMINATE, ELFEDIT_CONST_STV);
9925088Sab196087 	old_vis = st_other & MSK_SYM_VISIBILITY;
9935088Sab196087 
9945088Sab196087 	if (old_vis == vis) {
9955088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK),
9965088Sab196087 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
9975088Sab196087 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_VISIBILITY),
998*9273SAli.Bahrami@Sun.COM 		    conv_sym_other_vis(old_vis, CONV_FMT_ALT_CF,
9995088Sab196087 		    &inv_buf1));
10005088Sab196087 	} else {
10015088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG),
10025088Sab196087 		    symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name,
10035088Sab196087 		    EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_VISIBILITY),
1004*9273SAli.Bahrami@Sun.COM 		    conv_sym_other_vis(old_vis, CONV_FMT_ALT_CF,
10055088Sab196087 		    &inv_buf1),
1006*9273SAli.Bahrami@Sun.COM 		    conv_sym_other_vis(vis, CONV_FMT_ALT_CF, &inv_buf2));
10075088Sab196087 		ret = ELFEDIT_CMDRET_MOD;
10085088Sab196087 		st_other = (st_other & ~MSK_SYM_VISIBILITY) |
10095088Sab196087 		    ELF_ST_VISIBILITY(vis);
10105088Sab196087 		sym->st_other = st_other;
10115088Sab196087 	}
10125088Sab196087 
10135088Sab196087 	return (ret);
10145088Sab196087 }
10155088Sab196087 
10165088Sab196087 
10175088Sab196087 /*
10185088Sab196087  * Standard argument processing for sym module
10195088Sab196087  *
10205088Sab196087  * entry
10215088Sab196087  *	obj_state, argc, argv - Standard command arguments
10225088Sab196087  *	optmask - Mask of allowed optional arguments.
10235088Sab196087  *	symstate - State block for current symbol table.
10245088Sab196087  *	argstate - Address of ARGSTATE block to be initialized
10255088Sab196087  *
10265088Sab196087  * exit:
10275088Sab196087  *	On success, *argstate is initialized. On error,
10285088Sab196087  *	an error is issued and this routine does not return.
10295088Sab196087  *
10305088Sab196087  * note:
10315088Sab196087  *	Only the basic symbol table is initially referenced by
10325088Sab196087  *	argstate. Use the argstate_add_XXX() routines below to
10335088Sab196087  *	access any auxiliary sections needed.
10345088Sab196087  */
10355088Sab196087 static ARGSTATE *
process_args(elfedit_obj_state_t * obj_state,int argc,const char * argv[],SYM_CMD_T cmd)10365088Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
10375088Sab196087     SYM_CMD_T cmd)
10385088Sab196087 {
10395088Sab196087 	/*
10405088Sab196087 	 * We reuse this same argstate, resizing it to the required
10415088Sab196087 	 * number of symbol tables on the first call, and as necessary.
10425088Sab196087 	 */
10435088Sab196087 	static ARGSTATE *argstate;
10445088Sab196087 	static int argstate_size = 0;
10455088Sab196087 
10465088Sab196087 	elfedit_getopt_state_t	getopt_state;
10475088Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
10485088Sab196087 	elfedit_symtab_t	*symtab;
10495088Sab196087 	int		explicit = 0;
10505088Sab196087 	int		got_sym = 0;
10515088Sab196087 	Word		index;
10525088Sab196087 	Word		tblndx;
10535088Sab196087 	size_t		size;
10545088Sab196087 	SYMSTATE	*symstate;
10555088Sab196087 
10565088Sab196087 	/* If there are no symbol tables, we can't do a thing */
10575088Sab196087 	if (obj_state->os_symtabnum == 0)
10585088Sab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMTAB));
10595088Sab196087 
10605088Sab196087 	/* Calulate required size of argstate and realloc as necessary */
10615088Sab196087 	size = sizeof (ARGSTATE) +
10625088Sab196087 	    ((obj_state->os_symtabnum - 1) * sizeof (SYMSTATE));
10635088Sab196087 	if (argstate_size != size) {
10645088Sab196087 		argstate = elfedit_realloc(MSG_INTL(MSG_ALLOC_ARGSTATE),
10655088Sab196087 		    argstate, size);
10665088Sab196087 		argstate_size = size;
10675088Sab196087 	}
10685088Sab196087 	bzero(argstate, argstate_size);
10695088Sab196087 	argstate->obj_state = obj_state;
10705088Sab196087 
10715088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
10725088Sab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
10735088Sab196087 		argstate->optmask |= getopt_ret->gor_idmask;
10745088Sab196087 		switch (getopt_ret->gor_idmask) {
10755088Sab196087 		case SYM_OPT_F_SHNAME:		/* -shnam name */
10765088Sab196087 			index = elfedit_name_to_shndx(obj_state,
10775088Sab196087 			    getopt_ret->gor_value);
10785088Sab196087 			explicit = 1;
10795088Sab196087 			break;
10805088Sab196087 
10815088Sab196087 		case SYM_OPT_F_SHNDX:		/* -shndx index */
10825088Sab196087 			index = elfedit_atoui_range(getopt_ret->gor_value,
10835088Sab196087 			    MSG_INTL(MSG_ARG_SECNDX), 1,
10845088Sab196087 			    obj_state->os_shnum - 1, NULL);
10855088Sab196087 			explicit = 1;
10865088Sab196087 			break;
10875088Sab196087 
10885088Sab196087 		case SYM_OPT_F_SHTYP:		/* -shtyp type */
10895088Sab196087 			index = elfedit_type_to_shndx(obj_state,
10905088Sab196087 			    elfedit_atoconst(getopt_ret->gor_value,
10915088Sab196087 			    ELFEDIT_CONST_SHT));
10925088Sab196087 			explicit = 1;
10935088Sab196087 			break;
10945088Sab196087 		}
10955088Sab196087 	}
10965088Sab196087 
10975088Sab196087 	/*
10985088Sab196087 	 * Usage error if there are too many plain arguments. sym:dump accepts
10995088Sab196087 	 * a single argument, while the others accept 2.
11005088Sab196087 	 */
11015088Sab196087 	if (((cmd == SYM_CMD_T_DUMP) && (argc > 1)) || (argc > 2))
11025088Sab196087 		elfedit_command_usage();
11035088Sab196087 
11045088Sab196087 	/*
11055088Sab196087 	 * If the -symndx option was specified, the sym arg is an index
11065088Sab196087 	 * into the symbol table. In this case, the symbol table must be
11075088Sab196087 	 * explicitly specified (-shnam, -shndx, or -shtype).
11085088Sab196087 	 */
11095088Sab196087 	if ((argstate->optmask & SYM_OPT_F_SYMNDX) && !explicit)
11105088Sab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEXPSYMTAB));
11115088Sab196087 
11125088Sab196087 	/*
1113*9273SAli.Bahrami@Sun.COM 	 * If a section was explicitly specified, it must be a symbol table.
11145088Sab196087 	 */
11155088Sab196087 	if (explicit)
1116*9273SAli.Bahrami@Sun.COM 		(void) elfedit_sec_issymtab(obj_state,
1117*9273SAli.Bahrami@Sun.COM 		    &obj_state->os_secarr[index], 1, NULL);
11185088Sab196087 
11195088Sab196087 	/* If there may be an arbitrary amount of output, use a pager */
11205088Sab196087 	if (argc == 0)
11215088Sab196087 		elfedit_pager_init();
11225088Sab196087 
11235088Sab196087 	/* Return the updated values of argc/argv */
11245088Sab196087 	argstate->argc = argc;
11255088Sab196087 	argstate->argv = argv;
11265088Sab196087 
11275088Sab196087 	/*
11285088Sab196087 	 * Decide which symbol table(s) to use. Set up the symstate
11295088Sab196087 	 * array to contain them:
11305088Sab196087 	 *	- If a symbol table was explicitly specified, we use
11315088Sab196087 	 *		it, and only it.
11325088Sab196087 	 *	- If no symbol table is explicitly specified, and the symbol
11335088Sab196087 	 *		is given by name, we use all symbol tables that
11345088Sab196087 	 *		contain a symbol with that name, throwing an error
11355088Sab196087 	 *		if there isn't at least 1 such table.
11365088Sab196087 	 *	- If no symbol table is specified, and no symbol is specified,
11375088Sab196087 	 *		we use all the tables.
11385088Sab196087 	 */
11395088Sab196087 	symtab = obj_state->os_symtab;
11405088Sab196087 	symstate = argstate->symstate;
11415088Sab196087 	for (tblndx = 0; tblndx < obj_state->os_symtabnum;
11425088Sab196087 	    tblndx++, symtab++) {
1143*9273SAli.Bahrami@Sun.COM 		/*
1144*9273SAli.Bahrami@Sun.COM 		 * If an explicit table is specified, only that table is
1145*9273SAli.Bahrami@Sun.COM 		 * considered.
1146*9273SAli.Bahrami@Sun.COM 		 *
1147*9273SAli.Bahrami@Sun.COM 		 * If no explicit table is specified, verify that table
1148*9273SAli.Bahrami@Sun.COM 		 * is considered to be a symbol table by the current osabi,
1149*9273SAli.Bahrami@Sun.COM 		 * and quietly skip it if not.
1150*9273SAli.Bahrami@Sun.COM 		 */
1151*9273SAli.Bahrami@Sun.COM 		if (explicit) {
1152*9273SAli.Bahrami@Sun.COM 			if (symtab->symt_shndx != index)
1153*9273SAli.Bahrami@Sun.COM 				continue;
1154*9273SAli.Bahrami@Sun.COM 		} else if (elfedit_sec_issymtab(obj_state,
1155*9273SAli.Bahrami@Sun.COM 		    &obj_state->os_secarr[symtab->symt_shndx], 0, NULL) == 0) {
11565088Sab196087 			continue;
1157*9273SAli.Bahrami@Sun.COM 		}
11585088Sab196087 
11595088Sab196087 		symstate->sym.sec = elfedit_sec_getsymtab(obj_state, 1,
11605088Sab196087 		    symtab->symt_shndx, NULL, &symstate->sym.data,
11615088Sab196087 		    &symstate->sym.n, &symtab);
11625088Sab196087 		symstate->versym.shndx = symtab->symt_versym;
11635088Sab196087 		symstate->xshndx.shndx = symtab->symt_xshndx;
11645088Sab196087 		if (argc > 0) {
11655088Sab196087 			if (argstate->optmask & SYM_OPT_F_SYMNDX) {
11665088Sab196087 				symstate->ndx = elfedit_atoui_range(
11675088Sab196087 				    argstate->argv[0], MSG_INTL(MSG_ARG_SYM), 0,
11685088Sab196087 				    symstate->sym.n - 1, NULL);
11695088Sab196087 			} else {
11705088Sab196087 				/*
11715088Sab196087 				 * arg is a symbol name. Use the index of
11725088Sab196087 				 * the first symbol that matches
11735088Sab196087 				 */
11745088Sab196087 
11755088Sab196087 				/*
11765088Sab196087 				 * We will use debug messages for failure up
11775088Sab196087 				 * until we run out of symbol tables. If we
11785088Sab196087 				 * don't find a table with the desired symbol
11795088Sab196087 				 * before the last table, we switch to error
11805088Sab196087 				 * messages. Hence, we will jump with an error
11815088Sab196087 				 * if no table will work.
11825088Sab196087 				 */
11835088Sab196087 				int err_type = (!got_sym &&
11845088Sab196087 				    ((tblndx + 1) == obj_state->os_symtabnum)) ?
11855088Sab196087 				    ELFEDIT_MSG_ERR : ELFEDIT_MSG_DEBUG;
11865088Sab196087 
11875088Sab196087 				symstate_add_str(argstate, symstate);
11885088Sab196087 
11895088Sab196087 				/*
11905088Sab196087 				 * If the symbol table doesn't have this
11915088Sab196087 				 * symbol, then forget it.
11925088Sab196087 				 */
11935088Sab196087 				if (elfedit_name_to_symndx(symstate->sym.sec,
11945088Sab196087 				    symstate->str.sec, argstate->argv[0],
11955088Sab196087 				    err_type, &symstate->ndx) == 0) {
11965088Sab196087 					bzero(symstate, sizeof (*symstate));
11975088Sab196087 					continue;
11985088Sab196087 				}
11995088Sab196087 			}
12005088Sab196087 		}
12015088Sab196087 		argstate->numsymstate++;
12025088Sab196087 		symstate++;
12035088Sab196087 		/*
12045088Sab196087 		 * If the symbol table was given explicitly, and
12055088Sab196087 		 * we've just taken it, then there is no reason to
12065088Sab196087 		 * continue searching.
12075088Sab196087 		 */
12085088Sab196087 		if (explicit)
12095088Sab196087 			break;
12105088Sab196087 	}
12115088Sab196087 
12125088Sab196087 	return (argstate);
12135088Sab196087 }
12145088Sab196087 
12155088Sab196087 
12165088Sab196087 
12175088Sab196087 /*
12185088Sab196087  * Called by cmd_body() to handle the value change for a single
12195088Sab196087  * symbol table.
12205088Sab196087  *
12215088Sab196087  * entry:
12225088Sab196087  *	cmd - One of the SYM_CMD_T_* constants listed above, specifying
12235088Sab196087  *		which command to implement.
12245088Sab196087  *	argstate - Overall state block
12255088Sab196087  *	symstate - State block for current symbol table.
12265088Sab196087  */
12275088Sab196087 static elfedit_cmdret_t
symstate_cmd_body(SYM_CMD_T cmd,ARGSTATE * argstate,SYMSTATE * symstate)12285088Sab196087 symstate_cmd_body(SYM_CMD_T cmd, ARGSTATE *argstate, SYMSTATE *symstate)
12295088Sab196087 {
12305088Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
12315088Sab196087 	Sym			*sym = &symstate->sym.data[symstate->ndx];
12325088Sab196087 
12335088Sab196087 	/* You're not supposed to change the value of symbol [0] */
12345088Sab196087 	if (symstate->ndx == 0)
12355088Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSYMELT0),
12365088Sab196087 		    EC_WORD(symstate->sym.sec->sec_shndx),
12375088Sab196087 		    symstate->sym.sec->sec_name, EC_WORD(symstate->ndx));
12385088Sab196087 
12395088Sab196087 	/* The second value is an integer giving a new value */
12405088Sab196087 	switch (cmd) {
12415088Sab196087 		/*
12425088Sab196087 		 * SYM_CMD_T_DUMP can't get here: It never has more than
12435088Sab196087 		 * one argument, and is handled above.
12445088Sab196087 		 */
12455088Sab196087 
12465088Sab196087 	case SYM_CMD_T_ST_BIND:
12475088Sab196087 		ret = cmd_body_set_st_bind(argstate, symstate);
12485088Sab196087 		break;
12495088Sab196087 
12505088Sab196087 	case SYM_CMD_T_ST_INFO:
12515088Sab196087 		{
12525088Sab196087 			/* Treat st_info as a raw integer field */
12535088Sab196087 			uchar_t st_info =
12545088Sab196087 			    elfedit_atoui(argstate->argv[1], NULL);
12555088Sab196087 
12565088Sab196087 			if (sym->st_info == st_info) {
12575088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
12585088Sab196087 				    MSG_INTL(MSG_DEBUG_D_OK),
12595088Sab196087 				    symstate->sym.sec->sec_shndx,
12605088Sab196087 				    symstate->sym.sec->sec_name,
12615088Sab196087 				    EC_WORD(symstate->ndx),
12625088Sab196087 				    MSG_ORIG(MSG_CMD_ST_INFO),
12635088Sab196087 				    EC_WORD(sym->st_info));
12645088Sab196087 			} else {
12655088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
12665088Sab196087 				    MSG_INTL(MSG_DEBUG_D_CHG),
12675088Sab196087 				    symstate->sym.sec->sec_shndx,
12685088Sab196087 				    symstate->sym.sec->sec_name,
12695088Sab196087 				    EC_WORD(symstate->ndx),
12705088Sab196087 				    MSG_ORIG(MSG_CMD_ST_INFO),
12715088Sab196087 				    EC_WORD(sym->st_info), EC_WORD(st_info));
12725088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
12735088Sab196087 				sym->st_info = st_info;
12745088Sab196087 			}
12755088Sab196087 		}
12765088Sab196087 	break;
12775088Sab196087 
12785088Sab196087 	case SYM_CMD_T_ST_NAME:
12795088Sab196087 		ret = cmd_body_set_st_name(argstate, symstate);
12805088Sab196087 		break;
12815088Sab196087 
12825088Sab196087 	case SYM_CMD_T_ST_OTHER:
12835088Sab196087 		{
12845088Sab196087 			/* Treat st_other as a raw integer field */
12855088Sab196087 			uchar_t st_other =
12865088Sab196087 			    elfedit_atoui(argstate->argv[1], NULL);
12875088Sab196087 
12885088Sab196087 			if (sym->st_other == st_other) {
12895088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
12905088Sab196087 				    MSG_INTL(MSG_DEBUG_D_OK),
12915088Sab196087 				    symstate->sym.sec->sec_shndx,
12925088Sab196087 				    symstate->sym.sec->sec_name,
12935088Sab196087 				    EC_WORD(symstate->ndx),
12945088Sab196087 				    MSG_ORIG(MSG_CMD_ST_OTHER),
12955088Sab196087 				    EC_WORD(sym->st_other));
12965088Sab196087 			} else {
12975088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
12985088Sab196087 				    MSG_INTL(MSG_DEBUG_D_CHG),
12995088Sab196087 				    symstate->sym.sec->sec_shndx,
13005088Sab196087 				    symstate->sym.sec->sec_name,
13015088Sab196087 				    EC_WORD(symstate->ndx),
13025088Sab196087 				    MSG_ORIG(MSG_CMD_ST_OTHER),
13035088Sab196087 				    EC_WORD(sym->st_other), EC_WORD(st_other));
13045088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
13055088Sab196087 				sym->st_other = st_other;
13065088Sab196087 			}
13075088Sab196087 		}
13085088Sab196087 		break;
13095088Sab196087 
13105088Sab196087 	case SYM_CMD_T_ST_SHNDX:
13115088Sab196087 		ret = cmd_body_set_st_shndx(argstate, symstate);
13125088Sab196087 		break;
13135088Sab196087 
13145088Sab196087 	case SYM_CMD_T_ST_SIZE:
13155088Sab196087 		{
13165088Sab196087 			Xword st_size = elfedit_atoui(argstate->argv[1], NULL);
13175088Sab196087 
13185088Sab196087 			if (sym->st_size == st_size) {
13195088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
13205088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_OK),
13215088Sab196087 				    symstate->sym.sec->sec_shndx,
13225088Sab196087 				    symstate->sym.sec->sec_name,
13235088Sab196087 				    EC_WORD(symstate->ndx),
13245088Sab196087 				    MSG_ORIG(MSG_CMD_ST_SIZE),
13255088Sab196087 				    EC_XWORD(sym->st_size));
13265088Sab196087 			} else {
13275088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
13285088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_CHG),
13295088Sab196087 				    symstate->sym.sec->sec_shndx,
13305088Sab196087 				    symstate->sym.sec->sec_name,
13315088Sab196087 				    EC_WORD(symstate->ndx),
13325088Sab196087 				    MSG_ORIG(MSG_CMD_ST_SIZE),
13335088Sab196087 				    EC_XWORD(sym->st_size), EC_XWORD(st_size));
13345088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
13355088Sab196087 				sym->st_size = st_size;
13365088Sab196087 			}
13375088Sab196087 		}
13385088Sab196087 		break;
13395088Sab196087 
13405088Sab196087 	case SYM_CMD_T_ST_TYPE:
13415088Sab196087 		ret = cmd_body_set_st_type(argstate, symstate);
13425088Sab196087 		break;
13435088Sab196087 
13445088Sab196087 	case SYM_CMD_T_ST_VALUE:
13455088Sab196087 		{
13465088Sab196087 			Addr st_value = elfedit_atoui(argstate->argv[1], NULL);
13475088Sab196087 
13485088Sab196087 			if (sym->st_value == st_value) {
13495088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
13505088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_OK),
13515088Sab196087 				    symstate->sym.sec->sec_shndx,
13525088Sab196087 				    symstate->sym.sec->sec_name,
13535088Sab196087 				    EC_WORD(symstate->ndx),
13545088Sab196087 				    MSG_ORIG(MSG_CMD_ST_VALUE),
13555088Sab196087 				    EC_ADDR(sym->st_value));
13565088Sab196087 			} else {
13575088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
13585088Sab196087 				    MSG_INTL(MSG_DEBUG_LLX_CHG),
13595088Sab196087 				    symstate->sym.sec->sec_shndx,
13605088Sab196087 				    symstate->sym.sec->sec_name,
13615088Sab196087 				    EC_WORD(symstate->ndx),
13625088Sab196087 				    MSG_ORIG(MSG_CMD_ST_VALUE),
13635088Sab196087 				    EC_ADDR(sym->st_value),
13645088Sab196087 				    EC_ADDR(st_value));
13655088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
13665088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
13675088Sab196087 				sym->st_value = st_value;
13685088Sab196087 			}
13695088Sab196087 		}
13705088Sab196087 		break;
13715088Sab196087 
13725088Sab196087 	case SYM_CMD_T_ST_VISIBILITY:
13735088Sab196087 		ret = cmd_body_set_st_visibility(argstate, symstate);
13745088Sab196087 		break;
13755088Sab196087 	}
13765088Sab196087 
13775088Sab196087 	/*
13785088Sab196087 	 * If we modified the symbol table, tell libelf.
13795088Sab196087 	 * Any other modified sections are the responsibility
13805088Sab196087 	 * of the cmd_body_set_st_*() function that did it, but
13815088Sab196087 	 * everyone modifies the table itself, so we handle that here.
13825088Sab196087 	 */
13835088Sab196087 	if (ret == ELFEDIT_CMDRET_MOD)
13845088Sab196087 		elfedit_modified_data(symstate->sym.sec);
13855088Sab196087 
13865088Sab196087 	return (ret);
13875088Sab196087 }
13885088Sab196087 
13895088Sab196087 
13905088Sab196087 
13915088Sab196087 
13925088Sab196087 /*
13935088Sab196087  * Common body for the sym: module commands. These commands
13945088Sab196087  * share a large amount of common behavior, so it is convenient
13955088Sab196087  * to centralize things and use the cmd argument to handle the
13965088Sab196087  * small differences.
13975088Sab196087  *
13985088Sab196087  * entry:
13995088Sab196087  *	cmd - One of the SYM_CMD_T_* constants listed above, specifying
14005088Sab196087  *		which command to implement.
14015088Sab196087  *	obj_state, argc, argv - Standard command arguments
14025088Sab196087  */
14035088Sab196087 static elfedit_cmdret_t
cmd_body(SYM_CMD_T cmd,elfedit_obj_state_t * obj_state,int argc,const char * argv[])14045088Sab196087 cmd_body(SYM_CMD_T cmd, elfedit_obj_state_t *obj_state,
14055088Sab196087     int argc, const char *argv[])
14065088Sab196087 {
14075088Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
14085088Sab196087 	ARGSTATE		*argstate;
14095088Sab196087 	SYMSTATE		*symstate;
14105088Sab196087 	Word			tblndx;
14115088Sab196087 
14125088Sab196087 	argstate = process_args(obj_state, argc, argv, cmd);
14135088Sab196087 
14145088Sab196087 	/*
14155088Sab196087 	 * If there are not 2 arguments, then this is a display request.
14165088Sab196087 	 * If no arguments are present, the full table (or tables) is
14175088Sab196087 	 * dumped. If there is one argument, then the specified item is shown.
14185088Sab196087 	 */
14195088Sab196087 	if (argstate->argc < 2) {
14205088Sab196087 		print_sym(cmd, 0, argstate);
14215088Sab196087 		return (ELFEDIT_CMDRET_NONE);
14225088Sab196087 	}
14235088Sab196087 
14245088Sab196087 	/*
14255088Sab196087 	 * When processing multiple symbol tables, it is important that
14265088Sab196087 	 * any failure happen before anything is changed. Otherwise, you
14275088Sab196087 	 * can end up in a situation where things are left in an inconsistent
14285088Sab196087 	 * half done state. sym:st_name has that issue when the -name_offset
14295088Sab196087 	 * option is used, because the string may be insertable into some
14305088Sab196087 	 * (dynstr) string tables, but not all of them. So, do the tests
14315088Sab196087 	 * up front, and refuse to continue if any string insertions would
14325088Sab196087 	 * fail.
14335088Sab196087 	 */
14345088Sab196087 	if ((cmd == SYM_CMD_T_ST_NAME) && (argstate->numsymstate > 1) &&
14355088Sab196087 	    ((argstate->optmask & SYM_OPT_F_NAMOFFSET) == 0)) {
14365088Sab196087 		symstate = argstate->symstate;
14375088Sab196087 		for (tblndx = 0; tblndx < argstate->numsymstate;
14385088Sab196087 		    tblndx++, symstate++)
14395088Sab196087 			elfedit_strtab_insert_test(obj_state, symstate->str.sec,
14405088Sab196087 			    NULL, argstate->argv[1]);
14415088Sab196087 	}
14425088Sab196087 
14435088Sab196087 
14445088Sab196087 	/* Loop over the table(s) and make the specified value change */
14455088Sab196087 	symstate = argstate->symstate;
14465088Sab196087 	for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++)
14475088Sab196087 		if (symstate_cmd_body(cmd, argstate, symstate) ==
14485088Sab196087 		    ELFEDIT_CMDRET_MOD)
14495088Sab196087 			ret = ELFEDIT_CMDRET_MOD;
14505088Sab196087 
14515088Sab196087 	/* Do autoprint */
14525088Sab196087 	print_sym(cmd, 1, argstate);
14535088Sab196087 
14545088Sab196087 	return (ret);
14555088Sab196087 }
14565088Sab196087 
14575088Sab196087 
14585088Sab196087 
14595088Sab196087 
14605088Sab196087 /*
14615088Sab196087  * Command completion functions for the various commands
14625088Sab196087  */
14635088Sab196087 
14645088Sab196087 /*
14655088Sab196087  * Handle filling in the values for -shnam, -shndx, and -shtyp options.
14665088Sab196087  */
14675088Sab196087 /*ARGSUSED*/
14685088Sab196087 static void
cpl_sh_opt(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)14695088Sab196087 cpl_sh_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
14705088Sab196087     const char *argv[], int num_opt)
14715088Sab196087 {
14725088Sab196087 	enum { NAME, INDEX, TYPE }	op;
14735088Sab196087 	elfedit_symtab_t		*symtab;
14745088Sab196087 	Word 	tblndx;
14755088Sab196087 
14765088Sab196087 	if ((argc != num_opt) || (argc < 2))
14775088Sab196087 		return;
14785088Sab196087 
14795088Sab196087 	if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) {
14805088Sab196087 		op = NAME;
14815088Sab196087 	} else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) {
14825088Sab196087 		op = INDEX;
14835088Sab196087 
14845088Sab196087 	} else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) {
14855088Sab196087 		op = TYPE;
14865088Sab196087 		if (obj_state == NULL)	 /* No object available */
14875088Sab196087 			elfedit_cpl_atoconst(cpldata,
14885088Sab196087 			    ELFEDIT_CONST_SHT_ALLSYMTAB);
14895088Sab196087 	} else {
14905088Sab196087 		return;
14915088Sab196087 	}
14925088Sab196087 
14935088Sab196087 	if (obj_state == NULL)	 /* No object available */
14945088Sab196087 		return;
14955088Sab196087 
14965088Sab196087 	/*
14975088Sab196087 	 * Loop over the symbol tables and supply command completion
14985088Sab196087 	 * for the items in the file.
14995088Sab196087 	 */
15005088Sab196087 	symtab = obj_state->os_symtab;
15015088Sab196087 	for (tblndx = 0; tblndx < obj_state->os_symtabnum;
15025088Sab196087 	    tblndx++, symtab++) {
15035088Sab196087 		elfedit_section_t *sec =
15045088Sab196087 		    &obj_state->os_secarr[symtab->symt_shndx];
15055088Sab196087 
15065088Sab196087 		switch (op) {
15075088Sab196087 		case NAME:
15085088Sab196087 			elfedit_cpl_match(cpldata, sec->sec_name, 0);
15095088Sab196087 			break;
15105088Sab196087 		case INDEX:
15116225Sab196087 			elfedit_cpl_ndx(cpldata, symtab->symt_shndx);
15125088Sab196087 			break;
15135088Sab196087 		case TYPE:
15145088Sab196087 			{
15155088Sab196087 				elfedit_atoui_sym_t *cpl_list;
15165088Sab196087 
1517*9273SAli.Bahrami@Sun.COM 				(void) elfedit_sec_issymtab(obj_state,
1518*9273SAli.Bahrami@Sun.COM 				    sec, 1, &cpl_list);
15195088Sab196087 				elfedit_cpl_atoui(cpldata, cpl_list);
15205088Sab196087 			}
15215088Sab196087 			break;
15225088Sab196087 		}
15235088Sab196087 	}
15245088Sab196087 }
15255088Sab196087 
15265088Sab196087 /*ARGSUSED*/
15275088Sab196087 static void
cpl_st_bind(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)15285088Sab196087 cpl_st_bind(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
15295088Sab196087     const char *argv[], int num_opt)
15305088Sab196087 {
15315088Sab196087 	/* Handle -shXXX options */
15325088Sab196087 	cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt);
15335088Sab196087 
15345088Sab196087 	/* The second argument can be an STB_ value */
15355088Sab196087 	if (argc == (num_opt + 2))
15365088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STB);
15375088Sab196087 }
15385088Sab196087 
15395088Sab196087 /*ARGSUSED*/
15405088Sab196087 static void
cpl_st_shndx(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)15415088Sab196087 cpl_st_shndx(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
15425088Sab196087     const char *argv[], int num_opt)
15435088Sab196087 {
15445088Sab196087 	elfedit_section_t *sec;
15455088Sab196087 	enum { NAME, INDEX, TYPE } op;
15465088Sab196087 	Word ndx;
15475088Sab196087 
15485088Sab196087 	/* Handle -shXXX options */
15495088Sab196087 	cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt);
15505088Sab196087 
15515088Sab196087 	/*
15525088Sab196087 	 * The second argument can be a section name, a section
15535088Sab196087 	 * index (-secshndx), or a section type (-secshtyp). We
15545088Sab196087 	 * can do completions for each of these.
15555088Sab196087 	 */
15565088Sab196087 	if (argc != (num_opt + 2))
15575088Sab196087 		return;
15585088Sab196087 
15595088Sab196087 	op = NAME;
15605088Sab196087 	for (ndx = 0; ndx < num_opt; ndx++) {
15615088Sab196087 		if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SECSHNDX)) == 0)
15625088Sab196087 			op = INDEX;
15635088Sab196087 		else if (strcmp(argv[ndx],
15645088Sab196087 		    MSG_ORIG(MSG_STR_MINUS_SECSHTYP)) == 0)
15655088Sab196087 			op = TYPE;
15665088Sab196087 	}
15675088Sab196087 
15685088Sab196087 	switch (op) {
15695088Sab196087 	case NAME:
15705088Sab196087 		if (obj_state == NULL)
15715088Sab196087 			break;
15725088Sab196087 		sec = obj_state->os_secarr;
15735088Sab196087 		for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++)
15745088Sab196087 			elfedit_cpl_match(cpldata, sec->sec_name, 0);
15755088Sab196087 		break;
15765088Sab196087 
15775088Sab196087 	case INDEX:
15785088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHN);
15795088Sab196087 		break;
15805088Sab196087 
15815088Sab196087 	case TYPE:
15825088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT);
15835088Sab196087 		break;
15845088Sab196087 	}
15855088Sab196087 }
15865088Sab196087 
15875088Sab196087 /*ARGSUSED*/
15885088Sab196087 static void
cpl_st_type(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)15895088Sab196087 cpl_st_type(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
15905088Sab196087     const char *argv[], int num_opt)
15915088Sab196087 {
15925088Sab196087 	/* Handle -shXXX options */
15935088Sab196087 	cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt);
15945088Sab196087 
15955088Sab196087 	/* The second argument can be an STT_ value */
15965088Sab196087 	if (argc == (num_opt + 2))
15975088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STT);
15985088Sab196087 }
15995088Sab196087 
16005088Sab196087 /*ARGSUSED*/
16015088Sab196087 static void
cpl_st_visibility(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)16025088Sab196087 cpl_st_visibility(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
16035088Sab196087     const char *argv[], int num_opt)
16045088Sab196087 {
16055088Sab196087 	/* Handle -shXXX options */
16065088Sab196087 	cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt);
16075088Sab196087 
16085088Sab196087 	/* The second argument can be an STV_ value */
16095088Sab196087 	if (argc == (num_opt + 2))
16105088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STV);
16115088Sab196087 }
16125088Sab196087 
16135088Sab196087 
16145088Sab196087 
16155088Sab196087 /*
16165088Sab196087  * Implementation functions for the commands
16175088Sab196087  */
16185088Sab196087 static elfedit_cmdret_t
cmd_dump(elfedit_obj_state_t * obj_state,int argc,const char * argv[])16195088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
16205088Sab196087 {
16215088Sab196087 	return (cmd_body(SYM_CMD_T_DUMP, obj_state, argc, argv));
16225088Sab196087 }
16235088Sab196087 
16245088Sab196087 
16255088Sab196087 static elfedit_cmdret_t
cmd_st_bind(elfedit_obj_state_t * obj_state,int argc,const char * argv[])16265088Sab196087 cmd_st_bind(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
16275088Sab196087 {
16285088Sab196087 	return (cmd_body(SYM_CMD_T_ST_BIND, obj_state, argc, argv));
16295088Sab196087 }
16305088Sab196087 
16315088Sab196087 
16325088Sab196087 static elfedit_cmdret_t
cmd_st_info(elfedit_obj_state_t * obj_state,int argc,const char * argv[])16335088Sab196087 cmd_st_info(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
16345088Sab196087 {
16355088Sab196087 	return (cmd_body(SYM_CMD_T_ST_INFO, obj_state, argc, argv));
16365088Sab196087 }
16375088Sab196087 
16385088Sab196087 static elfedit_cmdret_t
cmd_st_name(elfedit_obj_state_t * obj_state,int argc,const char * argv[])16395088Sab196087 cmd_st_name(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
16405088Sab196087 {
16415088Sab196087 	return (cmd_body(SYM_CMD_T_ST_NAME, obj_state, argc, argv));
16425088Sab196087 }
16435088Sab196087 
16445088Sab196087 static elfedit_cmdret_t
cmd_st_other(elfedit_obj_state_t * obj_state,int argc,const char * argv[])16455088Sab196087 cmd_st_other(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
16465088Sab196087 {
16475088Sab196087 	return (cmd_body(SYM_CMD_T_ST_OTHER, obj_state, argc, argv));
16485088Sab196087 }
16495088Sab196087 
16505088Sab196087 static elfedit_cmdret_t
cmd_st_shndx(elfedit_obj_state_t * obj_state,int argc,const char * argv[])16515088Sab196087 cmd_st_shndx(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
16525088Sab196087 {
16535088Sab196087 	return (cmd_body(SYM_CMD_T_ST_SHNDX, obj_state, argc, argv));
16545088Sab196087 }
16555088Sab196087 
16565088Sab196087 static elfedit_cmdret_t
cmd_st_size(elfedit_obj_state_t * obj_state,int argc,const char * argv[])16575088Sab196087 cmd_st_size(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
16585088Sab196087 {
16595088Sab196087 	return (cmd_body(SYM_CMD_T_ST_SIZE, obj_state, argc, argv));
16605088Sab196087 }
16615088Sab196087 
16625088Sab196087 static elfedit_cmdret_t
cmd_st_type(elfedit_obj_state_t * obj_state,int argc,const char * argv[])16635088Sab196087 cmd_st_type(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
16645088Sab196087 {
16655088Sab196087 	return (cmd_body(SYM_CMD_T_ST_TYPE, obj_state, argc, argv));
16665088Sab196087 }
16675088Sab196087 
16685088Sab196087 static elfedit_cmdret_t
cmd_st_value(elfedit_obj_state_t * obj_state,int argc,const char * argv[])16695088Sab196087 cmd_st_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
16705088Sab196087 {
16715088Sab196087 	return (cmd_body(SYM_CMD_T_ST_VALUE, obj_state, argc, argv));
16725088Sab196087 }
16735088Sab196087 
16745088Sab196087 static elfedit_cmdret_t
cmd_st_visibility(elfedit_obj_state_t * obj_state,int argc,const char * argv[])16755088Sab196087 cmd_st_visibility(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
16765088Sab196087 {
16775088Sab196087 	return (cmd_body(SYM_CMD_T_ST_VISIBILITY, obj_state, argc, argv));
16785088Sab196087 }
16795088Sab196087 
16805088Sab196087 
16815088Sab196087 
16825088Sab196087 /*ARGSUSED*/
16835088Sab196087 elfedit_module_t *
elfedit_init(elfedit_module_version_t version)16845088Sab196087 elfedit_init(elfedit_module_version_t version)
16855088Sab196087 {
16865088Sab196087 	/* Multiple commands accept only the standard set of options */
16875088Sab196087 	static elfedit_cmd_optarg_t opt_std[] = {
16885088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
16895088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
16905088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
16915088Sab196087 		    SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP },
16925088Sab196087 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0 },
16935088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
16945088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
16955088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
16965088Sab196087 		    SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP },
16975088Sab196087 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
16985088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
16995088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
17005088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
17015088Sab196087 		    SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX },
17025088Sab196087 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
17035088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SYMNDX),
17045088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SYMNDX) */
17055088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, SYM_OPT_F_SYMNDX },
17065088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
17075088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0 },
17085088Sab196087 		{ NULL }
17095088Sab196087 	};
17105088Sab196087 
17115088Sab196087 	/* sym:dump */
17125088Sab196087 	static const char *name_dump[] = {
17135088Sab196087 	    MSG_ORIG(MSG_CMD_DUMP),
17145088Sab196087 	    MSG_ORIG(MSG_STR_EMPTY),	/* "" makes this the default command */
17155088Sab196087 	    NULL
17165088Sab196087 	};
17175088Sab196087 	static elfedit_cmd_optarg_t opt_dump[] = {
17185088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
17195088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
17205088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
17215088Sab196087 		    SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP },
17225088Sab196087 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0 },
17235088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
17245088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
17255088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
17265088Sab196087 		    SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP },
17275088Sab196087 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
17285088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
17295088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
17305088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
17315088Sab196087 		    SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX },
17325088Sab196087 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
17335088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SYMNDX),
17345088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SYMNDX) */
17355088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, SYM_OPT_F_SYMNDX },
17365088Sab196087 		{ NULL }
17375088Sab196087 	};
17385088Sab196087 	static elfedit_cmd_optarg_t arg_dump[] = {
17395088Sab196087 		{ MSG_ORIG(MSG_STR_SYM),
17405088Sab196087 		    /* MSG_INTL(MSG_A1_SYM) */
17415088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
17425088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
17435088Sab196087 		{ NULL }
17445088Sab196087 	};
17455088Sab196087 
17465088Sab196087 	/* sym:st_bind */
17475088Sab196087 	static const char *name_st_bind[] = {
17485088Sab196087 	    MSG_ORIG(MSG_CMD_ST_BIND), NULL };
17495088Sab196087 	static elfedit_cmd_optarg_t arg_st_bind[] = {
17505088Sab196087 		{ MSG_ORIG(MSG_STR_SYM),
17515088Sab196087 		    /* MSG_INTL(MSG_A1_SYM) */
17525088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
17535088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
17545088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
17555088Sab196087 		    /* MSG_INTL(MSG_A2_DESC_ST_BIND) */
17565088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_BIND),
17575088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
17585088Sab196087 		{ NULL }
17595088Sab196087 	};
17605088Sab196087 
17615088Sab196087 	/* sym:st_info */
17625088Sab196087 	static const char *name_st_info[] = {
17635088Sab196087 	    MSG_ORIG(MSG_CMD_ST_INFO), NULL };
17645088Sab196087 	static elfedit_cmd_optarg_t arg_st_info[] = {
17655088Sab196087 		{ MSG_ORIG(MSG_STR_SYM),
17665088Sab196087 		    /* MSG_INTL(MSG_A1_SYM) */
17675088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
17685088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
17695088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
17705088Sab196087 		    /* MSG_INTL(MSG_A2_DESC_ST_INFO) */
17715088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_INFO),
17725088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
17735088Sab196087 		{ NULL }
17745088Sab196087 	};
17755088Sab196087 
17765088Sab196087 	/* sym:st_name */
17775088Sab196087 	static const char *name_st_name[] = {
17785088Sab196087 	    MSG_ORIG(MSG_CMD_ST_NAME), NULL };
17795088Sab196087 	static elfedit_cmd_optarg_t opt_st_name[] = {
17805088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
17815088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
17825088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
17835088Sab196087 		    SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP },
17845088Sab196087 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0, 0 },
17855088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
17865088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
17875088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
17885088Sab196087 		    SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP },
17895088Sab196087 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 },
17905088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
17915088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
17925088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
17935088Sab196087 		    SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX },
17945088Sab196087 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0, 0 },
17955088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SYMNDX),
17965088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SYMNDX) */
17975088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0,
17985088Sab196087 		    SYM_OPT_F_SYMNDX, 0 },
17995088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_NAME_OFFSET),
18005088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_NAME_OFFSET) */
18015088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_NAME_OFFSET), 0,
18025088Sab196087 		    SYM_OPT_F_NAMOFFSET, 0 },
18035088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
18045088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
18055088Sab196087 		{ NULL }
18065088Sab196087 	};
18075088Sab196087 	static elfedit_cmd_optarg_t arg_st_name[] = {
18085088Sab196087 		{ MSG_ORIG(MSG_STR_SYM),
18095088Sab196087 		    /* MSG_INTL(MSG_A1_SYM) */
18105088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
18115088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18125088Sab196087 		{ MSG_ORIG(MSG_STR_NAME),
18135088Sab196087 		    /* MSG_INTL(MSG_A2_DESC_ST_NAME) */
18145088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_NAME),
18155088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18165088Sab196087 		{ NULL }
18175088Sab196087 	};
18185088Sab196087 
18195088Sab196087 	/* sym:st_other */
18205088Sab196087 	static const char *name_st_other[] = {
18215088Sab196087 	    MSG_ORIG(MSG_CMD_ST_OTHER), NULL };
18225088Sab196087 	static elfedit_cmd_optarg_t arg_st_other[] = {
18235088Sab196087 		{ MSG_ORIG(MSG_STR_SYM),
18245088Sab196087 		    /* MSG_INTL(MSG_A1_SYM) */
18255088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
18265088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18275088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
18285088Sab196087 		    /* MSG_INTL(MSG_A2_DESC_ST_OTHER) */
18295088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_OTHER),
18305088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18315088Sab196087 		{ NULL }
18325088Sab196087 	};
18335088Sab196087 
18345088Sab196087 	/* sym:st_shndx */
18355088Sab196087 	static const char *name_st_shndx[] = {
18365088Sab196087 	    MSG_ORIG(MSG_CMD_ST_SHNDX), NULL };
18375088Sab196087 	static elfedit_cmd_optarg_t opt_st_shndx[] = {
18385088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_E),
18395088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_E) */
18405088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_E), 0, SYM_OPT_F_XSHINDEX, 0 },
18415088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
18425088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
18435088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
18445088Sab196087 		    SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP },
18455088Sab196087 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0, 0 },
18465088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
18475088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
18485088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
18495088Sab196087 		    SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP },
18505088Sab196087 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 },
18515088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
18525088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
18535088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
18545088Sab196087 		    SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX },
18555088Sab196087 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0, 0 },
18565088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SYMNDX),
18575088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SYMNDX) */
18585088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0,
18595088Sab196087 		    SYM_OPT_F_SYMNDX, 0 },
18605088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
18615088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
18625088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SECSHNDX),
18635088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SECSHNDX) */
18645088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SECSHNDX),
18655088Sab196087 		    0, SYM_OPT_F_SECSHNDX, SYM_OPT_F_SECSHTYP },
18665088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SECSHTYP),
18675088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SECSHTYP) */
18685088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SECSHTYP),
18695088Sab196087 		    0, SYM_OPT_F_SECSHTYP, SYM_OPT_F_SECSHNDX },
18705088Sab196087 		{ NULL }
18715088Sab196087 	};
18725088Sab196087 	static elfedit_cmd_optarg_t arg_st_shndx[] = {
18735088Sab196087 		{ MSG_ORIG(MSG_STR_SYM),
18745088Sab196087 		    /* MSG_INTL(MSG_A1_SYM) */
18755088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
18765088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18775088Sab196087 		{ MSG_ORIG(MSG_STR_SEC),
18785088Sab196087 		    /* MSG_INTL(MSG_A2_DESC_ST_SEC) */
18795088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_SEC),
18805088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18815088Sab196087 		{ NULL }
18825088Sab196087 	};
18835088Sab196087 
18845088Sab196087 	/* sym:st_size */
18855088Sab196087 	static const char *name_st_size[] = {
18865088Sab196087 	    MSG_ORIG(MSG_CMD_ST_SIZE), NULL };
18875088Sab196087 	static elfedit_cmd_optarg_t arg_st_size[] = {
18885088Sab196087 		{ MSG_ORIG(MSG_STR_SYM),
18895088Sab196087 		    /* MSG_INTL(MSG_A1_SYM) */
18905088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
18915088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18925088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
18935088Sab196087 		    /* MSG_INTL(MSG_A2_DESC_ST_SIZE) */
18945088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_SIZE),
18955088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
18965088Sab196087 		{ NULL }
18975088Sab196087 	};
18985088Sab196087 
18995088Sab196087 	/* sym:st_type */
19005088Sab196087 	static const char *name_st_type[] = {
19015088Sab196087 	    MSG_ORIG(MSG_CMD_ST_TYPE), NULL };
19025088Sab196087 	static elfedit_cmd_optarg_t arg_st_type[] = {
19035088Sab196087 		{ MSG_ORIG(MSG_STR_SYM),
19045088Sab196087 		    /* MSG_INTL(MSG_A1_SYM) */
19055088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
19065088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
19075088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
19085088Sab196087 		    /* MSG_INTL(MSG_A2_DESC_ST_TYPE) */
19095088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_TYPE),
19105088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
19115088Sab196087 		{ NULL }
19125088Sab196087 	};
19135088Sab196087 
19145088Sab196087 	/* sym:st_value */
19155088Sab196087 	static const char *name_st_value[] = {
19165088Sab196087 	    MSG_ORIG(MSG_CMD_ST_VALUE), NULL };
19175088Sab196087 	static elfedit_cmd_optarg_t arg_st_value[] = {
19185088Sab196087 		{ MSG_ORIG(MSG_STR_SYM),
19195088Sab196087 		    /* MSG_INTL(MSG_A1_SYM) */
19205088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
19215088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
19225088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
19235088Sab196087 		    /* MSG_INTL(MSG_A2_DESC_ST_VALUE) */
19245088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_VALUE),
19255088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
19265088Sab196087 		{ NULL }
19275088Sab196087 	};
19285088Sab196087 
19295088Sab196087 	/* sym:st_visibility */
19305088Sab196087 	static const char *name_st_visibility[] = {
19315088Sab196087 	    MSG_ORIG(MSG_CMD_ST_VISIBILITY), NULL };
19325088Sab196087 	static elfedit_cmd_optarg_t arg_st_visibility[] = {
19335088Sab196087 		{ MSG_ORIG(MSG_STR_SYM),
19345088Sab196087 		    /* MSG_INTL(MSG_A1_SYM) */
19355088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SYM),
19365088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
19375088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
19385088Sab196087 		    /* MSG_INTL(MSG_A2_DESC_ST_VISIBILITY) */
19395088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DESC_ST_VISIBILITY),
19405088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
19415088Sab196087 		{ NULL }
19425088Sab196087 	};
19435088Sab196087 
19445088Sab196087 	static elfedit_cmd_t cmds[] = {
19455088Sab196087 		/* sym:dump */
19465088Sab196087 		{ cmd_dump, cpl_sh_opt, name_dump,
19475088Sab196087 		    /* MSG_INTL(MSG_DESC_DUMP) */
19485088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_DUMP),
19495088Sab196087 		    /* MSG_INTL(MSG_HELP_DUMP) */
19505088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_DUMP),
19515088Sab196087 		    opt_dump, arg_dump },
19525088Sab196087 
19535088Sab196087 		/* sym:st_bind */
19545088Sab196087 		{ cmd_st_bind, cpl_st_bind, name_st_bind,
19555088Sab196087 		    /* MSG_INTL(MSG_DESC_ST_BIND) */
19565088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ST_BIND),
19575088Sab196087 		    /* MSG_INTL(MSG_HELP_ST_BIND) */
19585088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ST_BIND),
19595088Sab196087 		    opt_std, arg_st_bind },
19605088Sab196087 
19615088Sab196087 		/* sym:st_info */
19625088Sab196087 		{ cmd_st_info, cpl_sh_opt, name_st_info,
19635088Sab196087 		    /* MSG_INTL(MSG_DESC_ST_INFO) */
19645088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ST_INFO),
19655088Sab196087 		    /* MSG_INTL(MSG_HELP_ST_INFO) */
19665088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ST_INFO),
19675088Sab196087 		    opt_std, arg_st_info },
19685088Sab196087 
19695088Sab196087 		/* sym:st_name */
19705088Sab196087 		{ cmd_st_name, cpl_sh_opt, name_st_name,
19715088Sab196087 		    /* MSG_INTL(MSG_DESC_ST_NAME) */
19725088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ST_NAME),
19735088Sab196087 		    /* MSG_INTL(MSG_HELP_ST_NAME) */
19745088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ST_NAME),
19755088Sab196087 		    opt_st_name, arg_st_name },
19765088Sab196087 
19775088Sab196087 		/* sym:st_other */
19785088Sab196087 		{ cmd_st_other, cpl_sh_opt, name_st_other,
19795088Sab196087 		    /* MSG_INTL(MSG_DESC_ST_OTHER) */
19805088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ST_OTHER),
19815088Sab196087 		    /* MSG_INTL(MSG_HELP_ST_OTHER) */
19825088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ST_OTHER),
19835088Sab196087 		    opt_std, arg_st_other },
19845088Sab196087 
19855088Sab196087 		/* sym:st_shndx */
19865088Sab196087 		{ cmd_st_shndx, cpl_st_shndx, name_st_shndx,
19875088Sab196087 		    /* MSG_INTL(MSG_DESC_ST_SHNDX) */
19885088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ST_SHNDX),
19895088Sab196087 		    /* MSG_INTL(MSG_HELP_ST_SHNDX) */
19905088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ST_SHNDX),
19915088Sab196087 		    opt_st_shndx, arg_st_shndx },
19925088Sab196087 
19935088Sab196087 		/* sym:st_size */
19945088Sab196087 		{ cmd_st_size, cpl_sh_opt, name_st_size,
19955088Sab196087 		    /* MSG_INTL(MSG_DESC_ST_SIZE) */
19965088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ST_SIZE),
19975088Sab196087 		    /* MSG_INTL(MSG_HELP_ST_SIZE) */
19985088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ST_SIZE),
19995088Sab196087 		    opt_std, arg_st_size },
20005088Sab196087 
20015088Sab196087 		/* sym:st_type */
20025088Sab196087 		{ cmd_st_type, cpl_st_type, name_st_type,
20035088Sab196087 		    /* MSG_INTL(MSG_DESC_ST_TYPE) */
20045088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ST_TYPE),
20055088Sab196087 		    /* MSG_INTL(MSG_HELP_ST_TYPE) */
20065088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ST_TYPE),
20075088Sab196087 		    opt_std, arg_st_type },
20085088Sab196087 
20095088Sab196087 		/* sym:st_value */
20105088Sab196087 		{ cmd_st_value, cpl_sh_opt, name_st_value,
20115088Sab196087 		    /* MSG_INTL(MSG_DESC_ST_VALUE) */
20125088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ST_VALUE),
20135088Sab196087 		    /* MSG_INTL(MSG_HELP_ST_VALUE) */
20145088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ST_VALUE),
20155088Sab196087 		    opt_std, arg_st_value },
20165088Sab196087 
20175088Sab196087 		/* sym:st_visibility */
20185088Sab196087 		{ cmd_st_visibility, cpl_st_visibility, name_st_visibility,
20195088Sab196087 		    /* MSG_INTL(MSG_DESC_ST_VISIBILITY) */
20205088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ST_VISIBILITY),
20215088Sab196087 		    /* MSG_INTL(MSG_HELP_ST_VISIBILITY) */
20225088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ST_VISIBILITY),
20235088Sab196087 		    opt_std, arg_st_visibility },
20245088Sab196087 
20255088Sab196087 		{ NULL }
20265088Sab196087 	};
20275088Sab196087 
20285088Sab196087 	static elfedit_module_t module = {
20295088Sab196087 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
20305088Sab196087 	    /* MSG_INTL(MSG_MOD_DESC) */
20315088Sab196087 	    ELFEDIT_I18NHDL(MSG_MOD_DESC),
20325088Sab196087 	    cmds, mod_i18nhdl_to_str };
20335088Sab196087 
20345088Sab196087 	return (&module);
20355088Sab196087 }
2036