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