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