xref: /onnv-gate/usr/src/cmd/sgs/elfedit/modules/common/str.c (revision 9273:9a0603d78ad3)
15308Sab196087 /*
25308Sab196087  * CDDL HEADER START
35308Sab196087  *
45308Sab196087  * The contents of this file are subject to the terms of the
55308Sab196087  * Common Development and Distribution License (the "License").
65308Sab196087  * You may not use this file except in compliance with the License.
75308Sab196087  *
85308Sab196087  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95308Sab196087  * or http://www.opensolaris.org/os/licensing.
105308Sab196087  * See the License for the specific language governing permissions
115308Sab196087  * and limitations under the License.
125308Sab196087  *
135308Sab196087  * When distributing Covered Code, include this CDDL HEADER in each
145308Sab196087  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155308Sab196087  * If applicable, add the following below this CDDL HEADER, with the
165308Sab196087  * fields enclosed by brackets "[]" replaced with your own identifying
175308Sab196087  * information: Portions Copyright [yyyy] [name of copyright owner]
185308Sab196087  *
195308Sab196087  * CDDL HEADER END
205308Sab196087  */
215308Sab196087 
225308Sab196087 /*
23*9273SAli.Bahrami@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245308Sab196087  * Use is subject to license terms.
255308Sab196087  */
265308Sab196087 
275308Sab196087 #include	<stdio.h>
285308Sab196087 #include	<ctype.h>
295308Sab196087 #include	<unistd.h>
305308Sab196087 #include	<elfedit.h>
315308Sab196087 #include	<strings.h>
325308Sab196087 #include	<debug.h>
335308Sab196087 #include	<conv.h>
345308Sab196087 #include	<str_msg.h>
355308Sab196087 
365308Sab196087 
375308Sab196087 
385308Sab196087 
395308Sab196087 #define	MAXNDXSIZE	10
405308Sab196087 
415308Sab196087 
425308Sab196087 
435308Sab196087 /*
445308Sab196087  * This module uses shared code for several of the commands.
455308Sab196087  * It is sometimes necessary to know which specific command
465308Sab196087  * is active.
475308Sab196087  */
485308Sab196087 typedef enum {
495308Sab196087 	STR_CMD_T_DUMP =	0,	/* str:dump */
505308Sab196087 	STR_CMD_T_SET =		1,	/* str:set */
515308Sab196087 	STR_CMD_T_ADD =		2,	/* str:add */
525308Sab196087 	STR_CMD_T_ZERO =	3,	/* str:zero */
535308Sab196087 } STR_CMD_T;
545308Sab196087 
555308Sab196087 
565308Sab196087 
575308Sab196087 #ifndef _ELF64
585308Sab196087 /*
595308Sab196087  * We supply this function for the msg module. Only one copy is needed.
605308Sab196087  */
615308Sab196087 const char *
_str_msg(Msg mid)625308Sab196087 _str_msg(Msg mid)
635308Sab196087 {
645308Sab196087 	return (gettext(MSG_ORIG(mid)));
655308Sab196087 }
665308Sab196087 
675308Sab196087 #endif
685308Sab196087 
695308Sab196087 
705308Sab196087 
715308Sab196087 /*
725308Sab196087  * This function is supplied to elfedit through our elfedit_module_t
735308Sab196087  * definition. It translates the opaque elfedit_i18nhdl_t handles
745308Sab196087  * in our module interface into the actual strings for elfedit to
755308Sab196087  * use.
765308Sab196087  *
775308Sab196087  * note:
785308Sab196087  *	This module uses Msg codes for its i18n handle type.
795308Sab196087  *	So the translation is simply to use MSG_INTL() to turn
805308Sab196087  *	it into a string and return it.
815308Sab196087  */
825308Sab196087 static const char *
mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)835308Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
845308Sab196087 {
855308Sab196087 	Msg msg = (Msg)hdl;
865308Sab196087 
875308Sab196087 	return (MSG_INTL(msg));
885308Sab196087 }
895308Sab196087 
905308Sab196087 
915308Sab196087 
925308Sab196087 /*
935308Sab196087  * The sym_opt_t enum specifies a bit value for every optional
945308Sab196087  * argument allowed by a command in this module.
955308Sab196087  */
965308Sab196087 typedef enum {
975892Sab196087 	STR_OPT_F_ANY =		1,	/* -any: treat any sec. as strtab */
985892Sab196087 	STR_OPT_F_END =		2,	/* -end: zero to end of strtab */
995892Sab196087 	STR_OPT_F_NOTERM =	4,	/* -noterm: str:set won't term string */
1005892Sab196087 	STR_OPT_F_SHNAME =	8,	/* -shnam name: section spec. by name */
1015892Sab196087 	STR_OPT_F_SHNDX =	16,	/* -shndx ndx: strtab spec. by index */
1025892Sab196087 	STR_OPT_F_SHTYP =	32,	/* -shtyp type: section spec. by type */
1035892Sab196087 	STR_OPT_F_STRNDX =	64,	/* -strndx: String specified by index */
1045308Sab196087 } str_opt_t;
1055308Sab196087 
1065308Sab196087 
1075308Sab196087 /*
1085308Sab196087  * A variable of type ARGSTATE is used by each command to maintain
1095308Sab196087  * information about the string table section being used, and for any
1105308Sab196087  * auxiliary sections that are related to it.
1115308Sab196087  */
1125308Sab196087 typedef struct {
1135308Sab196087 	elfedit_obj_state_t	*obj_state;
1145308Sab196087 	str_opt_t		optmask;   	/* Mask of options used */
1155308Sab196087 	int			argc;		/* # of plain arguments */
1165308Sab196087 	const char		**argv;		/* Plain arguments */
1175308Sab196087 
1185308Sab196087 	struct {				/* String table */
1195308Sab196087 		elfedit_section_t	*sec;
1205308Sab196087 		Word			ndx;	/* Table offset if (argc > 0) */
1215308Sab196087 	} str;
1225308Sab196087 	struct {				/* Dynamic section */
1235308Sab196087 		elfedit_section_t	*sec;
1245308Sab196087 		Dyn			*data;
1255308Sab196087 		Word			n;
1265308Sab196087 		elfedit_dyn_elt_t	strpad;
1275308Sab196087 	} dyn;
1285308Sab196087 } ARGSTATE;
1295308Sab196087 
1305308Sab196087 
1315308Sab196087 
1325308Sab196087 /*
1335892Sab196087  * Given an ELF SHT_ section type constant, shndx_to_strtab() returns
1345308Sab196087  * one of the following
1355308Sab196087  */
1365308Sab196087 
1375308Sab196087 typedef enum {
1385308Sab196087 	SHTOSTR_NONE = 0,		/* Type can't lead to a  string table */
1395308Sab196087 	SHTOSTR_STRTAB = 1,		/* type is SHT_STRTAB */
1405308Sab196087 	SHTOSTR_LINK_STRTAB = 2,	/* sh_link for type yields strtab */
1415308Sab196087 	SHTOSTR_LINK_SYMTAB = 3,	/* sh_link for type yields symtab */
1426225Sab196087 	SHTOSTR_SHF_STRINGS = 4,	/* Not strtab, but SHF_STRINGS set */
1435308Sab196087 } SHTOSTR_T;
1445308Sab196087 
1456225Sab196087 static SHTOSTR_T
shtype_to_strtab(Word sh_type,Word sh_flags)1466225Sab196087 shtype_to_strtab(Word sh_type, Word sh_flags)
1475308Sab196087 {
1486225Sab196087 	/*
1496225Sab196087 	 * A string table section always leads to itself. A
1506225Sab196087 	 * non-string table that has it's SHF_STRINGS section flag
1516225Sab196087 	 * set trumps anything else.
1526225Sab196087 	 */
1536225Sab196087 	if (sh_type == SHT_STRTAB)
1546225Sab196087 		return (SHTOSTR_STRTAB);
1556225Sab196087 	if (sh_flags & SHF_STRINGS)
1566225Sab196087 		return (SHTOSTR_SHF_STRINGS);
1576225Sab196087 
1586225Sab196087 	/*
1596225Sab196087 	 * Look at non-stringtable section types that can lead to
1606225Sab196087 	 * string tables via sh_link.
1616225Sab196087 	 */
1625308Sab196087 	switch (sh_type) {
1635308Sab196087 	/* These sections reference a string table via sh_link */
1645308Sab196087 	case SHT_DYNAMIC:
1655308Sab196087 	case SHT_SYMTAB:
1665308Sab196087 	case SHT_DYNSYM:
1675308Sab196087 	case SHT_SUNW_LDYNSYM:
1685308Sab196087 	case SHT_SUNW_verdef:
1695308Sab196087 	case SHT_SUNW_verneed:
1705308Sab196087 		return (SHTOSTR_LINK_STRTAB);
1715308Sab196087 
1725308Sab196087 	/*
1735308Sab196087 	 * These sections reference a symbol table via sh_link.
1745308Sab196087 	 * Symbol tables, in turn, reference a string table
1755308Sab196087 	 * via their sh_link.
1765308Sab196087 	 */
1775308Sab196087 	case SHT_HASH:
1785308Sab196087 	case SHT_REL:
1795308Sab196087 	case SHT_RELA:
1805308Sab196087 	case SHT_GROUP:
1815308Sab196087 	case SHT_SYMTAB_SHNDX:
1825308Sab196087 	case SHT_SUNW_move:
1835308Sab196087 	case SHT_SUNW_syminfo:
1845308Sab196087 	case SHT_SUNW_versym:
1855308Sab196087 	case SHT_SUNW_symsort:
1865308Sab196087 	case SHT_SUNW_tlssort:
1875308Sab196087 		return (SHTOSTR_LINK_SYMTAB);
1885308Sab196087 	}
1895308Sab196087 
1905308Sab196087 	/* Types that lead to string tables were caught above */
1915308Sab196087 	return (SHTOSTR_NONE);
1925308Sab196087 }
1935308Sab196087 
1945308Sab196087 /*
1955308Sab196087  * Given a section index, attempt to convert it into an index
1965308Sab196087  * to a string table section.
1975308Sab196087  */
1985308Sab196087 static Word
shndx_to_strtab(elfedit_obj_state_t * obj_state,Word ndx)1995308Sab196087 shndx_to_strtab(elfedit_obj_state_t *obj_state, Word ndx)
2005308Sab196087 {
2015308Sab196087 	/*
2025308Sab196087 	 * Locate and validate the string table. In the case where
2035308Sab196087 	 * a non-string table section is given that references a string
2045308Sab196087 	 * table, we will use the referenced table.
2055308Sab196087 	 */
2065308Sab196087 	if (ndx < obj_state->os_shnum) {
2076225Sab196087 		Shdr *shdr = obj_state->os_secarr[ndx].sec_shdr;
2086225Sab196087 
2096225Sab196087 		switch (shtype_to_strtab(shdr->sh_type, shdr->sh_flags)) {
2105308Sab196087 
2115308Sab196087 		/* Sections that reference a string table via sh_link */
2125308Sab196087 		case SHTOSTR_LINK_STRTAB:
2136225Sab196087 			ndx = shdr->sh_link;
2145308Sab196087 			break;
2155308Sab196087 
2165308Sab196087 		/*
2175308Sab196087 		 * Sections that reference a symbol tabel via sh_link,
2185308Sab196087 		 * which in turn reference a string table via their sh_link.
2195308Sab196087 		 */
2205308Sab196087 		case SHTOSTR_LINK_SYMTAB:
2216225Sab196087 			ndx = shdr->sh_link;
2225308Sab196087 			if (ndx < obj_state->os_shnum)
2235308Sab196087 				ndx =
2245308Sab196087 				    obj_state->os_secarr[ndx].sec_shdr->sh_link;
2255308Sab196087 			break;
2265308Sab196087 		}
2275308Sab196087 	}
2285308Sab196087 
2295308Sab196087 	return (ndx);
2305308Sab196087 }
2315308Sab196087 
2325308Sab196087 
2335308Sab196087 
2345308Sab196087 /*
2355308Sab196087  * Standard argument processing for string table module
2365308Sab196087  *
2375308Sab196087  * entry
2385308Sab196087  *	obj_state, argc, argv - Standard command arguments
2395308Sab196087  *	optmask - Mask of allowed optional arguments.
2405308Sab196087  *	argstate - Address of ARGSTATE block to be initialized
2415308Sab196087  *
2425308Sab196087  * exit:
2435308Sab196087  *	On success, *argstate is initialized. On error,
2445308Sab196087  *	an error is issued and this routine does not return.
2455308Sab196087  */
2465308Sab196087 static void
process_args(elfedit_obj_state_t * obj_state,int argc,const char * argv[],STR_CMD_T cmd,ARGSTATE * argstate,int * print_only)2475308Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
2485308Sab196087     STR_CMD_T cmd, ARGSTATE *argstate, int *print_only)
2495308Sab196087 {
2505308Sab196087 	elfedit_getopt_state_t	getopt_state;
2515308Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
2525308Sab196087 	Word			ndx;
2535308Sab196087 	int			argc_ok;
2545308Sab196087 
2555308Sab196087 	bzero(argstate, sizeof (*argstate));
2565308Sab196087 	argstate->obj_state = obj_state;
2575308Sab196087 
2585308Sab196087 	/*
2595308Sab196087 	 * By default, we use the section name string table pointed at
2605308Sab196087 	 * by the ELF header.
2615308Sab196087 	 */
2625308Sab196087 	ndx = obj_state->os_ehdr->e_shstrndx;
2635308Sab196087 
2645308Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
2655308Sab196087 
2665308Sab196087 	/* Add each new option to the options mask */
2675308Sab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
2685308Sab196087 		argstate->optmask |= getopt_ret->gor_idmask;
2695308Sab196087 
2705308Sab196087 		switch (getopt_ret->gor_idmask) {
2715308Sab196087 		case STR_OPT_F_SHNAME:		/* -shnam name */
2725308Sab196087 			ndx = elfedit_name_to_shndx(obj_state,
2735308Sab196087 			    getopt_ret->gor_value);
2745308Sab196087 			break;
2755308Sab196087 
2765308Sab196087 		case STR_OPT_F_SHNDX:		/* -shndx index */
2775308Sab196087 			ndx = elfedit_atoui(getopt_ret->gor_value, NULL);
2785308Sab196087 			break;
2795308Sab196087 
2805308Sab196087 		case STR_OPT_F_SHTYP:		/* -shtyp type */
2815308Sab196087 			ndx = elfedit_type_to_shndx(obj_state,
2825308Sab196087 			    elfedit_atoconst(getopt_ret->gor_value,
2835308Sab196087 			    ELFEDIT_CONST_SHT));
2845308Sab196087 			break;
2855308Sab196087 		}
2865308Sab196087 	}
2875308Sab196087 
2885308Sab196087 	/*
2895308Sab196087 	 * Usage error if there are the wrong number of plain arguments.
2905308Sab196087 	 */
2915308Sab196087 	switch (cmd) {
2925308Sab196087 	case STR_CMD_T_DUMP:
2935308Sab196087 		argc_ok = (argc == 0) || (argc == 1);
2945308Sab196087 		*print_only = 1;
2955308Sab196087 		break;
2965308Sab196087 	case STR_CMD_T_SET:
2975308Sab196087 		argc_ok = (argc == 1) || (argc == 2);
2985308Sab196087 		*print_only = (argc == 1);
2995308Sab196087 		break;
3005308Sab196087 	case STR_CMD_T_ADD:
3015308Sab196087 		argc_ok = (argc == 1);
3025308Sab196087 		*print_only = 0;
3035308Sab196087 		break;
3045308Sab196087 	case STR_CMD_T_ZERO:
3055308Sab196087 		/*
3065308Sab196087 		 * The second argument (count) and the -end option are
3075308Sab196087 		 * mutally exclusive.
3085308Sab196087 		 */
3095308Sab196087 		argc_ok = ((argc == 1) || (argc == 2)) &&
3105308Sab196087 		    !((argc == 2) && (argstate->optmask & STR_OPT_F_END));
3115308Sab196087 		*print_only = 0;
3125308Sab196087 		break;
3135308Sab196087 	default:
3145308Sab196087 		argc_ok = 0;	/* Unknown command? */
3155308Sab196087 		break;
3165308Sab196087 	}
3175308Sab196087 	if (!argc_ok)
3185308Sab196087 		elfedit_command_usage();
3195308Sab196087 
3205308Sab196087 	/* If there may be an arbitrary amount of output, use a pager */
3215308Sab196087 	if (argc == 0)
3225308Sab196087 		elfedit_pager_init();
3235308Sab196087 
3245308Sab196087 	/* Return the updated values of argc/argv */
3255308Sab196087 	argstate->argc = argc;
3265308Sab196087 	argstate->argv = argv;
3275308Sab196087 
3285892Sab196087 	if (argstate->optmask & STR_OPT_F_ANY) {
3295892Sab196087 		/* Take the arbitrary section */
3305892Sab196087 		argstate->str.sec = elfedit_sec_get(obj_state, ndx);
3315308Sab196087 
3325892Sab196087 	} else {
3335892Sab196087 		/*
3345892Sab196087 		 * Locate and validate the string table. In the case where
3355892Sab196087 		 * a non-string table section is given that references a string
3365892Sab196087 		 * table, we will use the referenced table.
3375892Sab196087 		 */
3385892Sab196087 		ndx = shndx_to_strtab(obj_state, ndx);
3395892Sab196087 
3405892Sab196087 		/*
3415892Sab196087 		 * If ndx is a string table, the following will issue the
3425892Sab196087 		 * proper debug messages. If it is out of range, or of any
3435892Sab196087 		 * other type, an error is issued and it doesn't return.
3445892Sab196087 		 */
3456225Sab196087 		argstate->str.sec = elfedit_sec_getstr(obj_state, ndx, 1);
3465892Sab196087 	}
3475308Sab196087 
3485308Sab196087 	/*
3495308Sab196087 	 * If there is a dynamic section, check its sh_link to the
3505308Sab196087 	 * string table index. If these match, then we have the
3515308Sab196087 	 * dynamic string table. In that case, fetch the dynamic
3525308Sab196087 	 * section and locate the DT_SUNW_STRPAD entry, causing
3535308Sab196087 	 * debug messages to be issued.
3545308Sab196087 	 */
3555308Sab196087 	argstate->dyn.sec = NULL;
3565308Sab196087 	elfedit_dyn_elt_init(&argstate->dyn.strpad);
3575308Sab196087 	if (obj_state->os_dynndx != SHN_UNDEF) {
3585308Sab196087 		elfedit_section_t *dynsec =
3595308Sab196087 		    &obj_state->os_secarr[obj_state->os_dynndx];
3605308Sab196087 
3615308Sab196087 		if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) &&
3625308Sab196087 		    (argstate->str.sec->sec_shndx ==
3635308Sab196087 		    dynsec->sec_shdr->sh_link)) {
3645308Sab196087 			argstate->dyn.sec = elfedit_sec_getdyn(obj_state,
3655308Sab196087 			    &argstate->dyn.data, &argstate->dyn.n);
366*9273SAli.Bahrami@Sun.COM 			(void) elfedit_dynstr_getpad(obj_state, dynsec,
3675308Sab196087 			    &argstate->dyn.strpad);
3685308Sab196087 
3695308Sab196087 			/*
3705308Sab196087 			 * Does the pad value make sense?
3715308Sab196087 			 * Issue debug message and ignore it if not.
3725308Sab196087 			 */
3735308Sab196087 			if ((argstate->dyn.strpad.dn_seen != 0) &&
3745308Sab196087 			    (argstate->dyn.strpad.dn_dyn.d_un.d_val >
3755308Sab196087 			    argstate->str.sec->sec_data->d_size)) {
3765308Sab196087 				argstate->dyn.strpad.dn_seen = 0;
3775308Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
3785308Sab196087 				    MSG_INTL(MSG_DEBUG_BADSTRPAD),
3795308Sab196087 				    EC_WORD(argstate->str.sec->sec_shndx),
3805308Sab196087 				    argstate->str.sec->sec_name,
3815308Sab196087 				    EC_XWORD(argstate->dyn.strpad.dn_dyn.
3825308Sab196087 				    d_un.d_val),
3835308Sab196087 				    EC_XWORD(argstate->str.sec->
3845308Sab196087 				    sec_data->d_size));
3855308Sab196087 
3865308Sab196087 			}
3875308Sab196087 		}
3885308Sab196087 	}
3895308Sab196087 
3905308Sab196087 	/* Locate the string table offset if argument is present */
3915308Sab196087 	if ((argc > 0) && (cmd != STR_CMD_T_ADD)) {
3925308Sab196087 		/*
3935308Sab196087 		 * If the -strndx option was specified, arg is an index
3945308Sab196087 		 * into the string table. Otherwise it is a string
3955308Sab196087 		 * to be looked up.
3965308Sab196087 		 */
3975308Sab196087 		if (argstate->optmask & STR_OPT_F_STRNDX) {
3985308Sab196087 			argstate->str.ndx = (elfedit_atoui_range(argv[0],
3995308Sab196087 			    MSG_ORIG(MSG_STR_STRING), 0,
4005308Sab196087 			    argstate->str.sec->sec_data->d_size - 1, NULL));
4015308Sab196087 		} else {
4025308Sab196087 			if (elfedit_sec_findstr(argstate->str.sec, 0, argv[0],
4035308Sab196087 			    &argstate->str.ndx) == 0)
4045308Sab196087 				elfedit_msg(ELFEDIT_MSG_ERR,
4055308Sab196087 				    MSG_INTL(MSG_ERR_STRNOTFND),
4065308Sab196087 				    EC_WORD(argstate->str.sec->sec_shndx),
4075308Sab196087 				    argstate->str.sec->sec_name, argv[0]);
4085308Sab196087 		}
4095308Sab196087 	} else {
4105308Sab196087 		argstate->str.ndx = 0;
4115308Sab196087 	}
4125308Sab196087 }
4135308Sab196087 
4145308Sab196087 
4155308Sab196087 
4165308Sab196087 /*
4175308Sab196087  * Print string table values, taking output style into account.
4185308Sab196087  *
4195308Sab196087  * entry:
4205308Sab196087  *	autoprint - If True, output is only produced if the elfedit
4215308Sab196087  *		autoprint flag is set. If False, output is always produced.
4225308Sab196087  *	argstate - State block for current symbol table.
4235308Sab196087  */
4245308Sab196087 static void
print_strtab(int autoprint,ARGSTATE * argstate)4255308Sab196087 print_strtab(int autoprint, ARGSTATE *argstate)
4265308Sab196087 {
4275308Sab196087 	char			index[(MAXNDXSIZE * 2) + 4];
4285308Sab196087 	elfedit_outstyle_t	outstyle;
4295308Sab196087 	const char		*str, *limit, *tbl_limit;
4305308Sab196087 	Word			ndx;
4315308Sab196087 
4325308Sab196087 
4335308Sab196087 	if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
4345308Sab196087 		return;
4355308Sab196087 
4365308Sab196087 	outstyle = elfedit_outstyle();
4375308Sab196087 	if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
4385308Sab196087 		elfedit_printf(MSG_INTL(MSG_FMT_STRTAB),
4395308Sab196087 		    argstate->str.sec->sec_name);
4405308Sab196087 		if (argstate->dyn.strpad.dn_seen)
4415308Sab196087 			elfedit_printf(MSG_INTL(MSG_FMT_DYNSTRPAD),
4425308Sab196087 			    EC_WORD(argstate->str.sec->sec_data->d_size -
4435308Sab196087 			    argstate->dyn.strpad.dn_dyn.d_un.d_val),
4445308Sab196087 			    EC_WORD(argstate->str.sec->sec_data->d_size - 1),
4455308Sab196087 			    EC_WORD(argstate->dyn.strpad.dn_dyn.d_un.d_val));
4465308Sab196087 		elfedit_printf(MSG_INTL(MSG_FMT_DUMPTITLE));
4475308Sab196087 	}
4485308Sab196087 
4495308Sab196087 	str = argstate->str.sec->sec_data->d_buf;
4505308Sab196087 	tbl_limit = str + argstate->str.sec->sec_data->d_size;
4515308Sab196087 	ndx = argstate->str.ndx;
4525308Sab196087 	if (argstate->argc > 0) {
4535308Sab196087 		str += ndx;
4545308Sab196087 		/*
4555308Sab196087 		 * If first byte is NULL and this is the default output style,
4565308Sab196087 		 * then we want to display the range of NULL bytes, and we
4575308Sab196087 		 * push limit out to the last one in the sequence. Otherwise,
4585308Sab196087 		 * just display the string.
4595308Sab196087 		 */
4605308Sab196087 		if ((*str == '\0') && (outstyle == ELFEDIT_OUTSTYLE_DEFAULT)) {
4615308Sab196087 			limit = str;
4625308Sab196087 			while (((limit + 1) < tbl_limit) &&
4635308Sab196087 			    (*(limit + 1) == '\0'))
4645308Sab196087 				limit++;
4655308Sab196087 		} else {
4665308Sab196087 			limit = str + strlen(str) + 1;
4675308Sab196087 		}
4685308Sab196087 	} else {
4695308Sab196087 		/* Display the entire string table  */
4705308Sab196087 		limit = tbl_limit;
4715308Sab196087 	}
4725308Sab196087 
4735308Sab196087 
4745308Sab196087 	while (str < limit) {
4755308Sab196087 		Word	skip = strlen(str) + 1;
4765308Sab196087 		Word	start_ndx;
4775308Sab196087 
4785308Sab196087 		if (outstyle != ELFEDIT_OUTSTYLE_DEFAULT) {
4795308Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), str);
4805308Sab196087 			str += skip;
4815308Sab196087 			ndx += skip;
4825308Sab196087 			continue;
4835308Sab196087 		}
4845308Sab196087 
4855308Sab196087 		start_ndx = ndx;
4865308Sab196087 		if (*str == '\0')
4875308Sab196087 			while (((str + 1) < limit) && (*(str + 1) == '\0')) {
4885308Sab196087 				ndx++;
4895308Sab196087 				str++;
4905308Sab196087 			}
4915308Sab196087 
4925308Sab196087 		if (start_ndx != ndx) {
4935308Sab196087 			(void) snprintf(index, sizeof (index),
4945308Sab196087 			    MSG_ORIG(MSG_FMT_INDEXRANGE),
4955308Sab196087 			    EC_XWORD(start_ndx), EC_XWORD(ndx));
4965308Sab196087 		} else {
4975308Sab196087 			(void) snprintf(index, sizeof (index),
4985308Sab196087 			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(ndx));
4995308Sab196087 		}
5005892Sab196087 		elfedit_printf(MSG_ORIG(MSG_FMT_DUMPENTRY), index);
5015892Sab196087 		elfedit_write(MSG_ORIG(MSG_STR_DQUOTE), MSG_STR_DQUOTE_SIZE);
5025892Sab196087 		if (start_ndx == ndx)
5035892Sab196087 			elfedit_str_to_c_literal(str, elfedit_write);
5045892Sab196087 		elfedit_write(MSG_ORIG(MSG_STR_DQUOTENL),
5055892Sab196087 		    MSG_STR_DQUOTENL_SIZE);
5065308Sab196087 		str += skip;
5075308Sab196087 		ndx += skip;
5085308Sab196087 	}
5095308Sab196087 }
5105308Sab196087 
5115308Sab196087 
5125308Sab196087 /*
5135308Sab196087  * Command body for str:set, handling the case where the 3rd
5145308Sab196087  * argument (new-str) is present.
5155308Sab196087  */
5165308Sab196087 static elfedit_cmdret_t
cmd_body_set(ARGSTATE * argstate)5175308Sab196087 cmd_body_set(ARGSTATE *argstate)
5185308Sab196087 {
5195308Sab196087 	elfedit_section_t	*strsec = argstate->str.sec;
5205308Sab196087 	const char		*newstr = argstate->argv[1];
5215308Sab196087 	Word	ndx = argstate->str.ndx;
5225308Sab196087 	char	*oldstr;
5235308Sab196087 	int	i, len, ncp;
5245308Sab196087 
5255308Sab196087 	len = strlen(newstr);
5265308Sab196087 	ncp = len;
5275308Sab196087 	if (!(argstate->optmask & STR_OPT_F_NOTERM))
5285308Sab196087 		ncp++;
5295308Sab196087 
5305308Sab196087 	/* NULL string with no termination? Nothing to do */
5315308Sab196087 	if (ncp == 0)
5325308Sab196087 		return (ELFEDIT_CMDRET_NONE);
5335308Sab196087 
5345308Sab196087 	/* Does it fit? */
5355308Sab196087 	if ((ndx + ncp) > strsec->sec_data->d_size)
5365308Sab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOFIT),
5375308Sab196087 		    EC_WORD(strsec->sec_shndx), strsec->sec_name,
5385308Sab196087 		    EC_WORD(ndx), newstr);
5395308Sab196087 
5405308Sab196087 	/* Does it clobber the final NULL termination? */
5415308Sab196087 	if (((ndx + ncp) == strsec->sec_data->d_size) &&
5425308Sab196087 	    (argstate->optmask & STR_OPT_F_NOTERM))
5435308Sab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_FINALNULL),
5445308Sab196087 		    EC_WORD(strsec->sec_shndx), strsec->sec_name,
5455308Sab196087 		    EC_WORD(ndx), newstr);
5465308Sab196087 
5475308Sab196087 	/*
5485308Sab196087 	 * strtab[0] is always supposed to contain a NULL byte. You're not
5495308Sab196087 	 * supposed to mess with it. We will carry out this operation,
5505308Sab196087 	 * but with a debug message indicating that it is unorthodox.
5515308Sab196087 	 */
5525308Sab196087 	if ((ndx == 0) && (*newstr != '\0'))
5535308Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSTR0),
5545308Sab196087 		    EC_WORD(strsec->sec_shndx), strsec->sec_name,
5555308Sab196087 		    EC_WORD(ndx), newstr);
5565308Sab196087 
5575308Sab196087 	/* Does it alter the existing value? */
5585308Sab196087 	oldstr = ndx + (char *)strsec->sec_data->d_buf;
5595308Sab196087 	for (i = 0; i < ncp; i++)
5605308Sab196087 		if (newstr[i] != oldstr[i])
5615308Sab196087 			break;
5625308Sab196087 	if (i == ncp) {		/* No change */
5635308Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK),
5645308Sab196087 		    strsec->sec_shndx, strsec->sec_name, ndx, newstr);
5655308Sab196087 		return (ELFEDIT_CMDRET_NONE);
5665308Sab196087 	}
5675308Sab196087 
5685308Sab196087 	/*
5695308Sab196087 	 * If the new string is longer than the old one, then it will
5705308Sab196087 	 * clobber the start of the following string. The resulting
5715308Sab196087 	 * string table is perfectly legal, but issue a debug message
5725308Sab196087 	 * letting the user know.
5735308Sab196087 	 */
5745308Sab196087 	i = strlen(oldstr);
5755308Sab196087 	if (len > i)
5765308Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_LONGSTR),
5775308Sab196087 		    EC_WORD(strsec->sec_shndx), strsec->sec_name,
5785308Sab196087 		    EC_WORD(ndx), len, i);
5795308Sab196087 
5805308Sab196087 	/*
5815308Sab196087 	 * If we have strayed into the reserved part of the dynstr, then
5825308Sab196087 	 * update DT_SUNW_STRPAD.
5835308Sab196087 	 */
5845308Sab196087 	if (argstate->dyn.strpad.dn_seen) {
5855308Sab196087 		elfedit_dyn_elt_t	*strpad = &argstate->dyn.strpad;
5865308Sab196087 		Word	new_pad_ndx = ndx + len + 1;
5875308Sab196087 		Word	pad_ndx = argstate->str.sec->sec_data->d_size -
5885308Sab196087 		    strpad->dn_dyn.d_un.d_val;
5895308Sab196087 
5905308Sab196087 		if (new_pad_ndx > pad_ndx) {
5915308Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
5925308Sab196087 			    MSG_INTL(MSG_DEBUG_ADDDYNSTR),
5935308Sab196087 			    EC_WORD(strsec->sec_shndx), strsec->sec_name,
5945308Sab196087 			    EC_WORD(ndx), EC_WORD(new_pad_ndx - pad_ndx),
5955308Sab196087 			    EC_WORD(strpad->dn_dyn.d_un.d_val),
5965308Sab196087 			    newstr);
5975308Sab196087 
5985308Sab196087 			strpad->dn_dyn.d_un.d_val =
5995308Sab196087 			    argstate->dyn.data[strpad->dn_ndx].d_un.d_val =
6005308Sab196087 			    (argstate->str.sec->sec_data->d_size - new_pad_ndx);
6015308Sab196087 			elfedit_modified_data(argstate->dyn.sec);
6025308Sab196087 		}
6035308Sab196087 	}
6045308Sab196087 
6055308Sab196087 
6065308Sab196087 
6075308Sab196087 	elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG),
6085308Sab196087 	    strsec->sec_shndx, strsec->sec_name, ndx, len, oldstr, newstr);
6095308Sab196087 	bcopy(newstr, oldstr, ncp);
6105308Sab196087 
6115308Sab196087 	return (ELFEDIT_CMDRET_MOD);
6125308Sab196087 }
6135308Sab196087 
6145308Sab196087 
6155308Sab196087 /*
6165308Sab196087  * Command body for str:zero
6175308Sab196087  */
6185308Sab196087 static elfedit_cmdret_t
cmd_body_zero(ARGSTATE * argstate)6195308Sab196087 cmd_body_zero(ARGSTATE *argstate)
6205308Sab196087 {
6215308Sab196087 	elfedit_section_t	*strsec = argstate->str.sec;
6225308Sab196087 	Word	count;
6235308Sab196087 	Word	ndx = argstate->str.ndx;
6245308Sab196087 	char	*oldstr = ndx + (char *)strsec->sec_data->d_buf;
6255308Sab196087 	Word	i;
6265308Sab196087 
6275308Sab196087 	/* How many bytes to zero? */
6285308Sab196087 	if (argstate->optmask & STR_OPT_F_END)
6295308Sab196087 		count = strsec->sec_data->d_size - argstate->str.ndx;
6305308Sab196087 	else if (argstate->argc == 2)
6315308Sab196087 		count = elfedit_atoui_range(argstate->argv[1],
6325308Sab196087 		    MSG_ORIG(MSG_STR_COUNT), 0,
6335308Sab196087 		    argstate->str.sec->sec_data->d_size - argstate->str.ndx,
6345308Sab196087 		    NULL);
6355308Sab196087 	else
6365308Sab196087 		count = strlen(oldstr);
6375308Sab196087 
6385308Sab196087 	/* Does it alter the existing value? */
6395308Sab196087 	for (i = 0; i < count; i++)
6405308Sab196087 		if (oldstr[i] != '\0')
6415308Sab196087 			break;
6425308Sab196087 	if (i == count) {		/* No change */
6435308Sab196087 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_Z_OK),
6445308Sab196087 		    strsec->sec_shndx, strsec->sec_name, ndx);
6455308Sab196087 		return (ELFEDIT_CMDRET_NONE);
6465308Sab196087 	}
6475308Sab196087 
6485308Sab196087 	elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_Z_CHG),
6495308Sab196087 	    strsec->sec_shndx, strsec->sec_name, ndx, count);
6505308Sab196087 	bzero(oldstr, count);
6515308Sab196087 
6525308Sab196087 	return (ELFEDIT_CMDRET_MOD);
6535308Sab196087 }
6545308Sab196087 
6555308Sab196087 
6565308Sab196087 /*
6575308Sab196087  * Common body for the str: module commands.
6585308Sab196087  *
6595308Sab196087  * entry:
6605308Sab196087  *	cmd - One of the STR_CMD_T_* constants listed above, specifying
6615308Sab196087  *		which command to implement.
6625308Sab196087  *	obj_state, argc, argv - Standard command arguments
6635308Sab196087  */
6645308Sab196087 static elfedit_cmdret_t
cmd_body(STR_CMD_T cmd,elfedit_obj_state_t * obj_state,int argc,const char * argv[])6655308Sab196087 cmd_body(STR_CMD_T cmd, elfedit_obj_state_t *obj_state,
6665308Sab196087     int argc, const char *argv[])
6675308Sab196087 {
6685308Sab196087 	ARGSTATE		argstate;
6695308Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
6705308Sab196087 	int			print_only;
6715308Sab196087 
6725308Sab196087 	process_args(obj_state, argc, argv, cmd, &argstate, &print_only);
6735308Sab196087 
6745308Sab196087 	/*
6755308Sab196087 	 * If this call call does not change data, display the current
6765308Sab196087 	 * value(s) and return.
6775308Sab196087 	 */
6785308Sab196087 	if (print_only) {
6795308Sab196087 		print_strtab(0, &argstate);
6805308Sab196087 		return (ELFEDIT_CMDRET_NONE);
6815308Sab196087 	}
6825308Sab196087 
6835308Sab196087 	switch (cmd) {
6845308Sab196087 	/* NOTE: STR_CMD_T_DUMP can't get here --- it's always print_only */
6855308Sab196087 
6865308Sab196087 	case STR_CMD_T_SET:
6875308Sab196087 		ret = cmd_body_set(&argstate);
6885308Sab196087 		break;
6895308Sab196087 
6905308Sab196087 	case STR_CMD_T_ADD:
6915308Sab196087 		argstate.str.ndx = elfedit_strtab_insert(obj_state,
6925308Sab196087 		    argstate.str.sec, argstate.dyn.sec, argstate.argv[0]);
6935308Sab196087 		break;
6945308Sab196087 
6955308Sab196087 	case STR_CMD_T_ZERO:
6965308Sab196087 		ret = cmd_body_zero(&argstate);
6975308Sab196087 		break;
6985308Sab196087 	}
6995308Sab196087 
7005308Sab196087 	/*
7015308Sab196087 	 * If we modified the strtab section, tell libelf.
7025308Sab196087 	 */
7035308Sab196087 	if (ret == ELFEDIT_CMDRET_MOD)
7045308Sab196087 		elfedit_modified_data(argstate.str.sec);
7055308Sab196087 
7065308Sab196087 	/* Do autoprint */
7075308Sab196087 	print_strtab(1, &argstate);
7085308Sab196087 
7095308Sab196087 	return (ret);
7105308Sab196087 }
7115308Sab196087 
7125308Sab196087 
7135308Sab196087 
7145308Sab196087 
7155308Sab196087 /*
7165308Sab196087  * Command completion functions for the various commands
7175308Sab196087  */
7185308Sab196087 
7195308Sab196087 static void
add_shtyp_match(Word sh_type,void * cpldata)7205308Sab196087 add_shtyp_match(Word sh_type, void *cpldata)
7215308Sab196087 {
7225308Sab196087 	char		buf[128];
7235308Sab196087 	const char	*s;
7245308Sab196087 	char		*s2;
7255308Sab196087 
7265308Sab196087 	s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_SHT, sh_type, 0);
7275308Sab196087 	elfedit_cpl_match(cpldata, s, 1);
7285308Sab196087 
7295308Sab196087 	/*
7305308Sab196087 	 * To get the informal tag names that are lowercase
7315308Sab196087 	 * and lack the leading SHT_, we copy the string we
7325308Sab196087 	 * have into a buffer and process it.
7335308Sab196087 	 */
7345308Sab196087 	if (strlen(s) < 4)
7355308Sab196087 		return;
7365308Sab196087 	(void) strlcpy(buf, s + 4, sizeof (buf));
7375308Sab196087 	for (s2 = buf; *s2 != '\0'; s2++)
7385308Sab196087 		if (isupper(*s2))
7395308Sab196087 			*s2 = tolower(*s2);
7405308Sab196087 	elfedit_cpl_match(cpldata, buf, 1);
7415308Sab196087 }
7425308Sab196087 
7435308Sab196087 /*
7445308Sab196087  * Handle filling in the values for -shnam, -shndx, and -shtyp options.
7455308Sab196087  */
7465308Sab196087 /*ARGSUSED*/
7475308Sab196087 static void
cpl_sh_opt(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)7485308Sab196087 cpl_sh_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
7495308Sab196087     const char *argv[], int num_opt)
7505308Sab196087 {
7515308Sab196087 	enum { NAME, INDEX, TYPE }	op;
7525308Sab196087 	elfedit_section_t		*sec;
7535308Sab196087 	Word 	ndx;
7545308Sab196087 
7555308Sab196087 	if ((argc != num_opt) || (argc < 2))
7565308Sab196087 		return;
7575308Sab196087 
7585308Sab196087 	if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) {
7595308Sab196087 		op = NAME;
7605308Sab196087 	} else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) {
7615308Sab196087 		op = INDEX;
7625308Sab196087 
7635308Sab196087 	} else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) {
7645308Sab196087 		op = TYPE;
7655308Sab196087 
7665308Sab196087 		if (obj_state == NULL) {	 /* No object available */
7675308Sab196087 			elfedit_atoui_sym_t *atoui_sym;
7685308Sab196087 
7695308Sab196087 			atoui_sym = elfedit_const_to_atoui(ELFEDIT_CONST_SHT);
7705308Sab196087 			for (; atoui_sym->sym_name != NULL; atoui_sym++)
7716225Sab196087 				if (shtype_to_strtab(atoui_sym->sym_value, 0) !=
7725308Sab196087 				    SHTOSTR_NONE)
7735308Sab196087 					elfedit_cpl_match(cpldata,
7745308Sab196087 					    atoui_sym->sym_name, 1);
7755308Sab196087 		}
7765308Sab196087 	} else {
7775308Sab196087 		return;
7785308Sab196087 	}
7795308Sab196087 
7805308Sab196087 	if (obj_state == NULL)	 /* No object available */
7815308Sab196087 		return;
7825308Sab196087 
7835308Sab196087 	/*
7845308Sab196087 	 * Loop over the section headers and supply command completion
7855308Sab196087 	 * for the items in the file that can yield a string table.
7865308Sab196087 	 */
7875308Sab196087 	sec = obj_state->os_secarr;
7885308Sab196087 	for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++) {
7896225Sab196087 		Shdr		*shdr = sec->sec_shdr;
7906225Sab196087 		SHTOSTR_T	shtostr_type;
7915308Sab196087 
7926225Sab196087 		shtostr_type = shtype_to_strtab(shdr->sh_type, shdr->sh_flags);
7936225Sab196087 		if (shtostr_type == SHTOSTR_NONE)
7945308Sab196087 			continue;
7955308Sab196087 
7965308Sab196087 		switch (op) {
7975308Sab196087 		case NAME:
7985308Sab196087 			elfedit_cpl_match(cpldata, sec->sec_name, 0);
7995308Sab196087 			break;
8005308Sab196087 		case INDEX:
8016225Sab196087 			elfedit_cpl_ndx(cpldata, sec->sec_shndx);
8025308Sab196087 			break;
8035308Sab196087 		case TYPE:
8046225Sab196087 			if (shtostr_type != SHTOSTR_SHF_STRINGS)
8056225Sab196087 				add_shtyp_match(shdr->sh_type, cpldata);
8065308Sab196087 			break;
8075308Sab196087 		}
8085308Sab196087 	}
8095308Sab196087 }
8105308Sab196087 
8115308Sab196087 
8125308Sab196087 /*
8135308Sab196087  * Most of the commands accept an -shXXX option for the string table
8145308Sab196087  * and a string first argument. This routine examines which argument
8155308Sab196087  * is being processed, and supplies completion for these items.
8165308Sab196087  */
8175308Sab196087 static void
cpl_sec_str(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)8185308Sab196087 cpl_sec_str(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
8195308Sab196087     const char *argv[], int num_opt)
8205308Sab196087 {
8215308Sab196087 	const char		*str, *limit;
8225308Sab196087 	elfedit_section_t	*sec;
8235308Sab196087 	Word			strtab_ndx;
8245308Sab196087 	Word			ndx;
8255308Sab196087 
8265308Sab196087 	/* Handle -shXXX options */
8275308Sab196087 	cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt);
8285308Sab196087 
8295308Sab196087 	/* Without object state, there's no data to work from */
8305308Sab196087 	if (obj_state == NULL)
8315308Sab196087 		return;
8325308Sab196087 
8335308Sab196087 	/* If not first plain arg, return */
8345308Sab196087 	if (argc != (num_opt + 1))
8355308Sab196087 		return;
8365308Sab196087 
8375308Sab196087 	/*
8385308Sab196087 	 * Look at the options, looking for two things:
8395308Sab196087 	 *	1) A -shXXX option specifying a section. If so, turn that
8405308Sab196087 	 *		into a section index if possible.
8415308Sab196087 	 *	2) Was -strndx used? If so, we are looking at an integer
8425308Sab196087 	 *		value and have nothing to complete.
8435308Sab196087 	 */
8445308Sab196087 	strtab_ndx = obj_state->os_ehdr->e_shstrndx;
8455308Sab196087 	for (ndx = 0; ndx < num_opt; ndx++) {
8465308Sab196087 		if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_STRNDX)) == 0)
8475308Sab196087 			return;
8485308Sab196087 
8495308Sab196087 		if ((ndx+1) < num_opt) {
8505308Sab196087 			if (strcmp(argv[ndx],
8515308Sab196087 			    MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) {
8525308Sab196087 				Word		i;
8535308Sab196087 
8545308Sab196087 				for (i = 1; i < obj_state->os_shnum; i++)
8555308Sab196087 					if (strcmp(obj_state->os_secarr[i].
8565308Sab196087 					    sec_name, argv[ndx+1]) == 0) {
8575308Sab196087 						strtab_ndx = i;
8585308Sab196087 						break;
8595308Sab196087 					}
8605308Sab196087 			} else if (strcmp(argv[ndx],
8615308Sab196087 			    MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) {
8625308Sab196087 				elfedit_atoui_t val;
8635308Sab196087 
8645308Sab196087 				if (elfedit_atoui2(argv[ndx+1], NULL,
8655308Sab196087 				    &val) != 0)
8665308Sab196087 					strtab_ndx = val;
8675308Sab196087 			} else if (strcmp(argv[ndx],
8685308Sab196087 			    MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) {
8695308Sab196087 				elfedit_atoui_t	sh_type;
8705308Sab196087 				Word		i;
8715308Sab196087 
8725308Sab196087 				if (elfedit_atoconst2(argv[ndx+1],
8735308Sab196087 				    ELFEDIT_CONST_SHT, &sh_type) == 0)
8745308Sab196087 					continue;
8755308Sab196087 				for (i = 1; i < obj_state->os_shnum; i++)
8765308Sab196087 					if (obj_state->os_secarr[i].sec_shdr->
8775308Sab196087 					    sh_type == sh_type) {
8785308Sab196087 						strtab_ndx = i;
8795308Sab196087 						break;
8805308Sab196087 					}
8815308Sab196087 			}
8825308Sab196087 		}
8835308Sab196087 	}
8845308Sab196087 
8855308Sab196087 	/*
8865308Sab196087 	 * Locate and validate the string table. In the case where
8875308Sab196087 	 * a non-string table section is given that references a string
8885308Sab196087 	 * table, we will use the referenced table.
8895308Sab196087 	 */
8905308Sab196087 	strtab_ndx = shndx_to_strtab(obj_state, strtab_ndx);
8915308Sab196087 	if ((strtab_ndx >= obj_state->os_shnum) ||
8925308Sab196087 	    (obj_state->os_secarr[strtab_ndx].sec_shdr->sh_type != SHT_STRTAB))
8935308Sab196087 		return;
8945308Sab196087 	sec = &obj_state->os_secarr[strtab_ndx];
8955308Sab196087 
8965308Sab196087 	str = sec->sec_data->d_buf;
8975308Sab196087 	limit = str + sec->sec_data->d_size;
8985308Sab196087 	while (str < limit) {
8995308Sab196087 		if (*str != '\0')
9005308Sab196087 			elfedit_cpl_match(cpldata, str, 0);
9015308Sab196087 		str += strlen(str) + 1;
9025308Sab196087 	}
9035308Sab196087 }
9045308Sab196087 
9055308Sab196087 
9065308Sab196087 
9075308Sab196087 /*
9085308Sab196087  * Implementation functions for the commands
9095308Sab196087  */
9105308Sab196087 static elfedit_cmdret_t
cmd_dump(elfedit_obj_state_t * obj_state,int argc,const char * argv[])9115308Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
9125308Sab196087 {
9135308Sab196087 	return (cmd_body(STR_CMD_T_DUMP, obj_state, argc, argv));
9145308Sab196087 }
9155308Sab196087 
9165308Sab196087 static elfedit_cmdret_t
cmd_set(elfedit_obj_state_t * obj_state,int argc,const char * argv[])9175308Sab196087 cmd_set(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
9185308Sab196087 {
9195308Sab196087 	return (cmd_body(STR_CMD_T_SET, obj_state, argc, argv));
9205308Sab196087 }
9215308Sab196087 
9225308Sab196087 static elfedit_cmdret_t
cmd_add(elfedit_obj_state_t * obj_state,int argc,const char * argv[])9235308Sab196087 cmd_add(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
9245308Sab196087 {
9255308Sab196087 	return (cmd_body(STR_CMD_T_ADD, obj_state, argc, argv));
9265308Sab196087 }
9275308Sab196087 
9285308Sab196087 static elfedit_cmdret_t
cmd_zero(elfedit_obj_state_t * obj_state,int argc,const char * argv[])9295308Sab196087 cmd_zero(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
9305308Sab196087 {
9315308Sab196087 	return (cmd_body(STR_CMD_T_ZERO, obj_state, argc, argv));
9325308Sab196087 }
9335308Sab196087 
9345308Sab196087 
9355308Sab196087 
9365308Sab196087 /*ARGSUSED*/
9375308Sab196087 elfedit_module_t *
elfedit_init(elfedit_module_version_t version)9385308Sab196087 elfedit_init(elfedit_module_version_t version)
9395308Sab196087 {
9405308Sab196087 	/* str:dump */
9415308Sab196087 	static const char *name_dump[] = {
9425308Sab196087 	    MSG_ORIG(MSG_CMD_DUMP),
9435308Sab196087 	    MSG_ORIG(MSG_STR_EMPTY),	/* "" makes this the default command */
9445308Sab196087 	    NULL
9455308Sab196087 	};
9465308Sab196087 	static elfedit_cmd_optarg_t opt_dump[] = {
9475892Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_ANY),
9485892Sab196087 		    /* MSG_INTL(MSG_OPTDESC_ANY) */
9495892Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_ANY), 0,
9505892Sab196087 		    STR_OPT_F_ANY, 0 },
9515308Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
9525308Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
9535308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
9545308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
9555308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
9565308Sab196087 		    STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP },
9575308Sab196087 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0 },
9585308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
9595308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
9605308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
9615308Sab196087 		    STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP },
9625308Sab196087 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
9635308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
9645308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
9655308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
9665308Sab196087 		    STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX },
9675308Sab196087 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
9685308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_STRNDX),
9695308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_STRNDX) */
9705308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_STRNDX), 0,
9715308Sab196087 		    STR_OPT_F_STRNDX, 0 },
9725308Sab196087 		{ NULL }
9735308Sab196087 	};
9745308Sab196087 	static elfedit_cmd_optarg_t arg_dump[] = {
9755308Sab196087 		{ MSG_ORIG(MSG_STR_STRING),
9765308Sab196087 		    /* MSG_INTL(MSG_A1_STRING) */
9775308Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_STRING),
9785308Sab196087 		    ELFEDIT_CMDOA_F_OPT },
9795308Sab196087 		{ NULL }
9805308Sab196087 	};
9815308Sab196087 
9825308Sab196087 	/* str:set */
9835308Sab196087 	static const char *name_set[] = {
9845308Sab196087 	    MSG_ORIG(MSG_CMD_SET), NULL };
9855308Sab196087 	static elfedit_cmd_optarg_t opt_set[] = {
9865892Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_ANY),
9875892Sab196087 		    /* MSG_INTL(MSG_OPTDESC_ANY) */
9885892Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_ANY), 0,
9895892Sab196087 		    STR_OPT_F_ANY, 0 },
9905308Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
9915308Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
9925308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_NOTERM),
9935308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_NOTERM) */
9945308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_NOTERM), 0,
9955308Sab196087 		    STR_OPT_F_NOTERM, 0 },
9965308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
9975308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
9985308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
9995308Sab196087 		    STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP },
10005308Sab196087 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0 },
10015308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
10025308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
10035308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
10045308Sab196087 		    STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP },
10055308Sab196087 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
10065308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
10075308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
10085308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
10095308Sab196087 		    STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX },
10105308Sab196087 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
10115308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_STRNDX),
10125308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_STRNDX) */
10135308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_STRNDX), 0,
10145308Sab196087 		    STR_OPT_F_STRNDX, 0 },
10155308Sab196087 		{ NULL }
10165308Sab196087 	};
10175308Sab196087 	static elfedit_cmd_optarg_t arg_set[] = {
10185308Sab196087 		{ MSG_ORIG(MSG_STR_STRING),
10195308Sab196087 		    /* MSG_INTL(MSG_A1_STRING) */
10205308Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_STRING),
10215308Sab196087 		    0 },
10225308Sab196087 		{ MSG_ORIG(MSG_STR_NEWSTRING),
10235308Sab196087 		    /* MSG_INTL(MSG_A2_NEWSTRING) */
10245308Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_NEWSTRING),
10255308Sab196087 		    ELFEDIT_CMDOA_F_OPT },
10265308Sab196087 		{ NULL }
10275308Sab196087 	};
10285308Sab196087 
10295308Sab196087 	/* str:add */
10305308Sab196087 	static const char *name_add[] = {
10315308Sab196087 	    MSG_ORIG(MSG_CMD_ADD), NULL };
10325308Sab196087 	static elfedit_cmd_optarg_t opt_add[] = {
10335308Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
10345308Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
10355308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
10365308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
10375308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
10385308Sab196087 		    STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP },
10395308Sab196087 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0 },
10405308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
10415308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
10425308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
10435308Sab196087 		    STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP },
10445308Sab196087 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
10455308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
10465308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
10475308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
10485308Sab196087 		    STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX },
10495308Sab196087 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
10505308Sab196087 		{ NULL }
10515308Sab196087 	};
10525308Sab196087 	static elfedit_cmd_optarg_t arg_add[] = {
10535308Sab196087 		{ MSG_ORIG(MSG_STR_NEWSTRING),
10545308Sab196087 		    /* MSG_INTL(MSG_A1_NEWSTRING) */
10555308Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_NEWSTRING),
10565308Sab196087 		    0 },
10575308Sab196087 		{ NULL }
10585308Sab196087 	};
10595308Sab196087 
10605308Sab196087 	/* str:zero */
10615308Sab196087 	static const char *name_zero[] = {
10625308Sab196087 	    MSG_ORIG(MSG_CMD_ZERO), NULL };
10635308Sab196087 	static elfedit_cmd_optarg_t opt_zero[] = {
10645892Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_ANY),
10655892Sab196087 		    /* MSG_INTL(MSG_OPTDESC_ANY) */
10665892Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_ANY), 0,
10675892Sab196087 		    STR_OPT_F_ANY, 0 },
10685308Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
10695308Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
10705308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNAM),
10715308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNAM) */
10725308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE,
10735308Sab196087 		    STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP },
10745308Sab196087 		{ MSG_ORIG(MSG_STR_NAME), NULL, 0 },
10755308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHNDX),
10765308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHNDX) */
10775308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE,
10785308Sab196087 		    STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP },
10795308Sab196087 		{ MSG_ORIG(MSG_STR_INDEX), NULL, 0 },
10805308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_SHTYP),
10815308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_SHTYP) */
10825308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE,
10835308Sab196087 		    STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX },
10845308Sab196087 		{ MSG_ORIG(MSG_STR_TYPE), NULL, 0 },
10855308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_STRNDX),
10865308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_STRNDX) */
10875308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_STRNDX), 0,
10885308Sab196087 		    STR_OPT_F_STRNDX, 0 },
10895308Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_END),
10905308Sab196087 		    /* MSG_INTL(MSG_OPTDESC_END) */
10915308Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_END), 0,
10925308Sab196087 		    STR_OPT_F_END, 0 },
10935308Sab196087 		{ NULL }
10945308Sab196087 	};
10955308Sab196087 	static elfedit_cmd_optarg_t arg_zero[] = {
10965308Sab196087 		{ MSG_ORIG(MSG_STR_STRING),
10975308Sab196087 		    /* MSG_INTL(MSG_A1_STRING) */
10985308Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_STRING),
10995308Sab196087 		    0 },
11005308Sab196087 		{ MSG_ORIG(MSG_STR_COUNT),
11015308Sab196087 		    /* MSG_INTL(MSG_A2_COUNT) */
11025308Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_COUNT),
11035308Sab196087 		    ELFEDIT_CMDOA_F_OPT },
11045308Sab196087 		{ NULL }
11055308Sab196087 	};
11065308Sab196087 
11075308Sab196087 
11085308Sab196087 	static elfedit_cmd_t cmds[] = {
11095308Sab196087 		/* str:dump */
11105308Sab196087 		{ cmd_dump, cpl_sec_str, name_dump,
11115308Sab196087 		    /* MSG_INTL(MSG_DESC_DUMP) */
11125308Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_DUMP),
11135308Sab196087 		    /* MSG_INTL(MSG_HELP_DUMP) */
11145308Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_DUMP),
11155308Sab196087 		    opt_dump, arg_dump },
11165308Sab196087 
11175308Sab196087 		/* str:set */
11185308Sab196087 		{ cmd_set, cpl_sec_str, name_set,
11195308Sab196087 		    /* MSG_INTL(MSG_DESC_SET) */
11205308Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_SET),
11215308Sab196087 		    /* MSG_INTL(MSG_HELP_SET) */
11225308Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_SET),
11235308Sab196087 		    opt_set, arg_set },
11245308Sab196087 
11255308Sab196087 		/* str:add */
11265308Sab196087 		{ cmd_add, cpl_sh_opt, name_add,
11275308Sab196087 		    /* MSG_INTL(MSG_DESC_ADD) */
11285308Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ADD),
11295308Sab196087 		    /* MSG_INTL(MSG_HELP_ADD) */
11305308Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ADD),
11315308Sab196087 		    opt_add, arg_add },
11325308Sab196087 
11335308Sab196087 		/* str:zero */
11345308Sab196087 		{ cmd_zero, cpl_sec_str, name_zero,
11355308Sab196087 		    /* MSG_INTL(MSG_DESC_ZERO) */
11365308Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_ZERO),
11375308Sab196087 		    /* MSG_INTL(MSG_HELP_ZERO) */
11385308Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_ZERO),
11395308Sab196087 		    opt_zero, arg_zero },
11405308Sab196087 
11415308Sab196087 		{ NULL }
11425308Sab196087 	};
11435308Sab196087 
11445308Sab196087 	static elfedit_module_t module = {
11455308Sab196087 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
11465308Sab196087 	    /* MSG_INTL(MSG_MOD_DESC) */
11475308Sab196087 	    ELFEDIT_I18NHDL(MSG_MOD_DESC),
11485308Sab196087 	    cmds, mod_i18nhdl_to_str };
11495308Sab196087 
11505308Sab196087 	return (&module);
11515308Sab196087 }
1152