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 /* 23*6206Sab196087 * 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 */ 65*6206Sab196087 DYN_CMD_T_CHECKSUM = 10, /* dyn:checksum */ 66*6206Sab196087 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 */ 1135088Sab196087 DYN_OPT_F_DYNNDX = 8, /* -dynndx: elt is tag index, */ 1145088Sab196087 /* not name */ 1155088Sab196087 DYN_OPT_F_OR = 16, /* -or: OR (|) values to dest */ 1165088Sab196087 DYN_OPT_F_STRVAL = 32 /* -s: value is string, not integer */ 1175088Sab196087 } dyn_opt_t; 1185088Sab196087 1195088Sab196087 1205088Sab196087 /* 1215088Sab196087 * A variable of type ARGSTATE is used by each command to maintain 1225088Sab196087 * information about the arguments and related things. It is 1235088Sab196087 * initialized by process_args(), and used by the other routines. 1245088Sab196087 */ 1255088Sab196087 typedef struct { 1265088Sab196087 elfedit_obj_state_t *obj_state; 1275088Sab196087 elfedit_section_t *strsec; /* Dynamic string table ref */ 1285088Sab196087 struct { 1295088Sab196087 elfedit_section_t *sec; /* Dynamic section reference */ 1305088Sab196087 Dyn *data; /* Start dynamic section data */ 1315088Sab196087 Word num; /* # dynamic elts */ 1325088Sab196087 Word null_ndx; /* Index of first DT_NULL */ 1335088Sab196087 Word num_null_ndx; /* # of DT_NULL elements */ 1345088Sab196087 } dyn; 1355088Sab196087 dyn_opt_t optmask; /* Mask of options used */ 1365088Sab196087 int argc; /* # of plain arguments */ 1375088Sab196087 const char **argv; /* Plain arguments */ 1385088Sab196087 } ARGSTATE; 1395088Sab196087 1405088Sab196087 1415088Sab196087 1425088Sab196087 /* 1435088Sab196087 * Set argstate null_ndx field for current dynamic area 1445088Sab196087 */ 1455088Sab196087 static void 1465088Sab196087 set_null_ndx(ARGSTATE *argstate) 1475088Sab196087 { 1485088Sab196087 Word num, null_ndx; 1495088Sab196087 1505088Sab196087 num = argstate->dyn.num; 1515088Sab196087 argstate->dyn.num_null_ndx = 0; 1525088Sab196087 for (null_ndx = 0; null_ndx < num; null_ndx++) 1535088Sab196087 if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) { 1545088Sab196087 argstate->dyn.num_null_ndx++; 1555088Sab196087 break; 1565088Sab196087 } 1575088Sab196087 argstate->dyn.null_ndx = null_ndx; 1585088Sab196087 1595088Sab196087 /* Count the number of remaining DT_NULL items */ 1605088Sab196087 for (; null_ndx < num; null_ndx++) 1615088Sab196087 if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) 1625088Sab196087 argstate->dyn.num_null_ndx++; 1635088Sab196087 } 1645088Sab196087 1655088Sab196087 1665088Sab196087 /* 1675088Sab196087 * Convert the first available DT_NULL slot in the dynamic section 1685088Sab196087 * into something else. 1695088Sab196087 * 1705088Sab196087 * entry: 1715088Sab196087 * argstate - Argument state block 1725088Sab196087 * d_tag, d_val - Values to be set in new element 1735088Sab196087 * 1745088Sab196087 * exit: 1755088Sab196087 * If an extra DT_NULL slot is available, a debug message is 1765088Sab196087 * issued, the slot is converted to its new use, and the argstate 1775088Sab196087 * block state related to DT_NULL slots is updated. 1785088Sab196087 * 1795088Sab196087 * if no extra DT_NULL slot is present, an error is issued and 1805088Sab196087 * this routine does not return to the caller. 1815088Sab196087 */ 1825088Sab196087 static Word 1835088Sab196087 convert_dt_null(ARGSTATE *argstate, Word d_tag, Xword d_val) 1845088Sab196087 { 1855088Sab196087 Conv_inv_buf_t inv_buf; 1865088Sab196087 Word ndx; 1875088Sab196087 Dyn *dyn; 1885088Sab196087 1895088Sab196087 /* If we lack an extra element, we can't continue */ 1905088Sab196087 if (argstate->dyn.num_null_ndx <= 1) 1915088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 1925088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 1935088Sab196087 argstate->dyn.sec->sec_name); 1945088Sab196087 1955088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL), 1965088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), argstate->dyn.sec->sec_name, 1975088Sab196087 EC_WORD(argstate->dyn.null_ndx), conv_dyn_tag(d_tag, 1985088Sab196087 argstate->obj_state->os_ehdr->e_machine, 0, &inv_buf)); 1995088Sab196087 2005088Sab196087 ndx = argstate->dyn.null_ndx; 2015088Sab196087 dyn = &argstate->dyn.data[ndx]; 2025088Sab196087 dyn->d_tag = d_tag; 2035088Sab196087 dyn->d_un.d_val = d_val; 2045088Sab196087 2055088Sab196087 /* Recompute the DT_NULL situation */ 2065088Sab196087 set_null_ndx(argstate); 2075088Sab196087 2085088Sab196087 return (ndx); 2095088Sab196087 } 2105088Sab196087 2115088Sab196087 2125088Sab196087 /* 2135088Sab196087 * Standard argument processing for dyn module 2145088Sab196087 * 2155088Sab196087 * entry 2165088Sab196087 * obj_state, argc, argv - Standard command arguments 2175088Sab196087 * argstate - Address of ARGSTATE block to be initialized 2185088Sab196087 * 2195088Sab196087 * exit: 2205088Sab196087 * On success, *argstate is initialized. On error, 2215088Sab196087 * an error is issued and this routine does not return. 2225088Sab196087 */ 2235088Sab196087 static void 2245088Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 2255088Sab196087 ARGSTATE *argstate) 2265088Sab196087 { 2275088Sab196087 elfedit_getopt_state_t getopt_state; 2285088Sab196087 elfedit_getopt_ret_t *getopt_ret; 2295088Sab196087 2305088Sab196087 bzero(argstate, sizeof (*argstate)); 2315088Sab196087 argstate->obj_state = obj_state; 2325088Sab196087 2335088Sab196087 elfedit_getopt_init(&getopt_state, &argc, &argv); 2345088Sab196087 2355088Sab196087 /* Add each new option to the options mask */ 2365088Sab196087 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) 2375088Sab196087 argstate->optmask |= getopt_ret->gor_idmask; 2385088Sab196087 2395088Sab196087 /* If there may be an arbitrary amount of output, use a pager */ 2405088Sab196087 if (argc == 0) 2415088Sab196087 elfedit_pager_init(); 2425088Sab196087 2435088Sab196087 /* Return the updated values of argc/argv */ 2445088Sab196087 argstate->argc = argc; 2455088Sab196087 argstate->argv = argv; 2465088Sab196087 2475088Sab196087 /* Locate the dynamic section, and the assocated string table */ 2485088Sab196087 argstate->dyn.sec = elfedit_sec_getdyn(obj_state, &argstate->dyn.data, 2495088Sab196087 &argstate->dyn.num); 2505088Sab196087 argstate->strsec = elfedit_sec_getstr(obj_state, 2515088Sab196087 argstate->dyn.sec->sec_shdr->sh_link); 2525088Sab196087 2535088Sab196087 /* Index of first DT_NULL */ 2545088Sab196087 set_null_ndx(argstate); 2555088Sab196087 } 2565088Sab196087 2575088Sab196087 2585088Sab196087 2595088Sab196087 /* 2605088Sab196087 * Print ELF header values, taking the calling command, and output style 2615088Sab196087 * into account. 2625088Sab196087 * 2635088Sab196087 * entry: 2645088Sab196087 * cmd - DYN_CMD_T_* value giving identify of caller 2655088Sab196087 * autoprint - If True, output is only produced if the elfedit 2665088Sab196087 * autoprint flag is set. If False, output is always produced. 2675088Sab196087 * argstate - Argument state block 2685088Sab196087 * print_type - Specifies which dynamic elements to display. 2695088Sab196087 * ndx = If print_type is PRINT_DYN_T_NDX, displays the index specified. 2705088Sab196087 * Otherwise ignored. 2715088Sab196087 */ 2725088Sab196087 typedef enum { 2735088Sab196087 PRINT_DYN_T_ALL = 0, /* Show all indexes */ 2745088Sab196087 PRINT_DYN_T_NDX = 1, /* Show dynamic[arg] only */ 2755088Sab196087 PRINT_DYN_T_TAG = 2, /* Show all elts with tag type */ 2765088Sab196087 /* given by arg */ 2775088Sab196087 PRINT_DYN_T_RUNPATH = 3 /* Show all runpath/rpath elts */ 2785088Sab196087 2795088Sab196087 } PRINT_DYN_T; 2805088Sab196087 2815088Sab196087 static void 2825088Sab196087 print_dyn(DYN_CMD_T cmd, int autoprint, ARGSTATE *argstate, 2835088Sab196087 PRINT_DYN_T print_type, Word arg) 2845088Sab196087 { 2855088Sab196087 elfedit_outstyle_t outstyle; 2865088Sab196087 Conv_fmt_flags_t flags_fmt_flags; 2875088Sab196087 Word end_ndx, cnt, ndx, printed = 0; 2885088Sab196087 Dyn *dyn; 2895088Sab196087 int header_done = 0; 2905088Sab196087 Xword last_d_val; 2915088Sab196087 2925088Sab196087 if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) 2935088Sab196087 return; 2945088Sab196087 2955088Sab196087 /* 2965088Sab196087 * Pick an output style. dyn:dump is required to use the default 2975088Sab196087 * style. The other commands use the current output style. 2985088Sab196087 */ 2995088Sab196087 outstyle = (cmd == DYN_CMD_T_DUMP) ? 3005088Sab196087 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 3015088Sab196087 3025088Sab196087 /* 3035088Sab196087 * When using the simple output style, omit the 3045088Sab196087 * brackets from around the values. 3055088Sab196087 */ 3065088Sab196087 flags_fmt_flags = (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) ? 3075088Sab196087 CONV_FMT_NOBKT : 0; 3085088Sab196087 3095088Sab196087 /* How many elements do we examine? */ 3105088Sab196087 if (print_type == PRINT_DYN_T_NDX) { 3115088Sab196087 if (arg >= argstate->dyn.num) 3125088Sab196087 return; /* Out of range */ 3135088Sab196087 ndx = arg; 3145088Sab196087 cnt = 1; 3155088Sab196087 } else { 3165088Sab196087 ndx = 0; 3175088Sab196087 cnt = argstate->dyn.num; 3185088Sab196087 } 3195088Sab196087 3205088Sab196087 dyn = &argstate->dyn.data[ndx]; 3215088Sab196087 for (; cnt--; dyn++, ndx++) { 3225088Sab196087 union { 323*6206Sab196087 Conv_inv_buf_t inv; 3245088Sab196087 Conv_dyn_flag_buf_t flag; 3255088Sab196087 Conv_dyn_flag1_buf_t flag1; 3265088Sab196087 Conv_dyn_posflag1_buf_t posflag1; 3275088Sab196087 Conv_dyn_feature1_buf_t feature1; 3285088Sab196087 } c_buf; 3295088Sab196087 const char *name; 3305088Sab196087 3315088Sab196087 /* 3325088Sab196087 * If we are only displaying certain tag types and 3335088Sab196087 * this isn't one of those, move on to next element. 3345088Sab196087 */ 3355088Sab196087 switch (print_type) { 3365088Sab196087 case PRINT_DYN_T_TAG: 3375088Sab196087 if (dyn->d_tag != arg) 3385088Sab196087 continue; 3395088Sab196087 break; 3405088Sab196087 case PRINT_DYN_T_RUNPATH: 3415088Sab196087 if ((dyn->d_tag != DT_RPATH) && 3425088Sab196087 (dyn->d_tag != DT_RUNPATH)) 3435088Sab196087 continue; 3445088Sab196087 break; 3455088Sab196087 } 3465088Sab196087 3475088Sab196087 /* 3485088Sab196087 * Print the information numerically, and if possible 3495088Sab196087 * as a string. 3505088Sab196087 */ 3515088Sab196087 name = NULL; 3525088Sab196087 switch (dyn->d_tag) { 3535088Sab196087 case DT_NULL: 3545088Sab196087 if (!((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) && 3555088Sab196087 (print_type == PRINT_DYN_T_ALL) && 3565088Sab196087 (dyn->d_un.d_val == 0))) 3575088Sab196087 break; 3585088Sab196087 end_ndx = ndx; 3595088Sab196087 /* 3605088Sab196087 * Special case: DT_NULLs can come in groups 3615088Sab196087 * that we prefer to reduce to a single line. 3625088Sab196087 */ 3635088Sab196087 while ((end_ndx < (argstate->dyn.num - 1)) && 3645088Sab196087 ((dyn + 1)->d_tag == DT_NULL) && 3655088Sab196087 ((dyn + 1)->d_un.d_val == 0)) { 3665088Sab196087 dyn++; 3675088Sab196087 end_ndx++; 3685088Sab196087 cnt--; 3695088Sab196087 } 3705088Sab196087 if (header_done == 0) { 3715088Sab196087 header_done = 1; 3725088Sab196087 Elf_dyn_title(0); 3735088Sab196087 } 3745088Sab196087 Elf_dyn_null_entry(0, dyn, ndx, end_ndx); 3755088Sab196087 ndx = end_ndx; 3765088Sab196087 printed = 1; 3775088Sab196087 last_d_val = dyn->d_un.d_val; 3785088Sab196087 continue; 3795088Sab196087 3805088Sab196087 /* 3815088Sab196087 * Print the information numerically, and if possible 3825088Sab196087 * as a string. 3835088Sab196087 */ 3845088Sab196087 case DT_NEEDED: 3855088Sab196087 case DT_SONAME: 3865088Sab196087 case DT_FILTER: 3875088Sab196087 case DT_AUXILIARY: 3885088Sab196087 case DT_CONFIG: 3895088Sab196087 case DT_RPATH: 3905088Sab196087 case DT_RUNPATH: 3915088Sab196087 case DT_USED: 3925088Sab196087 case DT_DEPAUDIT: 3935088Sab196087 case DT_AUDIT: 3945088Sab196087 case DT_SUNW_AUXILIARY: 3955088Sab196087 case DT_SUNW_FILTER: 3965088Sab196087 name = elfedit_offset_to_str(argstate->strsec, 3975088Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 3985088Sab196087 break; 3995088Sab196087 4005088Sab196087 case DT_FLAGS: 4015088Sab196087 name = conv_dyn_flag(dyn->d_un.d_val, 4025088Sab196087 flags_fmt_flags, &c_buf.flag); 4035088Sab196087 break; 4045088Sab196087 case DT_FLAGS_1: 4055088Sab196087 name = conv_dyn_flag1(dyn->d_un.d_val, 4065088Sab196087 flags_fmt_flags, &c_buf.flag1); 4075088Sab196087 break; 4085088Sab196087 case DT_POSFLAG_1: 4095088Sab196087 name = conv_dyn_posflag1(dyn->d_un.d_val, 4105088Sab196087 flags_fmt_flags, &c_buf.posflag1); 4115088Sab196087 break; 4125088Sab196087 case DT_FEATURE_1: 4135088Sab196087 name = conv_dyn_feature1(dyn->d_un.d_val, 4145088Sab196087 flags_fmt_flags, &c_buf.feature1); 4155088Sab196087 break; 4165088Sab196087 case DT_DEPRECATED_SPARC_REGISTER: 4175088Sab196087 name = MSG_INTL(MSG_STR_DEPRECATED); 4185088Sab196087 break; 419*6206Sab196087 case DT_SUNW_LDMACH: 420*6206Sab196087 name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0, 421*6206Sab196087 &c_buf.inv); 422*6206Sab196087 break; 4235088Sab196087 } 4245088Sab196087 4255088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 4265088Sab196087 if (header_done == 0) { 4275088Sab196087 header_done = 1; 4285088Sab196087 Elf_dyn_title(0); 4295088Sab196087 } 4305088Sab196087 if (name == NULL) 4315088Sab196087 name = MSG_ORIG(MSG_STR_EMPTY); 4325088Sab196087 Elf_dyn_entry(0, dyn, ndx, name, 4335088Sab196087 argstate->obj_state->os_ehdr->e_machine); 4345088Sab196087 } else { 4355088Sab196087 /* 4365088Sab196087 * In simple or numeric mode under a print type 4375088Sab196087 * that is based on tag type rather than on index, 4385088Sab196087 * quietly: If we've already printed this value, 4395088Sab196087 * don't print it again. A common example of this 4405088Sab196087 * is PRINT_DYN_T_RUNPATH when both DT_RPATH and 4415088Sab196087 * DT_RUNPATH are present with the same value. 4425088Sab196087 */ 4435088Sab196087 switch (print_type) { 4445088Sab196087 case PRINT_DYN_T_TAG: 4455088Sab196087 case PRINT_DYN_T_RUNPATH: 4465088Sab196087 if (printed && (last_d_val == dyn->d_un.d_val)) 4475088Sab196087 continue; 4485088Sab196087 } 4495088Sab196087 4505088Sab196087 if ((name != NULL) && 4515088Sab196087 (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) { 4525088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name); 4535088Sab196087 } else { 4545088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), 4555088Sab196087 dyn->d_un.d_val); 4565088Sab196087 } 4575088Sab196087 } 4585088Sab196087 printed = 1; 4595088Sab196087 last_d_val = dyn->d_un.d_val; 4605088Sab196087 } 4615088Sab196087 4625088Sab196087 /* 4635088Sab196087 * If nothing was output under the print types that are 4645088Sab196087 * based on tag type, issue an error saying it doesn't exist. 4655088Sab196087 */ 4665088Sab196087 if (!printed) { 4675088Sab196087 if (print_type == PRINT_DYN_T_TAG) { 4685088Sab196087 Conv_inv_buf_t inv_buf; 4695088Sab196087 4705088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 4715088Sab196087 MSG_INTL(MSG_ERR_NODYNELT), 4725088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 4735088Sab196087 argstate->dyn.sec->sec_name, conv_dyn_tag(arg, 4745088Sab196087 argstate->obj_state->os_ehdr->e_machine, 4755088Sab196087 0, &inv_buf)); 4765088Sab196087 } 4775088Sab196087 4785088Sab196087 if (print_type == PRINT_DYN_T_RUNPATH) 4795088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 4805088Sab196087 MSG_INTL(MSG_ERR_NORUNPATH), 4815088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 4825088Sab196087 argstate->dyn.sec->sec_name); 4835088Sab196087 } 4845088Sab196087 } 4855088Sab196087 4865088Sab196087 4875088Sab196087 /* 4885088Sab196087 * Process the elt argument: This will be a tag type if -dynndx is 4895088Sab196087 * not present and this is a print request. It will be an index otherwise. 4905088Sab196087 * 4915088Sab196087 * entry: 4925088Sab196087 * argstate - Argument state block 4935088Sab196087 * arg - Argument string to be converted into an index 4945088Sab196087 * argname - String giving the name by which the argument is 4955088Sab196087 * referred in the online help for the command. 4965088Sab196087 * print_request - True if the command is to print the current 4975088Sab196087 * value(s) and return without changing anything. 4985088Sab196087 * print_type - Address of variable containing PRINT_DYN_T_ 4995088Sab196087 * code specifying how the elements will be displayed. 5005088Sab196087 * 5015088Sab196087 * exit: 5025088Sab196087 * If print_request is False: arg is converted into an integer value. 5035088Sab196087 * If -dynndx was used, we convert it into an integer. If it was not 5045088Sab196087 * used, then arg is a tag name --- we find the first dynamic entry 5055088Sab196087 * that matches. If no entry matches, and there is an extra DT_NULL, 5065088Sab196087 * it is added. Otherwise an error is issued. *print_type is set 5075088Sab196087 * to PRINT_DYN_T_NDX. 5085088Sab196087 * 5095088Sab196087 * If print_request is True: If -dynndx was used, arg is converted into 5105088Sab196087 * an integer value, *print_type is set to PRINT_DYN_T_NDX, and 5115088Sab196087 * the value is returned. If -dynndx was not used, *print_type is set to 5125088Sab196087 * PRINT_DYN_T_TAG, and the tag value is returned. 5135088Sab196087 */ 5145088Sab196087 static Word 5155088Sab196087 arg_to_index(ARGSTATE *argstate, const char *arg, const char *argname, 5165088Sab196087 int print_request, PRINT_DYN_T *print_type) 5175088Sab196087 { 5185088Sab196087 Word ndx, dt_value; 5195088Sab196087 5205088Sab196087 5215088Sab196087 /* Assume we are returning an index, alter as needed below */ 5225088Sab196087 *print_type = PRINT_DYN_T_NDX; 5235088Sab196087 5245088Sab196087 /* If -dynndx was used, this is a simple numeric index */ 5255088Sab196087 if ((argstate->optmask & DYN_OPT_F_DYNNDX) != 0) 5265088Sab196087 return ((Word) elfedit_atoui_range(arg, argname, 0, 5275088Sab196087 argstate->dyn.num - 1, NULL)); 5285088Sab196087 5295088Sab196087 /* The argument is a DT_ tag type, not a numeric index */ 5305088Sab196087 dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT); 5315088Sab196087 5325088Sab196087 /* 5335088Sab196087 * If this is a printing request, then we let print_dyn() show 5345088Sab196087 * all the items with this tag type. 5355088Sab196087 */ 5365088Sab196087 if (print_request) { 5375088Sab196087 *print_type = PRINT_DYN_T_TAG; 5385088Sab196087 return (dt_value); 5395088Sab196087 } 5405088Sab196087 5415088Sab196087 /* Locate the first entry with the given tag type */ 5425088Sab196087 for (ndx = 0; ndx < argstate->dyn.num; ndx++) { 5435088Sab196087 if (argstate->dyn.data[ndx].d_tag == dt_value) { 5445088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 5455088Sab196087 MSG_INTL(MSG_DEBUG_DT2NDX), 5465088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 5475088Sab196087 argstate->dyn.sec->sec_name, EC_WORD(ndx), arg); 5485088Sab196087 return (ndx); 5495088Sab196087 } 5505088Sab196087 } 5515088Sab196087 5525088Sab196087 /* Not found. Can we create one? */ 5535088Sab196087 if (argstate->dyn.num_null_ndx > 1) 5545088Sab196087 return (convert_dt_null(argstate, dt_value, 0)); 5555088Sab196087 5565088Sab196087 /* No room to create one, so we're out of options and must fail */ 5575088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT), 5585088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 5595088Sab196087 argstate->dyn.sec->sec_name, arg); 5605088Sab196087 5615088Sab196087 /*NOTREACHED*/ 5625088Sab196087 return (0); /* For lint */ 5635088Sab196087 } 5645088Sab196087 5655088Sab196087 5665088Sab196087 /* 5675088Sab196087 * Called by cmd_body() for dyn:value. Implements the core functionality 5685088Sab196087 * for that command. 5695088Sab196087 * 5705088Sab196087 * This routine expects that both the index and value arguments are 5715088Sab196087 * present. 5725088Sab196087 */ 5735088Sab196087 static elfedit_cmdret_t 5745088Sab196087 cmd_body_value(ARGSTATE *argstate, Word *ret_ndx) 5755088Sab196087 { 5765088Sab196087 elfedit_section_t *dynsec = argstate->dyn.sec; 5775088Sab196087 elfedit_section_t *strsec = argstate->strsec; 5785088Sab196087 elfedit_dyn_elt_t strpad_elt; 5795088Sab196087 Word i; 5805088Sab196087 Dyn *dyn = argstate->dyn.data; 5815088Sab196087 Word numdyn = argstate->dyn.num; 5825088Sab196087 int minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0); 5835088Sab196087 int minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0); 5845088Sab196087 int minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX) != 0); 5855088Sab196087 Word arg1, tmp_val; 5865088Sab196087 Xword arg2; 5875088Sab196087 int arg2_known = 1; 5885088Sab196087 5895088Sab196087 5905088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 5915088Sab196087 5925088Sab196087 /* 5935088Sab196087 * The first argument is an index if -dynndx is used, and is a 5945088Sab196087 * tag value otherwise. 5955088Sab196087 */ 5965088Sab196087 arg1 = minus_dynndx ? 5975088Sab196087 elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT), 5985088Sab196087 0, numdyn - 1, NULL) : 5995088Sab196087 elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT); 6005088Sab196087 6015088Sab196087 if (minus_s) { 6025088Sab196087 /* 6035088Sab196087 * Don't allow the user to specify -s when manipulating a 6045088Sab196087 * DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to 6055088Sab196087 * manage the extra space used for strings, this would break 6065088Sab196087 * our ability to add the string. 6075088Sab196087 */ 6085088Sab196087 if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) || 6095088Sab196087 (minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD))) 6105088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 6115088Sab196087 MSG_INTL(MSG_ERR_STRPADSTRVAL), 6125088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 6135088Sab196087 6145088Sab196087 /* Locate DT_SUNW_STRPAD element if present */ 6155088Sab196087 strpad_elt.dn_dyn.d_un.d_val = 0; 6165088Sab196087 (void) elfedit_dynstr_getpad(argstate->dyn.sec, &strpad_elt); 6175088Sab196087 6185088Sab196087 /* 6195088Sab196087 * Look up the string: If the user specified the -dynndx 6205088Sab196087 * -option, then we will insert it if possible, and 6215088Sab196087 * fail with an error if not. However, if they did not 6225088Sab196087 * specify -dynndx, we want to look up the string if it is 6235088Sab196087 * already there, but defer the insertion. The reason for 6245088Sab196087 * this is that we may have to grab an unused DT_NULL element 6255088Sab196087 * below, and if there are none available, we won't want 6265088Sab196087 * to have modified the string table. 6275088Sab196087 * 6285088Sab196087 * This isn't a problem, because if the string isn't 6295088Sab196087 * in the string table, it can't be used by a dynamic element. 6305088Sab196087 * Hence, we don't need to insert it to know that there is 6315088Sab196087 * no match. 6325088Sab196087 */ 6335088Sab196087 if (minus_dynndx == 0) { 6345088Sab196087 if (elfedit_sec_findstr(strsec, 6355088Sab196087 strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1], 6365088Sab196087 &tmp_val) == 0) { 6375088Sab196087 arg2_known = 0; 6385088Sab196087 } else { 6395088Sab196087 arg2 = tmp_val; 6405088Sab196087 } 6415088Sab196087 } else { 6425088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 6435088Sab196087 &strpad_elt, argstate->argv[1]); 6445088Sab196087 } 6455088Sab196087 } else { /* Argument 2 is an integer */ 6465088Sab196087 arg2 = elfedit_atoui(argstate->argv[1], NULL); 6475088Sab196087 } 6485088Sab196087 6495088Sab196087 6505088Sab196087 if (!minus_dynndx && !(minus_add && !arg2_known)) { 6515088Sab196087 /* 6525088Sab196087 * Search the dynamic section and see if an item with the 6535088Sab196087 * specified tag value already exists. We can reduce this 6545088Sab196087 * to a simple update of an existing value if -add is not 6555088Sab196087 * specified or the existing d_un value matches the new one. 6565088Sab196087 * 6575088Sab196087 * In either of these cases, we will change arg1 to be the 6585088Sab196087 * index, and set minus_dynndx, causing the simple update to 6595088Sab196087 * happen immediately below. 6605088Sab196087 */ 6615088Sab196087 for (i = 0; i < numdyn; i++) { 6625088Sab196087 if ((dyn[i].d_tag == arg1) && 6635088Sab196087 (!minus_add || (dyn[i].d_un.d_val == arg2))) { 6645088Sab196087 arg1 = i; 6655088Sab196087 minus_dynndx = 1; 6665088Sab196087 break; 6675088Sab196087 } 6685088Sab196087 } 6695088Sab196087 } 6705088Sab196087 6715088Sab196087 /* 6725088Sab196087 * If -dynndx is used, then this is a relatively simple 6735088Sab196087 * operation, as we simply write over the specified index. 6745088Sab196087 */ 6755088Sab196087 if (minus_dynndx) { 6765088Sab196087 /* 6775088Sab196087 * If we held back from inserting a new string into 6785088Sab196087 * the dynstr above, we insert it now, because we 6795088Sab196087 * have a slot in the dynamic section, and we need 6805088Sab196087 * the string offset ot finish. 6815088Sab196087 */ 6825088Sab196087 if (!arg2_known) 6835088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 6845088Sab196087 &strpad_elt, argstate->argv[1]); 6855088Sab196087 6865088Sab196087 *ret_ndx = arg1; 6875088Sab196087 if (dyn[arg1].d_un.d_val == arg2) { 6885088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 6895088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), 6905088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 6915088Sab196087 EC_WORD(arg1), EC_XWORD(arg2)); 6925088Sab196087 return (ELFEDIT_CMDRET_NONE); 6935088Sab196087 } else { 6945088Sab196087 /* Warn if setting DT_NULL value to non-zero */ 6955088Sab196087 if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0)) 6965088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 6975088Sab196087 MSG_INTL(MSG_DEBUG_DTNULLVALUE), 6985088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 6995088Sab196087 EC_WORD(arg1), EC_XWORD(arg2)); 7005088Sab196087 7015088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 7025088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 7035088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 7045088Sab196087 EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val), 7055088Sab196087 EC_XWORD(arg2)); 7065088Sab196087 dyn[arg1].d_un.d_val = arg2; 7075088Sab196087 return (ELFEDIT_CMDRET_MOD); 7085088Sab196087 } 7095088Sab196087 } 7105088Sab196087 7115088Sab196087 /* 7125088Sab196087 * We need a new slot in the dynamic section. If we can't have 7135088Sab196087 * one, then we fail. 7145088Sab196087 */ 7155088Sab196087 if (argstate->dyn.num_null_ndx <= 1) 7165088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 7175088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 7185088Sab196087 7195088Sab196087 /* 7205088Sab196087 * If we still need to insert a new string into the dynstr, 7215088Sab196087 * then it is safe now, because if we succeed, we know that 7225088Sab196087 * there is an available slot to receive it. If we fail, we 7235088Sab196087 * haven't claimed the extra slot yet, and it will be unharmed. 7245088Sab196087 */ 7255088Sab196087 if (!arg2_known) 7265088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 7275088Sab196087 &strpad_elt, argstate->argv[1]); 7285088Sab196087 7295088Sab196087 /* Use an extra DT_NULL slot and enter the new element */ 7305088Sab196087 *ret_ndx = convert_dt_null(argstate, arg1, arg2); 7315088Sab196087 return (ELFEDIT_CMDRET_MOD); 7325088Sab196087 } 7335088Sab196087 7345088Sab196087 7355088Sab196087 7365088Sab196087 /* 7375088Sab196087 * Called by cmd_body() for dyn:runpath. Implements the core functionality 7385088Sab196087 * for that command. 7395088Sab196087 * 7405088Sab196087 * History Lesson And Strategy: 7415088Sab196087 * 7425088Sab196087 * This routine handles both DT_RPATH and DT_RUNPATH entries, altering 7435088Sab196087 * either or both if they are present. 7445088Sab196087 * 7455088Sab196087 * The original SYSV ABI only had DT_RPATH, and the runtime loader used 7465088Sab196087 * it to search for things in the following order: 7475088Sab196087 * 7485088Sab196087 * DT_RPATH, LD_LIBRARY_PATH, defaults 7495088Sab196087 * 7505088Sab196087 * Solaris did not follow this rule, an extremely rare deviation from 7515088Sab196087 * the ABI. Environment variables should supercede everything else, 7525088Sab196087 * otherwise they are not very useful. This decision was made at the 7535088Sab196087 * very beginning of the SunOS 5.x development, so we have always 7545088Sab196087 * deviated from the ABI and and instead search in the order 7555088Sab196087 * 7565088Sab196087 * LD_LIBRARY_PATH, DT_RPATH, defaults 7575088Sab196087 * 7585088Sab196087 * Other Unix variants initially followed the ABI, but in recent years 7595088Sab196087 * have come to agree with the early Solaris folks that it was a mistake. 7605088Sab196087 * Hence, DT_RUNPATH was invented, with the search order: 7615088Sab196087 * 7625088Sab196087 * LD_LIBRARY_PATH, DT_RUNPATH, defaults 7635088Sab196087 * 7645088Sab196087 * So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both 7655088Sab196087 * are present (which does happen), we set them both to the new 7665088Sab196087 * value. If either one is present, we set that one. If neither is 7675088Sab196087 * present, and we have a spare DT_NULL slot, we create a DT_RUNPATH, but 7685088Sab196087 * not a DT_RPATH, to conserve available slots for other uses. 7695088Sab196087 */ 7705088Sab196087 static elfedit_cmdret_t 7715088Sab196087 cmd_body_runpath(ARGSTATE *argstate) 7725088Sab196087 { 7735088Sab196087 elfedit_section_t *dynsec = argstate->dyn.sec; 7745088Sab196087 elfedit_section_t *strsec = argstate->strsec; 7755088Sab196087 elfedit_dyn_elt_t rpath_elt; 7765088Sab196087 elfedit_dyn_elt_t runpath_elt; 7775088Sab196087 elfedit_dyn_elt_t strpad_elt; 7785088Sab196087 Word i; 7795088Sab196087 Dyn *dyn = argstate->dyn.data; 7805088Sab196087 Word numdyn = argstate->dyn.num; 7815088Sab196087 7825088Sab196087 /* Go through the tags and gather what we need */ 7835088Sab196087 elfedit_dyn_elt_init(&rpath_elt); 7845088Sab196087 elfedit_dyn_elt_init(&runpath_elt); 7855088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 7865088Sab196087 for (i = 0; i < numdyn; i++) { 7875088Sab196087 switch (dyn[i].d_tag) { 7885088Sab196087 case DT_RPATH: 7895088Sab196087 elfedit_dyn_elt_save(&rpath_elt, i, &dyn[i]); 7905088Sab196087 break; 7915088Sab196087 7925088Sab196087 case DT_RUNPATH: 7935088Sab196087 elfedit_dyn_elt_save(&runpath_elt, i, &dyn[i]); 7945088Sab196087 break; 7955088Sab196087 7965088Sab196087 case DT_SUNW_STRPAD: 7975088Sab196087 elfedit_dyn_elt_save(&strpad_elt, i, &dyn[i]); 7985088Sab196087 break; 7995088Sab196087 } 8005088Sab196087 } 8015088Sab196087 8025088Sab196087 /* Do we have an available dynamic section entry to use? */ 8035088Sab196087 if (rpath_elt.dn_seen || runpath_elt.dn_seen) { 8045088Sab196087 /* 8055088Sab196087 * We have seen a DT_RPATH, or a DT_RUNPATH, or both. 8065088Sab196087 * If all of these have the same string as the desired 8075088Sab196087 * new value, then we don't need to alter anything and can 8085088Sab196087 * simply return. Otherwise, we'll modify them all to have 8095088Sab196087 * the new string (below). 8105088Sab196087 */ 8115088Sab196087 if ((!rpath_elt.dn_seen || 8125088Sab196087 (strcmp(elfedit_dyn_offset_to_str(strsec, &rpath_elt), 8135088Sab196087 argstate->argv[0]) == 0)) && 8145088Sab196087 (!runpath_elt.dn_seen || 8155088Sab196087 (strcmp(elfedit_dyn_offset_to_str(strsec, &runpath_elt), 8165088Sab196087 argstate->argv[0]) == 0))) { 8175088Sab196087 if (rpath_elt.dn_seen) 8185088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8195088Sab196087 MSG_INTL(MSG_DEBUG_OLDRPATHOK), 8205088Sab196087 EC_WORD(dynsec->sec_shndx), 8215088Sab196087 dynsec->sec_name, EC_WORD(rpath_elt.dn_ndx), 8225088Sab196087 elfedit_atoconst_value_to_str( 8235088Sab196087 ELFEDIT_CONST_DT, DT_RPATH, 1)); 8245088Sab196087 if (runpath_elt.dn_seen) 8255088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8265088Sab196087 MSG_INTL(MSG_DEBUG_OLDRPATHOK), 8275088Sab196087 EC_WORD(dynsec->sec_shndx), 8285088Sab196087 dynsec->sec_name, 8295088Sab196087 EC_WORD(runpath_elt.dn_ndx), 8305088Sab196087 elfedit_atoconst_value_to_str( 8315088Sab196087 ELFEDIT_CONST_DT, DT_RUNPATH, 1)); 8325088Sab196087 return (ELFEDIT_CMDRET_NONE); 8335088Sab196087 } 8345088Sab196087 } else if (argstate->dyn.num_null_ndx <= 1) { 8355088Sab196087 /* 8365088Sab196087 * There is no DT_RPATH or DT_RUNPATH in the dynamic array, 8375088Sab196087 * and there are no extra DT_NULL entries that we can 8385088Sab196087 * convert into one. We cannot proceed. 8395088Sab196087 */ 8405088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 8415088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 8425088Sab196087 } 8435088Sab196087 8445088Sab196087 /* Does the string exist in the table already, or can we add it? */ 8455088Sab196087 rpath_elt.dn_dyn.d_un.d_val = runpath_elt.dn_dyn.d_un.d_val = 8465088Sab196087 elfedit_dynstr_insert(dynsec, strsec, &strpad_elt, 8475088Sab196087 argstate->argv[0]); 8485088Sab196087 8495088Sab196087 /* Update DT_RPATH entry if present */ 8505088Sab196087 if (rpath_elt.dn_seen) { 8515088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_PREVRPATH), 8525088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 8535088Sab196087 EC_WORD(rpath_elt.dn_ndx), 8545088Sab196087 elfedit_atoconst_value_to_str( 8555088Sab196087 ELFEDIT_CONST_DT, DT_RPATH, 1), 8565088Sab196087 elfedit_dyn_offset_to_str(strsec, &rpath_elt)); 8575088Sab196087 dyn[rpath_elt.dn_ndx] = rpath_elt.dn_dyn; 8585088Sab196087 } 8595088Sab196087 8605088Sab196087 /* 8615088Sab196087 * Update the DT_RUNPATH entry in the dynamic section, if present. 8625088Sab196087 * If one is not present, and there is also no DT_RPATH, then 8635088Sab196087 * we use a spare DT_NULL entry to create a new DT_RUNPATH. 8645088Sab196087 */ 8655088Sab196087 if (runpath_elt.dn_seen || !rpath_elt.dn_seen) { 8665088Sab196087 if (runpath_elt.dn_seen) { 8675088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8685088Sab196087 MSG_INTL(MSG_DEBUG_PREVRPATH), 8695088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 8705088Sab196087 EC_WORD(runpath_elt.dn_ndx), 8715088Sab196087 elfedit_atoconst_value_to_str( 8725088Sab196087 ELFEDIT_CONST_DT, DT_RUNPATH, 1), 8735088Sab196087 elfedit_dyn_offset_to_str(strsec, &runpath_elt)); 8745088Sab196087 dyn[runpath_elt.dn_ndx] = runpath_elt.dn_dyn; 8755088Sab196087 } else { /* Using a spare DT_NULL entry */ 8765088Sab196087 (void) convert_dt_null(argstate, DT_RUNPATH, 8775088Sab196087 runpath_elt.dn_dyn.d_un.d_val); 8785088Sab196087 } 8795088Sab196087 } 8805088Sab196087 8815088Sab196087 return (ELFEDIT_CMDRET_MOD); 8825088Sab196087 } 8835088Sab196087 8845088Sab196087 8855088Sab196087 8865088Sab196087 /* 8875088Sab196087 * Argument processing for the bitmask commands. Convert the arguments 8885088Sab196087 * to integer form, apply -and/-cmp/-or, and return the resulting value. 8895088Sab196087 * 8905088Sab196087 * entry: 8915088Sab196087 * argstate - Argument state block 8925088Sab196087 * orig - Value of original bitmask 8935088Sab196087 * const_type - ELFEDIT_CONST_* value for type of constants 8945088Sab196087 */ 8955088Sab196087 static Word 8965088Sab196087 flag_bitop(ARGSTATE *argstate, Word orig, elfedit_const_t const_type) 8975088Sab196087 { 8985088Sab196087 Word flags = 0; 8995088Sab196087 int i; 9005088Sab196087 9015088Sab196087 /* Collect the arguments */ 9025088Sab196087 for (i = 0; i < argstate->argc; i++) 9035088Sab196087 flags |= (Word) elfedit_atoconst(argstate->argv[i], const_type); 9045088Sab196087 9055088Sab196087 /* Complement the value? */ 9065088Sab196087 if (argstate->optmask & DYN_OPT_F_CMP) 9075088Sab196087 flags = ~flags; 9085088Sab196087 9095088Sab196087 /* Perform any requested bit operations */ 9105088Sab196087 if (argstate->optmask & DYN_OPT_F_AND) 9115088Sab196087 flags &= orig; 9125088Sab196087 else if (argstate->optmask & DYN_OPT_F_OR) 9135088Sab196087 flags |= orig; 9145088Sab196087 9155088Sab196087 return (flags); 9165088Sab196087 } 9175088Sab196087 9185088Sab196087 9195088Sab196087 9205088Sab196087 /* 9215088Sab196087 * Common body for the dyn: module commands. These commands 9225088Sab196087 * share a large amount of common behavior, so it is convenient 9235088Sab196087 * to centralize things and use the cmd argument to handle the 9245088Sab196087 * small differences. 9255088Sab196087 * 9265088Sab196087 * entry: 9275088Sab196087 * cmd - One of the DYN_CMD_T_* constants listed above, specifying 9285088Sab196087 * which command to implement. 9295088Sab196087 * obj_state, argc, argv - Standard command arguments 9305088Sab196087 */ 9315088Sab196087 static elfedit_cmdret_t 9325088Sab196087 cmd_body(DYN_CMD_T cmd, elfedit_obj_state_t *obj_state, 9335088Sab196087 int argc, const char *argv[]) 9345088Sab196087 { 9355088Sab196087 ARGSTATE argstate; 9365088Sab196087 Dyn *dyn; 9375088Sab196087 const char *dyn_name; 9385088Sab196087 Word dyn_ndx, dyn_num, null_ndx; 9395088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 9405088Sab196087 PRINT_DYN_T print_type = PRINT_DYN_T_ALL; 9415088Sab196087 Word ndx; 9425088Sab196087 int print_only = 0; 9435088Sab196087 int do_autoprint = 1; 9445088Sab196087 9455088Sab196087 /* Process the optional arguments */ 9465088Sab196087 process_args(obj_state, argc, argv, &argstate); 9475088Sab196087 9485088Sab196087 dyn = argstate.dyn.data; 9495088Sab196087 dyn_num = argstate.dyn.num; 9505088Sab196087 dyn_name = argstate.dyn.sec->sec_name; 9515088Sab196087 dyn_ndx = argstate.dyn.sec->sec_shndx; 9525088Sab196087 9535088Sab196087 /* Check number of arguments, gather information */ 9545088Sab196087 switch (cmd) { 9555088Sab196087 case DYN_CMD_T_DUMP: 9565088Sab196087 /* dyn:dump can accept an optional index argument */ 9575088Sab196087 if (argstate.argc > 1) 9585088Sab196087 elfedit_command_usage(); 9595088Sab196087 print_only = 1; 9605088Sab196087 if (argstate.argc == 1) 9615088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 9625088Sab196087 MSG_ORIG(MSG_STR_ELT), print_only, &print_type); 9635088Sab196087 break; 9645088Sab196087 9655088Sab196087 case DYN_CMD_T_TAG: 9665088Sab196087 print_only = (argstate.argc != 2); 9675088Sab196087 if (argstate.argc > 0) { 9685088Sab196087 if (argstate.argc > 2) 9695088Sab196087 elfedit_command_usage(); 9705088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 9715088Sab196087 MSG_ORIG(MSG_STR_ELT), print_only, &print_type); 9725088Sab196087 } 9735088Sab196087 break; 9745088Sab196087 9755088Sab196087 case DYN_CMD_T_VALUE: 9765088Sab196087 print_only = (argstate.argc != 2); 9775088Sab196087 if (argstate.argc > 2) 9785088Sab196087 elfedit_command_usage(); 9795088Sab196087 if (argstate.argc > 0) { 9805088Sab196087 if (print_only) { 9815088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 9825088Sab196087 MSG_ORIG(MSG_STR_ELT), 9835088Sab196087 print_only, &print_type); 9845088Sab196087 } else { 9855088Sab196087 print_type = PRINT_DYN_T_NDX; 9865088Sab196087 } 9875088Sab196087 } 9885088Sab196087 break; 9895088Sab196087 9905088Sab196087 case DYN_CMD_T_DELETE: 9915088Sab196087 if ((argstate.argc < 1) || (argstate.argc > 2)) 9925088Sab196087 elfedit_command_usage(); 9935088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 9945088Sab196087 MSG_ORIG(MSG_STR_ELT), 9955088Sab196087 0, &print_type); 9965088Sab196087 do_autoprint = 0; 9975088Sab196087 break; 9985088Sab196087 9995088Sab196087 case DYN_CMD_T_MOVE: 10005088Sab196087 if ((argstate.argc < 2) || (argstate.argc > 3)) 10015088Sab196087 elfedit_command_usage(); 10025088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 10035088Sab196087 MSG_ORIG(MSG_STR_ELT), 0, &print_type); 10045088Sab196087 do_autoprint = 0; 10055088Sab196087 break; 10065088Sab196087 10075088Sab196087 case DYN_CMD_T_RUNPATH: 10085088Sab196087 if (argstate.argc > 1) 10095088Sab196087 elfedit_command_usage(); 10105088Sab196087 /* 10115088Sab196087 * dyn:runpath does not accept an explicit index 10125088Sab196087 * argument, so we implicitly only show the DT_RPATH and 10135088Sab196087 * DT_RUNPATH elements. 10145088Sab196087 */ 10155088Sab196087 print_type = PRINT_DYN_T_RUNPATH; 10165088Sab196087 print_only = (argstate.argc == 0); 10175088Sab196087 break; 10185088Sab196087 10195088Sab196087 case DYN_CMD_T_POSFLAG1: 10205088Sab196087 print_only = (argstate.argc == 0); 10215088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 10225088Sab196087 ELFEDIT_CONST_DT, DT_POSFLAG_1, 1), 10235088Sab196087 MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); 10245088Sab196087 break; 10255088Sab196087 10265088Sab196087 case DYN_CMD_T_FLAGS: 10275088Sab196087 print_only = (argstate.argc == 0); 10285088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 10295088Sab196087 ELFEDIT_CONST_DT, DT_FLAGS, 1), 10305088Sab196087 MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); 10315088Sab196087 break; 10325088Sab196087 10335088Sab196087 case DYN_CMD_T_FLAGS1: 10345088Sab196087 print_only = (argstate.argc == 0); 10355088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 10365088Sab196087 ELFEDIT_CONST_DT, DT_FLAGS_1, 1), 10375088Sab196087 MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); 10385088Sab196087 break; 10395088Sab196087 10405088Sab196087 case DYN_CMD_T_FEATURE1: 10415088Sab196087 print_only = (argstate.argc == 0); 10425088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 10435088Sab196087 ELFEDIT_CONST_DT, DT_FEATURE_1, 1), 10445088Sab196087 MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); 10455088Sab196087 break; 10465088Sab196087 10475088Sab196087 case DYN_CMD_T_CHECKSUM: 10485088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 10495088Sab196087 ELFEDIT_CONST_DT, DT_CHECKSUM, 1), 10505088Sab196087 MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); 10515088Sab196087 break; 10525088Sab196087 1053*6206Sab196087 case DYN_CMD_T_SUNW_LDMACH: 1054*6206Sab196087 if (argstate.argc > 1) 1055*6206Sab196087 elfedit_command_usage(); 1056*6206Sab196087 print_only = (argstate.argc == 0); 1057*6206Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1058*6206Sab196087 ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1), 1059*6206Sab196087 MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); 1060*6206Sab196087 break; 1061*6206Sab196087 10625088Sab196087 default: 10635088Sab196087 /* Note expected: All commands should have been caught above */ 10645088Sab196087 elfedit_command_usage(); 10655088Sab196087 break; 10665088Sab196087 } 10675088Sab196087 10685088Sab196087 10695088Sab196087 /* If this is a request to print current values, do it and return */ 10705088Sab196087 if (print_only) { 10715088Sab196087 print_dyn(cmd, 0, &argstate, print_type, ndx); 10725088Sab196087 return (ELFEDIT_CMDRET_NONE); 10735088Sab196087 } 10745088Sab196087 10755088Sab196087 10765088Sab196087 switch (cmd) { 10775088Sab196087 /* 10785088Sab196087 * DYN_CMD_T_DUMP can't get here: It is a print-only 10795088Sab196087 * command. 10805088Sab196087 */ 10815088Sab196087 10825088Sab196087 case DYN_CMD_T_TAG: 10835088Sab196087 { 10845088Sab196087 Conv_inv_buf_t inv_buf1, inv_buf2; 10855088Sab196087 Half mach = argstate.obj_state->os_ehdr->e_machine; 10865088Sab196087 Word d_tag = (Word) elfedit_atoconst(argstate.argv[1], 10875088Sab196087 ELFEDIT_CONST_DT); 10885088Sab196087 10895088Sab196087 if (dyn[ndx].d_tag == d_tag) { 10905088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 10915088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), 10925088Sab196087 dyn_ndx, 10935088Sab196087 dyn_name, EC_WORD(ndx), 10945088Sab196087 conv_dyn_tag(d_tag, mach, 0, &inv_buf1)); 10955088Sab196087 } else { 10965088Sab196087 Word orig_d_tag = dyn[ndx].d_tag; 10975088Sab196087 10985088Sab196087 ret = ELFEDIT_CMDRET_MOD; 10995088Sab196087 dyn[ndx].d_tag = d_tag; 11005088Sab196087 11015088Sab196087 /* 11025088Sab196087 * Update null termination index. Warn if we 11035088Sab196087 * just clobbered the only DT_NULL termination 11045088Sab196087 * for the array. 11055088Sab196087 */ 11065088Sab196087 null_ndx = argstate.dyn.null_ndx; 11075088Sab196087 set_null_ndx(&argstate); 11085088Sab196087 if ((argstate.dyn.null_ndx >= 11095088Sab196087 argstate.dyn.num) && 11105088Sab196087 (null_ndx != argstate.dyn.null_ndx)) 11115088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 11125088Sab196087 MSG_INTL(MSG_DEBUG_NULLTERM), 11135088Sab196087 dyn_ndx, dyn_name, 11145088Sab196087 EC_WORD(ndx), 11155088Sab196087 conv_dyn_tag(d_tag, mach, 11165088Sab196087 0, &inv_buf1)); 11175088Sab196087 11185088Sab196087 /* 11195088Sab196087 * Warning if 11205088Sab196087 * - Inserting a DT_NULL cuts off following 11215088Sab196087 * non-null elements. 11225088Sab196087 * - Inserting a non-DT_NULL after the 11235088Sab196087 * first null element, will be 11245088Sab196087 * ignored by rtld. 11255088Sab196087 */ 11265088Sab196087 if (d_tag == DT_NULL) { 11275088Sab196087 if ((ndx + 1) < null_ndx) 11285088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 11295088Sab196087 MSG_INTL(MSG_DEBUG_NULCLIP), 11305088Sab196087 dyn_ndx, dyn_name, 11315088Sab196087 EC_WORD(ndx), 11325088Sab196087 conv_dyn_tag(d_tag, mach, 11335088Sab196087 0, &inv_buf1)); 11345088Sab196087 } else { 11355088Sab196087 if ((ndx + 1) > argstate.dyn.null_ndx) 11365088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 11375088Sab196087 MSG_INTL(MSG_DEBUG_NULHIDE), 11385088Sab196087 dyn_ndx, dyn_name, 11395088Sab196087 EC_WORD(ndx), 11405088Sab196087 conv_dyn_tag(d_tag, mach, 11415088Sab196087 0, &inv_buf1)); 11425088Sab196087 } 11435088Sab196087 11445088Sab196087 /* Debug message that we changed it */ 11455088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 11465088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 11475088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 11485088Sab196087 conv_dyn_tag(orig_d_tag, mach, 0, 11495088Sab196087 &inv_buf1), 11505088Sab196087 conv_dyn_tag(d_tag, mach, 0, &inv_buf2)); 11515088Sab196087 } 11525088Sab196087 } 11535088Sab196087 break; 11545088Sab196087 11555088Sab196087 case DYN_CMD_T_VALUE: 11565088Sab196087 ret = cmd_body_value(&argstate, &ndx); 11575088Sab196087 break; 11585088Sab196087 11595088Sab196087 case DYN_CMD_T_DELETE: 11605088Sab196087 { 11615088Sab196087 Word cnt = (argstate.argc == 1) ? 1 : 11625088Sab196087 (Word) elfedit_atoui_range(argstate.argv[1], 11635088Sab196087 MSG_ORIG(MSG_STR_COUNT), 1, dyn_num - ndx, NULL); 11645088Sab196087 const char *msg_prefix = 11655088Sab196087 elfedit_sec_msgprefix(argstate.dyn.sec); 11665088Sab196087 11675088Sab196087 elfedit_array_elts_delete(msg_prefix, argstate.dyn.data, 11685088Sab196087 sizeof (Dyn), dyn_num, ndx, cnt); 11695088Sab196087 ret = ELFEDIT_CMDRET_MOD; 11705088Sab196087 } 11715088Sab196087 break; 11725088Sab196087 11735088Sab196087 case DYN_CMD_T_MOVE: 11745088Sab196087 { 11755088Sab196087 Dyn save; 11765088Sab196087 Word cnt; 11775088Sab196087 Word dstndx; 11785088Sab196087 const char *msg_prefix = 11795088Sab196087 elfedit_sec_msgprefix(argstate.dyn.sec); 11805088Sab196087 11815088Sab196087 dstndx = (Word) 11825088Sab196087 elfedit_atoui_range(argstate.argv[1], 11835088Sab196087 MSG_ORIG(MSG_STR_DST_INDEX), 0, dyn_num - 1, 11845088Sab196087 NULL); 11855088Sab196087 if (argstate.argc == 2) { 11865088Sab196087 cnt = 1; 11875088Sab196087 } else { 11885088Sab196087 cnt = (Word) elfedit_atoui_range( 11895088Sab196087 argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), 11905088Sab196087 1, dyn_num, NULL); 11915088Sab196087 } 11925088Sab196087 elfedit_array_elts_move(msg_prefix, argstate.dyn.data, 11935088Sab196087 sizeof (save), dyn_num, ndx, dstndx, cnt, &save); 11945088Sab196087 ret = ELFEDIT_CMDRET_MOD; 11955088Sab196087 } 11965088Sab196087 break; 11975088Sab196087 11985088Sab196087 11995088Sab196087 case DYN_CMD_T_RUNPATH: 12005088Sab196087 ret = cmd_body_runpath(&argstate); 12015088Sab196087 break; 12025088Sab196087 12035088Sab196087 case DYN_CMD_T_POSFLAG1: 12045088Sab196087 { 12055088Sab196087 Conv_dyn_posflag1_buf_t buf1, buf2; 12065088Sab196087 Word flags; 12075088Sab196087 12085088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 12095088Sab196087 ELFEDIT_CONST_DF_P1); 12105088Sab196087 12115088Sab196087 /* Set the value */ 12125088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 12135088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12145088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 12155088Sab196087 dyn_name, EC_WORD(ndx), 12165088Sab196087 conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 12175088Sab196087 &buf1)); 12185088Sab196087 } else { 12195088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12205088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 12215088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 12225088Sab196087 conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 12235088Sab196087 &buf1), 12245088Sab196087 conv_dyn_posflag1(flags, 0, &buf2)); 12255088Sab196087 ret = ELFEDIT_CMDRET_MOD; 12265088Sab196087 dyn[ndx].d_un.d_val = flags; 12275088Sab196087 } 12285088Sab196087 } 12295088Sab196087 break; 12305088Sab196087 12315088Sab196087 case DYN_CMD_T_FLAGS: 12325088Sab196087 { 12335088Sab196087 Conv_dyn_flag_buf_t buf1, buf2; 12345088Sab196087 Word flags; 12355088Sab196087 12365088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 12375088Sab196087 ELFEDIT_CONST_DF); 12385088Sab196087 12395088Sab196087 /* Set the value */ 12405088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 12415088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12425088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 12435088Sab196087 dyn_name, EC_WORD(ndx), 12445088Sab196087 conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 12455088Sab196087 &buf1)); 12465088Sab196087 } else { 12475088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12485088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 12495088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 12505088Sab196087 conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 12515088Sab196087 &buf1), 12525088Sab196087 conv_dyn_flag(flags, 0, &buf2)); 12535088Sab196087 ret = ELFEDIT_CMDRET_MOD; 12545088Sab196087 dyn[ndx].d_un.d_val = flags; 12555088Sab196087 } 12565088Sab196087 } 12575088Sab196087 break; 12585088Sab196087 12595088Sab196087 case DYN_CMD_T_FLAGS1: 12605088Sab196087 { 12615088Sab196087 Conv_dyn_flag1_buf_t buf1, buf2; 12625088Sab196087 Word flags1; 12635088Sab196087 12645088Sab196087 flags1 = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 12655088Sab196087 ELFEDIT_CONST_DF_1); 12665088Sab196087 12675088Sab196087 /* Set the value */ 12685088Sab196087 if (dyn[ndx].d_un.d_val == flags1) { 12695088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12705088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 12715088Sab196087 dyn_name, EC_WORD(ndx), 12725088Sab196087 conv_dyn_flag1(dyn[ndx].d_un.d_val, 12735088Sab196087 0, &buf1)); 12745088Sab196087 } else { 12755088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12765088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 12775088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 12785088Sab196087 conv_dyn_flag1(dyn[ndx].d_un.d_val, 12795088Sab196087 0, &buf1), 12805088Sab196087 conv_dyn_flag1(flags1, 0, &buf2)); 12815088Sab196087 ret = ELFEDIT_CMDRET_MOD; 12825088Sab196087 dyn[ndx].d_un.d_val = flags1; 12835088Sab196087 } 12845088Sab196087 } 12855088Sab196087 break; 12865088Sab196087 12875088Sab196087 case DYN_CMD_T_FEATURE1: 12885088Sab196087 { 12895088Sab196087 Conv_dyn_feature1_buf_t buf1, buf2; 12905088Sab196087 Word flags; 12915088Sab196087 12925088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 12935088Sab196087 ELFEDIT_CONST_DTF_1); 12945088Sab196087 12955088Sab196087 /* Set the value */ 12965088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 12975088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 12985088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 12995088Sab196087 dyn_name, EC_WORD(ndx), 13005088Sab196087 conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 13015088Sab196087 &buf1)); 13025088Sab196087 } else { 13035088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13045088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 13055088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 13065088Sab196087 conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 13075088Sab196087 &buf1), 13085088Sab196087 conv_dyn_feature1(flags, 0, &buf2)); 13095088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13105088Sab196087 dyn[ndx].d_un.d_val = flags; 13115088Sab196087 } 13125088Sab196087 } 13135088Sab196087 break; 13145088Sab196087 13155088Sab196087 case DYN_CMD_T_CHECKSUM: 13165088Sab196087 { 13175088Sab196087 long checksum = elf_checksum(obj_state->os_elf); 13185088Sab196087 13195088Sab196087 /* Set the value */ 13205088Sab196087 if (dyn[ndx].d_un.d_val == checksum) { 13215088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13225088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), dyn_ndx, 13235088Sab196087 dyn_name, EC_WORD(ndx), EC_XWORD(checksum)); 13245088Sab196087 } else { 13255088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13265088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 13275088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 13285088Sab196087 EC_XWORD(dyn[ndx].d_un.d_val), 13295088Sab196087 EC_XWORD(checksum)); 13305088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13315088Sab196087 dyn[ndx].d_un.d_val = checksum; 13325088Sab196087 } 13335088Sab196087 13345088Sab196087 } 1335*6206Sab196087 break; 1336*6206Sab196087 1337*6206Sab196087 case DYN_CMD_T_SUNW_LDMACH: 1338*6206Sab196087 { 1339*6206Sab196087 Conv_inv_buf_t buf1, buf2; 1340*6206Sab196087 Half ldmach; 1341*6206Sab196087 1342*6206Sab196087 ldmach = (Half) elfedit_atoconst(argstate.argv[0], 1343*6206Sab196087 ELFEDIT_CONST_EM); 1344*6206Sab196087 1345*6206Sab196087 /* Set the value */ 1346*6206Sab196087 if (dyn[ndx].d_un.d_val == ldmach) { 1347*6206Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 1348*6206Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1349*6206Sab196087 dyn_name, EC_WORD(ndx), 1350*6206Sab196087 conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 1351*6206Sab196087 &buf1)); 1352*6206Sab196087 } else { 1353*6206Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 1354*6206Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 1355*6206Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 1356*6206Sab196087 conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 1357*6206Sab196087 &buf1), 1358*6206Sab196087 conv_ehdr_mach(ldmach, 0, &buf2)); 1359*6206Sab196087 ret = ELFEDIT_CMDRET_MOD; 1360*6206Sab196087 dyn[ndx].d_un.d_val = ldmach; 1361*6206Sab196087 } 1362*6206Sab196087 } 1363*6206Sab196087 break; 1364*6206Sab196087 13655088Sab196087 } 13665088Sab196087 13675088Sab196087 /* 13685088Sab196087 * If we modified the dynamic section header, tell libelf. 13695088Sab196087 */ 13705088Sab196087 if (ret == ELFEDIT_CMDRET_MOD) 13715088Sab196087 elfedit_modified_data(argstate.dyn.sec); 13725088Sab196087 13735088Sab196087 /* Do autoprint */ 13745088Sab196087 if (do_autoprint) 13755088Sab196087 print_dyn(cmd, 1, &argstate, print_type, ndx); 13765088Sab196087 13775088Sab196087 return (ret); 13785088Sab196087 } 13795088Sab196087 13805088Sab196087 13815088Sab196087 13825088Sab196087 /* 13835088Sab196087 * Command completion functions for the commands 13845088Sab196087 */ 13855088Sab196087 13865088Sab196087 /* 13875088Sab196087 * Command completion for the first argument, which specifies 13885088Sab196087 * the dynamic element to use. Examines the options to see if 13895088Sab196087 * -dynndx is present, and if not, supplies the completion 13905088Sab196087 * strings for argument 1. 13915088Sab196087 */ 13925088Sab196087 /*ARGSUSED*/ 13935088Sab196087 static void 13945088Sab196087 cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 13955088Sab196087 const char *argv[], int num_opt) 13965088Sab196087 { 13975088Sab196087 elfedit_section_t *cache; 13985088Sab196087 Dyn *dyn; 13995088Sab196087 Word i; 14005088Sab196087 const char *s; 14015088Sab196087 char *s2; 14025088Sab196087 char buf[128]; 14035088Sab196087 14045088Sab196087 /* Make sure it's the first argument */ 14055088Sab196087 if ((argc - num_opt) != 1) 14065088Sab196087 return; 14075088Sab196087 14085088Sab196087 /* Is -dynndx present? If so, we don't complete tag types */ 14095088Sab196087 for (i = 0; i < num_opt; i++) 14105088Sab196087 if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0) 14115088Sab196087 return; 14125088Sab196087 14135088Sab196087 /* 14145088Sab196087 * If there is no object, or if there is no dynamic section, 14155088Sab196087 * then supply all possible names. 14165088Sab196087 */ 14175088Sab196087 if ((obj_state == NULL) || (obj_state->os_dynndx == SHN_UNDEF)) { 14185088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 14195088Sab196087 return; 14205088Sab196087 } 14215088Sab196087 14225088Sab196087 /* Supply completions for the tags present in the dynamic section */ 14235088Sab196087 cache = &obj_state->os_secarr[obj_state->os_dynndx]; 14245088Sab196087 dyn = (Dyn *) cache->sec_data->d_buf; 14255088Sab196087 i = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize; 14265088Sab196087 for (; i-- > 0; dyn++) { 14275088Sab196087 s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_DT, 14285088Sab196087 dyn->d_tag, 0); 14295088Sab196087 if (s == NULL) 14305088Sab196087 continue; 14315088Sab196087 elfedit_cpl_match(cpldata, s, 1); 14325088Sab196087 14335088Sab196087 /* 14345088Sab196087 * To get the informal tag names that are lowercase 14355088Sab196087 * and lack the leading DT_, we copy the string we 14365088Sab196087 * have into a buffer and process it. 14375088Sab196087 */ 14385088Sab196087 if (strlen(s) < 3) 14395088Sab196087 continue; 14405088Sab196087 (void) strlcpy(buf, s + 3, sizeof (buf)); 14415088Sab196087 for (s2 = buf; *s2 != '\0'; s2++) 14425088Sab196087 if (isupper(*s2)) 14435088Sab196087 *s2 = tolower(*s2); 14445088Sab196087 elfedit_cpl_match(cpldata, buf, 1); 14455088Sab196087 } 14465088Sab196087 } 14475088Sab196087 14485088Sab196087 14495088Sab196087 /*ARGSUSED*/ 14505088Sab196087 static void 14515088Sab196087 cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 14525088Sab196087 const char *argv[], int num_opt) 14535088Sab196087 { 14545088Sab196087 /* First argument */ 14555088Sab196087 if ((argc - num_opt) == 1) { 14565088Sab196087 cpl_eltarg(obj_state, cpldata, argc, argv, num_opt); 14575088Sab196087 return; 14585088Sab196087 } 14595088Sab196087 14605088Sab196087 /* The second argument is always a tag value */ 14615088Sab196087 if ((argc - num_opt) == 2) 14625088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 14635088Sab196087 } 14645088Sab196087 14655088Sab196087 /*ARGSUSED*/ 14665088Sab196087 static void 14675088Sab196087 cpl_posflag1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 14685088Sab196087 const char *argv[], int num_opt) 14695088Sab196087 { 14705088Sab196087 /* This routine allows multiple flags to be specified */ 14715088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_P1); 14725088Sab196087 } 14735088Sab196087 14745088Sab196087 /*ARGSUSED*/ 14755088Sab196087 static void 14765088Sab196087 cpl_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 14775088Sab196087 const char *argv[], int num_opt) 14785088Sab196087 { 14795088Sab196087 /* This routine allows multiple flags to be specified */ 14805088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF); 14815088Sab196087 } 14825088Sab196087 14835088Sab196087 /*ARGSUSED*/ 14845088Sab196087 static void 14855088Sab196087 cpl_flags1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 14865088Sab196087 const char *argv[], int num_opt) 14875088Sab196087 { 14885088Sab196087 /* This routine allows multiple flags to be specified */ 14895088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_1); 14905088Sab196087 } 14915088Sab196087 14925088Sab196087 /*ARGSUSED*/ 14935088Sab196087 static void 14945088Sab196087 cpl_feature1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 14955088Sab196087 const char *argv[], int num_opt) 14965088Sab196087 { 14975088Sab196087 /* This routine allows multiple flags to be specified */ 14985088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1); 14995088Sab196087 } 15005088Sab196087 1501*6206Sab196087 /*ARGSUSED*/ 1502*6206Sab196087 static void 1503*6206Sab196087 cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1504*6206Sab196087 const char *argv[], int num_opt) 1505*6206Sab196087 { 1506*6206Sab196087 /* 1507*6206Sab196087 * This command doesn't accept options, so num_opt should be 1508*6206Sab196087 * 0. This is a defensive measure, in case that should change. 1509*6206Sab196087 */ 1510*6206Sab196087 argc -= num_opt; 1511*6206Sab196087 argv += num_opt; 1512*6206Sab196087 1513*6206Sab196087 if (argc == 1) 1514*6206Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM); 1515*6206Sab196087 } 1516*6206Sab196087 15175088Sab196087 15185088Sab196087 /* 15195088Sab196087 * Implementation functions for the commands 15205088Sab196087 */ 15215088Sab196087 static elfedit_cmdret_t 15225088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15235088Sab196087 { 15245088Sab196087 return (cmd_body(DYN_CMD_T_DUMP, obj_state, argc, argv)); 15255088Sab196087 } 15265088Sab196087 15275088Sab196087 static elfedit_cmdret_t 15285088Sab196087 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15295088Sab196087 { 15305088Sab196087 return (cmd_body(DYN_CMD_T_TAG, obj_state, argc, argv)); 15315088Sab196087 } 15325088Sab196087 15335088Sab196087 static elfedit_cmdret_t 15345088Sab196087 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15355088Sab196087 { 15365088Sab196087 return (cmd_body(DYN_CMD_T_VALUE, obj_state, argc, argv)); 15375088Sab196087 } 15385088Sab196087 15395088Sab196087 static elfedit_cmdret_t 15405088Sab196087 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15415088Sab196087 { 15425088Sab196087 return (cmd_body(DYN_CMD_T_DELETE, obj_state, argc, argv)); 15435088Sab196087 } 15445088Sab196087 15455088Sab196087 static elfedit_cmdret_t 15465088Sab196087 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15475088Sab196087 { 15485088Sab196087 return (cmd_body(DYN_CMD_T_MOVE, obj_state, argc, argv)); 15495088Sab196087 } 15505088Sab196087 15515088Sab196087 static elfedit_cmdret_t 15525088Sab196087 cmd_runpath(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15535088Sab196087 { 15545088Sab196087 return (cmd_body(DYN_CMD_T_RUNPATH, obj_state, argc, argv)); 15555088Sab196087 } 15565088Sab196087 15575088Sab196087 static elfedit_cmdret_t 15585088Sab196087 cmd_posflag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15595088Sab196087 { 15605088Sab196087 return (cmd_body(DYN_CMD_T_POSFLAG1, obj_state, argc, argv)); 15615088Sab196087 } 15625088Sab196087 15635088Sab196087 static elfedit_cmdret_t 15645088Sab196087 cmd_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15655088Sab196087 { 15665088Sab196087 return (cmd_body(DYN_CMD_T_FLAGS, obj_state, argc, argv)); 15675088Sab196087 } 15685088Sab196087 15695088Sab196087 static elfedit_cmdret_t 15705088Sab196087 cmd_flags1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15715088Sab196087 { 15725088Sab196087 return (cmd_body(DYN_CMD_T_FLAGS1, obj_state, argc, argv)); 15735088Sab196087 } 15745088Sab196087 15755088Sab196087 static elfedit_cmdret_t 15765088Sab196087 cmd_feature1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15775088Sab196087 { 15785088Sab196087 return (cmd_body(DYN_CMD_T_FEATURE1, obj_state, argc, argv)); 15795088Sab196087 } 15805088Sab196087 15815088Sab196087 static elfedit_cmdret_t 15825088Sab196087 cmd_checksum(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 15835088Sab196087 { 15845088Sab196087 return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv)); 15855088Sab196087 } 15865088Sab196087 1587*6206Sab196087 static elfedit_cmdret_t 1588*6206Sab196087 cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1589*6206Sab196087 { 1590*6206Sab196087 return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv)); 1591*6206Sab196087 } 1592*6206Sab196087 15935088Sab196087 15945088Sab196087 15955088Sab196087 /*ARGSUSED*/ 15965088Sab196087 elfedit_module_t * 15975088Sab196087 elfedit_init(elfedit_module_version_t version) 15985088Sab196087 { 15995088Sab196087 /* For commands that only accept -o */ 16005088Sab196087 static elfedit_cmd_optarg_t opt_ostyle[] = { 16015088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 16025088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 16035088Sab196087 { NULL } 16045088Sab196087 }; 16055088Sab196087 16065088Sab196087 /* For commands that only accept -and, -cmp, -o, -or */ 16075088Sab196087 static elfedit_cmd_optarg_t opt_ostyle_bitop[] = { 16085088Sab196087 { ELFEDIT_STDOA_OPT_AND, NULL, 16095088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 16105088Sab196087 { ELFEDIT_STDOA_OPT_CMP, NULL, 16115088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 16125088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 16135088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 16145088Sab196087 { ELFEDIT_STDOA_OPT_OR, NULL, 16155088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 16165088Sab196087 { NULL } 16175088Sab196087 }; 16185088Sab196087 16195088Sab196087 /* For commands that only accept -dynndx */ 16205088Sab196087 static elfedit_cmd_optarg_t opt_minus_dynndx[] = { 16215088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 16225088Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX) */ 16235088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX), 0, 16245088Sab196087 DYN_OPT_F_DYNNDX, 0 }, 16255088Sab196087 { NULL } 16265088Sab196087 }; 16275088Sab196087 16285088Sab196087 /* dyn:dump */ 16295088Sab196087 static const char *name_dump[] = { 16305088Sab196087 MSG_ORIG(MSG_CMD_DUMP), 16315088Sab196087 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 16325088Sab196087 NULL 16335088Sab196087 }; 16345088Sab196087 static elfedit_cmd_optarg_t arg_dump[] = { 16355088Sab196087 { MSG_ORIG(MSG_STR_ELT), 16365088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 16375088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 16385088Sab196087 ELFEDIT_CMDOA_F_OPT }, 16395088Sab196087 { NULL } 16405088Sab196087 }; 16415088Sab196087 16425088Sab196087 16435088Sab196087 /* dyn:tag */ 16445088Sab196087 static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL }; 16455088Sab196087 static elfedit_cmd_optarg_t opt_tag[] = { 16465088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 16475088Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX) */ 16485088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX), 0, 16495088Sab196087 DYN_OPT_F_DYNNDX, 0 }, 16505088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 16515088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 16525088Sab196087 { NULL } 16535088Sab196087 }; 16545088Sab196087 static elfedit_cmd_optarg_t arg_tag[] = { 16555088Sab196087 { MSG_ORIG(MSG_STR_ELT), 16565088Sab196087 /* MSG_INTL(MSG_A1_TAG_ELT) */ 16575088Sab196087 ELFEDIT_I18NHDL(MSG_A1_TAG_ELT), 16585088Sab196087 ELFEDIT_CMDOA_F_OPT }, 16595088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 16605088Sab196087 /* MSG_INTL(MSG_A2_TAG_VALUE) */ 16615088Sab196087 ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE), 16625088Sab196087 ELFEDIT_CMDOA_F_OPT }, 16635088Sab196087 { NULL } 16645088Sab196087 }; 16655088Sab196087 16665088Sab196087 16675088Sab196087 /* dyn:value */ 16685088Sab196087 static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL }; 16695088Sab196087 static elfedit_cmd_optarg_t opt_value[] = { 16705088Sab196087 { MSG_ORIG(MSG_STR_MINUS_ADD), 16715088Sab196087 /* MSG_INTL(MSG_OPTDESC_ADD) */ 16725088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_ADD), 0, 16735088Sab196087 DYN_OPT_F_ADD, DYN_OPT_F_DYNNDX }, 16745088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 16755088Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX) */ 16765088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX), 0, 16775088Sab196087 DYN_OPT_F_DYNNDX, DYN_OPT_F_ADD }, 16785088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 16795088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 16805088Sab196087 { MSG_ORIG(MSG_STR_MINUS_S), 16815088Sab196087 /* MSG_INTL(MSG_OPTDESC_S) */ 16825088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0, 16835088Sab196087 DYN_OPT_F_STRVAL, 0 }, 16845088Sab196087 { NULL } 16855088Sab196087 }; 16865088Sab196087 static elfedit_cmd_optarg_t arg_value[] = { 16875088Sab196087 { MSG_ORIG(MSG_STR_ELT), 16885088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 16895088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 16905088Sab196087 ELFEDIT_CMDOA_F_OPT }, 16915088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 16925088Sab196087 /* MSG_INTL(MSG_A2_VALUE_VALUE) */ 16935088Sab196087 ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE), 16945088Sab196087 ELFEDIT_CMDOA_F_OPT }, 16955088Sab196087 { NULL } 16965088Sab196087 }; 16975088Sab196087 16985088Sab196087 /* dyn:delete */ 16995088Sab196087 static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL }; 17005088Sab196087 static elfedit_cmd_optarg_t arg_delete[] = { 17015088Sab196087 { MSG_ORIG(MSG_STR_ELT), 17025088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 17035088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 17045088Sab196087 0 }, 17055088Sab196087 { MSG_ORIG(MSG_STR_COUNT), 17065088Sab196087 /* MSG_INTL(MSG_A2_DELETE_COUNT) */ 17075088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT), 17085088Sab196087 ELFEDIT_CMDOA_F_OPT }, 17095088Sab196087 { NULL } 17105088Sab196087 }; 17115088Sab196087 17125088Sab196087 /* dyn:move */ 17135088Sab196087 static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL }; 17145088Sab196087 static elfedit_cmd_optarg_t arg_move[] = { 17155088Sab196087 { MSG_ORIG(MSG_STR_ELT), 17165088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 17175088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 17185088Sab196087 0 }, 17195088Sab196087 { MSG_ORIG(MSG_STR_DST_INDEX), 17205088Sab196087 /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */ 17215088Sab196087 ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX), 17225088Sab196087 0 }, 17235088Sab196087 { MSG_ORIG(MSG_STR_COUNT), 17245088Sab196087 /* MSG_INTL(MSG_A3_MOVE_COUNT) */ 17255088Sab196087 ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT), 17265088Sab196087 ELFEDIT_CMDOA_F_OPT }, 17275088Sab196087 { NULL } 17285088Sab196087 }; 17295088Sab196087 17305088Sab196087 /* dyn:runpath / dyn:rpath */ 17315088Sab196087 static const char *name_runpath[] = { MSG_ORIG(MSG_CMD_RUNPATH), 17325088Sab196087 MSG_ORIG(MSG_CMD_RUNPATH_A1), NULL }; 17335088Sab196087 static elfedit_cmd_optarg_t arg_runpath[] = { 17345088Sab196087 { MSG_ORIG(MSG_STR_NEWPATH), 17355088Sab196087 /* MSG_INTL(MSG_A1_RUNPATH_NEWPATH) */ 17365088Sab196087 ELFEDIT_I18NHDL(MSG_A1_RUNPATH_NEWPATH), 17375088Sab196087 ELFEDIT_CMDOA_F_OPT }, 17385088Sab196087 { NULL } 17395088Sab196087 }; 17405088Sab196087 17415088Sab196087 /* dyn:posflag1 */ 17425088Sab196087 static const char *name_posflag1[] = { MSG_ORIG(MSG_CMD_POSFLAG1), 17435088Sab196087 NULL }; 17445088Sab196087 static elfedit_cmd_optarg_t arg_posflag1[] = { 17455088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 17465088Sab196087 /* MSG_INTL(MSG_A1_POSFLAG1_VALUE) */ 17475088Sab196087 ELFEDIT_I18NHDL(MSG_A1_POSFLAG1_VALUE), 17485088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 17495088Sab196087 { NULL } 17505088Sab196087 }; 17515088Sab196087 17525088Sab196087 /* dyn:flags */ 17535088Sab196087 static const char *name_flags[] = { MSG_ORIG(MSG_CMD_FLAGS), NULL }; 17545088Sab196087 static elfedit_cmd_optarg_t arg_flags[] = { 17555088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 17565088Sab196087 /* MSG_INTL(MSG_A1_FLAGS_VALUE) */ 17575088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FLAGS_VALUE), 17585088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 17595088Sab196087 { NULL } 17605088Sab196087 }; 17615088Sab196087 17625088Sab196087 /* dyn:flags1 */ 17635088Sab196087 static const char *name_flags1[] = { MSG_ORIG(MSG_CMD_FLAGS1), NULL }; 17645088Sab196087 static elfedit_cmd_optarg_t arg_flags1[] = { 17655088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 17665088Sab196087 /* MSG_INTL(MSG_A1_FLAGS1_VALUE) */ 17675088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FLAGS1_VALUE), 17685088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 17695088Sab196087 { NULL } 17705088Sab196087 }; 17715088Sab196087 17725088Sab196087 /* dyn:feature1 */ 17735088Sab196087 static const char *name_feature1[] = { MSG_ORIG(MSG_CMD_FEATURE1), 17745088Sab196087 NULL }; 17755088Sab196087 static elfedit_cmd_optarg_t arg_feature1[] = { 17765088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 17775088Sab196087 /* MSG_INTL(MSG_A1_FEATURE1_VALUE) */ 17785088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FEATURE1_VALUE), 17795088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 17805088Sab196087 { NULL } 17815088Sab196087 }; 17825088Sab196087 17835088Sab196087 /* dyn:checksum */ 17845088Sab196087 static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM), 17855088Sab196087 NULL }; 17865088Sab196087 1787*6206Sab196087 /* dyn:sunw_ldmach */ 1788*6206Sab196087 static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH), 1789*6206Sab196087 NULL }; 1790*6206Sab196087 static elfedit_cmd_optarg_t arg_sunw_ldmach[] = { 1791*6206Sab196087 { MSG_ORIG(MSG_STR_VALUE), 1792*6206Sab196087 /* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */ 1793*6206Sab196087 ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE), 1794*6206Sab196087 ELFEDIT_CMDOA_F_OPT }, 1795*6206Sab196087 { NULL } 1796*6206Sab196087 }; 1797*6206Sab196087 17985088Sab196087 17995088Sab196087 18005088Sab196087 static elfedit_cmd_t cmds[] = { 18015088Sab196087 /* dyn:dump */ 18025088Sab196087 { cmd_dump, cpl_eltarg, name_dump, 18035088Sab196087 /* MSG_INTL(MSG_DESC_DUMP) */ 18045088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 18055088Sab196087 /* MSG_INTL(MSG_HELP_DUMP) */ 18065088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 18075088Sab196087 opt_minus_dynndx, arg_dump }, 18085088Sab196087 18095088Sab196087 /* dyn:tag */ 18105088Sab196087 { cmd_tag, cpl_tag, name_tag, 18115088Sab196087 /* MSG_INTL(MSG_DESC_TAG) */ 18125088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_TAG), 18135088Sab196087 /* MSG_INTL(MSG_HELP_TAG) */ 18145088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_TAG), 18155088Sab196087 opt_tag, arg_tag }, 18165088Sab196087 18175088Sab196087 /* dyn:value */ 18185088Sab196087 { cmd_value, cpl_eltarg, name_value, 18195088Sab196087 /* MSG_INTL(MSG_DESC_VALUE) */ 18205088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_VALUE), 18215088Sab196087 /* MSG_INTL(MSG_HELP_VALUE) */ 18225088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_VALUE), 18235088Sab196087 opt_value, arg_value }, 18245088Sab196087 18255088Sab196087 /* dyn:delete */ 18265088Sab196087 { cmd_delete, cpl_eltarg, name_delete, 18275088Sab196087 /* MSG_INTL(MSG_DESC_DELETE) */ 18285088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DELETE), 18295088Sab196087 /* MSG_INTL(MSG_HELP_DELETE) */ 18305088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DELETE), 18315088Sab196087 opt_minus_dynndx, arg_delete }, 18325088Sab196087 18335088Sab196087 /* dyn:move */ 18345088Sab196087 { cmd_move, cpl_eltarg, name_move, 18355088Sab196087 /* MSG_INTL(MSG_DESC_MOVE) */ 18365088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_MOVE), 18375088Sab196087 /* MSG_INTL(MSG_HELP_MOVE) */ 18385088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_MOVE), 18395088Sab196087 opt_minus_dynndx, arg_move }, 18405088Sab196087 18415088Sab196087 /* dyn:runpath */ 18425088Sab196087 { cmd_runpath, NULL, name_runpath, 18435088Sab196087 /* MSG_INTL(MSG_DESC_RUNPATH) */ 18445088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_RUNPATH), 18455088Sab196087 /* MSG_INTL(MSG_HELP_RUNPATH) */ 18465088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_RUNPATH), 18475088Sab196087 opt_ostyle, arg_runpath }, 18485088Sab196087 18495088Sab196087 /* dyn:posflag1 */ 18505088Sab196087 { cmd_posflag1, cpl_posflag1, name_posflag1, 18515088Sab196087 /* MSG_INTL(MSG_DESC_POSFLAG1) */ 18525088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_POSFLAG1), 18535088Sab196087 /* MSG_INTL(MSG_HELP_POSFLAG1) */ 18545088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_POSFLAG1), 18555088Sab196087 opt_ostyle_bitop, arg_posflag1 }, 18565088Sab196087 18575088Sab196087 /* dyn:flags */ 18585088Sab196087 { cmd_flags, cpl_flags, name_flags, 18595088Sab196087 /* MSG_INTL(MSG_DESC_FLAGS) */ 18605088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FLAGS), 18615088Sab196087 /* MSG_INTL(MSG_HELP_FLAGS) */ 18625088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FLAGS), 18635088Sab196087 opt_ostyle_bitop, arg_flags }, 18645088Sab196087 18655088Sab196087 /* dyn:flags1 */ 18665088Sab196087 { cmd_flags1, cpl_flags1, name_flags1, 18675088Sab196087 /* MSG_INTL(MSG_DESC_FLAGS1) */ 18685088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FLAGS1), 18695088Sab196087 /* MSG_INTL(MSG_HELP_FLAGS1) */ 18705088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FLAGS1), 18715088Sab196087 opt_ostyle_bitop, arg_flags1 }, 18725088Sab196087 18735088Sab196087 /* dyn:feature1 */ 18745088Sab196087 { cmd_feature1, cpl_feature1, name_feature1, 18755088Sab196087 /* MSG_INTL(MSG_DESC_FEATURE1) */ 18765088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FEATURE1), 18775088Sab196087 /* MSG_INTL(MSG_HELP_FEATURE1) */ 18785088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FEATURE1), 18795088Sab196087 opt_ostyle_bitop, arg_feature1 }, 18805088Sab196087 18815088Sab196087 /* dyn:checksum */ 18825088Sab196087 { cmd_checksum, NULL, name_checksum, 18835088Sab196087 /* MSG_INTL(MSG_DESC_CHECKSUM) */ 18845088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_CHECKSUM), 18855088Sab196087 /* MSG_INTL(MSG_HELP_CHECKSUM) */ 18865088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM), 18875088Sab196087 NULL, NULL }, 18885088Sab196087 1889*6206Sab196087 /* dyn:sunw_ldmach */ 1890*6206Sab196087 { cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach, 1891*6206Sab196087 /* MSG_INTL(MSG_DESC_SUNW_LDMACH) */ 1892*6206Sab196087 ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH), 1893*6206Sab196087 /* MSG_INTL(MSG_HELP_SUNW_LDMACH) */ 1894*6206Sab196087 ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH), 1895*6206Sab196087 opt_ostyle, arg_sunw_ldmach }, 1896*6206Sab196087 18975088Sab196087 { NULL } 18985088Sab196087 }; 18995088Sab196087 19005088Sab196087 static elfedit_module_t module = { 19015088Sab196087 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 19025088Sab196087 /* MSG_INTL(MSG_MOD_DESC) */ 19035088Sab196087 ELFEDIT_I18NHDL(MSG_MOD_DESC), cmds, mod_i18nhdl_to_str }; 19045088Sab196087 19055088Sab196087 return (&module); 19065088Sab196087 } 1907