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