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 /* 236206Sab196087 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 245088Sab196087 * Use is subject to license terms. 255088Sab196087 */ 265088Sab196087 275088Sab196087 #include <ctype.h> 285088Sab196087 #include <elfedit.h> 295088Sab196087 #include <sys/elf_SPARC.h> 305088Sab196087 #include <strings.h> 315088Sab196087 #include <debug.h> 325088Sab196087 #include <conv.h> 335088Sab196087 #include <dyn_msg.h> 345088Sab196087 355088Sab196087 365088Sab196087 /* 375088Sab196087 * Dynamic section 385088Sab196087 */ 395088Sab196087 405088Sab196087 415088Sab196087 425088Sab196087 435088Sab196087 /* 445088Sab196087 * This module uses shared code for several of the commands. 455088Sab196087 * It is sometimes necessary to know which specific command 465088Sab196087 * is active. 475088Sab196087 */ 485088Sab196087 typedef enum { 495088Sab196087 /* Dump command, used as module default to display dynamic section */ 505088Sab196087 DYN_CMD_T_DUMP = 0, /* dyn:dump */ 515088Sab196087 525088Sab196087 /* Commands that do not correspond directly to a specific DT tag */ 535088Sab196087 DYN_CMD_T_TAG = 1, /* dyn:tag */ 545088Sab196087 DYN_CMD_T_VALUE = 2, /* dyn:value */ 555088Sab196087 DYN_CMD_T_DELETE = 3, /* dyn:delete */ 565088Sab196087 DYN_CMD_T_MOVE = 4, /* dyn:shift */ 575088Sab196087 585088Sab196087 /* Commands that embody tag specific knowledge */ 595088Sab196087 DYN_CMD_T_RUNPATH = 5, /* dyn:runpath/rpath */ 605088Sab196087 DYN_CMD_T_POSFLAG1 = 6, /* dyn:posflag1 */ 615088Sab196087 DYN_CMD_T_FLAGS = 7, /* dyn:flags */ 625088Sab196087 DYN_CMD_T_FLAGS1 = 8, /* dyn:flags1 */ 635088Sab196087 DYN_CMD_T_FEATURE1 = 9, /* dyn:feature1 */ 646206Sab196087 DYN_CMD_T_CHECKSUM = 10, /* dyn:checksum */ 656206Sab196087 DYN_CMD_T_SUNW_LDMACH = 11 /* dyn:sunw_ldmach */ 665088Sab196087 } DYN_CMD_T; 675088Sab196087 685088Sab196087 695088Sab196087 705088Sab196087 #ifndef _ELF64 715088Sab196087 /* 725088Sab196087 * We supply this function for the msg module 735088Sab196087 */ 745088Sab196087 const char * 755088Sab196087 _dyn_msg(Msg mid) 765088Sab196087 { 775088Sab196087 return (gettext(MSG_ORIG(mid))); 785088Sab196087 } 795088Sab196087 #endif 805088Sab196087 815088Sab196087 825088Sab196087 /* 835088Sab196087 * This function is supplied to elfedit through our elfedit_module_t 845088Sab196087 * definition. It translates the opaque elfedit_i18nhdl_t handles 855088Sab196087 * in our module interface into the actual strings for elfedit to 865088Sab196087 * use. 875088Sab196087 * 885088Sab196087 * note: 895088Sab196087 * This module uses Msg codes for its i18n handle type. 905088Sab196087 * So the translation is simply to use MSG_INTL() to turn 915088Sab196087 * it into a string and return it. 925088Sab196087 */ 935088Sab196087 static const char * 945088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 955088Sab196087 { 965088Sab196087 Msg msg = (Msg)hdl; 975088Sab196087 985088Sab196087 return (MSG_INTL(msg)); 995088Sab196087 } 1005088Sab196087 1015088Sab196087 1025088Sab196087 1035088Sab196087 /* 1045088Sab196087 * The dyn_opt_t enum specifies a bit value for every optional 1055088Sab196087 * argument allowed by a command in this module. 1065088Sab196087 */ 1075088Sab196087 typedef enum { 1085088Sab196087 DYN_OPT_F_ADD = 1, /* -add: Add new elt rather than */ 1095088Sab196087 /* modifying an existing one */ 1105088Sab196087 DYN_OPT_F_AND = 2, /* -and: AND (&) values to dest */ 1115088Sab196087 DYN_OPT_F_CMP = 4, /* -cmp: Complement (~) values */ 1126225Sab196087 DYN_OPT_F_DYNNDX_ELT = 8, /* -dynndx: 1st plain arg is tag */ 1136225Sab196087 /* index, not name */ 1146225Sab196087 DYN_OPT_F_DYNNDX_VAL = 16, /* -dynndx ndx: Index is value to */ 1156225Sab196087 /* option rather than 1st plain */ 1166225Sab196087 /* arg. Used for dyn:posflag1 */ 1176225Sab196087 DYN_OPT_F_NEEDED = 32, /* -needed str: Locate DT_POSFLAG_1 */ 1186225Sab196087 /* relative to DT_NEEDED element */ 1196225Sab196087 DYN_OPT_F_OR = 64, /* -or: OR (|) values to dest */ 1206225Sab196087 DYN_OPT_F_STRVAL = 128 /* -s: value is string, not integer */ 1215088Sab196087 } dyn_opt_t; 1225088Sab196087 1235088Sab196087 1245088Sab196087 /* 1255088Sab196087 * A variable of type ARGSTATE is used by each command to maintain 1265088Sab196087 * information about the arguments and related things. It is 1275088Sab196087 * initialized by process_args(), and used by the other routines. 1285088Sab196087 */ 1295088Sab196087 typedef struct { 1305088Sab196087 elfedit_obj_state_t *obj_state; 1315088Sab196087 elfedit_section_t *strsec; /* Dynamic string table ref */ 1325088Sab196087 struct { 1335088Sab196087 elfedit_section_t *sec; /* Dynamic section reference */ 1345088Sab196087 Dyn *data; /* Start dynamic section data */ 1355088Sab196087 Word num; /* # dynamic elts */ 1365088Sab196087 Word null_ndx; /* Index of first DT_NULL */ 1375088Sab196087 Word num_null_ndx; /* # of DT_NULL elements */ 1385088Sab196087 } dyn; 1395088Sab196087 dyn_opt_t optmask; /* Mask of options used */ 1405088Sab196087 int argc; /* # of plain arguments */ 1415088Sab196087 const char **argv; /* Plain arguments */ 1426225Sab196087 const char *dyn_elt_str; /* Value string for */ 1436225Sab196087 /* DYN_OPT_F_DYNNDX_VAL */ 1446225Sab196087 /* or DYN_OPT_F_NEEDED */ 1455088Sab196087 } ARGSTATE; 1465088Sab196087 1475088Sab196087 1485088Sab196087 1495088Sab196087 /* 1505088Sab196087 * Set argstate null_ndx field for current dynamic area 1515088Sab196087 */ 1525088Sab196087 static void 1535088Sab196087 set_null_ndx(ARGSTATE *argstate) 1545088Sab196087 { 1555088Sab196087 Word num, null_ndx; 1565088Sab196087 1575088Sab196087 num = argstate->dyn.num; 1585088Sab196087 argstate->dyn.num_null_ndx = 0; 1595088Sab196087 for (null_ndx = 0; null_ndx < num; null_ndx++) 1605088Sab196087 if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) { 1615088Sab196087 argstate->dyn.num_null_ndx++; 1625088Sab196087 break; 1635088Sab196087 } 1645088Sab196087 argstate->dyn.null_ndx = null_ndx; 1655088Sab196087 1665088Sab196087 /* Count the number of remaining DT_NULL items */ 1675088Sab196087 for (; null_ndx < num; null_ndx++) 1685088Sab196087 if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) 1695088Sab196087 argstate->dyn.num_null_ndx++; 1705088Sab196087 } 1715088Sab196087 1725088Sab196087 1735088Sab196087 /* 1745088Sab196087 * Convert the first available DT_NULL slot in the dynamic section 1755088Sab196087 * into something else. 1765088Sab196087 * 1775088Sab196087 * entry: 1785088Sab196087 * argstate - Argument state block 1795088Sab196087 * d_tag, d_val - Values to be set in new element 1805088Sab196087 * 1815088Sab196087 * exit: 1825088Sab196087 * If an extra DT_NULL slot is available, a debug message is 1835088Sab196087 * issued, the slot is converted to its new use, and the argstate 1845088Sab196087 * block state related to DT_NULL slots is updated. 1855088Sab196087 * 1865088Sab196087 * if no extra DT_NULL slot is present, an error is issued and 1875088Sab196087 * this routine does not return to the caller. 1885088Sab196087 */ 1895088Sab196087 static Word 1905088Sab196087 convert_dt_null(ARGSTATE *argstate, Word d_tag, Xword d_val) 1915088Sab196087 { 1925088Sab196087 Conv_inv_buf_t inv_buf; 1935088Sab196087 Word ndx; 1945088Sab196087 Dyn *dyn; 1955088Sab196087 1965088Sab196087 /* If we lack an extra element, we can't continue */ 1975088Sab196087 if (argstate->dyn.num_null_ndx <= 1) 1985088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 1995088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 2005088Sab196087 argstate->dyn.sec->sec_name); 2015088Sab196087 2025088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL), 2035088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), argstate->dyn.sec->sec_name, 2045088Sab196087 EC_WORD(argstate->dyn.null_ndx), conv_dyn_tag(d_tag, 2055088Sab196087 argstate->obj_state->os_ehdr->e_machine, 0, &inv_buf)); 2065088Sab196087 2075088Sab196087 ndx = argstate->dyn.null_ndx; 2085088Sab196087 dyn = &argstate->dyn.data[ndx]; 2095088Sab196087 dyn->d_tag = d_tag; 2105088Sab196087 dyn->d_un.d_val = d_val; 2115088Sab196087 2125088Sab196087 /* Recompute the DT_NULL situation */ 2135088Sab196087 set_null_ndx(argstate); 2145088Sab196087 2155088Sab196087 return (ndx); 2165088Sab196087 } 2175088Sab196087 2185088Sab196087 2195088Sab196087 /* 2205088Sab196087 * Standard argument processing for dyn module 2215088Sab196087 * 2225088Sab196087 * entry 2235088Sab196087 * obj_state, argc, argv - Standard command arguments 2245088Sab196087 * argstate - Address of ARGSTATE block to be initialized 2255088Sab196087 * 2265088Sab196087 * exit: 2275088Sab196087 * On success, *argstate is initialized. On error, 2285088Sab196087 * an error is issued and this routine does not return. 2295088Sab196087 */ 2305088Sab196087 static void 2315088Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 2325088Sab196087 ARGSTATE *argstate) 2335088Sab196087 { 2345088Sab196087 elfedit_getopt_state_t getopt_state; 2355088Sab196087 elfedit_getopt_ret_t *getopt_ret; 2365088Sab196087 2375088Sab196087 bzero(argstate, sizeof (*argstate)); 2385088Sab196087 argstate->obj_state = obj_state; 2395088Sab196087 2405088Sab196087 elfedit_getopt_init(&getopt_state, &argc, &argv); 2415088Sab196087 2425088Sab196087 /* Add each new option to the options mask */ 2436225Sab196087 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) { 2445088Sab196087 argstate->optmask |= getopt_ret->gor_idmask; 2456225Sab196087 switch (getopt_ret->gor_idmask) { 2466225Sab196087 case DYN_OPT_F_DYNNDX_VAL: 2476225Sab196087 case DYN_OPT_F_NEEDED: 2486225Sab196087 argstate->dyn_elt_str = getopt_ret->gor_value; 2496225Sab196087 break; 2506225Sab196087 } 2516225Sab196087 } 2525088Sab196087 2535088Sab196087 /* If there may be an arbitrary amount of output, use a pager */ 2545088Sab196087 if (argc == 0) 2555088Sab196087 elfedit_pager_init(); 2565088Sab196087 2575088Sab196087 /* Return the updated values of argc/argv */ 2585088Sab196087 argstate->argc = argc; 2595088Sab196087 argstate->argv = argv; 2605088Sab196087 2615088Sab196087 /* Locate the dynamic section, and the assocated string table */ 2625088Sab196087 argstate->dyn.sec = elfedit_sec_getdyn(obj_state, &argstate->dyn.data, 2635088Sab196087 &argstate->dyn.num); 2645088Sab196087 argstate->strsec = elfedit_sec_getstr(obj_state, 2656225Sab196087 argstate->dyn.sec->sec_shdr->sh_link, 0); 2665088Sab196087 2675088Sab196087 /* Index of first DT_NULL */ 2685088Sab196087 set_null_ndx(argstate); 2695088Sab196087 } 2705088Sab196087 2715088Sab196087 2725088Sab196087 2735088Sab196087 /* 2745088Sab196087 * Print ELF header values, taking the calling command, and output style 2755088Sab196087 * into account. 2765088Sab196087 * 2775088Sab196087 * entry: 2785088Sab196087 * cmd - DYN_CMD_T_* value giving identify of caller 2795088Sab196087 * autoprint - If True, output is only produced if the elfedit 2805088Sab196087 * autoprint flag is set. If False, output is always produced. 2815088Sab196087 * argstate - Argument state block 2825088Sab196087 * print_type - Specifies which dynamic elements to display. 2835088Sab196087 * ndx = If print_type is PRINT_DYN_T_NDX, displays the index specified. 2845088Sab196087 * Otherwise ignored. 2855088Sab196087 */ 2865088Sab196087 typedef enum { 2875088Sab196087 PRINT_DYN_T_ALL = 0, /* Show all indexes */ 2885088Sab196087 PRINT_DYN_T_NDX = 1, /* Show dynamic[arg] only */ 2895088Sab196087 PRINT_DYN_T_TAG = 2, /* Show all elts with tag type */ 2905088Sab196087 /* given by arg */ 2915088Sab196087 PRINT_DYN_T_RUNPATH = 3 /* Show all runpath/rpath elts */ 2925088Sab196087 2935088Sab196087 } PRINT_DYN_T; 2945088Sab196087 2955088Sab196087 static void 2965088Sab196087 print_dyn(DYN_CMD_T cmd, int autoprint, ARGSTATE *argstate, 2975088Sab196087 PRINT_DYN_T print_type, Word arg) 2985088Sab196087 { 2995088Sab196087 elfedit_outstyle_t outstyle; 3005088Sab196087 Conv_fmt_flags_t flags_fmt_flags; 3016635Sab196087 Word end_ndx, ndx, printed = 0; 3025088Sab196087 Dyn *dyn; 3035088Sab196087 int header_done = 0; 3045088Sab196087 Xword last_d_val; 3056225Sab196087 int one_shot; 3065088Sab196087 3075088Sab196087 if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) 3085088Sab196087 return; 3095088Sab196087 3105088Sab196087 /* 3115088Sab196087 * Pick an output style. dyn:dump is required to use the default 3125088Sab196087 * style. The other commands use the current output style. 3135088Sab196087 */ 3145088Sab196087 outstyle = (cmd == DYN_CMD_T_DUMP) ? 3155088Sab196087 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 3165088Sab196087 3175088Sab196087 /* 3185088Sab196087 * When using the simple output style, omit the 3195088Sab196087 * brackets from around the values. 3205088Sab196087 */ 3215088Sab196087 flags_fmt_flags = (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) ? 3225088Sab196087 CONV_FMT_NOBKT : 0; 3235088Sab196087 3246635Sab196087 /* Starting index */ 3255088Sab196087 if (print_type == PRINT_DYN_T_NDX) { 3265088Sab196087 if (arg >= argstate->dyn.num) 3275088Sab196087 return; /* Out of range */ 3285088Sab196087 ndx = arg; 3295088Sab196087 } else { 3305088Sab196087 ndx = 0; 3315088Sab196087 } 3325088Sab196087 3336225Sab196087 /* 3346225Sab196087 * one_shot is used by positional elements (e.g. DT_POSFLAG_1) 3356225Sab196087 * to get the item following them to be shown even if they 3366225Sab196087 * are not of the desired tag type or the count of elements 3376225Sab196087 * to be displayed is only 1. 3386225Sab196087 */ 3396225Sab196087 one_shot = 0; 3406225Sab196087 3415088Sab196087 dyn = &argstate->dyn.data[ndx]; 3426635Sab196087 3436635Sab196087 /* 3446635Sab196087 * Loop predicate explanation: 3456635Sab196087 * Normally, we want to iterate from the starting index 3466635Sab196087 * to the end. However, in the case of PRINT_DYN_T_NDX, we 3476635Sab196087 * only want to display one item (ndx == arg) and then quit, 3486635Sab196087 * with the exception that if we've been through the loop 3496635Sab196087 * and encountered a one_shot situation, we want to continue 3506635Sab196087 * iterating until the one-shot situation is cleared. 3516635Sab196087 */ 3526635Sab196087 for (; (ndx < argstate->dyn.num) && 3536635Sab196087 ((print_type != PRINT_DYN_T_NDX) || ((ndx == arg) || one_shot)); 3546635Sab196087 dyn++, ndx++) { 3555088Sab196087 union { 3566206Sab196087 Conv_inv_buf_t inv; 3575088Sab196087 Conv_dyn_flag_buf_t flag; 3585088Sab196087 Conv_dyn_flag1_buf_t flag1; 3595088Sab196087 Conv_dyn_posflag1_buf_t posflag1; 3605088Sab196087 Conv_dyn_feature1_buf_t feature1; 3615088Sab196087 } c_buf; 3625088Sab196087 const char *name; 3635088Sab196087 3646225Sab196087 if (one_shot) { 3656225Sab196087 one_shot = 0; 3666225Sab196087 } else { 3676225Sab196087 /* 3686225Sab196087 * If we are only displaying certain tag types and 3696225Sab196087 * this isn't one of those, move on to next element. 3706225Sab196087 */ 3716225Sab196087 switch (print_type) { 3726225Sab196087 case PRINT_DYN_T_TAG: 3736225Sab196087 if (dyn->d_tag != arg) 3746225Sab196087 continue; 3756225Sab196087 break; 3766225Sab196087 case PRINT_DYN_T_RUNPATH: 3776225Sab196087 if ((dyn->d_tag != DT_RPATH) && 3786225Sab196087 (dyn->d_tag != DT_RUNPATH)) 3796225Sab196087 continue; 3806225Sab196087 break; 3816225Sab196087 } 3825088Sab196087 } 3835088Sab196087 3845088Sab196087 /* 3855088Sab196087 * Print the information numerically, and if possible 3865088Sab196087 * as a string. 3875088Sab196087 */ 3885088Sab196087 name = NULL; 3895088Sab196087 switch (dyn->d_tag) { 3905088Sab196087 case DT_NULL: 3915088Sab196087 if (!((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) && 3925088Sab196087 (print_type == PRINT_DYN_T_ALL) && 3935088Sab196087 (dyn->d_un.d_val == 0))) 3945088Sab196087 break; 3955088Sab196087 end_ndx = ndx; 3965088Sab196087 /* 3975088Sab196087 * Special case: DT_NULLs can come in groups 3985088Sab196087 * that we prefer to reduce to a single line. 3995088Sab196087 */ 4005088Sab196087 while ((end_ndx < (argstate->dyn.num - 1)) && 4015088Sab196087 ((dyn + 1)->d_tag == DT_NULL) && 4025088Sab196087 ((dyn + 1)->d_un.d_val == 0)) { 4035088Sab196087 dyn++; 4045088Sab196087 end_ndx++; 4055088Sab196087 } 4065088Sab196087 if (header_done == 0) { 4075088Sab196087 header_done = 1; 4085088Sab196087 Elf_dyn_title(0); 4095088Sab196087 } 4105088Sab196087 Elf_dyn_null_entry(0, dyn, ndx, end_ndx); 4115088Sab196087 ndx = end_ndx; 4125088Sab196087 printed = 1; 4135088Sab196087 last_d_val = dyn->d_un.d_val; 4145088Sab196087 continue; 4155088Sab196087 4165088Sab196087 /* 4175088Sab196087 * Print the information numerically, and if possible 4185088Sab196087 * as a string. 4195088Sab196087 */ 4205088Sab196087 case DT_NEEDED: 4215088Sab196087 case DT_SONAME: 4225088Sab196087 case DT_FILTER: 4235088Sab196087 case DT_AUXILIARY: 4245088Sab196087 case DT_CONFIG: 4255088Sab196087 case DT_RPATH: 4265088Sab196087 case DT_RUNPATH: 4275088Sab196087 case DT_USED: 4285088Sab196087 case DT_DEPAUDIT: 4295088Sab196087 case DT_AUDIT: 4305088Sab196087 case DT_SUNW_AUXILIARY: 4315088Sab196087 case DT_SUNW_FILTER: 4325088Sab196087 name = elfedit_offset_to_str(argstate->strsec, 4335088Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 4345088Sab196087 break; 4355088Sab196087 4365088Sab196087 case DT_FLAGS: 4375088Sab196087 name = conv_dyn_flag(dyn->d_un.d_val, 4385088Sab196087 flags_fmt_flags, &c_buf.flag); 4395088Sab196087 break; 4405088Sab196087 case DT_FLAGS_1: 4415088Sab196087 name = conv_dyn_flag1(dyn->d_un.d_val, 4425088Sab196087 flags_fmt_flags, &c_buf.flag1); 4435088Sab196087 break; 4445088Sab196087 case DT_POSFLAG_1: 4456225Sab196087 /* 4466225Sab196087 * If this is dyn:posflag1, and the print_type 4476225Sab196087 * is PRINT_DYN_T_TAG, and the -needed option is 4486225Sab196087 * used, then don't show any DT_POSFLAG_1 elements 4496225Sab196087 * that are not followed by a DT_NEEDED element 4506225Sab196087 * that matches the -needed string. 4516225Sab196087 */ 4526225Sab196087 if ((cmd == DYN_CMD_T_POSFLAG1) && 4536225Sab196087 (print_type == PRINT_DYN_T_TAG) && 4546225Sab196087 ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) && 4556225Sab196087 ((ndx + 1) < argstate->dyn.num)) { 4566225Sab196087 Dyn *dyn1 = &argstate->dyn.data[ndx + 1]; 4576225Sab196087 4586225Sab196087 if (dyn1->d_tag != DT_NEEDED) 4596225Sab196087 continue; 4606225Sab196087 name = elfedit_offset_to_str(argstate->strsec, 4616225Sab196087 dyn1->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 4626225Sab196087 if (strncmp(name, argstate->dyn_elt_str, 4636225Sab196087 strlen(argstate->dyn_elt_str)) != 0) 4646225Sab196087 continue; 4656225Sab196087 } 4666225Sab196087 4675088Sab196087 name = conv_dyn_posflag1(dyn->d_un.d_val, 4685088Sab196087 flags_fmt_flags, &c_buf.posflag1); 4696225Sab196087 /* 4706225Sab196087 * DT_POSFLAG_1 is a positional element that affects 4716225Sab196087 * the following item. If using the default output 4726225Sab196087 * style, then show the following item as well. 4736225Sab196087 */ 4746225Sab196087 one_shot = (outstyle == ELFEDIT_OUTSTYLE_DEFAULT); 4755088Sab196087 break; 4765088Sab196087 case DT_FEATURE_1: 4775088Sab196087 name = conv_dyn_feature1(dyn->d_un.d_val, 4785088Sab196087 flags_fmt_flags, &c_buf.feature1); 4795088Sab196087 break; 4805088Sab196087 case DT_DEPRECATED_SPARC_REGISTER: 4815088Sab196087 name = MSG_INTL(MSG_STR_DEPRECATED); 4825088Sab196087 break; 4836206Sab196087 case DT_SUNW_LDMACH: 4846206Sab196087 name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0, 4856206Sab196087 &c_buf.inv); 4866206Sab196087 break; 4875088Sab196087 } 4885088Sab196087 4895088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 4905088Sab196087 if (header_done == 0) { 4915088Sab196087 header_done = 1; 4925088Sab196087 Elf_dyn_title(0); 4935088Sab196087 } 4945088Sab196087 if (name == NULL) 4955088Sab196087 name = MSG_ORIG(MSG_STR_EMPTY); 4965088Sab196087 Elf_dyn_entry(0, dyn, ndx, name, 4975088Sab196087 argstate->obj_state->os_ehdr->e_machine); 4985088Sab196087 } else { 4995088Sab196087 /* 5005088Sab196087 * In simple or numeric mode under a print type 5015088Sab196087 * that is based on tag type rather than on index, 502*8368SAli.Bahrami@Sun.COM * if there are more than one qualifying tag, we 503*8368SAli.Bahrami@Sun.COM * want to skip printing redundant information. 5045088Sab196087 */ 5055088Sab196087 switch (print_type) { 5065088Sab196087 case PRINT_DYN_T_TAG: 507*8368SAli.Bahrami@Sun.COM switch (dyn->d_tag) { 508*8368SAli.Bahrami@Sun.COM case DT_NEEDED: 509*8368SAli.Bahrami@Sun.COM /* Multiple NEEDED entries are normal */ 510*8368SAli.Bahrami@Sun.COM break; 511*8368SAli.Bahrami@Sun.COM case DT_POSFLAG_1: 512*8368SAli.Bahrami@Sun.COM /* 513*8368SAli.Bahrami@Sun.COM * Positional flags don't count, 514*8368SAli.Bahrami@Sun.COM * because each one affects a different 515*8368SAli.Bahrami@Sun.COM * item. Don't skip those even if they 516*8368SAli.Bahrami@Sun.COM * have duplicate values. 517*8368SAli.Bahrami@Sun.COM */ 518*8368SAli.Bahrami@Sun.COM break; 519*8368SAli.Bahrami@Sun.COM default: 520*8368SAli.Bahrami@Sun.COM /* 521*8368SAli.Bahrami@Sun.COM * Anything else: If we've already 522*8368SAli.Bahrami@Sun.COM * printed this value, don't print 523*8368SAli.Bahrami@Sun.COM * it again. 524*8368SAli.Bahrami@Sun.COM */ 525*8368SAli.Bahrami@Sun.COM if (printed && 526*8368SAli.Bahrami@Sun.COM (last_d_val == dyn->d_un.d_val)) 527*8368SAli.Bahrami@Sun.COM continue; 528*8368SAli.Bahrami@Sun.COM } 529*8368SAli.Bahrami@Sun.COM break; 530*8368SAli.Bahrami@Sun.COM case PRINT_DYN_T_RUNPATH: 5316225Sab196087 /* 532*8368SAli.Bahrami@Sun.COM * If we've already printed this value, 533*8368SAli.Bahrami@Sun.COM * don't print it again. This commonly 534*8368SAli.Bahrami@Sun.COM * happens when both DT_RPATH and DT_RUNPATH 535*8368SAli.Bahrami@Sun.COM * are present with the same value. 5366225Sab196087 */ 5375088Sab196087 if (printed && (last_d_val == dyn->d_un.d_val)) 5385088Sab196087 continue; 5396225Sab196087 break; 5405088Sab196087 } 5415088Sab196087 5425088Sab196087 if ((name != NULL) && 5435088Sab196087 (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) { 5445088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name); 5455088Sab196087 } else { 5465088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), 5475088Sab196087 dyn->d_un.d_val); 5485088Sab196087 } 5495088Sab196087 } 5505088Sab196087 printed = 1; 5515088Sab196087 last_d_val = dyn->d_un.d_val; 5525088Sab196087 } 5535088Sab196087 5545088Sab196087 /* 5555088Sab196087 * If nothing was output under the print types that are 5565088Sab196087 * based on tag type, issue an error saying it doesn't exist. 5575088Sab196087 */ 5585088Sab196087 if (!printed) { 5595088Sab196087 if (print_type == PRINT_DYN_T_TAG) { 5605088Sab196087 Conv_inv_buf_t inv_buf; 5615088Sab196087 5625088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 5635088Sab196087 MSG_INTL(MSG_ERR_NODYNELT), 5645088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 5655088Sab196087 argstate->dyn.sec->sec_name, conv_dyn_tag(arg, 5665088Sab196087 argstate->obj_state->os_ehdr->e_machine, 5675088Sab196087 0, &inv_buf)); 5685088Sab196087 } 5695088Sab196087 5705088Sab196087 if (print_type == PRINT_DYN_T_RUNPATH) 5715088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 5725088Sab196087 MSG_INTL(MSG_ERR_NORUNPATH), 5735088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 5745088Sab196087 argstate->dyn.sec->sec_name); 5755088Sab196087 } 5765088Sab196087 } 5775088Sab196087 5785088Sab196087 5795088Sab196087 /* 5806225Sab196087 * Determine the index(s) of the dynamic element(s) to be displayed and/or 5816225Sab196087 * manipulated. 5825088Sab196087 * 5835088Sab196087 * entry: 5845088Sab196087 * argstate - Argument state block 5856225Sab196087 * arg - If the command being called accepts a first plain argument 5866225Sab196087 * named 'elt' which is used to specify the dynamic element, 5876225Sab196087 * arg is the value of argv[0] for that command. If the 5886225Sab196087 * command does not accept an 'elt' argument and instead 5896225Sab196087 * implicitly assumes a tag type, arg is the constant string 5906225Sab196087 * for that type (e.g. "DT_POSFLAG_1"). 5915088Sab196087 * print_request - True if the command is to print the current 5925088Sab196087 * value(s) and return without changing anything. 5935088Sab196087 * print_type - Address of variable containing PRINT_DYN_T_ 5945088Sab196087 * code specifying how the elements will be displayed. 5955088Sab196087 * 5965088Sab196087 * exit: 5976225Sab196087 * If print_request is False: This routine always returns the index 5986225Sab196087 * of a single dynamic element. *print_type is set to PRINT_DYN_T_NDX. 5996225Sab196087 * The 'elt' argument as well as any modifier options (-dynndx, -needed) 6006225Sab196087 * are examined to determine this index. If there are no modifier options, 6016225Sab196087 * the dynamic section contains no element of the desired type, and there 6026225Sab196087 * is an extra DT_NULL element in the section, then a new element of 6036225Sab196087 * the desired type is created and its index returned. Otherwise an 6046225Sab196087 * error is issued. 6055088Sab196087 * 6066225Sab196087 * If print_request is True: If a modifier (-dynndx, -needed) was used, 6076225Sab196087 * *print_type is set to PRINT_DYN_T_NDX and the index of the 6086225Sab196087 * corresponding single dynamic element is returned. If no modifier 6096225Sab196087 * was used, *print_type is set to PRINT_DYN_T_TAG, and the tag 6106225Sab196087 * type code is returned. 6115088Sab196087 */ 6125088Sab196087 static Word 6136225Sab196087 arg_to_index(ARGSTATE *argstate, const char *arg, 6145088Sab196087 int print_request, PRINT_DYN_T *print_type) 6155088Sab196087 { 6165088Sab196087 Word ndx, dt_value; 6176225Sab196087 Dyn *dyn; 6185088Sab196087 6195088Sab196087 6205088Sab196087 /* Assume we are returning an index, alter as needed below */ 6215088Sab196087 *print_type = PRINT_DYN_T_NDX; 6225088Sab196087 6236225Sab196087 /* 6246225Sab196087 * All the commands that accept the DYN_OPT_F_DYNNDX_ELT form 6256225Sab196087 * of -dynndx require a plain argument named 'elt' as their first 6266225Sab196087 * argument. -dynndx is a modifier that means that 'elt' is a 6276225Sab196087 * simple numeric section index. Routines that accept this form 6286225Sab196087 * of -dynndx are willing to handle any tag type, so all we need 6296225Sab196087 * to check is that the value is in range. 6306225Sab196087 */ 6316225Sab196087 if ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0) 6326225Sab196087 return ((Word) elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_ELT), 6336225Sab196087 0, argstate->dyn.num - 1, NULL)); 6346225Sab196087 6356225Sab196087 /* arg is a DT_ tag type, not a numeric index */ 6366225Sab196087 dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT); 6375088Sab196087 6386225Sab196087 /* 6396225Sab196087 * Commands that accept the DYN_OPT_F_DYNNDX_VAL form of 6406225Sab196087 * dynndx do not accept the 'elt' argument. The index is a 6416225Sab196087 * value that follows the option, and was saved in argstate by 6426225Sab196087 * process_args(). Routines that accept this form of -dynndx 6436225Sab196087 * require the specified element to have a specific tag type, 6446225Sab196087 * so we test for this as well as for the index being in range. 6456225Sab196087 */ 6466225Sab196087 if ((argstate->optmask & DYN_OPT_F_DYNNDX_VAL) != 0) { 6476225Sab196087 ndx = ((Word) elfedit_atoui_range(argstate->dyn_elt_str, 6486225Sab196087 MSG_ORIG(MSG_STR_INDEX), 0, argstate->dyn.num - 1, NULL)); 6496225Sab196087 if (argstate->dyn.data[ndx].d_tag != dt_value) { 6506225Sab196087 Half mach = argstate->obj_state->os_ehdr->e_machine; 6516225Sab196087 Conv_inv_buf_t is, want; 6526225Sab196087 6536225Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_WRONGTAG), 6546225Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 6556225Sab196087 argstate->dyn.sec->sec_name, ndx, 6566225Sab196087 conv_dyn_tag(dt_value, mach, 0, &want), 6576225Sab196087 conv_dyn_tag(argstate->dyn.data[ndx].d_tag, mach, 6586225Sab196087 0, &is)); 6596225Sab196087 } 6606225Sab196087 return (ndx); 6616225Sab196087 } 6625088Sab196087 6635088Sab196087 /* 6645088Sab196087 * If this is a printing request, then we let print_dyn() show 6655088Sab196087 * all the items with this tag type. 6665088Sab196087 */ 6675088Sab196087 if (print_request) { 6685088Sab196087 *print_type = PRINT_DYN_T_TAG; 6695088Sab196087 return (dt_value); 6705088Sab196087 } 6715088Sab196087 6726225Sab196087 /* 6736225Sab196087 * Commands that accept -needed are looking for the dt_value element 6746225Sab196087 * (usually DT_POSFLAG_1) that immediately preceeds the DT_NEEDED 6756225Sab196087 * element with the string given by argstate->dyn_elt_str. 6766225Sab196087 */ 6776225Sab196087 if ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) { 6786225Sab196087 Word retndx = argstate->dyn.num; /* Out of range value */ 6796225Sab196087 const char *name; 6806225Sab196087 size_t len; 6816225Sab196087 6826225Sab196087 len = strlen(argstate->dyn_elt_str); 6836225Sab196087 for (ndx = 0, dyn = argstate->dyn.data; 6846225Sab196087 ndx < argstate->dyn.num; dyn++, ndx++) { 6856225Sab196087 /* 6866225Sab196087 * If the immediately preceeding item has the 6876225Sab196087 * tag type we're looking for, and the current item 6886225Sab196087 * is a DT_NEEDED with a string that matches, 6896225Sab196087 * then the preceeding item is the one we want. 6906225Sab196087 */ 6916225Sab196087 if ((dyn->d_tag == DT_NEEDED) && 6926225Sab196087 (ndx > 0) && (retndx == (ndx - 1))) { 6936225Sab196087 name = elfedit_offset_to_str(argstate->strsec, 6946225Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 6956225Sab196087 6966225Sab196087 if (strncmp(name, 6976225Sab196087 argstate->dyn_elt_str, len) == 0) 6986225Sab196087 return (retndx); 6996225Sab196087 continue; 7006225Sab196087 } 7016225Sab196087 7026225Sab196087 /* 7036225Sab196087 * If the current item has the tag type we're 7046225Sab196087 * looking for, make it our current candidate. 7056225Sab196087 * If the next item is a DT_NEEDED with the right 7066225Sab196087 * string value, we'll use it then. 7076225Sab196087 */ 7086225Sab196087 if (dyn->d_tag == dt_value) 7096225Sab196087 retndx = ndx; 7106225Sab196087 } 7116225Sab196087 7126225Sab196087 /* If we get here, no matching DT_NEEDED was found */ 7136225Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEDNOMATCH), 7146225Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 7156225Sab196087 argstate->dyn.sec->sec_name, argstate->dyn_elt_str); 7166225Sab196087 } 7176225Sab196087 7185088Sab196087 /* Locate the first entry with the given tag type */ 7195088Sab196087 for (ndx = 0; ndx < argstate->dyn.num; ndx++) { 7205088Sab196087 if (argstate->dyn.data[ndx].d_tag == dt_value) { 7215088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 7225088Sab196087 MSG_INTL(MSG_DEBUG_DT2NDX), 7235088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 7245088Sab196087 argstate->dyn.sec->sec_name, EC_WORD(ndx), arg); 7255088Sab196087 return (ndx); 7265088Sab196087 } 7275088Sab196087 } 7285088Sab196087 7295088Sab196087 /* Not found. Can we create one? */ 7305088Sab196087 if (argstate->dyn.num_null_ndx > 1) 7315088Sab196087 return (convert_dt_null(argstate, dt_value, 0)); 7325088Sab196087 7335088Sab196087 /* No room to create one, so we're out of options and must fail */ 7345088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT), 7355088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 7365088Sab196087 argstate->dyn.sec->sec_name, arg); 7375088Sab196087 7385088Sab196087 /*NOTREACHED*/ 7395088Sab196087 return (0); /* For lint */ 7405088Sab196087 } 7415088Sab196087 7425088Sab196087 7435088Sab196087 /* 7445088Sab196087 * Called by cmd_body() for dyn:value. Implements the core functionality 7455088Sab196087 * for that command. 7465088Sab196087 * 7475088Sab196087 * This routine expects that both the index and value arguments are 7485088Sab196087 * present. 7495088Sab196087 */ 7505088Sab196087 static elfedit_cmdret_t 7515088Sab196087 cmd_body_value(ARGSTATE *argstate, Word *ret_ndx) 7525088Sab196087 { 7535088Sab196087 elfedit_section_t *dynsec = argstate->dyn.sec; 7545088Sab196087 elfedit_section_t *strsec = argstate->strsec; 7555088Sab196087 elfedit_dyn_elt_t strpad_elt; 7565088Sab196087 Word i; 7575088Sab196087 Dyn *dyn = argstate->dyn.data; 7585088Sab196087 Word numdyn = argstate->dyn.num; 7596225Sab196087 int minus_add, minus_s, minus_dynndx; 7605088Sab196087 Word arg1, tmp_val; 7615088Sab196087 Xword arg2; 7625088Sab196087 int arg2_known = 1; 7635088Sab196087 7646225Sab196087 minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0); 7656225Sab196087 minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0); 7666225Sab196087 minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0); 7675088Sab196087 7685088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 7695088Sab196087 7705088Sab196087 /* 7715088Sab196087 * The first argument is an index if -dynndx is used, and is a 7725088Sab196087 * tag value otherwise. 7735088Sab196087 */ 7745088Sab196087 arg1 = minus_dynndx ? 7755088Sab196087 elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT), 7765088Sab196087 0, numdyn - 1, NULL) : 7775088Sab196087 elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT); 7785088Sab196087 7795088Sab196087 if (minus_s) { 7805088Sab196087 /* 7815088Sab196087 * Don't allow the user to specify -s when manipulating a 7825088Sab196087 * DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to 7835088Sab196087 * manage the extra space used for strings, this would break 7845088Sab196087 * our ability to add the string. 7855088Sab196087 */ 7865088Sab196087 if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) || 7875088Sab196087 (minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD))) 7885088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 7895088Sab196087 MSG_INTL(MSG_ERR_STRPADSTRVAL), 7905088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 7915088Sab196087 7925088Sab196087 /* Locate DT_SUNW_STRPAD element if present */ 7935088Sab196087 strpad_elt.dn_dyn.d_un.d_val = 0; 7945088Sab196087 (void) elfedit_dynstr_getpad(argstate->dyn.sec, &strpad_elt); 7955088Sab196087 7965088Sab196087 /* 7975088Sab196087 * Look up the string: If the user specified the -dynndx 7985088Sab196087 * -option, then we will insert it if possible, and 7995088Sab196087 * fail with an error if not. However, if they did not 8005088Sab196087 * specify -dynndx, we want to look up the string if it is 8015088Sab196087 * already there, but defer the insertion. The reason for 8025088Sab196087 * this is that we may have to grab an unused DT_NULL element 8035088Sab196087 * below, and if there are none available, we won't want 8045088Sab196087 * to have modified the string table. 8055088Sab196087 * 8065088Sab196087 * This isn't a problem, because if the string isn't 8075088Sab196087 * in the string table, it can't be used by a dynamic element. 8085088Sab196087 * Hence, we don't need to insert it to know that there is 8095088Sab196087 * no match. 8105088Sab196087 */ 8115088Sab196087 if (minus_dynndx == 0) { 8125088Sab196087 if (elfedit_sec_findstr(strsec, 8135088Sab196087 strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1], 8145088Sab196087 &tmp_val) == 0) { 8155088Sab196087 arg2_known = 0; 8165088Sab196087 } else { 8175088Sab196087 arg2 = tmp_val; 8185088Sab196087 } 8195088Sab196087 } else { 8205088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 8215088Sab196087 &strpad_elt, argstate->argv[1]); 8225088Sab196087 } 8235088Sab196087 } else { /* Argument 2 is an integer */ 8245088Sab196087 arg2 = elfedit_atoui(argstate->argv[1], NULL); 8255088Sab196087 } 8265088Sab196087 8275088Sab196087 8285088Sab196087 if (!minus_dynndx && !(minus_add && !arg2_known)) { 8295088Sab196087 /* 8305088Sab196087 * Search the dynamic section and see if an item with the 8315088Sab196087 * specified tag value already exists. We can reduce this 8325088Sab196087 * to a simple update of an existing value if -add is not 8335088Sab196087 * specified or the existing d_un value matches the new one. 8345088Sab196087 * 8355088Sab196087 * In either of these cases, we will change arg1 to be the 8365088Sab196087 * index, and set minus_dynndx, causing the simple update to 8375088Sab196087 * happen immediately below. 8385088Sab196087 */ 8395088Sab196087 for (i = 0; i < numdyn; i++) { 8405088Sab196087 if ((dyn[i].d_tag == arg1) && 8415088Sab196087 (!minus_add || (dyn[i].d_un.d_val == arg2))) { 8425088Sab196087 arg1 = i; 8435088Sab196087 minus_dynndx = 1; 8445088Sab196087 break; 8455088Sab196087 } 8465088Sab196087 } 8475088Sab196087 } 8485088Sab196087 8495088Sab196087 /* 8505088Sab196087 * If -dynndx is used, then this is a relatively simple 8515088Sab196087 * operation, as we simply write over the specified index. 8525088Sab196087 */ 8535088Sab196087 if (minus_dynndx) { 8545088Sab196087 /* 8555088Sab196087 * If we held back from inserting a new string into 8565088Sab196087 * the dynstr above, we insert it now, because we 8575088Sab196087 * have a slot in the dynamic section, and we need 8585088Sab196087 * the string offset ot finish. 8595088Sab196087 */ 8605088Sab196087 if (!arg2_known) 8615088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 8625088Sab196087 &strpad_elt, argstate->argv[1]); 8635088Sab196087 8645088Sab196087 *ret_ndx = arg1; 8655088Sab196087 if (dyn[arg1].d_un.d_val == arg2) { 8665088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8675088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), 8685088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8695088Sab196087 EC_WORD(arg1), EC_XWORD(arg2)); 8705088Sab196087 return (ELFEDIT_CMDRET_NONE); 8715088Sab196087 } else { 8725088Sab196087 /* Warn if setting DT_NULL value to non-zero */ 8735088Sab196087 if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0)) 8745088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8755088Sab196087 MSG_INTL(MSG_DEBUG_DTNULLVALUE), 8765088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8775088Sab196087 EC_WORD(arg1), EC_XWORD(arg2)); 8785088Sab196087 8795088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8805088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 8815088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8825088Sab196087 EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val), 8835088Sab196087 EC_XWORD(arg2)); 8845088Sab196087 dyn[arg1].d_un.d_val = arg2; 8855088Sab196087 return (ELFEDIT_CMDRET_MOD); 8865088Sab196087 } 8875088Sab196087 } 8885088Sab196087 8895088Sab196087 /* 8905088Sab196087 * We need a new slot in the dynamic section. If we can't have 8915088Sab196087 * one, then we fail. 8925088Sab196087 */ 8935088Sab196087 if (argstate->dyn.num_null_ndx <= 1) 8945088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 8955088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 8965088Sab196087 8975088Sab196087 /* 8985088Sab196087 * If we still need to insert a new string into the dynstr, 8995088Sab196087 * then it is safe now, because if we succeed, we know that 9005088Sab196087 * there is an available slot to receive it. If we fail, we 9015088Sab196087 * haven't claimed the extra slot yet, and it will be unharmed. 9025088Sab196087 */ 9035088Sab196087 if (!arg2_known) 9045088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 9055088Sab196087 &strpad_elt, argstate->argv[1]); 9065088Sab196087 9075088Sab196087 /* Use an extra DT_NULL slot and enter the new element */ 9085088Sab196087 *ret_ndx = convert_dt_null(argstate, arg1, arg2); 9095088Sab196087 return (ELFEDIT_CMDRET_MOD); 9105088Sab196087 } 9115088Sab196087 9125088Sab196087 9135088Sab196087 9145088Sab196087 /* 9155088Sab196087 * Called by cmd_body() for dyn:runpath. Implements the core functionality 9165088Sab196087 * for that command. 9175088Sab196087 * 9185088Sab196087 * History Lesson And Strategy: 9195088Sab196087 * 9205088Sab196087 * This routine handles both DT_RPATH and DT_RUNPATH entries, altering 9215088Sab196087 * either or both if they are present. 9225088Sab196087 * 9235088Sab196087 * The original SYSV ABI only had DT_RPATH, and the runtime loader used 9245088Sab196087 * it to search for things in the following order: 9255088Sab196087 * 9265088Sab196087 * DT_RPATH, LD_LIBRARY_PATH, defaults 9275088Sab196087 * 9285088Sab196087 * Solaris did not follow this rule, an extremely rare deviation from 9295088Sab196087 * the ABI. Environment variables should supercede everything else, 9305088Sab196087 * otherwise they are not very useful. This decision was made at the 9315088Sab196087 * very beginning of the SunOS 5.x development, so we have always 9325088Sab196087 * deviated from the ABI and and instead search in the order 9335088Sab196087 * 9345088Sab196087 * LD_LIBRARY_PATH, DT_RPATH, defaults 9355088Sab196087 * 9365088Sab196087 * Other Unix variants initially followed the ABI, but in recent years 9375088Sab196087 * have come to agree with the early Solaris folks that it was a mistake. 9385088Sab196087 * Hence, DT_RUNPATH was invented, with the search order: 9395088Sab196087 * 9405088Sab196087 * LD_LIBRARY_PATH, DT_RUNPATH, defaults 9415088Sab196087 * 9425088Sab196087 * So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both 9435088Sab196087 * are present (which does happen), we set them both to the new 9445088Sab196087 * value. If either one is present, we set that one. If neither is 9455088Sab196087 * present, and we have a spare DT_NULL slot, we create a DT_RUNPATH, but 9465088Sab196087 * not a DT_RPATH, to conserve available slots for other uses. 9475088Sab196087 */ 9485088Sab196087 static elfedit_cmdret_t 9495088Sab196087 cmd_body_runpath(ARGSTATE *argstate) 9505088Sab196087 { 9515088Sab196087 elfedit_section_t *dynsec = argstate->dyn.sec; 9525088Sab196087 elfedit_section_t *strsec = argstate->strsec; 9535088Sab196087 elfedit_dyn_elt_t rpath_elt; 9545088Sab196087 elfedit_dyn_elt_t runpath_elt; 9555088Sab196087 elfedit_dyn_elt_t strpad_elt; 9565088Sab196087 Word i; 9575088Sab196087 Dyn *dyn = argstate->dyn.data; 9585088Sab196087 Word numdyn = argstate->dyn.num; 9595088Sab196087 9605088Sab196087 /* Go through the tags and gather what we need */ 9615088Sab196087 elfedit_dyn_elt_init(&rpath_elt); 9625088Sab196087 elfedit_dyn_elt_init(&runpath_elt); 9635088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 9645088Sab196087 for (i = 0; i < numdyn; i++) { 9655088Sab196087 switch (dyn[i].d_tag) { 9665088Sab196087 case DT_RPATH: 9675088Sab196087 elfedit_dyn_elt_save(&rpath_elt, i, &dyn[i]); 9685088Sab196087 break; 9695088Sab196087 9705088Sab196087 case DT_RUNPATH: 9715088Sab196087 elfedit_dyn_elt_save(&runpath_elt, i, &dyn[i]); 9725088Sab196087 break; 9735088Sab196087 9745088Sab196087 case DT_SUNW_STRPAD: 9755088Sab196087 elfedit_dyn_elt_save(&strpad_elt, i, &dyn[i]); 9765088Sab196087 break; 9775088Sab196087 } 9785088Sab196087 } 9795088Sab196087 9805088Sab196087 /* Do we have an available dynamic section entry to use? */ 9815088Sab196087 if (rpath_elt.dn_seen || runpath_elt.dn_seen) { 9825088Sab196087 /* 9835088Sab196087 * We have seen a DT_RPATH, or a DT_RUNPATH, or both. 9845088Sab196087 * If all of these have the same string as the desired 9855088Sab196087 * new value, then we don't need to alter anything and can 9865088Sab196087 * simply return. Otherwise, we'll modify them all to have 9875088Sab196087 * the new string (below). 9885088Sab196087 */ 9895088Sab196087 if ((!rpath_elt.dn_seen || 9905088Sab196087 (strcmp(elfedit_dyn_offset_to_str(strsec, &rpath_elt), 9915088Sab196087 argstate->argv[0]) == 0)) && 9925088Sab196087 (!runpath_elt.dn_seen || 9935088Sab196087 (strcmp(elfedit_dyn_offset_to_str(strsec, &runpath_elt), 9945088Sab196087 argstate->argv[0]) == 0))) { 9955088Sab196087 if (rpath_elt.dn_seen) 9965088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 9975088Sab196087 MSG_INTL(MSG_DEBUG_OLDRPATHOK), 9985088Sab196087 EC_WORD(dynsec->sec_shndx), 9995088Sab196087 dynsec->sec_name, EC_WORD(rpath_elt.dn_ndx), 10005088Sab196087 elfedit_atoconst_value_to_str( 10015088Sab196087 ELFEDIT_CONST_DT, DT_RPATH, 1)); 10025088Sab196087 if (runpath_elt.dn_seen) 10035088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 10045088Sab196087 MSG_INTL(MSG_DEBUG_OLDRPATHOK), 10055088Sab196087 EC_WORD(dynsec->sec_shndx), 10065088Sab196087 dynsec->sec_name, 10075088Sab196087 EC_WORD(runpath_elt.dn_ndx), 10085088Sab196087 elfedit_atoconst_value_to_str( 10095088Sab196087 ELFEDIT_CONST_DT, DT_RUNPATH, 1)); 10105088Sab196087 return (ELFEDIT_CMDRET_NONE); 10115088Sab196087 } 10125088Sab196087 } else if (argstate->dyn.num_null_ndx <= 1) { 10135088Sab196087 /* 10145088Sab196087 * There is no DT_RPATH or DT_RUNPATH in the dynamic array, 10155088Sab196087 * and there are no extra DT_NULL entries that we can 10165088Sab196087 * convert into one. We cannot proceed. 10175088Sab196087 */ 10185088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 10195088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 10205088Sab196087 } 10215088Sab196087 10225088Sab196087 /* Does the string exist in the table already, or can we add it? */ 10235088Sab196087 rpath_elt.dn_dyn.d_un.d_val = runpath_elt.dn_dyn.d_un.d_val = 10245088Sab196087 elfedit_dynstr_insert(dynsec, strsec, &strpad_elt, 10255088Sab196087 argstate->argv[0]); 10265088Sab196087 10275088Sab196087 /* Update DT_RPATH entry if present */ 10285088Sab196087 if (rpath_elt.dn_seen) { 10295088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_PREVRPATH), 10305088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 10315088Sab196087 EC_WORD(rpath_elt.dn_ndx), 10325088Sab196087 elfedit_atoconst_value_to_str( 10335088Sab196087 ELFEDIT_CONST_DT, DT_RPATH, 1), 10345088Sab196087 elfedit_dyn_offset_to_str(strsec, &rpath_elt)); 10355088Sab196087 dyn[rpath_elt.dn_ndx] = rpath_elt.dn_dyn; 10365088Sab196087 } 10375088Sab196087 10385088Sab196087 /* 10395088Sab196087 * Update the DT_RUNPATH entry in the dynamic section, if present. 10405088Sab196087 * If one is not present, and there is also no DT_RPATH, then 10415088Sab196087 * we use a spare DT_NULL entry to create a new DT_RUNPATH. 10425088Sab196087 */ 10435088Sab196087 if (runpath_elt.dn_seen || !rpath_elt.dn_seen) { 10445088Sab196087 if (runpath_elt.dn_seen) { 10455088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 10465088Sab196087 MSG_INTL(MSG_DEBUG_PREVRPATH), 10475088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 10485088Sab196087 EC_WORD(runpath_elt.dn_ndx), 10495088Sab196087 elfedit_atoconst_value_to_str( 10505088Sab196087 ELFEDIT_CONST_DT, DT_RUNPATH, 1), 10515088Sab196087 elfedit_dyn_offset_to_str(strsec, &runpath_elt)); 10525088Sab196087 dyn[runpath_elt.dn_ndx] = runpath_elt.dn_dyn; 10535088Sab196087 } else { /* Using a spare DT_NULL entry */ 10545088Sab196087 (void) convert_dt_null(argstate, DT_RUNPATH, 10555088Sab196087 runpath_elt.dn_dyn.d_un.d_val); 10565088Sab196087 } 10575088Sab196087 } 10585088Sab196087 10595088Sab196087 return (ELFEDIT_CMDRET_MOD); 10605088Sab196087 } 10615088Sab196087 10625088Sab196087 10635088Sab196087 10645088Sab196087 /* 10655088Sab196087 * Argument processing for the bitmask commands. Convert the arguments 10665088Sab196087 * to integer form, apply -and/-cmp/-or, and return the resulting value. 10675088Sab196087 * 10685088Sab196087 * entry: 10695088Sab196087 * argstate - Argument state block 10705088Sab196087 * orig - Value of original bitmask 10715088Sab196087 * const_type - ELFEDIT_CONST_* value for type of constants 10725088Sab196087 */ 10735088Sab196087 static Word 10745088Sab196087 flag_bitop(ARGSTATE *argstate, Word orig, elfedit_const_t const_type) 10755088Sab196087 { 10765088Sab196087 Word flags = 0; 10775088Sab196087 int i; 10785088Sab196087 10795088Sab196087 /* Collect the arguments */ 10805088Sab196087 for (i = 0; i < argstate->argc; i++) 10815088Sab196087 flags |= (Word) elfedit_atoconst(argstate->argv[i], const_type); 10825088Sab196087 10835088Sab196087 /* Complement the value? */ 10845088Sab196087 if (argstate->optmask & DYN_OPT_F_CMP) 10855088Sab196087 flags = ~flags; 10865088Sab196087 10875088Sab196087 /* Perform any requested bit operations */ 10885088Sab196087 if (argstate->optmask & DYN_OPT_F_AND) 10895088Sab196087 flags &= orig; 10905088Sab196087 else if (argstate->optmask & DYN_OPT_F_OR) 10915088Sab196087 flags |= orig; 10925088Sab196087 10935088Sab196087 return (flags); 10945088Sab196087 } 10955088Sab196087 10965088Sab196087 10975088Sab196087 10985088Sab196087 /* 10995088Sab196087 * Common body for the dyn: module commands. These commands 11005088Sab196087 * share a large amount of common behavior, so it is convenient 11015088Sab196087 * to centralize things and use the cmd argument to handle the 11025088Sab196087 * small differences. 11035088Sab196087 * 11045088Sab196087 * entry: 11055088Sab196087 * cmd - One of the DYN_CMD_T_* constants listed above, specifying 11065088Sab196087 * which command to implement. 11075088Sab196087 * obj_state, argc, argv - Standard command arguments 11085088Sab196087 */ 11095088Sab196087 static elfedit_cmdret_t 11105088Sab196087 cmd_body(DYN_CMD_T cmd, elfedit_obj_state_t *obj_state, 11115088Sab196087 int argc, const char *argv[]) 11125088Sab196087 { 11135088Sab196087 ARGSTATE argstate; 11145088Sab196087 Dyn *dyn; 11155088Sab196087 const char *dyn_name; 11165088Sab196087 Word dyn_ndx, dyn_num, null_ndx; 11175088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 11185088Sab196087 PRINT_DYN_T print_type = PRINT_DYN_T_ALL; 11195088Sab196087 Word ndx; 11205088Sab196087 int print_only = 0; 11215088Sab196087 int do_autoprint = 1; 11225088Sab196087 11235088Sab196087 /* Process the optional arguments */ 11245088Sab196087 process_args(obj_state, argc, argv, &argstate); 11255088Sab196087 11265088Sab196087 dyn = argstate.dyn.data; 11275088Sab196087 dyn_num = argstate.dyn.num; 11285088Sab196087 dyn_name = argstate.dyn.sec->sec_name; 11295088Sab196087 dyn_ndx = argstate.dyn.sec->sec_shndx; 11305088Sab196087 11315088Sab196087 /* Check number of arguments, gather information */ 11325088Sab196087 switch (cmd) { 11335088Sab196087 case DYN_CMD_T_DUMP: 11345088Sab196087 /* dyn:dump can accept an optional index argument */ 11355088Sab196087 if (argstate.argc > 1) 11365088Sab196087 elfedit_command_usage(); 11375088Sab196087 print_only = 1; 11385088Sab196087 if (argstate.argc == 1) 11395088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11406225Sab196087 print_only, &print_type); 11415088Sab196087 break; 11425088Sab196087 11435088Sab196087 case DYN_CMD_T_TAG: 11445088Sab196087 print_only = (argstate.argc != 2); 11455088Sab196087 if (argstate.argc > 0) { 11465088Sab196087 if (argstate.argc > 2) 11475088Sab196087 elfedit_command_usage(); 11485088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11496225Sab196087 print_only, &print_type); 11505088Sab196087 } 11515088Sab196087 break; 11525088Sab196087 11535088Sab196087 case DYN_CMD_T_VALUE: 11545088Sab196087 print_only = (argstate.argc != 2); 11555088Sab196087 if (argstate.argc > 2) 11565088Sab196087 elfedit_command_usage(); 11575088Sab196087 if (argstate.argc > 0) { 11585088Sab196087 if (print_only) { 11595088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11605088Sab196087 print_only, &print_type); 11615088Sab196087 } else { 11625088Sab196087 print_type = PRINT_DYN_T_NDX; 11635088Sab196087 } 11645088Sab196087 } 11655088Sab196087 break; 11665088Sab196087 11675088Sab196087 case DYN_CMD_T_DELETE: 11685088Sab196087 if ((argstate.argc < 1) || (argstate.argc > 2)) 11695088Sab196087 elfedit_command_usage(); 11705088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11715088Sab196087 0, &print_type); 11725088Sab196087 do_autoprint = 0; 11735088Sab196087 break; 11745088Sab196087 11755088Sab196087 case DYN_CMD_T_MOVE: 11765088Sab196087 if ((argstate.argc < 2) || (argstate.argc > 3)) 11775088Sab196087 elfedit_command_usage(); 11785088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11796225Sab196087 0, &print_type); 11805088Sab196087 do_autoprint = 0; 11815088Sab196087 break; 11825088Sab196087 11835088Sab196087 case DYN_CMD_T_RUNPATH: 11845088Sab196087 if (argstate.argc > 1) 11855088Sab196087 elfedit_command_usage(); 11865088Sab196087 /* 11875088Sab196087 * dyn:runpath does not accept an explicit index 11885088Sab196087 * argument, so we implicitly only show the DT_RPATH and 11895088Sab196087 * DT_RUNPATH elements. 11905088Sab196087 */ 11915088Sab196087 print_type = PRINT_DYN_T_RUNPATH; 11925088Sab196087 print_only = (argstate.argc == 0); 11935088Sab196087 break; 11945088Sab196087 11955088Sab196087 case DYN_CMD_T_POSFLAG1: 11965088Sab196087 print_only = (argstate.argc == 0); 11975088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 11985088Sab196087 ELFEDIT_CONST_DT, DT_POSFLAG_1, 1), 11996225Sab196087 print_only, &print_type); 12005088Sab196087 break; 12015088Sab196087 12025088Sab196087 case DYN_CMD_T_FLAGS: 12035088Sab196087 print_only = (argstate.argc == 0); 12045088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12055088Sab196087 ELFEDIT_CONST_DT, DT_FLAGS, 1), 12066225Sab196087 print_only, &print_type); 12075088Sab196087 break; 12085088Sab196087 12095088Sab196087 case DYN_CMD_T_FLAGS1: 12105088Sab196087 print_only = (argstate.argc == 0); 12115088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12125088Sab196087 ELFEDIT_CONST_DT, DT_FLAGS_1, 1), 12136225Sab196087 print_only, &print_type); 12145088Sab196087 break; 12155088Sab196087 12165088Sab196087 case DYN_CMD_T_FEATURE1: 12175088Sab196087 print_only = (argstate.argc == 0); 12185088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12195088Sab196087 ELFEDIT_CONST_DT, DT_FEATURE_1, 1), 12206225Sab196087 print_only, &print_type); 12215088Sab196087 break; 12225088Sab196087 12235088Sab196087 case DYN_CMD_T_CHECKSUM: 12245088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12255088Sab196087 ELFEDIT_CONST_DT, DT_CHECKSUM, 1), 12266225Sab196087 print_only, &print_type); 12275088Sab196087 break; 12285088Sab196087 12296206Sab196087 case DYN_CMD_T_SUNW_LDMACH: 12306206Sab196087 if (argstate.argc > 1) 12316206Sab196087 elfedit_command_usage(); 12326206Sab196087 print_only = (argstate.argc == 0); 12336206Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12346206Sab196087 ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1), 12356225Sab196087 print_only, &print_type); 12366206Sab196087 break; 12376206Sab196087 12385088Sab196087 default: 12395088Sab196087 /* Note expected: All commands should have been caught above */ 12405088Sab196087 elfedit_command_usage(); 12415088Sab196087 break; 12425088Sab196087 } 12435088Sab196087 12445088Sab196087 12455088Sab196087 /* If this is a request to print current values, do it and return */ 12465088Sab196087 if (print_only) { 12475088Sab196087 print_dyn(cmd, 0, &argstate, print_type, ndx); 12485088Sab196087 return (ELFEDIT_CMDRET_NONE); 12495088Sab196087 } 12505088Sab196087 12515088Sab196087 12525088Sab196087 switch (cmd) { 12535088Sab196087 /* 12545088Sab196087 * DYN_CMD_T_DUMP can't get here: It is a print-only 12555088Sab196087 * command. 12565088Sab196087 */ 12575088Sab196087 12585088Sab196087 case DYN_CMD_T_TAG: 12595088Sab196087 { 12605088Sab196087 Conv_inv_buf_t inv_buf1, inv_buf2; 12615088Sab196087 Half mach = argstate.obj_state->os_ehdr->e_machine; 12625088Sab196087 Word d_tag = (Word) elfedit_atoconst(argstate.argv[1], 12635088Sab196087 ELFEDIT_CONST_DT); 12645088Sab196087 12655088Sab196087 if (dyn[ndx].d_tag == d_tag) { 12665088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12675088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), 12685088Sab196087 dyn_ndx, 12695088Sab196087 dyn_name, EC_WORD(ndx), 12705088Sab196087 conv_dyn_tag(d_tag, mach, 0, &inv_buf1)); 12715088Sab196087 } else { 12725088Sab196087 Word orig_d_tag = dyn[ndx].d_tag; 12735088Sab196087 12745088Sab196087 ret = ELFEDIT_CMDRET_MOD; 12755088Sab196087 dyn[ndx].d_tag = d_tag; 12765088Sab196087 12775088Sab196087 /* 12785088Sab196087 * Update null termination index. Warn if we 12795088Sab196087 * just clobbered the only DT_NULL termination 12805088Sab196087 * for the array. 12815088Sab196087 */ 12825088Sab196087 null_ndx = argstate.dyn.null_ndx; 12835088Sab196087 set_null_ndx(&argstate); 12845088Sab196087 if ((argstate.dyn.null_ndx >= 12855088Sab196087 argstate.dyn.num) && 12865088Sab196087 (null_ndx != argstate.dyn.null_ndx)) 12875088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12885088Sab196087 MSG_INTL(MSG_DEBUG_NULLTERM), 12895088Sab196087 dyn_ndx, dyn_name, 12905088Sab196087 EC_WORD(ndx), 12915088Sab196087 conv_dyn_tag(d_tag, mach, 12925088Sab196087 0, &inv_buf1)); 12935088Sab196087 12945088Sab196087 /* 12955088Sab196087 * Warning if 12965088Sab196087 * - Inserting a DT_NULL cuts off following 12975088Sab196087 * non-null elements. 12985088Sab196087 * - Inserting a non-DT_NULL after the 12995088Sab196087 * first null element, will be 13005088Sab196087 * ignored by rtld. 13015088Sab196087 */ 13025088Sab196087 if (d_tag == DT_NULL) { 13035088Sab196087 if ((ndx + 1) < null_ndx) 13045088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13055088Sab196087 MSG_INTL(MSG_DEBUG_NULCLIP), 13065088Sab196087 dyn_ndx, dyn_name, 13075088Sab196087 EC_WORD(ndx), 13085088Sab196087 conv_dyn_tag(d_tag, mach, 13095088Sab196087 0, &inv_buf1)); 13105088Sab196087 } else { 13115088Sab196087 if ((ndx + 1) > argstate.dyn.null_ndx) 13125088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13135088Sab196087 MSG_INTL(MSG_DEBUG_NULHIDE), 13145088Sab196087 dyn_ndx, dyn_name, 13155088Sab196087 EC_WORD(ndx), 13165088Sab196087 conv_dyn_tag(d_tag, mach, 13175088Sab196087 0, &inv_buf1)); 13185088Sab196087 } 13195088Sab196087 13205088Sab196087 /* Debug message that we changed it */ 13215088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13225088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 13235088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 13245088Sab196087 conv_dyn_tag(orig_d_tag, mach, 0, 13255088Sab196087 &inv_buf1), 13265088Sab196087 conv_dyn_tag(d_tag, mach, 0, &inv_buf2)); 13275088Sab196087 } 13285088Sab196087 } 13295088Sab196087 break; 13305088Sab196087 13315088Sab196087 case DYN_CMD_T_VALUE: 13325088Sab196087 ret = cmd_body_value(&argstate, &ndx); 13335088Sab196087 break; 13345088Sab196087 13355088Sab196087 case DYN_CMD_T_DELETE: 13365088Sab196087 { 13375088Sab196087 Word cnt = (argstate.argc == 1) ? 1 : 13385088Sab196087 (Word) elfedit_atoui_range(argstate.argv[1], 13395088Sab196087 MSG_ORIG(MSG_STR_COUNT), 1, dyn_num - ndx, NULL); 13405088Sab196087 const char *msg_prefix = 13415088Sab196087 elfedit_sec_msgprefix(argstate.dyn.sec); 13425088Sab196087 13435088Sab196087 elfedit_array_elts_delete(msg_prefix, argstate.dyn.data, 13445088Sab196087 sizeof (Dyn), dyn_num, ndx, cnt); 13455088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13465088Sab196087 } 13475088Sab196087 break; 13485088Sab196087 13495088Sab196087 case DYN_CMD_T_MOVE: 13505088Sab196087 { 13515088Sab196087 Dyn save; 13525088Sab196087 Word cnt; 13535088Sab196087 Word dstndx; 13545088Sab196087 const char *msg_prefix = 13555088Sab196087 elfedit_sec_msgprefix(argstate.dyn.sec); 13565088Sab196087 13575088Sab196087 dstndx = (Word) 13585088Sab196087 elfedit_atoui_range(argstate.argv[1], 13595088Sab196087 MSG_ORIG(MSG_STR_DST_INDEX), 0, dyn_num - 1, 13605088Sab196087 NULL); 13615088Sab196087 if (argstate.argc == 2) { 13625088Sab196087 cnt = 1; 13635088Sab196087 } else { 13645088Sab196087 cnt = (Word) elfedit_atoui_range( 13655088Sab196087 argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), 13665088Sab196087 1, dyn_num, NULL); 13675088Sab196087 } 13685088Sab196087 elfedit_array_elts_move(msg_prefix, argstate.dyn.data, 13695088Sab196087 sizeof (save), dyn_num, ndx, dstndx, cnt, &save); 13705088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13715088Sab196087 } 13725088Sab196087 break; 13735088Sab196087 13745088Sab196087 13755088Sab196087 case DYN_CMD_T_RUNPATH: 13765088Sab196087 ret = cmd_body_runpath(&argstate); 13775088Sab196087 break; 13785088Sab196087 13795088Sab196087 case DYN_CMD_T_POSFLAG1: 13805088Sab196087 { 13815088Sab196087 Conv_dyn_posflag1_buf_t buf1, buf2; 13825088Sab196087 Word flags; 13835088Sab196087 13845088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 13855088Sab196087 ELFEDIT_CONST_DF_P1); 13865088Sab196087 13875088Sab196087 /* Set the value */ 13885088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 13895088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13905088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 13915088Sab196087 dyn_name, EC_WORD(ndx), 13925088Sab196087 conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 13935088Sab196087 &buf1)); 13945088Sab196087 } else { 13955088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13965088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 13975088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 13985088Sab196087 conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 13995088Sab196087 &buf1), 14005088Sab196087 conv_dyn_posflag1(flags, 0, &buf2)); 14015088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14025088Sab196087 dyn[ndx].d_un.d_val = flags; 14035088Sab196087 } 14045088Sab196087 } 14055088Sab196087 break; 14065088Sab196087 14075088Sab196087 case DYN_CMD_T_FLAGS: 14085088Sab196087 { 14095088Sab196087 Conv_dyn_flag_buf_t buf1, buf2; 14105088Sab196087 Word flags; 14115088Sab196087 14125088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14135088Sab196087 ELFEDIT_CONST_DF); 14145088Sab196087 14155088Sab196087 /* Set the value */ 14165088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 14175088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14185088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14195088Sab196087 dyn_name, EC_WORD(ndx), 14205088Sab196087 conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 14215088Sab196087 &buf1)); 14225088Sab196087 } else { 14235088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14245088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14255088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14265088Sab196087 conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 14275088Sab196087 &buf1), 14285088Sab196087 conv_dyn_flag(flags, 0, &buf2)); 14295088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14305088Sab196087 dyn[ndx].d_un.d_val = flags; 14315088Sab196087 } 14325088Sab196087 } 14335088Sab196087 break; 14345088Sab196087 14355088Sab196087 case DYN_CMD_T_FLAGS1: 14365088Sab196087 { 14375088Sab196087 Conv_dyn_flag1_buf_t buf1, buf2; 14385088Sab196087 Word flags1; 14395088Sab196087 14405088Sab196087 flags1 = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14415088Sab196087 ELFEDIT_CONST_DF_1); 14425088Sab196087 14435088Sab196087 /* Set the value */ 14445088Sab196087 if (dyn[ndx].d_un.d_val == flags1) { 14455088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14465088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14475088Sab196087 dyn_name, EC_WORD(ndx), 14485088Sab196087 conv_dyn_flag1(dyn[ndx].d_un.d_val, 14495088Sab196087 0, &buf1)); 14505088Sab196087 } else { 14515088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14525088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14535088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14545088Sab196087 conv_dyn_flag1(dyn[ndx].d_un.d_val, 14555088Sab196087 0, &buf1), 14565088Sab196087 conv_dyn_flag1(flags1, 0, &buf2)); 14575088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14585088Sab196087 dyn[ndx].d_un.d_val = flags1; 14595088Sab196087 } 14605088Sab196087 } 14615088Sab196087 break; 14625088Sab196087 14635088Sab196087 case DYN_CMD_T_FEATURE1: 14645088Sab196087 { 14655088Sab196087 Conv_dyn_feature1_buf_t buf1, buf2; 14665088Sab196087 Word flags; 14675088Sab196087 14685088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14695088Sab196087 ELFEDIT_CONST_DTF_1); 14705088Sab196087 14715088Sab196087 /* Set the value */ 14725088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 14735088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14745088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14755088Sab196087 dyn_name, EC_WORD(ndx), 14765088Sab196087 conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 14775088Sab196087 &buf1)); 14785088Sab196087 } else { 14795088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14805088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14815088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14825088Sab196087 conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 14835088Sab196087 &buf1), 14845088Sab196087 conv_dyn_feature1(flags, 0, &buf2)); 14855088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14865088Sab196087 dyn[ndx].d_un.d_val = flags; 14875088Sab196087 } 14885088Sab196087 } 14895088Sab196087 break; 14905088Sab196087 14915088Sab196087 case DYN_CMD_T_CHECKSUM: 14925088Sab196087 { 14935088Sab196087 long checksum = elf_checksum(obj_state->os_elf); 14945088Sab196087 14955088Sab196087 /* Set the value */ 14965088Sab196087 if (dyn[ndx].d_un.d_val == checksum) { 14975088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14985088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), dyn_ndx, 14995088Sab196087 dyn_name, EC_WORD(ndx), EC_XWORD(checksum)); 15005088Sab196087 } else { 15015088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15025088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 15035088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 15045088Sab196087 EC_XWORD(dyn[ndx].d_un.d_val), 15055088Sab196087 EC_XWORD(checksum)); 15065088Sab196087 ret = ELFEDIT_CMDRET_MOD; 15075088Sab196087 dyn[ndx].d_un.d_val = checksum; 15085088Sab196087 } 15095088Sab196087 15105088Sab196087 } 15116206Sab196087 break; 15126206Sab196087 15136206Sab196087 case DYN_CMD_T_SUNW_LDMACH: 15146206Sab196087 { 15156206Sab196087 Conv_inv_buf_t buf1, buf2; 15166206Sab196087 Half ldmach; 15176206Sab196087 15186206Sab196087 ldmach = (Half) elfedit_atoconst(argstate.argv[0], 15196206Sab196087 ELFEDIT_CONST_EM); 15206206Sab196087 15216206Sab196087 /* Set the value */ 15226206Sab196087 if (dyn[ndx].d_un.d_val == ldmach) { 15236206Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15246206Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 15256206Sab196087 dyn_name, EC_WORD(ndx), 15266206Sab196087 conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 15276206Sab196087 &buf1)); 15286206Sab196087 } else { 15296206Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15306206Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 15316206Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 15326206Sab196087 conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 15336206Sab196087 &buf1), 15346206Sab196087 conv_ehdr_mach(ldmach, 0, &buf2)); 15356206Sab196087 ret = ELFEDIT_CMDRET_MOD; 15366206Sab196087 dyn[ndx].d_un.d_val = ldmach; 15376206Sab196087 } 15386206Sab196087 } 15396206Sab196087 break; 15406206Sab196087 15415088Sab196087 } 15425088Sab196087 15435088Sab196087 /* 15445088Sab196087 * If we modified the dynamic section header, tell libelf. 15455088Sab196087 */ 15465088Sab196087 if (ret == ELFEDIT_CMDRET_MOD) 15475088Sab196087 elfedit_modified_data(argstate.dyn.sec); 15485088Sab196087 15495088Sab196087 /* Do autoprint */ 15505088Sab196087 if (do_autoprint) 15515088Sab196087 print_dyn(cmd, 1, &argstate, print_type, ndx); 15525088Sab196087 15535088Sab196087 return (ret); 15545088Sab196087 } 15555088Sab196087 15565088Sab196087 15575088Sab196087 15585088Sab196087 /* 15595088Sab196087 * Command completion functions for the commands 15605088Sab196087 */ 15615088Sab196087 15625088Sab196087 /* 15635088Sab196087 * Command completion for the first argument, which specifies 15645088Sab196087 * the dynamic element to use. Examines the options to see if 15655088Sab196087 * -dynndx is present, and if not, supplies the completion 15665088Sab196087 * strings for argument 1. 15675088Sab196087 */ 15685088Sab196087 /*ARGSUSED*/ 15695088Sab196087 static void 15705088Sab196087 cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 15715088Sab196087 const char *argv[], int num_opt) 15725088Sab196087 { 15735088Sab196087 elfedit_section_t *cache; 15745088Sab196087 Dyn *dyn; 15755088Sab196087 Word i; 15765088Sab196087 const char *s; 15775088Sab196087 char *s2; 15785088Sab196087 char buf[128]; 15795088Sab196087 15805088Sab196087 /* Make sure it's the first argument */ 15815088Sab196087 if ((argc - num_opt) != 1) 15825088Sab196087 return; 15835088Sab196087 15845088Sab196087 /* Is -dynndx present? If so, we don't complete tag types */ 15855088Sab196087 for (i = 0; i < num_opt; i++) 15865088Sab196087 if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0) 15875088Sab196087 return; 15885088Sab196087 15895088Sab196087 /* 15905088Sab196087 * If there is no object, or if there is no dynamic section, 15915088Sab196087 * then supply all possible names. 15925088Sab196087 */ 15935088Sab196087 if ((obj_state == NULL) || (obj_state->os_dynndx == SHN_UNDEF)) { 15945088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 15955088Sab196087 return; 15965088Sab196087 } 15975088Sab196087 15985088Sab196087 /* Supply completions for the tags present in the dynamic section */ 15995088Sab196087 cache = &obj_state->os_secarr[obj_state->os_dynndx]; 16005088Sab196087 dyn = (Dyn *) cache->sec_data->d_buf; 16015088Sab196087 i = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize; 16025088Sab196087 for (; i-- > 0; dyn++) { 16035088Sab196087 s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_DT, 16045088Sab196087 dyn->d_tag, 0); 16055088Sab196087 if (s == NULL) 16065088Sab196087 continue; 16075088Sab196087 elfedit_cpl_match(cpldata, s, 1); 16085088Sab196087 16095088Sab196087 /* 16105088Sab196087 * To get the informal tag names that are lowercase 16115088Sab196087 * and lack the leading DT_, we copy the string we 16125088Sab196087 * have into a buffer and process it. 16135088Sab196087 */ 16145088Sab196087 if (strlen(s) < 3) 16155088Sab196087 continue; 16165088Sab196087 (void) strlcpy(buf, s + 3, sizeof (buf)); 16175088Sab196087 for (s2 = buf; *s2 != '\0'; s2++) 16185088Sab196087 if (isupper(*s2)) 16195088Sab196087 *s2 = tolower(*s2); 16205088Sab196087 elfedit_cpl_match(cpldata, buf, 1); 16215088Sab196087 } 16225088Sab196087 } 16235088Sab196087 16245088Sab196087 16255088Sab196087 /*ARGSUSED*/ 16265088Sab196087 static void 16275088Sab196087 cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16285088Sab196087 const char *argv[], int num_opt) 16295088Sab196087 { 16305088Sab196087 /* First argument */ 16315088Sab196087 if ((argc - num_opt) == 1) { 16325088Sab196087 cpl_eltarg(obj_state, cpldata, argc, argv, num_opt); 16335088Sab196087 return; 16345088Sab196087 } 16355088Sab196087 16365088Sab196087 /* The second argument is always a tag value */ 16375088Sab196087 if ((argc - num_opt) == 2) 16385088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 16395088Sab196087 } 16405088Sab196087 16415088Sab196087 /*ARGSUSED*/ 16425088Sab196087 static void 16435088Sab196087 cpl_posflag1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16445088Sab196087 const char *argv[], int num_opt) 16455088Sab196087 { 16466225Sab196087 /* 16476225Sab196087 * dyn:posflag1 accepts two mutually exclusive options that have 16486225Sab196087 * a corresponding value argument: -dynndx and -needed. If we 16496225Sab196087 * are being called to supply options for the value, handle that here. 16506225Sab196087 */ 16516225Sab196087 if ((num_opt > 1) && (argc == num_opt)) { 16526225Sab196087 elfedit_section_t *dynsec, *strsec; 16536225Sab196087 const char *opt = argv[num_opt - 2]; 16546225Sab196087 dyn_opt_t type; 16556225Sab196087 Dyn *dyn; 16566225Sab196087 Word i, num; 16576225Sab196087 16586225Sab196087 /* 16596225Sab196087 * If there is no object available, or if the object has no 16606225Sab196087 * dynamic section, then there is nothing to report. 16616225Sab196087 */ 16626225Sab196087 if ((obj_state == NULL) || obj_state->os_dynndx == SHN_UNDEF) 16636225Sab196087 return; 16646225Sab196087 16656225Sab196087 /* 16666225Sab196087 * Determine which option it is, bail if it isn't one of 16676225Sab196087 * the ones we are concerned with. 16686225Sab196087 */ 16696225Sab196087 if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_NEEDED)) == 0)) 16706225Sab196087 type = DYN_OPT_F_NEEDED; 16716225Sab196087 else if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0)) 16726225Sab196087 type = DYN_OPT_F_DYNNDX_VAL; 16736225Sab196087 else 16746225Sab196087 return; 16756225Sab196087 16766225Sab196087 dynsec = elfedit_sec_getdyn(obj_state, &dyn, &num); 16776225Sab196087 switch (type) { 16786225Sab196087 case DYN_OPT_F_NEEDED: 16796225Sab196087 strsec = elfedit_sec_getstr(obj_state, 16806225Sab196087 dynsec->sec_shdr->sh_link, 0); 16816225Sab196087 for (; num-- > 0; dyn++) 16826225Sab196087 if (dyn->d_tag == DT_NEEDED) 16836225Sab196087 elfedit_cpl_match(cpldata, 16846225Sab196087 elfedit_offset_to_str(strsec, 16856225Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 16866225Sab196087 0), 0); 16876225Sab196087 break; 16886225Sab196087 16896225Sab196087 case DYN_OPT_F_DYNNDX_VAL: 16906225Sab196087 for (i = 0; i < num; i++, dyn++) 16916225Sab196087 if (dyn->d_tag == DT_POSFLAG_1) 16926225Sab196087 elfedit_cpl_ndx(cpldata, i); 16936225Sab196087 break; 16946225Sab196087 } 16956225Sab196087 return; 16966225Sab196087 } 16976225Sab196087 16985088Sab196087 /* This routine allows multiple flags to be specified */ 16995088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_P1); 17005088Sab196087 } 17015088Sab196087 17025088Sab196087 /*ARGSUSED*/ 17035088Sab196087 static void 17045088Sab196087 cpl_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17055088Sab196087 const char *argv[], int num_opt) 17065088Sab196087 { 17075088Sab196087 /* This routine allows multiple flags to be specified */ 17085088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF); 17095088Sab196087 } 17105088Sab196087 17115088Sab196087 /*ARGSUSED*/ 17125088Sab196087 static void 17135088Sab196087 cpl_flags1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17145088Sab196087 const char *argv[], int num_opt) 17155088Sab196087 { 17165088Sab196087 /* This routine allows multiple flags to be specified */ 17175088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_1); 17185088Sab196087 } 17195088Sab196087 17205088Sab196087 /*ARGSUSED*/ 17215088Sab196087 static void 17225088Sab196087 cpl_feature1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17235088Sab196087 const char *argv[], int num_opt) 17245088Sab196087 { 17255088Sab196087 /* This routine allows multiple flags to be specified */ 17265088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1); 17275088Sab196087 } 17285088Sab196087 17296206Sab196087 /*ARGSUSED*/ 17306206Sab196087 static void 17316206Sab196087 cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17326206Sab196087 const char *argv[], int num_opt) 17336206Sab196087 { 17346206Sab196087 /* 17356206Sab196087 * This command doesn't accept options, so num_opt should be 17366206Sab196087 * 0. This is a defensive measure, in case that should change. 17376206Sab196087 */ 17386206Sab196087 argc -= num_opt; 17396206Sab196087 argv += num_opt; 17406206Sab196087 17416206Sab196087 if (argc == 1) 17426206Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM); 17436206Sab196087 } 17446206Sab196087 17455088Sab196087 17465088Sab196087 /* 17475088Sab196087 * Implementation functions for the commands 17485088Sab196087 */ 17495088Sab196087 static elfedit_cmdret_t 17505088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17515088Sab196087 { 17525088Sab196087 return (cmd_body(DYN_CMD_T_DUMP, obj_state, argc, argv)); 17535088Sab196087 } 17545088Sab196087 17555088Sab196087 static elfedit_cmdret_t 17565088Sab196087 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17575088Sab196087 { 17585088Sab196087 return (cmd_body(DYN_CMD_T_TAG, obj_state, argc, argv)); 17595088Sab196087 } 17605088Sab196087 17615088Sab196087 static elfedit_cmdret_t 17625088Sab196087 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17635088Sab196087 { 17645088Sab196087 return (cmd_body(DYN_CMD_T_VALUE, obj_state, argc, argv)); 17655088Sab196087 } 17665088Sab196087 17675088Sab196087 static elfedit_cmdret_t 17685088Sab196087 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17695088Sab196087 { 17705088Sab196087 return (cmd_body(DYN_CMD_T_DELETE, obj_state, argc, argv)); 17715088Sab196087 } 17725088Sab196087 17735088Sab196087 static elfedit_cmdret_t 17745088Sab196087 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17755088Sab196087 { 17765088Sab196087 return (cmd_body(DYN_CMD_T_MOVE, obj_state, argc, argv)); 17775088Sab196087 } 17785088Sab196087 17795088Sab196087 static elfedit_cmdret_t 17805088Sab196087 cmd_runpath(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17815088Sab196087 { 17825088Sab196087 return (cmd_body(DYN_CMD_T_RUNPATH, obj_state, argc, argv)); 17835088Sab196087 } 17845088Sab196087 17855088Sab196087 static elfedit_cmdret_t 17865088Sab196087 cmd_posflag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17875088Sab196087 { 17885088Sab196087 return (cmd_body(DYN_CMD_T_POSFLAG1, obj_state, argc, argv)); 17895088Sab196087 } 17905088Sab196087 17915088Sab196087 static elfedit_cmdret_t 17925088Sab196087 cmd_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17935088Sab196087 { 17945088Sab196087 return (cmd_body(DYN_CMD_T_FLAGS, obj_state, argc, argv)); 17955088Sab196087 } 17965088Sab196087 17975088Sab196087 static elfedit_cmdret_t 17985088Sab196087 cmd_flags1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17995088Sab196087 { 18005088Sab196087 return (cmd_body(DYN_CMD_T_FLAGS1, obj_state, argc, argv)); 18015088Sab196087 } 18025088Sab196087 18035088Sab196087 static elfedit_cmdret_t 18045088Sab196087 cmd_feature1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18055088Sab196087 { 18065088Sab196087 return (cmd_body(DYN_CMD_T_FEATURE1, obj_state, argc, argv)); 18075088Sab196087 } 18085088Sab196087 18095088Sab196087 static elfedit_cmdret_t 18105088Sab196087 cmd_checksum(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18115088Sab196087 { 18125088Sab196087 return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv)); 18135088Sab196087 } 18145088Sab196087 18156206Sab196087 static elfedit_cmdret_t 18166206Sab196087 cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18176206Sab196087 { 18186206Sab196087 return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv)); 18196206Sab196087 } 18206206Sab196087 18215088Sab196087 18225088Sab196087 18235088Sab196087 /*ARGSUSED*/ 18245088Sab196087 elfedit_module_t * 18255088Sab196087 elfedit_init(elfedit_module_version_t version) 18265088Sab196087 { 18275088Sab196087 /* For commands that only accept -o */ 18285088Sab196087 static elfedit_cmd_optarg_t opt_ostyle[] = { 18295088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18305088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18315088Sab196087 { NULL } 18325088Sab196087 }; 18335088Sab196087 18345088Sab196087 /* For commands that only accept -and, -cmp, -o, -or */ 18355088Sab196087 static elfedit_cmd_optarg_t opt_ostyle_bitop[] = { 18365088Sab196087 { ELFEDIT_STDOA_OPT_AND, NULL, 18375088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 18385088Sab196087 { ELFEDIT_STDOA_OPT_CMP, NULL, 18395088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 18405088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18415088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18425088Sab196087 { ELFEDIT_STDOA_OPT_OR, NULL, 18435088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 18445088Sab196087 { NULL } 18455088Sab196087 }; 18465088Sab196087 18475088Sab196087 /* For commands that only accept -dynndx */ 18485088Sab196087 static elfedit_cmd_optarg_t opt_minus_dynndx[] = { 18495088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 18506225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 18516225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 18526225Sab196087 DYN_OPT_F_DYNNDX_ELT, 0 }, 18535088Sab196087 { NULL } 18545088Sab196087 }; 18555088Sab196087 18565088Sab196087 /* dyn:dump */ 18575088Sab196087 static const char *name_dump[] = { 18585088Sab196087 MSG_ORIG(MSG_CMD_DUMP), 18595088Sab196087 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 18605088Sab196087 NULL 18615088Sab196087 }; 18625088Sab196087 static elfedit_cmd_optarg_t arg_dump[] = { 18635088Sab196087 { MSG_ORIG(MSG_STR_ELT), 18645088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 18655088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 18665088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18675088Sab196087 { NULL } 18685088Sab196087 }; 18695088Sab196087 18705088Sab196087 18715088Sab196087 /* dyn:tag */ 18725088Sab196087 static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL }; 18735088Sab196087 static elfedit_cmd_optarg_t opt_tag[] = { 18745088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 18756225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 18766225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 18776225Sab196087 DYN_OPT_F_DYNNDX_ELT, 0 }, 18785088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18795088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18805088Sab196087 { NULL } 18815088Sab196087 }; 18825088Sab196087 static elfedit_cmd_optarg_t arg_tag[] = { 18835088Sab196087 { MSG_ORIG(MSG_STR_ELT), 18845088Sab196087 /* MSG_INTL(MSG_A1_TAG_ELT) */ 18855088Sab196087 ELFEDIT_I18NHDL(MSG_A1_TAG_ELT), 18865088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18875088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 18885088Sab196087 /* MSG_INTL(MSG_A2_TAG_VALUE) */ 18895088Sab196087 ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE), 18905088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18915088Sab196087 { NULL } 18925088Sab196087 }; 18935088Sab196087 18945088Sab196087 18955088Sab196087 /* dyn:value */ 18965088Sab196087 static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL }; 18975088Sab196087 static elfedit_cmd_optarg_t opt_value[] = { 18985088Sab196087 { MSG_ORIG(MSG_STR_MINUS_ADD), 18995088Sab196087 /* MSG_INTL(MSG_OPTDESC_ADD) */ 19005088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_ADD), 0, 19016225Sab196087 DYN_OPT_F_ADD, DYN_OPT_F_DYNNDX_ELT }, 19025088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 19036225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 19046225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 19056225Sab196087 DYN_OPT_F_DYNNDX_ELT, DYN_OPT_F_ADD }, 19065088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 19075088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 19085088Sab196087 { MSG_ORIG(MSG_STR_MINUS_S), 19095088Sab196087 /* MSG_INTL(MSG_OPTDESC_S) */ 19105088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0, 19115088Sab196087 DYN_OPT_F_STRVAL, 0 }, 19125088Sab196087 { NULL } 19135088Sab196087 }; 19145088Sab196087 static elfedit_cmd_optarg_t arg_value[] = { 19155088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19165088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19175088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19185088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19195088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19205088Sab196087 /* MSG_INTL(MSG_A2_VALUE_VALUE) */ 19215088Sab196087 ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE), 19225088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19235088Sab196087 { NULL } 19245088Sab196087 }; 19255088Sab196087 19265088Sab196087 /* dyn:delete */ 19275088Sab196087 static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL }; 19285088Sab196087 static elfedit_cmd_optarg_t arg_delete[] = { 19295088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19305088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19315088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19325088Sab196087 0 }, 19335088Sab196087 { MSG_ORIG(MSG_STR_COUNT), 19345088Sab196087 /* MSG_INTL(MSG_A2_DELETE_COUNT) */ 19355088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT), 19365088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19375088Sab196087 { NULL } 19385088Sab196087 }; 19395088Sab196087 19405088Sab196087 /* dyn:move */ 19415088Sab196087 static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL }; 19425088Sab196087 static elfedit_cmd_optarg_t arg_move[] = { 19435088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19445088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19455088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19465088Sab196087 0 }, 19475088Sab196087 { MSG_ORIG(MSG_STR_DST_INDEX), 19485088Sab196087 /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */ 19495088Sab196087 ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX), 19505088Sab196087 0 }, 19515088Sab196087 { MSG_ORIG(MSG_STR_COUNT), 19525088Sab196087 /* MSG_INTL(MSG_A3_MOVE_COUNT) */ 19535088Sab196087 ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT), 19545088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19555088Sab196087 { NULL } 19565088Sab196087 }; 19575088Sab196087 19585088Sab196087 /* dyn:runpath / dyn:rpath */ 19595088Sab196087 static const char *name_runpath[] = { MSG_ORIG(MSG_CMD_RUNPATH), 19605088Sab196087 MSG_ORIG(MSG_CMD_RUNPATH_A1), NULL }; 19615088Sab196087 static elfedit_cmd_optarg_t arg_runpath[] = { 19625088Sab196087 { MSG_ORIG(MSG_STR_NEWPATH), 19635088Sab196087 /* MSG_INTL(MSG_A1_RUNPATH_NEWPATH) */ 19645088Sab196087 ELFEDIT_I18NHDL(MSG_A1_RUNPATH_NEWPATH), 19655088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19665088Sab196087 { NULL } 19675088Sab196087 }; 19685088Sab196087 19695088Sab196087 /* dyn:posflag1 */ 19705088Sab196087 static const char *name_posflag1[] = { MSG_ORIG(MSG_CMD_POSFLAG1), 19715088Sab196087 NULL }; 19726225Sab196087 static elfedit_cmd_optarg_t opt_posflag1[] = { 19736225Sab196087 { ELFEDIT_STDOA_OPT_AND, NULL, 19746225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 19756225Sab196087 { ELFEDIT_STDOA_OPT_CMP, NULL, 19766225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 19776225Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 19786225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_VAL) */ 19796225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_VAL), 19806225Sab196087 ELFEDIT_CMDOA_F_VALUE, 19816225Sab196087 DYN_OPT_F_DYNNDX_VAL, DYN_OPT_F_NEEDED }, 19826225Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 19836225Sab196087 { MSG_ORIG(MSG_STR_MINUS_NEEDED), 19846225Sab196087 /* MSG_INTL(MSG_OPTDESC_NEEDED) */ 19856225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_NEEDED), 19866225Sab196087 ELFEDIT_CMDOA_F_VALUE, 19876225Sab196087 DYN_OPT_F_NEEDED, DYN_OPT_F_DYNNDX_VAL }, 19886225Sab196087 { MSG_ORIG(MSG_STR_PREFIX), NULL, 0, 0 }, 19896225Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 19906225Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 19916225Sab196087 { ELFEDIT_STDOA_OPT_OR, NULL, 19926225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 19936225Sab196087 { NULL } 19946225Sab196087 }; 19955088Sab196087 static elfedit_cmd_optarg_t arg_posflag1[] = { 19965088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19975088Sab196087 /* MSG_INTL(MSG_A1_POSFLAG1_VALUE) */ 19985088Sab196087 ELFEDIT_I18NHDL(MSG_A1_POSFLAG1_VALUE), 19995088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20005088Sab196087 { NULL } 20015088Sab196087 }; 20025088Sab196087 20035088Sab196087 /* dyn:flags */ 20045088Sab196087 static const char *name_flags[] = { MSG_ORIG(MSG_CMD_FLAGS), NULL }; 20055088Sab196087 static elfedit_cmd_optarg_t arg_flags[] = { 20065088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20075088Sab196087 /* MSG_INTL(MSG_A1_FLAGS_VALUE) */ 20085088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FLAGS_VALUE), 20095088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20105088Sab196087 { NULL } 20115088Sab196087 }; 20125088Sab196087 20135088Sab196087 /* dyn:flags1 */ 20145088Sab196087 static const char *name_flags1[] = { MSG_ORIG(MSG_CMD_FLAGS1), NULL }; 20155088Sab196087 static elfedit_cmd_optarg_t arg_flags1[] = { 20165088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20175088Sab196087 /* MSG_INTL(MSG_A1_FLAGS1_VALUE) */ 20185088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FLAGS1_VALUE), 20195088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20205088Sab196087 { NULL } 20215088Sab196087 }; 20225088Sab196087 20235088Sab196087 /* dyn:feature1 */ 20245088Sab196087 static const char *name_feature1[] = { MSG_ORIG(MSG_CMD_FEATURE1), 20255088Sab196087 NULL }; 20265088Sab196087 static elfedit_cmd_optarg_t arg_feature1[] = { 20275088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20285088Sab196087 /* MSG_INTL(MSG_A1_FEATURE1_VALUE) */ 20295088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FEATURE1_VALUE), 20305088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20315088Sab196087 { NULL } 20325088Sab196087 }; 20335088Sab196087 20345088Sab196087 /* dyn:checksum */ 20355088Sab196087 static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM), 20365088Sab196087 NULL }; 20375088Sab196087 20386206Sab196087 /* dyn:sunw_ldmach */ 20396206Sab196087 static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH), 20406206Sab196087 NULL }; 20416206Sab196087 static elfedit_cmd_optarg_t arg_sunw_ldmach[] = { 20426206Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20436206Sab196087 /* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */ 20446206Sab196087 ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE), 20456206Sab196087 ELFEDIT_CMDOA_F_OPT }, 20466206Sab196087 { NULL } 20476206Sab196087 }; 20486206Sab196087 20495088Sab196087 20505088Sab196087 20515088Sab196087 static elfedit_cmd_t cmds[] = { 20525088Sab196087 /* dyn:dump */ 20535088Sab196087 { cmd_dump, cpl_eltarg, name_dump, 20545088Sab196087 /* MSG_INTL(MSG_DESC_DUMP) */ 20555088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 20565088Sab196087 /* MSG_INTL(MSG_HELP_DUMP) */ 20575088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 20585088Sab196087 opt_minus_dynndx, arg_dump }, 20595088Sab196087 20605088Sab196087 /* dyn:tag */ 20615088Sab196087 { cmd_tag, cpl_tag, name_tag, 20625088Sab196087 /* MSG_INTL(MSG_DESC_TAG) */ 20635088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_TAG), 20645088Sab196087 /* MSG_INTL(MSG_HELP_TAG) */ 20655088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_TAG), 20665088Sab196087 opt_tag, arg_tag }, 20675088Sab196087 20685088Sab196087 /* dyn:value */ 20695088Sab196087 { cmd_value, cpl_eltarg, name_value, 20705088Sab196087 /* MSG_INTL(MSG_DESC_VALUE) */ 20715088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_VALUE), 20725088Sab196087 /* MSG_INTL(MSG_HELP_VALUE) */ 20735088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_VALUE), 20745088Sab196087 opt_value, arg_value }, 20755088Sab196087 20765088Sab196087 /* dyn:delete */ 20775088Sab196087 { cmd_delete, cpl_eltarg, name_delete, 20785088Sab196087 /* MSG_INTL(MSG_DESC_DELETE) */ 20795088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DELETE), 20805088Sab196087 /* MSG_INTL(MSG_HELP_DELETE) */ 20815088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DELETE), 20825088Sab196087 opt_minus_dynndx, arg_delete }, 20835088Sab196087 20845088Sab196087 /* dyn:move */ 20855088Sab196087 { cmd_move, cpl_eltarg, name_move, 20865088Sab196087 /* MSG_INTL(MSG_DESC_MOVE) */ 20875088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_MOVE), 20885088Sab196087 /* MSG_INTL(MSG_HELP_MOVE) */ 20895088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_MOVE), 20905088Sab196087 opt_minus_dynndx, arg_move }, 20915088Sab196087 20925088Sab196087 /* dyn:runpath */ 20935088Sab196087 { cmd_runpath, NULL, name_runpath, 20945088Sab196087 /* MSG_INTL(MSG_DESC_RUNPATH) */ 20955088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_RUNPATH), 20965088Sab196087 /* MSG_INTL(MSG_HELP_RUNPATH) */ 20975088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_RUNPATH), 20985088Sab196087 opt_ostyle, arg_runpath }, 20995088Sab196087 21005088Sab196087 /* dyn:posflag1 */ 21015088Sab196087 { cmd_posflag1, cpl_posflag1, name_posflag1, 21025088Sab196087 /* MSG_INTL(MSG_DESC_POSFLAG1) */ 21035088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_POSFLAG1), 21045088Sab196087 /* MSG_INTL(MSG_HELP_POSFLAG1) */ 21055088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_POSFLAG1), 21066225Sab196087 opt_posflag1, arg_posflag1 }, 21075088Sab196087 21085088Sab196087 /* dyn:flags */ 21095088Sab196087 { cmd_flags, cpl_flags, name_flags, 21105088Sab196087 /* MSG_INTL(MSG_DESC_FLAGS) */ 21115088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FLAGS), 21125088Sab196087 /* MSG_INTL(MSG_HELP_FLAGS) */ 21135088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FLAGS), 21145088Sab196087 opt_ostyle_bitop, arg_flags }, 21155088Sab196087 21165088Sab196087 /* dyn:flags1 */ 21175088Sab196087 { cmd_flags1, cpl_flags1, name_flags1, 21185088Sab196087 /* MSG_INTL(MSG_DESC_FLAGS1) */ 21195088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FLAGS1), 21205088Sab196087 /* MSG_INTL(MSG_HELP_FLAGS1) */ 21215088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FLAGS1), 21225088Sab196087 opt_ostyle_bitop, arg_flags1 }, 21235088Sab196087 21245088Sab196087 /* dyn:feature1 */ 21255088Sab196087 { cmd_feature1, cpl_feature1, name_feature1, 21265088Sab196087 /* MSG_INTL(MSG_DESC_FEATURE1) */ 21275088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FEATURE1), 21285088Sab196087 /* MSG_INTL(MSG_HELP_FEATURE1) */ 21295088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FEATURE1), 21305088Sab196087 opt_ostyle_bitop, arg_feature1 }, 21315088Sab196087 21325088Sab196087 /* dyn:checksum */ 21335088Sab196087 { cmd_checksum, NULL, name_checksum, 21345088Sab196087 /* MSG_INTL(MSG_DESC_CHECKSUM) */ 21355088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_CHECKSUM), 21365088Sab196087 /* MSG_INTL(MSG_HELP_CHECKSUM) */ 21375088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM), 21385088Sab196087 NULL, NULL }, 21395088Sab196087 21406206Sab196087 /* dyn:sunw_ldmach */ 21416206Sab196087 { cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach, 21426206Sab196087 /* MSG_INTL(MSG_DESC_SUNW_LDMACH) */ 21436206Sab196087 ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH), 21446206Sab196087 /* MSG_INTL(MSG_HELP_SUNW_LDMACH) */ 21456206Sab196087 ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH), 21466206Sab196087 opt_ostyle, arg_sunw_ldmach }, 21476206Sab196087 21485088Sab196087 { NULL } 21495088Sab196087 }; 21505088Sab196087 21515088Sab196087 static elfedit_module_t module = { 21525088Sab196087 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 21535088Sab196087 /* MSG_INTL(MSG_MOD_DESC) */ 21545088Sab196087 ELFEDIT_I18NHDL(MSG_MOD_DESC), cmds, mod_i18nhdl_to_str }; 21555088Sab196087 21565088Sab196087 return (&module); 21575088Sab196087 } 2158