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