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 #pragma ident "%Z%%M% %I% %E% SMI" 275088Sab196087 285088Sab196087 #include <ctype.h> 295088Sab196087 #include <elfedit.h> 305088Sab196087 #include <sys/elf_SPARC.h> 315088Sab196087 #include <strings.h> 325088Sab196087 #include <debug.h> 335088Sab196087 #include <conv.h> 345088Sab196087 #include <dyn_msg.h> 355088Sab196087 365088Sab196087 375088Sab196087 /* 385088Sab196087 * Dynamic section 395088Sab196087 */ 405088Sab196087 415088Sab196087 425088Sab196087 435088Sab196087 445088Sab196087 /* 455088Sab196087 * This module uses shared code for several of the commands. 465088Sab196087 * It is sometimes necessary to know which specific command 475088Sab196087 * is active. 485088Sab196087 */ 495088Sab196087 typedef enum { 505088Sab196087 /* Dump command, used as module default to display dynamic section */ 515088Sab196087 DYN_CMD_T_DUMP = 0, /* dyn:dump */ 525088Sab196087 535088Sab196087 /* Commands that do not correspond directly to a specific DT tag */ 545088Sab196087 DYN_CMD_T_TAG = 1, /* dyn:tag */ 555088Sab196087 DYN_CMD_T_VALUE = 2, /* dyn:value */ 565088Sab196087 DYN_CMD_T_DELETE = 3, /* dyn:delete */ 575088Sab196087 DYN_CMD_T_MOVE = 4, /* dyn:shift */ 585088Sab196087 595088Sab196087 /* Commands that embody tag specific knowledge */ 605088Sab196087 DYN_CMD_T_RUNPATH = 5, /* dyn:runpath/rpath */ 615088Sab196087 DYN_CMD_T_POSFLAG1 = 6, /* dyn:posflag1 */ 625088Sab196087 DYN_CMD_T_FLAGS = 7, /* dyn:flags */ 635088Sab196087 DYN_CMD_T_FLAGS1 = 8, /* dyn:flags1 */ 645088Sab196087 DYN_CMD_T_FEATURE1 = 9, /* dyn:feature1 */ 656206Sab196087 DYN_CMD_T_CHECKSUM = 10, /* dyn:checksum */ 666206Sab196087 DYN_CMD_T_SUNW_LDMACH = 11 /* dyn:sunw_ldmach */ 675088Sab196087 } DYN_CMD_T; 685088Sab196087 695088Sab196087 705088Sab196087 715088Sab196087 #ifndef _ELF64 725088Sab196087 /* 735088Sab196087 * We supply this function for the msg module 745088Sab196087 */ 755088Sab196087 const char * 765088Sab196087 _dyn_msg(Msg mid) 775088Sab196087 { 785088Sab196087 return (gettext(MSG_ORIG(mid))); 795088Sab196087 } 805088Sab196087 #endif 815088Sab196087 825088Sab196087 835088Sab196087 /* 845088Sab196087 * This function is supplied to elfedit through our elfedit_module_t 855088Sab196087 * definition. It translates the opaque elfedit_i18nhdl_t handles 865088Sab196087 * in our module interface into the actual strings for elfedit to 875088Sab196087 * use. 885088Sab196087 * 895088Sab196087 * note: 905088Sab196087 * This module uses Msg codes for its i18n handle type. 915088Sab196087 * So the translation is simply to use MSG_INTL() to turn 925088Sab196087 * it into a string and return it. 935088Sab196087 */ 945088Sab196087 static const char * 955088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 965088Sab196087 { 975088Sab196087 Msg msg = (Msg)hdl; 985088Sab196087 995088Sab196087 return (MSG_INTL(msg)); 1005088Sab196087 } 1015088Sab196087 1025088Sab196087 1035088Sab196087 1045088Sab196087 /* 1055088Sab196087 * The dyn_opt_t enum specifies a bit value for every optional 1065088Sab196087 * argument allowed by a command in this module. 1075088Sab196087 */ 1085088Sab196087 typedef enum { 1095088Sab196087 DYN_OPT_F_ADD = 1, /* -add: Add new elt rather than */ 1105088Sab196087 /* modifying an existing one */ 1115088Sab196087 DYN_OPT_F_AND = 2, /* -and: AND (&) values to dest */ 1125088Sab196087 DYN_OPT_F_CMP = 4, /* -cmp: Complement (~) values */ 113*6225Sab196087 DYN_OPT_F_DYNNDX_ELT = 8, /* -dynndx: 1st plain arg is tag */ 114*6225Sab196087 /* index, not name */ 115*6225Sab196087 DYN_OPT_F_DYNNDX_VAL = 16, /* -dynndx ndx: Index is value to */ 116*6225Sab196087 /* option rather than 1st plain */ 117*6225Sab196087 /* arg. Used for dyn:posflag1 */ 118*6225Sab196087 DYN_OPT_F_NEEDED = 32, /* -needed str: Locate DT_POSFLAG_1 */ 119*6225Sab196087 /* relative to DT_NEEDED element */ 120*6225Sab196087 DYN_OPT_F_OR = 64, /* -or: OR (|) values to dest */ 121*6225Sab196087 DYN_OPT_F_STRVAL = 128 /* -s: value is string, not integer */ 1225088Sab196087 } dyn_opt_t; 1235088Sab196087 1245088Sab196087 1255088Sab196087 /* 1265088Sab196087 * A variable of type ARGSTATE is used by each command to maintain 1275088Sab196087 * information about the arguments and related things. It is 1285088Sab196087 * initialized by process_args(), and used by the other routines. 1295088Sab196087 */ 1305088Sab196087 typedef struct { 1315088Sab196087 elfedit_obj_state_t *obj_state; 1325088Sab196087 elfedit_section_t *strsec; /* Dynamic string table ref */ 1335088Sab196087 struct { 1345088Sab196087 elfedit_section_t *sec; /* Dynamic section reference */ 1355088Sab196087 Dyn *data; /* Start dynamic section data */ 1365088Sab196087 Word num; /* # dynamic elts */ 1375088Sab196087 Word null_ndx; /* Index of first DT_NULL */ 1385088Sab196087 Word num_null_ndx; /* # of DT_NULL elements */ 1395088Sab196087 } dyn; 1405088Sab196087 dyn_opt_t optmask; /* Mask of options used */ 1415088Sab196087 int argc; /* # of plain arguments */ 1425088Sab196087 const char **argv; /* Plain arguments */ 143*6225Sab196087 const char *dyn_elt_str; /* Value string for */ 144*6225Sab196087 /* DYN_OPT_F_DYNNDX_VAL */ 145*6225Sab196087 /* or DYN_OPT_F_NEEDED */ 1465088Sab196087 } ARGSTATE; 1475088Sab196087 1485088Sab196087 1495088Sab196087 1505088Sab196087 /* 1515088Sab196087 * Set argstate null_ndx field for current dynamic area 1525088Sab196087 */ 1535088Sab196087 static void 1545088Sab196087 set_null_ndx(ARGSTATE *argstate) 1555088Sab196087 { 1565088Sab196087 Word num, null_ndx; 1575088Sab196087 1585088Sab196087 num = argstate->dyn.num; 1595088Sab196087 argstate->dyn.num_null_ndx = 0; 1605088Sab196087 for (null_ndx = 0; null_ndx < num; null_ndx++) 1615088Sab196087 if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) { 1625088Sab196087 argstate->dyn.num_null_ndx++; 1635088Sab196087 break; 1645088Sab196087 } 1655088Sab196087 argstate->dyn.null_ndx = null_ndx; 1665088Sab196087 1675088Sab196087 /* Count the number of remaining DT_NULL items */ 1685088Sab196087 for (; null_ndx < num; null_ndx++) 1695088Sab196087 if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) 1705088Sab196087 argstate->dyn.num_null_ndx++; 1715088Sab196087 } 1725088Sab196087 1735088Sab196087 1745088Sab196087 /* 1755088Sab196087 * Convert the first available DT_NULL slot in the dynamic section 1765088Sab196087 * into something else. 1775088Sab196087 * 1785088Sab196087 * entry: 1795088Sab196087 * argstate - Argument state block 1805088Sab196087 * d_tag, d_val - Values to be set in new element 1815088Sab196087 * 1825088Sab196087 * exit: 1835088Sab196087 * If an extra DT_NULL slot is available, a debug message is 1845088Sab196087 * issued, the slot is converted to its new use, and the argstate 1855088Sab196087 * block state related to DT_NULL slots is updated. 1865088Sab196087 * 1875088Sab196087 * if no extra DT_NULL slot is present, an error is issued and 1885088Sab196087 * this routine does not return to the caller. 1895088Sab196087 */ 1905088Sab196087 static Word 1915088Sab196087 convert_dt_null(ARGSTATE *argstate, Word d_tag, Xword d_val) 1925088Sab196087 { 1935088Sab196087 Conv_inv_buf_t inv_buf; 1945088Sab196087 Word ndx; 1955088Sab196087 Dyn *dyn; 1965088Sab196087 1975088Sab196087 /* If we lack an extra element, we can't continue */ 1985088Sab196087 if (argstate->dyn.num_null_ndx <= 1) 1995088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 2005088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 2015088Sab196087 argstate->dyn.sec->sec_name); 2025088Sab196087 2035088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL), 2045088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), argstate->dyn.sec->sec_name, 2055088Sab196087 EC_WORD(argstate->dyn.null_ndx), conv_dyn_tag(d_tag, 2065088Sab196087 argstate->obj_state->os_ehdr->e_machine, 0, &inv_buf)); 2075088Sab196087 2085088Sab196087 ndx = argstate->dyn.null_ndx; 2095088Sab196087 dyn = &argstate->dyn.data[ndx]; 2105088Sab196087 dyn->d_tag = d_tag; 2115088Sab196087 dyn->d_un.d_val = d_val; 2125088Sab196087 2135088Sab196087 /* Recompute the DT_NULL situation */ 2145088Sab196087 set_null_ndx(argstate); 2155088Sab196087 2165088Sab196087 return (ndx); 2175088Sab196087 } 2185088Sab196087 2195088Sab196087 2205088Sab196087 /* 2215088Sab196087 * Standard argument processing for dyn module 2225088Sab196087 * 2235088Sab196087 * entry 2245088Sab196087 * obj_state, argc, argv - Standard command arguments 2255088Sab196087 * argstate - Address of ARGSTATE block to be initialized 2265088Sab196087 * 2275088Sab196087 * exit: 2285088Sab196087 * On success, *argstate is initialized. On error, 2295088Sab196087 * an error is issued and this routine does not return. 2305088Sab196087 */ 2315088Sab196087 static void 2325088Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 2335088Sab196087 ARGSTATE *argstate) 2345088Sab196087 { 2355088Sab196087 elfedit_getopt_state_t getopt_state; 2365088Sab196087 elfedit_getopt_ret_t *getopt_ret; 2375088Sab196087 2385088Sab196087 bzero(argstate, sizeof (*argstate)); 2395088Sab196087 argstate->obj_state = obj_state; 2405088Sab196087 2415088Sab196087 elfedit_getopt_init(&getopt_state, &argc, &argv); 2425088Sab196087 2435088Sab196087 /* Add each new option to the options mask */ 244*6225Sab196087 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) { 2455088Sab196087 argstate->optmask |= getopt_ret->gor_idmask; 246*6225Sab196087 switch (getopt_ret->gor_idmask) { 247*6225Sab196087 case DYN_OPT_F_DYNNDX_VAL: 248*6225Sab196087 case DYN_OPT_F_NEEDED: 249*6225Sab196087 argstate->dyn_elt_str = getopt_ret->gor_value; 250*6225Sab196087 break; 251*6225Sab196087 } 252*6225Sab196087 } 2535088Sab196087 2545088Sab196087 /* If there may be an arbitrary amount of output, use a pager */ 2555088Sab196087 if (argc == 0) 2565088Sab196087 elfedit_pager_init(); 2575088Sab196087 2585088Sab196087 /* Return the updated values of argc/argv */ 2595088Sab196087 argstate->argc = argc; 2605088Sab196087 argstate->argv = argv; 2615088Sab196087 2625088Sab196087 /* Locate the dynamic section, and the assocated string table */ 2635088Sab196087 argstate->dyn.sec = elfedit_sec_getdyn(obj_state, &argstate->dyn.data, 2645088Sab196087 &argstate->dyn.num); 2655088Sab196087 argstate->strsec = elfedit_sec_getstr(obj_state, 266*6225Sab196087 argstate->dyn.sec->sec_shdr->sh_link, 0); 2675088Sab196087 2685088Sab196087 /* Index of first DT_NULL */ 2695088Sab196087 set_null_ndx(argstate); 2705088Sab196087 } 2715088Sab196087 2725088Sab196087 2735088Sab196087 2745088Sab196087 /* 2755088Sab196087 * Print ELF header values, taking the calling command, and output style 2765088Sab196087 * into account. 2775088Sab196087 * 2785088Sab196087 * entry: 2795088Sab196087 * cmd - DYN_CMD_T_* value giving identify of caller 2805088Sab196087 * autoprint - If True, output is only produced if the elfedit 2815088Sab196087 * autoprint flag is set. If False, output is always produced. 2825088Sab196087 * argstate - Argument state block 2835088Sab196087 * print_type - Specifies which dynamic elements to display. 2845088Sab196087 * ndx = If print_type is PRINT_DYN_T_NDX, displays the index specified. 2855088Sab196087 * Otherwise ignored. 2865088Sab196087 */ 2875088Sab196087 typedef enum { 2885088Sab196087 PRINT_DYN_T_ALL = 0, /* Show all indexes */ 2895088Sab196087 PRINT_DYN_T_NDX = 1, /* Show dynamic[arg] only */ 2905088Sab196087 PRINT_DYN_T_TAG = 2, /* Show all elts with tag type */ 2915088Sab196087 /* given by arg */ 2925088Sab196087 PRINT_DYN_T_RUNPATH = 3 /* Show all runpath/rpath elts */ 2935088Sab196087 2945088Sab196087 } PRINT_DYN_T; 2955088Sab196087 2965088Sab196087 static void 2975088Sab196087 print_dyn(DYN_CMD_T cmd, int autoprint, ARGSTATE *argstate, 2985088Sab196087 PRINT_DYN_T print_type, Word arg) 2995088Sab196087 { 3005088Sab196087 elfedit_outstyle_t outstyle; 3015088Sab196087 Conv_fmt_flags_t flags_fmt_flags; 3025088Sab196087 Word end_ndx, cnt, ndx, printed = 0; 3035088Sab196087 Dyn *dyn; 3045088Sab196087 int header_done = 0; 3055088Sab196087 Xword last_d_val; 306*6225Sab196087 int one_shot; 3075088Sab196087 3085088Sab196087 if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) 3095088Sab196087 return; 3105088Sab196087 3115088Sab196087 /* 3125088Sab196087 * Pick an output style. dyn:dump is required to use the default 3135088Sab196087 * style. The other commands use the current output style. 3145088Sab196087 */ 3155088Sab196087 outstyle = (cmd == DYN_CMD_T_DUMP) ? 3165088Sab196087 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 3175088Sab196087 3185088Sab196087 /* 3195088Sab196087 * When using the simple output style, omit the 3205088Sab196087 * brackets from around the values. 3215088Sab196087 */ 3225088Sab196087 flags_fmt_flags = (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) ? 3235088Sab196087 CONV_FMT_NOBKT : 0; 3245088Sab196087 3255088Sab196087 /* How many elements do we examine? */ 3265088Sab196087 if (print_type == PRINT_DYN_T_NDX) { 3275088Sab196087 if (arg >= argstate->dyn.num) 3285088Sab196087 return; /* Out of range */ 3295088Sab196087 ndx = arg; 3305088Sab196087 cnt = 1; 3315088Sab196087 } else { 3325088Sab196087 ndx = 0; 3335088Sab196087 cnt = argstate->dyn.num; 3345088Sab196087 } 3355088Sab196087 336*6225Sab196087 /* 337*6225Sab196087 * one_shot is used by positional elements (e.g. DT_POSFLAG_1) 338*6225Sab196087 * to get the item following them to be shown even if they 339*6225Sab196087 * are not of the desired tag type or the count of elements 340*6225Sab196087 * to be displayed is only 1. 341*6225Sab196087 */ 342*6225Sab196087 one_shot = 0; 343*6225Sab196087 3445088Sab196087 dyn = &argstate->dyn.data[ndx]; 345*6225Sab196087 for (; (one_shot && (ndx < argstate->dyn.num)) || cnt--; dyn++, ndx++) { 3465088Sab196087 union { 3476206Sab196087 Conv_inv_buf_t inv; 3485088Sab196087 Conv_dyn_flag_buf_t flag; 3495088Sab196087 Conv_dyn_flag1_buf_t flag1; 3505088Sab196087 Conv_dyn_posflag1_buf_t posflag1; 3515088Sab196087 Conv_dyn_feature1_buf_t feature1; 3525088Sab196087 } c_buf; 3535088Sab196087 const char *name; 3545088Sab196087 355*6225Sab196087 if (one_shot) { 356*6225Sab196087 one_shot = 0; 357*6225Sab196087 } else { 358*6225Sab196087 /* 359*6225Sab196087 * If we are only displaying certain tag types and 360*6225Sab196087 * this isn't one of those, move on to next element. 361*6225Sab196087 */ 362*6225Sab196087 switch (print_type) { 363*6225Sab196087 case PRINT_DYN_T_TAG: 364*6225Sab196087 if (dyn->d_tag != arg) 365*6225Sab196087 continue; 366*6225Sab196087 break; 367*6225Sab196087 case PRINT_DYN_T_RUNPATH: 368*6225Sab196087 if ((dyn->d_tag != DT_RPATH) && 369*6225Sab196087 (dyn->d_tag != DT_RUNPATH)) 370*6225Sab196087 continue; 371*6225Sab196087 break; 372*6225Sab196087 } 3735088Sab196087 } 3745088Sab196087 3755088Sab196087 /* 3765088Sab196087 * Print the information numerically, and if possible 3775088Sab196087 * as a string. 3785088Sab196087 */ 3795088Sab196087 name = NULL; 3805088Sab196087 switch (dyn->d_tag) { 3815088Sab196087 case DT_NULL: 3825088Sab196087 if (!((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) && 3835088Sab196087 (print_type == PRINT_DYN_T_ALL) && 3845088Sab196087 (dyn->d_un.d_val == 0))) 3855088Sab196087 break; 3865088Sab196087 end_ndx = ndx; 3875088Sab196087 /* 3885088Sab196087 * Special case: DT_NULLs can come in groups 3895088Sab196087 * that we prefer to reduce to a single line. 3905088Sab196087 */ 3915088Sab196087 while ((end_ndx < (argstate->dyn.num - 1)) && 3925088Sab196087 ((dyn + 1)->d_tag == DT_NULL) && 3935088Sab196087 ((dyn + 1)->d_un.d_val == 0)) { 3945088Sab196087 dyn++; 3955088Sab196087 end_ndx++; 3965088Sab196087 cnt--; 3975088Sab196087 } 3985088Sab196087 if (header_done == 0) { 3995088Sab196087 header_done = 1; 4005088Sab196087 Elf_dyn_title(0); 4015088Sab196087 } 4025088Sab196087 Elf_dyn_null_entry(0, dyn, ndx, end_ndx); 4035088Sab196087 ndx = end_ndx; 4045088Sab196087 printed = 1; 4055088Sab196087 last_d_val = dyn->d_un.d_val; 4065088Sab196087 continue; 4075088Sab196087 4085088Sab196087 /* 4095088Sab196087 * Print the information numerically, and if possible 4105088Sab196087 * as a string. 4115088Sab196087 */ 4125088Sab196087 case DT_NEEDED: 4135088Sab196087 case DT_SONAME: 4145088Sab196087 case DT_FILTER: 4155088Sab196087 case DT_AUXILIARY: 4165088Sab196087 case DT_CONFIG: 4175088Sab196087 case DT_RPATH: 4185088Sab196087 case DT_RUNPATH: 4195088Sab196087 case DT_USED: 4205088Sab196087 case DT_DEPAUDIT: 4215088Sab196087 case DT_AUDIT: 4225088Sab196087 case DT_SUNW_AUXILIARY: 4235088Sab196087 case DT_SUNW_FILTER: 4245088Sab196087 name = elfedit_offset_to_str(argstate->strsec, 4255088Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 4265088Sab196087 break; 4275088Sab196087 4285088Sab196087 case DT_FLAGS: 4295088Sab196087 name = conv_dyn_flag(dyn->d_un.d_val, 4305088Sab196087 flags_fmt_flags, &c_buf.flag); 4315088Sab196087 break; 4325088Sab196087 case DT_FLAGS_1: 4335088Sab196087 name = conv_dyn_flag1(dyn->d_un.d_val, 4345088Sab196087 flags_fmt_flags, &c_buf.flag1); 4355088Sab196087 break; 4365088Sab196087 case DT_POSFLAG_1: 437*6225Sab196087 /* 438*6225Sab196087 * If this is dyn:posflag1, and the print_type 439*6225Sab196087 * is PRINT_DYN_T_TAG, and the -needed option is 440*6225Sab196087 * used, then don't show any DT_POSFLAG_1 elements 441*6225Sab196087 * that are not followed by a DT_NEEDED element 442*6225Sab196087 * that matches the -needed string. 443*6225Sab196087 */ 444*6225Sab196087 if ((cmd == DYN_CMD_T_POSFLAG1) && 445*6225Sab196087 (print_type == PRINT_DYN_T_TAG) && 446*6225Sab196087 ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) && 447*6225Sab196087 ((ndx + 1) < argstate->dyn.num)) { 448*6225Sab196087 Dyn *dyn1 = &argstate->dyn.data[ndx + 1]; 449*6225Sab196087 450*6225Sab196087 if (dyn1->d_tag != DT_NEEDED) 451*6225Sab196087 continue; 452*6225Sab196087 name = elfedit_offset_to_str(argstate->strsec, 453*6225Sab196087 dyn1->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 454*6225Sab196087 if (strncmp(name, argstate->dyn_elt_str, 455*6225Sab196087 strlen(argstate->dyn_elt_str)) != 0) 456*6225Sab196087 continue; 457*6225Sab196087 } 458*6225Sab196087 4595088Sab196087 name = conv_dyn_posflag1(dyn->d_un.d_val, 4605088Sab196087 flags_fmt_flags, &c_buf.posflag1); 461*6225Sab196087 /* 462*6225Sab196087 * DT_POSFLAG_1 is a positional element that affects 463*6225Sab196087 * the following item. If using the default output 464*6225Sab196087 * style, then show the following item as well. 465*6225Sab196087 */ 466*6225Sab196087 one_shot = (outstyle == ELFEDIT_OUTSTYLE_DEFAULT); 4675088Sab196087 break; 4685088Sab196087 case DT_FEATURE_1: 4695088Sab196087 name = conv_dyn_feature1(dyn->d_un.d_val, 4705088Sab196087 flags_fmt_flags, &c_buf.feature1); 4715088Sab196087 break; 4725088Sab196087 case DT_DEPRECATED_SPARC_REGISTER: 4735088Sab196087 name = MSG_INTL(MSG_STR_DEPRECATED); 4745088Sab196087 break; 4756206Sab196087 case DT_SUNW_LDMACH: 4766206Sab196087 name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0, 4776206Sab196087 &c_buf.inv); 4786206Sab196087 break; 4795088Sab196087 } 4805088Sab196087 4815088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 4825088Sab196087 if (header_done == 0) { 4835088Sab196087 header_done = 1; 4845088Sab196087 Elf_dyn_title(0); 4855088Sab196087 } 4865088Sab196087 if (name == NULL) 4875088Sab196087 name = MSG_ORIG(MSG_STR_EMPTY); 4885088Sab196087 Elf_dyn_entry(0, dyn, ndx, name, 4895088Sab196087 argstate->obj_state->os_ehdr->e_machine); 4905088Sab196087 } else { 4915088Sab196087 /* 4925088Sab196087 * In simple or numeric mode under a print type 4935088Sab196087 * that is based on tag type rather than on index, 4945088Sab196087 * quietly: If we've already printed this value, 4955088Sab196087 * don't print it again. A common example of this 4965088Sab196087 * is PRINT_DYN_T_RUNPATH when both DT_RPATH and 4975088Sab196087 * DT_RUNPATH are present with the same value. 4985088Sab196087 */ 4995088Sab196087 switch (print_type) { 5005088Sab196087 case PRINT_DYN_T_TAG: 501*6225Sab196087 /* 502*6225Sab196087 * Positional flags don't count, because 503*6225Sab196087 * each one affects a different item. So don't 504*6225Sab196087 * skip those. 505*6225Sab196087 */ 506*6225Sab196087 if (dyn->d_tag != DT_POSFLAG_1) 507*6225Sab196087 continue; 508*6225Sab196087 break; 509*6225Sab196087 5105088Sab196087 case PRINT_DYN_T_RUNPATH: 5115088Sab196087 if (printed && (last_d_val == dyn->d_un.d_val)) 5125088Sab196087 continue; 513*6225Sab196087 break; 5145088Sab196087 } 5155088Sab196087 5165088Sab196087 if ((name != NULL) && 5175088Sab196087 (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) { 5185088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name); 5195088Sab196087 } else { 5205088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), 5215088Sab196087 dyn->d_un.d_val); 5225088Sab196087 } 5235088Sab196087 } 5245088Sab196087 printed = 1; 5255088Sab196087 last_d_val = dyn->d_un.d_val; 5265088Sab196087 } 5275088Sab196087 5285088Sab196087 /* 5295088Sab196087 * If nothing was output under the print types that are 5305088Sab196087 * based on tag type, issue an error saying it doesn't exist. 5315088Sab196087 */ 5325088Sab196087 if (!printed) { 5335088Sab196087 if (print_type == PRINT_DYN_T_TAG) { 5345088Sab196087 Conv_inv_buf_t inv_buf; 5355088Sab196087 5365088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 5375088Sab196087 MSG_INTL(MSG_ERR_NODYNELT), 5385088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 5395088Sab196087 argstate->dyn.sec->sec_name, conv_dyn_tag(arg, 5405088Sab196087 argstate->obj_state->os_ehdr->e_machine, 5415088Sab196087 0, &inv_buf)); 5425088Sab196087 } 5435088Sab196087 5445088Sab196087 if (print_type == PRINT_DYN_T_RUNPATH) 5455088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 5465088Sab196087 MSG_INTL(MSG_ERR_NORUNPATH), 5475088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 5485088Sab196087 argstate->dyn.sec->sec_name); 5495088Sab196087 } 5505088Sab196087 } 5515088Sab196087 5525088Sab196087 5535088Sab196087 /* 554*6225Sab196087 * Determine the index(s) of the dynamic element(s) to be displayed and/or 555*6225Sab196087 * manipulated. 5565088Sab196087 * 5575088Sab196087 * entry: 5585088Sab196087 * argstate - Argument state block 559*6225Sab196087 * arg - If the command being called accepts a first plain argument 560*6225Sab196087 * named 'elt' which is used to specify the dynamic element, 561*6225Sab196087 * arg is the value of argv[0] for that command. If the 562*6225Sab196087 * command does not accept an 'elt' argument and instead 563*6225Sab196087 * implicitly assumes a tag type, arg is the constant string 564*6225Sab196087 * for that type (e.g. "DT_POSFLAG_1"). 5655088Sab196087 * print_request - True if the command is to print the current 5665088Sab196087 * value(s) and return without changing anything. 5675088Sab196087 * print_type - Address of variable containing PRINT_DYN_T_ 5685088Sab196087 * code specifying how the elements will be displayed. 5695088Sab196087 * 5705088Sab196087 * exit: 571*6225Sab196087 * If print_request is False: This routine always returns the index 572*6225Sab196087 * of a single dynamic element. *print_type is set to PRINT_DYN_T_NDX. 573*6225Sab196087 * The 'elt' argument as well as any modifier options (-dynndx, -needed) 574*6225Sab196087 * are examined to determine this index. If there are no modifier options, 575*6225Sab196087 * the dynamic section contains no element of the desired type, and there 576*6225Sab196087 * is an extra DT_NULL element in the section, then a new element of 577*6225Sab196087 * the desired type is created and its index returned. Otherwise an 578*6225Sab196087 * error is issued. 5795088Sab196087 * 580*6225Sab196087 * If print_request is True: If a modifier (-dynndx, -needed) was used, 581*6225Sab196087 * *print_type is set to PRINT_DYN_T_NDX and the index of the 582*6225Sab196087 * corresponding single dynamic element is returned. If no modifier 583*6225Sab196087 * was used, *print_type is set to PRINT_DYN_T_TAG, and the tag 584*6225Sab196087 * type code is returned. 5855088Sab196087 */ 5865088Sab196087 static Word 587*6225Sab196087 arg_to_index(ARGSTATE *argstate, const char *arg, 5885088Sab196087 int print_request, PRINT_DYN_T *print_type) 5895088Sab196087 { 5905088Sab196087 Word ndx, dt_value; 591*6225Sab196087 Dyn *dyn; 5925088Sab196087 5935088Sab196087 5945088Sab196087 /* Assume we are returning an index, alter as needed below */ 5955088Sab196087 *print_type = PRINT_DYN_T_NDX; 5965088Sab196087 597*6225Sab196087 /* 598*6225Sab196087 * All the commands that accept the DYN_OPT_F_DYNNDX_ELT form 599*6225Sab196087 * of -dynndx require a plain argument named 'elt' as their first 600*6225Sab196087 * argument. -dynndx is a modifier that means that 'elt' is a 601*6225Sab196087 * simple numeric section index. Routines that accept this form 602*6225Sab196087 * of -dynndx are willing to handle any tag type, so all we need 603*6225Sab196087 * to check is that the value is in range. 604*6225Sab196087 */ 605*6225Sab196087 if ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0) 606*6225Sab196087 return ((Word) elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_ELT), 607*6225Sab196087 0, argstate->dyn.num - 1, NULL)); 608*6225Sab196087 609*6225Sab196087 /* arg is a DT_ tag type, not a numeric index */ 610*6225Sab196087 dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT); 6115088Sab196087 612*6225Sab196087 /* 613*6225Sab196087 * Commands that accept the DYN_OPT_F_DYNNDX_VAL form of 614*6225Sab196087 * dynndx do not accept the 'elt' argument. The index is a 615*6225Sab196087 * value that follows the option, and was saved in argstate by 616*6225Sab196087 * process_args(). Routines that accept this form of -dynndx 617*6225Sab196087 * require the specified element to have a specific tag type, 618*6225Sab196087 * so we test for this as well as for the index being in range. 619*6225Sab196087 */ 620*6225Sab196087 if ((argstate->optmask & DYN_OPT_F_DYNNDX_VAL) != 0) { 621*6225Sab196087 ndx = ((Word) elfedit_atoui_range(argstate->dyn_elt_str, 622*6225Sab196087 MSG_ORIG(MSG_STR_INDEX), 0, argstate->dyn.num - 1, NULL)); 623*6225Sab196087 if (argstate->dyn.data[ndx].d_tag != dt_value) { 624*6225Sab196087 Half mach = argstate->obj_state->os_ehdr->e_machine; 625*6225Sab196087 Conv_inv_buf_t is, want; 626*6225Sab196087 627*6225Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_WRONGTAG), 628*6225Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 629*6225Sab196087 argstate->dyn.sec->sec_name, ndx, 630*6225Sab196087 conv_dyn_tag(dt_value, mach, 0, &want), 631*6225Sab196087 conv_dyn_tag(argstate->dyn.data[ndx].d_tag, mach, 632*6225Sab196087 0, &is)); 633*6225Sab196087 } 634*6225Sab196087 return (ndx); 635*6225Sab196087 } 6365088Sab196087 6375088Sab196087 /* 6385088Sab196087 * If this is a printing request, then we let print_dyn() show 6395088Sab196087 * all the items with this tag type. 6405088Sab196087 */ 6415088Sab196087 if (print_request) { 6425088Sab196087 *print_type = PRINT_DYN_T_TAG; 6435088Sab196087 return (dt_value); 6445088Sab196087 } 6455088Sab196087 646*6225Sab196087 /* 647*6225Sab196087 * Commands that accept -needed are looking for the dt_value element 648*6225Sab196087 * (usually DT_POSFLAG_1) that immediately preceeds the DT_NEEDED 649*6225Sab196087 * element with the string given by argstate->dyn_elt_str. 650*6225Sab196087 */ 651*6225Sab196087 if ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) { 652*6225Sab196087 Word retndx = argstate->dyn.num; /* Out of range value */ 653*6225Sab196087 const char *name; 654*6225Sab196087 size_t len; 655*6225Sab196087 656*6225Sab196087 len = strlen(argstate->dyn_elt_str); 657*6225Sab196087 for (ndx = 0, dyn = argstate->dyn.data; 658*6225Sab196087 ndx < argstate->dyn.num; dyn++, ndx++) { 659*6225Sab196087 /* 660*6225Sab196087 * If the immediately preceeding item has the 661*6225Sab196087 * tag type we're looking for, and the current item 662*6225Sab196087 * is a DT_NEEDED with a string that matches, 663*6225Sab196087 * then the preceeding item is the one we want. 664*6225Sab196087 */ 665*6225Sab196087 if ((dyn->d_tag == DT_NEEDED) && 666*6225Sab196087 (ndx > 0) && (retndx == (ndx - 1))) { 667*6225Sab196087 name = elfedit_offset_to_str(argstate->strsec, 668*6225Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 669*6225Sab196087 670*6225Sab196087 if (strncmp(name, 671*6225Sab196087 argstate->dyn_elt_str, len) == 0) 672*6225Sab196087 return (retndx); 673*6225Sab196087 continue; 674*6225Sab196087 } 675*6225Sab196087 676*6225Sab196087 /* 677*6225Sab196087 * If the current item has the tag type we're 678*6225Sab196087 * looking for, make it our current candidate. 679*6225Sab196087 * If the next item is a DT_NEEDED with the right 680*6225Sab196087 * string value, we'll use it then. 681*6225Sab196087 */ 682*6225Sab196087 if (dyn->d_tag == dt_value) 683*6225Sab196087 retndx = ndx; 684*6225Sab196087 } 685*6225Sab196087 686*6225Sab196087 /* If we get here, no matching DT_NEEDED was found */ 687*6225Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEDNOMATCH), 688*6225Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 689*6225Sab196087 argstate->dyn.sec->sec_name, argstate->dyn_elt_str); 690*6225Sab196087 } 691*6225Sab196087 6925088Sab196087 /* Locate the first entry with the given tag type */ 6935088Sab196087 for (ndx = 0; ndx < argstate->dyn.num; ndx++) { 6945088Sab196087 if (argstate->dyn.data[ndx].d_tag == dt_value) { 6955088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 6965088Sab196087 MSG_INTL(MSG_DEBUG_DT2NDX), 6975088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 6985088Sab196087 argstate->dyn.sec->sec_name, EC_WORD(ndx), arg); 6995088Sab196087 return (ndx); 7005088Sab196087 } 7015088Sab196087 } 7025088Sab196087 7035088Sab196087 /* Not found. Can we create one? */ 7045088Sab196087 if (argstate->dyn.num_null_ndx > 1) 7055088Sab196087 return (convert_dt_null(argstate, dt_value, 0)); 7065088Sab196087 7075088Sab196087 /* No room to create one, so we're out of options and must fail */ 7085088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT), 7095088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 7105088Sab196087 argstate->dyn.sec->sec_name, arg); 7115088Sab196087 7125088Sab196087 /*NOTREACHED*/ 7135088Sab196087 return (0); /* For lint */ 7145088Sab196087 } 7155088Sab196087 7165088Sab196087 7175088Sab196087 /* 7185088Sab196087 * Called by cmd_body() for dyn:value. Implements the core functionality 7195088Sab196087 * for that command. 7205088Sab196087 * 7215088Sab196087 * This routine expects that both the index and value arguments are 7225088Sab196087 * present. 7235088Sab196087 */ 7245088Sab196087 static elfedit_cmdret_t 7255088Sab196087 cmd_body_value(ARGSTATE *argstate, Word *ret_ndx) 7265088Sab196087 { 7275088Sab196087 elfedit_section_t *dynsec = argstate->dyn.sec; 7285088Sab196087 elfedit_section_t *strsec = argstate->strsec; 7295088Sab196087 elfedit_dyn_elt_t strpad_elt; 7305088Sab196087 Word i; 7315088Sab196087 Dyn *dyn = argstate->dyn.data; 7325088Sab196087 Word numdyn = argstate->dyn.num; 733*6225Sab196087 int minus_add, minus_s, minus_dynndx; 7345088Sab196087 Word arg1, tmp_val; 7355088Sab196087 Xword arg2; 7365088Sab196087 int arg2_known = 1; 7375088Sab196087 738*6225Sab196087 minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0); 739*6225Sab196087 minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0); 740*6225Sab196087 minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0); 7415088Sab196087 7425088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 7435088Sab196087 7445088Sab196087 /* 7455088Sab196087 * The first argument is an index if -dynndx is used, and is a 7465088Sab196087 * tag value otherwise. 7475088Sab196087 */ 7485088Sab196087 arg1 = minus_dynndx ? 7495088Sab196087 elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT), 7505088Sab196087 0, numdyn - 1, NULL) : 7515088Sab196087 elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT); 7525088Sab196087 7535088Sab196087 if (minus_s) { 7545088Sab196087 /* 7555088Sab196087 * Don't allow the user to specify -s when manipulating a 7565088Sab196087 * DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to 7575088Sab196087 * manage the extra space used for strings, this would break 7585088Sab196087 * our ability to add the string. 7595088Sab196087 */ 7605088Sab196087 if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) || 7615088Sab196087 (minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD))) 7625088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 7635088Sab196087 MSG_INTL(MSG_ERR_STRPADSTRVAL), 7645088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 7655088Sab196087 7665088Sab196087 /* Locate DT_SUNW_STRPAD element if present */ 7675088Sab196087 strpad_elt.dn_dyn.d_un.d_val = 0; 7685088Sab196087 (void) elfedit_dynstr_getpad(argstate->dyn.sec, &strpad_elt); 7695088Sab196087 7705088Sab196087 /* 7715088Sab196087 * Look up the string: If the user specified the -dynndx 7725088Sab196087 * -option, then we will insert it if possible, and 7735088Sab196087 * fail with an error if not. However, if they did not 7745088Sab196087 * specify -dynndx, we want to look up the string if it is 7755088Sab196087 * already there, but defer the insertion. The reason for 7765088Sab196087 * this is that we may have to grab an unused DT_NULL element 7775088Sab196087 * below, and if there are none available, we won't want 7785088Sab196087 * to have modified the string table. 7795088Sab196087 * 7805088Sab196087 * This isn't a problem, because if the string isn't 7815088Sab196087 * in the string table, it can't be used by a dynamic element. 7825088Sab196087 * Hence, we don't need to insert it to know that there is 7835088Sab196087 * no match. 7845088Sab196087 */ 7855088Sab196087 if (minus_dynndx == 0) { 7865088Sab196087 if (elfedit_sec_findstr(strsec, 7875088Sab196087 strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1], 7885088Sab196087 &tmp_val) == 0) { 7895088Sab196087 arg2_known = 0; 7905088Sab196087 } else { 7915088Sab196087 arg2 = tmp_val; 7925088Sab196087 } 7935088Sab196087 } else { 7945088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 7955088Sab196087 &strpad_elt, argstate->argv[1]); 7965088Sab196087 } 7975088Sab196087 } else { /* Argument 2 is an integer */ 7985088Sab196087 arg2 = elfedit_atoui(argstate->argv[1], NULL); 7995088Sab196087 } 8005088Sab196087 8015088Sab196087 8025088Sab196087 if (!minus_dynndx && !(minus_add && !arg2_known)) { 8035088Sab196087 /* 8045088Sab196087 * Search the dynamic section and see if an item with the 8055088Sab196087 * specified tag value already exists. We can reduce this 8065088Sab196087 * to a simple update of an existing value if -add is not 8075088Sab196087 * specified or the existing d_un value matches the new one. 8085088Sab196087 * 8095088Sab196087 * In either of these cases, we will change arg1 to be the 8105088Sab196087 * index, and set minus_dynndx, causing the simple update to 8115088Sab196087 * happen immediately below. 8125088Sab196087 */ 8135088Sab196087 for (i = 0; i < numdyn; i++) { 8145088Sab196087 if ((dyn[i].d_tag == arg1) && 8155088Sab196087 (!minus_add || (dyn[i].d_un.d_val == arg2))) { 8165088Sab196087 arg1 = i; 8175088Sab196087 minus_dynndx = 1; 8185088Sab196087 break; 8195088Sab196087 } 8205088Sab196087 } 8215088Sab196087 } 8225088Sab196087 8235088Sab196087 /* 8245088Sab196087 * If -dynndx is used, then this is a relatively simple 8255088Sab196087 * operation, as we simply write over the specified index. 8265088Sab196087 */ 8275088Sab196087 if (minus_dynndx) { 8285088Sab196087 /* 8295088Sab196087 * If we held back from inserting a new string into 8305088Sab196087 * the dynstr above, we insert it now, because we 8315088Sab196087 * have a slot in the dynamic section, and we need 8325088Sab196087 * the string offset ot finish. 8335088Sab196087 */ 8345088Sab196087 if (!arg2_known) 8355088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 8365088Sab196087 &strpad_elt, argstate->argv[1]); 8375088Sab196087 8385088Sab196087 *ret_ndx = arg1; 8395088Sab196087 if (dyn[arg1].d_un.d_val == arg2) { 8405088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8415088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), 8425088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8435088Sab196087 EC_WORD(arg1), EC_XWORD(arg2)); 8445088Sab196087 return (ELFEDIT_CMDRET_NONE); 8455088Sab196087 } else { 8465088Sab196087 /* Warn if setting DT_NULL value to non-zero */ 8475088Sab196087 if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0)) 8485088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8495088Sab196087 MSG_INTL(MSG_DEBUG_DTNULLVALUE), 8505088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8515088Sab196087 EC_WORD(arg1), EC_XWORD(arg2)); 8525088Sab196087 8535088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8545088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 8555088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8565088Sab196087 EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val), 8575088Sab196087 EC_XWORD(arg2)); 8585088Sab196087 dyn[arg1].d_un.d_val = arg2; 8595088Sab196087 return (ELFEDIT_CMDRET_MOD); 8605088Sab196087 } 8615088Sab196087 } 8625088Sab196087 8635088Sab196087 /* 8645088Sab196087 * We need a new slot in the dynamic section. If we can't have 8655088Sab196087 * one, then we fail. 8665088Sab196087 */ 8675088Sab196087 if (argstate->dyn.num_null_ndx <= 1) 8685088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 8695088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 8705088Sab196087 8715088Sab196087 /* 8725088Sab196087 * If we still need to insert a new string into the dynstr, 8735088Sab196087 * then it is safe now, because if we succeed, we know that 8745088Sab196087 * there is an available slot to receive it. If we fail, we 8755088Sab196087 * haven't claimed the extra slot yet, and it will be unharmed. 8765088Sab196087 */ 8775088Sab196087 if (!arg2_known) 8785088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 8795088Sab196087 &strpad_elt, argstate->argv[1]); 8805088Sab196087 8815088Sab196087 /* Use an extra DT_NULL slot and enter the new element */ 8825088Sab196087 *ret_ndx = convert_dt_null(argstate, arg1, arg2); 8835088Sab196087 return (ELFEDIT_CMDRET_MOD); 8845088Sab196087 } 8855088Sab196087 8865088Sab196087 8875088Sab196087 8885088Sab196087 /* 8895088Sab196087 * Called by cmd_body() for dyn:runpath. Implements the core functionality 8905088Sab196087 * for that command. 8915088Sab196087 * 8925088Sab196087 * History Lesson And Strategy: 8935088Sab196087 * 8945088Sab196087 * This routine handles both DT_RPATH and DT_RUNPATH entries, altering 8955088Sab196087 * either or both if they are present. 8965088Sab196087 * 8975088Sab196087 * The original SYSV ABI only had DT_RPATH, and the runtime loader used 8985088Sab196087 * it to search for things in the following order: 8995088Sab196087 * 9005088Sab196087 * DT_RPATH, LD_LIBRARY_PATH, defaults 9015088Sab196087 * 9025088Sab196087 * Solaris did not follow this rule, an extremely rare deviation from 9035088Sab196087 * the ABI. Environment variables should supercede everything else, 9045088Sab196087 * otherwise they are not very useful. This decision was made at the 9055088Sab196087 * very beginning of the SunOS 5.x development, so we have always 9065088Sab196087 * deviated from the ABI and and instead search in the order 9075088Sab196087 * 9085088Sab196087 * LD_LIBRARY_PATH, DT_RPATH, defaults 9095088Sab196087 * 9105088Sab196087 * Other Unix variants initially followed the ABI, but in recent years 9115088Sab196087 * have come to agree with the early Solaris folks that it was a mistake. 9125088Sab196087 * Hence, DT_RUNPATH was invented, with the search order: 9135088Sab196087 * 9145088Sab196087 * LD_LIBRARY_PATH, DT_RUNPATH, defaults 9155088Sab196087 * 9165088Sab196087 * So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both 9175088Sab196087 * are present (which does happen), we set them both to the new 9185088Sab196087 * value. If either one is present, we set that one. If neither is 9195088Sab196087 * present, and we have a spare DT_NULL slot, we create a DT_RUNPATH, but 9205088Sab196087 * not a DT_RPATH, to conserve available slots for other uses. 9215088Sab196087 */ 9225088Sab196087 static elfedit_cmdret_t 9235088Sab196087 cmd_body_runpath(ARGSTATE *argstate) 9245088Sab196087 { 9255088Sab196087 elfedit_section_t *dynsec = argstate->dyn.sec; 9265088Sab196087 elfedit_section_t *strsec = argstate->strsec; 9275088Sab196087 elfedit_dyn_elt_t rpath_elt; 9285088Sab196087 elfedit_dyn_elt_t runpath_elt; 9295088Sab196087 elfedit_dyn_elt_t strpad_elt; 9305088Sab196087 Word i; 9315088Sab196087 Dyn *dyn = argstate->dyn.data; 9325088Sab196087 Word numdyn = argstate->dyn.num; 9335088Sab196087 9345088Sab196087 /* Go through the tags and gather what we need */ 9355088Sab196087 elfedit_dyn_elt_init(&rpath_elt); 9365088Sab196087 elfedit_dyn_elt_init(&runpath_elt); 9375088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 9385088Sab196087 for (i = 0; i < numdyn; i++) { 9395088Sab196087 switch (dyn[i].d_tag) { 9405088Sab196087 case DT_RPATH: 9415088Sab196087 elfedit_dyn_elt_save(&rpath_elt, i, &dyn[i]); 9425088Sab196087 break; 9435088Sab196087 9445088Sab196087 case DT_RUNPATH: 9455088Sab196087 elfedit_dyn_elt_save(&runpath_elt, i, &dyn[i]); 9465088Sab196087 break; 9475088Sab196087 9485088Sab196087 case DT_SUNW_STRPAD: 9495088Sab196087 elfedit_dyn_elt_save(&strpad_elt, i, &dyn[i]); 9505088Sab196087 break; 9515088Sab196087 } 9525088Sab196087 } 9535088Sab196087 9545088Sab196087 /* Do we have an available dynamic section entry to use? */ 9555088Sab196087 if (rpath_elt.dn_seen || runpath_elt.dn_seen) { 9565088Sab196087 /* 9575088Sab196087 * We have seen a DT_RPATH, or a DT_RUNPATH, or both. 9585088Sab196087 * If all of these have the same string as the desired 9595088Sab196087 * new value, then we don't need to alter anything and can 9605088Sab196087 * simply return. Otherwise, we'll modify them all to have 9615088Sab196087 * the new string (below). 9625088Sab196087 */ 9635088Sab196087 if ((!rpath_elt.dn_seen || 9645088Sab196087 (strcmp(elfedit_dyn_offset_to_str(strsec, &rpath_elt), 9655088Sab196087 argstate->argv[0]) == 0)) && 9665088Sab196087 (!runpath_elt.dn_seen || 9675088Sab196087 (strcmp(elfedit_dyn_offset_to_str(strsec, &runpath_elt), 9685088Sab196087 argstate->argv[0]) == 0))) { 9695088Sab196087 if (rpath_elt.dn_seen) 9705088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 9715088Sab196087 MSG_INTL(MSG_DEBUG_OLDRPATHOK), 9725088Sab196087 EC_WORD(dynsec->sec_shndx), 9735088Sab196087 dynsec->sec_name, EC_WORD(rpath_elt.dn_ndx), 9745088Sab196087 elfedit_atoconst_value_to_str( 9755088Sab196087 ELFEDIT_CONST_DT, DT_RPATH, 1)); 9765088Sab196087 if (runpath_elt.dn_seen) 9775088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 9785088Sab196087 MSG_INTL(MSG_DEBUG_OLDRPATHOK), 9795088Sab196087 EC_WORD(dynsec->sec_shndx), 9805088Sab196087 dynsec->sec_name, 9815088Sab196087 EC_WORD(runpath_elt.dn_ndx), 9825088Sab196087 elfedit_atoconst_value_to_str( 9835088Sab196087 ELFEDIT_CONST_DT, DT_RUNPATH, 1)); 9845088Sab196087 return (ELFEDIT_CMDRET_NONE); 9855088Sab196087 } 9865088Sab196087 } else if (argstate->dyn.num_null_ndx <= 1) { 9875088Sab196087 /* 9885088Sab196087 * There is no DT_RPATH or DT_RUNPATH in the dynamic array, 9895088Sab196087 * and there are no extra DT_NULL entries that we can 9905088Sab196087 * convert into one. We cannot proceed. 9915088Sab196087 */ 9925088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 9935088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 9945088Sab196087 } 9955088Sab196087 9965088Sab196087 /* Does the string exist in the table already, or can we add it? */ 9975088Sab196087 rpath_elt.dn_dyn.d_un.d_val = runpath_elt.dn_dyn.d_un.d_val = 9985088Sab196087 elfedit_dynstr_insert(dynsec, strsec, &strpad_elt, 9995088Sab196087 argstate->argv[0]); 10005088Sab196087 10015088Sab196087 /* Update DT_RPATH entry if present */ 10025088Sab196087 if (rpath_elt.dn_seen) { 10035088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_PREVRPATH), 10045088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 10055088Sab196087 EC_WORD(rpath_elt.dn_ndx), 10065088Sab196087 elfedit_atoconst_value_to_str( 10075088Sab196087 ELFEDIT_CONST_DT, DT_RPATH, 1), 10085088Sab196087 elfedit_dyn_offset_to_str(strsec, &rpath_elt)); 10095088Sab196087 dyn[rpath_elt.dn_ndx] = rpath_elt.dn_dyn; 10105088Sab196087 } 10115088Sab196087 10125088Sab196087 /* 10135088Sab196087 * Update the DT_RUNPATH entry in the dynamic section, if present. 10145088Sab196087 * If one is not present, and there is also no DT_RPATH, then 10155088Sab196087 * we use a spare DT_NULL entry to create a new DT_RUNPATH. 10165088Sab196087 */ 10175088Sab196087 if (runpath_elt.dn_seen || !rpath_elt.dn_seen) { 10185088Sab196087 if (runpath_elt.dn_seen) { 10195088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 10205088Sab196087 MSG_INTL(MSG_DEBUG_PREVRPATH), 10215088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 10225088Sab196087 EC_WORD(runpath_elt.dn_ndx), 10235088Sab196087 elfedit_atoconst_value_to_str( 10245088Sab196087 ELFEDIT_CONST_DT, DT_RUNPATH, 1), 10255088Sab196087 elfedit_dyn_offset_to_str(strsec, &runpath_elt)); 10265088Sab196087 dyn[runpath_elt.dn_ndx] = runpath_elt.dn_dyn; 10275088Sab196087 } else { /* Using a spare DT_NULL entry */ 10285088Sab196087 (void) convert_dt_null(argstate, DT_RUNPATH, 10295088Sab196087 runpath_elt.dn_dyn.d_un.d_val); 10305088Sab196087 } 10315088Sab196087 } 10325088Sab196087 10335088Sab196087 return (ELFEDIT_CMDRET_MOD); 10345088Sab196087 } 10355088Sab196087 10365088Sab196087 10375088Sab196087 10385088Sab196087 /* 10395088Sab196087 * Argument processing for the bitmask commands. Convert the arguments 10405088Sab196087 * to integer form, apply -and/-cmp/-or, and return the resulting value. 10415088Sab196087 * 10425088Sab196087 * entry: 10435088Sab196087 * argstate - Argument state block 10445088Sab196087 * orig - Value of original bitmask 10455088Sab196087 * const_type - ELFEDIT_CONST_* value for type of constants 10465088Sab196087 */ 10475088Sab196087 static Word 10485088Sab196087 flag_bitop(ARGSTATE *argstate, Word orig, elfedit_const_t const_type) 10495088Sab196087 { 10505088Sab196087 Word flags = 0; 10515088Sab196087 int i; 10525088Sab196087 10535088Sab196087 /* Collect the arguments */ 10545088Sab196087 for (i = 0; i < argstate->argc; i++) 10555088Sab196087 flags |= (Word) elfedit_atoconst(argstate->argv[i], const_type); 10565088Sab196087 10575088Sab196087 /* Complement the value? */ 10585088Sab196087 if (argstate->optmask & DYN_OPT_F_CMP) 10595088Sab196087 flags = ~flags; 10605088Sab196087 10615088Sab196087 /* Perform any requested bit operations */ 10625088Sab196087 if (argstate->optmask & DYN_OPT_F_AND) 10635088Sab196087 flags &= orig; 10645088Sab196087 else if (argstate->optmask & DYN_OPT_F_OR) 10655088Sab196087 flags |= orig; 10665088Sab196087 10675088Sab196087 return (flags); 10685088Sab196087 } 10695088Sab196087 10705088Sab196087 10715088Sab196087 10725088Sab196087 /* 10735088Sab196087 * Common body for the dyn: module commands. These commands 10745088Sab196087 * share a large amount of common behavior, so it is convenient 10755088Sab196087 * to centralize things and use the cmd argument to handle the 10765088Sab196087 * small differences. 10775088Sab196087 * 10785088Sab196087 * entry: 10795088Sab196087 * cmd - One of the DYN_CMD_T_* constants listed above, specifying 10805088Sab196087 * which command to implement. 10815088Sab196087 * obj_state, argc, argv - Standard command arguments 10825088Sab196087 */ 10835088Sab196087 static elfedit_cmdret_t 10845088Sab196087 cmd_body(DYN_CMD_T cmd, elfedit_obj_state_t *obj_state, 10855088Sab196087 int argc, const char *argv[]) 10865088Sab196087 { 10875088Sab196087 ARGSTATE argstate; 10885088Sab196087 Dyn *dyn; 10895088Sab196087 const char *dyn_name; 10905088Sab196087 Word dyn_ndx, dyn_num, null_ndx; 10915088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 10925088Sab196087 PRINT_DYN_T print_type = PRINT_DYN_T_ALL; 10935088Sab196087 Word ndx; 10945088Sab196087 int print_only = 0; 10955088Sab196087 int do_autoprint = 1; 10965088Sab196087 10975088Sab196087 /* Process the optional arguments */ 10985088Sab196087 process_args(obj_state, argc, argv, &argstate); 10995088Sab196087 11005088Sab196087 dyn = argstate.dyn.data; 11015088Sab196087 dyn_num = argstate.dyn.num; 11025088Sab196087 dyn_name = argstate.dyn.sec->sec_name; 11035088Sab196087 dyn_ndx = argstate.dyn.sec->sec_shndx; 11045088Sab196087 11055088Sab196087 /* Check number of arguments, gather information */ 11065088Sab196087 switch (cmd) { 11075088Sab196087 case DYN_CMD_T_DUMP: 11085088Sab196087 /* dyn:dump can accept an optional index argument */ 11095088Sab196087 if (argstate.argc > 1) 11105088Sab196087 elfedit_command_usage(); 11115088Sab196087 print_only = 1; 11125088Sab196087 if (argstate.argc == 1) 11135088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 1114*6225Sab196087 print_only, &print_type); 11155088Sab196087 break; 11165088Sab196087 11175088Sab196087 case DYN_CMD_T_TAG: 11185088Sab196087 print_only = (argstate.argc != 2); 11195088Sab196087 if (argstate.argc > 0) { 11205088Sab196087 if (argstate.argc > 2) 11215088Sab196087 elfedit_command_usage(); 11225088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 1123*6225Sab196087 print_only, &print_type); 11245088Sab196087 } 11255088Sab196087 break; 11265088Sab196087 11275088Sab196087 case DYN_CMD_T_VALUE: 11285088Sab196087 print_only = (argstate.argc != 2); 11295088Sab196087 if (argstate.argc > 2) 11305088Sab196087 elfedit_command_usage(); 11315088Sab196087 if (argstate.argc > 0) { 11325088Sab196087 if (print_only) { 11335088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11345088Sab196087 print_only, &print_type); 11355088Sab196087 } else { 11365088Sab196087 print_type = PRINT_DYN_T_NDX; 11375088Sab196087 } 11385088Sab196087 } 11395088Sab196087 break; 11405088Sab196087 11415088Sab196087 case DYN_CMD_T_DELETE: 11425088Sab196087 if ((argstate.argc < 1) || (argstate.argc > 2)) 11435088Sab196087 elfedit_command_usage(); 11445088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11455088Sab196087 0, &print_type); 11465088Sab196087 do_autoprint = 0; 11475088Sab196087 break; 11485088Sab196087 11495088Sab196087 case DYN_CMD_T_MOVE: 11505088Sab196087 if ((argstate.argc < 2) || (argstate.argc > 3)) 11515088Sab196087 elfedit_command_usage(); 11525088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 1153*6225Sab196087 0, &print_type); 11545088Sab196087 do_autoprint = 0; 11555088Sab196087 break; 11565088Sab196087 11575088Sab196087 case DYN_CMD_T_RUNPATH: 11585088Sab196087 if (argstate.argc > 1) 11595088Sab196087 elfedit_command_usage(); 11605088Sab196087 /* 11615088Sab196087 * dyn:runpath does not accept an explicit index 11625088Sab196087 * argument, so we implicitly only show the DT_RPATH and 11635088Sab196087 * DT_RUNPATH elements. 11645088Sab196087 */ 11655088Sab196087 print_type = PRINT_DYN_T_RUNPATH; 11665088Sab196087 print_only = (argstate.argc == 0); 11675088Sab196087 break; 11685088Sab196087 11695088Sab196087 case DYN_CMD_T_POSFLAG1: 11705088Sab196087 print_only = (argstate.argc == 0); 11715088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 11725088Sab196087 ELFEDIT_CONST_DT, DT_POSFLAG_1, 1), 1173*6225Sab196087 print_only, &print_type); 11745088Sab196087 break; 11755088Sab196087 11765088Sab196087 case DYN_CMD_T_FLAGS: 11775088Sab196087 print_only = (argstate.argc == 0); 11785088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 11795088Sab196087 ELFEDIT_CONST_DT, DT_FLAGS, 1), 1180*6225Sab196087 print_only, &print_type); 11815088Sab196087 break; 11825088Sab196087 11835088Sab196087 case DYN_CMD_T_FLAGS1: 11845088Sab196087 print_only = (argstate.argc == 0); 11855088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 11865088Sab196087 ELFEDIT_CONST_DT, DT_FLAGS_1, 1), 1187*6225Sab196087 print_only, &print_type); 11885088Sab196087 break; 11895088Sab196087 11905088Sab196087 case DYN_CMD_T_FEATURE1: 11915088Sab196087 print_only = (argstate.argc == 0); 11925088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 11935088Sab196087 ELFEDIT_CONST_DT, DT_FEATURE_1, 1), 1194*6225Sab196087 print_only, &print_type); 11955088Sab196087 break; 11965088Sab196087 11975088Sab196087 case DYN_CMD_T_CHECKSUM: 11985088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 11995088Sab196087 ELFEDIT_CONST_DT, DT_CHECKSUM, 1), 1200*6225Sab196087 print_only, &print_type); 12015088Sab196087 break; 12025088Sab196087 12036206Sab196087 case DYN_CMD_T_SUNW_LDMACH: 12046206Sab196087 if (argstate.argc > 1) 12056206Sab196087 elfedit_command_usage(); 12066206Sab196087 print_only = (argstate.argc == 0); 12076206Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12086206Sab196087 ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1), 1209*6225Sab196087 print_only, &print_type); 12106206Sab196087 break; 12116206Sab196087 12125088Sab196087 default: 12135088Sab196087 /* Note expected: All commands should have been caught above */ 12145088Sab196087 elfedit_command_usage(); 12155088Sab196087 break; 12165088Sab196087 } 12175088Sab196087 12185088Sab196087 12195088Sab196087 /* If this is a request to print current values, do it and return */ 12205088Sab196087 if (print_only) { 12215088Sab196087 print_dyn(cmd, 0, &argstate, print_type, ndx); 12225088Sab196087 return (ELFEDIT_CMDRET_NONE); 12235088Sab196087 } 12245088Sab196087 12255088Sab196087 12265088Sab196087 switch (cmd) { 12275088Sab196087 /* 12285088Sab196087 * DYN_CMD_T_DUMP can't get here: It is a print-only 12295088Sab196087 * command. 12305088Sab196087 */ 12315088Sab196087 12325088Sab196087 case DYN_CMD_T_TAG: 12335088Sab196087 { 12345088Sab196087 Conv_inv_buf_t inv_buf1, inv_buf2; 12355088Sab196087 Half mach = argstate.obj_state->os_ehdr->e_machine; 12365088Sab196087 Word d_tag = (Word) elfedit_atoconst(argstate.argv[1], 12375088Sab196087 ELFEDIT_CONST_DT); 12385088Sab196087 12395088Sab196087 if (dyn[ndx].d_tag == d_tag) { 12405088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12415088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), 12425088Sab196087 dyn_ndx, 12435088Sab196087 dyn_name, EC_WORD(ndx), 12445088Sab196087 conv_dyn_tag(d_tag, mach, 0, &inv_buf1)); 12455088Sab196087 } else { 12465088Sab196087 Word orig_d_tag = dyn[ndx].d_tag; 12475088Sab196087 12485088Sab196087 ret = ELFEDIT_CMDRET_MOD; 12495088Sab196087 dyn[ndx].d_tag = d_tag; 12505088Sab196087 12515088Sab196087 /* 12525088Sab196087 * Update null termination index. Warn if we 12535088Sab196087 * just clobbered the only DT_NULL termination 12545088Sab196087 * for the array. 12555088Sab196087 */ 12565088Sab196087 null_ndx = argstate.dyn.null_ndx; 12575088Sab196087 set_null_ndx(&argstate); 12585088Sab196087 if ((argstate.dyn.null_ndx >= 12595088Sab196087 argstate.dyn.num) && 12605088Sab196087 (null_ndx != argstate.dyn.null_ndx)) 12615088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12625088Sab196087 MSG_INTL(MSG_DEBUG_NULLTERM), 12635088Sab196087 dyn_ndx, dyn_name, 12645088Sab196087 EC_WORD(ndx), 12655088Sab196087 conv_dyn_tag(d_tag, mach, 12665088Sab196087 0, &inv_buf1)); 12675088Sab196087 12685088Sab196087 /* 12695088Sab196087 * Warning if 12705088Sab196087 * - Inserting a DT_NULL cuts off following 12715088Sab196087 * non-null elements. 12725088Sab196087 * - Inserting a non-DT_NULL after the 12735088Sab196087 * first null element, will be 12745088Sab196087 * ignored by rtld. 12755088Sab196087 */ 12765088Sab196087 if (d_tag == DT_NULL) { 12775088Sab196087 if ((ndx + 1) < null_ndx) 12785088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12795088Sab196087 MSG_INTL(MSG_DEBUG_NULCLIP), 12805088Sab196087 dyn_ndx, dyn_name, 12815088Sab196087 EC_WORD(ndx), 12825088Sab196087 conv_dyn_tag(d_tag, mach, 12835088Sab196087 0, &inv_buf1)); 12845088Sab196087 } else { 12855088Sab196087 if ((ndx + 1) > argstate.dyn.null_ndx) 12865088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12875088Sab196087 MSG_INTL(MSG_DEBUG_NULHIDE), 12885088Sab196087 dyn_ndx, dyn_name, 12895088Sab196087 EC_WORD(ndx), 12905088Sab196087 conv_dyn_tag(d_tag, mach, 12915088Sab196087 0, &inv_buf1)); 12925088Sab196087 } 12935088Sab196087 12945088Sab196087 /* Debug message that we changed it */ 12955088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12965088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 12975088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 12985088Sab196087 conv_dyn_tag(orig_d_tag, mach, 0, 12995088Sab196087 &inv_buf1), 13005088Sab196087 conv_dyn_tag(d_tag, mach, 0, &inv_buf2)); 13015088Sab196087 } 13025088Sab196087 } 13035088Sab196087 break; 13045088Sab196087 13055088Sab196087 case DYN_CMD_T_VALUE: 13065088Sab196087 ret = cmd_body_value(&argstate, &ndx); 13075088Sab196087 break; 13085088Sab196087 13095088Sab196087 case DYN_CMD_T_DELETE: 13105088Sab196087 { 13115088Sab196087 Word cnt = (argstate.argc == 1) ? 1 : 13125088Sab196087 (Word) elfedit_atoui_range(argstate.argv[1], 13135088Sab196087 MSG_ORIG(MSG_STR_COUNT), 1, dyn_num - ndx, NULL); 13145088Sab196087 const char *msg_prefix = 13155088Sab196087 elfedit_sec_msgprefix(argstate.dyn.sec); 13165088Sab196087 13175088Sab196087 elfedit_array_elts_delete(msg_prefix, argstate.dyn.data, 13185088Sab196087 sizeof (Dyn), dyn_num, ndx, cnt); 13195088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13205088Sab196087 } 13215088Sab196087 break; 13225088Sab196087 13235088Sab196087 case DYN_CMD_T_MOVE: 13245088Sab196087 { 13255088Sab196087 Dyn save; 13265088Sab196087 Word cnt; 13275088Sab196087 Word dstndx; 13285088Sab196087 const char *msg_prefix = 13295088Sab196087 elfedit_sec_msgprefix(argstate.dyn.sec); 13305088Sab196087 13315088Sab196087 dstndx = (Word) 13325088Sab196087 elfedit_atoui_range(argstate.argv[1], 13335088Sab196087 MSG_ORIG(MSG_STR_DST_INDEX), 0, dyn_num - 1, 13345088Sab196087 NULL); 13355088Sab196087 if (argstate.argc == 2) { 13365088Sab196087 cnt = 1; 13375088Sab196087 } else { 13385088Sab196087 cnt = (Word) elfedit_atoui_range( 13395088Sab196087 argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), 13405088Sab196087 1, dyn_num, NULL); 13415088Sab196087 } 13425088Sab196087 elfedit_array_elts_move(msg_prefix, argstate.dyn.data, 13435088Sab196087 sizeof (save), dyn_num, ndx, dstndx, cnt, &save); 13445088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13455088Sab196087 } 13465088Sab196087 break; 13475088Sab196087 13485088Sab196087 13495088Sab196087 case DYN_CMD_T_RUNPATH: 13505088Sab196087 ret = cmd_body_runpath(&argstate); 13515088Sab196087 break; 13525088Sab196087 13535088Sab196087 case DYN_CMD_T_POSFLAG1: 13545088Sab196087 { 13555088Sab196087 Conv_dyn_posflag1_buf_t buf1, buf2; 13565088Sab196087 Word flags; 13575088Sab196087 13585088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 13595088Sab196087 ELFEDIT_CONST_DF_P1); 13605088Sab196087 13615088Sab196087 /* Set the value */ 13625088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 13635088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13645088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 13655088Sab196087 dyn_name, EC_WORD(ndx), 13665088Sab196087 conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 13675088Sab196087 &buf1)); 13685088Sab196087 } else { 13695088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13705088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 13715088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 13725088Sab196087 conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 13735088Sab196087 &buf1), 13745088Sab196087 conv_dyn_posflag1(flags, 0, &buf2)); 13755088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13765088Sab196087 dyn[ndx].d_un.d_val = flags; 13775088Sab196087 } 13785088Sab196087 } 13795088Sab196087 break; 13805088Sab196087 13815088Sab196087 case DYN_CMD_T_FLAGS: 13825088Sab196087 { 13835088Sab196087 Conv_dyn_flag_buf_t buf1, buf2; 13845088Sab196087 Word flags; 13855088Sab196087 13865088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 13875088Sab196087 ELFEDIT_CONST_DF); 13885088Sab196087 13895088Sab196087 /* Set the value */ 13905088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 13915088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13925088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 13935088Sab196087 dyn_name, EC_WORD(ndx), 13945088Sab196087 conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 13955088Sab196087 &buf1)); 13965088Sab196087 } else { 13975088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13985088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 13995088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14005088Sab196087 conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 14015088Sab196087 &buf1), 14025088Sab196087 conv_dyn_flag(flags, 0, &buf2)); 14035088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14045088Sab196087 dyn[ndx].d_un.d_val = flags; 14055088Sab196087 } 14065088Sab196087 } 14075088Sab196087 break; 14085088Sab196087 14095088Sab196087 case DYN_CMD_T_FLAGS1: 14105088Sab196087 { 14115088Sab196087 Conv_dyn_flag1_buf_t buf1, buf2; 14125088Sab196087 Word flags1; 14135088Sab196087 14145088Sab196087 flags1 = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14155088Sab196087 ELFEDIT_CONST_DF_1); 14165088Sab196087 14175088Sab196087 /* Set the value */ 14185088Sab196087 if (dyn[ndx].d_un.d_val == flags1) { 14195088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14205088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14215088Sab196087 dyn_name, EC_WORD(ndx), 14225088Sab196087 conv_dyn_flag1(dyn[ndx].d_un.d_val, 14235088Sab196087 0, &buf1)); 14245088Sab196087 } else { 14255088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14265088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14275088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14285088Sab196087 conv_dyn_flag1(dyn[ndx].d_un.d_val, 14295088Sab196087 0, &buf1), 14305088Sab196087 conv_dyn_flag1(flags1, 0, &buf2)); 14315088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14325088Sab196087 dyn[ndx].d_un.d_val = flags1; 14335088Sab196087 } 14345088Sab196087 } 14355088Sab196087 break; 14365088Sab196087 14375088Sab196087 case DYN_CMD_T_FEATURE1: 14385088Sab196087 { 14395088Sab196087 Conv_dyn_feature1_buf_t buf1, buf2; 14405088Sab196087 Word flags; 14415088Sab196087 14425088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14435088Sab196087 ELFEDIT_CONST_DTF_1); 14445088Sab196087 14455088Sab196087 /* Set the value */ 14465088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 14475088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14485088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14495088Sab196087 dyn_name, EC_WORD(ndx), 14505088Sab196087 conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 14515088Sab196087 &buf1)); 14525088Sab196087 } else { 14535088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14545088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14555088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14565088Sab196087 conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 14575088Sab196087 &buf1), 14585088Sab196087 conv_dyn_feature1(flags, 0, &buf2)); 14595088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14605088Sab196087 dyn[ndx].d_un.d_val = flags; 14615088Sab196087 } 14625088Sab196087 } 14635088Sab196087 break; 14645088Sab196087 14655088Sab196087 case DYN_CMD_T_CHECKSUM: 14665088Sab196087 { 14675088Sab196087 long checksum = elf_checksum(obj_state->os_elf); 14685088Sab196087 14695088Sab196087 /* Set the value */ 14705088Sab196087 if (dyn[ndx].d_un.d_val == checksum) { 14715088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14725088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), dyn_ndx, 14735088Sab196087 dyn_name, EC_WORD(ndx), EC_XWORD(checksum)); 14745088Sab196087 } else { 14755088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14765088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 14775088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14785088Sab196087 EC_XWORD(dyn[ndx].d_un.d_val), 14795088Sab196087 EC_XWORD(checksum)); 14805088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14815088Sab196087 dyn[ndx].d_un.d_val = checksum; 14825088Sab196087 } 14835088Sab196087 14845088Sab196087 } 14856206Sab196087 break; 14866206Sab196087 14876206Sab196087 case DYN_CMD_T_SUNW_LDMACH: 14886206Sab196087 { 14896206Sab196087 Conv_inv_buf_t buf1, buf2; 14906206Sab196087 Half ldmach; 14916206Sab196087 14926206Sab196087 ldmach = (Half) elfedit_atoconst(argstate.argv[0], 14936206Sab196087 ELFEDIT_CONST_EM); 14946206Sab196087 14956206Sab196087 /* Set the value */ 14966206Sab196087 if (dyn[ndx].d_un.d_val == ldmach) { 14976206Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14986206Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14996206Sab196087 dyn_name, EC_WORD(ndx), 15006206Sab196087 conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 15016206Sab196087 &buf1)); 15026206Sab196087 } else { 15036206Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15046206Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 15056206Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 15066206Sab196087 conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 15076206Sab196087 &buf1), 15086206Sab196087 conv_ehdr_mach(ldmach, 0, &buf2)); 15096206Sab196087 ret = ELFEDIT_CMDRET_MOD; 15106206Sab196087 dyn[ndx].d_un.d_val = ldmach; 15116206Sab196087 } 15126206Sab196087 } 15136206Sab196087 break; 15146206Sab196087 15155088Sab196087 } 15165088Sab196087 15175088Sab196087 /* 15185088Sab196087 * If we modified the dynamic section header, tell libelf. 15195088Sab196087 */ 15205088Sab196087 if (ret == ELFEDIT_CMDRET_MOD) 15215088Sab196087 elfedit_modified_data(argstate.dyn.sec); 15225088Sab196087 15235088Sab196087 /* Do autoprint */ 15245088Sab196087 if (do_autoprint) 15255088Sab196087 print_dyn(cmd, 1, &argstate, print_type, ndx); 15265088Sab196087 15275088Sab196087 return (ret); 15285088Sab196087 } 15295088Sab196087 15305088Sab196087 15315088Sab196087 15325088Sab196087 /* 15335088Sab196087 * Command completion functions for the commands 15345088Sab196087 */ 15355088Sab196087 15365088Sab196087 /* 15375088Sab196087 * Command completion for the first argument, which specifies 15385088Sab196087 * the dynamic element to use. Examines the options to see if 15395088Sab196087 * -dynndx is present, and if not, supplies the completion 15405088Sab196087 * strings for argument 1. 15415088Sab196087 */ 15425088Sab196087 /*ARGSUSED*/ 15435088Sab196087 static void 15445088Sab196087 cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 15455088Sab196087 const char *argv[], int num_opt) 15465088Sab196087 { 15475088Sab196087 elfedit_section_t *cache; 15485088Sab196087 Dyn *dyn; 15495088Sab196087 Word i; 15505088Sab196087 const char *s; 15515088Sab196087 char *s2; 15525088Sab196087 char buf[128]; 15535088Sab196087 15545088Sab196087 /* Make sure it's the first argument */ 15555088Sab196087 if ((argc - num_opt) != 1) 15565088Sab196087 return; 15575088Sab196087 15585088Sab196087 /* Is -dynndx present? If so, we don't complete tag types */ 15595088Sab196087 for (i = 0; i < num_opt; i++) 15605088Sab196087 if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0) 15615088Sab196087 return; 15625088Sab196087 15635088Sab196087 /* 15645088Sab196087 * If there is no object, or if there is no dynamic section, 15655088Sab196087 * then supply all possible names. 15665088Sab196087 */ 15675088Sab196087 if ((obj_state == NULL) || (obj_state->os_dynndx == SHN_UNDEF)) { 15685088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 15695088Sab196087 return; 15705088Sab196087 } 15715088Sab196087 15725088Sab196087 /* Supply completions for the tags present in the dynamic section */ 15735088Sab196087 cache = &obj_state->os_secarr[obj_state->os_dynndx]; 15745088Sab196087 dyn = (Dyn *) cache->sec_data->d_buf; 15755088Sab196087 i = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize; 15765088Sab196087 for (; i-- > 0; dyn++) { 15775088Sab196087 s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_DT, 15785088Sab196087 dyn->d_tag, 0); 15795088Sab196087 if (s == NULL) 15805088Sab196087 continue; 15815088Sab196087 elfedit_cpl_match(cpldata, s, 1); 15825088Sab196087 15835088Sab196087 /* 15845088Sab196087 * To get the informal tag names that are lowercase 15855088Sab196087 * and lack the leading DT_, we copy the string we 15865088Sab196087 * have into a buffer and process it. 15875088Sab196087 */ 15885088Sab196087 if (strlen(s) < 3) 15895088Sab196087 continue; 15905088Sab196087 (void) strlcpy(buf, s + 3, sizeof (buf)); 15915088Sab196087 for (s2 = buf; *s2 != '\0'; s2++) 15925088Sab196087 if (isupper(*s2)) 15935088Sab196087 *s2 = tolower(*s2); 15945088Sab196087 elfedit_cpl_match(cpldata, buf, 1); 15955088Sab196087 } 15965088Sab196087 } 15975088Sab196087 15985088Sab196087 15995088Sab196087 /*ARGSUSED*/ 16005088Sab196087 static void 16015088Sab196087 cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16025088Sab196087 const char *argv[], int num_opt) 16035088Sab196087 { 16045088Sab196087 /* First argument */ 16055088Sab196087 if ((argc - num_opt) == 1) { 16065088Sab196087 cpl_eltarg(obj_state, cpldata, argc, argv, num_opt); 16075088Sab196087 return; 16085088Sab196087 } 16095088Sab196087 16105088Sab196087 /* The second argument is always a tag value */ 16115088Sab196087 if ((argc - num_opt) == 2) 16125088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 16135088Sab196087 } 16145088Sab196087 16155088Sab196087 /*ARGSUSED*/ 16165088Sab196087 static void 16175088Sab196087 cpl_posflag1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16185088Sab196087 const char *argv[], int num_opt) 16195088Sab196087 { 1620*6225Sab196087 /* 1621*6225Sab196087 * dyn:posflag1 accepts two mutually exclusive options that have 1622*6225Sab196087 * a corresponding value argument: -dynndx and -needed. If we 1623*6225Sab196087 * are being called to supply options for the value, handle that here. 1624*6225Sab196087 */ 1625*6225Sab196087 if ((num_opt > 1) && (argc == num_opt)) { 1626*6225Sab196087 elfedit_section_t *dynsec, *strsec; 1627*6225Sab196087 const char *opt = argv[num_opt - 2]; 1628*6225Sab196087 dyn_opt_t type; 1629*6225Sab196087 Dyn *dyn; 1630*6225Sab196087 Word i, num; 1631*6225Sab196087 1632*6225Sab196087 /* 1633*6225Sab196087 * If there is no object available, or if the object has no 1634*6225Sab196087 * dynamic section, then there is nothing to report. 1635*6225Sab196087 */ 1636*6225Sab196087 if ((obj_state == NULL) || obj_state->os_dynndx == SHN_UNDEF) 1637*6225Sab196087 return; 1638*6225Sab196087 1639*6225Sab196087 /* 1640*6225Sab196087 * Determine which option it is, bail if it isn't one of 1641*6225Sab196087 * the ones we are concerned with. 1642*6225Sab196087 */ 1643*6225Sab196087 if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_NEEDED)) == 0)) 1644*6225Sab196087 type = DYN_OPT_F_NEEDED; 1645*6225Sab196087 else if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0)) 1646*6225Sab196087 type = DYN_OPT_F_DYNNDX_VAL; 1647*6225Sab196087 else 1648*6225Sab196087 return; 1649*6225Sab196087 1650*6225Sab196087 dynsec = elfedit_sec_getdyn(obj_state, &dyn, &num); 1651*6225Sab196087 switch (type) { 1652*6225Sab196087 case DYN_OPT_F_NEEDED: 1653*6225Sab196087 strsec = elfedit_sec_getstr(obj_state, 1654*6225Sab196087 dynsec->sec_shdr->sh_link, 0); 1655*6225Sab196087 for (; num-- > 0; dyn++) 1656*6225Sab196087 if (dyn->d_tag == DT_NEEDED) 1657*6225Sab196087 elfedit_cpl_match(cpldata, 1658*6225Sab196087 elfedit_offset_to_str(strsec, 1659*6225Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 1660*6225Sab196087 0), 0); 1661*6225Sab196087 break; 1662*6225Sab196087 1663*6225Sab196087 case DYN_OPT_F_DYNNDX_VAL: 1664*6225Sab196087 for (i = 0; i < num; i++, dyn++) 1665*6225Sab196087 if (dyn->d_tag == DT_POSFLAG_1) 1666*6225Sab196087 elfedit_cpl_ndx(cpldata, i); 1667*6225Sab196087 break; 1668*6225Sab196087 } 1669*6225Sab196087 return; 1670*6225Sab196087 } 1671*6225Sab196087 16725088Sab196087 /* This routine allows multiple flags to be specified */ 16735088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_P1); 16745088Sab196087 } 16755088Sab196087 16765088Sab196087 /*ARGSUSED*/ 16775088Sab196087 static void 16785088Sab196087 cpl_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16795088Sab196087 const char *argv[], int num_opt) 16805088Sab196087 { 16815088Sab196087 /* This routine allows multiple flags to be specified */ 16825088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF); 16835088Sab196087 } 16845088Sab196087 16855088Sab196087 /*ARGSUSED*/ 16865088Sab196087 static void 16875088Sab196087 cpl_flags1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16885088Sab196087 const char *argv[], int num_opt) 16895088Sab196087 { 16905088Sab196087 /* This routine allows multiple flags to be specified */ 16915088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_1); 16925088Sab196087 } 16935088Sab196087 16945088Sab196087 /*ARGSUSED*/ 16955088Sab196087 static void 16965088Sab196087 cpl_feature1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16975088Sab196087 const char *argv[], int num_opt) 16985088Sab196087 { 16995088Sab196087 /* This routine allows multiple flags to be specified */ 17005088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1); 17015088Sab196087 } 17025088Sab196087 17036206Sab196087 /*ARGSUSED*/ 17046206Sab196087 static void 17056206Sab196087 cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17066206Sab196087 const char *argv[], int num_opt) 17076206Sab196087 { 17086206Sab196087 /* 17096206Sab196087 * This command doesn't accept options, so num_opt should be 17106206Sab196087 * 0. This is a defensive measure, in case that should change. 17116206Sab196087 */ 17126206Sab196087 argc -= num_opt; 17136206Sab196087 argv += num_opt; 17146206Sab196087 17156206Sab196087 if (argc == 1) 17166206Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM); 17176206Sab196087 } 17186206Sab196087 17195088Sab196087 17205088Sab196087 /* 17215088Sab196087 * Implementation functions for the commands 17225088Sab196087 */ 17235088Sab196087 static elfedit_cmdret_t 17245088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17255088Sab196087 { 17265088Sab196087 return (cmd_body(DYN_CMD_T_DUMP, obj_state, argc, argv)); 17275088Sab196087 } 17285088Sab196087 17295088Sab196087 static elfedit_cmdret_t 17305088Sab196087 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17315088Sab196087 { 17325088Sab196087 return (cmd_body(DYN_CMD_T_TAG, obj_state, argc, argv)); 17335088Sab196087 } 17345088Sab196087 17355088Sab196087 static elfedit_cmdret_t 17365088Sab196087 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17375088Sab196087 { 17385088Sab196087 return (cmd_body(DYN_CMD_T_VALUE, obj_state, argc, argv)); 17395088Sab196087 } 17405088Sab196087 17415088Sab196087 static elfedit_cmdret_t 17425088Sab196087 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17435088Sab196087 { 17445088Sab196087 return (cmd_body(DYN_CMD_T_DELETE, obj_state, argc, argv)); 17455088Sab196087 } 17465088Sab196087 17475088Sab196087 static elfedit_cmdret_t 17485088Sab196087 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17495088Sab196087 { 17505088Sab196087 return (cmd_body(DYN_CMD_T_MOVE, obj_state, argc, argv)); 17515088Sab196087 } 17525088Sab196087 17535088Sab196087 static elfedit_cmdret_t 17545088Sab196087 cmd_runpath(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17555088Sab196087 { 17565088Sab196087 return (cmd_body(DYN_CMD_T_RUNPATH, obj_state, argc, argv)); 17575088Sab196087 } 17585088Sab196087 17595088Sab196087 static elfedit_cmdret_t 17605088Sab196087 cmd_posflag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17615088Sab196087 { 17625088Sab196087 return (cmd_body(DYN_CMD_T_POSFLAG1, obj_state, argc, argv)); 17635088Sab196087 } 17645088Sab196087 17655088Sab196087 static elfedit_cmdret_t 17665088Sab196087 cmd_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17675088Sab196087 { 17685088Sab196087 return (cmd_body(DYN_CMD_T_FLAGS, obj_state, argc, argv)); 17695088Sab196087 } 17705088Sab196087 17715088Sab196087 static elfedit_cmdret_t 17725088Sab196087 cmd_flags1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17735088Sab196087 { 17745088Sab196087 return (cmd_body(DYN_CMD_T_FLAGS1, obj_state, argc, argv)); 17755088Sab196087 } 17765088Sab196087 17775088Sab196087 static elfedit_cmdret_t 17785088Sab196087 cmd_feature1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17795088Sab196087 { 17805088Sab196087 return (cmd_body(DYN_CMD_T_FEATURE1, obj_state, argc, argv)); 17815088Sab196087 } 17825088Sab196087 17835088Sab196087 static elfedit_cmdret_t 17845088Sab196087 cmd_checksum(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17855088Sab196087 { 17865088Sab196087 return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv)); 17875088Sab196087 } 17885088Sab196087 17896206Sab196087 static elfedit_cmdret_t 17906206Sab196087 cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17916206Sab196087 { 17926206Sab196087 return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv)); 17936206Sab196087 } 17946206Sab196087 17955088Sab196087 17965088Sab196087 17975088Sab196087 /*ARGSUSED*/ 17985088Sab196087 elfedit_module_t * 17995088Sab196087 elfedit_init(elfedit_module_version_t version) 18005088Sab196087 { 18015088Sab196087 /* For commands that only accept -o */ 18025088Sab196087 static elfedit_cmd_optarg_t opt_ostyle[] = { 18035088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18045088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18055088Sab196087 { NULL } 18065088Sab196087 }; 18075088Sab196087 18085088Sab196087 /* For commands that only accept -and, -cmp, -o, -or */ 18095088Sab196087 static elfedit_cmd_optarg_t opt_ostyle_bitop[] = { 18105088Sab196087 { ELFEDIT_STDOA_OPT_AND, NULL, 18115088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 18125088Sab196087 { ELFEDIT_STDOA_OPT_CMP, NULL, 18135088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 18145088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18155088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18165088Sab196087 { ELFEDIT_STDOA_OPT_OR, NULL, 18175088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 18185088Sab196087 { NULL } 18195088Sab196087 }; 18205088Sab196087 18215088Sab196087 /* For commands that only accept -dynndx */ 18225088Sab196087 static elfedit_cmd_optarg_t opt_minus_dynndx[] = { 18235088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 1824*6225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 1825*6225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 1826*6225Sab196087 DYN_OPT_F_DYNNDX_ELT, 0 }, 18275088Sab196087 { NULL } 18285088Sab196087 }; 18295088Sab196087 18305088Sab196087 /* dyn:dump */ 18315088Sab196087 static const char *name_dump[] = { 18325088Sab196087 MSG_ORIG(MSG_CMD_DUMP), 18335088Sab196087 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 18345088Sab196087 NULL 18355088Sab196087 }; 18365088Sab196087 static elfedit_cmd_optarg_t arg_dump[] = { 18375088Sab196087 { MSG_ORIG(MSG_STR_ELT), 18385088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 18395088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 18405088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18415088Sab196087 { NULL } 18425088Sab196087 }; 18435088Sab196087 18445088Sab196087 18455088Sab196087 /* dyn:tag */ 18465088Sab196087 static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL }; 18475088Sab196087 static elfedit_cmd_optarg_t opt_tag[] = { 18485088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 1849*6225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 1850*6225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 1851*6225Sab196087 DYN_OPT_F_DYNNDX_ELT, 0 }, 18525088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18535088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18545088Sab196087 { NULL } 18555088Sab196087 }; 18565088Sab196087 static elfedit_cmd_optarg_t arg_tag[] = { 18575088Sab196087 { MSG_ORIG(MSG_STR_ELT), 18585088Sab196087 /* MSG_INTL(MSG_A1_TAG_ELT) */ 18595088Sab196087 ELFEDIT_I18NHDL(MSG_A1_TAG_ELT), 18605088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18615088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 18625088Sab196087 /* MSG_INTL(MSG_A2_TAG_VALUE) */ 18635088Sab196087 ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE), 18645088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18655088Sab196087 { NULL } 18665088Sab196087 }; 18675088Sab196087 18685088Sab196087 18695088Sab196087 /* dyn:value */ 18705088Sab196087 static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL }; 18715088Sab196087 static elfedit_cmd_optarg_t opt_value[] = { 18725088Sab196087 { MSG_ORIG(MSG_STR_MINUS_ADD), 18735088Sab196087 /* MSG_INTL(MSG_OPTDESC_ADD) */ 18745088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_ADD), 0, 1875*6225Sab196087 DYN_OPT_F_ADD, DYN_OPT_F_DYNNDX_ELT }, 18765088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 1877*6225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 1878*6225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 1879*6225Sab196087 DYN_OPT_F_DYNNDX_ELT, DYN_OPT_F_ADD }, 18805088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18815088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18825088Sab196087 { MSG_ORIG(MSG_STR_MINUS_S), 18835088Sab196087 /* MSG_INTL(MSG_OPTDESC_S) */ 18845088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0, 18855088Sab196087 DYN_OPT_F_STRVAL, 0 }, 18865088Sab196087 { NULL } 18875088Sab196087 }; 18885088Sab196087 static elfedit_cmd_optarg_t arg_value[] = { 18895088Sab196087 { MSG_ORIG(MSG_STR_ELT), 18905088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 18915088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 18925088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18935088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 18945088Sab196087 /* MSG_INTL(MSG_A2_VALUE_VALUE) */ 18955088Sab196087 ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE), 18965088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18975088Sab196087 { NULL } 18985088Sab196087 }; 18995088Sab196087 19005088Sab196087 /* dyn:delete */ 19015088Sab196087 static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL }; 19025088Sab196087 static elfedit_cmd_optarg_t arg_delete[] = { 19035088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19045088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19055088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19065088Sab196087 0 }, 19075088Sab196087 { MSG_ORIG(MSG_STR_COUNT), 19085088Sab196087 /* MSG_INTL(MSG_A2_DELETE_COUNT) */ 19095088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT), 19105088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19115088Sab196087 { NULL } 19125088Sab196087 }; 19135088Sab196087 19145088Sab196087 /* dyn:move */ 19155088Sab196087 static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL }; 19165088Sab196087 static elfedit_cmd_optarg_t arg_move[] = { 19175088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19185088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19195088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19205088Sab196087 0 }, 19215088Sab196087 { MSG_ORIG(MSG_STR_DST_INDEX), 19225088Sab196087 /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */ 19235088Sab196087 ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX), 19245088Sab196087 0 }, 19255088Sab196087 { MSG_ORIG(MSG_STR_COUNT), 19265088Sab196087 /* MSG_INTL(MSG_A3_MOVE_COUNT) */ 19275088Sab196087 ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT), 19285088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19295088Sab196087 { NULL } 19305088Sab196087 }; 19315088Sab196087 19325088Sab196087 /* dyn:runpath / dyn:rpath */ 19335088Sab196087 static const char *name_runpath[] = { MSG_ORIG(MSG_CMD_RUNPATH), 19345088Sab196087 MSG_ORIG(MSG_CMD_RUNPATH_A1), NULL }; 19355088Sab196087 static elfedit_cmd_optarg_t arg_runpath[] = { 19365088Sab196087 { MSG_ORIG(MSG_STR_NEWPATH), 19375088Sab196087 /* MSG_INTL(MSG_A1_RUNPATH_NEWPATH) */ 19385088Sab196087 ELFEDIT_I18NHDL(MSG_A1_RUNPATH_NEWPATH), 19395088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19405088Sab196087 { NULL } 19415088Sab196087 }; 19425088Sab196087 19435088Sab196087 /* dyn:posflag1 */ 19445088Sab196087 static const char *name_posflag1[] = { MSG_ORIG(MSG_CMD_POSFLAG1), 19455088Sab196087 NULL }; 1946*6225Sab196087 static elfedit_cmd_optarg_t opt_posflag1[] = { 1947*6225Sab196087 { ELFEDIT_STDOA_OPT_AND, NULL, 1948*6225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 1949*6225Sab196087 { ELFEDIT_STDOA_OPT_CMP, NULL, 1950*6225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 1951*6225Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 1952*6225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_VAL) */ 1953*6225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_VAL), 1954*6225Sab196087 ELFEDIT_CMDOA_F_VALUE, 1955*6225Sab196087 DYN_OPT_F_DYNNDX_VAL, DYN_OPT_F_NEEDED }, 1956*6225Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 1957*6225Sab196087 { MSG_ORIG(MSG_STR_MINUS_NEEDED), 1958*6225Sab196087 /* MSG_INTL(MSG_OPTDESC_NEEDED) */ 1959*6225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_NEEDED), 1960*6225Sab196087 ELFEDIT_CMDOA_F_VALUE, 1961*6225Sab196087 DYN_OPT_F_NEEDED, DYN_OPT_F_DYNNDX_VAL }, 1962*6225Sab196087 { MSG_ORIG(MSG_STR_PREFIX), NULL, 0, 0 }, 1963*6225Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 1964*6225Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1965*6225Sab196087 { ELFEDIT_STDOA_OPT_OR, NULL, 1966*6225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 1967*6225Sab196087 { NULL } 1968*6225Sab196087 }; 19695088Sab196087 static elfedit_cmd_optarg_t arg_posflag1[] = { 19705088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19715088Sab196087 /* MSG_INTL(MSG_A1_POSFLAG1_VALUE) */ 19725088Sab196087 ELFEDIT_I18NHDL(MSG_A1_POSFLAG1_VALUE), 19735088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 19745088Sab196087 { NULL } 19755088Sab196087 }; 19765088Sab196087 19775088Sab196087 /* dyn:flags */ 19785088Sab196087 static const char *name_flags[] = { MSG_ORIG(MSG_CMD_FLAGS), NULL }; 19795088Sab196087 static elfedit_cmd_optarg_t arg_flags[] = { 19805088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19815088Sab196087 /* MSG_INTL(MSG_A1_FLAGS_VALUE) */ 19825088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FLAGS_VALUE), 19835088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 19845088Sab196087 { NULL } 19855088Sab196087 }; 19865088Sab196087 19875088Sab196087 /* dyn:flags1 */ 19885088Sab196087 static const char *name_flags1[] = { MSG_ORIG(MSG_CMD_FLAGS1), NULL }; 19895088Sab196087 static elfedit_cmd_optarg_t arg_flags1[] = { 19905088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19915088Sab196087 /* MSG_INTL(MSG_A1_FLAGS1_VALUE) */ 19925088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FLAGS1_VALUE), 19935088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 19945088Sab196087 { NULL } 19955088Sab196087 }; 19965088Sab196087 19975088Sab196087 /* dyn:feature1 */ 19985088Sab196087 static const char *name_feature1[] = { MSG_ORIG(MSG_CMD_FEATURE1), 19995088Sab196087 NULL }; 20005088Sab196087 static elfedit_cmd_optarg_t arg_feature1[] = { 20015088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20025088Sab196087 /* MSG_INTL(MSG_A1_FEATURE1_VALUE) */ 20035088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FEATURE1_VALUE), 20045088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20055088Sab196087 { NULL } 20065088Sab196087 }; 20075088Sab196087 20085088Sab196087 /* dyn:checksum */ 20095088Sab196087 static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM), 20105088Sab196087 NULL }; 20115088Sab196087 20126206Sab196087 /* dyn:sunw_ldmach */ 20136206Sab196087 static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH), 20146206Sab196087 NULL }; 20156206Sab196087 static elfedit_cmd_optarg_t arg_sunw_ldmach[] = { 20166206Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20176206Sab196087 /* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */ 20186206Sab196087 ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE), 20196206Sab196087 ELFEDIT_CMDOA_F_OPT }, 20206206Sab196087 { NULL } 20216206Sab196087 }; 20226206Sab196087 20235088Sab196087 20245088Sab196087 20255088Sab196087 static elfedit_cmd_t cmds[] = { 20265088Sab196087 /* dyn:dump */ 20275088Sab196087 { cmd_dump, cpl_eltarg, name_dump, 20285088Sab196087 /* MSG_INTL(MSG_DESC_DUMP) */ 20295088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 20305088Sab196087 /* MSG_INTL(MSG_HELP_DUMP) */ 20315088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 20325088Sab196087 opt_minus_dynndx, arg_dump }, 20335088Sab196087 20345088Sab196087 /* dyn:tag */ 20355088Sab196087 { cmd_tag, cpl_tag, name_tag, 20365088Sab196087 /* MSG_INTL(MSG_DESC_TAG) */ 20375088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_TAG), 20385088Sab196087 /* MSG_INTL(MSG_HELP_TAG) */ 20395088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_TAG), 20405088Sab196087 opt_tag, arg_tag }, 20415088Sab196087 20425088Sab196087 /* dyn:value */ 20435088Sab196087 { cmd_value, cpl_eltarg, name_value, 20445088Sab196087 /* MSG_INTL(MSG_DESC_VALUE) */ 20455088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_VALUE), 20465088Sab196087 /* MSG_INTL(MSG_HELP_VALUE) */ 20475088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_VALUE), 20485088Sab196087 opt_value, arg_value }, 20495088Sab196087 20505088Sab196087 /* dyn:delete */ 20515088Sab196087 { cmd_delete, cpl_eltarg, name_delete, 20525088Sab196087 /* MSG_INTL(MSG_DESC_DELETE) */ 20535088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DELETE), 20545088Sab196087 /* MSG_INTL(MSG_HELP_DELETE) */ 20555088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DELETE), 20565088Sab196087 opt_minus_dynndx, arg_delete }, 20575088Sab196087 20585088Sab196087 /* dyn:move */ 20595088Sab196087 { cmd_move, cpl_eltarg, name_move, 20605088Sab196087 /* MSG_INTL(MSG_DESC_MOVE) */ 20615088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_MOVE), 20625088Sab196087 /* MSG_INTL(MSG_HELP_MOVE) */ 20635088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_MOVE), 20645088Sab196087 opt_minus_dynndx, arg_move }, 20655088Sab196087 20665088Sab196087 /* dyn:runpath */ 20675088Sab196087 { cmd_runpath, NULL, name_runpath, 20685088Sab196087 /* MSG_INTL(MSG_DESC_RUNPATH) */ 20695088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_RUNPATH), 20705088Sab196087 /* MSG_INTL(MSG_HELP_RUNPATH) */ 20715088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_RUNPATH), 20725088Sab196087 opt_ostyle, arg_runpath }, 20735088Sab196087 20745088Sab196087 /* dyn:posflag1 */ 20755088Sab196087 { cmd_posflag1, cpl_posflag1, name_posflag1, 20765088Sab196087 /* MSG_INTL(MSG_DESC_POSFLAG1) */ 20775088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_POSFLAG1), 20785088Sab196087 /* MSG_INTL(MSG_HELP_POSFLAG1) */ 20795088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_POSFLAG1), 2080*6225Sab196087 opt_posflag1, arg_posflag1 }, 20815088Sab196087 20825088Sab196087 /* dyn:flags */ 20835088Sab196087 { cmd_flags, cpl_flags, name_flags, 20845088Sab196087 /* MSG_INTL(MSG_DESC_FLAGS) */ 20855088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FLAGS), 20865088Sab196087 /* MSG_INTL(MSG_HELP_FLAGS) */ 20875088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FLAGS), 20885088Sab196087 opt_ostyle_bitop, arg_flags }, 20895088Sab196087 20905088Sab196087 /* dyn:flags1 */ 20915088Sab196087 { cmd_flags1, cpl_flags1, name_flags1, 20925088Sab196087 /* MSG_INTL(MSG_DESC_FLAGS1) */ 20935088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FLAGS1), 20945088Sab196087 /* MSG_INTL(MSG_HELP_FLAGS1) */ 20955088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FLAGS1), 20965088Sab196087 opt_ostyle_bitop, arg_flags1 }, 20975088Sab196087 20985088Sab196087 /* dyn:feature1 */ 20995088Sab196087 { cmd_feature1, cpl_feature1, name_feature1, 21005088Sab196087 /* MSG_INTL(MSG_DESC_FEATURE1) */ 21015088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FEATURE1), 21025088Sab196087 /* MSG_INTL(MSG_HELP_FEATURE1) */ 21035088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FEATURE1), 21045088Sab196087 opt_ostyle_bitop, arg_feature1 }, 21055088Sab196087 21065088Sab196087 /* dyn:checksum */ 21075088Sab196087 { cmd_checksum, NULL, name_checksum, 21085088Sab196087 /* MSG_INTL(MSG_DESC_CHECKSUM) */ 21095088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_CHECKSUM), 21105088Sab196087 /* MSG_INTL(MSG_HELP_CHECKSUM) */ 21115088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM), 21125088Sab196087 NULL, NULL }, 21135088Sab196087 21146206Sab196087 /* dyn:sunw_ldmach */ 21156206Sab196087 { cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach, 21166206Sab196087 /* MSG_INTL(MSG_DESC_SUNW_LDMACH) */ 21176206Sab196087 ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH), 21186206Sab196087 /* MSG_INTL(MSG_HELP_SUNW_LDMACH) */ 21196206Sab196087 ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH), 21206206Sab196087 opt_ostyle, arg_sunw_ldmach }, 21216206Sab196087 21225088Sab196087 { NULL } 21235088Sab196087 }; 21245088Sab196087 21255088Sab196087 static elfedit_module_t module = { 21265088Sab196087 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 21275088Sab196087 /* MSG_INTL(MSG_MOD_DESC) */ 21285088Sab196087 ELFEDIT_I18NHDL(MSG_MOD_DESC), cmds, mod_i18nhdl_to_str }; 21295088Sab196087 21305088Sab196087 return (&module); 21315088Sab196087 } 2132