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 */ 1136225Sab196087 DYN_OPT_F_DYNNDX_ELT = 8, /* -dynndx: 1st plain arg is tag */ 1146225Sab196087 /* index, not name */ 1156225Sab196087 DYN_OPT_F_DYNNDX_VAL = 16, /* -dynndx ndx: Index is value to */ 1166225Sab196087 /* option rather than 1st plain */ 1176225Sab196087 /* arg. Used for dyn:posflag1 */ 1186225Sab196087 DYN_OPT_F_NEEDED = 32, /* -needed str: Locate DT_POSFLAG_1 */ 1196225Sab196087 /* relative to DT_NEEDED element */ 1206225Sab196087 DYN_OPT_F_OR = 64, /* -or: OR (|) values to dest */ 1216225Sab196087 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 */ 1436225Sab196087 const char *dyn_elt_str; /* Value string for */ 1446225Sab196087 /* DYN_OPT_F_DYNNDX_VAL */ 1456225Sab196087 /* 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 */ 2446225Sab196087 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) { 2455088Sab196087 argstate->optmask |= getopt_ret->gor_idmask; 2466225Sab196087 switch (getopt_ret->gor_idmask) { 2476225Sab196087 case DYN_OPT_F_DYNNDX_VAL: 2486225Sab196087 case DYN_OPT_F_NEEDED: 2496225Sab196087 argstate->dyn_elt_str = getopt_ret->gor_value; 2506225Sab196087 break; 2516225Sab196087 } 2526225Sab196087 } 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, 2666225Sab196087 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; 302*6635Sab196087 Word end_ndx, ndx, printed = 0; 3035088Sab196087 Dyn *dyn; 3045088Sab196087 int header_done = 0; 3055088Sab196087 Xword last_d_val; 3066225Sab196087 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 325*6635Sab196087 /* Starting index */ 3265088Sab196087 if (print_type == PRINT_DYN_T_NDX) { 3275088Sab196087 if (arg >= argstate->dyn.num) 3285088Sab196087 return; /* Out of range */ 3295088Sab196087 ndx = arg; 3305088Sab196087 } else { 3315088Sab196087 ndx = 0; 3325088Sab196087 } 3335088Sab196087 3346225Sab196087 /* 3356225Sab196087 * one_shot is used by positional elements (e.g. DT_POSFLAG_1) 3366225Sab196087 * to get the item following them to be shown even if they 3376225Sab196087 * are not of the desired tag type or the count of elements 3386225Sab196087 * to be displayed is only 1. 3396225Sab196087 */ 3406225Sab196087 one_shot = 0; 3416225Sab196087 3425088Sab196087 dyn = &argstate->dyn.data[ndx]; 343*6635Sab196087 344*6635Sab196087 /* 345*6635Sab196087 * Loop predicate explanation: 346*6635Sab196087 * Normally, we want to iterate from the starting index 347*6635Sab196087 * to the end. However, in the case of PRINT_DYN_T_NDX, we 348*6635Sab196087 * only want to display one item (ndx == arg) and then quit, 349*6635Sab196087 * with the exception that if we've been through the loop 350*6635Sab196087 * and encountered a one_shot situation, we want to continue 351*6635Sab196087 * iterating until the one-shot situation is cleared. 352*6635Sab196087 */ 353*6635Sab196087 for (; (ndx < argstate->dyn.num) && 354*6635Sab196087 ((print_type != PRINT_DYN_T_NDX) || ((ndx == arg) || one_shot)); 355*6635Sab196087 dyn++, ndx++) { 3565088Sab196087 union { 3576206Sab196087 Conv_inv_buf_t inv; 3585088Sab196087 Conv_dyn_flag_buf_t flag; 3595088Sab196087 Conv_dyn_flag1_buf_t flag1; 3605088Sab196087 Conv_dyn_posflag1_buf_t posflag1; 3615088Sab196087 Conv_dyn_feature1_buf_t feature1; 3625088Sab196087 } c_buf; 3635088Sab196087 const char *name; 3645088Sab196087 3656225Sab196087 if (one_shot) { 3666225Sab196087 one_shot = 0; 3676225Sab196087 } else { 3686225Sab196087 /* 3696225Sab196087 * If we are only displaying certain tag types and 3706225Sab196087 * this isn't one of those, move on to next element. 3716225Sab196087 */ 3726225Sab196087 switch (print_type) { 3736225Sab196087 case PRINT_DYN_T_TAG: 3746225Sab196087 if (dyn->d_tag != arg) 3756225Sab196087 continue; 3766225Sab196087 break; 3776225Sab196087 case PRINT_DYN_T_RUNPATH: 3786225Sab196087 if ((dyn->d_tag != DT_RPATH) && 3796225Sab196087 (dyn->d_tag != DT_RUNPATH)) 3806225Sab196087 continue; 3816225Sab196087 break; 3826225Sab196087 } 3835088Sab196087 } 3845088Sab196087 3855088Sab196087 /* 3865088Sab196087 * Print the information numerically, and if possible 3875088Sab196087 * as a string. 3885088Sab196087 */ 3895088Sab196087 name = NULL; 3905088Sab196087 switch (dyn->d_tag) { 3915088Sab196087 case DT_NULL: 3925088Sab196087 if (!((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) && 3935088Sab196087 (print_type == PRINT_DYN_T_ALL) && 3945088Sab196087 (dyn->d_un.d_val == 0))) 3955088Sab196087 break; 3965088Sab196087 end_ndx = ndx; 3975088Sab196087 /* 3985088Sab196087 * Special case: DT_NULLs can come in groups 3995088Sab196087 * that we prefer to reduce to a single line. 4005088Sab196087 */ 4015088Sab196087 while ((end_ndx < (argstate->dyn.num - 1)) && 4025088Sab196087 ((dyn + 1)->d_tag == DT_NULL) && 4035088Sab196087 ((dyn + 1)->d_un.d_val == 0)) { 4045088Sab196087 dyn++; 4055088Sab196087 end_ndx++; 4065088Sab196087 } 4075088Sab196087 if (header_done == 0) { 4085088Sab196087 header_done = 1; 4095088Sab196087 Elf_dyn_title(0); 4105088Sab196087 } 4115088Sab196087 Elf_dyn_null_entry(0, dyn, ndx, end_ndx); 4125088Sab196087 ndx = end_ndx; 4135088Sab196087 printed = 1; 4145088Sab196087 last_d_val = dyn->d_un.d_val; 4155088Sab196087 continue; 4165088Sab196087 4175088Sab196087 /* 4185088Sab196087 * Print the information numerically, and if possible 4195088Sab196087 * as a string. 4205088Sab196087 */ 4215088Sab196087 case DT_NEEDED: 4225088Sab196087 case DT_SONAME: 4235088Sab196087 case DT_FILTER: 4245088Sab196087 case DT_AUXILIARY: 4255088Sab196087 case DT_CONFIG: 4265088Sab196087 case DT_RPATH: 4275088Sab196087 case DT_RUNPATH: 4285088Sab196087 case DT_USED: 4295088Sab196087 case DT_DEPAUDIT: 4305088Sab196087 case DT_AUDIT: 4315088Sab196087 case DT_SUNW_AUXILIARY: 4325088Sab196087 case DT_SUNW_FILTER: 4335088Sab196087 name = elfedit_offset_to_str(argstate->strsec, 4345088Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 4355088Sab196087 break; 4365088Sab196087 4375088Sab196087 case DT_FLAGS: 4385088Sab196087 name = conv_dyn_flag(dyn->d_un.d_val, 4395088Sab196087 flags_fmt_flags, &c_buf.flag); 4405088Sab196087 break; 4415088Sab196087 case DT_FLAGS_1: 4425088Sab196087 name = conv_dyn_flag1(dyn->d_un.d_val, 4435088Sab196087 flags_fmt_flags, &c_buf.flag1); 4445088Sab196087 break; 4455088Sab196087 case DT_POSFLAG_1: 4466225Sab196087 /* 4476225Sab196087 * If this is dyn:posflag1, and the print_type 4486225Sab196087 * is PRINT_DYN_T_TAG, and the -needed option is 4496225Sab196087 * used, then don't show any DT_POSFLAG_1 elements 4506225Sab196087 * that are not followed by a DT_NEEDED element 4516225Sab196087 * that matches the -needed string. 4526225Sab196087 */ 4536225Sab196087 if ((cmd == DYN_CMD_T_POSFLAG1) && 4546225Sab196087 (print_type == PRINT_DYN_T_TAG) && 4556225Sab196087 ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) && 4566225Sab196087 ((ndx + 1) < argstate->dyn.num)) { 4576225Sab196087 Dyn *dyn1 = &argstate->dyn.data[ndx + 1]; 4586225Sab196087 4596225Sab196087 if (dyn1->d_tag != DT_NEEDED) 4606225Sab196087 continue; 4616225Sab196087 name = elfedit_offset_to_str(argstate->strsec, 4626225Sab196087 dyn1->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 4636225Sab196087 if (strncmp(name, argstate->dyn_elt_str, 4646225Sab196087 strlen(argstate->dyn_elt_str)) != 0) 4656225Sab196087 continue; 4666225Sab196087 } 4676225Sab196087 4685088Sab196087 name = conv_dyn_posflag1(dyn->d_un.d_val, 4695088Sab196087 flags_fmt_flags, &c_buf.posflag1); 4706225Sab196087 /* 4716225Sab196087 * DT_POSFLAG_1 is a positional element that affects 4726225Sab196087 * the following item. If using the default output 4736225Sab196087 * style, then show the following item as well. 4746225Sab196087 */ 4756225Sab196087 one_shot = (outstyle == ELFEDIT_OUTSTYLE_DEFAULT); 4765088Sab196087 break; 4775088Sab196087 case DT_FEATURE_1: 4785088Sab196087 name = conv_dyn_feature1(dyn->d_un.d_val, 4795088Sab196087 flags_fmt_flags, &c_buf.feature1); 4805088Sab196087 break; 4815088Sab196087 case DT_DEPRECATED_SPARC_REGISTER: 4825088Sab196087 name = MSG_INTL(MSG_STR_DEPRECATED); 4835088Sab196087 break; 4846206Sab196087 case DT_SUNW_LDMACH: 4856206Sab196087 name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0, 4866206Sab196087 &c_buf.inv); 4876206Sab196087 break; 4885088Sab196087 } 4895088Sab196087 4905088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 4915088Sab196087 if (header_done == 0) { 4925088Sab196087 header_done = 1; 4935088Sab196087 Elf_dyn_title(0); 4945088Sab196087 } 4955088Sab196087 if (name == NULL) 4965088Sab196087 name = MSG_ORIG(MSG_STR_EMPTY); 4975088Sab196087 Elf_dyn_entry(0, dyn, ndx, name, 4985088Sab196087 argstate->obj_state->os_ehdr->e_machine); 4995088Sab196087 } else { 5005088Sab196087 /* 5015088Sab196087 * In simple or numeric mode under a print type 5025088Sab196087 * that is based on tag type rather than on index, 5035088Sab196087 * quietly: If we've already printed this value, 5045088Sab196087 * don't print it again. A common example of this 5055088Sab196087 * is PRINT_DYN_T_RUNPATH when both DT_RPATH and 5065088Sab196087 * DT_RUNPATH are present with the same value. 5075088Sab196087 */ 5085088Sab196087 switch (print_type) { 5095088Sab196087 case PRINT_DYN_T_TAG: 5106225Sab196087 /* 5116225Sab196087 * Positional flags don't count, because 5126225Sab196087 * each one affects a different item. So don't 5136225Sab196087 * skip those. 5146225Sab196087 */ 5156225Sab196087 if (dyn->d_tag != DT_POSFLAG_1) 5166225Sab196087 continue; 5176225Sab196087 break; 5186225Sab196087 5195088Sab196087 case PRINT_DYN_T_RUNPATH: 5205088Sab196087 if (printed && (last_d_val == dyn->d_un.d_val)) 5215088Sab196087 continue; 5226225Sab196087 break; 5235088Sab196087 } 5245088Sab196087 5255088Sab196087 if ((name != NULL) && 5265088Sab196087 (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) { 5275088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name); 5285088Sab196087 } else { 5295088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), 5305088Sab196087 dyn->d_un.d_val); 5315088Sab196087 } 5325088Sab196087 } 5335088Sab196087 printed = 1; 5345088Sab196087 last_d_val = dyn->d_un.d_val; 5355088Sab196087 } 5365088Sab196087 5375088Sab196087 /* 5385088Sab196087 * If nothing was output under the print types that are 5395088Sab196087 * based on tag type, issue an error saying it doesn't exist. 5405088Sab196087 */ 5415088Sab196087 if (!printed) { 5425088Sab196087 if (print_type == PRINT_DYN_T_TAG) { 5435088Sab196087 Conv_inv_buf_t inv_buf; 5445088Sab196087 5455088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 5465088Sab196087 MSG_INTL(MSG_ERR_NODYNELT), 5475088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 5485088Sab196087 argstate->dyn.sec->sec_name, conv_dyn_tag(arg, 5495088Sab196087 argstate->obj_state->os_ehdr->e_machine, 5505088Sab196087 0, &inv_buf)); 5515088Sab196087 } 5525088Sab196087 5535088Sab196087 if (print_type == PRINT_DYN_T_RUNPATH) 5545088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 5555088Sab196087 MSG_INTL(MSG_ERR_NORUNPATH), 5565088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 5575088Sab196087 argstate->dyn.sec->sec_name); 5585088Sab196087 } 5595088Sab196087 } 5605088Sab196087 5615088Sab196087 5625088Sab196087 /* 5636225Sab196087 * Determine the index(s) of the dynamic element(s) to be displayed and/or 5646225Sab196087 * manipulated. 5655088Sab196087 * 5665088Sab196087 * entry: 5675088Sab196087 * argstate - Argument state block 5686225Sab196087 * arg - If the command being called accepts a first plain argument 5696225Sab196087 * named 'elt' which is used to specify the dynamic element, 5706225Sab196087 * arg is the value of argv[0] for that command. If the 5716225Sab196087 * command does not accept an 'elt' argument and instead 5726225Sab196087 * implicitly assumes a tag type, arg is the constant string 5736225Sab196087 * for that type (e.g. "DT_POSFLAG_1"). 5745088Sab196087 * print_request - True if the command is to print the current 5755088Sab196087 * value(s) and return without changing anything. 5765088Sab196087 * print_type - Address of variable containing PRINT_DYN_T_ 5775088Sab196087 * code specifying how the elements will be displayed. 5785088Sab196087 * 5795088Sab196087 * exit: 5806225Sab196087 * If print_request is False: This routine always returns the index 5816225Sab196087 * of a single dynamic element. *print_type is set to PRINT_DYN_T_NDX. 5826225Sab196087 * The 'elt' argument as well as any modifier options (-dynndx, -needed) 5836225Sab196087 * are examined to determine this index. If there are no modifier options, 5846225Sab196087 * the dynamic section contains no element of the desired type, and there 5856225Sab196087 * is an extra DT_NULL element in the section, then a new element of 5866225Sab196087 * the desired type is created and its index returned. Otherwise an 5876225Sab196087 * error is issued. 5885088Sab196087 * 5896225Sab196087 * If print_request is True: If a modifier (-dynndx, -needed) was used, 5906225Sab196087 * *print_type is set to PRINT_DYN_T_NDX and the index of the 5916225Sab196087 * corresponding single dynamic element is returned. If no modifier 5926225Sab196087 * was used, *print_type is set to PRINT_DYN_T_TAG, and the tag 5936225Sab196087 * type code is returned. 5945088Sab196087 */ 5955088Sab196087 static Word 5966225Sab196087 arg_to_index(ARGSTATE *argstate, const char *arg, 5975088Sab196087 int print_request, PRINT_DYN_T *print_type) 5985088Sab196087 { 5995088Sab196087 Word ndx, dt_value; 6006225Sab196087 Dyn *dyn; 6015088Sab196087 6025088Sab196087 6035088Sab196087 /* Assume we are returning an index, alter as needed below */ 6045088Sab196087 *print_type = PRINT_DYN_T_NDX; 6055088Sab196087 6066225Sab196087 /* 6076225Sab196087 * All the commands that accept the DYN_OPT_F_DYNNDX_ELT form 6086225Sab196087 * of -dynndx require a plain argument named 'elt' as their first 6096225Sab196087 * argument. -dynndx is a modifier that means that 'elt' is a 6106225Sab196087 * simple numeric section index. Routines that accept this form 6116225Sab196087 * of -dynndx are willing to handle any tag type, so all we need 6126225Sab196087 * to check is that the value is in range. 6136225Sab196087 */ 6146225Sab196087 if ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0) 6156225Sab196087 return ((Word) elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_ELT), 6166225Sab196087 0, argstate->dyn.num - 1, NULL)); 6176225Sab196087 6186225Sab196087 /* arg is a DT_ tag type, not a numeric index */ 6196225Sab196087 dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT); 6205088Sab196087 6216225Sab196087 /* 6226225Sab196087 * Commands that accept the DYN_OPT_F_DYNNDX_VAL form of 6236225Sab196087 * dynndx do not accept the 'elt' argument. The index is a 6246225Sab196087 * value that follows the option, and was saved in argstate by 6256225Sab196087 * process_args(). Routines that accept this form of -dynndx 6266225Sab196087 * require the specified element to have a specific tag type, 6276225Sab196087 * so we test for this as well as for the index being in range. 6286225Sab196087 */ 6296225Sab196087 if ((argstate->optmask & DYN_OPT_F_DYNNDX_VAL) != 0) { 6306225Sab196087 ndx = ((Word) elfedit_atoui_range(argstate->dyn_elt_str, 6316225Sab196087 MSG_ORIG(MSG_STR_INDEX), 0, argstate->dyn.num - 1, NULL)); 6326225Sab196087 if (argstate->dyn.data[ndx].d_tag != dt_value) { 6336225Sab196087 Half mach = argstate->obj_state->os_ehdr->e_machine; 6346225Sab196087 Conv_inv_buf_t is, want; 6356225Sab196087 6366225Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_WRONGTAG), 6376225Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 6386225Sab196087 argstate->dyn.sec->sec_name, ndx, 6396225Sab196087 conv_dyn_tag(dt_value, mach, 0, &want), 6406225Sab196087 conv_dyn_tag(argstate->dyn.data[ndx].d_tag, mach, 6416225Sab196087 0, &is)); 6426225Sab196087 } 6436225Sab196087 return (ndx); 6446225Sab196087 } 6455088Sab196087 6465088Sab196087 /* 6475088Sab196087 * If this is a printing request, then we let print_dyn() show 6485088Sab196087 * all the items with this tag type. 6495088Sab196087 */ 6505088Sab196087 if (print_request) { 6515088Sab196087 *print_type = PRINT_DYN_T_TAG; 6525088Sab196087 return (dt_value); 6535088Sab196087 } 6545088Sab196087 6556225Sab196087 /* 6566225Sab196087 * Commands that accept -needed are looking for the dt_value element 6576225Sab196087 * (usually DT_POSFLAG_1) that immediately preceeds the DT_NEEDED 6586225Sab196087 * element with the string given by argstate->dyn_elt_str. 6596225Sab196087 */ 6606225Sab196087 if ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) { 6616225Sab196087 Word retndx = argstate->dyn.num; /* Out of range value */ 6626225Sab196087 const char *name; 6636225Sab196087 size_t len; 6646225Sab196087 6656225Sab196087 len = strlen(argstate->dyn_elt_str); 6666225Sab196087 for (ndx = 0, dyn = argstate->dyn.data; 6676225Sab196087 ndx < argstate->dyn.num; dyn++, ndx++) { 6686225Sab196087 /* 6696225Sab196087 * If the immediately preceeding item has the 6706225Sab196087 * tag type we're looking for, and the current item 6716225Sab196087 * is a DT_NEEDED with a string that matches, 6726225Sab196087 * then the preceeding item is the one we want. 6736225Sab196087 */ 6746225Sab196087 if ((dyn->d_tag == DT_NEEDED) && 6756225Sab196087 (ndx > 0) && (retndx == (ndx - 1))) { 6766225Sab196087 name = elfedit_offset_to_str(argstate->strsec, 6776225Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 6786225Sab196087 6796225Sab196087 if (strncmp(name, 6806225Sab196087 argstate->dyn_elt_str, len) == 0) 6816225Sab196087 return (retndx); 6826225Sab196087 continue; 6836225Sab196087 } 6846225Sab196087 6856225Sab196087 /* 6866225Sab196087 * If the current item has the tag type we're 6876225Sab196087 * looking for, make it our current candidate. 6886225Sab196087 * If the next item is a DT_NEEDED with the right 6896225Sab196087 * string value, we'll use it then. 6906225Sab196087 */ 6916225Sab196087 if (dyn->d_tag == dt_value) 6926225Sab196087 retndx = ndx; 6936225Sab196087 } 6946225Sab196087 6956225Sab196087 /* If we get here, no matching DT_NEEDED was found */ 6966225Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEDNOMATCH), 6976225Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 6986225Sab196087 argstate->dyn.sec->sec_name, argstate->dyn_elt_str); 6996225Sab196087 } 7006225Sab196087 7015088Sab196087 /* Locate the first entry with the given tag type */ 7025088Sab196087 for (ndx = 0; ndx < argstate->dyn.num; ndx++) { 7035088Sab196087 if (argstate->dyn.data[ndx].d_tag == dt_value) { 7045088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 7055088Sab196087 MSG_INTL(MSG_DEBUG_DT2NDX), 7065088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 7075088Sab196087 argstate->dyn.sec->sec_name, EC_WORD(ndx), arg); 7085088Sab196087 return (ndx); 7095088Sab196087 } 7105088Sab196087 } 7115088Sab196087 7125088Sab196087 /* Not found. Can we create one? */ 7135088Sab196087 if (argstate->dyn.num_null_ndx > 1) 7145088Sab196087 return (convert_dt_null(argstate, dt_value, 0)); 7155088Sab196087 7165088Sab196087 /* No room to create one, so we're out of options and must fail */ 7175088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT), 7185088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 7195088Sab196087 argstate->dyn.sec->sec_name, arg); 7205088Sab196087 7215088Sab196087 /*NOTREACHED*/ 7225088Sab196087 return (0); /* For lint */ 7235088Sab196087 } 7245088Sab196087 7255088Sab196087 7265088Sab196087 /* 7275088Sab196087 * Called by cmd_body() for dyn:value. Implements the core functionality 7285088Sab196087 * for that command. 7295088Sab196087 * 7305088Sab196087 * This routine expects that both the index and value arguments are 7315088Sab196087 * present. 7325088Sab196087 */ 7335088Sab196087 static elfedit_cmdret_t 7345088Sab196087 cmd_body_value(ARGSTATE *argstate, Word *ret_ndx) 7355088Sab196087 { 7365088Sab196087 elfedit_section_t *dynsec = argstate->dyn.sec; 7375088Sab196087 elfedit_section_t *strsec = argstate->strsec; 7385088Sab196087 elfedit_dyn_elt_t strpad_elt; 7395088Sab196087 Word i; 7405088Sab196087 Dyn *dyn = argstate->dyn.data; 7415088Sab196087 Word numdyn = argstate->dyn.num; 7426225Sab196087 int minus_add, minus_s, minus_dynndx; 7435088Sab196087 Word arg1, tmp_val; 7445088Sab196087 Xword arg2; 7455088Sab196087 int arg2_known = 1; 7465088Sab196087 7476225Sab196087 minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0); 7486225Sab196087 minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0); 7496225Sab196087 minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0); 7505088Sab196087 7515088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 7525088Sab196087 7535088Sab196087 /* 7545088Sab196087 * The first argument is an index if -dynndx is used, and is a 7555088Sab196087 * tag value otherwise. 7565088Sab196087 */ 7575088Sab196087 arg1 = minus_dynndx ? 7585088Sab196087 elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT), 7595088Sab196087 0, numdyn - 1, NULL) : 7605088Sab196087 elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT); 7615088Sab196087 7625088Sab196087 if (minus_s) { 7635088Sab196087 /* 7645088Sab196087 * Don't allow the user to specify -s when manipulating a 7655088Sab196087 * DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to 7665088Sab196087 * manage the extra space used for strings, this would break 7675088Sab196087 * our ability to add the string. 7685088Sab196087 */ 7695088Sab196087 if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) || 7705088Sab196087 (minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD))) 7715088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 7725088Sab196087 MSG_INTL(MSG_ERR_STRPADSTRVAL), 7735088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 7745088Sab196087 7755088Sab196087 /* Locate DT_SUNW_STRPAD element if present */ 7765088Sab196087 strpad_elt.dn_dyn.d_un.d_val = 0; 7775088Sab196087 (void) elfedit_dynstr_getpad(argstate->dyn.sec, &strpad_elt); 7785088Sab196087 7795088Sab196087 /* 7805088Sab196087 * Look up the string: If the user specified the -dynndx 7815088Sab196087 * -option, then we will insert it if possible, and 7825088Sab196087 * fail with an error if not. However, if they did not 7835088Sab196087 * specify -dynndx, we want to look up the string if it is 7845088Sab196087 * already there, but defer the insertion. The reason for 7855088Sab196087 * this is that we may have to grab an unused DT_NULL element 7865088Sab196087 * below, and if there are none available, we won't want 7875088Sab196087 * to have modified the string table. 7885088Sab196087 * 7895088Sab196087 * This isn't a problem, because if the string isn't 7905088Sab196087 * in the string table, it can't be used by a dynamic element. 7915088Sab196087 * Hence, we don't need to insert it to know that there is 7925088Sab196087 * no match. 7935088Sab196087 */ 7945088Sab196087 if (minus_dynndx == 0) { 7955088Sab196087 if (elfedit_sec_findstr(strsec, 7965088Sab196087 strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1], 7975088Sab196087 &tmp_val) == 0) { 7985088Sab196087 arg2_known = 0; 7995088Sab196087 } else { 8005088Sab196087 arg2 = tmp_val; 8015088Sab196087 } 8025088Sab196087 } else { 8035088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 8045088Sab196087 &strpad_elt, argstate->argv[1]); 8055088Sab196087 } 8065088Sab196087 } else { /* Argument 2 is an integer */ 8075088Sab196087 arg2 = elfedit_atoui(argstate->argv[1], NULL); 8085088Sab196087 } 8095088Sab196087 8105088Sab196087 8115088Sab196087 if (!minus_dynndx && !(minus_add && !arg2_known)) { 8125088Sab196087 /* 8135088Sab196087 * Search the dynamic section and see if an item with the 8145088Sab196087 * specified tag value already exists. We can reduce this 8155088Sab196087 * to a simple update of an existing value if -add is not 8165088Sab196087 * specified or the existing d_un value matches the new one. 8175088Sab196087 * 8185088Sab196087 * In either of these cases, we will change arg1 to be the 8195088Sab196087 * index, and set minus_dynndx, causing the simple update to 8205088Sab196087 * happen immediately below. 8215088Sab196087 */ 8225088Sab196087 for (i = 0; i < numdyn; i++) { 8235088Sab196087 if ((dyn[i].d_tag == arg1) && 8245088Sab196087 (!minus_add || (dyn[i].d_un.d_val == arg2))) { 8255088Sab196087 arg1 = i; 8265088Sab196087 minus_dynndx = 1; 8275088Sab196087 break; 8285088Sab196087 } 8295088Sab196087 } 8305088Sab196087 } 8315088Sab196087 8325088Sab196087 /* 8335088Sab196087 * If -dynndx is used, then this is a relatively simple 8345088Sab196087 * operation, as we simply write over the specified index. 8355088Sab196087 */ 8365088Sab196087 if (minus_dynndx) { 8375088Sab196087 /* 8385088Sab196087 * If we held back from inserting a new string into 8395088Sab196087 * the dynstr above, we insert it now, because we 8405088Sab196087 * have a slot in the dynamic section, and we need 8415088Sab196087 * the string offset ot finish. 8425088Sab196087 */ 8435088Sab196087 if (!arg2_known) 8445088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 8455088Sab196087 &strpad_elt, argstate->argv[1]); 8465088Sab196087 8475088Sab196087 *ret_ndx = arg1; 8485088Sab196087 if (dyn[arg1].d_un.d_val == arg2) { 8495088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8505088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), 8515088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8525088Sab196087 EC_WORD(arg1), EC_XWORD(arg2)); 8535088Sab196087 return (ELFEDIT_CMDRET_NONE); 8545088Sab196087 } else { 8555088Sab196087 /* Warn if setting DT_NULL value to non-zero */ 8565088Sab196087 if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0)) 8575088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8585088Sab196087 MSG_INTL(MSG_DEBUG_DTNULLVALUE), 8595088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8605088Sab196087 EC_WORD(arg1), EC_XWORD(arg2)); 8615088Sab196087 8625088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8635088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 8645088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8655088Sab196087 EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val), 8665088Sab196087 EC_XWORD(arg2)); 8675088Sab196087 dyn[arg1].d_un.d_val = arg2; 8685088Sab196087 return (ELFEDIT_CMDRET_MOD); 8695088Sab196087 } 8705088Sab196087 } 8715088Sab196087 8725088Sab196087 /* 8735088Sab196087 * We need a new slot in the dynamic section. If we can't have 8745088Sab196087 * one, then we fail. 8755088Sab196087 */ 8765088Sab196087 if (argstate->dyn.num_null_ndx <= 1) 8775088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 8785088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 8795088Sab196087 8805088Sab196087 /* 8815088Sab196087 * If we still need to insert a new string into the dynstr, 8825088Sab196087 * then it is safe now, because if we succeed, we know that 8835088Sab196087 * there is an available slot to receive it. If we fail, we 8845088Sab196087 * haven't claimed the extra slot yet, and it will be unharmed. 8855088Sab196087 */ 8865088Sab196087 if (!arg2_known) 8875088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 8885088Sab196087 &strpad_elt, argstate->argv[1]); 8895088Sab196087 8905088Sab196087 /* Use an extra DT_NULL slot and enter the new element */ 8915088Sab196087 *ret_ndx = convert_dt_null(argstate, arg1, arg2); 8925088Sab196087 return (ELFEDIT_CMDRET_MOD); 8935088Sab196087 } 8945088Sab196087 8955088Sab196087 8965088Sab196087 8975088Sab196087 /* 8985088Sab196087 * Called by cmd_body() for dyn:runpath. Implements the core functionality 8995088Sab196087 * for that command. 9005088Sab196087 * 9015088Sab196087 * History Lesson And Strategy: 9025088Sab196087 * 9035088Sab196087 * This routine handles both DT_RPATH and DT_RUNPATH entries, altering 9045088Sab196087 * either or both if they are present. 9055088Sab196087 * 9065088Sab196087 * The original SYSV ABI only had DT_RPATH, and the runtime loader used 9075088Sab196087 * it to search for things in the following order: 9085088Sab196087 * 9095088Sab196087 * DT_RPATH, LD_LIBRARY_PATH, defaults 9105088Sab196087 * 9115088Sab196087 * Solaris did not follow this rule, an extremely rare deviation from 9125088Sab196087 * the ABI. Environment variables should supercede everything else, 9135088Sab196087 * otherwise they are not very useful. This decision was made at the 9145088Sab196087 * very beginning of the SunOS 5.x development, so we have always 9155088Sab196087 * deviated from the ABI and and instead search in the order 9165088Sab196087 * 9175088Sab196087 * LD_LIBRARY_PATH, DT_RPATH, defaults 9185088Sab196087 * 9195088Sab196087 * Other Unix variants initially followed the ABI, but in recent years 9205088Sab196087 * have come to agree with the early Solaris folks that it was a mistake. 9215088Sab196087 * Hence, DT_RUNPATH was invented, with the search order: 9225088Sab196087 * 9235088Sab196087 * LD_LIBRARY_PATH, DT_RUNPATH, defaults 9245088Sab196087 * 9255088Sab196087 * So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both 9265088Sab196087 * are present (which does happen), we set them both to the new 9275088Sab196087 * value. If either one is present, we set that one. If neither is 9285088Sab196087 * present, and we have a spare DT_NULL slot, we create a DT_RUNPATH, but 9295088Sab196087 * not a DT_RPATH, to conserve available slots for other uses. 9305088Sab196087 */ 9315088Sab196087 static elfedit_cmdret_t 9325088Sab196087 cmd_body_runpath(ARGSTATE *argstate) 9335088Sab196087 { 9345088Sab196087 elfedit_section_t *dynsec = argstate->dyn.sec; 9355088Sab196087 elfedit_section_t *strsec = argstate->strsec; 9365088Sab196087 elfedit_dyn_elt_t rpath_elt; 9375088Sab196087 elfedit_dyn_elt_t runpath_elt; 9385088Sab196087 elfedit_dyn_elt_t strpad_elt; 9395088Sab196087 Word i; 9405088Sab196087 Dyn *dyn = argstate->dyn.data; 9415088Sab196087 Word numdyn = argstate->dyn.num; 9425088Sab196087 9435088Sab196087 /* Go through the tags and gather what we need */ 9445088Sab196087 elfedit_dyn_elt_init(&rpath_elt); 9455088Sab196087 elfedit_dyn_elt_init(&runpath_elt); 9465088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 9475088Sab196087 for (i = 0; i < numdyn; i++) { 9485088Sab196087 switch (dyn[i].d_tag) { 9495088Sab196087 case DT_RPATH: 9505088Sab196087 elfedit_dyn_elt_save(&rpath_elt, i, &dyn[i]); 9515088Sab196087 break; 9525088Sab196087 9535088Sab196087 case DT_RUNPATH: 9545088Sab196087 elfedit_dyn_elt_save(&runpath_elt, i, &dyn[i]); 9555088Sab196087 break; 9565088Sab196087 9575088Sab196087 case DT_SUNW_STRPAD: 9585088Sab196087 elfedit_dyn_elt_save(&strpad_elt, i, &dyn[i]); 9595088Sab196087 break; 9605088Sab196087 } 9615088Sab196087 } 9625088Sab196087 9635088Sab196087 /* Do we have an available dynamic section entry to use? */ 9645088Sab196087 if (rpath_elt.dn_seen || runpath_elt.dn_seen) { 9655088Sab196087 /* 9665088Sab196087 * We have seen a DT_RPATH, or a DT_RUNPATH, or both. 9675088Sab196087 * If all of these have the same string as the desired 9685088Sab196087 * new value, then we don't need to alter anything and can 9695088Sab196087 * simply return. Otherwise, we'll modify them all to have 9705088Sab196087 * the new string (below). 9715088Sab196087 */ 9725088Sab196087 if ((!rpath_elt.dn_seen || 9735088Sab196087 (strcmp(elfedit_dyn_offset_to_str(strsec, &rpath_elt), 9745088Sab196087 argstate->argv[0]) == 0)) && 9755088Sab196087 (!runpath_elt.dn_seen || 9765088Sab196087 (strcmp(elfedit_dyn_offset_to_str(strsec, &runpath_elt), 9775088Sab196087 argstate->argv[0]) == 0))) { 9785088Sab196087 if (rpath_elt.dn_seen) 9795088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 9805088Sab196087 MSG_INTL(MSG_DEBUG_OLDRPATHOK), 9815088Sab196087 EC_WORD(dynsec->sec_shndx), 9825088Sab196087 dynsec->sec_name, EC_WORD(rpath_elt.dn_ndx), 9835088Sab196087 elfedit_atoconst_value_to_str( 9845088Sab196087 ELFEDIT_CONST_DT, DT_RPATH, 1)); 9855088Sab196087 if (runpath_elt.dn_seen) 9865088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 9875088Sab196087 MSG_INTL(MSG_DEBUG_OLDRPATHOK), 9885088Sab196087 EC_WORD(dynsec->sec_shndx), 9895088Sab196087 dynsec->sec_name, 9905088Sab196087 EC_WORD(runpath_elt.dn_ndx), 9915088Sab196087 elfedit_atoconst_value_to_str( 9925088Sab196087 ELFEDIT_CONST_DT, DT_RUNPATH, 1)); 9935088Sab196087 return (ELFEDIT_CMDRET_NONE); 9945088Sab196087 } 9955088Sab196087 } else if (argstate->dyn.num_null_ndx <= 1) { 9965088Sab196087 /* 9975088Sab196087 * There is no DT_RPATH or DT_RUNPATH in the dynamic array, 9985088Sab196087 * and there are no extra DT_NULL entries that we can 9995088Sab196087 * convert into one. We cannot proceed. 10005088Sab196087 */ 10015088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 10025088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 10035088Sab196087 } 10045088Sab196087 10055088Sab196087 /* Does the string exist in the table already, or can we add it? */ 10065088Sab196087 rpath_elt.dn_dyn.d_un.d_val = runpath_elt.dn_dyn.d_un.d_val = 10075088Sab196087 elfedit_dynstr_insert(dynsec, strsec, &strpad_elt, 10085088Sab196087 argstate->argv[0]); 10095088Sab196087 10105088Sab196087 /* Update DT_RPATH entry if present */ 10115088Sab196087 if (rpath_elt.dn_seen) { 10125088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_PREVRPATH), 10135088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 10145088Sab196087 EC_WORD(rpath_elt.dn_ndx), 10155088Sab196087 elfedit_atoconst_value_to_str( 10165088Sab196087 ELFEDIT_CONST_DT, DT_RPATH, 1), 10175088Sab196087 elfedit_dyn_offset_to_str(strsec, &rpath_elt)); 10185088Sab196087 dyn[rpath_elt.dn_ndx] = rpath_elt.dn_dyn; 10195088Sab196087 } 10205088Sab196087 10215088Sab196087 /* 10225088Sab196087 * Update the DT_RUNPATH entry in the dynamic section, if present. 10235088Sab196087 * If one is not present, and there is also no DT_RPATH, then 10245088Sab196087 * we use a spare DT_NULL entry to create a new DT_RUNPATH. 10255088Sab196087 */ 10265088Sab196087 if (runpath_elt.dn_seen || !rpath_elt.dn_seen) { 10275088Sab196087 if (runpath_elt.dn_seen) { 10285088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 10295088Sab196087 MSG_INTL(MSG_DEBUG_PREVRPATH), 10305088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 10315088Sab196087 EC_WORD(runpath_elt.dn_ndx), 10325088Sab196087 elfedit_atoconst_value_to_str( 10335088Sab196087 ELFEDIT_CONST_DT, DT_RUNPATH, 1), 10345088Sab196087 elfedit_dyn_offset_to_str(strsec, &runpath_elt)); 10355088Sab196087 dyn[runpath_elt.dn_ndx] = runpath_elt.dn_dyn; 10365088Sab196087 } else { /* Using a spare DT_NULL entry */ 10375088Sab196087 (void) convert_dt_null(argstate, DT_RUNPATH, 10385088Sab196087 runpath_elt.dn_dyn.d_un.d_val); 10395088Sab196087 } 10405088Sab196087 } 10415088Sab196087 10425088Sab196087 return (ELFEDIT_CMDRET_MOD); 10435088Sab196087 } 10445088Sab196087 10455088Sab196087 10465088Sab196087 10475088Sab196087 /* 10485088Sab196087 * Argument processing for the bitmask commands. Convert the arguments 10495088Sab196087 * to integer form, apply -and/-cmp/-or, and return the resulting value. 10505088Sab196087 * 10515088Sab196087 * entry: 10525088Sab196087 * argstate - Argument state block 10535088Sab196087 * orig - Value of original bitmask 10545088Sab196087 * const_type - ELFEDIT_CONST_* value for type of constants 10555088Sab196087 */ 10565088Sab196087 static Word 10575088Sab196087 flag_bitop(ARGSTATE *argstate, Word orig, elfedit_const_t const_type) 10585088Sab196087 { 10595088Sab196087 Word flags = 0; 10605088Sab196087 int i; 10615088Sab196087 10625088Sab196087 /* Collect the arguments */ 10635088Sab196087 for (i = 0; i < argstate->argc; i++) 10645088Sab196087 flags |= (Word) elfedit_atoconst(argstate->argv[i], const_type); 10655088Sab196087 10665088Sab196087 /* Complement the value? */ 10675088Sab196087 if (argstate->optmask & DYN_OPT_F_CMP) 10685088Sab196087 flags = ~flags; 10695088Sab196087 10705088Sab196087 /* Perform any requested bit operations */ 10715088Sab196087 if (argstate->optmask & DYN_OPT_F_AND) 10725088Sab196087 flags &= orig; 10735088Sab196087 else if (argstate->optmask & DYN_OPT_F_OR) 10745088Sab196087 flags |= orig; 10755088Sab196087 10765088Sab196087 return (flags); 10775088Sab196087 } 10785088Sab196087 10795088Sab196087 10805088Sab196087 10815088Sab196087 /* 10825088Sab196087 * Common body for the dyn: module commands. These commands 10835088Sab196087 * share a large amount of common behavior, so it is convenient 10845088Sab196087 * to centralize things and use the cmd argument to handle the 10855088Sab196087 * small differences. 10865088Sab196087 * 10875088Sab196087 * entry: 10885088Sab196087 * cmd - One of the DYN_CMD_T_* constants listed above, specifying 10895088Sab196087 * which command to implement. 10905088Sab196087 * obj_state, argc, argv - Standard command arguments 10915088Sab196087 */ 10925088Sab196087 static elfedit_cmdret_t 10935088Sab196087 cmd_body(DYN_CMD_T cmd, elfedit_obj_state_t *obj_state, 10945088Sab196087 int argc, const char *argv[]) 10955088Sab196087 { 10965088Sab196087 ARGSTATE argstate; 10975088Sab196087 Dyn *dyn; 10985088Sab196087 const char *dyn_name; 10995088Sab196087 Word dyn_ndx, dyn_num, null_ndx; 11005088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 11015088Sab196087 PRINT_DYN_T print_type = PRINT_DYN_T_ALL; 11025088Sab196087 Word ndx; 11035088Sab196087 int print_only = 0; 11045088Sab196087 int do_autoprint = 1; 11055088Sab196087 11065088Sab196087 /* Process the optional arguments */ 11075088Sab196087 process_args(obj_state, argc, argv, &argstate); 11085088Sab196087 11095088Sab196087 dyn = argstate.dyn.data; 11105088Sab196087 dyn_num = argstate.dyn.num; 11115088Sab196087 dyn_name = argstate.dyn.sec->sec_name; 11125088Sab196087 dyn_ndx = argstate.dyn.sec->sec_shndx; 11135088Sab196087 11145088Sab196087 /* Check number of arguments, gather information */ 11155088Sab196087 switch (cmd) { 11165088Sab196087 case DYN_CMD_T_DUMP: 11175088Sab196087 /* dyn:dump can accept an optional index argument */ 11185088Sab196087 if (argstate.argc > 1) 11195088Sab196087 elfedit_command_usage(); 11205088Sab196087 print_only = 1; 11215088Sab196087 if (argstate.argc == 1) 11225088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11236225Sab196087 print_only, &print_type); 11245088Sab196087 break; 11255088Sab196087 11265088Sab196087 case DYN_CMD_T_TAG: 11275088Sab196087 print_only = (argstate.argc != 2); 11285088Sab196087 if (argstate.argc > 0) { 11295088Sab196087 if (argstate.argc > 2) 11305088Sab196087 elfedit_command_usage(); 11315088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11326225Sab196087 print_only, &print_type); 11335088Sab196087 } 11345088Sab196087 break; 11355088Sab196087 11365088Sab196087 case DYN_CMD_T_VALUE: 11375088Sab196087 print_only = (argstate.argc != 2); 11385088Sab196087 if (argstate.argc > 2) 11395088Sab196087 elfedit_command_usage(); 11405088Sab196087 if (argstate.argc > 0) { 11415088Sab196087 if (print_only) { 11425088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11435088Sab196087 print_only, &print_type); 11445088Sab196087 } else { 11455088Sab196087 print_type = PRINT_DYN_T_NDX; 11465088Sab196087 } 11475088Sab196087 } 11485088Sab196087 break; 11495088Sab196087 11505088Sab196087 case DYN_CMD_T_DELETE: 11515088Sab196087 if ((argstate.argc < 1) || (argstate.argc > 2)) 11525088Sab196087 elfedit_command_usage(); 11535088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11545088Sab196087 0, &print_type); 11555088Sab196087 do_autoprint = 0; 11565088Sab196087 break; 11575088Sab196087 11585088Sab196087 case DYN_CMD_T_MOVE: 11595088Sab196087 if ((argstate.argc < 2) || (argstate.argc > 3)) 11605088Sab196087 elfedit_command_usage(); 11615088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11626225Sab196087 0, &print_type); 11635088Sab196087 do_autoprint = 0; 11645088Sab196087 break; 11655088Sab196087 11665088Sab196087 case DYN_CMD_T_RUNPATH: 11675088Sab196087 if (argstate.argc > 1) 11685088Sab196087 elfedit_command_usage(); 11695088Sab196087 /* 11705088Sab196087 * dyn:runpath does not accept an explicit index 11715088Sab196087 * argument, so we implicitly only show the DT_RPATH and 11725088Sab196087 * DT_RUNPATH elements. 11735088Sab196087 */ 11745088Sab196087 print_type = PRINT_DYN_T_RUNPATH; 11755088Sab196087 print_only = (argstate.argc == 0); 11765088Sab196087 break; 11775088Sab196087 11785088Sab196087 case DYN_CMD_T_POSFLAG1: 11795088Sab196087 print_only = (argstate.argc == 0); 11805088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 11815088Sab196087 ELFEDIT_CONST_DT, DT_POSFLAG_1, 1), 11826225Sab196087 print_only, &print_type); 11835088Sab196087 break; 11845088Sab196087 11855088Sab196087 case DYN_CMD_T_FLAGS: 11865088Sab196087 print_only = (argstate.argc == 0); 11875088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 11885088Sab196087 ELFEDIT_CONST_DT, DT_FLAGS, 1), 11896225Sab196087 print_only, &print_type); 11905088Sab196087 break; 11915088Sab196087 11925088Sab196087 case DYN_CMD_T_FLAGS1: 11935088Sab196087 print_only = (argstate.argc == 0); 11945088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 11955088Sab196087 ELFEDIT_CONST_DT, DT_FLAGS_1, 1), 11966225Sab196087 print_only, &print_type); 11975088Sab196087 break; 11985088Sab196087 11995088Sab196087 case DYN_CMD_T_FEATURE1: 12005088Sab196087 print_only = (argstate.argc == 0); 12015088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12025088Sab196087 ELFEDIT_CONST_DT, DT_FEATURE_1, 1), 12036225Sab196087 print_only, &print_type); 12045088Sab196087 break; 12055088Sab196087 12065088Sab196087 case DYN_CMD_T_CHECKSUM: 12075088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12085088Sab196087 ELFEDIT_CONST_DT, DT_CHECKSUM, 1), 12096225Sab196087 print_only, &print_type); 12105088Sab196087 break; 12115088Sab196087 12126206Sab196087 case DYN_CMD_T_SUNW_LDMACH: 12136206Sab196087 if (argstate.argc > 1) 12146206Sab196087 elfedit_command_usage(); 12156206Sab196087 print_only = (argstate.argc == 0); 12166206Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12176206Sab196087 ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1), 12186225Sab196087 print_only, &print_type); 12196206Sab196087 break; 12206206Sab196087 12215088Sab196087 default: 12225088Sab196087 /* Note expected: All commands should have been caught above */ 12235088Sab196087 elfedit_command_usage(); 12245088Sab196087 break; 12255088Sab196087 } 12265088Sab196087 12275088Sab196087 12285088Sab196087 /* If this is a request to print current values, do it and return */ 12295088Sab196087 if (print_only) { 12305088Sab196087 print_dyn(cmd, 0, &argstate, print_type, ndx); 12315088Sab196087 return (ELFEDIT_CMDRET_NONE); 12325088Sab196087 } 12335088Sab196087 12345088Sab196087 12355088Sab196087 switch (cmd) { 12365088Sab196087 /* 12375088Sab196087 * DYN_CMD_T_DUMP can't get here: It is a print-only 12385088Sab196087 * command. 12395088Sab196087 */ 12405088Sab196087 12415088Sab196087 case DYN_CMD_T_TAG: 12425088Sab196087 { 12435088Sab196087 Conv_inv_buf_t inv_buf1, inv_buf2; 12445088Sab196087 Half mach = argstate.obj_state->os_ehdr->e_machine; 12455088Sab196087 Word d_tag = (Word) elfedit_atoconst(argstate.argv[1], 12465088Sab196087 ELFEDIT_CONST_DT); 12475088Sab196087 12485088Sab196087 if (dyn[ndx].d_tag == d_tag) { 12495088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12505088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), 12515088Sab196087 dyn_ndx, 12525088Sab196087 dyn_name, EC_WORD(ndx), 12535088Sab196087 conv_dyn_tag(d_tag, mach, 0, &inv_buf1)); 12545088Sab196087 } else { 12555088Sab196087 Word orig_d_tag = dyn[ndx].d_tag; 12565088Sab196087 12575088Sab196087 ret = ELFEDIT_CMDRET_MOD; 12585088Sab196087 dyn[ndx].d_tag = d_tag; 12595088Sab196087 12605088Sab196087 /* 12615088Sab196087 * Update null termination index. Warn if we 12625088Sab196087 * just clobbered the only DT_NULL termination 12635088Sab196087 * for the array. 12645088Sab196087 */ 12655088Sab196087 null_ndx = argstate.dyn.null_ndx; 12665088Sab196087 set_null_ndx(&argstate); 12675088Sab196087 if ((argstate.dyn.null_ndx >= 12685088Sab196087 argstate.dyn.num) && 12695088Sab196087 (null_ndx != argstate.dyn.null_ndx)) 12705088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12715088Sab196087 MSG_INTL(MSG_DEBUG_NULLTERM), 12725088Sab196087 dyn_ndx, dyn_name, 12735088Sab196087 EC_WORD(ndx), 12745088Sab196087 conv_dyn_tag(d_tag, mach, 12755088Sab196087 0, &inv_buf1)); 12765088Sab196087 12775088Sab196087 /* 12785088Sab196087 * Warning if 12795088Sab196087 * - Inserting a DT_NULL cuts off following 12805088Sab196087 * non-null elements. 12815088Sab196087 * - Inserting a non-DT_NULL after the 12825088Sab196087 * first null element, will be 12835088Sab196087 * ignored by rtld. 12845088Sab196087 */ 12855088Sab196087 if (d_tag == DT_NULL) { 12865088Sab196087 if ((ndx + 1) < null_ndx) 12875088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12885088Sab196087 MSG_INTL(MSG_DEBUG_NULCLIP), 12895088Sab196087 dyn_ndx, dyn_name, 12905088Sab196087 EC_WORD(ndx), 12915088Sab196087 conv_dyn_tag(d_tag, mach, 12925088Sab196087 0, &inv_buf1)); 12935088Sab196087 } else { 12945088Sab196087 if ((ndx + 1) > argstate.dyn.null_ndx) 12955088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12965088Sab196087 MSG_INTL(MSG_DEBUG_NULHIDE), 12975088Sab196087 dyn_ndx, dyn_name, 12985088Sab196087 EC_WORD(ndx), 12995088Sab196087 conv_dyn_tag(d_tag, mach, 13005088Sab196087 0, &inv_buf1)); 13015088Sab196087 } 13025088Sab196087 13035088Sab196087 /* Debug message that we changed it */ 13045088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13055088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 13065088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 13075088Sab196087 conv_dyn_tag(orig_d_tag, mach, 0, 13085088Sab196087 &inv_buf1), 13095088Sab196087 conv_dyn_tag(d_tag, mach, 0, &inv_buf2)); 13105088Sab196087 } 13115088Sab196087 } 13125088Sab196087 break; 13135088Sab196087 13145088Sab196087 case DYN_CMD_T_VALUE: 13155088Sab196087 ret = cmd_body_value(&argstate, &ndx); 13165088Sab196087 break; 13175088Sab196087 13185088Sab196087 case DYN_CMD_T_DELETE: 13195088Sab196087 { 13205088Sab196087 Word cnt = (argstate.argc == 1) ? 1 : 13215088Sab196087 (Word) elfedit_atoui_range(argstate.argv[1], 13225088Sab196087 MSG_ORIG(MSG_STR_COUNT), 1, dyn_num - ndx, NULL); 13235088Sab196087 const char *msg_prefix = 13245088Sab196087 elfedit_sec_msgprefix(argstate.dyn.sec); 13255088Sab196087 13265088Sab196087 elfedit_array_elts_delete(msg_prefix, argstate.dyn.data, 13275088Sab196087 sizeof (Dyn), dyn_num, ndx, cnt); 13285088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13295088Sab196087 } 13305088Sab196087 break; 13315088Sab196087 13325088Sab196087 case DYN_CMD_T_MOVE: 13335088Sab196087 { 13345088Sab196087 Dyn save; 13355088Sab196087 Word cnt; 13365088Sab196087 Word dstndx; 13375088Sab196087 const char *msg_prefix = 13385088Sab196087 elfedit_sec_msgprefix(argstate.dyn.sec); 13395088Sab196087 13405088Sab196087 dstndx = (Word) 13415088Sab196087 elfedit_atoui_range(argstate.argv[1], 13425088Sab196087 MSG_ORIG(MSG_STR_DST_INDEX), 0, dyn_num - 1, 13435088Sab196087 NULL); 13445088Sab196087 if (argstate.argc == 2) { 13455088Sab196087 cnt = 1; 13465088Sab196087 } else { 13475088Sab196087 cnt = (Word) elfedit_atoui_range( 13485088Sab196087 argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), 13495088Sab196087 1, dyn_num, NULL); 13505088Sab196087 } 13515088Sab196087 elfedit_array_elts_move(msg_prefix, argstate.dyn.data, 13525088Sab196087 sizeof (save), dyn_num, ndx, dstndx, cnt, &save); 13535088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13545088Sab196087 } 13555088Sab196087 break; 13565088Sab196087 13575088Sab196087 13585088Sab196087 case DYN_CMD_T_RUNPATH: 13595088Sab196087 ret = cmd_body_runpath(&argstate); 13605088Sab196087 break; 13615088Sab196087 13625088Sab196087 case DYN_CMD_T_POSFLAG1: 13635088Sab196087 { 13645088Sab196087 Conv_dyn_posflag1_buf_t buf1, buf2; 13655088Sab196087 Word flags; 13665088Sab196087 13675088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 13685088Sab196087 ELFEDIT_CONST_DF_P1); 13695088Sab196087 13705088Sab196087 /* Set the value */ 13715088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 13725088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13735088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 13745088Sab196087 dyn_name, EC_WORD(ndx), 13755088Sab196087 conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 13765088Sab196087 &buf1)); 13775088Sab196087 } else { 13785088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13795088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 13805088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 13815088Sab196087 conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 13825088Sab196087 &buf1), 13835088Sab196087 conv_dyn_posflag1(flags, 0, &buf2)); 13845088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13855088Sab196087 dyn[ndx].d_un.d_val = flags; 13865088Sab196087 } 13875088Sab196087 } 13885088Sab196087 break; 13895088Sab196087 13905088Sab196087 case DYN_CMD_T_FLAGS: 13915088Sab196087 { 13925088Sab196087 Conv_dyn_flag_buf_t buf1, buf2; 13935088Sab196087 Word flags; 13945088Sab196087 13955088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 13965088Sab196087 ELFEDIT_CONST_DF); 13975088Sab196087 13985088Sab196087 /* Set the value */ 13995088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 14005088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14015088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14025088Sab196087 dyn_name, EC_WORD(ndx), 14035088Sab196087 conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 14045088Sab196087 &buf1)); 14055088Sab196087 } else { 14065088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14075088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14085088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14095088Sab196087 conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 14105088Sab196087 &buf1), 14115088Sab196087 conv_dyn_flag(flags, 0, &buf2)); 14125088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14135088Sab196087 dyn[ndx].d_un.d_val = flags; 14145088Sab196087 } 14155088Sab196087 } 14165088Sab196087 break; 14175088Sab196087 14185088Sab196087 case DYN_CMD_T_FLAGS1: 14195088Sab196087 { 14205088Sab196087 Conv_dyn_flag1_buf_t buf1, buf2; 14215088Sab196087 Word flags1; 14225088Sab196087 14235088Sab196087 flags1 = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14245088Sab196087 ELFEDIT_CONST_DF_1); 14255088Sab196087 14265088Sab196087 /* Set the value */ 14275088Sab196087 if (dyn[ndx].d_un.d_val == flags1) { 14285088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14295088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14305088Sab196087 dyn_name, EC_WORD(ndx), 14315088Sab196087 conv_dyn_flag1(dyn[ndx].d_un.d_val, 14325088Sab196087 0, &buf1)); 14335088Sab196087 } else { 14345088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14355088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14365088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14375088Sab196087 conv_dyn_flag1(dyn[ndx].d_un.d_val, 14385088Sab196087 0, &buf1), 14395088Sab196087 conv_dyn_flag1(flags1, 0, &buf2)); 14405088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14415088Sab196087 dyn[ndx].d_un.d_val = flags1; 14425088Sab196087 } 14435088Sab196087 } 14445088Sab196087 break; 14455088Sab196087 14465088Sab196087 case DYN_CMD_T_FEATURE1: 14475088Sab196087 { 14485088Sab196087 Conv_dyn_feature1_buf_t buf1, buf2; 14495088Sab196087 Word flags; 14505088Sab196087 14515088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14525088Sab196087 ELFEDIT_CONST_DTF_1); 14535088Sab196087 14545088Sab196087 /* Set the value */ 14555088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 14565088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14575088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14585088Sab196087 dyn_name, EC_WORD(ndx), 14595088Sab196087 conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 14605088Sab196087 &buf1)); 14615088Sab196087 } else { 14625088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14635088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14645088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14655088Sab196087 conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 14665088Sab196087 &buf1), 14675088Sab196087 conv_dyn_feature1(flags, 0, &buf2)); 14685088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14695088Sab196087 dyn[ndx].d_un.d_val = flags; 14705088Sab196087 } 14715088Sab196087 } 14725088Sab196087 break; 14735088Sab196087 14745088Sab196087 case DYN_CMD_T_CHECKSUM: 14755088Sab196087 { 14765088Sab196087 long checksum = elf_checksum(obj_state->os_elf); 14775088Sab196087 14785088Sab196087 /* Set the value */ 14795088Sab196087 if (dyn[ndx].d_un.d_val == checksum) { 14805088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14815088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), dyn_ndx, 14825088Sab196087 dyn_name, EC_WORD(ndx), EC_XWORD(checksum)); 14835088Sab196087 } else { 14845088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14855088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 14865088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14875088Sab196087 EC_XWORD(dyn[ndx].d_un.d_val), 14885088Sab196087 EC_XWORD(checksum)); 14895088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14905088Sab196087 dyn[ndx].d_un.d_val = checksum; 14915088Sab196087 } 14925088Sab196087 14935088Sab196087 } 14946206Sab196087 break; 14956206Sab196087 14966206Sab196087 case DYN_CMD_T_SUNW_LDMACH: 14976206Sab196087 { 14986206Sab196087 Conv_inv_buf_t buf1, buf2; 14996206Sab196087 Half ldmach; 15006206Sab196087 15016206Sab196087 ldmach = (Half) elfedit_atoconst(argstate.argv[0], 15026206Sab196087 ELFEDIT_CONST_EM); 15036206Sab196087 15046206Sab196087 /* Set the value */ 15056206Sab196087 if (dyn[ndx].d_un.d_val == ldmach) { 15066206Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15076206Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 15086206Sab196087 dyn_name, EC_WORD(ndx), 15096206Sab196087 conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 15106206Sab196087 &buf1)); 15116206Sab196087 } else { 15126206Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15136206Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 15146206Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 15156206Sab196087 conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 15166206Sab196087 &buf1), 15176206Sab196087 conv_ehdr_mach(ldmach, 0, &buf2)); 15186206Sab196087 ret = ELFEDIT_CMDRET_MOD; 15196206Sab196087 dyn[ndx].d_un.d_val = ldmach; 15206206Sab196087 } 15216206Sab196087 } 15226206Sab196087 break; 15236206Sab196087 15245088Sab196087 } 15255088Sab196087 15265088Sab196087 /* 15275088Sab196087 * If we modified the dynamic section header, tell libelf. 15285088Sab196087 */ 15295088Sab196087 if (ret == ELFEDIT_CMDRET_MOD) 15305088Sab196087 elfedit_modified_data(argstate.dyn.sec); 15315088Sab196087 15325088Sab196087 /* Do autoprint */ 15335088Sab196087 if (do_autoprint) 15345088Sab196087 print_dyn(cmd, 1, &argstate, print_type, ndx); 15355088Sab196087 15365088Sab196087 return (ret); 15375088Sab196087 } 15385088Sab196087 15395088Sab196087 15405088Sab196087 15415088Sab196087 /* 15425088Sab196087 * Command completion functions for the commands 15435088Sab196087 */ 15445088Sab196087 15455088Sab196087 /* 15465088Sab196087 * Command completion for the first argument, which specifies 15475088Sab196087 * the dynamic element to use. Examines the options to see if 15485088Sab196087 * -dynndx is present, and if not, supplies the completion 15495088Sab196087 * strings for argument 1. 15505088Sab196087 */ 15515088Sab196087 /*ARGSUSED*/ 15525088Sab196087 static void 15535088Sab196087 cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 15545088Sab196087 const char *argv[], int num_opt) 15555088Sab196087 { 15565088Sab196087 elfedit_section_t *cache; 15575088Sab196087 Dyn *dyn; 15585088Sab196087 Word i; 15595088Sab196087 const char *s; 15605088Sab196087 char *s2; 15615088Sab196087 char buf[128]; 15625088Sab196087 15635088Sab196087 /* Make sure it's the first argument */ 15645088Sab196087 if ((argc - num_opt) != 1) 15655088Sab196087 return; 15665088Sab196087 15675088Sab196087 /* Is -dynndx present? If so, we don't complete tag types */ 15685088Sab196087 for (i = 0; i < num_opt; i++) 15695088Sab196087 if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0) 15705088Sab196087 return; 15715088Sab196087 15725088Sab196087 /* 15735088Sab196087 * If there is no object, or if there is no dynamic section, 15745088Sab196087 * then supply all possible names. 15755088Sab196087 */ 15765088Sab196087 if ((obj_state == NULL) || (obj_state->os_dynndx == SHN_UNDEF)) { 15775088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 15785088Sab196087 return; 15795088Sab196087 } 15805088Sab196087 15815088Sab196087 /* Supply completions for the tags present in the dynamic section */ 15825088Sab196087 cache = &obj_state->os_secarr[obj_state->os_dynndx]; 15835088Sab196087 dyn = (Dyn *) cache->sec_data->d_buf; 15845088Sab196087 i = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize; 15855088Sab196087 for (; i-- > 0; dyn++) { 15865088Sab196087 s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_DT, 15875088Sab196087 dyn->d_tag, 0); 15885088Sab196087 if (s == NULL) 15895088Sab196087 continue; 15905088Sab196087 elfedit_cpl_match(cpldata, s, 1); 15915088Sab196087 15925088Sab196087 /* 15935088Sab196087 * To get the informal tag names that are lowercase 15945088Sab196087 * and lack the leading DT_, we copy the string we 15955088Sab196087 * have into a buffer and process it. 15965088Sab196087 */ 15975088Sab196087 if (strlen(s) < 3) 15985088Sab196087 continue; 15995088Sab196087 (void) strlcpy(buf, s + 3, sizeof (buf)); 16005088Sab196087 for (s2 = buf; *s2 != '\0'; s2++) 16015088Sab196087 if (isupper(*s2)) 16025088Sab196087 *s2 = tolower(*s2); 16035088Sab196087 elfedit_cpl_match(cpldata, buf, 1); 16045088Sab196087 } 16055088Sab196087 } 16065088Sab196087 16075088Sab196087 16085088Sab196087 /*ARGSUSED*/ 16095088Sab196087 static void 16105088Sab196087 cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16115088Sab196087 const char *argv[], int num_opt) 16125088Sab196087 { 16135088Sab196087 /* First argument */ 16145088Sab196087 if ((argc - num_opt) == 1) { 16155088Sab196087 cpl_eltarg(obj_state, cpldata, argc, argv, num_opt); 16165088Sab196087 return; 16175088Sab196087 } 16185088Sab196087 16195088Sab196087 /* The second argument is always a tag value */ 16205088Sab196087 if ((argc - num_opt) == 2) 16215088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 16225088Sab196087 } 16235088Sab196087 16245088Sab196087 /*ARGSUSED*/ 16255088Sab196087 static void 16265088Sab196087 cpl_posflag1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16275088Sab196087 const char *argv[], int num_opt) 16285088Sab196087 { 16296225Sab196087 /* 16306225Sab196087 * dyn:posflag1 accepts two mutually exclusive options that have 16316225Sab196087 * a corresponding value argument: -dynndx and -needed. If we 16326225Sab196087 * are being called to supply options for the value, handle that here. 16336225Sab196087 */ 16346225Sab196087 if ((num_opt > 1) && (argc == num_opt)) { 16356225Sab196087 elfedit_section_t *dynsec, *strsec; 16366225Sab196087 const char *opt = argv[num_opt - 2]; 16376225Sab196087 dyn_opt_t type; 16386225Sab196087 Dyn *dyn; 16396225Sab196087 Word i, num; 16406225Sab196087 16416225Sab196087 /* 16426225Sab196087 * If there is no object available, or if the object has no 16436225Sab196087 * dynamic section, then there is nothing to report. 16446225Sab196087 */ 16456225Sab196087 if ((obj_state == NULL) || obj_state->os_dynndx == SHN_UNDEF) 16466225Sab196087 return; 16476225Sab196087 16486225Sab196087 /* 16496225Sab196087 * Determine which option it is, bail if it isn't one of 16506225Sab196087 * the ones we are concerned with. 16516225Sab196087 */ 16526225Sab196087 if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_NEEDED)) == 0)) 16536225Sab196087 type = DYN_OPT_F_NEEDED; 16546225Sab196087 else if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0)) 16556225Sab196087 type = DYN_OPT_F_DYNNDX_VAL; 16566225Sab196087 else 16576225Sab196087 return; 16586225Sab196087 16596225Sab196087 dynsec = elfedit_sec_getdyn(obj_state, &dyn, &num); 16606225Sab196087 switch (type) { 16616225Sab196087 case DYN_OPT_F_NEEDED: 16626225Sab196087 strsec = elfedit_sec_getstr(obj_state, 16636225Sab196087 dynsec->sec_shdr->sh_link, 0); 16646225Sab196087 for (; num-- > 0; dyn++) 16656225Sab196087 if (dyn->d_tag == DT_NEEDED) 16666225Sab196087 elfedit_cpl_match(cpldata, 16676225Sab196087 elfedit_offset_to_str(strsec, 16686225Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 16696225Sab196087 0), 0); 16706225Sab196087 break; 16716225Sab196087 16726225Sab196087 case DYN_OPT_F_DYNNDX_VAL: 16736225Sab196087 for (i = 0; i < num; i++, dyn++) 16746225Sab196087 if (dyn->d_tag == DT_POSFLAG_1) 16756225Sab196087 elfedit_cpl_ndx(cpldata, i); 16766225Sab196087 break; 16776225Sab196087 } 16786225Sab196087 return; 16796225Sab196087 } 16806225Sab196087 16815088Sab196087 /* This routine allows multiple flags to be specified */ 16825088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_P1); 16835088Sab196087 } 16845088Sab196087 16855088Sab196087 /*ARGSUSED*/ 16865088Sab196087 static void 16875088Sab196087 cpl_flags(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); 16925088Sab196087 } 16935088Sab196087 16945088Sab196087 /*ARGSUSED*/ 16955088Sab196087 static void 16965088Sab196087 cpl_flags1(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_DF_1); 17015088Sab196087 } 17025088Sab196087 17035088Sab196087 /*ARGSUSED*/ 17045088Sab196087 static void 17055088Sab196087 cpl_feature1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17065088Sab196087 const char *argv[], int num_opt) 17075088Sab196087 { 17085088Sab196087 /* This routine allows multiple flags to be specified */ 17095088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1); 17105088Sab196087 } 17115088Sab196087 17126206Sab196087 /*ARGSUSED*/ 17136206Sab196087 static void 17146206Sab196087 cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17156206Sab196087 const char *argv[], int num_opt) 17166206Sab196087 { 17176206Sab196087 /* 17186206Sab196087 * This command doesn't accept options, so num_opt should be 17196206Sab196087 * 0. This is a defensive measure, in case that should change. 17206206Sab196087 */ 17216206Sab196087 argc -= num_opt; 17226206Sab196087 argv += num_opt; 17236206Sab196087 17246206Sab196087 if (argc == 1) 17256206Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM); 17266206Sab196087 } 17276206Sab196087 17285088Sab196087 17295088Sab196087 /* 17305088Sab196087 * Implementation functions for the commands 17315088Sab196087 */ 17325088Sab196087 static elfedit_cmdret_t 17335088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17345088Sab196087 { 17355088Sab196087 return (cmd_body(DYN_CMD_T_DUMP, obj_state, argc, argv)); 17365088Sab196087 } 17375088Sab196087 17385088Sab196087 static elfedit_cmdret_t 17395088Sab196087 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17405088Sab196087 { 17415088Sab196087 return (cmd_body(DYN_CMD_T_TAG, obj_state, argc, argv)); 17425088Sab196087 } 17435088Sab196087 17445088Sab196087 static elfedit_cmdret_t 17455088Sab196087 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17465088Sab196087 { 17475088Sab196087 return (cmd_body(DYN_CMD_T_VALUE, obj_state, argc, argv)); 17485088Sab196087 } 17495088Sab196087 17505088Sab196087 static elfedit_cmdret_t 17515088Sab196087 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17525088Sab196087 { 17535088Sab196087 return (cmd_body(DYN_CMD_T_DELETE, obj_state, argc, argv)); 17545088Sab196087 } 17555088Sab196087 17565088Sab196087 static elfedit_cmdret_t 17575088Sab196087 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17585088Sab196087 { 17595088Sab196087 return (cmd_body(DYN_CMD_T_MOVE, obj_state, argc, argv)); 17605088Sab196087 } 17615088Sab196087 17625088Sab196087 static elfedit_cmdret_t 17635088Sab196087 cmd_runpath(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17645088Sab196087 { 17655088Sab196087 return (cmd_body(DYN_CMD_T_RUNPATH, obj_state, argc, argv)); 17665088Sab196087 } 17675088Sab196087 17685088Sab196087 static elfedit_cmdret_t 17695088Sab196087 cmd_posflag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17705088Sab196087 { 17715088Sab196087 return (cmd_body(DYN_CMD_T_POSFLAG1, obj_state, argc, argv)); 17725088Sab196087 } 17735088Sab196087 17745088Sab196087 static elfedit_cmdret_t 17755088Sab196087 cmd_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17765088Sab196087 { 17775088Sab196087 return (cmd_body(DYN_CMD_T_FLAGS, obj_state, argc, argv)); 17785088Sab196087 } 17795088Sab196087 17805088Sab196087 static elfedit_cmdret_t 17815088Sab196087 cmd_flags1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17825088Sab196087 { 17835088Sab196087 return (cmd_body(DYN_CMD_T_FLAGS1, obj_state, argc, argv)); 17845088Sab196087 } 17855088Sab196087 17865088Sab196087 static elfedit_cmdret_t 17875088Sab196087 cmd_feature1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17885088Sab196087 { 17895088Sab196087 return (cmd_body(DYN_CMD_T_FEATURE1, obj_state, argc, argv)); 17905088Sab196087 } 17915088Sab196087 17925088Sab196087 static elfedit_cmdret_t 17935088Sab196087 cmd_checksum(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17945088Sab196087 { 17955088Sab196087 return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv)); 17965088Sab196087 } 17975088Sab196087 17986206Sab196087 static elfedit_cmdret_t 17996206Sab196087 cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18006206Sab196087 { 18016206Sab196087 return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv)); 18026206Sab196087 } 18036206Sab196087 18045088Sab196087 18055088Sab196087 18065088Sab196087 /*ARGSUSED*/ 18075088Sab196087 elfedit_module_t * 18085088Sab196087 elfedit_init(elfedit_module_version_t version) 18095088Sab196087 { 18105088Sab196087 /* For commands that only accept -o */ 18115088Sab196087 static elfedit_cmd_optarg_t opt_ostyle[] = { 18125088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18135088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18145088Sab196087 { NULL } 18155088Sab196087 }; 18165088Sab196087 18175088Sab196087 /* For commands that only accept -and, -cmp, -o, -or */ 18185088Sab196087 static elfedit_cmd_optarg_t opt_ostyle_bitop[] = { 18195088Sab196087 { ELFEDIT_STDOA_OPT_AND, NULL, 18205088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 18215088Sab196087 { ELFEDIT_STDOA_OPT_CMP, NULL, 18225088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 18235088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18245088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18255088Sab196087 { ELFEDIT_STDOA_OPT_OR, NULL, 18265088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 18275088Sab196087 { NULL } 18285088Sab196087 }; 18295088Sab196087 18305088Sab196087 /* For commands that only accept -dynndx */ 18315088Sab196087 static elfedit_cmd_optarg_t opt_minus_dynndx[] = { 18325088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 18336225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 18346225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 18356225Sab196087 DYN_OPT_F_DYNNDX_ELT, 0 }, 18365088Sab196087 { NULL } 18375088Sab196087 }; 18385088Sab196087 18395088Sab196087 /* dyn:dump */ 18405088Sab196087 static const char *name_dump[] = { 18415088Sab196087 MSG_ORIG(MSG_CMD_DUMP), 18425088Sab196087 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 18435088Sab196087 NULL 18445088Sab196087 }; 18455088Sab196087 static elfedit_cmd_optarg_t arg_dump[] = { 18465088Sab196087 { MSG_ORIG(MSG_STR_ELT), 18475088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 18485088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 18495088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18505088Sab196087 { NULL } 18515088Sab196087 }; 18525088Sab196087 18535088Sab196087 18545088Sab196087 /* dyn:tag */ 18555088Sab196087 static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL }; 18565088Sab196087 static elfedit_cmd_optarg_t opt_tag[] = { 18575088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 18586225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 18596225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 18606225Sab196087 DYN_OPT_F_DYNNDX_ELT, 0 }, 18615088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18625088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18635088Sab196087 { NULL } 18645088Sab196087 }; 18655088Sab196087 static elfedit_cmd_optarg_t arg_tag[] = { 18665088Sab196087 { MSG_ORIG(MSG_STR_ELT), 18675088Sab196087 /* MSG_INTL(MSG_A1_TAG_ELT) */ 18685088Sab196087 ELFEDIT_I18NHDL(MSG_A1_TAG_ELT), 18695088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18705088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 18715088Sab196087 /* MSG_INTL(MSG_A2_TAG_VALUE) */ 18725088Sab196087 ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE), 18735088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18745088Sab196087 { NULL } 18755088Sab196087 }; 18765088Sab196087 18775088Sab196087 18785088Sab196087 /* dyn:value */ 18795088Sab196087 static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL }; 18805088Sab196087 static elfedit_cmd_optarg_t opt_value[] = { 18815088Sab196087 { MSG_ORIG(MSG_STR_MINUS_ADD), 18825088Sab196087 /* MSG_INTL(MSG_OPTDESC_ADD) */ 18835088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_ADD), 0, 18846225Sab196087 DYN_OPT_F_ADD, DYN_OPT_F_DYNNDX_ELT }, 18855088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 18866225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 18876225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 18886225Sab196087 DYN_OPT_F_DYNNDX_ELT, DYN_OPT_F_ADD }, 18895088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18905088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18915088Sab196087 { MSG_ORIG(MSG_STR_MINUS_S), 18925088Sab196087 /* MSG_INTL(MSG_OPTDESC_S) */ 18935088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0, 18945088Sab196087 DYN_OPT_F_STRVAL, 0 }, 18955088Sab196087 { NULL } 18965088Sab196087 }; 18975088Sab196087 static elfedit_cmd_optarg_t arg_value[] = { 18985088Sab196087 { MSG_ORIG(MSG_STR_ELT), 18995088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19005088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19015088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19025088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19035088Sab196087 /* MSG_INTL(MSG_A2_VALUE_VALUE) */ 19045088Sab196087 ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE), 19055088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19065088Sab196087 { NULL } 19075088Sab196087 }; 19085088Sab196087 19095088Sab196087 /* dyn:delete */ 19105088Sab196087 static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL }; 19115088Sab196087 static elfedit_cmd_optarg_t arg_delete[] = { 19125088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19135088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19145088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19155088Sab196087 0 }, 19165088Sab196087 { MSG_ORIG(MSG_STR_COUNT), 19175088Sab196087 /* MSG_INTL(MSG_A2_DELETE_COUNT) */ 19185088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT), 19195088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19205088Sab196087 { NULL } 19215088Sab196087 }; 19225088Sab196087 19235088Sab196087 /* dyn:move */ 19245088Sab196087 static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL }; 19255088Sab196087 static elfedit_cmd_optarg_t arg_move[] = { 19265088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19275088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19285088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19295088Sab196087 0 }, 19305088Sab196087 { MSG_ORIG(MSG_STR_DST_INDEX), 19315088Sab196087 /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */ 19325088Sab196087 ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX), 19335088Sab196087 0 }, 19345088Sab196087 { MSG_ORIG(MSG_STR_COUNT), 19355088Sab196087 /* MSG_INTL(MSG_A3_MOVE_COUNT) */ 19365088Sab196087 ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT), 19375088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19385088Sab196087 { NULL } 19395088Sab196087 }; 19405088Sab196087 19415088Sab196087 /* dyn:runpath / dyn:rpath */ 19425088Sab196087 static const char *name_runpath[] = { MSG_ORIG(MSG_CMD_RUNPATH), 19435088Sab196087 MSG_ORIG(MSG_CMD_RUNPATH_A1), NULL }; 19445088Sab196087 static elfedit_cmd_optarg_t arg_runpath[] = { 19455088Sab196087 { MSG_ORIG(MSG_STR_NEWPATH), 19465088Sab196087 /* MSG_INTL(MSG_A1_RUNPATH_NEWPATH) */ 19475088Sab196087 ELFEDIT_I18NHDL(MSG_A1_RUNPATH_NEWPATH), 19485088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19495088Sab196087 { NULL } 19505088Sab196087 }; 19515088Sab196087 19525088Sab196087 /* dyn:posflag1 */ 19535088Sab196087 static const char *name_posflag1[] = { MSG_ORIG(MSG_CMD_POSFLAG1), 19545088Sab196087 NULL }; 19556225Sab196087 static elfedit_cmd_optarg_t opt_posflag1[] = { 19566225Sab196087 { ELFEDIT_STDOA_OPT_AND, NULL, 19576225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 19586225Sab196087 { ELFEDIT_STDOA_OPT_CMP, NULL, 19596225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 19606225Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 19616225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_VAL) */ 19626225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_VAL), 19636225Sab196087 ELFEDIT_CMDOA_F_VALUE, 19646225Sab196087 DYN_OPT_F_DYNNDX_VAL, DYN_OPT_F_NEEDED }, 19656225Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 19666225Sab196087 { MSG_ORIG(MSG_STR_MINUS_NEEDED), 19676225Sab196087 /* MSG_INTL(MSG_OPTDESC_NEEDED) */ 19686225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_NEEDED), 19696225Sab196087 ELFEDIT_CMDOA_F_VALUE, 19706225Sab196087 DYN_OPT_F_NEEDED, DYN_OPT_F_DYNNDX_VAL }, 19716225Sab196087 { MSG_ORIG(MSG_STR_PREFIX), NULL, 0, 0 }, 19726225Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 19736225Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 19746225Sab196087 { ELFEDIT_STDOA_OPT_OR, NULL, 19756225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 19766225Sab196087 { NULL } 19776225Sab196087 }; 19785088Sab196087 static elfedit_cmd_optarg_t arg_posflag1[] = { 19795088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19805088Sab196087 /* MSG_INTL(MSG_A1_POSFLAG1_VALUE) */ 19815088Sab196087 ELFEDIT_I18NHDL(MSG_A1_POSFLAG1_VALUE), 19825088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 19835088Sab196087 { NULL } 19845088Sab196087 }; 19855088Sab196087 19865088Sab196087 /* dyn:flags */ 19875088Sab196087 static const char *name_flags[] = { MSG_ORIG(MSG_CMD_FLAGS), NULL }; 19885088Sab196087 static elfedit_cmd_optarg_t arg_flags[] = { 19895088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19905088Sab196087 /* MSG_INTL(MSG_A1_FLAGS_VALUE) */ 19915088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FLAGS_VALUE), 19925088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 19935088Sab196087 { NULL } 19945088Sab196087 }; 19955088Sab196087 19965088Sab196087 /* dyn:flags1 */ 19975088Sab196087 static const char *name_flags1[] = { MSG_ORIG(MSG_CMD_FLAGS1), NULL }; 19985088Sab196087 static elfedit_cmd_optarg_t arg_flags1[] = { 19995088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20005088Sab196087 /* MSG_INTL(MSG_A1_FLAGS1_VALUE) */ 20015088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FLAGS1_VALUE), 20025088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20035088Sab196087 { NULL } 20045088Sab196087 }; 20055088Sab196087 20065088Sab196087 /* dyn:feature1 */ 20075088Sab196087 static const char *name_feature1[] = { MSG_ORIG(MSG_CMD_FEATURE1), 20085088Sab196087 NULL }; 20095088Sab196087 static elfedit_cmd_optarg_t arg_feature1[] = { 20105088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20115088Sab196087 /* MSG_INTL(MSG_A1_FEATURE1_VALUE) */ 20125088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FEATURE1_VALUE), 20135088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20145088Sab196087 { NULL } 20155088Sab196087 }; 20165088Sab196087 20175088Sab196087 /* dyn:checksum */ 20185088Sab196087 static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM), 20195088Sab196087 NULL }; 20205088Sab196087 20216206Sab196087 /* dyn:sunw_ldmach */ 20226206Sab196087 static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH), 20236206Sab196087 NULL }; 20246206Sab196087 static elfedit_cmd_optarg_t arg_sunw_ldmach[] = { 20256206Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20266206Sab196087 /* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */ 20276206Sab196087 ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE), 20286206Sab196087 ELFEDIT_CMDOA_F_OPT }, 20296206Sab196087 { NULL } 20306206Sab196087 }; 20316206Sab196087 20325088Sab196087 20335088Sab196087 20345088Sab196087 static elfedit_cmd_t cmds[] = { 20355088Sab196087 /* dyn:dump */ 20365088Sab196087 { cmd_dump, cpl_eltarg, name_dump, 20375088Sab196087 /* MSG_INTL(MSG_DESC_DUMP) */ 20385088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 20395088Sab196087 /* MSG_INTL(MSG_HELP_DUMP) */ 20405088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 20415088Sab196087 opt_minus_dynndx, arg_dump }, 20425088Sab196087 20435088Sab196087 /* dyn:tag */ 20445088Sab196087 { cmd_tag, cpl_tag, name_tag, 20455088Sab196087 /* MSG_INTL(MSG_DESC_TAG) */ 20465088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_TAG), 20475088Sab196087 /* MSG_INTL(MSG_HELP_TAG) */ 20485088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_TAG), 20495088Sab196087 opt_tag, arg_tag }, 20505088Sab196087 20515088Sab196087 /* dyn:value */ 20525088Sab196087 { cmd_value, cpl_eltarg, name_value, 20535088Sab196087 /* MSG_INTL(MSG_DESC_VALUE) */ 20545088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_VALUE), 20555088Sab196087 /* MSG_INTL(MSG_HELP_VALUE) */ 20565088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_VALUE), 20575088Sab196087 opt_value, arg_value }, 20585088Sab196087 20595088Sab196087 /* dyn:delete */ 20605088Sab196087 { cmd_delete, cpl_eltarg, name_delete, 20615088Sab196087 /* MSG_INTL(MSG_DESC_DELETE) */ 20625088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DELETE), 20635088Sab196087 /* MSG_INTL(MSG_HELP_DELETE) */ 20645088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DELETE), 20655088Sab196087 opt_minus_dynndx, arg_delete }, 20665088Sab196087 20675088Sab196087 /* dyn:move */ 20685088Sab196087 { cmd_move, cpl_eltarg, name_move, 20695088Sab196087 /* MSG_INTL(MSG_DESC_MOVE) */ 20705088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_MOVE), 20715088Sab196087 /* MSG_INTL(MSG_HELP_MOVE) */ 20725088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_MOVE), 20735088Sab196087 opt_minus_dynndx, arg_move }, 20745088Sab196087 20755088Sab196087 /* dyn:runpath */ 20765088Sab196087 { cmd_runpath, NULL, name_runpath, 20775088Sab196087 /* MSG_INTL(MSG_DESC_RUNPATH) */ 20785088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_RUNPATH), 20795088Sab196087 /* MSG_INTL(MSG_HELP_RUNPATH) */ 20805088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_RUNPATH), 20815088Sab196087 opt_ostyle, arg_runpath }, 20825088Sab196087 20835088Sab196087 /* dyn:posflag1 */ 20845088Sab196087 { cmd_posflag1, cpl_posflag1, name_posflag1, 20855088Sab196087 /* MSG_INTL(MSG_DESC_POSFLAG1) */ 20865088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_POSFLAG1), 20875088Sab196087 /* MSG_INTL(MSG_HELP_POSFLAG1) */ 20885088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_POSFLAG1), 20896225Sab196087 opt_posflag1, arg_posflag1 }, 20905088Sab196087 20915088Sab196087 /* dyn:flags */ 20925088Sab196087 { cmd_flags, cpl_flags, name_flags, 20935088Sab196087 /* MSG_INTL(MSG_DESC_FLAGS) */ 20945088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FLAGS), 20955088Sab196087 /* MSG_INTL(MSG_HELP_FLAGS) */ 20965088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FLAGS), 20975088Sab196087 opt_ostyle_bitop, arg_flags }, 20985088Sab196087 20995088Sab196087 /* dyn:flags1 */ 21005088Sab196087 { cmd_flags1, cpl_flags1, name_flags1, 21015088Sab196087 /* MSG_INTL(MSG_DESC_FLAGS1) */ 21025088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FLAGS1), 21035088Sab196087 /* MSG_INTL(MSG_HELP_FLAGS1) */ 21045088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FLAGS1), 21055088Sab196087 opt_ostyle_bitop, arg_flags1 }, 21065088Sab196087 21075088Sab196087 /* dyn:feature1 */ 21085088Sab196087 { cmd_feature1, cpl_feature1, name_feature1, 21095088Sab196087 /* MSG_INTL(MSG_DESC_FEATURE1) */ 21105088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FEATURE1), 21115088Sab196087 /* MSG_INTL(MSG_HELP_FEATURE1) */ 21125088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FEATURE1), 21135088Sab196087 opt_ostyle_bitop, arg_feature1 }, 21145088Sab196087 21155088Sab196087 /* dyn:checksum */ 21165088Sab196087 { cmd_checksum, NULL, name_checksum, 21175088Sab196087 /* MSG_INTL(MSG_DESC_CHECKSUM) */ 21185088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_CHECKSUM), 21195088Sab196087 /* MSG_INTL(MSG_HELP_CHECKSUM) */ 21205088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM), 21215088Sab196087 NULL, NULL }, 21225088Sab196087 21236206Sab196087 /* dyn:sunw_ldmach */ 21246206Sab196087 { cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach, 21256206Sab196087 /* MSG_INTL(MSG_DESC_SUNW_LDMACH) */ 21266206Sab196087 ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH), 21276206Sab196087 /* MSG_INTL(MSG_HELP_SUNW_LDMACH) */ 21286206Sab196087 ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH), 21296206Sab196087 opt_ostyle, arg_sunw_ldmach }, 21306206Sab196087 21315088Sab196087 { NULL } 21325088Sab196087 }; 21335088Sab196087 21345088Sab196087 static elfedit_module_t module = { 21355088Sab196087 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 21365088Sab196087 /* MSG_INTL(MSG_MOD_DESC) */ 21375088Sab196087 ELFEDIT_I18NHDL(MSG_MOD_DESC), cmds, mod_i18nhdl_to_str }; 21385088Sab196087 21395088Sab196087 return (&module); 21405088Sab196087 } 2141