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