15088Sab196087 /* 25088Sab196087 * CDDL HEADER START 35088Sab196087 * 45088Sab196087 * The contents of this file are subject to the terms of the 55088Sab196087 * Common Development and Distribution License (the "License"). 65088Sab196087 * You may not use this file except in compliance with the License. 75088Sab196087 * 85088Sab196087 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95088Sab196087 * or http://www.opensolaris.org/os/licensing. 105088Sab196087 * See the License for the specific language governing permissions 115088Sab196087 * and limitations under the License. 125088Sab196087 * 135088Sab196087 * When distributing Covered Code, include this CDDL HEADER in each 145088Sab196087 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155088Sab196087 * If applicable, add the following below this CDDL HEADER, with the 165088Sab196087 * fields enclosed by brackets "[]" replaced with your own identifying 175088Sab196087 * information: Portions Copyright [yyyy] [name of copyright owner] 185088Sab196087 * 195088Sab196087 * CDDL HEADER END 205088Sab196087 */ 215088Sab196087 225088Sab196087 /* 235088Sab196087 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 245088Sab196087 * Use is subject to license terms. 255088Sab196087 */ 265088Sab196087 #pragma ident "%Z%%M% %I% %E% SMI" 275088Sab196087 285088Sab196087 #define ELF_TARGET_AMD64 /* SHN_AMD64_LCOMMON */ 295088Sab196087 305088Sab196087 #include <stdio.h> 315088Sab196087 #include <unistd.h> 325088Sab196087 #include <machdep.h> 335088Sab196087 #include <elfedit.h> 345088Sab196087 #include <strings.h> 355088Sab196087 #include <debug.h> 365088Sab196087 #include <conv.h> 375088Sab196087 #include <sym_msg.h> 385088Sab196087 395088Sab196087 405088Sab196087 415088Sab196087 425088Sab196087 #define MAXNDXSIZE 10 435088Sab196087 445088Sab196087 455088Sab196087 465088Sab196087 /* 475088Sab196087 * This module uses shared code for several of the commands. 485088Sab196087 * It is sometimes necessary to know which specific command 495088Sab196087 * is active. 505088Sab196087 */ 515088Sab196087 typedef enum { 525088Sab196087 SYM_CMD_T_DUMP = 0, /* sym:dump */ 535088Sab196087 545088Sab196087 SYM_CMD_T_ST_BIND = 1, /* sym:st_bind */ 555088Sab196087 SYM_CMD_T_ST_INFO = 2, /* sym:st_info */ 565088Sab196087 SYM_CMD_T_ST_NAME = 3, /* sym:st_name */ 575088Sab196087 SYM_CMD_T_ST_OTHER = 4, /* sym:st_other */ 585088Sab196087 SYM_CMD_T_ST_SHNDX = 5, /* sym:st_shndx */ 595088Sab196087 SYM_CMD_T_ST_SIZE = 6, /* sym:st_size */ 605088Sab196087 SYM_CMD_T_ST_TYPE = 7, /* sym:st_type */ 615088Sab196087 SYM_CMD_T_ST_VALUE = 8, /* sym:st_value */ 625088Sab196087 SYM_CMD_T_ST_VISIBILITY = 9 /* sym:st_visibility */ 635088Sab196087 } SYM_CMD_T; 645088Sab196087 655088Sab196087 665088Sab196087 675088Sab196087 /* 685088Sab196087 * ELFCLASS-specific definitions 695088Sab196087 */ 705088Sab196087 #ifdef _ELF64 715088Sab196087 725088Sab196087 #define MSG_FMT_XWORDVALNL MSG_FMT_XWORDVALNL_64 735088Sab196087 745088Sab196087 #else 755088Sab196087 765088Sab196087 #define MSG_FMT_XWORDVALNL MSG_FMT_XWORDVALNL_32 775088Sab196087 785088Sab196087 /* 795088Sab196087 * We supply this function for the msg module. Only one copy is needed. 805088Sab196087 */ 815088Sab196087 const char * 825088Sab196087 _sym_msg(Msg mid) 835088Sab196087 { 845088Sab196087 return (gettext(MSG_ORIG(mid))); 855088Sab196087 } 865088Sab196087 875088Sab196087 #endif 885088Sab196087 895088Sab196087 905088Sab196087 915088Sab196087 /* 925088Sab196087 * This function is supplied to elfedit through our elfedit_module_t 935088Sab196087 * definition. It translates the opaque elfedit_i18nhdl_t handles 945088Sab196087 * in our module interface into the actual strings for elfedit to 955088Sab196087 * use. 965088Sab196087 * 975088Sab196087 * note: 985088Sab196087 * This module uses Msg codes for its i18n handle type. 995088Sab196087 * So the translation is simply to use MSG_INTL() to turn 1005088Sab196087 * it into a string and return it. 1015088Sab196087 */ 1025088Sab196087 static const char * 1035088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 1045088Sab196087 { 1055088Sab196087 Msg msg = (Msg)hdl; 1065088Sab196087 1075088Sab196087 return (MSG_INTL(msg)); 1085088Sab196087 } 1095088Sab196087 1105088Sab196087 1115088Sab196087 1125088Sab196087 /* 1135088Sab196087 * The sym_opt_t enum specifies a bit value for every optional 1145088Sab196087 * argument allowed by a command in this module. 1155088Sab196087 */ 1165088Sab196087 typedef enum { 1175088Sab196087 SYM_OPT_F_XSHINDEX = 1, /* -e: Force shndx update to extended */ 1185088Sab196087 /* index section */ 1195088Sab196087 SYM_OPT_F_NAMOFFSET = 2, /* -name_offset: sym:st_name name arg */ 1205088Sab196087 /* is numeric offset */ 1215088Sab196087 /* rather than ASCII string */ 1225088Sab196087 SYM_OPT_F_SECSHNDX = 4, /* -secshndx: Section arg is */ 1235088Sab196087 /* section index, not name */ 1245088Sab196087 SYM_OPT_F_SECSHTYP = 8, /* -secshtyp: Section arg is */ 1255088Sab196087 /* section type, not name */ 1265088Sab196087 SYM_OPT_F_SHNAME = 16, /* -shnam name: section spec. by name */ 1275088Sab196087 SYM_OPT_F_SHNDX = 32, /* -shndx ndx: section spec. by index */ 1285088Sab196087 SYM_OPT_F_SHTYP = 64, /* -shtyp type: section spec. by type */ 1295088Sab196087 SYM_OPT_F_SYMNDX = 128 /* -symndx: Sym specified by index */ 1305088Sab196087 } sym_opt_t; 1315088Sab196087 1325088Sab196087 1335088Sab196087 /* 1345088Sab196087 * A variable of type ARGSTATE is used by each command to maintain 1355088Sab196087 * the overall state for a given set of arguments and the symbol tables 1365088Sab196087 * being managed. 1375088Sab196087 * 1385088Sab196087 * The state for each symbol table and the auxiliary sections that are 1395088Sab196087 * related to it are kept in a SYMSTATE sub-struct. 1405088Sab196087 * 1415088Sab196087 * One benefit of ARGSTATE is that it helps us to ensure that we only 1425088Sab196087 * fetch each section a single time: 1435088Sab196087 * - More efficient 1445088Sab196087 * - Prevents multiple ELFEDIT_MSG_DEBUG messages from 1455088Sab196087 * being produced for a given section. 1465088Sab196087 * 1475088Sab196087 * note: The symstate array in ARGSTATE is defined as having one 1485088Sab196087 * element, but in reality, we allocate enough room for 1495088Sab196087 * the number of elements defined in the numsymstate field. 1505088Sab196087 */ 1515088Sab196087 typedef struct { 1525088Sab196087 Word ndx; /* If argstate.argc > 0, this is the table index */ 1535088Sab196087 struct { /* Symbol table */ 1545088Sab196087 elfedit_section_t *sec; 1555088Sab196087 Sym *data; 1565088Sab196087 Word n; 1575088Sab196087 } sym; 1585088Sab196087 struct { /* String table */ 1595088Sab196087 elfedit_section_t *sec; 1605088Sab196087 } str; 1615088Sab196087 struct { /* Versym */ 1625088Sab196087 Word shndx; 1635088Sab196087 elfedit_section_t *sec; 1645088Sab196087 Versym *data; 1655088Sab196087 Word n; 1665088Sab196087 } versym; 1675088Sab196087 struct { /* Extended section indices */ 1685088Sab196087 Word shndx; 1695088Sab196087 elfedit_section_t *sec; 1705088Sab196087 Word *data; 1715088Sab196087 Word n; 1725088Sab196087 } xshndx; 1735088Sab196087 } SYMSTATE; 1745088Sab196087 typedef struct { 1755088Sab196087 elfedit_obj_state_t *obj_state; 1765088Sab196087 sym_opt_t optmask; /* Mask of options used */ 1775088Sab196087 int argc; /* # of plain arguments */ 1785088Sab196087 const char **argv; /* Plain arguments */ 1795088Sab196087 int numsymstate; /* # of items in symstate[] */ 1805088Sab196087 SYMSTATE symstate[1]; /* Symbol tables to process */ 1815088Sab196087 } ARGSTATE; 1825088Sab196087 1835088Sab196087 1845088Sab196087 /* 1855088Sab196087 * We maintain the state of each symbol table and related associated 1865088Sab196087 * sections in a SYMSTATE structure . We don't look those auxiliary 1875088Sab196087 * things up unless we actually need them, both to be efficient, 1885088Sab196087 * and to prevent duplicate ELFEDIT_MSG_DEBUG messages from being 1895088Sab196087 * issued as they are located. Hence, process_args() is used to 1905088Sab196087 * initialize the state block with just the symbol table, and then one 1915088Sab196087 * of the argstate_add_XXX() functions is used as needed 1925088Sab196087 * to fetch the additional sections. 1935088Sab196087 * 1945088Sab196087 * entry: 1955088Sab196087 * argstate - Overall state block 1965088Sab196087 * symstate - State block for current symbol table. 1975088Sab196087 * 1985088Sab196087 * exit: 1995088Sab196087 * If the needed auxiliary section is not found, an error is 2005088Sab196087 * issued and the argstate_add_XXX() routine does not return. 2015088Sab196087 * Otherwise, the fields in argstate have been filled in, ready 2025088Sab196087 * for use. 2035088Sab196087 * 2045088Sab196087 */ 2055088Sab196087 static void 2065088Sab196087 symstate_add_str(ARGSTATE *argstate, SYMSTATE *symstate) 2075088Sab196087 { 2085088Sab196087 if (symstate->str.sec != NULL) 2095088Sab196087 return; 2105088Sab196087 2115088Sab196087 symstate->str.sec = elfedit_sec_getstr(argstate->obj_state, 2125088Sab196087 symstate->sym.sec->sec_shdr->sh_link); 2135088Sab196087 } 2145088Sab196087 static void 2155088Sab196087 symstate_add_versym(ARGSTATE *argstate, SYMSTATE *symstate) 2165088Sab196087 { 2175088Sab196087 if (symstate->versym.sec != NULL) 2185088Sab196087 return; 2195088Sab196087 2205088Sab196087 symstate->versym.sec = elfedit_sec_getversym(argstate->obj_state, 2215088Sab196087 symstate->sym.sec, &symstate->versym.data, &symstate->versym.n); 2225088Sab196087 } 2235088Sab196087 static void 2245088Sab196087 symstate_add_xshndx(ARGSTATE *argstate, SYMSTATE *symstate) 2255088Sab196087 { 2265088Sab196087 if (symstate->xshndx.sec != NULL) 2275088Sab196087 return; 2285088Sab196087 2295088Sab196087 symstate->xshndx.sec = elfedit_sec_getxshndx(argstate->obj_state, 2305088Sab196087 symstate->sym.sec, &symstate->xshndx.data, &symstate->xshndx.n); 2315088Sab196087 } 2325088Sab196087 2335088Sab196087 2345088Sab196087 2355088Sab196087 /* 2365088Sab196087 * Display symbol table entries in the style used by elfdump. 2375088Sab196087 * 2385088Sab196087 * entry: 2395088Sab196087 * argstate - Overall state block 2405088Sab196087 * symstate - State block for current symbol table. 2415088Sab196087 * ndx - Index of first symbol to display 2425088Sab196087 * cnt - Number of symbols to display 2435088Sab196087 */ 2445088Sab196087 static void 2455088Sab196087 dump_symtab(ARGSTATE *argstate, SYMSTATE *symstate, Word ndx, Word cnt) 2465088Sab196087 { 2475088Sab196087 char index[MAXNDXSIZE]; 2485088Sab196087 Word shndx; 2495088Sab196087 const char *shndx_name; 2505088Sab196087 elfedit_section_t *symsec; 2515088Sab196087 elfedit_section_t *strsec; 2525088Sab196087 Sym *sym; 2535088Sab196087 elfedit_obj_state_t *obj_state = argstate->obj_state; 2545088Sab196087 Half mach = obj_state->os_ehdr->e_machine; 2555088Sab196087 const char *symname; 2565088Sab196087 Versym versym; 2575088Sab196087 2585088Sab196087 symsec = symstate->sym.sec; 2595088Sab196087 sym = symstate->sym.data + ndx; 2605088Sab196087 2615088Sab196087 symstate_add_str(argstate, symstate); 2625088Sab196087 strsec = symstate->str.sec; 2635088Sab196087 2645088Sab196087 /* If there is a versym index section, fetch it */ 2655088Sab196087 if (symstate->versym.shndx != SHN_UNDEF) 2665088Sab196087 symstate_add_versym(argstate, symstate); 2675088Sab196087 2685088Sab196087 /* If there is an extended index section, fetch it */ 2695088Sab196087 if (symstate->xshndx.shndx != SHN_UNDEF) 2705088Sab196087 symstate_add_xshndx(argstate, symstate); 2715088Sab196087 2725088Sab196087 elfedit_printf(MSG_INTL(MSG_FMT_SYMTAB), symsec->sec_name); 2735088Sab196087 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 2745088Sab196087 for (; cnt-- > 0; ndx++, sym++) { 2755088Sab196087 (void) snprintf(index, MAXNDXSIZE, 2765088Sab196087 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(ndx)); 2775088Sab196087 versym = (symstate->versym.sec == NULL) ? 0 : 2785088Sab196087 symstate->versym.data[ndx]; 2795088Sab196087 symname = elfedit_offset_to_str(strsec, sym->st_name, 2805088Sab196087 ELFEDIT_MSG_DEBUG, 0); 2815088Sab196087 shndx = sym->st_shndx; 2825088Sab196087 if ((shndx == SHN_XINDEX) && (symstate->xshndx.sec != NULL)) 2835088Sab196087 shndx = symstate->xshndx.data[ndx]; 2845088Sab196087 shndx_name = elfedit_shndx_to_name(obj_state, shndx); 2855088Sab196087 Elf_syms_table_entry(NULL, ELF_DBG_ELFDUMP, index, mach, 2865088Sab196087 sym, versym, 0, shndx_name, symname); 2875088Sab196087 } 2885088Sab196087 } 2895088Sab196087 2905088Sab196087 2915088Sab196087 2925088Sab196087 /* 2935088Sab196087 * Called by print_sym() to determine if a given symbol has the same 2945088Sab196087 * display value for the current command in every symbol table. 2955088Sab196087 * 2965088Sab196087 * entry: 2975088Sab196087 * cmd - SYM_CMD_T_* value giving identify of caller 2985088Sab196087 * argstate - Overall state block 2995088Sab196087 * outstyle - Output style to use 3005088Sab196087 */ 3015088Sab196087 static int 3025088Sab196087 all_same(SYM_CMD_T cmd, ARGSTATE *argstate, elfedit_outstyle_t outstyle) 3035088Sab196087 { 3045088Sab196087 Word tblndx; 3055088Sab196087 SYMSTATE *symstate1, *symstate2; 3065088Sab196087 Sym *sym1, *sym2; 3075088Sab196087 3085088Sab196087 symstate1 = argstate->symstate; 3095088Sab196087 for (tblndx = 0; tblndx < (argstate->numsymstate - 1); 3105088Sab196087 tblndx++, symstate1++) { 3115088Sab196087 symstate2 = symstate1 + 1; 3125088Sab196087 sym1 = &symstate1->sym.data[symstate1->ndx]; 3135088Sab196087 sym2 = &symstate2->sym.data[symstate2->ndx]; 3145088Sab196087 3155088Sab196087 switch (cmd) { 3165088Sab196087 case SYM_CMD_T_DUMP: 3175088Sab196087 /* sym:dump should always show everything */ 3185088Sab196087 return (0); 3195088Sab196087 3205088Sab196087 case SYM_CMD_T_ST_BIND: 3215088Sab196087 if (ELF_ST_BIND(sym1->st_info) != 3225088Sab196087 ELF_ST_BIND(sym2->st_info)) 3235088Sab196087 return (0); 3245088Sab196087 break; 3255088Sab196087 3265088Sab196087 case SYM_CMD_T_ST_INFO: 3275088Sab196087 if (sym1->st_info != sym2->st_info) 3285088Sab196087 return (0); 3295088Sab196087 break; 3305088Sab196087 3315088Sab196087 case SYM_CMD_T_ST_NAME: 3325088Sab196087 /* 3335088Sab196087 * In simple output mode, we show the string. In 3345088Sab196087 * numeric mode, we show the string table offset. 3355088Sab196087 */ 3365088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 3375088Sab196087 const char *n1, *n2; 3385088Sab196087 3395088Sab196087 symstate_add_str(argstate, symstate1); 3405088Sab196087 symstate_add_str(argstate, symstate2); 3415088Sab196087 n1 = elfedit_offset_to_str(symstate1->str.sec, 3425088Sab196087 sym1->st_name, ELFEDIT_MSG_DEBUG, 0); 3435088Sab196087 n2 = elfedit_offset_to_str(symstate2->str.sec, 3445088Sab196087 sym2->st_name, ELFEDIT_MSG_DEBUG, 0); 3455088Sab196087 if (strcmp(n1, n2) != 0) 3465088Sab196087 return (0); 3475088Sab196087 } else { 3485088Sab196087 if (sym1->st_name != sym2->st_name) 3495088Sab196087 return (0); 3505088Sab196087 } 3515088Sab196087 break; 3525088Sab196087 3535088Sab196087 case SYM_CMD_T_ST_OTHER: 3545088Sab196087 if (sym1->st_other != sym2->st_other) 3555088Sab196087 return (0); 3565088Sab196087 break; 3575088Sab196087 3585088Sab196087 case SYM_CMD_T_ST_SHNDX: 3595088Sab196087 { 3605088Sab196087 Word ndx1, ndx2; 3615088Sab196087 3625088Sab196087 ndx1 = sym1->st_shndx; 3635088Sab196087 if ((ndx1 == SHN_XINDEX) && 3645088Sab196087 (symstate1->xshndx.shndx != SHN_UNDEF)) { 3655088Sab196087 symstate_add_xshndx(argstate, 3665088Sab196087 symstate1); 3675088Sab196087 ndx1 = symstate1->xshndx. 3685088Sab196087 data[symstate1->ndx]; 3695088Sab196087 } 3705088Sab196087 ndx2 = sym2->st_shndx; 3715088Sab196087 if ((ndx2 == SHN_XINDEX) && 3725088Sab196087 (symstate2->xshndx.shndx != SHN_UNDEF)) { 3735088Sab196087 symstate_add_xshndx(argstate, 3745088Sab196087 symstate2); 3755088Sab196087 ndx2 = symstate2->xshndx. 3765088Sab196087 data[symstate2->ndx]; 3775088Sab196087 } 3785088Sab196087 if (ndx1 != ndx2) 3795088Sab196087 return (0); 3805088Sab196087 } 3815088Sab196087 break; 3825088Sab196087 3835088Sab196087 case SYM_CMD_T_ST_SIZE: 3845088Sab196087 if (sym1->st_size != sym2->st_size) 3855088Sab196087 return (0); 3865088Sab196087 break; 3875088Sab196087 3885088Sab196087 case SYM_CMD_T_ST_TYPE: 3895088Sab196087 if (ELF_ST_TYPE(sym1->st_info) != 3905088Sab196087 ELF_ST_TYPE(sym2->st_info)) 3915088Sab196087 return (0); 3925088Sab196087 break; 3935088Sab196087 3945088Sab196087 case SYM_CMD_T_ST_VALUE: 3955088Sab196087 if (sym1->st_value != sym2->st_value) 3965088Sab196087 return (0); 3975088Sab196087 break; 3985088Sab196087 3995088Sab196087 case SYM_CMD_T_ST_VISIBILITY: 4005088Sab196087 if (ELF_ST_VISIBILITY(sym1->st_info) != 4015088Sab196087 ELF_ST_VISIBILITY(sym2->st_info)) 4025088Sab196087 return (0); 4035088Sab196087 break; 4045088Sab196087 } 4055088Sab196087 } 4065088Sab196087 4075088Sab196087 /* If we got here, there are no differences (or maybe only 1 table */ 4085088Sab196087 return (1); 4095088Sab196087 } 4105088Sab196087 4115088Sab196087 4125088Sab196087 /* 4135088Sab196087 * Called by print_sym() to display values for a single symbol table. 4145088Sab196087 * 4155088Sab196087 * entry: 4165088Sab196087 * autoprint - If True, output is only produced if the elfedit 4175088Sab196087 * autoprint flag is set. If False, output is always produced. 4185088Sab196087 * cmd - SYM_CMD_T_* value giving identify of caller 4195088Sab196087 * argstate - Overall state block 4205088Sab196087 * symstate - State block for current symbol table. 4215088Sab196087 * ndx - Index of first symbol to display 4225088Sab196087 * cnt - Number of symbols to display 4235088Sab196087 */ 4245088Sab196087 static void 4255088Sab196087 print_symstate(SYM_CMD_T cmd, ARGSTATE *argstate, SYMSTATE *symstate, 4265088Sab196087 elfedit_outstyle_t outstyle, Word ndx, Word cnt) 4275088Sab196087 { 4285088Sab196087 Word value; 4295088Sab196087 Sym *sym; 4305088Sab196087 4315088Sab196087 /* 4325088Sab196087 * If doing default output, use elfdump style where we 4335088Sab196087 * show all symbol attributes. In this case, the command 4345088Sab196087 * that called us doesn't matter 4355088Sab196087 */ 4365088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 4375088Sab196087 dump_symtab(argstate, symstate, ndx, cnt); 4385088Sab196087 return; 4395088Sab196087 } 4405088Sab196087 4415088Sab196087 sym = symstate->sym.data; 4425088Sab196087 4435088Sab196087 switch (cmd) { 4445088Sab196087 case SYM_CMD_T_ST_BIND: 4455088Sab196087 { 4465088Sab196087 Conv_inv_buf_t inv_buf; 4475088Sab196087 4485088Sab196087 for (sym += ndx; cnt--; sym++) { 4495088Sab196087 value = ELF_ST_BIND(sym->st_info); 4505088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 4515088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 4525088Sab196087 conv_sym_info_bind(value, 4535088Sab196087 CONV_FMT_ALT_FULLNAME, &inv_buf)); 4545088Sab196087 } else { 4555088Sab196087 elfedit_printf( 4565088Sab196087 MSG_ORIG(MSG_FMT_WORDVALNL), 4575088Sab196087 EC_WORD(value)); 4585088Sab196087 } 4595088Sab196087 } 4605088Sab196087 } 4615088Sab196087 return; 4625088Sab196087 4635088Sab196087 case SYM_CMD_T_ST_INFO: 4645088Sab196087 for (sym += ndx; cnt-- > 0; sym++) 4655088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 4665088Sab196087 EC_WORD(sym->st_info)); 4675088Sab196087 return; 4685088Sab196087 4695088Sab196087 case SYM_CMD_T_ST_NAME: 4705088Sab196087 /* 4715088Sab196087 * In simple output mode, we show the string. In numeric 4725088Sab196087 * mode, we show the string table offset. 4735088Sab196087 */ 4745088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 4755088Sab196087 symstate_add_str(argstate, symstate); 4765088Sab196087 for (sym += ndx; cnt--; sym++) { 4775088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 4785088Sab196087 elfedit_offset_to_str(symstate->str.sec, 4795088Sab196087 sym->st_name, ELFEDIT_MSG_ERR, 0)); 4805088Sab196087 } 4815088Sab196087 } else { 4825088Sab196087 for (; cnt--; sym++) 4835088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 4845088Sab196087 EC_WORD(sym->st_name)); 4855088Sab196087 } 4865088Sab196087 return; 4875088Sab196087 4885088Sab196087 case SYM_CMD_T_ST_OTHER: 4895088Sab196087 for (sym += ndx; cnt-- > 0; sym++) 4905088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 4915088Sab196087 EC_WORD(sym->st_other)); 4925088Sab196087 return; 4935088Sab196087 4945088Sab196087 case SYM_CMD_T_ST_SHNDX: 4955088Sab196087 /* If there is an extended index section, fetch it */ 4965088Sab196087 if (symstate->xshndx.shndx != SHN_UNDEF) 4975088Sab196087 symstate_add_xshndx(argstate, symstate); 4985088Sab196087 4995088Sab196087 for (; cnt--; ndx++) { 5005088Sab196087 value = sym[ndx].st_shndx; 5015088Sab196087 if ((value == SHN_XINDEX) && 5025088Sab196087 (symstate->xshndx.sec != NULL)) 5035088Sab196087 value = symstate->xshndx.data[ndx]; 5045088Sab196087 5055088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 5065088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 5075088Sab196087 elfedit_shndx_to_name(argstate->obj_state, 5085088Sab196087 value)); 5095088Sab196087 } else { 5105088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 5115088Sab196087 EC_WORD(value)); 5125088Sab196087 } 5135088Sab196087 } 5145088Sab196087 return; 5155088Sab196087 5165088Sab196087 case SYM_CMD_T_ST_SIZE: 5175088Sab196087 /* 5185088Sab196087 * machine word width integers displayed in fixed width 5195088Sab196087 * 0-filled hex format. 5205088Sab196087 */ 5215088Sab196087 for (sym += ndx; cnt--; sym++) 5225088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDVALNL), 5235088Sab196087 sym->st_size); 5245088Sab196087 return; 5255088Sab196087 5265088Sab196087 case SYM_CMD_T_ST_TYPE: 5275088Sab196087 { 5285088Sab196087 Half mach = argstate->obj_state->os_ehdr->e_machine; 5295088Sab196087 Conv_inv_buf_t inv_buf; 5305088Sab196087 5315088Sab196087 for (sym += ndx; cnt--; sym++) { 5325088Sab196087 value = ELF_ST_TYPE(sym->st_info); 5335088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 5345088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 5355088Sab196087 conv_sym_info_type(mach, value, 5365088Sab196087 CONV_FMT_ALT_FULLNAME, &inv_buf)); 5375088Sab196087 } else { 5385088Sab196087 elfedit_printf( 5395088Sab196087 MSG_ORIG(MSG_FMT_WORDVALNL), 5405088Sab196087 EC_WORD(value)); 5415088Sab196087 } 5425088Sab196087 } 5435088Sab196087 } 5445088Sab196087 return; 5455088Sab196087 5465088Sab196087 case SYM_CMD_T_ST_VALUE: 5475088Sab196087 /* 5485088Sab196087 * machine word width integers displayed in fixed width 5495088Sab196087 * 0-filled hex format. 5505088Sab196087 */ 5515088Sab196087 for (sym += ndx; cnt--; sym++) 5525088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDVALNL), 5535088Sab196087 sym->st_value); 5545088Sab196087 return; 5555088Sab196087 5565088Sab196087 case SYM_CMD_T_ST_VISIBILITY: 5575088Sab196087 { 5585088Sab196087 Conv_inv_buf_t inv_buf; 5595088Sab196087 5605088Sab196087 for (sym += ndx; cnt--; sym++) { 5615088Sab196087 value = ELF_ST_VISIBILITY(sym->st_other); 5625088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 5635088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 5645088Sab196087 conv_sym_other_vis(value, 5655088Sab196087 CONV_FMT_ALT_FULLNAME, &inv_buf)); 5665088Sab196087 } else { 5675088Sab196087 elfedit_printf( 5685088Sab196087 MSG_ORIG(MSG_FMT_WORDVALNL), 5695088Sab196087 EC_WORD(value)); 5705088Sab196087 } 5715088Sab196087 } 5725088Sab196087 } 5735088Sab196087 return; 5745088Sab196087 5755088Sab196087 } 5765088Sab196087 } 5775088Sab196087 5785088Sab196087 5795088Sab196087 /* 5805088Sab196087 * Print symbol values, taking the calling command, and output style 5815088Sab196087 * into account. 5825088Sab196087 * 5835088Sab196087 * entry: 5845088Sab196087 * autoprint - If True, output is only produced if the elfedit 5855088Sab196087 * autoprint flag is set. If False, output is always produced. 5865088Sab196087 * cmd - SYM_CMD_T_* value giving identify of caller 5875088Sab196087 * argstate - Overall state block 5885088Sab196087 * symstate - State block for current symbol table. 5895088Sab196087 * ndx - Index of first symbol to display 5905088Sab196087 * cnt - Number of symbols to display 5915088Sab196087 */ 5925088Sab196087 static void 5935088Sab196087 print_sym(SYM_CMD_T cmd, int autoprint, ARGSTATE *argstate) 5945088Sab196087 { 5955088Sab196087 Word ndx, tblndx; 5965088Sab196087 Word cnt; 5975088Sab196087 elfedit_outstyle_t outstyle; 5985088Sab196087 SYMSTATE *symstate; 5995088Sab196087 int only_one; 6005088Sab196087 6015088Sab196087 if ((autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))) 6025088Sab196087 return; 6035088Sab196087 6045088Sab196087 /* 6055088Sab196087 * Pick an output style. sym:dump is required to use the default 6065088Sab196087 * style. The other commands use the current output style. 6075088Sab196087 */ 6085088Sab196087 outstyle = (cmd == SYM_CMD_T_DUMP) ? 6095088Sab196087 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 6105088Sab196087 6115088Sab196087 /* 6125088Sab196087 * This is a nicity: Force any needed auxiliary sections to be 6135088Sab196087 * fetched here before any output is produced. This will put all 6145088Sab196087 * of the debug messages right at the top in a single cluster. 6155088Sab196087 */ 6165088Sab196087 symstate = argstate->symstate; 6175088Sab196087 for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) { 6185088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 6195088Sab196087 symstate_add_str(argstate, symstate); 6205088Sab196087 if (symstate->versym.shndx != SHN_UNDEF) 6215088Sab196087 symstate_add_versym(argstate, symstate); 6225088Sab196087 if (symstate->xshndx.shndx != SHN_UNDEF) 6235088Sab196087 symstate_add_xshndx(argstate, symstate); 6245088Sab196087 continue; 6255088Sab196087 } 6265088Sab196087 6275088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 6285088Sab196087 switch (cmd) { 6295088Sab196087 case SYM_CMD_T_ST_NAME: 6305088Sab196087 symstate_add_str(argstate, symstate); 6315088Sab196087 break; 6325088Sab196087 6335088Sab196087 case SYM_CMD_T_ST_SHNDX: 6345088Sab196087 if (symstate->xshndx.shndx != SHN_UNDEF) 6355088Sab196087 symstate_add_xshndx(argstate, symstate); 6365088Sab196087 break; 6375088Sab196087 } 6385088Sab196087 } 6395088Sab196087 } 6405088Sab196087 6415088Sab196087 /* 6425088Sab196087 * If there is more than one table, we are displaying a single 6435088Sab196087 * item, we are not using the default "elfdump" style, and all 6445088Sab196087 * the symbols have the same value for the thing we intend to 6455088Sab196087 * display, then we only want to display it once. 6465088Sab196087 */ 6475088Sab196087 only_one = (argstate->numsymstate > 1) && (argstate->argc > 0) && 6485088Sab196087 (outstyle != ELFEDIT_OUTSTYLE_DEFAULT) && 6495088Sab196087 all_same(cmd, argstate, outstyle); 6505088Sab196087 6515088Sab196087 /* Run through the tables and display from each one */ 6525088Sab196087 symstate = argstate->symstate; 6535088Sab196087 for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) { 6545088Sab196087 if (argstate->argc == 0) { 6555088Sab196087 ndx = 0; 6565088Sab196087 cnt = symstate->sym.n; 6575088Sab196087 } else { 6585088Sab196087 ndx = symstate->ndx; 6595088Sab196087 cnt = 1; 6605088Sab196087 } 6615088Sab196087 6625088Sab196087 if ((tblndx > 0) && ((argstate->argc == 0) || 6635088Sab196087 (outstyle == ELFEDIT_OUTSTYLE_DEFAULT))) 6645088Sab196087 elfedit_printf(MSG_ORIG(MSG_STR_NL)); 6655088Sab196087 6665088Sab196087 print_symstate(cmd, argstate, symstate, outstyle, ndx, cnt); 6675088Sab196087 if (only_one) 6685088Sab196087 break; 6695088Sab196087 } 6705088Sab196087 } 6715088Sab196087 6725088Sab196087 6735088Sab196087 /* 6745088Sab196087 * The cmd_body_set_st_XXX() functions are for use by cmd_body(). 6755088Sab196087 * They handle the case where the second plain argument is 6765088Sab196087 * a value to be stored in the symbol. 6775088Sab196087 * 6785088Sab196087 * entry: 6795088Sab196087 * argstate - Overall state block 6805088Sab196087 * symstate - State block for current symbol table. 6815088Sab196087 */ 6825088Sab196087 static elfedit_cmdret_t 6835088Sab196087 cmd_body_set_st_bind(ARGSTATE *argstate, SYMSTATE *symstate) 6845088Sab196087 { 6855088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 6865088Sab196087 Sym *sym = &symstate->sym.data[symstate->ndx]; 6875088Sab196087 Word gbl_ndx; 6885088Sab196087 uchar_t bind, type, old_bind; 6895088Sab196087 Word symndx; 6905088Sab196087 Conv_inv_buf_t inv_buf1, inv_buf2; 6915088Sab196087 6925088Sab196087 /* 6935088Sab196087 * Use the ELF_ST_BIND() macro to access the defined bits 6945088Sab196087 * of the st_info field related to symbol binding. 6955088Sab196087 * Accepts STB_ symbolic names as well as integers. 6965088Sab196087 */ 6975088Sab196087 bind = elfedit_atoconst_range(argstate->argv[1], 6985088Sab196087 MSG_INTL(MSG_ARG_SYMBIND), 0, 15, ELFEDIT_CONST_STB); 6995088Sab196087 old_bind = ELF_ST_BIND(sym->st_info); 7005088Sab196087 type = ELF_ST_TYPE(sym->st_info); 7015088Sab196087 7025088Sab196087 if (old_bind == bind) { 7035088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK), 7045088Sab196087 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 7055088Sab196087 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_BIND), 7065088Sab196087 conv_sym_info_bind(bind, CONV_FMT_ALT_FULLNAME, &inv_buf1)); 7075088Sab196087 } else { 7085088Sab196087 /* 7095088Sab196087 * The sh_info field of the symbol table section header 7105088Sab196087 * gives the index of the first non-local symbol in 7115088Sab196087 * the table. Issue warnings if the binding we set 7125088Sab196087 * contradicts this. 7135088Sab196087 */ 7145088Sab196087 gbl_ndx = symstate->sym.sec->sec_shdr->sh_info; 7155088Sab196087 symndx = symstate->sym.sec->sec_shndx; 7165088Sab196087 if ((bind == STB_LOCAL) && (symstate->ndx >= gbl_ndx)) 7175088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 7185088Sab196087 MSG_INTL(MSG_DEBUG_LBINDGSYM), 7195088Sab196087 EC_WORD(symndx), symstate->sym.sec->sec_name, 7205088Sab196087 symstate->ndx, EC_WORD(symndx), gbl_ndx); 7215088Sab196087 if ((bind != STB_LOCAL) && (symstate->ndx < gbl_ndx)) 7225088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 7235088Sab196087 MSG_INTL(MSG_DEBUG_GBINDLSYM), 7245088Sab196087 EC_WORD(symndx), symstate->sym.sec->sec_name, 7255088Sab196087 symstate->ndx, EC_WORD(symndx), gbl_ndx); 7265088Sab196087 7275088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG), 7285088Sab196087 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 7295088Sab196087 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_BIND), 7305088Sab196087 conv_sym_info_bind(old_bind, CONV_FMT_ALT_FULLNAME, 7315088Sab196087 &inv_buf1), 7325088Sab196087 conv_sym_info_bind(bind, CONV_FMT_ALT_FULLNAME, &inv_buf2)); 7335088Sab196087 ret = ELFEDIT_CMDRET_MOD; 7345088Sab196087 sym->st_info = ELF_ST_INFO(bind, type); 7355088Sab196087 } 7365088Sab196087 7375088Sab196087 return (ret); 7385088Sab196087 } 7395088Sab196087 7405088Sab196087 static elfedit_cmdret_t 7415088Sab196087 cmd_body_set_st_name(ARGSTATE *argstate, SYMSTATE *symstate) 7425088Sab196087 { 7435088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 7445088Sab196087 Sym *sym = &symstate->sym.data[symstate->ndx]; 7455088Sab196087 Word str_offset; 7465088Sab196087 7475088Sab196087 /* 7485088Sab196087 * If -n was specified, this is an offset into the string 7495088Sab196087 * table. Otherwise it is a string we need to turn into 7505088Sab196087 * an offset 7515088Sab196087 */ 7525088Sab196087 symstate_add_str(argstate, symstate); 7535088Sab196087 if (argstate->optmask & SYM_OPT_F_NAMOFFSET) { 7545088Sab196087 str_offset = elfedit_atoui(argstate->argv[1], NULL); 7555088Sab196087 /* Warn if the offset is out of range */ 7565088Sab196087 (void) elfedit_offset_to_str(symstate->str.sec, 7575088Sab196087 str_offset, ELFEDIT_MSG_DEBUG, 1); 7585088Sab196087 } else { 7595088Sab196087 str_offset = elfedit_strtab_insert(argstate->obj_state, 7605088Sab196087 symstate->str.sec, NULL, argstate->argv[1]); 7615088Sab196087 } 7625088Sab196087 7635088Sab196087 if (sym->st_name == str_offset) { 7645088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_D_OK), 7655088Sab196087 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 7665088Sab196087 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_NAME), 7675088Sab196087 EC_WORD(sym->st_name)); 7685088Sab196087 } else { 7695088Sab196087 /* 7705088Sab196087 * Warn the user: Changing the name of a symbol in the dynsym 7715088Sab196087 * will break the hash table in this object. 7725088Sab196087 */ 7735088Sab196087 if (symstate->sym.sec->sec_shdr->sh_type == SHT_DYNSYM) 7745088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 7755088Sab196087 MSG_INTL(MSG_DEBUG_DYNSYMNAMCHG), 7765088Sab196087 EC_WORD(symstate->sym.sec->sec_shndx), 7775088Sab196087 symstate->sym.sec->sec_name, 7785088Sab196087 EC_WORD(symstate->ndx)); 7795088Sab196087 7805088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_D_CHG), 7815088Sab196087 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 7825088Sab196087 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_NAME), 7835088Sab196087 EC_WORD(sym->st_name), 7845088Sab196087 EC_WORD(str_offset)); 7855088Sab196087 ret = ELFEDIT_CMDRET_MOD; 7865088Sab196087 sym->st_name = str_offset; 7875088Sab196087 } 7885088Sab196087 7895088Sab196087 return (ret); 7905088Sab196087 } 7915088Sab196087 7925088Sab196087 static elfedit_cmdret_t 7935088Sab196087 cmd_body_set_st_shndx(ARGSTATE *argstate, SYMSTATE *symstate) 7945088Sab196087 { 7955088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 7965088Sab196087 Sym *sym = &symstate->sym.data[symstate->ndx]; 7975088Sab196087 Word shndx, st_shndx, xshndx; 7985088Sab196087 int use_xshndx; 7995088Sab196087 int shndx_chg, xshndx_chg; 8005088Sab196087 8015088Sab196087 8025088Sab196087 /* 8035088Sab196087 * By default, the sec argument is a section name. If -secshndx was 8045088Sab196087 * specified, it is a section index, and if -secshtyp is specified, 8055088Sab196087 * it is a section type. 8065088Sab196087 */ 8075088Sab196087 if (argstate->optmask & SYM_OPT_F_SECSHNDX) 8085088Sab196087 shndx = elfedit_atoshndx(argstate->argv[1], 8095088Sab196087 argstate->obj_state->os_shnum); 8105088Sab196087 else if (argstate->optmask & SYM_OPT_F_SECSHTYP) 8115088Sab196087 shndx = elfedit_type_to_shndx(argstate->obj_state, 8125088Sab196087 elfedit_atoconst(argstate->argv[1], ELFEDIT_CONST_SHT)); 8135088Sab196087 else 8145088Sab196087 shndx = elfedit_name_to_shndx(argstate->obj_state, 8155088Sab196087 argstate->argv[1]); 8165088Sab196087 8175088Sab196087 /* 8185088Sab196087 * We want to use an extended index section if the index is too 8195088Sab196087 * large to be represented otherwise, or if the caller specified 8205088Sab196087 * the -e option to make us do it anyway. However, we cannot 8215088Sab196087 * do this if the index is in the special reserved range between 8225088Sab196087 * SHN_LORESERVE and SHN_HIRESERVE. 8235088Sab196087 */ 8245088Sab196087 use_xshndx = (shndx > SHN_HIRESERVE) || 8255088Sab196087 ((shndx < SHN_LORESERVE) && 8265088Sab196087 (argstate->optmask & SYM_OPT_F_XSHINDEX)); 8275088Sab196087 8285088Sab196087 /* 8295088Sab196087 * There are two cases where we have to touch the extended 8305088Sab196087 * index section: 8315088Sab196087 * 8325088Sab196087 * 1) We have determined that we need to, as determined above. 8335088Sab196087 * 2) We do not require it, but the file has an extended 8345088Sab196087 * index section, in which case we should set the slot 8355088Sab196087 * in that extended section to SHN_UNDEF (0). 8365088Sab196087 * 8375088Sab196087 * Fetch the extended section as required, and determine the values 8385088Sab196087 * for st_shndx and the extended section slot. 8395088Sab196087 */ 8405088Sab196087 if (use_xshndx) { 8415088Sab196087 /* We must have an extended index section, or error out */ 8425088Sab196087 symstate_add_xshndx(argstate, symstate); 8435088Sab196087 8445088Sab196087 /* Set symbol to SHN_XINDEX, put index in the extended sec. */ 8455088Sab196087 st_shndx = SHN_XINDEX; 8465088Sab196087 xshndx = shndx; 8475088Sab196087 } else { 8485088Sab196087 st_shndx = shndx; 8495088Sab196087 xshndx = SHN_UNDEF; 8505088Sab196087 if (symstate->xshndx.shndx != SHN_UNDEF) 8515088Sab196087 use_xshndx = 1; 8525088Sab196087 } 8535088Sab196087 if (use_xshndx) 8545088Sab196087 symstate_add_xshndx(argstate, symstate); 8555088Sab196087 shndx_chg = (sym->st_shndx != st_shndx); 8565088Sab196087 xshndx_chg = use_xshndx && 8575088Sab196087 (symstate->xshndx.data[symstate->ndx] != xshndx); 8585088Sab196087 8595088Sab196087 8605088Sab196087 /* If anything is going to change, issue appropiate warnings */ 8615088Sab196087 if (shndx_chg || xshndx_chg) { 8625088Sab196087 /* 8635088Sab196087 * Setting the first symbol to anything other than SHN_UNDEF 8645088Sab196087 * produces a bad ELF file. 8655088Sab196087 */ 8665088Sab196087 if ((symstate->ndx == 0) && (shndx != SHN_UNDEF)) 8675088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8685088Sab196087 MSG_INTL(MSG_DEBUG_SHNDX_UNDEF0)); 8695088Sab196087 8705088Sab196087 /* 8715088Sab196087 * Setting SHN_XINDEX directly, instead of providing 8725088Sab196087 * an extended index and letting us decide to use 8735088Sab196087 * SHN_XINDEX to implement it, is probably a mistake. 8745088Sab196087 * Issue a warning, but go ahead and follow the directions 8755088Sab196087 * we've been given. 8765088Sab196087 */ 8775088Sab196087 if (shndx == SHN_XINDEX) 8785088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8795088Sab196087 MSG_INTL(MSG_DEBUG_SHNDX_XINDEX)); 8805088Sab196087 8815088Sab196087 /* 8825088Sab196087 * If the section index can fit in the symbol, but 8835088Sab196087 * -e is being used to force it into the extended 8845088Sab196087 * index section, issue a warning. 8855088Sab196087 */ 8865088Sab196087 if (use_xshndx && (shndx < SHN_LORESERVE) && 8875088Sab196087 (st_shndx == SHN_XINDEX)) 8885088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8895088Sab196087 MSG_INTL(MSG_DEBUG_SHNDX_EFORCE), 8905088Sab196087 EC_WORD(symstate->sym.sec->sec_shndx), 8915088Sab196087 symstate->sym.sec->sec_name, EC_WORD(symstate->ndx), 8925088Sab196087 EC_WORD(shndx)); 8935088Sab196087 } 8945088Sab196087 8955088Sab196087 if (shndx_chg) { 8965088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG), 8975088Sab196087 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 8985088Sab196087 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_SHNDX), 8995088Sab196087 elfedit_shndx_to_name(argstate->obj_state, 9005088Sab196087 sym->st_shndx), 9015088Sab196087 elfedit_shndx_to_name(argstate->obj_state, st_shndx)); 9025088Sab196087 ret = ELFEDIT_CMDRET_MOD; 9035088Sab196087 sym->st_shndx = st_shndx; 9045088Sab196087 } else { 9055088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK), 9065088Sab196087 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 9075088Sab196087 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_SHNDX), 9085088Sab196087 elfedit_shndx_to_name(argstate->obj_state, st_shndx)); 9095088Sab196087 } 9105088Sab196087 9115088Sab196087 if (use_xshndx) { 9125088Sab196087 if (xshndx_chg) { 9135088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 9145088Sab196087 MSG_INTL(MSG_DEBUG_EXT_S_CHG), 9155088Sab196087 symstate->xshndx.sec->sec_shndx, 9165088Sab196087 symstate->xshndx.sec->sec_name, 9175088Sab196087 EC_WORD(symstate->ndx), 9185088Sab196087 elfedit_shndx_to_name(argstate->obj_state, 9195088Sab196087 symstate->xshndx.data[symstate->ndx]), 9205088Sab196087 elfedit_shndx_to_name(argstate->obj_state, xshndx)); 9215088Sab196087 ret = ELFEDIT_CMDRET_MOD; 9225088Sab196087 symstate->xshndx.data[symstate->ndx] = xshndx; 9235088Sab196087 elfedit_modified_data(symstate->xshndx.sec); 9245088Sab196087 } else { 9255088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 9265088Sab196087 MSG_INTL(MSG_DEBUG_EXT_S_OK), 9275088Sab196087 symstate->xshndx.sec->sec_shndx, 9285088Sab196087 symstate->xshndx.sec->sec_name, 9295088Sab196087 EC_WORD(symstate->ndx), 9305088Sab196087 elfedit_shndx_to_name(argstate->obj_state, xshndx)); 9315088Sab196087 } 9325088Sab196087 } 9335088Sab196087 9345088Sab196087 return (ret); 9355088Sab196087 } 9365088Sab196087 9375088Sab196087 static elfedit_cmdret_t 9385088Sab196087 cmd_body_set_st_type(ARGSTATE *argstate, SYMSTATE *symstate) 9395088Sab196087 { 9405088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 9415088Sab196087 Conv_inv_buf_t inv_buf1, inv_buf2; 9425088Sab196087 Half mach = argstate->obj_state->os_ehdr->e_machine; 9435088Sab196087 Sym *sym = &symstate->sym.data[symstate->ndx]; 9445088Sab196087 uchar_t bind, type, old_type; 9455088Sab196087 9465088Sab196087 /* 9475088Sab196087 * Use the ELF_ST_TYPE() macro to access the defined bits 9485088Sab196087 * of the st_info field related to symbol type. 9495088Sab196087 * Accepts STT_ symbolic names as well as integers. 9505088Sab196087 */ 9515088Sab196087 bind = ELF_ST_BIND(sym->st_info); 9525088Sab196087 type = elfedit_atoconst_range(argstate->argv[1], 9535088Sab196087 MSG_INTL(MSG_ARG_SYMBIND), 0, 15, ELFEDIT_CONST_STT); 9545088Sab196087 old_type = ELF_ST_TYPE(sym->st_info); 9555088Sab196087 9565088Sab196087 if (old_type == type) { 9575088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK), 9585088Sab196087 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 9595088Sab196087 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_TYPE), 9605088Sab196087 conv_sym_info_type(mach, type, CONV_FMT_ALT_FULLNAME, 9615088Sab196087 &inv_buf1)); 9625088Sab196087 } else { 9635088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG), 9645088Sab196087 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 9655088Sab196087 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_TYPE), 9665088Sab196087 conv_sym_info_type(mach, old_type, CONV_FMT_ALT_FULLNAME, 9675088Sab196087 &inv_buf1), 9685088Sab196087 conv_sym_info_type(mach, type, CONV_FMT_ALT_FULLNAME, 9695088Sab196087 &inv_buf2)); 9705088Sab196087 ret = ELFEDIT_CMDRET_MOD; 9715088Sab196087 sym->st_info = ELF_ST_INFO(bind, type); 9725088Sab196087 } 9735088Sab196087 9745088Sab196087 return (ret); 9755088Sab196087 } 9765088Sab196087 9775088Sab196087 static elfedit_cmdret_t 9785088Sab196087 cmd_body_set_st_visibility(ARGSTATE *argstate, SYMSTATE *symstate) 9795088Sab196087 { 9805088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 9815088Sab196087 Conv_inv_buf_t inv_buf1, inv_buf2; 9825088Sab196087 Sym *sym = &symstate->sym.data[symstate->ndx]; 9835088Sab196087 uchar_t st_other = sym->st_other; 9845088Sab196087 uchar_t vis, old_vis; 9855088Sab196087 9865088Sab196087 /* 9875088Sab196087 * Use the ELF_ST_VISIBILITY() macro to access the 9885088Sab196087 * defined bits of the st_other field related to symbol 9895088Sab196087 * visibility. Accepts STV_ symbolic names as well as integers. 9905088Sab196087 */ 9915088Sab196087 vis = elfedit_atoconst_range(argstate->argv[1], 992*5220Srie MSG_INTL(MSG_ARG_SYMVIS), 0, STV_ELIMINATE, ELFEDIT_CONST_STV); 9935088Sab196087 old_vis = st_other & MSK_SYM_VISIBILITY; 9945088Sab196087 9955088Sab196087 if (old_vis == vis) { 9965088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK), 9975088Sab196087 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 9985088Sab196087 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_VISIBILITY), 9995088Sab196087 conv_sym_other_vis(old_vis, CONV_FMT_ALT_FULLNAME, 10005088Sab196087 &inv_buf1)); 10015088Sab196087 } else { 10025088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG), 10035088Sab196087 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 10045088Sab196087 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_VISIBILITY), 10055088Sab196087 conv_sym_other_vis(old_vis, CONV_FMT_ALT_FULLNAME, 10065088Sab196087 &inv_buf1), 10075088Sab196087 conv_sym_other_vis(vis, CONV_FMT_ALT_FULLNAME, &inv_buf2)); 10085088Sab196087 ret = ELFEDIT_CMDRET_MOD; 10095088Sab196087 st_other = (st_other & ~MSK_SYM_VISIBILITY) | 10105088Sab196087 ELF_ST_VISIBILITY(vis); 10115088Sab196087 sym->st_other = st_other; 10125088Sab196087 } 10135088Sab196087 10145088Sab196087 return (ret); 10155088Sab196087 } 10165088Sab196087 10175088Sab196087 10185088Sab196087 /* 10195088Sab196087 * Standard argument processing for sym module 10205088Sab196087 * 10215088Sab196087 * entry 10225088Sab196087 * obj_state, argc, argv - Standard command arguments 10235088Sab196087 * optmask - Mask of allowed optional arguments. 10245088Sab196087 * symstate - State block for current symbol table. 10255088Sab196087 * argstate - Address of ARGSTATE block to be initialized 10265088Sab196087 * 10275088Sab196087 * exit: 10285088Sab196087 * On success, *argstate is initialized. On error, 10295088Sab196087 * an error is issued and this routine does not return. 10305088Sab196087 * 10315088Sab196087 * note: 10325088Sab196087 * Only the basic symbol table is initially referenced by 10335088Sab196087 * argstate. Use the argstate_add_XXX() routines below to 10345088Sab196087 * access any auxiliary sections needed. 10355088Sab196087 */ 10365088Sab196087 static ARGSTATE * 10375088Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 10385088Sab196087 SYM_CMD_T cmd) 10395088Sab196087 { 10405088Sab196087 /* 10415088Sab196087 * We reuse this same argstate, resizing it to the required 10425088Sab196087 * number of symbol tables on the first call, and as necessary. 10435088Sab196087 */ 10445088Sab196087 static ARGSTATE *argstate; 10455088Sab196087 static int argstate_size = 0; 10465088Sab196087 10475088Sab196087 elfedit_getopt_state_t getopt_state; 10485088Sab196087 elfedit_getopt_ret_t *getopt_ret; 10495088Sab196087 elfedit_symtab_t *symtab; 10505088Sab196087 int explicit = 0; 10515088Sab196087 int got_sym = 0; 10525088Sab196087 Word index; 10535088Sab196087 Word tblndx; 10545088Sab196087 size_t size; 10555088Sab196087 SYMSTATE *symstate; 10565088Sab196087 10575088Sab196087 /* If there are no symbol tables, we can't do a thing */ 10585088Sab196087 if (obj_state->os_symtabnum == 0) 10595088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMTAB)); 10605088Sab196087 10615088Sab196087 /* Calulate required size of argstate and realloc as necessary */ 10625088Sab196087 size = sizeof (ARGSTATE) + 10635088Sab196087 ((obj_state->os_symtabnum - 1) * sizeof (SYMSTATE)); 10645088Sab196087 if (argstate_size != size) { 10655088Sab196087 argstate = elfedit_realloc(MSG_INTL(MSG_ALLOC_ARGSTATE), 10665088Sab196087 argstate, size); 10675088Sab196087 argstate_size = size; 10685088Sab196087 } 10695088Sab196087 bzero(argstate, argstate_size); 10705088Sab196087 argstate->obj_state = obj_state; 10715088Sab196087 10725088Sab196087 elfedit_getopt_init(&getopt_state, &argc, &argv); 10735088Sab196087 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) { 10745088Sab196087 argstate->optmask |= getopt_ret->gor_idmask; 10755088Sab196087 switch (getopt_ret->gor_idmask) { 10765088Sab196087 case SYM_OPT_F_SHNAME: /* -shnam name */ 10775088Sab196087 index = elfedit_name_to_shndx(obj_state, 10785088Sab196087 getopt_ret->gor_value); 10795088Sab196087 explicit = 1; 10805088Sab196087 break; 10815088Sab196087 10825088Sab196087 case SYM_OPT_F_SHNDX: /* -shndx index */ 10835088Sab196087 index = elfedit_atoui_range(getopt_ret->gor_value, 10845088Sab196087 MSG_INTL(MSG_ARG_SECNDX), 1, 10855088Sab196087 obj_state->os_shnum - 1, NULL); 10865088Sab196087 explicit = 1; 10875088Sab196087 break; 10885088Sab196087 10895088Sab196087 case SYM_OPT_F_SHTYP: /* -shtyp type */ 10905088Sab196087 index = elfedit_type_to_shndx(obj_state, 10915088Sab196087 elfedit_atoconst(getopt_ret->gor_value, 10925088Sab196087 ELFEDIT_CONST_SHT)); 10935088Sab196087 explicit = 1; 10945088Sab196087 break; 10955088Sab196087 } 10965088Sab196087 } 10975088Sab196087 10985088Sab196087 /* 10995088Sab196087 * Usage error if there are too many plain arguments. sym:dump accepts 11005088Sab196087 * a single argument, while the others accept 2. 11015088Sab196087 */ 11025088Sab196087 if (((cmd == SYM_CMD_T_DUMP) && (argc > 1)) || (argc > 2)) 11035088Sab196087 elfedit_command_usage(); 11045088Sab196087 11055088Sab196087 /* 11065088Sab196087 * If the -symndx option was specified, the sym arg is an index 11075088Sab196087 * into the symbol table. In this case, the symbol table must be 11085088Sab196087 * explicitly specified (-shnam, -shndx, or -shtype). 11095088Sab196087 */ 11105088Sab196087 if ((argstate->optmask & SYM_OPT_F_SYMNDX) && !explicit) 11115088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEXPSYMTAB)); 11125088Sab196087 11135088Sab196087 /* 11145088Sab196087 * If a section was explicitly specified, it needs 11155088Sab196087 * be a symbol table. 11165088Sab196087 */ 11175088Sab196087 if (explicit) 11185088Sab196087 (void) elfedit_sec_issymtab(&obj_state->os_secarr[index], 11195088Sab196087 1, NULL); 11205088Sab196087 11215088Sab196087 /* If there may be an arbitrary amount of output, use a pager */ 11225088Sab196087 if (argc == 0) 11235088Sab196087 elfedit_pager_init(); 11245088Sab196087 11255088Sab196087 /* Return the updated values of argc/argv */ 11265088Sab196087 argstate->argc = argc; 11275088Sab196087 argstate->argv = argv; 11285088Sab196087 11295088Sab196087 /* 11305088Sab196087 * Decide which symbol table(s) to use. Set up the symstate 11315088Sab196087 * array to contain them: 11325088Sab196087 * - If a symbol table was explicitly specified, we use 11335088Sab196087 * it, and only it. 11345088Sab196087 * - If no symbol table is explicitly specified, and the symbol 11355088Sab196087 * is given by name, we use all symbol tables that 11365088Sab196087 * contain a symbol with that name, throwing an error 11375088Sab196087 * if there isn't at least 1 such table. 11385088Sab196087 * - If no symbol table is specified, and no symbol is specified, 11395088Sab196087 * we use all the tables. 11405088Sab196087 */ 11415088Sab196087 symtab = obj_state->os_symtab; 11425088Sab196087 symstate = argstate->symstate; 11435088Sab196087 for (tblndx = 0; tblndx < obj_state->os_symtabnum; 11445088Sab196087 tblndx++, symtab++) { 11455088Sab196087 /* If explicit table specified, only that table is considered */ 11465088Sab196087 if (explicit && (symtab->symt_shndx != index)) 11475088Sab196087 continue; 11485088Sab196087 11495088Sab196087 symstate->sym.sec = elfedit_sec_getsymtab(obj_state, 1, 11505088Sab196087 symtab->symt_shndx, NULL, &symstate->sym.data, 11515088Sab196087 &symstate->sym.n, &symtab); 11525088Sab196087 symstate->versym.shndx = symtab->symt_versym; 11535088Sab196087 symstate->xshndx.shndx = symtab->symt_xshndx; 11545088Sab196087 if (argc > 0) { 11555088Sab196087 if (argstate->optmask & SYM_OPT_F_SYMNDX) { 11565088Sab196087 symstate->ndx = elfedit_atoui_range( 11575088Sab196087 argstate->argv[0], MSG_INTL(MSG_ARG_SYM), 0, 11585088Sab196087 symstate->sym.n - 1, NULL); 11595088Sab196087 } else { 11605088Sab196087 /* 11615088Sab196087 * arg is a symbol name. Use the index of 11625088Sab196087 * the first symbol that matches 11635088Sab196087 */ 11645088Sab196087 11655088Sab196087 /* 11665088Sab196087 * We will use debug messages for failure up 11675088Sab196087 * until we run out of symbol tables. If we 11685088Sab196087 * don't find a table with the desired symbol 11695088Sab196087 * before the last table, we switch to error 11705088Sab196087 * messages. Hence, we will jump with an error 11715088Sab196087 * if no table will work. 11725088Sab196087 */ 11735088Sab196087 int err_type = (!got_sym && 11745088Sab196087 ((tblndx + 1) == obj_state->os_symtabnum)) ? 11755088Sab196087 ELFEDIT_MSG_ERR : ELFEDIT_MSG_DEBUG; 11765088Sab196087 11775088Sab196087 symstate_add_str(argstate, symstate); 11785088Sab196087 11795088Sab196087 /* 11805088Sab196087 * If the symbol table doesn't have this 11815088Sab196087 * symbol, then forget it. 11825088Sab196087 */ 11835088Sab196087 if (elfedit_name_to_symndx(symstate->sym.sec, 11845088Sab196087 symstate->str.sec, argstate->argv[0], 11855088Sab196087 err_type, &symstate->ndx) == 0) { 11865088Sab196087 bzero(symstate, sizeof (*symstate)); 11875088Sab196087 continue; 11885088Sab196087 } 11895088Sab196087 } 11905088Sab196087 } 11915088Sab196087 argstate->numsymstate++; 11925088Sab196087 symstate++; 11935088Sab196087 /* 11945088Sab196087 * If the symbol table was given explicitly, and 11955088Sab196087 * we've just taken it, then there is no reason to 11965088Sab196087 * continue searching. 11975088Sab196087 */ 11985088Sab196087 if (explicit) 11995088Sab196087 break; 12005088Sab196087 } 12015088Sab196087 12025088Sab196087 return (argstate); 12035088Sab196087 } 12045088Sab196087 12055088Sab196087 12065088Sab196087 12075088Sab196087 /* 12085088Sab196087 * Called by cmd_body() to handle the value change for a single 12095088Sab196087 * symbol table. 12105088Sab196087 * 12115088Sab196087 * entry: 12125088Sab196087 * cmd - One of the SYM_CMD_T_* constants listed above, specifying 12135088Sab196087 * which command to implement. 12145088Sab196087 * argstate - Overall state block 12155088Sab196087 * symstate - State block for current symbol table. 12165088Sab196087 */ 12175088Sab196087 static elfedit_cmdret_t 12185088Sab196087 symstate_cmd_body(SYM_CMD_T cmd, ARGSTATE *argstate, SYMSTATE *symstate) 12195088Sab196087 { 12205088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 12215088Sab196087 Sym *sym = &symstate->sym.data[symstate->ndx]; 12225088Sab196087 12235088Sab196087 /* You're not supposed to change the value of symbol [0] */ 12245088Sab196087 if (symstate->ndx == 0) 12255088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSYMELT0), 12265088Sab196087 EC_WORD(symstate->sym.sec->sec_shndx), 12275088Sab196087 symstate->sym.sec->sec_name, EC_WORD(symstate->ndx)); 12285088Sab196087 12295088Sab196087 /* The second value is an integer giving a new value */ 12305088Sab196087 switch (cmd) { 12315088Sab196087 /* 12325088Sab196087 * SYM_CMD_T_DUMP can't get here: It never has more than 12335088Sab196087 * one argument, and is handled above. 12345088Sab196087 */ 12355088Sab196087 12365088Sab196087 case SYM_CMD_T_ST_BIND: 12375088Sab196087 ret = cmd_body_set_st_bind(argstate, symstate); 12385088Sab196087 break; 12395088Sab196087 12405088Sab196087 case SYM_CMD_T_ST_INFO: 12415088Sab196087 { 12425088Sab196087 /* Treat st_info as a raw integer field */ 12435088Sab196087 uchar_t st_info = 12445088Sab196087 elfedit_atoui(argstate->argv[1], NULL); 12455088Sab196087 12465088Sab196087 if (sym->st_info == st_info) { 12475088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12485088Sab196087 MSG_INTL(MSG_DEBUG_D_OK), 12495088Sab196087 symstate->sym.sec->sec_shndx, 12505088Sab196087 symstate->sym.sec->sec_name, 12515088Sab196087 EC_WORD(symstate->ndx), 12525088Sab196087 MSG_ORIG(MSG_CMD_ST_INFO), 12535088Sab196087 EC_WORD(sym->st_info)); 12545088Sab196087 } else { 12555088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12565088Sab196087 MSG_INTL(MSG_DEBUG_D_CHG), 12575088Sab196087 symstate->sym.sec->sec_shndx, 12585088Sab196087 symstate->sym.sec->sec_name, 12595088Sab196087 EC_WORD(symstate->ndx), 12605088Sab196087 MSG_ORIG(MSG_CMD_ST_INFO), 12615088Sab196087 EC_WORD(sym->st_info), EC_WORD(st_info)); 12625088Sab196087 ret = ELFEDIT_CMDRET_MOD; 12635088Sab196087 sym->st_info = st_info; 12645088Sab196087 } 12655088Sab196087 } 12665088Sab196087 break; 12675088Sab196087 12685088Sab196087 case SYM_CMD_T_ST_NAME: 12695088Sab196087 ret = cmd_body_set_st_name(argstate, symstate); 12705088Sab196087 break; 12715088Sab196087 12725088Sab196087 case SYM_CMD_T_ST_OTHER: 12735088Sab196087 { 12745088Sab196087 /* Treat st_other as a raw integer field */ 12755088Sab196087 uchar_t st_other = 12765088Sab196087 elfedit_atoui(argstate->argv[1], NULL); 12775088Sab196087 12785088Sab196087 if (sym->st_other == st_other) { 12795088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12805088Sab196087 MSG_INTL(MSG_DEBUG_D_OK), 12815088Sab196087 symstate->sym.sec->sec_shndx, 12825088Sab196087 symstate->sym.sec->sec_name, 12835088Sab196087 EC_WORD(symstate->ndx), 12845088Sab196087 MSG_ORIG(MSG_CMD_ST_OTHER), 12855088Sab196087 EC_WORD(sym->st_other)); 12865088Sab196087 } else { 12875088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12885088Sab196087 MSG_INTL(MSG_DEBUG_D_CHG), 12895088Sab196087 symstate->sym.sec->sec_shndx, 12905088Sab196087 symstate->sym.sec->sec_name, 12915088Sab196087 EC_WORD(symstate->ndx), 12925088Sab196087 MSG_ORIG(MSG_CMD_ST_OTHER), 12935088Sab196087 EC_WORD(sym->st_other), EC_WORD(st_other)); 12945088Sab196087 ret = ELFEDIT_CMDRET_MOD; 12955088Sab196087 sym->st_other = st_other; 12965088Sab196087 } 12975088Sab196087 } 12985088Sab196087 break; 12995088Sab196087 13005088Sab196087 case SYM_CMD_T_ST_SHNDX: 13015088Sab196087 ret = cmd_body_set_st_shndx(argstate, symstate); 13025088Sab196087 break; 13035088Sab196087 13045088Sab196087 case SYM_CMD_T_ST_SIZE: 13055088Sab196087 { 13065088Sab196087 Xword st_size = elfedit_atoui(argstate->argv[1], NULL); 13075088Sab196087 13085088Sab196087 if (sym->st_size == st_size) { 13095088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13105088Sab196087 MSG_INTL(MSG_DEBUG_LLX_OK), 13115088Sab196087 symstate->sym.sec->sec_shndx, 13125088Sab196087 symstate->sym.sec->sec_name, 13135088Sab196087 EC_WORD(symstate->ndx), 13145088Sab196087 MSG_ORIG(MSG_CMD_ST_SIZE), 13155088Sab196087 EC_XWORD(sym->st_size)); 13165088Sab196087 } else { 13175088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13185088Sab196087 MSG_INTL(MSG_DEBUG_LLX_CHG), 13195088Sab196087 symstate->sym.sec->sec_shndx, 13205088Sab196087 symstate->sym.sec->sec_name, 13215088Sab196087 EC_WORD(symstate->ndx), 13225088Sab196087 MSG_ORIG(MSG_CMD_ST_SIZE), 13235088Sab196087 EC_XWORD(sym->st_size), EC_XWORD(st_size)); 13245088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13255088Sab196087 sym->st_size = st_size; 13265088Sab196087 } 13275088Sab196087 } 13285088Sab196087 break; 13295088Sab196087 13305088Sab196087 case SYM_CMD_T_ST_TYPE: 13315088Sab196087 ret = cmd_body_set_st_type(argstate, symstate); 13325088Sab196087 break; 13335088Sab196087 13345088Sab196087 case SYM_CMD_T_ST_VALUE: 13355088Sab196087 { 13365088Sab196087 Addr st_value = elfedit_atoui(argstate->argv[1], NULL); 13375088Sab196087 13385088Sab196087 if (sym->st_value == st_value) { 13395088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13405088Sab196087 MSG_INTL(MSG_DEBUG_LLX_OK), 13415088Sab196087 symstate->sym.sec->sec_shndx, 13425088Sab196087 symstate->sym.sec->sec_name, 13435088Sab196087 EC_WORD(symstate->ndx), 13445088Sab196087 MSG_ORIG(MSG_CMD_ST_VALUE), 13455088Sab196087 EC_ADDR(sym->st_value)); 13465088Sab196087 } else { 13475088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13485088Sab196087 MSG_INTL(MSG_DEBUG_LLX_CHG), 13495088Sab196087 symstate->sym.sec->sec_shndx, 13505088Sab196087 symstate->sym.sec->sec_name, 13515088Sab196087 EC_WORD(symstate->ndx), 13525088Sab196087 MSG_ORIG(MSG_CMD_ST_VALUE), 13535088Sab196087 EC_ADDR(sym->st_value), 13545088Sab196087 EC_ADDR(st_value)); 13555088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13565088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13575088Sab196087 sym->st_value = st_value; 13585088Sab196087 } 13595088Sab196087 } 13605088Sab196087 break; 13615088Sab196087 13625088Sab196087 case SYM_CMD_T_ST_VISIBILITY: 13635088Sab196087 ret = cmd_body_set_st_visibility(argstate, symstate); 13645088Sab196087 break; 13655088Sab196087 } 13665088Sab196087 13675088Sab196087 /* 13685088Sab196087 * If we modified the symbol table, tell libelf. 13695088Sab196087 * Any other modified sections are the responsibility 13705088Sab196087 * of the cmd_body_set_st_*() function that did it, but 13715088Sab196087 * everyone modifies the table itself, so we handle that here. 13725088Sab196087 */ 13735088Sab196087 if (ret == ELFEDIT_CMDRET_MOD) 13745088Sab196087 elfedit_modified_data(symstate->sym.sec); 13755088Sab196087 13765088Sab196087 return (ret); 13775088Sab196087 } 13785088Sab196087 13795088Sab196087 13805088Sab196087 13815088Sab196087 13825088Sab196087 /* 13835088Sab196087 * Common body for the sym: module commands. These commands 13845088Sab196087 * share a large amount of common behavior, so it is convenient 13855088Sab196087 * to centralize things and use the cmd argument to handle the 13865088Sab196087 * small differences. 13875088Sab196087 * 13885088Sab196087 * entry: 13895088Sab196087 * cmd - One of the SYM_CMD_T_* constants listed above, specifying 13905088Sab196087 * which command to implement. 13915088Sab196087 * obj_state, argc, argv - Standard command arguments 13925088Sab196087 */ 13935088Sab196087 static elfedit_cmdret_t 13945088Sab196087 cmd_body(SYM_CMD_T cmd, elfedit_obj_state_t *obj_state, 13955088Sab196087 int argc, const char *argv[]) 13965088Sab196087 { 13975088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 13985088Sab196087 ARGSTATE *argstate; 13995088Sab196087 SYMSTATE *symstate; 14005088Sab196087 Word tblndx; 14015088Sab196087 14025088Sab196087 argstate = process_args(obj_state, argc, argv, cmd); 14035088Sab196087 14045088Sab196087 /* 14055088Sab196087 * If there are not 2 arguments, then this is a display request. 14065088Sab196087 * If no arguments are present, the full table (or tables) is 14075088Sab196087 * dumped. If there is one argument, then the specified item is shown. 14085088Sab196087 */ 14095088Sab196087 if (argstate->argc < 2) { 14105088Sab196087 print_sym(cmd, 0, argstate); 14115088Sab196087 return (ELFEDIT_CMDRET_NONE); 14125088Sab196087 } 14135088Sab196087 14145088Sab196087 /* 14155088Sab196087 * When processing multiple symbol tables, it is important that 14165088Sab196087 * any failure happen before anything is changed. Otherwise, you 14175088Sab196087 * can end up in a situation where things are left in an inconsistent 14185088Sab196087 * half done state. sym:st_name has that issue when the -name_offset 14195088Sab196087 * option is used, because the string may be insertable into some 14205088Sab196087 * (dynstr) string tables, but not all of them. So, do the tests 14215088Sab196087 * up front, and refuse to continue if any string insertions would 14225088Sab196087 * fail. 14235088Sab196087 */ 14245088Sab196087 if ((cmd == SYM_CMD_T_ST_NAME) && (argstate->numsymstate > 1) && 14255088Sab196087 ((argstate->optmask & SYM_OPT_F_NAMOFFSET) == 0)) { 14265088Sab196087 symstate = argstate->symstate; 14275088Sab196087 for (tblndx = 0; tblndx < argstate->numsymstate; 14285088Sab196087 tblndx++, symstate++) 14295088Sab196087 elfedit_strtab_insert_test(obj_state, symstate->str.sec, 14305088Sab196087 NULL, argstate->argv[1]); 14315088Sab196087 } 14325088Sab196087 14335088Sab196087 14345088Sab196087 /* Loop over the table(s) and make the specified value change */ 14355088Sab196087 symstate = argstate->symstate; 14365088Sab196087 for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) 14375088Sab196087 if (symstate_cmd_body(cmd, argstate, symstate) == 14385088Sab196087 ELFEDIT_CMDRET_MOD) 14395088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14405088Sab196087 14415088Sab196087 /* Do autoprint */ 14425088Sab196087 print_sym(cmd, 1, argstate); 14435088Sab196087 14445088Sab196087 return (ret); 14455088Sab196087 } 14465088Sab196087 14475088Sab196087 14485088Sab196087 14495088Sab196087 14505088Sab196087 /* 14515088Sab196087 * Command completion functions for the various commands 14525088Sab196087 */ 14535088Sab196087 14545088Sab196087 /* 14555088Sab196087 * Handle filling in the values for -shnam, -shndx, and -shtyp options. 14565088Sab196087 */ 14575088Sab196087 /*ARGSUSED*/ 14585088Sab196087 static void 14595088Sab196087 cpl_sh_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 14605088Sab196087 const char *argv[], int num_opt) 14615088Sab196087 { 14625088Sab196087 enum { NAME, INDEX, TYPE } op; 14635088Sab196087 elfedit_symtab_t *symtab; 14645088Sab196087 Word tblndx; 14655088Sab196087 14665088Sab196087 if ((argc != num_opt) || (argc < 2)) 14675088Sab196087 return; 14685088Sab196087 14695088Sab196087 if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) { 14705088Sab196087 op = NAME; 14715088Sab196087 } else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) { 14725088Sab196087 op = INDEX; 14735088Sab196087 14745088Sab196087 } else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) { 14755088Sab196087 op = TYPE; 14765088Sab196087 if (obj_state == NULL) /* No object available */ 14775088Sab196087 elfedit_cpl_atoconst(cpldata, 14785088Sab196087 ELFEDIT_CONST_SHT_ALLSYMTAB); 14795088Sab196087 } else { 14805088Sab196087 return; 14815088Sab196087 } 14825088Sab196087 14835088Sab196087 if (obj_state == NULL) /* No object available */ 14845088Sab196087 return; 14855088Sab196087 14865088Sab196087 /* 14875088Sab196087 * Loop over the symbol tables and supply command completion 14885088Sab196087 * for the items in the file. 14895088Sab196087 */ 14905088Sab196087 symtab = obj_state->os_symtab; 14915088Sab196087 for (tblndx = 0; tblndx < obj_state->os_symtabnum; 14925088Sab196087 tblndx++, symtab++) { 14935088Sab196087 elfedit_section_t *sec = 14945088Sab196087 &obj_state->os_secarr[symtab->symt_shndx]; 14955088Sab196087 14965088Sab196087 switch (op) { 14975088Sab196087 case NAME: 14985088Sab196087 elfedit_cpl_match(cpldata, sec->sec_name, 0); 14995088Sab196087 break; 15005088Sab196087 case INDEX: 15015088Sab196087 { 15025088Sab196087 char index[MAXNDXSIZE]; 15035088Sab196087 15045088Sab196087 (void) snprintf(index, sizeof (index), 15055088Sab196087 MSG_ORIG(MSG_FMT_WORDVAL), 15065088Sab196087 symtab->symt_shndx); 15075088Sab196087 elfedit_cpl_match(cpldata, index, 1); 15085088Sab196087 } 15095088Sab196087 break; 15105088Sab196087 case TYPE: 15115088Sab196087 { 15125088Sab196087 elfedit_atoui_sym_t *cpl_list; 15135088Sab196087 15145088Sab196087 (void) elfedit_sec_issymtab(sec, 1, &cpl_list); 15155088Sab196087 elfedit_cpl_atoui(cpldata, cpl_list); 15165088Sab196087 } 15175088Sab196087 break; 15185088Sab196087 } 15195088Sab196087 } 15205088Sab196087 } 15215088Sab196087 15225088Sab196087 /*ARGSUSED*/ 15235088Sab196087 static void 15245088Sab196087 cpl_st_bind(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 15255088Sab196087 const char *argv[], int num_opt) 15265088Sab196087 { 15275088Sab196087 /* Handle -shXXX options */ 15285088Sab196087 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 15295088Sab196087 15305088Sab196087 /* The second argument can be an STB_ value */ 15315088Sab196087 if (argc == (num_opt + 2)) 15325088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STB); 15335088Sab196087 } 15345088Sab196087 15355088Sab196087 /*ARGSUSED*/ 15365088Sab196087 static void 15375088Sab196087 cpl_st_shndx(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 15385088Sab196087 const char *argv[], int num_opt) 15395088Sab196087 { 15405088Sab196087 elfedit_section_t *sec; 15415088Sab196087 enum { NAME, INDEX, TYPE } op; 15425088Sab196087 Word ndx; 15435088Sab196087 15445088Sab196087 /* Handle -shXXX options */ 15455088Sab196087 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 15465088Sab196087 15475088Sab196087 /* 15485088Sab196087 * The second argument can be a section name, a section 15495088Sab196087 * index (-secshndx), or a section type (-secshtyp). We 15505088Sab196087 * can do completions for each of these. 15515088Sab196087 */ 15525088Sab196087 if (argc != (num_opt + 2)) 15535088Sab196087 return; 15545088Sab196087 15555088Sab196087 op = NAME; 15565088Sab196087 for (ndx = 0; ndx < num_opt; ndx++) { 15575088Sab196087 if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SECSHNDX)) == 0) 15585088Sab196087 op = INDEX; 15595088Sab196087 else if (strcmp(argv[ndx], 15605088Sab196087 MSG_ORIG(MSG_STR_MINUS_SECSHTYP)) == 0) 15615088Sab196087 op = TYPE; 15625088Sab196087 } 15635088Sab196087 15645088Sab196087 switch (op) { 15655088Sab196087 case NAME: 15665088Sab196087 if (obj_state == NULL) 15675088Sab196087 break; 15685088Sab196087 sec = obj_state->os_secarr; 15695088Sab196087 for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++) 15705088Sab196087 elfedit_cpl_match(cpldata, sec->sec_name, 0); 15715088Sab196087 break; 15725088Sab196087 15735088Sab196087 case INDEX: 15745088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHN); 15755088Sab196087 break; 15765088Sab196087 15775088Sab196087 case TYPE: 15785088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT); 15795088Sab196087 break; 15805088Sab196087 } 15815088Sab196087 } 15825088Sab196087 15835088Sab196087 /*ARGSUSED*/ 15845088Sab196087 static void 15855088Sab196087 cpl_st_type(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 15865088Sab196087 const char *argv[], int num_opt) 15875088Sab196087 { 15885088Sab196087 /* Handle -shXXX options */ 15895088Sab196087 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 15905088Sab196087 15915088Sab196087 /* The second argument can be an STT_ value */ 15925088Sab196087 if (argc == (num_opt + 2)) 15935088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STT); 15945088Sab196087 } 15955088Sab196087 15965088Sab196087 /*ARGSUSED*/ 15975088Sab196087 static void 15985088Sab196087 cpl_st_visibility(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 15995088Sab196087 const char *argv[], int num_opt) 16005088Sab196087 { 16015088Sab196087 /* Handle -shXXX options */ 16025088Sab196087 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 16035088Sab196087 16045088Sab196087 /* The second argument can be an STV_ value */ 16055088Sab196087 if (argc == (num_opt + 2)) 16065088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STV); 16075088Sab196087 } 16085088Sab196087 16095088Sab196087 16105088Sab196087 16115088Sab196087 /* 16125088Sab196087 * Implementation functions for the commands 16135088Sab196087 */ 16145088Sab196087 static elfedit_cmdret_t 16155088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 16165088Sab196087 { 16175088Sab196087 return (cmd_body(SYM_CMD_T_DUMP, obj_state, argc, argv)); 16185088Sab196087 } 16195088Sab196087 16205088Sab196087 16215088Sab196087 static elfedit_cmdret_t 16225088Sab196087 cmd_st_bind(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 16235088Sab196087 { 16245088Sab196087 return (cmd_body(SYM_CMD_T_ST_BIND, obj_state, argc, argv)); 16255088Sab196087 } 16265088Sab196087 16275088Sab196087 16285088Sab196087 static elfedit_cmdret_t 16295088Sab196087 cmd_st_info(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 16305088Sab196087 { 16315088Sab196087 return (cmd_body(SYM_CMD_T_ST_INFO, obj_state, argc, argv)); 16325088Sab196087 } 16335088Sab196087 16345088Sab196087 static elfedit_cmdret_t 16355088Sab196087 cmd_st_name(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 16365088Sab196087 { 16375088Sab196087 return (cmd_body(SYM_CMD_T_ST_NAME, obj_state, argc, argv)); 16385088Sab196087 } 16395088Sab196087 16405088Sab196087 static elfedit_cmdret_t 16415088Sab196087 cmd_st_other(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 16425088Sab196087 { 16435088Sab196087 return (cmd_body(SYM_CMD_T_ST_OTHER, obj_state, argc, argv)); 16445088Sab196087 } 16455088Sab196087 16465088Sab196087 static elfedit_cmdret_t 16475088Sab196087 cmd_st_shndx(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 16485088Sab196087 { 16495088Sab196087 return (cmd_body(SYM_CMD_T_ST_SHNDX, obj_state, argc, argv)); 16505088Sab196087 } 16515088Sab196087 16525088Sab196087 static elfedit_cmdret_t 16535088Sab196087 cmd_st_size(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 16545088Sab196087 { 16555088Sab196087 return (cmd_body(SYM_CMD_T_ST_SIZE, obj_state, argc, argv)); 16565088Sab196087 } 16575088Sab196087 16585088Sab196087 static elfedit_cmdret_t 16595088Sab196087 cmd_st_type(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 16605088Sab196087 { 16615088Sab196087 return (cmd_body(SYM_CMD_T_ST_TYPE, obj_state, argc, argv)); 16625088Sab196087 } 16635088Sab196087 16645088Sab196087 static elfedit_cmdret_t 16655088Sab196087 cmd_st_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 16665088Sab196087 { 16675088Sab196087 return (cmd_body(SYM_CMD_T_ST_VALUE, obj_state, argc, argv)); 16685088Sab196087 } 16695088Sab196087 16705088Sab196087 static elfedit_cmdret_t 16715088Sab196087 cmd_st_visibility(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 16725088Sab196087 { 16735088Sab196087 return (cmd_body(SYM_CMD_T_ST_VISIBILITY, obj_state, argc, argv)); 16745088Sab196087 } 16755088Sab196087 16765088Sab196087 16775088Sab196087 16785088Sab196087 /*ARGSUSED*/ 16795088Sab196087 elfedit_module_t * 16805088Sab196087 elfedit_init(elfedit_module_version_t version) 16815088Sab196087 { 16825088Sab196087 /* Multiple commands accept only the standard set of options */ 16835088Sab196087 static elfedit_cmd_optarg_t opt_std[] = { 16845088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 16855088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 16865088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 16875088Sab196087 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 16885088Sab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0 }, 16895088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 16905088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 16915088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 16925088Sab196087 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 16935088Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 }, 16945088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 16955088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 16965088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 16975088Sab196087 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 16985088Sab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 }, 16995088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 17005088Sab196087 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 17015088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, SYM_OPT_F_SYMNDX }, 17025088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 17035088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0 }, 17045088Sab196087 { NULL } 17055088Sab196087 }; 17065088Sab196087 17075088Sab196087 /* sym:dump */ 17085088Sab196087 static const char *name_dump[] = { 17095088Sab196087 MSG_ORIG(MSG_CMD_DUMP), 17105088Sab196087 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 17115088Sab196087 NULL 17125088Sab196087 }; 17135088Sab196087 static elfedit_cmd_optarg_t opt_dump[] = { 17145088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 17155088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 17165088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 17175088Sab196087 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 17185088Sab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0 }, 17195088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 17205088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 17215088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 17225088Sab196087 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 17235088Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 }, 17245088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 17255088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 17265088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 17275088Sab196087 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 17285088Sab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 }, 17295088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 17305088Sab196087 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 17315088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, SYM_OPT_F_SYMNDX }, 17325088Sab196087 { NULL } 17335088Sab196087 }; 17345088Sab196087 static elfedit_cmd_optarg_t arg_dump[] = { 17355088Sab196087 { MSG_ORIG(MSG_STR_SYM), 17365088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 17375088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 17385088Sab196087 ELFEDIT_CMDOA_F_OPT }, 17395088Sab196087 { NULL } 17405088Sab196087 }; 17415088Sab196087 17425088Sab196087 /* sym:st_bind */ 17435088Sab196087 static const char *name_st_bind[] = { 17445088Sab196087 MSG_ORIG(MSG_CMD_ST_BIND), NULL }; 17455088Sab196087 static elfedit_cmd_optarg_t arg_st_bind[] = { 17465088Sab196087 { MSG_ORIG(MSG_STR_SYM), 17475088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 17485088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 17495088Sab196087 ELFEDIT_CMDOA_F_OPT }, 17505088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 17515088Sab196087 /* MSG_INTL(MSG_A2_DESC_ST_BIND) */ 17525088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_BIND), 17535088Sab196087 ELFEDIT_CMDOA_F_OPT }, 17545088Sab196087 { NULL } 17555088Sab196087 }; 17565088Sab196087 17575088Sab196087 /* sym:st_info */ 17585088Sab196087 static const char *name_st_info[] = { 17595088Sab196087 MSG_ORIG(MSG_CMD_ST_INFO), NULL }; 17605088Sab196087 static elfedit_cmd_optarg_t arg_st_info[] = { 17615088Sab196087 { MSG_ORIG(MSG_STR_SYM), 17625088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 17635088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 17645088Sab196087 ELFEDIT_CMDOA_F_OPT }, 17655088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 17665088Sab196087 /* MSG_INTL(MSG_A2_DESC_ST_INFO) */ 17675088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_INFO), 17685088Sab196087 ELFEDIT_CMDOA_F_OPT }, 17695088Sab196087 { NULL } 17705088Sab196087 }; 17715088Sab196087 17725088Sab196087 /* sym:st_name */ 17735088Sab196087 static const char *name_st_name[] = { 17745088Sab196087 MSG_ORIG(MSG_CMD_ST_NAME), NULL }; 17755088Sab196087 static elfedit_cmd_optarg_t opt_st_name[] = { 17765088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 17775088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 17785088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 17795088Sab196087 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 17805088Sab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0, 0 }, 17815088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 17825088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 17835088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 17845088Sab196087 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 17855088Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 17865088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 17875088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 17885088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 17895088Sab196087 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 17905088Sab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0, 0 }, 17915088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 17925088Sab196087 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 17935088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, 17945088Sab196087 SYM_OPT_F_SYMNDX, 0 }, 17955088Sab196087 { MSG_ORIG(MSG_STR_MINUS_NAME_OFFSET), 17965088Sab196087 /* MSG_INTL(MSG_OPTDESC_NAME_OFFSET) */ 17975088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_NAME_OFFSET), 0, 17985088Sab196087 SYM_OPT_F_NAMOFFSET, 0 }, 17995088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18005088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18015088Sab196087 { NULL } 18025088Sab196087 }; 18035088Sab196087 static elfedit_cmd_optarg_t arg_st_name[] = { 18045088Sab196087 { MSG_ORIG(MSG_STR_SYM), 18055088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 18065088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 18075088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18085088Sab196087 { MSG_ORIG(MSG_STR_NAME), 18095088Sab196087 /* MSG_INTL(MSG_A2_DESC_ST_NAME) */ 18105088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_NAME), 18115088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18125088Sab196087 { NULL } 18135088Sab196087 }; 18145088Sab196087 18155088Sab196087 /* sym:st_other */ 18165088Sab196087 static const char *name_st_other[] = { 18175088Sab196087 MSG_ORIG(MSG_CMD_ST_OTHER), NULL }; 18185088Sab196087 static elfedit_cmd_optarg_t arg_st_other[] = { 18195088Sab196087 { MSG_ORIG(MSG_STR_SYM), 18205088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 18215088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 18225088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18235088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 18245088Sab196087 /* MSG_INTL(MSG_A2_DESC_ST_OTHER) */ 18255088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_OTHER), 18265088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18275088Sab196087 { NULL } 18285088Sab196087 }; 18295088Sab196087 18305088Sab196087 /* sym:st_shndx */ 18315088Sab196087 static const char *name_st_shndx[] = { 18325088Sab196087 MSG_ORIG(MSG_CMD_ST_SHNDX), NULL }; 18335088Sab196087 static elfedit_cmd_optarg_t opt_st_shndx[] = { 18345088Sab196087 { MSG_ORIG(MSG_STR_MINUS_E), 18355088Sab196087 /* MSG_INTL(MSG_OPTDESC_E) */ 18365088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_E), 0, SYM_OPT_F_XSHINDEX, 0 }, 18375088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 18385088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 18395088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 18405088Sab196087 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 18415088Sab196087 { MSG_ORIG(MSG_STR_NAME), NULL, 0, 0 }, 18425088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 18435088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 18445088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 18455088Sab196087 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 18465088Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 18475088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 18485088Sab196087 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 18495088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 18505088Sab196087 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 18515088Sab196087 { MSG_ORIG(MSG_STR_TYPE), NULL, 0, 0 }, 18525088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 18535088Sab196087 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 18545088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, 18555088Sab196087 SYM_OPT_F_SYMNDX, 0 }, 18565088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18575088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18585088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SECSHNDX), 18595088Sab196087 /* MSG_INTL(MSG_OPTDESC_SECSHNDX) */ 18605088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SECSHNDX), 18615088Sab196087 0, SYM_OPT_F_SECSHNDX, SYM_OPT_F_SECSHTYP }, 18625088Sab196087 { MSG_ORIG(MSG_STR_MINUS_SECSHTYP), 18635088Sab196087 /* MSG_INTL(MSG_OPTDESC_SECSHTYP) */ 18645088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_SECSHTYP), 18655088Sab196087 0, SYM_OPT_F_SECSHTYP, SYM_OPT_F_SECSHNDX }, 18665088Sab196087 { NULL } 18675088Sab196087 }; 18685088Sab196087 static elfedit_cmd_optarg_t arg_st_shndx[] = { 18695088Sab196087 { MSG_ORIG(MSG_STR_SYM), 18705088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 18715088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 18725088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18735088Sab196087 { MSG_ORIG(MSG_STR_SEC), 18745088Sab196087 /* MSG_INTL(MSG_A2_DESC_ST_SEC) */ 18755088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_SEC), 18765088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18775088Sab196087 { NULL } 18785088Sab196087 }; 18795088Sab196087 18805088Sab196087 /* sym:st_size */ 18815088Sab196087 static const char *name_st_size[] = { 18825088Sab196087 MSG_ORIG(MSG_CMD_ST_SIZE), NULL }; 18835088Sab196087 static elfedit_cmd_optarg_t arg_st_size[] = { 18845088Sab196087 { MSG_ORIG(MSG_STR_SYM), 18855088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 18865088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 18875088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18885088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 18895088Sab196087 /* MSG_INTL(MSG_A2_DESC_ST_SIZE) */ 18905088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_SIZE), 18915088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18925088Sab196087 { NULL } 18935088Sab196087 }; 18945088Sab196087 18955088Sab196087 /* sym:st_type */ 18965088Sab196087 static const char *name_st_type[] = { 18975088Sab196087 MSG_ORIG(MSG_CMD_ST_TYPE), NULL }; 18985088Sab196087 static elfedit_cmd_optarg_t arg_st_type[] = { 18995088Sab196087 { MSG_ORIG(MSG_STR_SYM), 19005088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 19015088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 19025088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19035088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19045088Sab196087 /* MSG_INTL(MSG_A2_DESC_ST_TYPE) */ 19055088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_TYPE), 19065088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19075088Sab196087 { NULL } 19085088Sab196087 }; 19095088Sab196087 19105088Sab196087 /* sym:st_value */ 19115088Sab196087 static const char *name_st_value[] = { 19125088Sab196087 MSG_ORIG(MSG_CMD_ST_VALUE), NULL }; 19135088Sab196087 static elfedit_cmd_optarg_t arg_st_value[] = { 19145088Sab196087 { MSG_ORIG(MSG_STR_SYM), 19155088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 19165088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 19175088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19185088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19195088Sab196087 /* MSG_INTL(MSG_A2_DESC_ST_VALUE) */ 19205088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_VALUE), 19215088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19225088Sab196087 { NULL } 19235088Sab196087 }; 19245088Sab196087 19255088Sab196087 /* sym:st_visibility */ 19265088Sab196087 static const char *name_st_visibility[] = { 19275088Sab196087 MSG_ORIG(MSG_CMD_ST_VISIBILITY), NULL }; 19285088Sab196087 static elfedit_cmd_optarg_t arg_st_visibility[] = { 19295088Sab196087 { MSG_ORIG(MSG_STR_SYM), 19305088Sab196087 /* MSG_INTL(MSG_A1_SYM) */ 19315088Sab196087 ELFEDIT_I18NHDL(MSG_A1_SYM), 19325088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19335088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19345088Sab196087 /* MSG_INTL(MSG_A2_DESC_ST_VISIBILITY) */ 19355088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_VISIBILITY), 19365088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19375088Sab196087 { NULL } 19385088Sab196087 }; 19395088Sab196087 19405088Sab196087 static elfedit_cmd_t cmds[] = { 19415088Sab196087 /* sym:dump */ 19425088Sab196087 { cmd_dump, cpl_sh_opt, name_dump, 19435088Sab196087 /* MSG_INTL(MSG_DESC_DUMP) */ 19445088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 19455088Sab196087 /* MSG_INTL(MSG_HELP_DUMP) */ 19465088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 19475088Sab196087 opt_dump, arg_dump }, 19485088Sab196087 19495088Sab196087 /* sym:st_bind */ 19505088Sab196087 { cmd_st_bind, cpl_st_bind, name_st_bind, 19515088Sab196087 /* MSG_INTL(MSG_DESC_ST_BIND) */ 19525088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ST_BIND), 19535088Sab196087 /* MSG_INTL(MSG_HELP_ST_BIND) */ 19545088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ST_BIND), 19555088Sab196087 opt_std, arg_st_bind }, 19565088Sab196087 19575088Sab196087 /* sym:st_info */ 19585088Sab196087 { cmd_st_info, cpl_sh_opt, name_st_info, 19595088Sab196087 /* MSG_INTL(MSG_DESC_ST_INFO) */ 19605088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ST_INFO), 19615088Sab196087 /* MSG_INTL(MSG_HELP_ST_INFO) */ 19625088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ST_INFO), 19635088Sab196087 opt_std, arg_st_info }, 19645088Sab196087 19655088Sab196087 /* sym:st_name */ 19665088Sab196087 { cmd_st_name, cpl_sh_opt, name_st_name, 19675088Sab196087 /* MSG_INTL(MSG_DESC_ST_NAME) */ 19685088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ST_NAME), 19695088Sab196087 /* MSG_INTL(MSG_HELP_ST_NAME) */ 19705088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ST_NAME), 19715088Sab196087 opt_st_name, arg_st_name }, 19725088Sab196087 19735088Sab196087 /* sym:st_other */ 19745088Sab196087 { cmd_st_other, cpl_sh_opt, name_st_other, 19755088Sab196087 /* MSG_INTL(MSG_DESC_ST_OTHER) */ 19765088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ST_OTHER), 19775088Sab196087 /* MSG_INTL(MSG_HELP_ST_OTHER) */ 19785088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ST_OTHER), 19795088Sab196087 opt_std, arg_st_other }, 19805088Sab196087 19815088Sab196087 /* sym:st_shndx */ 19825088Sab196087 { cmd_st_shndx, cpl_st_shndx, name_st_shndx, 19835088Sab196087 /* MSG_INTL(MSG_DESC_ST_SHNDX) */ 19845088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ST_SHNDX), 19855088Sab196087 /* MSG_INTL(MSG_HELP_ST_SHNDX) */ 19865088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ST_SHNDX), 19875088Sab196087 opt_st_shndx, arg_st_shndx }, 19885088Sab196087 19895088Sab196087 /* sym:st_size */ 19905088Sab196087 { cmd_st_size, cpl_sh_opt, name_st_size, 19915088Sab196087 /* MSG_INTL(MSG_DESC_ST_SIZE) */ 19925088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ST_SIZE), 19935088Sab196087 /* MSG_INTL(MSG_HELP_ST_SIZE) */ 19945088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ST_SIZE), 19955088Sab196087 opt_std, arg_st_size }, 19965088Sab196087 19975088Sab196087 /* sym:st_type */ 19985088Sab196087 { cmd_st_type, cpl_st_type, name_st_type, 19995088Sab196087 /* MSG_INTL(MSG_DESC_ST_TYPE) */ 20005088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ST_TYPE), 20015088Sab196087 /* MSG_INTL(MSG_HELP_ST_TYPE) */ 20025088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ST_TYPE), 20035088Sab196087 opt_std, arg_st_type }, 20045088Sab196087 20055088Sab196087 /* sym:st_value */ 20065088Sab196087 { cmd_st_value, cpl_sh_opt, name_st_value, 20075088Sab196087 /* MSG_INTL(MSG_DESC_ST_VALUE) */ 20085088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ST_VALUE), 20095088Sab196087 /* MSG_INTL(MSG_HELP_ST_VALUE) */ 20105088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ST_VALUE), 20115088Sab196087 opt_std, arg_st_value }, 20125088Sab196087 20135088Sab196087 /* sym:st_visibility */ 20145088Sab196087 { cmd_st_visibility, cpl_st_visibility, name_st_visibility, 20155088Sab196087 /* MSG_INTL(MSG_DESC_ST_VISIBILITY) */ 20165088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_ST_VISIBILITY), 20175088Sab196087 /* MSG_INTL(MSG_HELP_ST_VISIBILITY) */ 20185088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_ST_VISIBILITY), 20195088Sab196087 opt_std, arg_st_visibility }, 20205088Sab196087 20215088Sab196087 { NULL } 20225088Sab196087 }; 20235088Sab196087 20245088Sab196087 static elfedit_module_t module = { 20255088Sab196087 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 20265088Sab196087 /* MSG_INTL(MSG_MOD_DESC) */ 20275088Sab196087 ELFEDIT_I18NHDL(MSG_MOD_DESC), 20285088Sab196087 cmds, mod_i18nhdl_to_str }; 20295088Sab196087 20305088Sab196087 return (&module); 20315088Sab196087 } 2032