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