1*5088Sab196087 /* 2*5088Sab196087 * CDDL HEADER START 3*5088Sab196087 * 4*5088Sab196087 * The contents of this file are subject to the terms of the 5*5088Sab196087 * Common Development and Distribution License (the "License"). 6*5088Sab196087 * You may not use this file except in compliance with the License. 7*5088Sab196087 * 8*5088Sab196087 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5088Sab196087 * or http://www.opensolaris.org/os/licensing. 10*5088Sab196087 * See the License for the specific language governing permissions 11*5088Sab196087 * and limitations under the License. 12*5088Sab196087 * 13*5088Sab196087 * When distributing Covered Code, include this CDDL HEADER in each 14*5088Sab196087 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5088Sab196087 * If applicable, add the following below this CDDL HEADER, with the 16*5088Sab196087 * fields enclosed by brackets "[]" replaced with your own identifying 17*5088Sab196087 * information: Portions Copyright [yyyy] [name of copyright owner] 18*5088Sab196087 * 19*5088Sab196087 * CDDL HEADER END 20*5088Sab196087 */ 21*5088Sab196087 22*5088Sab196087 /* 23*5088Sab196087 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*5088Sab196087 * Use is subject to license terms. 25*5088Sab196087 */ 26*5088Sab196087 #pragma ident "%Z%%M% %I% %E% SMI" 27*5088Sab196087 28*5088Sab196087 #include <stdio.h> 29*5088Sab196087 #include <unistd.h> 30*5088Sab196087 #include <machdep.h> 31*5088Sab196087 #include <elfedit.h> 32*5088Sab196087 #include <strings.h> 33*5088Sab196087 #include <debug.h> 34*5088Sab196087 #include <conv.h> 35*5088Sab196087 #include <syminfo_msg.h> 36*5088Sab196087 37*5088Sab196087 38*5088Sab196087 39*5088Sab196087 /* 40*5088Sab196087 * This module uses shared code for several of the commands. 41*5088Sab196087 * It is sometimes necessary to know which specific command 42*5088Sab196087 * is active. 43*5088Sab196087 */ 44*5088Sab196087 typedef enum { 45*5088Sab196087 SYMINFO_CMD_T_DUMP = 0, /* syminfo:dump */ 46*5088Sab196087 47*5088Sab196087 SYMINFO_CMD_T_SI_BOUNDTO = 1, /* syminfo:si_boundto */ 48*5088Sab196087 SYMINFO_CMD_T_SI_FLAGS = 2 /* syminfo:si_boundto */ 49*5088Sab196087 } SYMINFO_CMD_T; 50*5088Sab196087 51*5088Sab196087 52*5088Sab196087 53*5088Sab196087 #ifndef _ELF64 54*5088Sab196087 /* 55*5088Sab196087 * We supply this function for the msg module. Only one copy is needed. 56*5088Sab196087 */ 57*5088Sab196087 const char * 58*5088Sab196087 _syminfo_msg(Msg mid) 59*5088Sab196087 { 60*5088Sab196087 return (gettext(MSG_ORIG(mid))); 61*5088Sab196087 } 62*5088Sab196087 63*5088Sab196087 #endif 64*5088Sab196087 65*5088Sab196087 66*5088Sab196087 67*5088Sab196087 /* 68*5088Sab196087 * This function is supplied to elfedit through our elfedit_module_t 69*5088Sab196087 * definition. It translates the opaque elfedit_i18nhdl_t handles 70*5088Sab196087 * in our module interface into the actual strings for elfedit to 71*5088Sab196087 * use. 72*5088Sab196087 * 73*5088Sab196087 * note: 74*5088Sab196087 * This module uses Msg codes for its i18n handle type. 75*5088Sab196087 * So the translation is simply to use MSG_INTL() to turn 76*5088Sab196087 * it into a string and return it. 77*5088Sab196087 */ 78*5088Sab196087 static const char * 79*5088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 80*5088Sab196087 { 81*5088Sab196087 Msg msg = (Msg)hdl; 82*5088Sab196087 83*5088Sab196087 return (MSG_INTL(msg)); 84*5088Sab196087 } 85*5088Sab196087 86*5088Sab196087 87*5088Sab196087 88*5088Sab196087 /* 89*5088Sab196087 * The sym_opt_t enum specifies a bit value for every optional 90*5088Sab196087 * argument allowed by a command in this module. 91*5088Sab196087 */ 92*5088Sab196087 typedef enum { 93*5088Sab196087 SYMINFO_OPT_F_AND = 1, /* -and: AND (&) values to dest */ 94*5088Sab196087 SYMINFO_OPT_F_CMP = 2, /* -cmp: Complement (~) values */ 95*5088Sab196087 SYMINFO_OPT_F_NEEDED = 4, /* -needed: arg is name of object to */ 96*5088Sab196087 /* be referenced via DT_NEEDED */ 97*5088Sab196087 /* dynamic entry */ 98*5088Sab196087 SYMINFO_OPT_F_OR = 8, /* -or: OR (|) values to dest */ 99*5088Sab196087 SYMINFO_OPT_F_SYMNDX = 16 /* -symndx: Sym specified by index */ 100*5088Sab196087 } syminfo_opt_t; 101*5088Sab196087 102*5088Sab196087 103*5088Sab196087 /* 104*5088Sab196087 * A variable of type ARGSTATE is used by each command to maintain 105*5088Sab196087 * information about the syminfo section being used, as and for any 106*5088Sab196087 * auxiliary sections that are related to it. This helps us to ensure 107*5088Sab196087 * that we only fetch each section a single time: 108*5088Sab196087 * - More efficient 109*5088Sab196087 * - Prevents multiple ELFEDIT_MSG_DEBUG messages from 110*5088Sab196087 * being produced for a given section. 111*5088Sab196087 */ 112*5088Sab196087 typedef struct { 113*5088Sab196087 elfedit_obj_state_t *obj_state; 114*5088Sab196087 syminfo_opt_t optmask; /* Mask of options used */ 115*5088Sab196087 int argc; /* # of plain arguments */ 116*5088Sab196087 const char **argv; /* Plain arguments */ 117*5088Sab196087 struct { /* Syminfo */ 118*5088Sab196087 elfedit_section_t *sec; 119*5088Sab196087 Syminfo *data; 120*5088Sab196087 Word n; 121*5088Sab196087 } syminfo; 122*5088Sab196087 struct { /* Symbol table */ 123*5088Sab196087 elfedit_section_t *sec; 124*5088Sab196087 Sym *data; 125*5088Sab196087 Word n; 126*5088Sab196087 } sym; 127*5088Sab196087 struct { /* String table */ 128*5088Sab196087 elfedit_section_t *sec; 129*5088Sab196087 } str; 130*5088Sab196087 struct { /* Dynamic section */ 131*5088Sab196087 elfedit_section_t *sec; 132*5088Sab196087 Dyn *data; 133*5088Sab196087 Word n; 134*5088Sab196087 } dynamic; 135*5088Sab196087 } ARGSTATE; 136*5088Sab196087 137*5088Sab196087 138*5088Sab196087 139*5088Sab196087 /* 140*5088Sab196087 * Standard argument processing for syminfo module 141*5088Sab196087 * 142*5088Sab196087 * entry 143*5088Sab196087 * obj_state, argc, argv - Standard command arguments 144*5088Sab196087 * optmask - Mask of allowed optional arguments. 145*5088Sab196087 * argstate - Address of ARGSTATE block to be initialized 146*5088Sab196087 * 147*5088Sab196087 * exit: 148*5088Sab196087 * On success, *argstate is initialized. On error, 149*5088Sab196087 * an error is issued and this routine does not return. 150*5088Sab196087 * 151*5088Sab196087 * note: 152*5088Sab196087 * Only the syminfo section is initially referenced by 153*5088Sab196087 * argstate. Use the argstate_add_XXX() routines below to 154*5088Sab196087 * access any other sections needed. 155*5088Sab196087 */ 156*5088Sab196087 static void 157*5088Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 158*5088Sab196087 SYMINFO_CMD_T cmd, ARGSTATE *argstate) 159*5088Sab196087 { 160*5088Sab196087 elfedit_getopt_state_t getopt_state; 161*5088Sab196087 elfedit_getopt_ret_t *getopt_ret; 162*5088Sab196087 163*5088Sab196087 bzero(argstate, sizeof (*argstate)); 164*5088Sab196087 argstate->obj_state = obj_state; 165*5088Sab196087 166*5088Sab196087 elfedit_getopt_init(&getopt_state, &argc, &argv); 167*5088Sab196087 168*5088Sab196087 /* Add each new option to the options mask */ 169*5088Sab196087 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) 170*5088Sab196087 argstate->optmask |= getopt_ret->gor_idmask; 171*5088Sab196087 172*5088Sab196087 /* 173*5088Sab196087 * Usage error if there are too many plain arguments. 174*5088Sab196087 * - syminfo:dump accepts a single argument 175*5088Sab196087 * - syminfo:si_boundto accepts 2 arguments 176*5088Sab196087 * - syminfo:si_flags accepts an unbounded number 177*5088Sab196087 */ 178*5088Sab196087 if (((cmd == SYMINFO_CMD_T_DUMP) && (argc > 1)) || 179*5088Sab196087 ((cmd == SYMINFO_CMD_T_SI_BOUNDTO) && (argc > 2))) 180*5088Sab196087 elfedit_command_usage(); 181*5088Sab196087 182*5088Sab196087 /* If there may be an arbitrary amount of output, use a pager */ 183*5088Sab196087 if (argc == 0) 184*5088Sab196087 elfedit_pager_init(); 185*5088Sab196087 186*5088Sab196087 /* Return the updated values of argc/argv */ 187*5088Sab196087 argstate->argc = argc; 188*5088Sab196087 argstate->argv = argv; 189*5088Sab196087 190*5088Sab196087 /* Locate the syminfo section */ 191*5088Sab196087 argstate->syminfo.sec = elfedit_sec_getsyminfo(obj_state, 192*5088Sab196087 &argstate->syminfo.data, &argstate->syminfo.n); 193*5088Sab196087 } 194*5088Sab196087 195*5088Sab196087 196*5088Sab196087 197*5088Sab196087 /* 198*5088Sab196087 * We maintain the state of the current syminfo table in a ARGSTATE 199*5088Sab196087 * structure. A syminfo is related to the dynamic symbol table, and 200*5088Sab196087 * can reference the dynamic section of the object. We don't look those 201*5088Sab196087 * things up unless we actually need them, both to be efficient, and 202*5088Sab196087 * to prevent duplicate ELFEDIT_MSG_DEBUG messages from being issued 203*5088Sab196087 * as they are located. Hence, process_args() is used to initialze the 204*5088Sab196087 * state block with just the syminfo section, and then one of the 205*5088Sab196087 * argstate_add_XXX() functions is used as needed to fetch the 206*5088Sab196087 * additional sections. 207*5088Sab196087 * 208*5088Sab196087 * entry: 209*5088Sab196087 * argstate - State block for current symbol table. 210*5088Sab196087 * 211*5088Sab196087 * exit: 212*5088Sab196087 * If the needed auxiliary section is not found, an error is 213*5088Sab196087 * issued and the argstate_add_XXX() routine does not return. 214*5088Sab196087 * Otherwise, the fields in argstate have been filled in, ready 215*5088Sab196087 * for use. 216*5088Sab196087 * 217*5088Sab196087 */ 218*5088Sab196087 static void 219*5088Sab196087 argstate_add_sym(ARGSTATE *argstate) 220*5088Sab196087 { 221*5088Sab196087 if (argstate->sym.sec != NULL) 222*5088Sab196087 return; 223*5088Sab196087 224*5088Sab196087 argstate->sym.sec = elfedit_sec_getsymtab(argstate->obj_state, 225*5088Sab196087 1, argstate->syminfo.sec->sec_shdr->sh_link, NULL, 226*5088Sab196087 &argstate->sym.data, &argstate->sym.n, NULL); 227*5088Sab196087 } 228*5088Sab196087 static void 229*5088Sab196087 argstate_add_str(ARGSTATE *argstate) 230*5088Sab196087 { 231*5088Sab196087 if (argstate->str.sec != NULL) 232*5088Sab196087 return; 233*5088Sab196087 234*5088Sab196087 argstate_add_sym(argstate); 235*5088Sab196087 argstate->str.sec = elfedit_sec_getstr(argstate->obj_state, 236*5088Sab196087 argstate->sym.sec->sec_shdr->sh_link); 237*5088Sab196087 } 238*5088Sab196087 static void 239*5088Sab196087 argstate_add_dynamic(ARGSTATE *argstate) 240*5088Sab196087 { 241*5088Sab196087 if (argstate->dynamic.sec != NULL) 242*5088Sab196087 return; 243*5088Sab196087 244*5088Sab196087 argstate->dynamic.sec = elfedit_sec_getdyn(argstate->obj_state, 245*5088Sab196087 &argstate->dynamic.data, &argstate->dynamic.n); 246*5088Sab196087 } 247*5088Sab196087 248*5088Sab196087 249*5088Sab196087 250*5088Sab196087 /* 251*5088Sab196087 * Display syminfo section entries in the style used by elfdump. 252*5088Sab196087 * 253*5088Sab196087 * entry: 254*5088Sab196087 * argstate - State block for current symbol table. 255*5088Sab196087 * ndx - Index of first symbol to display 256*5088Sab196087 * cnt - Number of symbols to display 257*5088Sab196087 */ 258*5088Sab196087 static void 259*5088Sab196087 dump_syminfo(ARGSTATE *argstate, Word ndx, Word cnt) 260*5088Sab196087 { 261*5088Sab196087 Syminfo *syminfo; 262*5088Sab196087 Sym *sym; 263*5088Sab196087 Dyn *dyn; 264*5088Sab196087 265*5088Sab196087 syminfo = argstate->syminfo.data + ndx; 266*5088Sab196087 267*5088Sab196087 argstate_add_sym(argstate); 268*5088Sab196087 sym = argstate->sym.data + ndx; 269*5088Sab196087 270*5088Sab196087 argstate_add_str(argstate); 271*5088Sab196087 272*5088Sab196087 argstate_add_dynamic(argstate); 273*5088Sab196087 dyn = argstate->dynamic.data; 274*5088Sab196087 275*5088Sab196087 /* 276*5088Sab196087 * Loop through the syminfo entries. 277*5088Sab196087 */ 278*5088Sab196087 Elf_syminfo_title(0); 279*5088Sab196087 280*5088Sab196087 for (; cnt-- > 0; ndx++, syminfo++, sym++) { 281*5088Sab196087 const char *needed = NULL, *name; 282*5088Sab196087 283*5088Sab196087 name = elfedit_offset_to_str(argstate->str.sec, 284*5088Sab196087 sym->st_name, ELFEDIT_MSG_ERR, 0); 285*5088Sab196087 286*5088Sab196087 if ((syminfo->si_boundto < SYMINFO_BT_LOWRESERVE) && 287*5088Sab196087 (syminfo->si_boundto < argstate->dynamic.n) && 288*5088Sab196087 ((dyn[syminfo->si_boundto].d_tag == DT_NEEDED) || 289*5088Sab196087 (dyn[syminfo->si_boundto].d_tag == DT_USED))) 290*5088Sab196087 needed = elfedit_offset_to_str(argstate->str.sec, 291*5088Sab196087 dyn[syminfo->si_boundto].d_un.d_val, 292*5088Sab196087 ELFEDIT_MSG_ERR, 0); 293*5088Sab196087 else 294*5088Sab196087 needed = MSG_ORIG(MSG_STR_EMPTY); 295*5088Sab196087 296*5088Sab196087 Elf_syminfo_entry(0, ndx, syminfo, name, needed); 297*5088Sab196087 } 298*5088Sab196087 } 299*5088Sab196087 300*5088Sab196087 301*5088Sab196087 302*5088Sab196087 /* 303*5088Sab196087 * Print syminfo values, taking the calling command, and output style 304*5088Sab196087 * into account. 305*5088Sab196087 * 306*5088Sab196087 * entry: 307*5088Sab196087 * cmd - SYMINFO_CMD_T_* value giving identify of caller 308*5088Sab196087 * autoprint - If True, output is only produced if the elfedit 309*5088Sab196087 * autoprint flag is set. If False, output is always produced. 310*5088Sab196087 * argstate - State block for current symbol table. 311*5088Sab196087 * ndx - Index of first symbol to display 312*5088Sab196087 * cnt - Number of symbols to display 313*5088Sab196087 */ 314*5088Sab196087 static void 315*5088Sab196087 print_syminfo(SYMINFO_CMD_T cmd, int autoprint, ARGSTATE *argstate, 316*5088Sab196087 Word ndx, Word cnt) 317*5088Sab196087 { 318*5088Sab196087 elfedit_outstyle_t outstyle; 319*5088Sab196087 Syminfo *syminfo; 320*5088Sab196087 321*5088Sab196087 if ((autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) || 322*5088Sab196087 (cnt == 0)) 323*5088Sab196087 return; 324*5088Sab196087 325*5088Sab196087 /* 326*5088Sab196087 * Pick an output style. syminfo:dump is required to use the default 327*5088Sab196087 * style. The other commands use the current output style. 328*5088Sab196087 */ 329*5088Sab196087 outstyle = (cmd == SYMINFO_CMD_T_DUMP) ? 330*5088Sab196087 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 331*5088Sab196087 332*5088Sab196087 /* 333*5088Sab196087 * If doing default output, use elfdump style where we 334*5088Sab196087 * show all symbol attributes. In this case, the command 335*5088Sab196087 * that called us doesn't matter 336*5088Sab196087 */ 337*5088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 338*5088Sab196087 dump_syminfo(argstate, ndx, cnt); 339*5088Sab196087 return; 340*5088Sab196087 } 341*5088Sab196087 342*5088Sab196087 syminfo = argstate->syminfo.data; 343*5088Sab196087 344*5088Sab196087 switch (cmd) { 345*5088Sab196087 case SYMINFO_CMD_T_SI_BOUNDTO: 346*5088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 347*5088Sab196087 /* Find the dynamic section and string table */ 348*5088Sab196087 argstate_add_dynamic(argstate); 349*5088Sab196087 argstate_add_str(argstate); 350*5088Sab196087 } 351*5088Sab196087 352*5088Sab196087 for (syminfo += ndx; cnt--; syminfo++) { 353*5088Sab196087 Half bndto = syminfo->si_boundto; 354*5088Sab196087 355*5088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 356*5088Sab196087 const char *str = NULL; 357*5088Sab196087 358*5088Sab196087 switch (bndto) { 359*5088Sab196087 case SYMINFO_BT_SELF: 360*5088Sab196087 str = elfedit_atoconst_value_to_str( 361*5088Sab196087 ELFEDIT_CONST_SYMINFO_BT, 362*5088Sab196087 SYMINFO_BT_SELF, 1); 363*5088Sab196087 break; 364*5088Sab196087 case SYMINFO_BT_PARENT: 365*5088Sab196087 str = elfedit_atoconst_value_to_str( 366*5088Sab196087 ELFEDIT_CONST_SYMINFO_BT, 367*5088Sab196087 SYMINFO_BT_PARENT, 1); 368*5088Sab196087 break; 369*5088Sab196087 case SYMINFO_BT_NONE: 370*5088Sab196087 str = elfedit_atoconst_value_to_str( 371*5088Sab196087 ELFEDIT_CONST_SYMINFO_BT, 372*5088Sab196087 SYMINFO_BT_NONE, 1); 373*5088Sab196087 break; 374*5088Sab196087 } 375*5088Sab196087 if ((str == NULL) && 376*5088Sab196087 (bndto < SYMINFO_BT_LOWRESERVE) && 377*5088Sab196087 (argstate->dynamic.sec != NULL) && 378*5088Sab196087 (bndto < argstate->dynamic.n) && 379*5088Sab196087 (argstate->dynamic.data[bndto].d_tag == 380*5088Sab196087 DT_NEEDED)) 381*5088Sab196087 str = elfedit_offset_to_str( 382*5088Sab196087 argstate->str.sec, 383*5088Sab196087 argstate->dynamic.data[bndto]. 384*5088Sab196087 d_un.d_val, ELFEDIT_MSG_ERR, 0); 385*5088Sab196087 386*5088Sab196087 if (str != NULL) { 387*5088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 388*5088Sab196087 str); 389*5088Sab196087 continue; 390*5088Sab196087 } 391*5088Sab196087 } 392*5088Sab196087 393*5088Sab196087 /* 394*5088Sab196087 * If we reach this point, we are either in numeric 395*5088Sab196087 * mode, or we were unable to find a string above. 396*5088Sab196087 * In either case, output as integer. 397*5088Sab196087 */ 398*5088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 399*5088Sab196087 EC_WORD(bndto)); 400*5088Sab196087 } 401*5088Sab196087 break; 402*5088Sab196087 403*5088Sab196087 case SYMINFO_CMD_T_SI_FLAGS: 404*5088Sab196087 for (syminfo += ndx; cnt--; syminfo++) { 405*5088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 406*5088Sab196087 Conv_syminfo_flags_buf_t buf; 407*5088Sab196087 408*5088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 409*5088Sab196087 conv_syminfo_flags(syminfo->si_flags, 410*5088Sab196087 CONV_FMT_NOBKT, &buf)); 411*5088Sab196087 } else { 412*5088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_HEXNUMNL), 413*5088Sab196087 EC_WORD(syminfo->si_flags)); 414*5088Sab196087 } 415*5088Sab196087 } 416*5088Sab196087 break; 417*5088Sab196087 } 418*5088Sab196087 } 419*5088Sab196087 420*5088Sab196087 421*5088Sab196087 /* 422*5088Sab196087 * Convert the given argument string into a symbol table index. 423*5088Sab196087 * 424*5088Sab196087 * entry: 425*5088Sab196087 * argstate - State block for current symbol table. 426*5088Sab196087 * arg - String containing symbol index argument. 427*5088Sab196087 * 428*5088Sab196087 * exit: 429*5088Sab196087 * On success, returns the symbol index. On failure, an error 430*5088Sab196087 * is issued and this routine does not return. 431*5088Sab196087 */ 432*5088Sab196087 static Word 433*5088Sab196087 arg_to_symndx(ARGSTATE *argstate, const char *arg) 434*5088Sab196087 { 435*5088Sab196087 Word symndx; 436*5088Sab196087 437*5088Sab196087 /* 438*5088Sab196087 * If the -symndx option was specified, arg is an index 439*5088Sab196087 * into the symbol table. 440*5088Sab196087 */ 441*5088Sab196087 if (argstate->optmask & SYMINFO_OPT_F_SYMNDX) 442*5088Sab196087 return (elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_SYM), 443*5088Sab196087 0, argstate->syminfo.n - 1, NULL)); 444*5088Sab196087 445*5088Sab196087 /* 446*5088Sab196087 * arg is a symbol name. Return the index of the first symbol 447*5088Sab196087 * that matches 448*5088Sab196087 */ 449*5088Sab196087 argstate_add_sym(argstate); 450*5088Sab196087 argstate_add_str(argstate); 451*5088Sab196087 452*5088Sab196087 (void) elfedit_name_to_symndx(argstate->sym.sec, 453*5088Sab196087 argstate->str.sec, arg, ELFEDIT_MSG_ERR, &symndx); 454*5088Sab196087 455*5088Sab196087 return (symndx); 456*5088Sab196087 } 457*5088Sab196087 458*5088Sab196087 459*5088Sab196087 /* 460*5088Sab196087 * Given a string argument representing an object, return the index of 461*5088Sab196087 * the dynamic section that should be used for the si_boundto value. 462*5088Sab196087 */ 463*5088Sab196087 static Half 464*5088Sab196087 needed_to_boundto(ARGSTATE *argstate, const char *arg) 465*5088Sab196087 { 466*5088Sab196087 Conv_inv_buf_t inv_buf; 467*5088Sab196087 elfedit_dyn_elt_t strpad_elt; 468*5088Sab196087 elfedit_dyn_elt_t null_elt; 469*5088Sab196087 elfedit_section_t *dynsec; 470*5088Sab196087 Word null_cnt; 471*5088Sab196087 Dyn *dyn; 472*5088Sab196087 Word str_offset, ndx, numdyn; 473*5088Sab196087 int have_string; 474*5088Sab196087 475*5088Sab196087 argstate_add_str(argstate); 476*5088Sab196087 argstate_add_dynamic(argstate); 477*5088Sab196087 dynsec = argstate->dynamic.sec; 478*5088Sab196087 numdyn = argstate->dynamic.n; 479*5088Sab196087 480*5088Sab196087 /* Locate DT_SUNW_STRPAD element if present and locate the DT_NULLs */ 481*5088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 482*5088Sab196087 elfedit_dyn_elt_init(&null_elt); 483*5088Sab196087 null_cnt = 0; 484*5088Sab196087 strpad_elt.dn_dyn.d_un.d_val = 0; 485*5088Sab196087 dyn = argstate->dynamic.data; 486*5088Sab196087 for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 487*5088Sab196087 switch (dyn->d_tag) { 488*5088Sab196087 case DT_NULL: 489*5088Sab196087 /* Count all the nulls, remember the first one */ 490*5088Sab196087 null_cnt++; 491*5088Sab196087 if (!null_elt.dn_seen) 492*5088Sab196087 elfedit_dyn_elt_save(&null_elt, ndx, dyn); 493*5088Sab196087 break; 494*5088Sab196087 495*5088Sab196087 case DT_SUNW_STRPAD: 496*5088Sab196087 elfedit_dyn_elt_save(&strpad_elt, ndx, dyn); 497*5088Sab196087 break; 498*5088Sab196087 } 499*5088Sab196087 } 500*5088Sab196087 501*5088Sab196087 /* 502*5088Sab196087 * Look up the string in the string table and get its offset. If 503*5088Sab196087 * this succeeds, then it is possible that there is a DT_NEEDED 504*5088Sab196087 * dynamic entry that references it. 505*5088Sab196087 */ 506*5088Sab196087 have_string = elfedit_sec_findstr(argstate->str.sec, 507*5088Sab196087 strpad_elt.dn_dyn.d_un.d_val, arg, &str_offset) != 0; 508*5088Sab196087 if (have_string) { 509*5088Sab196087 dyn = argstate->dynamic.data; 510*5088Sab196087 for (ndx = 0; ndx < numdyn; dyn++, ndx++) { 511*5088Sab196087 if (((dyn->d_tag == DT_NEEDED) || 512*5088Sab196087 (dyn->d_tag == DT_USED)) && 513*5088Sab196087 (dyn->d_un.d_val == str_offset)) 514*5088Sab196087 goto done; 515*5088Sab196087 } 516*5088Sab196087 } 517*5088Sab196087 518*5088Sab196087 /* 519*5088Sab196087 * It doesn't already exist. We might be able to add a DT_NEEDED 520*5088Sab196087 * to the dynamic section if an extra DT_NULL is available. 521*5088Sab196087 * Otherwise, we have to fail here. 522*5088Sab196087 */ 523*5088Sab196087 if (null_cnt < 2) 524*5088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 525*5088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 526*5088Sab196087 527*5088Sab196087 /* 528*5088Sab196087 * If the string is not already in the string table, try to 529*5088Sab196087 * insert it. If it succeeds, we will convert the DT_NULL. 530*5088Sab196087 * Otherwise, an error will be issued and control will not 531*5088Sab196087 * return here. 532*5088Sab196087 */ 533*5088Sab196087 if (!have_string) 534*5088Sab196087 str_offset = elfedit_dynstr_insert(dynsec, 535*5088Sab196087 argstate->str.sec, &strpad_elt, arg); 536*5088Sab196087 537*5088Sab196087 /* Convert the extra DT_NULL */ 538*5088Sab196087 ndx = null_elt.dn_ndx; 539*5088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL), 540*5088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, EC_WORD(ndx), 541*5088Sab196087 conv_dyn_tag(DT_NEEDED, argstate->obj_state->os_ehdr->e_machine, 542*5088Sab196087 0, &inv_buf)); 543*5088Sab196087 dyn = argstate->dynamic.data + ndx; 544*5088Sab196087 dyn->d_tag = DT_NEEDED; 545*5088Sab196087 dyn->d_un.d_val = str_offset; 546*5088Sab196087 elfedit_modified_data(dynsec); 547*5088Sab196087 548*5088Sab196087 done: 549*5088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDNEEDED), 550*5088Sab196087 dynsec->sec_shndx, dynsec->sec_name, ndx, arg); 551*5088Sab196087 return (ndx); 552*5088Sab196087 } 553*5088Sab196087 554*5088Sab196087 /* 555*5088Sab196087 * Common body for the syminfo: module commands. These commands 556*5088Sab196087 * share a large amount of common behavior, so it is convenient 557*5088Sab196087 * to centralize things and use the cmd argument to handle the 558*5088Sab196087 * small differences. 559*5088Sab196087 * 560*5088Sab196087 * entry: 561*5088Sab196087 * cmd - One of the SYMINFO_CMD_T_* constants listed above, specifying 562*5088Sab196087 * which command to implement. 563*5088Sab196087 * obj_state, argc, argv - Standard command arguments 564*5088Sab196087 */ 565*5088Sab196087 static elfedit_cmdret_t 566*5088Sab196087 cmd_body(SYMINFO_CMD_T cmd, elfedit_obj_state_t *obj_state, 567*5088Sab196087 int argc, const char *argv[]) 568*5088Sab196087 { 569*5088Sab196087 ARGSTATE argstate; 570*5088Sab196087 Word ndx; 571*5088Sab196087 Syminfo *syminfo; 572*5088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 573*5088Sab196087 574*5088Sab196087 process_args(obj_state, argc, argv, cmd, &argstate); 575*5088Sab196087 576*5088Sab196087 /* If there are no arguments, dump the whole table and return */ 577*5088Sab196087 if (argstate.argc == 0) { 578*5088Sab196087 print_syminfo(cmd, 0, &argstate, 0, argstate.syminfo.n); 579*5088Sab196087 return (ELFEDIT_CMDRET_NONE); 580*5088Sab196087 } 581*5088Sab196087 582*5088Sab196087 /* The first argument is the symbol name/index */ 583*5088Sab196087 ndx = arg_to_symndx(&argstate, argstate.argv[0]); 584*5088Sab196087 585*5088Sab196087 /* If there is a single argument, display that item and return */ 586*5088Sab196087 if (argstate.argc == 1) { 587*5088Sab196087 print_syminfo(cmd, 0, &argstate, ndx, 1); 588*5088Sab196087 return (ELFEDIT_CMDRET_NONE); 589*5088Sab196087 } 590*5088Sab196087 591*5088Sab196087 syminfo = &argstate.syminfo.data[ndx]; 592*5088Sab196087 593*5088Sab196087 /* 594*5088Sab196087 * Syminfo [0] holds the value SYMINFO_CURRENT, as a versioning 595*5088Sab196087 * technique. You're not supposed to mess with it. 596*5088Sab196087 */ 597*5088Sab196087 if (ndx == 0) 598*5088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSYMINFO0), 599*5088Sab196087 EC_WORD(argstate.syminfo.sec->sec_shndx), 600*5088Sab196087 argstate.syminfo.sec->sec_name, EC_WORD(ndx)); 601*5088Sab196087 602*5088Sab196087 /* The second value supplies a new value for the item */ 603*5088Sab196087 switch (cmd) { 604*5088Sab196087 /* 605*5088Sab196087 * SYMINFO_CMD_T_DUMP can't get here: It never has more than 606*5088Sab196087 * one argument, and is handled above. 607*5088Sab196087 */ 608*5088Sab196087 609*5088Sab196087 case SYMINFO_CMD_T_SI_BOUNDTO: 610*5088Sab196087 { 611*5088Sab196087 const char *name = MSG_ORIG(MSG_CMD_SI_BOUNDTO); 612*5088Sab196087 Half boundto; 613*5088Sab196087 614*5088Sab196087 if (argstate.optmask & SYMINFO_OPT_F_NEEDED) 615*5088Sab196087 boundto = needed_to_boundto(&argstate, 616*5088Sab196087 argstate.argv[1]); 617*5088Sab196087 else 618*5088Sab196087 boundto = elfedit_atoconst_range( 619*5088Sab196087 argstate.argv[1], MSG_ORIG(MSG_STR_VALUE), 620*5088Sab196087 0, 0xffff, ELFEDIT_CONST_SYMINFO_BT); 621*5088Sab196087 622*5088Sab196087 if (syminfo->si_boundto == boundto) { 623*5088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 624*5088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), 625*5088Sab196087 argstate.syminfo.sec->sec_shndx, 626*5088Sab196087 argstate.syminfo.sec->sec_name, ndx, name, 627*5088Sab196087 syminfo->si_boundto); 628*5088Sab196087 } else { 629*5088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 630*5088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 631*5088Sab196087 argstate.syminfo.sec->sec_shndx, 632*5088Sab196087 argstate.syminfo.sec->sec_name, ndx, name, 633*5088Sab196087 syminfo->si_boundto, boundto); 634*5088Sab196087 ret = ELFEDIT_CMDRET_MOD; 635*5088Sab196087 syminfo->si_boundto = boundto; 636*5088Sab196087 } 637*5088Sab196087 } 638*5088Sab196087 break; 639*5088Sab196087 640*5088Sab196087 case SYMINFO_CMD_T_SI_FLAGS: 641*5088Sab196087 { 642*5088Sab196087 Conv_syminfo_flags_buf_t flags_buf1, flags_buf2; 643*5088Sab196087 const char *name = MSG_ORIG(MSG_CMD_SI_FLAGS); 644*5088Sab196087 Half flags = 0; 645*5088Sab196087 int i; 646*5088Sab196087 647*5088Sab196087 /* Collect the arguments */ 648*5088Sab196087 for (i = 1; i < argstate.argc; i++) 649*5088Sab196087 flags |= (Word) 650*5088Sab196087 elfedit_atoconst(argstate.argv[i], 651*5088Sab196087 ELFEDIT_CONST_SYMINFO_FLG); 652*5088Sab196087 653*5088Sab196087 /* Complement the value? */ 654*5088Sab196087 if (argstate.optmask & SYMINFO_OPT_F_CMP) 655*5088Sab196087 flags = ~flags; 656*5088Sab196087 657*5088Sab196087 /* Perform any requested bit operations */ 658*5088Sab196087 if (argstate.optmask & SYMINFO_OPT_F_AND) 659*5088Sab196087 flags &= syminfo->si_flags; 660*5088Sab196087 else if (argstate.optmask & SYMINFO_OPT_F_OR) 661*5088Sab196087 flags |= syminfo->si_flags; 662*5088Sab196087 663*5088Sab196087 /* Set the value */ 664*5088Sab196087 if (syminfo->si_flags == flags) { 665*5088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 666*5088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), 667*5088Sab196087 argstate.syminfo.sec->sec_shndx, 668*5088Sab196087 argstate.syminfo.sec->sec_name, ndx, name, 669*5088Sab196087 conv_syminfo_flags(syminfo->si_flags, 670*5088Sab196087 0, &flags_buf1)); 671*5088Sab196087 } else { 672*5088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 673*5088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 674*5088Sab196087 argstate.syminfo.sec->sec_shndx, 675*5088Sab196087 argstate.syminfo.sec->sec_name, ndx, name, 676*5088Sab196087 conv_syminfo_flags(syminfo->si_flags, 677*5088Sab196087 0, &flags_buf1), 678*5088Sab196087 conv_syminfo_flags(flags, 0, &flags_buf2)); 679*5088Sab196087 ret = ELFEDIT_CMDRET_MOD; 680*5088Sab196087 syminfo->si_flags = flags; 681*5088Sab196087 } 682*5088Sab196087 } 683*5088Sab196087 break; 684*5088Sab196087 } 685*5088Sab196087 686*5088Sab196087 /* 687*5088Sab196087 * If we modified the syminfo section, tell libelf. 688*5088Sab196087 */ 689*5088Sab196087 if (ret == ELFEDIT_CMDRET_MOD) 690*5088Sab196087 elfedit_modified_data(argstate.syminfo.sec); 691*5088Sab196087 692*5088Sab196087 /* Do autoprint */ 693*5088Sab196087 print_syminfo(cmd, 1, &argstate, ndx, 1); 694*5088Sab196087 695*5088Sab196087 return (ret); 696*5088Sab196087 } 697*5088Sab196087 698*5088Sab196087 699*5088Sab196087 700*5088Sab196087 701*5088Sab196087 /* 702*5088Sab196087 * Command completion functions for the various commands 703*5088Sab196087 */ 704*5088Sab196087 /*ARGSUSED*/ 705*5088Sab196087 static void 706*5088Sab196087 cpl_si_boundto(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 707*5088Sab196087 const char *argv[], int num_opt) 708*5088Sab196087 { 709*5088Sab196087 int i; 710*5088Sab196087 711*5088Sab196087 /* 712*5088Sab196087 * If -needed option is not present, the second argument can be 713*5088Sab196087 * an SYMINFO_BT_ value. 714*5088Sab196087 */ 715*5088Sab196087 if (argc != (num_opt + 2)) 716*5088Sab196087 return; 717*5088Sab196087 718*5088Sab196087 /* Is -needed there? If so, no completion is possible so return */ 719*5088Sab196087 for (i = 0; i < num_opt; i++) 720*5088Sab196087 if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_NEEDED)) == 0) 721*5088Sab196087 return; 722*5088Sab196087 723*5088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SYMINFO_BT); 724*5088Sab196087 } 725*5088Sab196087 726*5088Sab196087 /*ARGSUSED*/ 727*5088Sab196087 static void 728*5088Sab196087 cpl_si_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 729*5088Sab196087 const char *argv[], int num_opt) 730*5088Sab196087 { 731*5088Sab196087 /* The second argument can be an SYMINFO_FLG_ value */ 732*5088Sab196087 if (argc == (num_opt + 2)) 733*5088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SYMINFO_FLG); 734*5088Sab196087 } 735*5088Sab196087 736*5088Sab196087 737*5088Sab196087 738*5088Sab196087 /* 739*5088Sab196087 * Implementation functions for the commands 740*5088Sab196087 */ 741*5088Sab196087 static elfedit_cmdret_t 742*5088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 743*5088Sab196087 { 744*5088Sab196087 return (cmd_body(SYMINFO_CMD_T_DUMP, obj_state, argc, argv)); 745*5088Sab196087 } 746*5088Sab196087 747*5088Sab196087 748*5088Sab196087 static elfedit_cmdret_t 749*5088Sab196087 cmd_si_boundto(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 750*5088Sab196087 { 751*5088Sab196087 return (cmd_body(SYMINFO_CMD_T_SI_BOUNDTO, obj_state, argc, argv)); 752*5088Sab196087 } 753*5088Sab196087 754*5088Sab196087 755*5088Sab196087 static elfedit_cmdret_t 756*5088Sab196087 cmd_si_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 757*5088Sab196087 { 758*5088Sab196087 return (cmd_body(SYMINFO_CMD_T_SI_FLAGS, obj_state, argc, argv)); 759*5088Sab196087 } 760*5088Sab196087 761*5088Sab196087 762*5088Sab196087 763*5088Sab196087 764*5088Sab196087 /*ARGSUSED*/ 765*5088Sab196087 elfedit_module_t * 766*5088Sab196087 elfedit_init(elfedit_module_version_t version) 767*5088Sab196087 { 768*5088Sab196087 /* sym:dump */ 769*5088Sab196087 static const char *name_dump[] = { 770*5088Sab196087 MSG_ORIG(MSG_CMD_DUMP), 771*5088Sab196087 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 772*5088Sab196087 NULL 773*5088Sab196087 }; 774*5088Sab196087 static elfedit_cmd_optarg_t opt_dump[] = { 775*5088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 776*5088Sab196087 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 777*5088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, 778*5088Sab196087 SYMINFO_OPT_F_SYMNDX, 0 }, 779*5088Sab196087 { NULL } 780*5088Sab196087 }; 781*5088Sab196087 static elfedit_cmd_optarg_t arg_dump[] = { 782*5088Sab196087 { MSG_ORIG(MSG_STR_SYM), 783*5088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 784*5088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 785*5088Sab196087 ELFEDIT_CMDOA_F_OPT }, 786*5088Sab196087 { NULL } 787*5088Sab196087 }; 788*5088Sab196087 789*5088Sab196087 /* sym:si_boundto */ 790*5088Sab196087 static const char *name_si_boundto[] = { 791*5088Sab196087 MSG_ORIG(MSG_CMD_SI_BOUNDTO), NULL }; 792*5088Sab196087 static elfedit_cmd_optarg_t opt_si_boundto[] = { 793*5088Sab196087 { MSG_ORIG(MSG_STR_MINUS_NEEDED), 794*5088Sab196087 /* MSG_INTL(MSG_OPTDESC_NEEDED) */ 795*5088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_NEEDED), 0, 796*5088Sab196087 SYMINFO_OPT_F_NEEDED, 0 }, 797*5088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 798*5088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 799*5088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 800*5088Sab196087 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 801*5088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, 802*5088Sab196087 SYMINFO_OPT_F_SYMNDX, 0 }, 803*5088Sab196087 { NULL } 804*5088Sab196087 }; 805*5088Sab196087 static elfedit_cmd_optarg_t arg_si_boundto[] = { 806*5088Sab196087 { MSG_ORIG(MSG_STR_SYM), 807*5088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 808*5088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 809*5088Sab196087 ELFEDIT_CMDOA_F_OPT }, 810*5088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 811*5088Sab196087 /* MSG_INTL(MSG_A2_DESC_SI_BOUNDTO) */ 812*5088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_SI_BOUNDTO), 813*5088Sab196087 ELFEDIT_CMDOA_F_OPT }, 814*5088Sab196087 { NULL } 815*5088Sab196087 }; 816*5088Sab196087 817*5088Sab196087 /* sym:si_flags */ 818*5088Sab196087 static const char *name_si_flags[] = { 819*5088Sab196087 MSG_ORIG(MSG_CMD_SI_FLAGS), NULL }; 820*5088Sab196087 static elfedit_cmd_optarg_t opt_si_flags[] = { 821*5088Sab196087 { ELFEDIT_STDOA_OPT_AND, NULL, ELFEDIT_CMDOA_F_INHERIT, 822*5088Sab196087 SYMINFO_OPT_F_AND, SYMINFO_OPT_F_OR }, 823*5088Sab196087 { ELFEDIT_STDOA_OPT_CMP, NULL, 824*5088Sab196087 ELFEDIT_CMDOA_F_INHERIT, SYMINFO_OPT_F_CMP, 0 }, 825*5088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 826*5088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 827*5088Sab196087 { ELFEDIT_STDOA_OPT_OR, NULL, ELFEDIT_CMDOA_F_INHERIT, 828*5088Sab196087 SYMINFO_OPT_F_OR, SYMINFO_OPT_F_AND }, 829*5088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 830*5088Sab196087 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 831*5088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, 832*5088Sab196087 SYMINFO_OPT_F_SYMNDX, 0 }, 833*5088Sab196087 { NULL } 834*5088Sab196087 }; 835*5088Sab196087 static elfedit_cmd_optarg_t arg_si_flags[] = { 836*5088Sab196087 { MSG_ORIG(MSG_STR_SYM), 837*5088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 838*5088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 839*5088Sab196087 ELFEDIT_CMDOA_F_OPT }, 840*5088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 841*5088Sab196087 /* MSG_INTL(MSG_A2_DESC_SI_FLAGS) */ 842*5088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_SI_FLAGS), 843*5088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 844*5088Sab196087 { NULL } 845*5088Sab196087 }; 846*5088Sab196087 847*5088Sab196087 static elfedit_cmd_t cmds[] = { 848*5088Sab196087 /* sym:dump */ 849*5088Sab196087 { cmd_dump, NULL, name_dump, 850*5088Sab196087 /* MSG_INTL(MSG_DESC_DUMP) */ 851*5088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 852*5088Sab196087 /* MSG_INTL(MSG_HELP_DUMP) */ 853*5088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 854*5088Sab196087 opt_dump, arg_dump }, 855*5088Sab196087 856*5088Sab196087 /* sym:si_boundto */ 857*5088Sab196087 { cmd_si_boundto, cpl_si_boundto, name_si_boundto, 858*5088Sab196087 /* MSG_INTL(MSG_DESC_SI_BOUNDTO) */ 859*5088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_SI_BOUNDTO), 860*5088Sab196087 /* MSG_INTL(MSG_HELP_SI_BOUNDTO) */ 861*5088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_SI_BOUNDTO), 862*5088Sab196087 opt_si_boundto, arg_si_boundto }, 863*5088Sab196087 864*5088Sab196087 /* sym:si_flags */ 865*5088Sab196087 { cmd_si_flags, cpl_si_flags, name_si_flags, 866*5088Sab196087 /* MSG_INTL(MSG_DESC_SI_FLAGS) */ 867*5088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_SI_FLAGS), 868*5088Sab196087 /* MSG_INTL(MSG_HELP_SI_FLAGS) */ 869*5088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_SI_FLAGS), 870*5088Sab196087 opt_si_flags, arg_si_flags }, 871*5088Sab196087 872*5088Sab196087 { NULL } 873*5088Sab196087 }; 874*5088Sab196087 875*5088Sab196087 static elfedit_module_t module = { 876*5088Sab196087 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 877*5088Sab196087 /* MSG_INTL(MSG_MOD_DESC) */ 878*5088Sab196087 ELFEDIT_I18NHDL(MSG_MOD_DESC), 879*5088Sab196087 cmds, mod_i18nhdl_to_str }; 880*5088Sab196087 881*5088Sab196087 return (&module); 882*5088Sab196087 } 883