1*5308Sab196087 /* 2*5308Sab196087 * CDDL HEADER START 3*5308Sab196087 * 4*5308Sab196087 * The contents of this file are subject to the terms of the 5*5308Sab196087 * Common Development and Distribution License (the "License"). 6*5308Sab196087 * You may not use this file except in compliance with the License. 7*5308Sab196087 * 8*5308Sab196087 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5308Sab196087 * or http://www.opensolaris.org/os/licensing. 10*5308Sab196087 * See the License for the specific language governing permissions 11*5308Sab196087 * and limitations under the License. 12*5308Sab196087 * 13*5308Sab196087 * When distributing Covered Code, include this CDDL HEADER in each 14*5308Sab196087 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5308Sab196087 * If applicable, add the following below this CDDL HEADER, with the 16*5308Sab196087 * fields enclosed by brackets "[]" replaced with your own identifying 17*5308Sab196087 * information: Portions Copyright [yyyy] [name of copyright owner] 18*5308Sab196087 * 19*5308Sab196087 * CDDL HEADER END 20*5308Sab196087 */ 21*5308Sab196087 22*5308Sab196087 /* 23*5308Sab196087 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*5308Sab196087 * Use is subject to license terms. 25*5308Sab196087 */ 26*5308Sab196087 #pragma ident "%Z%%M% %I% %E% SMI" 27*5308Sab196087 28*5308Sab196087 #include <stdio.h> 29*5308Sab196087 #include <ctype.h> 30*5308Sab196087 #include <unistd.h> 31*5308Sab196087 #include <machdep.h> 32*5308Sab196087 #include <elfedit.h> 33*5308Sab196087 #include <strings.h> 34*5308Sab196087 #include <debug.h> 35*5308Sab196087 #include <conv.h> 36*5308Sab196087 #include <str_msg.h> 37*5308Sab196087 38*5308Sab196087 39*5308Sab196087 40*5308Sab196087 41*5308Sab196087 #define MAXNDXSIZE 10 42*5308Sab196087 43*5308Sab196087 44*5308Sab196087 45*5308Sab196087 /* 46*5308Sab196087 * This module uses shared code for several of the commands. 47*5308Sab196087 * It is sometimes necessary to know which specific command 48*5308Sab196087 * is active. 49*5308Sab196087 */ 50*5308Sab196087 typedef enum { 51*5308Sab196087 STR_CMD_T_DUMP = 0, /* str:dump */ 52*5308Sab196087 STR_CMD_T_SET = 1, /* str:set */ 53*5308Sab196087 STR_CMD_T_ADD = 2, /* str:add */ 54*5308Sab196087 STR_CMD_T_ZERO = 3, /* str:zero */ 55*5308Sab196087 } STR_CMD_T; 56*5308Sab196087 57*5308Sab196087 58*5308Sab196087 59*5308Sab196087 #ifndef _ELF64 60*5308Sab196087 /* 61*5308Sab196087 * We supply this function for the msg module. Only one copy is needed. 62*5308Sab196087 */ 63*5308Sab196087 const char * 64*5308Sab196087 _str_msg(Msg mid) 65*5308Sab196087 { 66*5308Sab196087 return (gettext(MSG_ORIG(mid))); 67*5308Sab196087 } 68*5308Sab196087 69*5308Sab196087 #endif 70*5308Sab196087 71*5308Sab196087 72*5308Sab196087 73*5308Sab196087 /* 74*5308Sab196087 * This function is supplied to elfedit through our elfedit_module_t 75*5308Sab196087 * definition. It translates the opaque elfedit_i18nhdl_t handles 76*5308Sab196087 * in our module interface into the actual strings for elfedit to 77*5308Sab196087 * use. 78*5308Sab196087 * 79*5308Sab196087 * note: 80*5308Sab196087 * This module uses Msg codes for its i18n handle type. 81*5308Sab196087 * So the translation is simply to use MSG_INTL() to turn 82*5308Sab196087 * it into a string and return it. 83*5308Sab196087 */ 84*5308Sab196087 static const char * 85*5308Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 86*5308Sab196087 { 87*5308Sab196087 Msg msg = (Msg)hdl; 88*5308Sab196087 89*5308Sab196087 return (MSG_INTL(msg)); 90*5308Sab196087 } 91*5308Sab196087 92*5308Sab196087 93*5308Sab196087 94*5308Sab196087 /* 95*5308Sab196087 * The sym_opt_t enum specifies a bit value for every optional 96*5308Sab196087 * argument allowed by a command in this module. 97*5308Sab196087 */ 98*5308Sab196087 typedef enum { 99*5308Sab196087 STR_OPT_F_END = 1, /* -end: zero to end of strtab */ 100*5308Sab196087 STR_OPT_F_NOTERM = 2, /* -noterm: str:set won't term string */ 101*5308Sab196087 STR_OPT_F_SHNAME = 4, /* -shnam name: section spec. by name */ 102*5308Sab196087 STR_OPT_F_SHNDX = 8, /* -shndx ndx: strtab spec. by index */ 103*5308Sab196087 STR_OPT_F_SHTYP = 16, /* -shtyp type: section spec. by type */ 104*5308Sab196087 STR_OPT_F_STRNDX = 32, /* -strndx: String specified by index */ 105*5308Sab196087 } str_opt_t; 106*5308Sab196087 107*5308Sab196087 108*5308Sab196087 /* 109*5308Sab196087 * A variable of type ARGSTATE is used by each command to maintain 110*5308Sab196087 * information about the string table section being used, and for any 111*5308Sab196087 * auxiliary sections that are related to it. 112*5308Sab196087 */ 113*5308Sab196087 typedef struct { 114*5308Sab196087 elfedit_obj_state_t *obj_state; 115*5308Sab196087 str_opt_t optmask; /* Mask of options used */ 116*5308Sab196087 int argc; /* # of plain arguments */ 117*5308Sab196087 const char **argv; /* Plain arguments */ 118*5308Sab196087 119*5308Sab196087 struct { /* String table */ 120*5308Sab196087 elfedit_section_t *sec; 121*5308Sab196087 Word ndx; /* Table offset if (argc > 0) */ 122*5308Sab196087 } str; 123*5308Sab196087 struct { /* Dynamic section */ 124*5308Sab196087 elfedit_section_t *sec; 125*5308Sab196087 Dyn *data; 126*5308Sab196087 Word n; 127*5308Sab196087 elfedit_dyn_elt_t strpad; 128*5308Sab196087 } dyn; 129*5308Sab196087 } ARGSTATE; 130*5308Sab196087 131*5308Sab196087 132*5308Sab196087 133*5308Sab196087 /* 134*5308Sab196087 * Given an ELF SHT_ section type constant, shdr_to_strtab() returns 135*5308Sab196087 * one of the following 136*5308Sab196087 */ 137*5308Sab196087 138*5308Sab196087 typedef enum { 139*5308Sab196087 SHTOSTR_NONE = 0, /* Type can't lead to a string table */ 140*5308Sab196087 SHTOSTR_STRTAB = 1, /* type is SHT_STRTAB */ 141*5308Sab196087 SHTOSTR_LINK_STRTAB = 2, /* sh_link for type yields strtab */ 142*5308Sab196087 SHTOSTR_LINK_SYMTAB = 3, /* sh_link for type yields symtab */ 143*5308Sab196087 } SHTOSTR_T; 144*5308Sab196087 145*5308Sab196087 static int 146*5308Sab196087 shtype_to_strtab(Word sh_type) 147*5308Sab196087 { 148*5308Sab196087 switch (sh_type) { 149*5308Sab196087 case SHT_STRTAB: 150*5308Sab196087 return (SHTOSTR_STRTAB); 151*5308Sab196087 152*5308Sab196087 /* These sections reference a string table via sh_link */ 153*5308Sab196087 case SHT_DYNAMIC: 154*5308Sab196087 case SHT_SYMTAB: 155*5308Sab196087 case SHT_DYNSYM: 156*5308Sab196087 case SHT_SUNW_LDYNSYM: 157*5308Sab196087 case SHT_SUNW_verdef: 158*5308Sab196087 case SHT_SUNW_verneed: 159*5308Sab196087 return (SHTOSTR_LINK_STRTAB); 160*5308Sab196087 161*5308Sab196087 /* 162*5308Sab196087 * These sections reference a symbol table via sh_link. 163*5308Sab196087 * Symbol tables, in turn, reference a string table 164*5308Sab196087 * via their sh_link. 165*5308Sab196087 */ 166*5308Sab196087 case SHT_HASH: 167*5308Sab196087 case SHT_REL: 168*5308Sab196087 case SHT_RELA: 169*5308Sab196087 case SHT_GROUP: 170*5308Sab196087 case SHT_SYMTAB_SHNDX: 171*5308Sab196087 case SHT_SUNW_move: 172*5308Sab196087 case SHT_SUNW_syminfo: 173*5308Sab196087 case SHT_SUNW_versym: 174*5308Sab196087 case SHT_SUNW_symsort: 175*5308Sab196087 case SHT_SUNW_tlssort: 176*5308Sab196087 return (SHTOSTR_LINK_SYMTAB); 177*5308Sab196087 } 178*5308Sab196087 179*5308Sab196087 /* Types that lead to string tables were caught above */ 180*5308Sab196087 return (SHTOSTR_NONE); 181*5308Sab196087 } 182*5308Sab196087 183*5308Sab196087 /* 184*5308Sab196087 * Given a section index, attempt to convert it into an index 185*5308Sab196087 * to a string table section. 186*5308Sab196087 */ 187*5308Sab196087 static Word 188*5308Sab196087 shndx_to_strtab(elfedit_obj_state_t *obj_state, Word ndx) 189*5308Sab196087 { 190*5308Sab196087 /* 191*5308Sab196087 * Locate and validate the string table. In the case where 192*5308Sab196087 * a non-string table section is given that references a string 193*5308Sab196087 * table, we will use the referenced table. 194*5308Sab196087 */ 195*5308Sab196087 if (ndx < obj_state->os_shnum) { 196*5308Sab196087 switch (shtype_to_strtab( 197*5308Sab196087 obj_state->os_secarr[ndx].sec_shdr->sh_type)) { 198*5308Sab196087 199*5308Sab196087 /* Sections that reference a string table via sh_link */ 200*5308Sab196087 case SHTOSTR_LINK_STRTAB: 201*5308Sab196087 ndx = obj_state->os_secarr[ndx].sec_shdr->sh_link; 202*5308Sab196087 break; 203*5308Sab196087 204*5308Sab196087 /* 205*5308Sab196087 * Sections that reference a symbol tabel via sh_link, 206*5308Sab196087 * which in turn reference a string table via their sh_link. 207*5308Sab196087 */ 208*5308Sab196087 case SHTOSTR_LINK_SYMTAB: 209*5308Sab196087 ndx = obj_state->os_secarr[ndx].sec_shdr->sh_link; 210*5308Sab196087 if (ndx < obj_state->os_shnum) 211*5308Sab196087 ndx = 212*5308Sab196087 obj_state->os_secarr[ndx].sec_shdr->sh_link; 213*5308Sab196087 break; 214*5308Sab196087 } 215*5308Sab196087 } 216*5308Sab196087 217*5308Sab196087 return (ndx); 218*5308Sab196087 } 219*5308Sab196087 220*5308Sab196087 221*5308Sab196087 222*5308Sab196087 /* 223*5308Sab196087 * Standard argument processing for string table module 224*5308Sab196087 * 225*5308Sab196087 * entry 226*5308Sab196087 * obj_state, argc, argv - Standard command arguments 227*5308Sab196087 * optmask - Mask of allowed optional arguments. 228*5308Sab196087 * argstate - Address of ARGSTATE block to be initialized 229*5308Sab196087 * 230*5308Sab196087 * exit: 231*5308Sab196087 * On success, *argstate is initialized. On error, 232*5308Sab196087 * an error is issued and this routine does not return. 233*5308Sab196087 */ 234*5308Sab196087 static void 235*5308Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 236*5308Sab196087 STR_CMD_T cmd, ARGSTATE *argstate, int *print_only) 237*5308Sab196087 { 238*5308Sab196087 elfedit_getopt_state_t getopt_state; 239*5308Sab196087 elfedit_getopt_ret_t *getopt_ret; 240*5308Sab196087 Word ndx; 241*5308Sab196087 int argc_ok; 242*5308Sab196087 243*5308Sab196087 bzero(argstate, sizeof (*argstate)); 244*5308Sab196087 argstate->obj_state = obj_state; 245*5308Sab196087 246*5308Sab196087 /* 247*5308Sab196087 * By default, we use the section name string table pointed at 248*5308Sab196087 * by the ELF header. 249*5308Sab196087 */ 250*5308Sab196087 ndx = obj_state->os_ehdr->e_shstrndx; 251*5308Sab196087 252*5308Sab196087 elfedit_getopt_init(&getopt_state, &argc, &argv); 253*5308Sab196087 254*5308Sab196087 /* Add each new option to the options mask */ 255*5308Sab196087 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) { 256*5308Sab196087 argstate->optmask |= getopt_ret->gor_idmask; 257*5308Sab196087 258*5308Sab196087 switch (getopt_ret->gor_idmask) { 259*5308Sab196087 case STR_OPT_F_SHNAME: /* -shnam name */ 260*5308Sab196087 ndx = elfedit_name_to_shndx(obj_state, 261*5308Sab196087 getopt_ret->gor_value); 262*5308Sab196087 break; 263*5308Sab196087 264*5308Sab196087 case STR_OPT_F_SHNDX: /* -shndx index */ 265*5308Sab196087 ndx = elfedit_atoui(getopt_ret->gor_value, NULL); 266*5308Sab196087 break; 267*5308Sab196087 268*5308Sab196087 case STR_OPT_F_SHTYP: /* -shtyp type */ 269*5308Sab196087 ndx = elfedit_type_to_shndx(obj_state, 270*5308Sab196087 elfedit_atoconst(getopt_ret->gor_value, 271*5308Sab196087 ELFEDIT_CONST_SHT)); 272*5308Sab196087 break; 273*5308Sab196087 } 274*5308Sab196087 } 275*5308Sab196087 276*5308Sab196087 /* 277*5308Sab196087 * Usage error if there are the wrong number of plain arguments. 278*5308Sab196087 */ 279*5308Sab196087 switch (cmd) { 280*5308Sab196087 case STR_CMD_T_DUMP: 281*5308Sab196087 argc_ok = (argc == 0) || (argc == 1); 282*5308Sab196087 *print_only = 1; 283*5308Sab196087 break; 284*5308Sab196087 case STR_CMD_T_SET: 285*5308Sab196087 argc_ok = (argc == 1) || (argc == 2); 286*5308Sab196087 *print_only = (argc == 1); 287*5308Sab196087 break; 288*5308Sab196087 case STR_CMD_T_ADD: 289*5308Sab196087 argc_ok = (argc == 1); 290*5308Sab196087 *print_only = 0; 291*5308Sab196087 break; 292*5308Sab196087 case STR_CMD_T_ZERO: 293*5308Sab196087 /* 294*5308Sab196087 * The second argument (count) and the -end option are 295*5308Sab196087 * mutally exclusive. 296*5308Sab196087 */ 297*5308Sab196087 argc_ok = ((argc == 1) || (argc == 2)) && 298*5308Sab196087 !((argc == 2) && (argstate->optmask & STR_OPT_F_END)); 299*5308Sab196087 *print_only = 0; 300*5308Sab196087 break; 301*5308Sab196087 default: 302*5308Sab196087 argc_ok = 0; /* Unknown command? */ 303*5308Sab196087 break; 304*5308Sab196087 } 305*5308Sab196087 if (!argc_ok) 306*5308Sab196087 elfedit_command_usage(); 307*5308Sab196087 308*5308Sab196087 /* If there may be an arbitrary amount of output, use a pager */ 309*5308Sab196087 if (argc == 0) 310*5308Sab196087 elfedit_pager_init(); 311*5308Sab196087 312*5308Sab196087 /* Return the updated values of argc/argv */ 313*5308Sab196087 argstate->argc = argc; 314*5308Sab196087 argstate->argv = argv; 315*5308Sab196087 316*5308Sab196087 /* 317*5308Sab196087 * Locate and validate the string table. In the case where 318*5308Sab196087 * a non-string table section is given that references a string 319*5308Sab196087 * table, we will use the referenced table. 320*5308Sab196087 */ 321*5308Sab196087 ndx = shndx_to_strtab(obj_state, ndx); 322*5308Sab196087 323*5308Sab196087 /* 324*5308Sab196087 * If ndx is a string table, the following will issue the 325*5308Sab196087 * proper debug messages. If it is out of range, or of any 326*5308Sab196087 * other type, an error is issued and it doesn't return. 327*5308Sab196087 */ 328*5308Sab196087 argstate->str.sec = elfedit_sec_getstr(obj_state, ndx); 329*5308Sab196087 330*5308Sab196087 /* 331*5308Sab196087 * If there is a dynamic section, check its sh_link to the 332*5308Sab196087 * string table index. If these match, then we have the 333*5308Sab196087 * dynamic string table. In that case, fetch the dynamic 334*5308Sab196087 * section and locate the DT_SUNW_STRPAD entry, causing 335*5308Sab196087 * debug messages to be issued. 336*5308Sab196087 */ 337*5308Sab196087 argstate->dyn.sec = NULL; 338*5308Sab196087 elfedit_dyn_elt_init(&argstate->dyn.strpad); 339*5308Sab196087 if (obj_state->os_dynndx != SHN_UNDEF) { 340*5308Sab196087 elfedit_section_t *dynsec = 341*5308Sab196087 &obj_state->os_secarr[obj_state->os_dynndx]; 342*5308Sab196087 343*5308Sab196087 if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) && 344*5308Sab196087 (argstate->str.sec->sec_shndx == 345*5308Sab196087 dynsec->sec_shdr->sh_link)) { 346*5308Sab196087 argstate->dyn.sec = elfedit_sec_getdyn(obj_state, 347*5308Sab196087 &argstate->dyn.data, &argstate->dyn.n); 348*5308Sab196087 (void) elfedit_dynstr_getpad(dynsec, 349*5308Sab196087 &argstate->dyn.strpad); 350*5308Sab196087 351*5308Sab196087 /* 352*5308Sab196087 * Does the pad value make sense? 353*5308Sab196087 * Issue debug message and ignore it if not. 354*5308Sab196087 */ 355*5308Sab196087 if ((argstate->dyn.strpad.dn_seen != 0) && 356*5308Sab196087 (argstate->dyn.strpad.dn_dyn.d_un.d_val > 357*5308Sab196087 argstate->str.sec->sec_data->d_size)) { 358*5308Sab196087 argstate->dyn.strpad.dn_seen = 0; 359*5308Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 360*5308Sab196087 MSG_INTL(MSG_DEBUG_BADSTRPAD), 361*5308Sab196087 EC_WORD(argstate->str.sec->sec_shndx), 362*5308Sab196087 argstate->str.sec->sec_name, 363*5308Sab196087 EC_XWORD(argstate->dyn.strpad.dn_dyn. 364*5308Sab196087 d_un.d_val), 365*5308Sab196087 EC_XWORD(argstate->str.sec-> 366*5308Sab196087 sec_data->d_size)); 367*5308Sab196087 368*5308Sab196087 } 369*5308Sab196087 } 370*5308Sab196087 } 371*5308Sab196087 372*5308Sab196087 /* Locate the string table offset if argument is present */ 373*5308Sab196087 if ((argc > 0) && (cmd != STR_CMD_T_ADD)) { 374*5308Sab196087 /* 375*5308Sab196087 * If the -strndx option was specified, arg is an index 376*5308Sab196087 * into the string table. Otherwise it is a string 377*5308Sab196087 * to be looked up. 378*5308Sab196087 */ 379*5308Sab196087 if (argstate->optmask & STR_OPT_F_STRNDX) { 380*5308Sab196087 argstate->str.ndx = (elfedit_atoui_range(argv[0], 381*5308Sab196087 MSG_ORIG(MSG_STR_STRING), 0, 382*5308Sab196087 argstate->str.sec->sec_data->d_size - 1, NULL)); 383*5308Sab196087 } else { 384*5308Sab196087 if (elfedit_sec_findstr(argstate->str.sec, 0, argv[0], 385*5308Sab196087 &argstate->str.ndx) == 0) 386*5308Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 387*5308Sab196087 MSG_INTL(MSG_ERR_STRNOTFND), 388*5308Sab196087 EC_WORD(argstate->str.sec->sec_shndx), 389*5308Sab196087 argstate->str.sec->sec_name, argv[0]); 390*5308Sab196087 } 391*5308Sab196087 } else { 392*5308Sab196087 argstate->str.ndx = 0; 393*5308Sab196087 } 394*5308Sab196087 } 395*5308Sab196087 396*5308Sab196087 397*5308Sab196087 398*5308Sab196087 /* 399*5308Sab196087 * Print string table values, taking output style into account. 400*5308Sab196087 * 401*5308Sab196087 * entry: 402*5308Sab196087 * autoprint - If True, output is only produced if the elfedit 403*5308Sab196087 * autoprint flag is set. If False, output is always produced. 404*5308Sab196087 * argstate - State block for current symbol table. 405*5308Sab196087 */ 406*5308Sab196087 static void 407*5308Sab196087 print_strtab(int autoprint, ARGSTATE *argstate) 408*5308Sab196087 { 409*5308Sab196087 char index[(MAXNDXSIZE * 2) + 4]; 410*5308Sab196087 elfedit_outstyle_t outstyle; 411*5308Sab196087 const char *str, *limit, *tbl_limit; 412*5308Sab196087 Word ndx; 413*5308Sab196087 414*5308Sab196087 415*5308Sab196087 if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) 416*5308Sab196087 return; 417*5308Sab196087 418*5308Sab196087 outstyle = elfedit_outstyle(); 419*5308Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 420*5308Sab196087 elfedit_printf(MSG_INTL(MSG_FMT_STRTAB), 421*5308Sab196087 argstate->str.sec->sec_name); 422*5308Sab196087 if (argstate->dyn.strpad.dn_seen) 423*5308Sab196087 elfedit_printf(MSG_INTL(MSG_FMT_DYNSTRPAD), 424*5308Sab196087 EC_WORD(argstate->str.sec->sec_data->d_size - 425*5308Sab196087 argstate->dyn.strpad.dn_dyn.d_un.d_val), 426*5308Sab196087 EC_WORD(argstate->str.sec->sec_data->d_size - 1), 427*5308Sab196087 EC_WORD(argstate->dyn.strpad.dn_dyn.d_un.d_val)); 428*5308Sab196087 elfedit_printf(MSG_INTL(MSG_FMT_DUMPTITLE)); 429*5308Sab196087 } 430*5308Sab196087 431*5308Sab196087 str = argstate->str.sec->sec_data->d_buf; 432*5308Sab196087 tbl_limit = str + argstate->str.sec->sec_data->d_size; 433*5308Sab196087 ndx = argstate->str.ndx; 434*5308Sab196087 if (argstate->argc > 0) { 435*5308Sab196087 str += ndx; 436*5308Sab196087 /* 437*5308Sab196087 * If first byte is NULL and this is the default output style, 438*5308Sab196087 * then we want to display the range of NULL bytes, and we 439*5308Sab196087 * push limit out to the last one in the sequence. Otherwise, 440*5308Sab196087 * just display the string. 441*5308Sab196087 */ 442*5308Sab196087 if ((*str == '\0') && (outstyle == ELFEDIT_OUTSTYLE_DEFAULT)) { 443*5308Sab196087 limit = str; 444*5308Sab196087 while (((limit + 1) < tbl_limit) && 445*5308Sab196087 (*(limit + 1) == '\0')) 446*5308Sab196087 limit++; 447*5308Sab196087 } else { 448*5308Sab196087 limit = str + strlen(str) + 1; 449*5308Sab196087 } 450*5308Sab196087 } else { 451*5308Sab196087 /* Display the entire string table */ 452*5308Sab196087 limit = tbl_limit; 453*5308Sab196087 } 454*5308Sab196087 455*5308Sab196087 456*5308Sab196087 while (str < limit) { 457*5308Sab196087 Word skip = strlen(str) + 1; 458*5308Sab196087 Word start_ndx; 459*5308Sab196087 460*5308Sab196087 if (outstyle != ELFEDIT_OUTSTYLE_DEFAULT) { 461*5308Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), str); 462*5308Sab196087 str += skip; 463*5308Sab196087 ndx += skip; 464*5308Sab196087 continue; 465*5308Sab196087 } 466*5308Sab196087 467*5308Sab196087 start_ndx = ndx; 468*5308Sab196087 if (*str == '\0') 469*5308Sab196087 while (((str + 1) < limit) && (*(str + 1) == '\0')) { 470*5308Sab196087 ndx++; 471*5308Sab196087 str++; 472*5308Sab196087 } 473*5308Sab196087 474*5308Sab196087 if (start_ndx != ndx) { 475*5308Sab196087 (void) snprintf(index, sizeof (index), 476*5308Sab196087 MSG_ORIG(MSG_FMT_INDEXRANGE), 477*5308Sab196087 EC_XWORD(start_ndx), EC_XWORD(ndx)); 478*5308Sab196087 } else { 479*5308Sab196087 (void) snprintf(index, sizeof (index), 480*5308Sab196087 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(ndx)); 481*5308Sab196087 } 482*5308Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_DUMPENTRY), index, str); 483*5308Sab196087 str += skip; 484*5308Sab196087 ndx += skip; 485*5308Sab196087 } 486*5308Sab196087 } 487*5308Sab196087 488*5308Sab196087 489*5308Sab196087 /* 490*5308Sab196087 * Command body for str:set, handling the case where the 3rd 491*5308Sab196087 * argument (new-str) is present. 492*5308Sab196087 */ 493*5308Sab196087 static elfedit_cmdret_t 494*5308Sab196087 cmd_body_set(ARGSTATE *argstate) 495*5308Sab196087 { 496*5308Sab196087 elfedit_section_t *strsec = argstate->str.sec; 497*5308Sab196087 const char *newstr = argstate->argv[1]; 498*5308Sab196087 Word ndx = argstate->str.ndx; 499*5308Sab196087 char *oldstr; 500*5308Sab196087 int i, len, ncp; 501*5308Sab196087 502*5308Sab196087 len = strlen(newstr); 503*5308Sab196087 ncp = len; 504*5308Sab196087 if (!(argstate->optmask & STR_OPT_F_NOTERM)) 505*5308Sab196087 ncp++; 506*5308Sab196087 507*5308Sab196087 /* NULL string with no termination? Nothing to do */ 508*5308Sab196087 if (ncp == 0) 509*5308Sab196087 return (ELFEDIT_CMDRET_NONE); 510*5308Sab196087 511*5308Sab196087 /* Does it fit? */ 512*5308Sab196087 if ((ndx + ncp) > strsec->sec_data->d_size) 513*5308Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOFIT), 514*5308Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 515*5308Sab196087 EC_WORD(ndx), newstr); 516*5308Sab196087 517*5308Sab196087 /* Does it clobber the final NULL termination? */ 518*5308Sab196087 if (((ndx + ncp) == strsec->sec_data->d_size) && 519*5308Sab196087 (argstate->optmask & STR_OPT_F_NOTERM)) 520*5308Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_FINALNULL), 521*5308Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 522*5308Sab196087 EC_WORD(ndx), newstr); 523*5308Sab196087 524*5308Sab196087 /* 525*5308Sab196087 * strtab[0] is always supposed to contain a NULL byte. You're not 526*5308Sab196087 * supposed to mess with it. We will carry out this operation, 527*5308Sab196087 * but with a debug message indicating that it is unorthodox. 528*5308Sab196087 */ 529*5308Sab196087 if ((ndx == 0) && (*newstr != '\0')) 530*5308Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSTR0), 531*5308Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 532*5308Sab196087 EC_WORD(ndx), newstr); 533*5308Sab196087 534*5308Sab196087 /* Does it alter the existing value? */ 535*5308Sab196087 oldstr = ndx + (char *)strsec->sec_data->d_buf; 536*5308Sab196087 for (i = 0; i < ncp; i++) 537*5308Sab196087 if (newstr[i] != oldstr[i]) 538*5308Sab196087 break; 539*5308Sab196087 if (i == ncp) { /* No change */ 540*5308Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK), 541*5308Sab196087 strsec->sec_shndx, strsec->sec_name, ndx, newstr); 542*5308Sab196087 return (ELFEDIT_CMDRET_NONE); 543*5308Sab196087 } 544*5308Sab196087 545*5308Sab196087 /* 546*5308Sab196087 * If the new string is longer than the old one, then it will 547*5308Sab196087 * clobber the start of the following string. The resulting 548*5308Sab196087 * string table is perfectly legal, but issue a debug message 549*5308Sab196087 * letting the user know. 550*5308Sab196087 */ 551*5308Sab196087 i = strlen(oldstr); 552*5308Sab196087 if (len > i) 553*5308Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_LONGSTR), 554*5308Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 555*5308Sab196087 EC_WORD(ndx), len, i); 556*5308Sab196087 557*5308Sab196087 /* 558*5308Sab196087 * If we have strayed into the reserved part of the dynstr, then 559*5308Sab196087 * update DT_SUNW_STRPAD. 560*5308Sab196087 */ 561*5308Sab196087 if (argstate->dyn.strpad.dn_seen) { 562*5308Sab196087 elfedit_dyn_elt_t *strpad = &argstate->dyn.strpad; 563*5308Sab196087 Word new_pad_ndx = ndx + len + 1; 564*5308Sab196087 Word pad_ndx = argstate->str.sec->sec_data->d_size - 565*5308Sab196087 strpad->dn_dyn.d_un.d_val; 566*5308Sab196087 567*5308Sab196087 if (new_pad_ndx > pad_ndx) { 568*5308Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 569*5308Sab196087 MSG_INTL(MSG_DEBUG_ADDDYNSTR), 570*5308Sab196087 EC_WORD(strsec->sec_shndx), strsec->sec_name, 571*5308Sab196087 EC_WORD(ndx), EC_WORD(new_pad_ndx - pad_ndx), 572*5308Sab196087 EC_WORD(strpad->dn_dyn.d_un.d_val), 573*5308Sab196087 newstr); 574*5308Sab196087 575*5308Sab196087 strpad->dn_dyn.d_un.d_val = 576*5308Sab196087 argstate->dyn.data[strpad->dn_ndx].d_un.d_val = 577*5308Sab196087 (argstate->str.sec->sec_data->d_size - new_pad_ndx); 578*5308Sab196087 elfedit_modified_data(argstate->dyn.sec); 579*5308Sab196087 } 580*5308Sab196087 } 581*5308Sab196087 582*5308Sab196087 583*5308Sab196087 584*5308Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG), 585*5308Sab196087 strsec->sec_shndx, strsec->sec_name, ndx, len, oldstr, newstr); 586*5308Sab196087 bcopy(newstr, oldstr, ncp); 587*5308Sab196087 588*5308Sab196087 return (ELFEDIT_CMDRET_MOD); 589*5308Sab196087 } 590*5308Sab196087 591*5308Sab196087 592*5308Sab196087 /* 593*5308Sab196087 * Command body for str:zero 594*5308Sab196087 */ 595*5308Sab196087 static elfedit_cmdret_t 596*5308Sab196087 cmd_body_zero(ARGSTATE *argstate) 597*5308Sab196087 { 598*5308Sab196087 elfedit_section_t *strsec = argstate->str.sec; 599*5308Sab196087 Word count; 600*5308Sab196087 Word ndx = argstate->str.ndx; 601*5308Sab196087 char *oldstr = ndx + (char *)strsec->sec_data->d_buf; 602*5308Sab196087 Word i; 603*5308Sab196087 604*5308Sab196087 /* How many bytes to zero? */ 605*5308Sab196087 if (argstate->optmask & STR_OPT_F_END) 606*5308Sab196087 count = strsec->sec_data->d_size - argstate->str.ndx; 607*5308Sab196087 else if (argstate->argc == 2) 608*5308Sab196087 count = elfedit_atoui_range(argstate->argv[1], 609*5308Sab196087 MSG_ORIG(MSG_STR_COUNT), 0, 610*5308Sab196087 argstate->str.sec->sec_data->d_size - argstate->str.ndx, 611*5308Sab196087 NULL); 612*5308Sab196087 else 613*5308Sab196087 count = strlen(oldstr); 614*5308Sab196087 615*5308Sab196087 /* Does it alter the existing value? */ 616*5308Sab196087 for (i = 0; i < count; i++) 617*5308Sab196087 if (oldstr[i] != '\0') 618*5308Sab196087 break; 619*5308Sab196087 if (i == count) { /* No change */ 620*5308Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_Z_OK), 621*5308Sab196087 strsec->sec_shndx, strsec->sec_name, ndx); 622*5308Sab196087 return (ELFEDIT_CMDRET_NONE); 623*5308Sab196087 } 624*5308Sab196087 625*5308Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_Z_CHG), 626*5308Sab196087 strsec->sec_shndx, strsec->sec_name, ndx, count); 627*5308Sab196087 bzero(oldstr, count); 628*5308Sab196087 629*5308Sab196087 return (ELFEDIT_CMDRET_MOD); 630*5308Sab196087 } 631*5308Sab196087 632*5308Sab196087 633*5308Sab196087 /* 634*5308Sab196087 * Common body for the str: module commands. 635*5308Sab196087 * 636*5308Sab196087 * entry: 637*5308Sab196087 * cmd - One of the STR_CMD_T_* constants listed above, specifying 638*5308Sab196087 * which command to implement. 639*5308Sab196087 * obj_state, argc, argv - Standard command arguments 640*5308Sab196087 */ 641*5308Sab196087 static elfedit_cmdret_t 642*5308Sab196087 cmd_body(STR_CMD_T cmd, elfedit_obj_state_t *obj_state, 643*5308Sab196087 int argc, const char *argv[]) 644*5308Sab196087 { 645*5308Sab196087 ARGSTATE argstate; 646*5308Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 647*5308Sab196087 int print_only; 648*5308Sab196087 649*5308Sab196087 process_args(obj_state, argc, argv, cmd, &argstate, &print_only); 650*5308Sab196087 651*5308Sab196087 /* 652*5308Sab196087 * If this call call does not change data, display the current 653*5308Sab196087 * value(s) and return. 654*5308Sab196087 */ 655*5308Sab196087 if (print_only) { 656*5308Sab196087 print_strtab(0, &argstate); 657*5308Sab196087 return (ELFEDIT_CMDRET_NONE); 658*5308Sab196087 } 659*5308Sab196087 660*5308Sab196087 switch (cmd) { 661*5308Sab196087 /* NOTE: STR_CMD_T_DUMP can't get here --- it's always print_only */ 662*5308Sab196087 663*5308Sab196087 case STR_CMD_T_SET: 664*5308Sab196087 ret = cmd_body_set(&argstate); 665*5308Sab196087 break; 666*5308Sab196087 667*5308Sab196087 case STR_CMD_T_ADD: 668*5308Sab196087 argstate.str.ndx = elfedit_strtab_insert(obj_state, 669*5308Sab196087 argstate.str.sec, argstate.dyn.sec, argstate.argv[0]); 670*5308Sab196087 break; 671*5308Sab196087 672*5308Sab196087 case STR_CMD_T_ZERO: 673*5308Sab196087 ret = cmd_body_zero(&argstate); 674*5308Sab196087 break; 675*5308Sab196087 } 676*5308Sab196087 677*5308Sab196087 /* 678*5308Sab196087 * If we modified the strtab section, tell libelf. 679*5308Sab196087 */ 680*5308Sab196087 if (ret == ELFEDIT_CMDRET_MOD) 681*5308Sab196087 elfedit_modified_data(argstate.str.sec); 682*5308Sab196087 683*5308Sab196087 /* Do autoprint */ 684*5308Sab196087 print_strtab(1, &argstate); 685*5308Sab196087 686*5308Sab196087 return (ret); 687*5308Sab196087 } 688*5308Sab196087 689*5308Sab196087 690*5308Sab196087 691*5308Sab196087 692*5308Sab196087 /* 693*5308Sab196087 * Command completion functions for the various commands 694*5308Sab196087 */ 695*5308Sab196087 696*5308Sab196087 static void 697*5308Sab196087 add_shtyp_match(Word sh_type, void *cpldata) 698*5308Sab196087 { 699*5308Sab196087 char buf[128]; 700*5308Sab196087 const char *s; 701*5308Sab196087 char *s2; 702*5308Sab196087 703*5308Sab196087 s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_SHT, sh_type, 0); 704*5308Sab196087 elfedit_cpl_match(cpldata, s, 1); 705*5308Sab196087 706*5308Sab196087 /* 707*5308Sab196087 * To get the informal tag names that are lowercase 708*5308Sab196087 * and lack the leading SHT_, we copy the string we 709*5308Sab196087 * have into a buffer and process it. 710*5308Sab196087 */ 711*5308Sab196087 if (strlen(s) < 4) 712*5308Sab196087 return; 713*5308Sab196087 (void) strlcpy(buf, s + 4, sizeof (buf)); 714*5308Sab196087 for (s2 = buf; *s2 != '\0'; s2++) 715*5308Sab196087 if (isupper(*s2)) 716*5308Sab196087 *s2 = tolower(*s2); 717*5308Sab196087 elfedit_cpl_match(cpldata, buf, 1); 718*5308Sab196087 } 719*5308Sab196087 720*5308Sab196087 /* 721*5308Sab196087 * Handle filling in the values for -shnam, -shndx, and -shtyp options. 722*5308Sab196087 */ 723*5308Sab196087 /*ARGSUSED*/ 724*5308Sab196087 static void 725*5308Sab196087 cpl_sh_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 726*5308Sab196087 const char *argv[], int num_opt) 727*5308Sab196087 { 728*5308Sab196087 enum { NAME, INDEX, TYPE } op; 729*5308Sab196087 elfedit_section_t *sec; 730*5308Sab196087 Word ndx; 731*5308Sab196087 732*5308Sab196087 if ((argc != num_opt) || (argc < 2)) 733*5308Sab196087 return; 734*5308Sab196087 735*5308Sab196087 if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) { 736*5308Sab196087 op = NAME; 737*5308Sab196087 } else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) { 738*5308Sab196087 op = INDEX; 739*5308Sab196087 740*5308Sab196087 } else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) { 741*5308Sab196087 op = TYPE; 742*5308Sab196087 743*5308Sab196087 if (obj_state == NULL) { /* No object available */ 744*5308Sab196087 elfedit_atoui_sym_t *atoui_sym; 745*5308Sab196087 746*5308Sab196087 atoui_sym = elfedit_const_to_atoui(ELFEDIT_CONST_SHT); 747*5308Sab196087 for (; atoui_sym->sym_name != NULL; atoui_sym++) 748*5308Sab196087 if (shtype_to_strtab(atoui_sym->sym_value) != 749*5308Sab196087 SHTOSTR_NONE) 750*5308Sab196087 elfedit_cpl_match(cpldata, 751*5308Sab196087 atoui_sym->sym_name, 1); 752*5308Sab196087 } 753*5308Sab196087 } else { 754*5308Sab196087 return; 755*5308Sab196087 } 756*5308Sab196087 757*5308Sab196087 if (obj_state == NULL) /* No object available */ 758*5308Sab196087 return; 759*5308Sab196087 760*5308Sab196087 /* 761*5308Sab196087 * Loop over the section headers and supply command completion 762*5308Sab196087 * for the items in the file that can yield a string table. 763*5308Sab196087 */ 764*5308Sab196087 sec = obj_state->os_secarr; 765*5308Sab196087 for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++) { 766*5308Sab196087 Word sh_type = sec->sec_shdr->sh_type; 767*5308Sab196087 768*5308Sab196087 if (shtype_to_strtab(sh_type) == SHTOSTR_NONE) 769*5308Sab196087 continue; 770*5308Sab196087 771*5308Sab196087 switch (op) { 772*5308Sab196087 case NAME: 773*5308Sab196087 elfedit_cpl_match(cpldata, sec->sec_name, 0); 774*5308Sab196087 break; 775*5308Sab196087 case INDEX: 776*5308Sab196087 { 777*5308Sab196087 char index[MAXNDXSIZE]; 778*5308Sab196087 779*5308Sab196087 (void) snprintf(index, sizeof (index), 780*5308Sab196087 MSG_ORIG(MSG_FMT_WORDVAL), 781*5308Sab196087 sec->sec_shndx); 782*5308Sab196087 elfedit_cpl_match(cpldata, index, 1); 783*5308Sab196087 } 784*5308Sab196087 break; 785*5308Sab196087 case TYPE: 786*5308Sab196087 add_shtyp_match(sh_type, cpldata); 787*5308Sab196087 break; 788*5308Sab196087 } 789*5308Sab196087 } 790*5308Sab196087 } 791*5308Sab196087 792*5308Sab196087 793*5308Sab196087 /* 794*5308Sab196087 * Most of the commands accept an -shXXX option for the string table 795*5308Sab196087 * and a string first argument. This routine examines which argument 796*5308Sab196087 * is being processed, and supplies completion for these items. 797*5308Sab196087 */ 798*5308Sab196087 static void 799*5308Sab196087 cpl_sec_str(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 800*5308Sab196087 const char *argv[], int num_opt) 801*5308Sab196087 { 802*5308Sab196087 const char *str, *limit; 803*5308Sab196087 elfedit_section_t *sec; 804*5308Sab196087 Word strtab_ndx; 805*5308Sab196087 Word ndx; 806*5308Sab196087 807*5308Sab196087 /* Handle -shXXX options */ 808*5308Sab196087 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 809*5308Sab196087 810*5308Sab196087 /* Without object state, there's no data to work from */ 811*5308Sab196087 if (obj_state == NULL) 812*5308Sab196087 return; 813*5308Sab196087 814*5308Sab196087 /* If not first plain arg, return */ 815*5308Sab196087 if (argc != (num_opt + 1)) 816*5308Sab196087 return; 817*5308Sab196087 818*5308Sab196087 /* 819*5308Sab196087 * Look at the options, looking for two things: 820*5308Sab196087 * 1) A -shXXX option specifying a section. If so, turn that 821*5308Sab196087 * into a section index if possible. 822*5308Sab196087 * 2) Was -strndx used? If so, we are looking at an integer 823*5308Sab196087 * value and have nothing to complete. 824*5308Sab196087 */ 825*5308Sab196087 strtab_ndx = obj_state->os_ehdr->e_shstrndx; 826*5308Sab196087 for (ndx = 0; ndx < num_opt; ndx++) { 827*5308Sab196087 if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_STRNDX)) == 0) 828*5308Sab196087 return; 829*5308Sab196087 830*5308Sab196087 if ((ndx+1) < num_opt) { 831*5308Sab196087 if (strcmp(argv[ndx], 832*5308Sab196087 MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) { 833*5308Sab196087 Word i; 834*5308Sab196087 835*5308Sab196087 for (i = 1; i < obj_state->os_shnum; i++) 836*5308Sab196087 if (strcmp(obj_state->os_secarr[i]. 837*5308Sab196087 sec_name, argv[ndx+1]) == 0) { 838*5308Sab196087 strtab_ndx = i; 839*5308Sab196087 break; 840*5308Sab196087 } 841*5308Sab196087 } else if (strcmp(argv[ndx], 842*5308Sab196087 MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) { 843*5308Sab196087 elfedit_atoui_t val; 844*5308Sab196087 845*5308Sab196087 if (elfedit_atoui2(argv[ndx+1], NULL, 846*5308Sab196087 &val) != 0) 847*5308Sab196087 strtab_ndx = val; 848*5308Sab196087 } else if (strcmp(argv[ndx], 849*5308Sab196087 MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) { 850*5308Sab196087 elfedit_atoui_t sh_type; 851*5308Sab196087 Word i; 852*5308Sab196087 853*5308Sab196087 if (elfedit_atoconst2(argv[ndx+1], 854*5308Sab196087 ELFEDIT_CONST_SHT, &sh_type) == 0) 855*5308Sab196087 continue; 856*5308Sab196087 for (i = 1; i < obj_state->os_shnum; i++) 857*5308Sab196087 if (obj_state->os_secarr[i].sec_shdr-> 858*5308Sab196087 sh_type == sh_type) { 859*5308Sab196087 strtab_ndx = i; 860*5308Sab196087 break; 861*5308Sab196087 } 862*5308Sab196087 } 863*5308Sab196087 } 864*5308Sab196087 } 865*5308Sab196087 866*5308Sab196087 /* 867*5308Sab196087 * Locate and validate the string table. In the case where 868*5308Sab196087 * a non-string table section is given that references a string 869*5308Sab196087 * table, we will use the referenced table. 870*5308Sab196087 */ 871*5308Sab196087 strtab_ndx = shndx_to_strtab(obj_state, strtab_ndx); 872*5308Sab196087 if ((strtab_ndx >= obj_state->os_shnum) || 873*5308Sab196087 (obj_state->os_secarr[strtab_ndx].sec_shdr->sh_type != SHT_STRTAB)) 874*5308Sab196087 return; 875*5308Sab196087 sec = &obj_state->os_secarr[strtab_ndx]; 876*5308Sab196087 877*5308Sab196087 str = sec->sec_data->d_buf; 878*5308Sab196087 limit = str + sec->sec_data->d_size; 879*5308Sab196087 while (str < limit) { 880*5308Sab196087 if (*str != '\0') 881*5308Sab196087 elfedit_cpl_match(cpldata, str, 0); 882*5308Sab196087 str += strlen(str) + 1; 883*5308Sab196087 } 884*5308Sab196087 } 885*5308Sab196087 886*5308Sab196087 887*5308Sab196087 888*5308Sab196087 /* 889*5308Sab196087 * Implementation functions for the commands 890*5308Sab196087 */ 891*5308Sab196087 static elfedit_cmdret_t 892*5308Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 893*5308Sab196087 { 894*5308Sab196087 return (cmd_body(STR_CMD_T_DUMP, obj_state, argc, argv)); 895*5308Sab196087 } 896*5308Sab196087 897*5308Sab196087 static elfedit_cmdret_t 898*5308Sab196087 cmd_set(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 899*5308Sab196087 { 900*5308Sab196087 return (cmd_body(STR_CMD_T_SET, obj_state, argc, argv)); 901*5308Sab196087 } 902*5308Sab196087 903*5308Sab196087 static elfedit_cmdret_t 904*5308Sab196087 cmd_add(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 905*5308Sab196087 { 906*5308Sab196087 return (cmd_body(STR_CMD_T_ADD, obj_state, argc, argv)); 907*5308Sab196087 } 908*5308Sab196087 909*5308Sab196087 static elfedit_cmdret_t 910*5308Sab196087 cmd_zero(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 911*5308Sab196087 { 912*5308Sab196087 return (cmd_body(STR_CMD_T_ZERO, obj_state, argc, argv)); 913*5308Sab196087 } 914*5308Sab196087 915*5308Sab196087 916*5308Sab196087 917*5308Sab196087 /*ARGSUSED*/ 918*5308Sab196087 elfedit_module_t * 919*5308Sab196087 elfedit_init(elfedit_module_version_t version) 920*5308Sab196087 { 921*5308Sab196087 /* str:dump */ 922*5308Sab196087 static const char *name_dump[] = { 923*5308Sab196087 MSG_ORIG(MSG_CMD_DUMP), 924*5308Sab196087 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 925*5308Sab196087 NULL 926*5308Sab196087 }; 927*5308Sab196087 static elfedit_cmd_optarg_t opt_dump[] = { 928*5308Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 929*5308Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 930*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 931*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 932*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 933*5308Sab196087 STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP }, 934*5308Sab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0 }, 935*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 936*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 937*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 938*5308Sab196087 STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP }, 939*5308Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 }, 940*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 941*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 942*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 943*5308Sab196087 STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX }, 944*5308Sab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 }, 945*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_STRNDX), 946*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_STRNDX) */ 947*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_STRNDX), 0, 948*5308Sab196087 STR_OPT_F_STRNDX, 0 }, 949*5308Sab196087 { NULL } 950*5308Sab196087 }; 951*5308Sab196087 static elfedit_cmd_optarg_t arg_dump[] = { 952*5308Sab196087 { MSG_ORIG(MSG_STR_STRING), 953*5308Sab196087 /* MSG_INTL(MSG_A1_STRING) */ 954*5308Sab196087 ELFEDIT_I18NHDL(MSG_A1_STRING), 955*5308Sab196087 ELFEDIT_CMDOA_F_OPT }, 956*5308Sab196087 { NULL } 957*5308Sab196087 }; 958*5308Sab196087 959*5308Sab196087 /* str:set */ 960*5308Sab196087 static const char *name_set[] = { 961*5308Sab196087 MSG_ORIG(MSG_CMD_SET), NULL }; 962*5308Sab196087 static elfedit_cmd_optarg_t opt_set[] = { 963*5308Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 964*5308Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 965*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_NOTERM), 966*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_NOTERM) */ 967*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_NOTERM), 0, 968*5308Sab196087 STR_OPT_F_NOTERM, 0 }, 969*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 970*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 971*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 972*5308Sab196087 STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP }, 973*5308Sab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0 }, 974*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 975*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 976*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 977*5308Sab196087 STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP }, 978*5308Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 }, 979*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 980*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 981*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 982*5308Sab196087 STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX }, 983*5308Sab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 }, 984*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_STRNDX), 985*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_STRNDX) */ 986*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_STRNDX), 0, 987*5308Sab196087 STR_OPT_F_STRNDX, 0 }, 988*5308Sab196087 { NULL } 989*5308Sab196087 }; 990*5308Sab196087 static elfedit_cmd_optarg_t arg_set[] = { 991*5308Sab196087 { MSG_ORIG(MSG_STR_STRING), 992*5308Sab196087 /* MSG_INTL(MSG_A1_STRING) */ 993*5308Sab196087 ELFEDIT_I18NHDL(MSG_A1_STRING), 994*5308Sab196087 0 }, 995*5308Sab196087 { MSG_ORIG(MSG_STR_NEWSTRING), 996*5308Sab196087 /* MSG_INTL(MSG_A2_NEWSTRING) */ 997*5308Sab196087 ELFEDIT_I18NHDL(MSG_A2_NEWSTRING), 998*5308Sab196087 ELFEDIT_CMDOA_F_OPT }, 999*5308Sab196087 { NULL } 1000*5308Sab196087 }; 1001*5308Sab196087 1002*5308Sab196087 /* str:add */ 1003*5308Sab196087 static const char *name_add[] = { 1004*5308Sab196087 MSG_ORIG(MSG_CMD_ADD), NULL }; 1005*5308Sab196087 static elfedit_cmd_optarg_t opt_add[] = { 1006*5308Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 1007*5308Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1008*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 1009*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 1010*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 1011*5308Sab196087 STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP }, 1012*5308Sab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0 }, 1013*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1014*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1015*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 1016*5308Sab196087 STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP }, 1017*5308Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 }, 1018*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1019*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1020*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 1021*5308Sab196087 STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX }, 1022*5308Sab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 }, 1023*5308Sab196087 { NULL } 1024*5308Sab196087 }; 1025*5308Sab196087 static elfedit_cmd_optarg_t arg_add[] = { 1026*5308Sab196087 { MSG_ORIG(MSG_STR_NEWSTRING), 1027*5308Sab196087 /* MSG_INTL(MSG_A1_NEWSTRING) */ 1028*5308Sab196087 ELFEDIT_I18NHDL(MSG_A1_NEWSTRING), 1029*5308Sab196087 0 }, 1030*5308Sab196087 { NULL } 1031*5308Sab196087 }; 1032*5308Sab196087 1033*5308Sab196087 /* str:zero */ 1034*5308Sab196087 static const char *name_zero[] = { 1035*5308Sab196087 MSG_ORIG(MSG_CMD_ZERO), NULL }; 1036*5308Sab196087 static elfedit_cmd_optarg_t opt_zero[] = { 1037*5308Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 1038*5308Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1039*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 1040*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 1041*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 1042*5308Sab196087 STR_OPT_F_SHNAME, STR_OPT_F_SHNDX | STR_OPT_F_SHTYP }, 1043*5308Sab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0 }, 1044*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1045*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1046*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 1047*5308Sab196087 STR_OPT_F_SHNDX, STR_OPT_F_SHNAME | STR_OPT_F_SHTYP }, 1048*5308Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 }, 1049*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1050*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1051*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 1052*5308Sab196087 STR_OPT_F_SHTYP, STR_OPT_F_SHNAME | STR_OPT_F_SHNDX }, 1053*5308Sab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 }, 1054*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_STRNDX), 1055*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_STRNDX) */ 1056*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_STRNDX), 0, 1057*5308Sab196087 STR_OPT_F_STRNDX, 0 }, 1058*5308Sab196087 { MSG_ORIG(MSG_STR_MINUS_END), 1059*5308Sab196087 /* MSG_INTL(MSG_OPTDESC_END) */ 1060*5308Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_END), 0, 1061*5308Sab196087 STR_OPT_F_END, 0 }, 1062*5308Sab196087 { NULL } 1063*5308Sab196087 }; 1064*5308Sab196087 static elfedit_cmd_optarg_t arg_zero[] = { 1065*5308Sab196087 { MSG_ORIG(MSG_STR_STRING), 1066*5308Sab196087 /* MSG_INTL(MSG_A1_STRING) */ 1067*5308Sab196087 ELFEDIT_I18NHDL(MSG_A1_STRING), 1068*5308Sab196087 0 }, 1069*5308Sab196087 { MSG_ORIG(MSG_STR_COUNT), 1070*5308Sab196087 /* MSG_INTL(MSG_A2_COUNT) */ 1071*5308Sab196087 ELFEDIT_I18NHDL(MSG_A2_COUNT), 1072*5308Sab196087 ELFEDIT_CMDOA_F_OPT }, 1073*5308Sab196087 { NULL } 1074*5308Sab196087 }; 1075*5308Sab196087 1076*5308Sab196087 1077*5308Sab196087 static elfedit_cmd_t cmds[] = { 1078*5308Sab196087 /* str:dump */ 1079*5308Sab196087 { cmd_dump, cpl_sec_str, name_dump, 1080*5308Sab196087 /* MSG_INTL(MSG_DESC_DUMP) */ 1081*5308Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 1082*5308Sab196087 /* MSG_INTL(MSG_HELP_DUMP) */ 1083*5308Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 1084*5308Sab196087 opt_dump, arg_dump }, 1085*5308Sab196087 1086*5308Sab196087 /* str:set */ 1087*5308Sab196087 { cmd_set, cpl_sec_str, name_set, 1088*5308Sab196087 /* MSG_INTL(MSG_DESC_SET) */ 1089*5308Sab196087 ELFEDIT_I18NHDL(MSG_DESC_SET), 1090*5308Sab196087 /* MSG_INTL(MSG_HELP_SET) */ 1091*5308Sab196087 ELFEDIT_I18NHDL(MSG_HELP_SET), 1092*5308Sab196087 opt_set, arg_set }, 1093*5308Sab196087 1094*5308Sab196087 /* str:add */ 1095*5308Sab196087 { cmd_add, cpl_sh_opt, name_add, 1096*5308Sab196087 /* MSG_INTL(MSG_DESC_ADD) */ 1097*5308Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ADD), 1098*5308Sab196087 /* MSG_INTL(MSG_HELP_ADD) */ 1099*5308Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ADD), 1100*5308Sab196087 opt_add, arg_add }, 1101*5308Sab196087 1102*5308Sab196087 /* str:zero */ 1103*5308Sab196087 { cmd_zero, cpl_sec_str, name_zero, 1104*5308Sab196087 /* MSG_INTL(MSG_DESC_ZERO) */ 1105*5308Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ZERO), 1106*5308Sab196087 /* MSG_INTL(MSG_HELP_ZERO) */ 1107*5308Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ZERO), 1108*5308Sab196087 opt_zero, arg_zero }, 1109*5308Sab196087 1110*5308Sab196087 { NULL } 1111*5308Sab196087 }; 1112*5308Sab196087 1113*5308Sab196087 static elfedit_module_t module = { 1114*5308Sab196087 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 1115*5308Sab196087 /* MSG_INTL(MSG_MOD_DESC) */ 1116*5308Sab196087 ELFEDIT_I18NHDL(MSG_MOD_DESC), 1117*5308Sab196087 cmds, mod_i18nhdl_to_str }; 1118*5308Sab196087 1119*5308Sab196087 return (&module); 1120*5308Sab196087 } 1121