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*9273SAli.Bahrami@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 245088Sab196087 * Use is subject to license terms. 255088Sab196087 */ 265088Sab196087 275088Sab196087 #include <ctype.h> 285088Sab196087 #include <elfedit.h> 295088Sab196087 #include <sys/elf_SPARC.h> 305088Sab196087 #include <strings.h> 315088Sab196087 #include <debug.h> 325088Sab196087 #include <conv.h> 335088Sab196087 #include <dyn_msg.h> 345088Sab196087 355088Sab196087 365088Sab196087 /* 375088Sab196087 * Dynamic section 385088Sab196087 */ 395088Sab196087 405088Sab196087 /* 415088Sab196087 * This module uses shared code for several of the commands. 425088Sab196087 * It is sometimes necessary to know which specific command 435088Sab196087 * is active. 445088Sab196087 */ 455088Sab196087 typedef enum { 465088Sab196087 /* Dump command, used as module default to display dynamic section */ 475088Sab196087 DYN_CMD_T_DUMP = 0, /* dyn:dump */ 485088Sab196087 495088Sab196087 /* Commands that do not correspond directly to a specific DT tag */ 505088Sab196087 DYN_CMD_T_TAG = 1, /* dyn:tag */ 515088Sab196087 DYN_CMD_T_VALUE = 2, /* dyn:value */ 525088Sab196087 DYN_CMD_T_DELETE = 3, /* dyn:delete */ 535088Sab196087 DYN_CMD_T_MOVE = 4, /* dyn:shift */ 545088Sab196087 555088Sab196087 /* Commands that embody tag specific knowledge */ 565088Sab196087 DYN_CMD_T_RUNPATH = 5, /* dyn:runpath/rpath */ 575088Sab196087 DYN_CMD_T_POSFLAG1 = 6, /* dyn:posflag1 */ 585088Sab196087 DYN_CMD_T_FLAGS = 7, /* dyn:flags */ 595088Sab196087 DYN_CMD_T_FLAGS1 = 8, /* dyn:flags1 */ 605088Sab196087 DYN_CMD_T_FEATURE1 = 9, /* dyn:feature1 */ 616206Sab196087 DYN_CMD_T_CHECKSUM = 10, /* dyn:checksum */ 626206Sab196087 DYN_CMD_T_SUNW_LDMACH = 11 /* dyn:sunw_ldmach */ 635088Sab196087 } DYN_CMD_T; 645088Sab196087 655088Sab196087 665088Sab196087 675088Sab196087 #ifndef _ELF64 685088Sab196087 /* 695088Sab196087 * We supply this function for the msg module 705088Sab196087 */ 715088Sab196087 const char * 725088Sab196087 _dyn_msg(Msg mid) 735088Sab196087 { 745088Sab196087 return (gettext(MSG_ORIG(mid))); 755088Sab196087 } 765088Sab196087 #endif 775088Sab196087 785088Sab196087 795088Sab196087 /* 805088Sab196087 * This function is supplied to elfedit through our elfedit_module_t 815088Sab196087 * definition. It translates the opaque elfedit_i18nhdl_t handles 825088Sab196087 * in our module interface into the actual strings for elfedit to 835088Sab196087 * use. 845088Sab196087 * 855088Sab196087 * note: 865088Sab196087 * This module uses Msg codes for its i18n handle type. 875088Sab196087 * So the translation is simply to use MSG_INTL() to turn 885088Sab196087 * it into a string and return it. 895088Sab196087 */ 905088Sab196087 static const char * 915088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 925088Sab196087 { 935088Sab196087 Msg msg = (Msg)hdl; 945088Sab196087 955088Sab196087 return (MSG_INTL(msg)); 965088Sab196087 } 975088Sab196087 985088Sab196087 995088Sab196087 1005088Sab196087 /* 1015088Sab196087 * The dyn_opt_t enum specifies a bit value for every optional 1025088Sab196087 * argument allowed by a command in this module. 1035088Sab196087 */ 1045088Sab196087 typedef enum { 1055088Sab196087 DYN_OPT_F_ADD = 1, /* -add: Add new elt rather than */ 1065088Sab196087 /* modifying an existing one */ 1075088Sab196087 DYN_OPT_F_AND = 2, /* -and: AND (&) values to dest */ 1085088Sab196087 DYN_OPT_F_CMP = 4, /* -cmp: Complement (~) values */ 1096225Sab196087 DYN_OPT_F_DYNNDX_ELT = 8, /* -dynndx: 1st plain arg is tag */ 1106225Sab196087 /* index, not name */ 1116225Sab196087 DYN_OPT_F_DYNNDX_VAL = 16, /* -dynndx ndx: Index is value to */ 1126225Sab196087 /* option rather than 1st plain */ 1136225Sab196087 /* arg. Used for dyn:posflag1 */ 1146225Sab196087 DYN_OPT_F_NEEDED = 32, /* -needed str: Locate DT_POSFLAG_1 */ 1156225Sab196087 /* relative to DT_NEEDED element */ 1166225Sab196087 DYN_OPT_F_OR = 64, /* -or: OR (|) values to dest */ 1176225Sab196087 DYN_OPT_F_STRVAL = 128 /* -s: value is string, not integer */ 1185088Sab196087 } dyn_opt_t; 1195088Sab196087 1205088Sab196087 1215088Sab196087 /* 1225088Sab196087 * A variable of type ARGSTATE is used by each command to maintain 1235088Sab196087 * information about the arguments and related things. It is 1245088Sab196087 * initialized by process_args(), and used by the other routines. 1255088Sab196087 */ 1265088Sab196087 typedef struct { 1275088Sab196087 elfedit_obj_state_t *obj_state; 1285088Sab196087 elfedit_section_t *strsec; /* Dynamic string table ref */ 1295088Sab196087 struct { 1305088Sab196087 elfedit_section_t *sec; /* Dynamic section reference */ 1315088Sab196087 Dyn *data; /* Start dynamic section data */ 1325088Sab196087 Word num; /* # dynamic elts */ 1335088Sab196087 Word null_ndx; /* Index of first DT_NULL */ 1345088Sab196087 Word num_null_ndx; /* # of DT_NULL elements */ 1355088Sab196087 } dyn; 1365088Sab196087 dyn_opt_t optmask; /* Mask of options used */ 1375088Sab196087 int argc; /* # of plain arguments */ 1385088Sab196087 const char **argv; /* Plain arguments */ 1396225Sab196087 const char *dyn_elt_str; /* Value string for */ 1406225Sab196087 /* DYN_OPT_F_DYNNDX_VAL */ 1416225Sab196087 /* or DYN_OPT_F_NEEDED */ 1425088Sab196087 } ARGSTATE; 1435088Sab196087 1445088Sab196087 1455088Sab196087 1465088Sab196087 /* 1475088Sab196087 * Set argstate null_ndx field for current dynamic area 1485088Sab196087 */ 1495088Sab196087 static void 1505088Sab196087 set_null_ndx(ARGSTATE *argstate) 1515088Sab196087 { 1525088Sab196087 Word num, null_ndx; 1535088Sab196087 1545088Sab196087 num = argstate->dyn.num; 1555088Sab196087 argstate->dyn.num_null_ndx = 0; 1565088Sab196087 for (null_ndx = 0; null_ndx < num; null_ndx++) 1575088Sab196087 if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) { 1585088Sab196087 argstate->dyn.num_null_ndx++; 1595088Sab196087 break; 1605088Sab196087 } 1615088Sab196087 argstate->dyn.null_ndx = null_ndx; 1625088Sab196087 1635088Sab196087 /* Count the number of remaining DT_NULL items */ 1645088Sab196087 for (; null_ndx < num; null_ndx++) 1655088Sab196087 if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) 1665088Sab196087 argstate->dyn.num_null_ndx++; 1675088Sab196087 } 1685088Sab196087 1695088Sab196087 1705088Sab196087 /* 1715088Sab196087 * Convert the first available DT_NULL slot in the dynamic section 1725088Sab196087 * into something else. 1735088Sab196087 * 1745088Sab196087 * entry: 1755088Sab196087 * argstate - Argument state block 1765088Sab196087 * d_tag, d_val - Values to be set in new element 1775088Sab196087 * 1785088Sab196087 * exit: 1795088Sab196087 * If an extra DT_NULL slot is available, a debug message is 1805088Sab196087 * issued, the slot is converted to its new use, and the argstate 1815088Sab196087 * block state related to DT_NULL slots is updated. 1825088Sab196087 * 1835088Sab196087 * if no extra DT_NULL slot is present, an error is issued and 1845088Sab196087 * this routine does not return to the caller. 1855088Sab196087 */ 1865088Sab196087 static Word 187*9273SAli.Bahrami@Sun.COM convert_dt_null(ARGSTATE *argstate, Xword d_tag, Xword d_val) 1885088Sab196087 { 1895088Sab196087 Conv_inv_buf_t inv_buf; 1905088Sab196087 Word ndx; 1915088Sab196087 Dyn *dyn; 192*9273SAli.Bahrami@Sun.COM Ehdr *ehdr; 1935088Sab196087 1945088Sab196087 /* If we lack an extra element, we can't continue */ 1955088Sab196087 if (argstate->dyn.num_null_ndx <= 1) 1965088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 1975088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 1985088Sab196087 argstate->dyn.sec->sec_name); 1995088Sab196087 200*9273SAli.Bahrami@Sun.COM ehdr = argstate->obj_state->os_ehdr; 2015088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL), 2025088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), argstate->dyn.sec->sec_name, 2035088Sab196087 EC_WORD(argstate->dyn.null_ndx), conv_dyn_tag(d_tag, 204*9273SAli.Bahrami@Sun.COM ehdr->e_ident[EI_OSABI], ehdr->e_machine, 0, &inv_buf)); 2055088Sab196087 2065088Sab196087 ndx = argstate->dyn.null_ndx; 2075088Sab196087 dyn = &argstate->dyn.data[ndx]; 2085088Sab196087 dyn->d_tag = d_tag; 2095088Sab196087 dyn->d_un.d_val = d_val; 2105088Sab196087 2115088Sab196087 /* Recompute the DT_NULL situation */ 2125088Sab196087 set_null_ndx(argstate); 2135088Sab196087 2145088Sab196087 return (ndx); 2155088Sab196087 } 2165088Sab196087 2175088Sab196087 2185088Sab196087 /* 2195088Sab196087 * Standard argument processing for dyn module 2205088Sab196087 * 2215088Sab196087 * entry 2225088Sab196087 * obj_state, argc, argv - Standard command arguments 2235088Sab196087 * argstate - Address of ARGSTATE block to be initialized 2245088Sab196087 * 2255088Sab196087 * exit: 2265088Sab196087 * On success, *argstate is initialized. On error, 2275088Sab196087 * an error is issued and this routine does not return. 2285088Sab196087 */ 2295088Sab196087 static void 2305088Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 2315088Sab196087 ARGSTATE *argstate) 2325088Sab196087 { 2335088Sab196087 elfedit_getopt_state_t getopt_state; 2345088Sab196087 elfedit_getopt_ret_t *getopt_ret; 2355088Sab196087 2365088Sab196087 bzero(argstate, sizeof (*argstate)); 2375088Sab196087 argstate->obj_state = obj_state; 2385088Sab196087 2395088Sab196087 elfedit_getopt_init(&getopt_state, &argc, &argv); 2405088Sab196087 2415088Sab196087 /* Add each new option to the options mask */ 2426225Sab196087 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) { 2435088Sab196087 argstate->optmask |= getopt_ret->gor_idmask; 2446225Sab196087 switch (getopt_ret->gor_idmask) { 2456225Sab196087 case DYN_OPT_F_DYNNDX_VAL: 2466225Sab196087 case DYN_OPT_F_NEEDED: 2476225Sab196087 argstate->dyn_elt_str = getopt_ret->gor_value; 2486225Sab196087 break; 2496225Sab196087 } 2506225Sab196087 } 2515088Sab196087 2525088Sab196087 /* If there may be an arbitrary amount of output, use a pager */ 2535088Sab196087 if (argc == 0) 2545088Sab196087 elfedit_pager_init(); 2555088Sab196087 2565088Sab196087 /* Return the updated values of argc/argv */ 2575088Sab196087 argstate->argc = argc; 2585088Sab196087 argstate->argv = argv; 2595088Sab196087 2605088Sab196087 /* Locate the dynamic section, and the assocated string table */ 2615088Sab196087 argstate->dyn.sec = elfedit_sec_getdyn(obj_state, &argstate->dyn.data, 2625088Sab196087 &argstate->dyn.num); 2635088Sab196087 argstate->strsec = elfedit_sec_getstr(obj_state, 2646225Sab196087 argstate->dyn.sec->sec_shdr->sh_link, 0); 2655088Sab196087 2665088Sab196087 /* Index of first DT_NULL */ 2675088Sab196087 set_null_ndx(argstate); 2685088Sab196087 } 2695088Sab196087 2705088Sab196087 /* 2715088Sab196087 * Print ELF header values, taking the calling command, and output style 2725088Sab196087 * into account. 2735088Sab196087 * 2745088Sab196087 * entry: 2755088Sab196087 * cmd - DYN_CMD_T_* value giving identify of caller 2765088Sab196087 * autoprint - If True, output is only produced if the elfedit 2775088Sab196087 * autoprint flag is set. If False, output is always produced. 2785088Sab196087 * argstate - Argument state block 2795088Sab196087 * print_type - Specifies which dynamic elements to display. 280*9273SAli.Bahrami@Sun.COM * arg - If print_type is PRINT_DYN_T_NDX, displays the index specified. 2815088Sab196087 * Otherwise ignored. 2825088Sab196087 */ 2835088Sab196087 typedef enum { 2845088Sab196087 PRINT_DYN_T_ALL = 0, /* Show all indexes */ 2855088Sab196087 PRINT_DYN_T_NDX = 1, /* Show dynamic[arg] only */ 2865088Sab196087 PRINT_DYN_T_TAG = 2, /* Show all elts with tag type */ 2875088Sab196087 /* given by arg */ 2885088Sab196087 PRINT_DYN_T_RUNPATH = 3 /* Show all runpath/rpath elts */ 2895088Sab196087 2905088Sab196087 } PRINT_DYN_T; 2915088Sab196087 2925088Sab196087 static void 2935088Sab196087 print_dyn(DYN_CMD_T cmd, int autoprint, ARGSTATE *argstate, 2945088Sab196087 PRINT_DYN_T print_type, Word arg) 2955088Sab196087 { 2965088Sab196087 elfedit_outstyle_t outstyle; 2975088Sab196087 Conv_fmt_flags_t flags_fmt_flags; 2986635Sab196087 Word end_ndx, ndx, printed = 0; 2995088Sab196087 Dyn *dyn; 3005088Sab196087 int header_done = 0; 3015088Sab196087 Xword last_d_val; 3026225Sab196087 int one_shot; 303*9273SAli.Bahrami@Sun.COM int osabi_solaris; 3045088Sab196087 3055088Sab196087 if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) 3065088Sab196087 return; 3075088Sab196087 308*9273SAli.Bahrami@Sun.COM osabi_solaris = 309*9273SAli.Bahrami@Sun.COM elfedit_test_osabi(argstate->obj_state, ELFOSABI_SOLARIS, 0); 310*9273SAli.Bahrami@Sun.COM 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 3256635Sab196087 /* 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]; 3436635Sab196087 3446635Sab196087 /* 3456635Sab196087 * Loop predicate explanation: 3466635Sab196087 * Normally, we want to iterate from the starting index 3476635Sab196087 * to the end. However, in the case of PRINT_DYN_T_NDX, we 3486635Sab196087 * only want to display one item (ndx == arg) and then quit, 3496635Sab196087 * with the exception that if we've been through the loop 3506635Sab196087 * and encountered a one_shot situation, we want to continue 3516635Sab196087 * iterating until the one-shot situation is cleared. 3526635Sab196087 */ 3536635Sab196087 for (; (ndx < argstate->dyn.num) && 3546635Sab196087 ((print_type != PRINT_DYN_T_NDX) || ((ndx == arg) || one_shot)); 3556635Sab196087 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: 431*9273SAli.Bahrami@Sun.COM name = elfedit_offset_to_str(argstate->strsec, 432*9273SAli.Bahrami@Sun.COM dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 433*9273SAli.Bahrami@Sun.COM break; 4345088Sab196087 case DT_SUNW_AUXILIARY: 4355088Sab196087 case DT_SUNW_FILTER: 436*9273SAli.Bahrami@Sun.COM if (osabi_solaris) 437*9273SAli.Bahrami@Sun.COM name = elfedit_offset_to_str(argstate->strsec, 438*9273SAli.Bahrami@Sun.COM dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 4395088Sab196087 break; 4405088Sab196087 4415088Sab196087 case DT_FLAGS: 4425088Sab196087 name = conv_dyn_flag(dyn->d_un.d_val, 4435088Sab196087 flags_fmt_flags, &c_buf.flag); 4445088Sab196087 break; 4455088Sab196087 case DT_FLAGS_1: 4465088Sab196087 name = conv_dyn_flag1(dyn->d_un.d_val, 4475088Sab196087 flags_fmt_flags, &c_buf.flag1); 4485088Sab196087 break; 4495088Sab196087 case DT_POSFLAG_1: 4506225Sab196087 /* 4516225Sab196087 * If this is dyn:posflag1, and the print_type 4526225Sab196087 * is PRINT_DYN_T_TAG, and the -needed option is 4536225Sab196087 * used, then don't show any DT_POSFLAG_1 elements 4546225Sab196087 * that are not followed by a DT_NEEDED element 4556225Sab196087 * that matches the -needed string. 4566225Sab196087 */ 4576225Sab196087 if ((cmd == DYN_CMD_T_POSFLAG1) && 4586225Sab196087 (print_type == PRINT_DYN_T_TAG) && 4596225Sab196087 ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) && 4606225Sab196087 ((ndx + 1) < argstate->dyn.num)) { 4616225Sab196087 Dyn *dyn1 = &argstate->dyn.data[ndx + 1]; 4626225Sab196087 4636225Sab196087 if (dyn1->d_tag != DT_NEEDED) 4646225Sab196087 continue; 4656225Sab196087 name = elfedit_offset_to_str(argstate->strsec, 4666225Sab196087 dyn1->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 4676225Sab196087 if (strncmp(name, argstate->dyn_elt_str, 4686225Sab196087 strlen(argstate->dyn_elt_str)) != 0) 4696225Sab196087 continue; 4706225Sab196087 } 4716225Sab196087 4725088Sab196087 name = conv_dyn_posflag1(dyn->d_un.d_val, 4735088Sab196087 flags_fmt_flags, &c_buf.posflag1); 4746225Sab196087 /* 4756225Sab196087 * DT_POSFLAG_1 is a positional element that affects 4766225Sab196087 * the following item. If using the default output 4776225Sab196087 * style, then show the following item as well. 4786225Sab196087 */ 4796225Sab196087 one_shot = (outstyle == ELFEDIT_OUTSTYLE_DEFAULT); 4805088Sab196087 break; 4815088Sab196087 case DT_FEATURE_1: 4825088Sab196087 name = conv_dyn_feature1(dyn->d_un.d_val, 4835088Sab196087 flags_fmt_flags, &c_buf.feature1); 4845088Sab196087 break; 4855088Sab196087 case DT_DEPRECATED_SPARC_REGISTER: 4865088Sab196087 name = MSG_INTL(MSG_STR_DEPRECATED); 4875088Sab196087 break; 4886206Sab196087 case DT_SUNW_LDMACH: 489*9273SAli.Bahrami@Sun.COM if (osabi_solaris) 490*9273SAli.Bahrami@Sun.COM name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0, 491*9273SAli.Bahrami@Sun.COM &c_buf.inv); 4926206Sab196087 break; 4935088Sab196087 } 4945088Sab196087 4955088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 496*9273SAli.Bahrami@Sun.COM Ehdr *ehdr; 497*9273SAli.Bahrami@Sun.COM 4985088Sab196087 if (header_done == 0) { 4995088Sab196087 header_done = 1; 5005088Sab196087 Elf_dyn_title(0); 5015088Sab196087 } 5025088Sab196087 if (name == NULL) 5035088Sab196087 name = MSG_ORIG(MSG_STR_EMPTY); 504*9273SAli.Bahrami@Sun.COM ehdr = argstate->obj_state->os_ehdr; 5055088Sab196087 Elf_dyn_entry(0, dyn, ndx, name, 506*9273SAli.Bahrami@Sun.COM ehdr->e_ident[EI_OSABI], ehdr->e_machine); 5075088Sab196087 } else { 5085088Sab196087 /* 5095088Sab196087 * In simple or numeric mode under a print type 5105088Sab196087 * that is based on tag type rather than on index, 5118368SAli.Bahrami@Sun.COM * if there are more than one qualifying tag, we 5128368SAli.Bahrami@Sun.COM * want to skip printing redundant information. 5135088Sab196087 */ 5145088Sab196087 switch (print_type) { 5155088Sab196087 case PRINT_DYN_T_TAG: 5168368SAli.Bahrami@Sun.COM switch (dyn->d_tag) { 5178368SAli.Bahrami@Sun.COM case DT_NEEDED: 5188368SAli.Bahrami@Sun.COM /* Multiple NEEDED entries are normal */ 5198368SAli.Bahrami@Sun.COM break; 5208368SAli.Bahrami@Sun.COM case DT_POSFLAG_1: 5218368SAli.Bahrami@Sun.COM /* 5228368SAli.Bahrami@Sun.COM * Positional flags don't count, 5238368SAli.Bahrami@Sun.COM * because each one affects a different 5248368SAli.Bahrami@Sun.COM * item. Don't skip those even if they 5258368SAli.Bahrami@Sun.COM * have duplicate values. 5268368SAli.Bahrami@Sun.COM */ 5278368SAli.Bahrami@Sun.COM break; 5288368SAli.Bahrami@Sun.COM default: 5298368SAli.Bahrami@Sun.COM /* 5308368SAli.Bahrami@Sun.COM * Anything else: If we've already 5318368SAli.Bahrami@Sun.COM * printed this value, don't print 5328368SAli.Bahrami@Sun.COM * it again. 5338368SAli.Bahrami@Sun.COM */ 5348368SAli.Bahrami@Sun.COM if (printed && 5358368SAli.Bahrami@Sun.COM (last_d_val == dyn->d_un.d_val)) 5368368SAli.Bahrami@Sun.COM continue; 5378368SAli.Bahrami@Sun.COM } 5388368SAli.Bahrami@Sun.COM break; 5398368SAli.Bahrami@Sun.COM case PRINT_DYN_T_RUNPATH: 5406225Sab196087 /* 5418368SAli.Bahrami@Sun.COM * If we've already printed this value, 5428368SAli.Bahrami@Sun.COM * don't print it again. This commonly 5438368SAli.Bahrami@Sun.COM * happens when both DT_RPATH and DT_RUNPATH 5448368SAli.Bahrami@Sun.COM * are present with the same value. 5456225Sab196087 */ 5465088Sab196087 if (printed && (last_d_val == dyn->d_un.d_val)) 5475088Sab196087 continue; 5486225Sab196087 break; 5495088Sab196087 } 5505088Sab196087 5515088Sab196087 if ((name != NULL) && 5525088Sab196087 (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) { 5535088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name); 5545088Sab196087 } else { 5555088Sab196087 elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), 5565088Sab196087 dyn->d_un.d_val); 5575088Sab196087 } 5585088Sab196087 } 5595088Sab196087 printed = 1; 5605088Sab196087 last_d_val = dyn->d_un.d_val; 5615088Sab196087 } 5625088Sab196087 5635088Sab196087 /* 5645088Sab196087 * If nothing was output under the print types that are 5655088Sab196087 * based on tag type, issue an error saying it doesn't exist. 5665088Sab196087 */ 5675088Sab196087 if (!printed) { 5685088Sab196087 if (print_type == PRINT_DYN_T_TAG) { 569*9273SAli.Bahrami@Sun.COM Conv_inv_buf_t inv_buf; 570*9273SAli.Bahrami@Sun.COM Ehdr *ehdr = argstate->obj_state->os_ehdr; 5715088Sab196087 5725088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 5735088Sab196087 MSG_INTL(MSG_ERR_NODYNELT), 5745088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 5755088Sab196087 argstate->dyn.sec->sec_name, conv_dyn_tag(arg, 576*9273SAli.Bahrami@Sun.COM ehdr->e_ident[EI_OSABI], ehdr->e_machine, 5775088Sab196087 0, &inv_buf)); 5785088Sab196087 } 5795088Sab196087 5805088Sab196087 if (print_type == PRINT_DYN_T_RUNPATH) 5815088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 5825088Sab196087 MSG_INTL(MSG_ERR_NORUNPATH), 5835088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 5845088Sab196087 argstate->dyn.sec->sec_name); 5855088Sab196087 } 5865088Sab196087 } 5875088Sab196087 5885088Sab196087 5895088Sab196087 /* 5906225Sab196087 * Determine the index(s) of the dynamic element(s) to be displayed and/or 5916225Sab196087 * manipulated. 5925088Sab196087 * 5935088Sab196087 * entry: 5945088Sab196087 * argstate - Argument state block 5956225Sab196087 * arg - If the command being called accepts a first plain argument 5966225Sab196087 * named 'elt' which is used to specify the dynamic element, 5976225Sab196087 * arg is the value of argv[0] for that command. If the 5986225Sab196087 * command does not accept an 'elt' argument and instead 5996225Sab196087 * implicitly assumes a tag type, arg is the constant string 6006225Sab196087 * for that type (e.g. "DT_POSFLAG_1"). 6015088Sab196087 * print_request - True if the command is to print the current 6025088Sab196087 * value(s) and return without changing anything. 6035088Sab196087 * print_type - Address of variable containing PRINT_DYN_T_ 6045088Sab196087 * code specifying how the elements will be displayed. 6055088Sab196087 * 6065088Sab196087 * exit: 6076225Sab196087 * If print_request is False: This routine always returns the index 6086225Sab196087 * of a single dynamic element. *print_type is set to PRINT_DYN_T_NDX. 6096225Sab196087 * The 'elt' argument as well as any modifier options (-dynndx, -needed) 6106225Sab196087 * are examined to determine this index. If there are no modifier options, 6116225Sab196087 * the dynamic section contains no element of the desired type, and there 6126225Sab196087 * is an extra DT_NULL element in the section, then a new element of 6136225Sab196087 * the desired type is created and its index returned. Otherwise an 6146225Sab196087 * error is issued. 6155088Sab196087 * 6166225Sab196087 * If print_request is True: If a modifier (-dynndx, -needed) was used, 6176225Sab196087 * *print_type is set to PRINT_DYN_T_NDX and the index of the 6186225Sab196087 * corresponding single dynamic element is returned. If no modifier 6196225Sab196087 * was used, *print_type is set to PRINT_DYN_T_TAG, and the tag 6206225Sab196087 * type code is returned. 6215088Sab196087 */ 6225088Sab196087 static Word 6236225Sab196087 arg_to_index(ARGSTATE *argstate, const char *arg, 6245088Sab196087 int print_request, PRINT_DYN_T *print_type) 6255088Sab196087 { 626*9273SAli.Bahrami@Sun.COM Word ndx; 627*9273SAli.Bahrami@Sun.COM Xword dt_value; 6286225Sab196087 Dyn *dyn; 6295088Sab196087 6305088Sab196087 6315088Sab196087 /* Assume we are returning an index, alter as needed below */ 6325088Sab196087 *print_type = PRINT_DYN_T_NDX; 6335088Sab196087 6346225Sab196087 /* 6356225Sab196087 * All the commands that accept the DYN_OPT_F_DYNNDX_ELT form 6366225Sab196087 * of -dynndx require a plain argument named 'elt' as their first 6376225Sab196087 * argument. -dynndx is a modifier that means that 'elt' is a 6386225Sab196087 * simple numeric section index. Routines that accept this form 6396225Sab196087 * of -dynndx are willing to handle any tag type, so all we need 6406225Sab196087 * to check is that the value is in range. 6416225Sab196087 */ 6426225Sab196087 if ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0) 6436225Sab196087 return ((Word) elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_ELT), 6446225Sab196087 0, argstate->dyn.num - 1, NULL)); 6456225Sab196087 6466225Sab196087 /* arg is a DT_ tag type, not a numeric index */ 6476225Sab196087 dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT); 6485088Sab196087 6496225Sab196087 /* 6506225Sab196087 * Commands that accept the DYN_OPT_F_DYNNDX_VAL form of 6516225Sab196087 * dynndx do not accept the 'elt' argument. The index is a 6526225Sab196087 * value that follows the option, and was saved in argstate by 6536225Sab196087 * process_args(). Routines that accept this form of -dynndx 6546225Sab196087 * require the specified element to have a specific tag type, 6556225Sab196087 * so we test for this as well as for the index being in range. 6566225Sab196087 */ 6576225Sab196087 if ((argstate->optmask & DYN_OPT_F_DYNNDX_VAL) != 0) { 6586225Sab196087 ndx = ((Word) elfedit_atoui_range(argstate->dyn_elt_str, 6596225Sab196087 MSG_ORIG(MSG_STR_INDEX), 0, argstate->dyn.num - 1, NULL)); 6606225Sab196087 if (argstate->dyn.data[ndx].d_tag != dt_value) { 661*9273SAli.Bahrami@Sun.COM Ehdr *ehdr = argstate->obj_state->os_ehdr; 662*9273SAli.Bahrami@Sun.COM uchar_t osabi = ehdr->e_ident[EI_OSABI]; 663*9273SAli.Bahrami@Sun.COM Half mach = ehdr->e_machine; 6646225Sab196087 Conv_inv_buf_t is, want; 6656225Sab196087 6666225Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_WRONGTAG), 6676225Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 6686225Sab196087 argstate->dyn.sec->sec_name, ndx, 669*9273SAli.Bahrami@Sun.COM conv_dyn_tag(dt_value, osabi, mach, 0, &want), 670*9273SAli.Bahrami@Sun.COM conv_dyn_tag(argstate->dyn.data[ndx].d_tag, 671*9273SAli.Bahrami@Sun.COM osabi, mach, 0, &is)); 6726225Sab196087 } 6736225Sab196087 return (ndx); 6746225Sab196087 } 6755088Sab196087 6765088Sab196087 /* 6775088Sab196087 * If this is a printing request, then we let print_dyn() show 6785088Sab196087 * all the items with this tag type. 6795088Sab196087 */ 6805088Sab196087 if (print_request) { 6815088Sab196087 *print_type = PRINT_DYN_T_TAG; 6825088Sab196087 return (dt_value); 6835088Sab196087 } 6845088Sab196087 6856225Sab196087 /* 6866225Sab196087 * Commands that accept -needed are looking for the dt_value element 6876225Sab196087 * (usually DT_POSFLAG_1) that immediately preceeds the DT_NEEDED 6886225Sab196087 * element with the string given by argstate->dyn_elt_str. 6896225Sab196087 */ 6906225Sab196087 if ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) { 6916225Sab196087 Word retndx = argstate->dyn.num; /* Out of range value */ 6926225Sab196087 const char *name; 6936225Sab196087 size_t len; 6946225Sab196087 6956225Sab196087 len = strlen(argstate->dyn_elt_str); 6966225Sab196087 for (ndx = 0, dyn = argstate->dyn.data; 6976225Sab196087 ndx < argstate->dyn.num; dyn++, ndx++) { 6986225Sab196087 /* 6996225Sab196087 * If the immediately preceeding item has the 7006225Sab196087 * tag type we're looking for, and the current item 7016225Sab196087 * is a DT_NEEDED with a string that matches, 7026225Sab196087 * then the preceeding item is the one we want. 7036225Sab196087 */ 7046225Sab196087 if ((dyn->d_tag == DT_NEEDED) && 7056225Sab196087 (ndx > 0) && (retndx == (ndx - 1))) { 7066225Sab196087 name = elfedit_offset_to_str(argstate->strsec, 7076225Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 7086225Sab196087 7096225Sab196087 if (strncmp(name, 7106225Sab196087 argstate->dyn_elt_str, len) == 0) 7116225Sab196087 return (retndx); 7126225Sab196087 continue; 7136225Sab196087 } 7146225Sab196087 7156225Sab196087 /* 7166225Sab196087 * If the current item has the tag type we're 7176225Sab196087 * looking for, make it our current candidate. 7186225Sab196087 * If the next item is a DT_NEEDED with the right 7196225Sab196087 * string value, we'll use it then. 7206225Sab196087 */ 7216225Sab196087 if (dyn->d_tag == dt_value) 7226225Sab196087 retndx = ndx; 7236225Sab196087 } 7246225Sab196087 7256225Sab196087 /* If we get here, no matching DT_NEEDED was found */ 7266225Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEDNOMATCH), 7276225Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 7286225Sab196087 argstate->dyn.sec->sec_name, argstate->dyn_elt_str); 7296225Sab196087 } 7306225Sab196087 7315088Sab196087 /* Locate the first entry with the given tag type */ 7325088Sab196087 for (ndx = 0; ndx < argstate->dyn.num; ndx++) { 7335088Sab196087 if (argstate->dyn.data[ndx].d_tag == dt_value) { 7345088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 7355088Sab196087 MSG_INTL(MSG_DEBUG_DT2NDX), 7365088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 7375088Sab196087 argstate->dyn.sec->sec_name, EC_WORD(ndx), arg); 7385088Sab196087 return (ndx); 7395088Sab196087 } 7405088Sab196087 } 7415088Sab196087 7425088Sab196087 /* Not found. Can we create one? */ 7435088Sab196087 if (argstate->dyn.num_null_ndx > 1) 7445088Sab196087 return (convert_dt_null(argstate, dt_value, 0)); 7455088Sab196087 7465088Sab196087 /* No room to create one, so we're out of options and must fail */ 7475088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT), 7485088Sab196087 EC_WORD(argstate->dyn.sec->sec_shndx), 7495088Sab196087 argstate->dyn.sec->sec_name, arg); 7505088Sab196087 7515088Sab196087 /*NOTREACHED*/ 7525088Sab196087 return (0); /* For lint */ 7535088Sab196087 } 7545088Sab196087 7555088Sab196087 7565088Sab196087 /* 7575088Sab196087 * Called by cmd_body() for dyn:value. Implements the core functionality 7585088Sab196087 * for that command. 7595088Sab196087 * 7605088Sab196087 * This routine expects that both the index and value arguments are 7615088Sab196087 * present. 7625088Sab196087 */ 7635088Sab196087 static elfedit_cmdret_t 7645088Sab196087 cmd_body_value(ARGSTATE *argstate, Word *ret_ndx) 7655088Sab196087 { 7665088Sab196087 elfedit_section_t *dynsec = argstate->dyn.sec; 7675088Sab196087 elfedit_section_t *strsec = argstate->strsec; 7685088Sab196087 elfedit_dyn_elt_t strpad_elt; 7695088Sab196087 Word i; 7705088Sab196087 Dyn *dyn = argstate->dyn.data; 7715088Sab196087 Word numdyn = argstate->dyn.num; 7726225Sab196087 int minus_add, minus_s, minus_dynndx; 773*9273SAli.Bahrami@Sun.COM Word tmp_val; 774*9273SAli.Bahrami@Sun.COM Xword arg1, arg2; 7755088Sab196087 int arg2_known = 1; 7765088Sab196087 7776225Sab196087 minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0); 7786225Sab196087 minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0); 7796225Sab196087 minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0); 7805088Sab196087 7815088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 7825088Sab196087 7835088Sab196087 /* 7845088Sab196087 * The first argument is an index if -dynndx is used, and is a 7855088Sab196087 * tag value otherwise. 7865088Sab196087 */ 7875088Sab196087 arg1 = minus_dynndx ? 7885088Sab196087 elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT), 7895088Sab196087 0, numdyn - 1, NULL) : 7905088Sab196087 elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT); 7915088Sab196087 7925088Sab196087 if (minus_s) { 7935088Sab196087 /* 7945088Sab196087 * Don't allow the user to specify -s when manipulating a 7955088Sab196087 * DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to 7965088Sab196087 * manage the extra space used for strings, this would break 7975088Sab196087 * our ability to add the string. 7985088Sab196087 */ 7995088Sab196087 if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) || 8005088Sab196087 (minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD))) 8015088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, 8025088Sab196087 MSG_INTL(MSG_ERR_STRPADSTRVAL), 8035088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 8045088Sab196087 8055088Sab196087 /* Locate DT_SUNW_STRPAD element if present */ 8065088Sab196087 strpad_elt.dn_dyn.d_un.d_val = 0; 807*9273SAli.Bahrami@Sun.COM (void) elfedit_dynstr_getpad(argstate->obj_state, 808*9273SAli.Bahrami@Sun.COM argstate->dyn.sec, &strpad_elt); 8095088Sab196087 8105088Sab196087 /* 8115088Sab196087 * Look up the string: If the user specified the -dynndx 8125088Sab196087 * -option, then we will insert it if possible, and 8135088Sab196087 * fail with an error if not. However, if they did not 8145088Sab196087 * specify -dynndx, we want to look up the string if it is 8155088Sab196087 * already there, but defer the insertion. The reason for 8165088Sab196087 * this is that we may have to grab an unused DT_NULL element 8175088Sab196087 * below, and if there are none available, we won't want 8185088Sab196087 * to have modified the string table. 8195088Sab196087 * 8205088Sab196087 * This isn't a problem, because if the string isn't 8215088Sab196087 * in the string table, it can't be used by a dynamic element. 8225088Sab196087 * Hence, we don't need to insert it to know that there is 8235088Sab196087 * no match. 8245088Sab196087 */ 8255088Sab196087 if (minus_dynndx == 0) { 8265088Sab196087 if (elfedit_sec_findstr(strsec, 8275088Sab196087 strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1], 8285088Sab196087 &tmp_val) == 0) { 8295088Sab196087 arg2_known = 0; 8305088Sab196087 } else { 8315088Sab196087 arg2 = tmp_val; 8325088Sab196087 } 8335088Sab196087 } else { 8345088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 8355088Sab196087 &strpad_elt, argstate->argv[1]); 8365088Sab196087 } 8375088Sab196087 } else { /* Argument 2 is an integer */ 8385088Sab196087 arg2 = elfedit_atoui(argstate->argv[1], NULL); 8395088Sab196087 } 8405088Sab196087 8415088Sab196087 8425088Sab196087 if (!minus_dynndx && !(minus_add && !arg2_known)) { 8435088Sab196087 /* 8445088Sab196087 * Search the dynamic section and see if an item with the 8455088Sab196087 * specified tag value already exists. We can reduce this 8465088Sab196087 * to a simple update of an existing value if -add is not 8475088Sab196087 * specified or the existing d_un value matches the new one. 8485088Sab196087 * 8495088Sab196087 * In either of these cases, we will change arg1 to be the 8505088Sab196087 * index, and set minus_dynndx, causing the simple update to 8515088Sab196087 * happen immediately below. 8525088Sab196087 */ 8535088Sab196087 for (i = 0; i < numdyn; i++) { 8545088Sab196087 if ((dyn[i].d_tag == arg1) && 8555088Sab196087 (!minus_add || (dyn[i].d_un.d_val == arg2))) { 8565088Sab196087 arg1 = i; 8575088Sab196087 minus_dynndx = 1; 8585088Sab196087 break; 8595088Sab196087 } 8605088Sab196087 } 8615088Sab196087 } 8625088Sab196087 8635088Sab196087 /* 8645088Sab196087 * If -dynndx is used, then this is a relatively simple 8655088Sab196087 * operation, as we simply write over the specified index. 8665088Sab196087 */ 8675088Sab196087 if (minus_dynndx) { 8685088Sab196087 /* 8695088Sab196087 * If we held back from inserting a new string into 8705088Sab196087 * the dynstr above, we insert it now, because we 8715088Sab196087 * have a slot in the dynamic section, and we need 8725088Sab196087 * the string offset ot finish. 8735088Sab196087 */ 8745088Sab196087 if (!arg2_known) 8755088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 8765088Sab196087 &strpad_elt, argstate->argv[1]); 8775088Sab196087 8785088Sab196087 *ret_ndx = arg1; 8795088Sab196087 if (dyn[arg1].d_un.d_val == arg2) { 8805088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8815088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), 8825088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8835088Sab196087 EC_WORD(arg1), EC_XWORD(arg2)); 8845088Sab196087 return (ELFEDIT_CMDRET_NONE); 8855088Sab196087 } else { 8865088Sab196087 /* Warn if setting DT_NULL value to non-zero */ 8875088Sab196087 if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0)) 8885088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8895088Sab196087 MSG_INTL(MSG_DEBUG_DTNULLVALUE), 8905088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8915088Sab196087 EC_WORD(arg1), EC_XWORD(arg2)); 8925088Sab196087 8935088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 8945088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 8955088Sab196087 dynsec->sec_shndx, dynsec->sec_name, 8965088Sab196087 EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val), 8975088Sab196087 EC_XWORD(arg2)); 8985088Sab196087 dyn[arg1].d_un.d_val = arg2; 8995088Sab196087 return (ELFEDIT_CMDRET_MOD); 9005088Sab196087 } 9015088Sab196087 } 9025088Sab196087 9035088Sab196087 /* 9045088Sab196087 * We need a new slot in the dynamic section. If we can't have 9055088Sab196087 * one, then we fail. 9065088Sab196087 */ 9075088Sab196087 if (argstate->dyn.num_null_ndx <= 1) 9085088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 9095088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 9105088Sab196087 9115088Sab196087 /* 9125088Sab196087 * If we still need to insert a new string into the dynstr, 9135088Sab196087 * then it is safe now, because if we succeed, we know that 9145088Sab196087 * there is an available slot to receive it. If we fail, we 9155088Sab196087 * haven't claimed the extra slot yet, and it will be unharmed. 9165088Sab196087 */ 9175088Sab196087 if (!arg2_known) 9185088Sab196087 arg2 = elfedit_dynstr_insert(dynsec, strsec, 9195088Sab196087 &strpad_elt, argstate->argv[1]); 9205088Sab196087 9215088Sab196087 /* Use an extra DT_NULL slot and enter the new element */ 9225088Sab196087 *ret_ndx = convert_dt_null(argstate, arg1, arg2); 9235088Sab196087 return (ELFEDIT_CMDRET_MOD); 9245088Sab196087 } 9255088Sab196087 9265088Sab196087 9275088Sab196087 9285088Sab196087 /* 9295088Sab196087 * Called by cmd_body() for dyn:runpath. Implements the core functionality 9305088Sab196087 * for that command. 9315088Sab196087 * 9325088Sab196087 * History Lesson And Strategy: 9335088Sab196087 * 9345088Sab196087 * This routine handles both DT_RPATH and DT_RUNPATH entries, altering 9355088Sab196087 * either or both if they are present. 9365088Sab196087 * 9375088Sab196087 * The original SYSV ABI only had DT_RPATH, and the runtime loader used 9385088Sab196087 * it to search for things in the following order: 9395088Sab196087 * 9405088Sab196087 * DT_RPATH, LD_LIBRARY_PATH, defaults 9415088Sab196087 * 9425088Sab196087 * Solaris did not follow this rule, an extremely rare deviation from 9435088Sab196087 * the ABI. Environment variables should supercede everything else, 9445088Sab196087 * otherwise they are not very useful. This decision was made at the 9455088Sab196087 * very beginning of the SunOS 5.x development, so we have always 9465088Sab196087 * deviated from the ABI and and instead search in the order 9475088Sab196087 * 9485088Sab196087 * LD_LIBRARY_PATH, DT_RPATH, defaults 9495088Sab196087 * 9505088Sab196087 * Other Unix variants initially followed the ABI, but in recent years 9515088Sab196087 * have come to agree with the early Solaris folks that it was a mistake. 9525088Sab196087 * Hence, DT_RUNPATH was invented, with the search order: 9535088Sab196087 * 9545088Sab196087 * LD_LIBRARY_PATH, DT_RUNPATH, defaults 9555088Sab196087 * 9565088Sab196087 * So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both 9575088Sab196087 * are present (which does happen), we set them both to the new 9585088Sab196087 * value. If either one is present, we set that one. If neither is 9595088Sab196087 * present, and we have a spare DT_NULL slot, we create a DT_RUNPATH, but 9605088Sab196087 * not a DT_RPATH, to conserve available slots for other uses. 9615088Sab196087 */ 9625088Sab196087 static elfedit_cmdret_t 9635088Sab196087 cmd_body_runpath(ARGSTATE *argstate) 9645088Sab196087 { 9655088Sab196087 elfedit_section_t *dynsec = argstate->dyn.sec; 9665088Sab196087 elfedit_section_t *strsec = argstate->strsec; 9675088Sab196087 elfedit_dyn_elt_t rpath_elt; 9685088Sab196087 elfedit_dyn_elt_t runpath_elt; 9695088Sab196087 elfedit_dyn_elt_t strpad_elt; 9705088Sab196087 Word i; 9715088Sab196087 Dyn *dyn = argstate->dyn.data; 9725088Sab196087 Word numdyn = argstate->dyn.num; 9735088Sab196087 9745088Sab196087 /* Go through the tags and gather what we need */ 9755088Sab196087 elfedit_dyn_elt_init(&rpath_elt); 9765088Sab196087 elfedit_dyn_elt_init(&runpath_elt); 9775088Sab196087 elfedit_dyn_elt_init(&strpad_elt); 9785088Sab196087 for (i = 0; i < numdyn; i++) { 9795088Sab196087 switch (dyn[i].d_tag) { 9805088Sab196087 case DT_RPATH: 9815088Sab196087 elfedit_dyn_elt_save(&rpath_elt, i, &dyn[i]); 9825088Sab196087 break; 9835088Sab196087 9845088Sab196087 case DT_RUNPATH: 9855088Sab196087 elfedit_dyn_elt_save(&runpath_elt, i, &dyn[i]); 9865088Sab196087 break; 9875088Sab196087 9885088Sab196087 case DT_SUNW_STRPAD: 989*9273SAli.Bahrami@Sun.COM if (elfedit_test_osabi(argstate->obj_state, 990*9273SAli.Bahrami@Sun.COM ELFOSABI_SOLARIS, 0)) 991*9273SAli.Bahrami@Sun.COM elfedit_dyn_elt_save(&strpad_elt, i, &dyn[i]); 9925088Sab196087 break; 9935088Sab196087 } 9945088Sab196087 } 9955088Sab196087 9965088Sab196087 /* Do we have an available dynamic section entry to use? */ 9975088Sab196087 if (rpath_elt.dn_seen || runpath_elt.dn_seen) { 9985088Sab196087 /* 9995088Sab196087 * We have seen a DT_RPATH, or a DT_RUNPATH, or both. 10005088Sab196087 * If all of these have the same string as the desired 10015088Sab196087 * new value, then we don't need to alter anything and can 10025088Sab196087 * simply return. Otherwise, we'll modify them all to have 10035088Sab196087 * the new string (below). 10045088Sab196087 */ 10055088Sab196087 if ((!rpath_elt.dn_seen || 10065088Sab196087 (strcmp(elfedit_dyn_offset_to_str(strsec, &rpath_elt), 10075088Sab196087 argstate->argv[0]) == 0)) && 10085088Sab196087 (!runpath_elt.dn_seen || 10095088Sab196087 (strcmp(elfedit_dyn_offset_to_str(strsec, &runpath_elt), 10105088Sab196087 argstate->argv[0]) == 0))) { 10115088Sab196087 if (rpath_elt.dn_seen) 10125088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 10135088Sab196087 MSG_INTL(MSG_DEBUG_OLDRPATHOK), 10145088Sab196087 EC_WORD(dynsec->sec_shndx), 10155088Sab196087 dynsec->sec_name, EC_WORD(rpath_elt.dn_ndx), 10165088Sab196087 elfedit_atoconst_value_to_str( 10175088Sab196087 ELFEDIT_CONST_DT, DT_RPATH, 1)); 10185088Sab196087 if (runpath_elt.dn_seen) 10195088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 10205088Sab196087 MSG_INTL(MSG_DEBUG_OLDRPATHOK), 10215088Sab196087 EC_WORD(dynsec->sec_shndx), 10225088Sab196087 dynsec->sec_name, 10235088Sab196087 EC_WORD(runpath_elt.dn_ndx), 10245088Sab196087 elfedit_atoconst_value_to_str( 10255088Sab196087 ELFEDIT_CONST_DT, DT_RUNPATH, 1)); 10265088Sab196087 return (ELFEDIT_CMDRET_NONE); 10275088Sab196087 } 10285088Sab196087 } else if (argstate->dyn.num_null_ndx <= 1) { 10295088Sab196087 /* 10305088Sab196087 * There is no DT_RPATH or DT_RUNPATH in the dynamic array, 10315088Sab196087 * and there are no extra DT_NULL entries that we can 10325088Sab196087 * convert into one. We cannot proceed. 10335088Sab196087 */ 10345088Sab196087 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 10355088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 10365088Sab196087 } 10375088Sab196087 10385088Sab196087 /* Does the string exist in the table already, or can we add it? */ 10395088Sab196087 rpath_elt.dn_dyn.d_un.d_val = runpath_elt.dn_dyn.d_un.d_val = 10405088Sab196087 elfedit_dynstr_insert(dynsec, strsec, &strpad_elt, 10415088Sab196087 argstate->argv[0]); 10425088Sab196087 10435088Sab196087 /* Update DT_RPATH entry if present */ 10445088Sab196087 if (rpath_elt.dn_seen) { 10455088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_PREVRPATH), 10465088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 10475088Sab196087 EC_WORD(rpath_elt.dn_ndx), 10485088Sab196087 elfedit_atoconst_value_to_str( 10495088Sab196087 ELFEDIT_CONST_DT, DT_RPATH, 1), 10505088Sab196087 elfedit_dyn_offset_to_str(strsec, &rpath_elt)); 10515088Sab196087 dyn[rpath_elt.dn_ndx] = rpath_elt.dn_dyn; 10525088Sab196087 } 10535088Sab196087 10545088Sab196087 /* 10555088Sab196087 * Update the DT_RUNPATH entry in the dynamic section, if present. 10565088Sab196087 * If one is not present, and there is also no DT_RPATH, then 10575088Sab196087 * we use a spare DT_NULL entry to create a new DT_RUNPATH. 10585088Sab196087 */ 10595088Sab196087 if (runpath_elt.dn_seen || !rpath_elt.dn_seen) { 10605088Sab196087 if (runpath_elt.dn_seen) { 10615088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 10625088Sab196087 MSG_INTL(MSG_DEBUG_PREVRPATH), 10635088Sab196087 EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 10645088Sab196087 EC_WORD(runpath_elt.dn_ndx), 10655088Sab196087 elfedit_atoconst_value_to_str( 10665088Sab196087 ELFEDIT_CONST_DT, DT_RUNPATH, 1), 10675088Sab196087 elfedit_dyn_offset_to_str(strsec, &runpath_elt)); 10685088Sab196087 dyn[runpath_elt.dn_ndx] = runpath_elt.dn_dyn; 10695088Sab196087 } else { /* Using a spare DT_NULL entry */ 10705088Sab196087 (void) convert_dt_null(argstate, DT_RUNPATH, 10715088Sab196087 runpath_elt.dn_dyn.d_un.d_val); 10725088Sab196087 } 10735088Sab196087 } 10745088Sab196087 10755088Sab196087 return (ELFEDIT_CMDRET_MOD); 10765088Sab196087 } 10775088Sab196087 10785088Sab196087 10795088Sab196087 10805088Sab196087 /* 10815088Sab196087 * Argument processing for the bitmask commands. Convert the arguments 10825088Sab196087 * to integer form, apply -and/-cmp/-or, and return the resulting value. 10835088Sab196087 * 10845088Sab196087 * entry: 10855088Sab196087 * argstate - Argument state block 10865088Sab196087 * orig - Value of original bitmask 10875088Sab196087 * const_type - ELFEDIT_CONST_* value for type of constants 10885088Sab196087 */ 10895088Sab196087 static Word 10905088Sab196087 flag_bitop(ARGSTATE *argstate, Word orig, elfedit_const_t const_type) 10915088Sab196087 { 10925088Sab196087 Word flags = 0; 10935088Sab196087 int i; 10945088Sab196087 10955088Sab196087 /* Collect the arguments */ 10965088Sab196087 for (i = 0; i < argstate->argc; i++) 10975088Sab196087 flags |= (Word) elfedit_atoconst(argstate->argv[i], const_type); 10985088Sab196087 10995088Sab196087 /* Complement the value? */ 11005088Sab196087 if (argstate->optmask & DYN_OPT_F_CMP) 11015088Sab196087 flags = ~flags; 11025088Sab196087 11035088Sab196087 /* Perform any requested bit operations */ 11045088Sab196087 if (argstate->optmask & DYN_OPT_F_AND) 11055088Sab196087 flags &= orig; 11065088Sab196087 else if (argstate->optmask & DYN_OPT_F_OR) 11075088Sab196087 flags |= orig; 11085088Sab196087 11095088Sab196087 return (flags); 11105088Sab196087 } 11115088Sab196087 11125088Sab196087 11135088Sab196087 11145088Sab196087 /* 11155088Sab196087 * Common body for the dyn: module commands. These commands 11165088Sab196087 * share a large amount of common behavior, so it is convenient 11175088Sab196087 * to centralize things and use the cmd argument to handle the 11185088Sab196087 * small differences. 11195088Sab196087 * 11205088Sab196087 * entry: 11215088Sab196087 * cmd - One of the DYN_CMD_T_* constants listed above, specifying 11225088Sab196087 * which command to implement. 11235088Sab196087 * obj_state, argc, argv - Standard command arguments 11245088Sab196087 */ 11255088Sab196087 static elfedit_cmdret_t 11265088Sab196087 cmd_body(DYN_CMD_T cmd, elfedit_obj_state_t *obj_state, 11275088Sab196087 int argc, const char *argv[]) 11285088Sab196087 { 11295088Sab196087 ARGSTATE argstate; 11305088Sab196087 Dyn *dyn; 11315088Sab196087 const char *dyn_name; 11325088Sab196087 Word dyn_ndx, dyn_num, null_ndx; 11335088Sab196087 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 11345088Sab196087 PRINT_DYN_T print_type = PRINT_DYN_T_ALL; 11355088Sab196087 Word ndx; 11365088Sab196087 int print_only = 0; 11375088Sab196087 int do_autoprint = 1; 11385088Sab196087 11395088Sab196087 /* Process the optional arguments */ 11405088Sab196087 process_args(obj_state, argc, argv, &argstate); 11415088Sab196087 11425088Sab196087 dyn = argstate.dyn.data; 11435088Sab196087 dyn_num = argstate.dyn.num; 11445088Sab196087 dyn_name = argstate.dyn.sec->sec_name; 11455088Sab196087 dyn_ndx = argstate.dyn.sec->sec_shndx; 11465088Sab196087 11475088Sab196087 /* Check number of arguments, gather information */ 11485088Sab196087 switch (cmd) { 11495088Sab196087 case DYN_CMD_T_DUMP: 11505088Sab196087 /* dyn:dump can accept an optional index argument */ 11515088Sab196087 if (argstate.argc > 1) 11525088Sab196087 elfedit_command_usage(); 11535088Sab196087 print_only = 1; 11545088Sab196087 if (argstate.argc == 1) 11555088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11566225Sab196087 print_only, &print_type); 11575088Sab196087 break; 11585088Sab196087 11595088Sab196087 case DYN_CMD_T_TAG: 11605088Sab196087 print_only = (argstate.argc != 2); 11615088Sab196087 if (argstate.argc > 0) { 11625088Sab196087 if (argstate.argc > 2) 11635088Sab196087 elfedit_command_usage(); 11645088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11656225Sab196087 print_only, &print_type); 11665088Sab196087 } 11675088Sab196087 break; 11685088Sab196087 11695088Sab196087 case DYN_CMD_T_VALUE: 11705088Sab196087 print_only = (argstate.argc != 2); 11715088Sab196087 if (argstate.argc > 2) 11725088Sab196087 elfedit_command_usage(); 11735088Sab196087 if (argstate.argc > 0) { 11745088Sab196087 if (print_only) { 11755088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11765088Sab196087 print_only, &print_type); 11775088Sab196087 } else { 11785088Sab196087 print_type = PRINT_DYN_T_NDX; 11795088Sab196087 } 11805088Sab196087 } 11815088Sab196087 break; 11825088Sab196087 11835088Sab196087 case DYN_CMD_T_DELETE: 11845088Sab196087 if ((argstate.argc < 1) || (argstate.argc > 2)) 11855088Sab196087 elfedit_command_usage(); 11865088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11875088Sab196087 0, &print_type); 11885088Sab196087 do_autoprint = 0; 11895088Sab196087 break; 11905088Sab196087 11915088Sab196087 case DYN_CMD_T_MOVE: 11925088Sab196087 if ((argstate.argc < 2) || (argstate.argc > 3)) 11935088Sab196087 elfedit_command_usage(); 11945088Sab196087 ndx = arg_to_index(&argstate, argstate.argv[0], 11956225Sab196087 0, &print_type); 11965088Sab196087 do_autoprint = 0; 11975088Sab196087 break; 11985088Sab196087 11995088Sab196087 case DYN_CMD_T_RUNPATH: 12005088Sab196087 if (argstate.argc > 1) 12015088Sab196087 elfedit_command_usage(); 12025088Sab196087 /* 12035088Sab196087 * dyn:runpath does not accept an explicit index 12045088Sab196087 * argument, so we implicitly only show the DT_RPATH and 12055088Sab196087 * DT_RUNPATH elements. 12065088Sab196087 */ 12075088Sab196087 print_type = PRINT_DYN_T_RUNPATH; 12085088Sab196087 print_only = (argstate.argc == 0); 12095088Sab196087 break; 12105088Sab196087 12115088Sab196087 case DYN_CMD_T_POSFLAG1: 12125088Sab196087 print_only = (argstate.argc == 0); 12135088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12145088Sab196087 ELFEDIT_CONST_DT, DT_POSFLAG_1, 1), 12156225Sab196087 print_only, &print_type); 12165088Sab196087 break; 12175088Sab196087 12185088Sab196087 case DYN_CMD_T_FLAGS: 12195088Sab196087 print_only = (argstate.argc == 0); 12205088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12215088Sab196087 ELFEDIT_CONST_DT, DT_FLAGS, 1), 12226225Sab196087 print_only, &print_type); 12235088Sab196087 break; 12245088Sab196087 12255088Sab196087 case DYN_CMD_T_FLAGS1: 12265088Sab196087 print_only = (argstate.argc == 0); 12275088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12285088Sab196087 ELFEDIT_CONST_DT, DT_FLAGS_1, 1), 12296225Sab196087 print_only, &print_type); 12305088Sab196087 break; 12315088Sab196087 12325088Sab196087 case DYN_CMD_T_FEATURE1: 12335088Sab196087 print_only = (argstate.argc == 0); 12345088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12355088Sab196087 ELFEDIT_CONST_DT, DT_FEATURE_1, 1), 12366225Sab196087 print_only, &print_type); 12375088Sab196087 break; 12385088Sab196087 12395088Sab196087 case DYN_CMD_T_CHECKSUM: 12405088Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12415088Sab196087 ELFEDIT_CONST_DT, DT_CHECKSUM, 1), 12426225Sab196087 print_only, &print_type); 12435088Sab196087 break; 12445088Sab196087 12456206Sab196087 case DYN_CMD_T_SUNW_LDMACH: 12466206Sab196087 if (argstate.argc > 1) 12476206Sab196087 elfedit_command_usage(); 1248*9273SAli.Bahrami@Sun.COM /* DT_SUNW_LDMACH is an ELFOSABI_SOLARIS feature */ 1249*9273SAli.Bahrami@Sun.COM (void) elfedit_test_osabi(argstate.obj_state, 1250*9273SAli.Bahrami@Sun.COM ELFOSABI_SOLARIS, 1); 12516206Sab196087 print_only = (argstate.argc == 0); 12526206Sab196087 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 12536206Sab196087 ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1), 12546225Sab196087 print_only, &print_type); 12556206Sab196087 break; 12566206Sab196087 12575088Sab196087 default: 12585088Sab196087 /* Note expected: All commands should have been caught above */ 12595088Sab196087 elfedit_command_usage(); 12605088Sab196087 break; 12615088Sab196087 } 12625088Sab196087 12635088Sab196087 12645088Sab196087 /* If this is a request to print current values, do it and return */ 12655088Sab196087 if (print_only) { 12665088Sab196087 print_dyn(cmd, 0, &argstate, print_type, ndx); 12675088Sab196087 return (ELFEDIT_CMDRET_NONE); 12685088Sab196087 } 12695088Sab196087 12705088Sab196087 12715088Sab196087 switch (cmd) { 12725088Sab196087 /* 12735088Sab196087 * DYN_CMD_T_DUMP can't get here: It is a print-only 12745088Sab196087 * command. 12755088Sab196087 */ 12765088Sab196087 12775088Sab196087 case DYN_CMD_T_TAG: 12785088Sab196087 { 1279*9273SAli.Bahrami@Sun.COM Ehdr *ehdr = argstate.obj_state->os_ehdr; 1280*9273SAli.Bahrami@Sun.COM uchar_t osabi = ehdr->e_ident[EI_OSABI]; 1281*9273SAli.Bahrami@Sun.COM Half mach = ehdr->e_machine; 12825088Sab196087 Conv_inv_buf_t inv_buf1, inv_buf2; 1283*9273SAli.Bahrami@Sun.COM Xword d_tag = (Xword) elfedit_atoconst(argstate.argv[1], 12845088Sab196087 ELFEDIT_CONST_DT); 12855088Sab196087 12865088Sab196087 if (dyn[ndx].d_tag == d_tag) { 12875088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 1288*9273SAli.Bahrami@Sun.COM MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, dyn_name, 1289*9273SAli.Bahrami@Sun.COM EC_WORD(ndx), conv_dyn_tag(d_tag, osabi, 1290*9273SAli.Bahrami@Sun.COM mach, 0, &inv_buf1)); 12915088Sab196087 } else { 1292*9273SAli.Bahrami@Sun.COM Xword orig_d_tag = dyn[ndx].d_tag; 12935088Sab196087 12945088Sab196087 ret = ELFEDIT_CMDRET_MOD; 12955088Sab196087 dyn[ndx].d_tag = d_tag; 12965088Sab196087 12975088Sab196087 /* 12985088Sab196087 * Update null termination index. Warn if we 12995088Sab196087 * just clobbered the only DT_NULL termination 13005088Sab196087 * for the array. 13015088Sab196087 */ 13025088Sab196087 null_ndx = argstate.dyn.null_ndx; 13035088Sab196087 set_null_ndx(&argstate); 13045088Sab196087 if ((argstate.dyn.null_ndx >= 13055088Sab196087 argstate.dyn.num) && 13065088Sab196087 (null_ndx != argstate.dyn.null_ndx)) 13075088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13085088Sab196087 MSG_INTL(MSG_DEBUG_NULLTERM), 13095088Sab196087 dyn_ndx, dyn_name, 1310*9273SAli.Bahrami@Sun.COM EC_WORD(ndx), conv_dyn_tag(d_tag, 1311*9273SAli.Bahrami@Sun.COM osabi, mach, 0, &inv_buf1)); 13125088Sab196087 13135088Sab196087 /* 13145088Sab196087 * Warning if 13155088Sab196087 * - Inserting a DT_NULL cuts off following 13165088Sab196087 * non-null elements. 13175088Sab196087 * - Inserting a non-DT_NULL after the 13185088Sab196087 * first null element, will be 13195088Sab196087 * ignored by rtld. 13205088Sab196087 */ 13215088Sab196087 if (d_tag == DT_NULL) { 13225088Sab196087 if ((ndx + 1) < null_ndx) 13235088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13245088Sab196087 MSG_INTL(MSG_DEBUG_NULCLIP), 13255088Sab196087 dyn_ndx, dyn_name, 13265088Sab196087 EC_WORD(ndx), 1327*9273SAli.Bahrami@Sun.COM conv_dyn_tag(d_tag, osabi, 1328*9273SAli.Bahrami@Sun.COM mach, 0, &inv_buf1)); 13295088Sab196087 } else { 13305088Sab196087 if ((ndx + 1) > argstate.dyn.null_ndx) 13315088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13325088Sab196087 MSG_INTL(MSG_DEBUG_NULHIDE), 13335088Sab196087 dyn_ndx, dyn_name, 13345088Sab196087 EC_WORD(ndx), 1335*9273SAli.Bahrami@Sun.COM conv_dyn_tag(d_tag, osabi, 1336*9273SAli.Bahrami@Sun.COM mach, 0, &inv_buf1)); 13375088Sab196087 } 13385088Sab196087 13395088Sab196087 /* Debug message that we changed it */ 13405088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 13415088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 13425088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 1343*9273SAli.Bahrami@Sun.COM conv_dyn_tag(orig_d_tag, osabi, mach, 0, 13445088Sab196087 &inv_buf1), 1345*9273SAli.Bahrami@Sun.COM conv_dyn_tag(d_tag, osabi, mach, 0, 1346*9273SAli.Bahrami@Sun.COM &inv_buf2)); 13475088Sab196087 } 13485088Sab196087 } 13495088Sab196087 break; 13505088Sab196087 13515088Sab196087 case DYN_CMD_T_VALUE: 13525088Sab196087 ret = cmd_body_value(&argstate, &ndx); 13535088Sab196087 break; 13545088Sab196087 13555088Sab196087 case DYN_CMD_T_DELETE: 13565088Sab196087 { 13575088Sab196087 Word cnt = (argstate.argc == 1) ? 1 : 13585088Sab196087 (Word) elfedit_atoui_range(argstate.argv[1], 13595088Sab196087 MSG_ORIG(MSG_STR_COUNT), 1, dyn_num - ndx, NULL); 13605088Sab196087 const char *msg_prefix = 13615088Sab196087 elfedit_sec_msgprefix(argstate.dyn.sec); 13625088Sab196087 13635088Sab196087 elfedit_array_elts_delete(msg_prefix, argstate.dyn.data, 13645088Sab196087 sizeof (Dyn), dyn_num, ndx, cnt); 13655088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13665088Sab196087 } 13675088Sab196087 break; 13685088Sab196087 13695088Sab196087 case DYN_CMD_T_MOVE: 13705088Sab196087 { 13715088Sab196087 Dyn save; 13725088Sab196087 Word cnt; 13735088Sab196087 Word dstndx; 13745088Sab196087 const char *msg_prefix = 13755088Sab196087 elfedit_sec_msgprefix(argstate.dyn.sec); 13765088Sab196087 13775088Sab196087 dstndx = (Word) 13785088Sab196087 elfedit_atoui_range(argstate.argv[1], 13795088Sab196087 MSG_ORIG(MSG_STR_DST_INDEX), 0, dyn_num - 1, 13805088Sab196087 NULL); 13815088Sab196087 if (argstate.argc == 2) { 13825088Sab196087 cnt = 1; 13835088Sab196087 } else { 13845088Sab196087 cnt = (Word) elfedit_atoui_range( 13855088Sab196087 argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), 13865088Sab196087 1, dyn_num, NULL); 13875088Sab196087 } 13885088Sab196087 elfedit_array_elts_move(msg_prefix, argstate.dyn.data, 13895088Sab196087 sizeof (save), dyn_num, ndx, dstndx, cnt, &save); 13905088Sab196087 ret = ELFEDIT_CMDRET_MOD; 13915088Sab196087 } 13925088Sab196087 break; 13935088Sab196087 13945088Sab196087 13955088Sab196087 case DYN_CMD_T_RUNPATH: 13965088Sab196087 ret = cmd_body_runpath(&argstate); 13975088Sab196087 break; 13985088Sab196087 13995088Sab196087 case DYN_CMD_T_POSFLAG1: 14005088Sab196087 { 14015088Sab196087 Conv_dyn_posflag1_buf_t buf1, buf2; 14025088Sab196087 Word flags; 14035088Sab196087 14045088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14055088Sab196087 ELFEDIT_CONST_DF_P1); 14065088Sab196087 14075088Sab196087 /* Set the value */ 14085088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 14095088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14105088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14115088Sab196087 dyn_name, EC_WORD(ndx), 14125088Sab196087 conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 14135088Sab196087 &buf1)); 14145088Sab196087 } else { 14155088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14165088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14175088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14185088Sab196087 conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 14195088Sab196087 &buf1), 14205088Sab196087 conv_dyn_posflag1(flags, 0, &buf2)); 14215088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14225088Sab196087 dyn[ndx].d_un.d_val = flags; 14235088Sab196087 } 14245088Sab196087 } 14255088Sab196087 break; 14265088Sab196087 14275088Sab196087 case DYN_CMD_T_FLAGS: 14285088Sab196087 { 14295088Sab196087 Conv_dyn_flag_buf_t buf1, buf2; 14305088Sab196087 Word flags; 14315088Sab196087 14325088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14335088Sab196087 ELFEDIT_CONST_DF); 14345088Sab196087 14355088Sab196087 /* Set the value */ 14365088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 14375088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14385088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14395088Sab196087 dyn_name, EC_WORD(ndx), 14405088Sab196087 conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 14415088Sab196087 &buf1)); 14425088Sab196087 } else { 14435088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14445088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14455088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14465088Sab196087 conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 14475088Sab196087 &buf1), 14485088Sab196087 conv_dyn_flag(flags, 0, &buf2)); 14495088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14505088Sab196087 dyn[ndx].d_un.d_val = flags; 14515088Sab196087 } 14525088Sab196087 } 14535088Sab196087 break; 14545088Sab196087 14555088Sab196087 case DYN_CMD_T_FLAGS1: 14565088Sab196087 { 14575088Sab196087 Conv_dyn_flag1_buf_t buf1, buf2; 14585088Sab196087 Word flags1; 14595088Sab196087 14605088Sab196087 flags1 = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14615088Sab196087 ELFEDIT_CONST_DF_1); 14625088Sab196087 14635088Sab196087 /* Set the value */ 14645088Sab196087 if (dyn[ndx].d_un.d_val == flags1) { 14655088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14665088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14675088Sab196087 dyn_name, EC_WORD(ndx), 14685088Sab196087 conv_dyn_flag1(dyn[ndx].d_un.d_val, 14695088Sab196087 0, &buf1)); 14705088Sab196087 } else { 14715088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14725088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 14735088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 14745088Sab196087 conv_dyn_flag1(dyn[ndx].d_un.d_val, 14755088Sab196087 0, &buf1), 14765088Sab196087 conv_dyn_flag1(flags1, 0, &buf2)); 14775088Sab196087 ret = ELFEDIT_CMDRET_MOD; 14785088Sab196087 dyn[ndx].d_un.d_val = flags1; 14795088Sab196087 } 14805088Sab196087 } 14815088Sab196087 break; 14825088Sab196087 14835088Sab196087 case DYN_CMD_T_FEATURE1: 14845088Sab196087 { 14855088Sab196087 Conv_dyn_feature1_buf_t buf1, buf2; 14865088Sab196087 Word flags; 14875088Sab196087 14885088Sab196087 flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 14895088Sab196087 ELFEDIT_CONST_DTF_1); 14905088Sab196087 14915088Sab196087 /* Set the value */ 14925088Sab196087 if (dyn[ndx].d_un.d_val == flags) { 14935088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 14945088Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 14955088Sab196087 dyn_name, EC_WORD(ndx), 14965088Sab196087 conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 14975088Sab196087 &buf1)); 14985088Sab196087 } else { 14995088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15005088Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 15015088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 15025088Sab196087 conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 15035088Sab196087 &buf1), 15045088Sab196087 conv_dyn_feature1(flags, 0, &buf2)); 15055088Sab196087 ret = ELFEDIT_CMDRET_MOD; 15065088Sab196087 dyn[ndx].d_un.d_val = flags; 15075088Sab196087 } 15085088Sab196087 } 15095088Sab196087 break; 15105088Sab196087 15115088Sab196087 case DYN_CMD_T_CHECKSUM: 15125088Sab196087 { 15135088Sab196087 long checksum = elf_checksum(obj_state->os_elf); 15145088Sab196087 15155088Sab196087 /* Set the value */ 15165088Sab196087 if (dyn[ndx].d_un.d_val == checksum) { 15175088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15185088Sab196087 MSG_INTL(MSG_DEBUG_X_OK), dyn_ndx, 15195088Sab196087 dyn_name, EC_WORD(ndx), EC_XWORD(checksum)); 15205088Sab196087 } else { 15215088Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15225088Sab196087 MSG_INTL(MSG_DEBUG_X_CHG), 15235088Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 15245088Sab196087 EC_XWORD(dyn[ndx].d_un.d_val), 15255088Sab196087 EC_XWORD(checksum)); 15265088Sab196087 ret = ELFEDIT_CMDRET_MOD; 15275088Sab196087 dyn[ndx].d_un.d_val = checksum; 15285088Sab196087 } 15295088Sab196087 15305088Sab196087 } 15316206Sab196087 break; 15326206Sab196087 15336206Sab196087 case DYN_CMD_T_SUNW_LDMACH: 15346206Sab196087 { 15356206Sab196087 Conv_inv_buf_t buf1, buf2; 15366206Sab196087 Half ldmach; 15376206Sab196087 15386206Sab196087 ldmach = (Half) elfedit_atoconst(argstate.argv[0], 15396206Sab196087 ELFEDIT_CONST_EM); 15406206Sab196087 15416206Sab196087 /* Set the value */ 15426206Sab196087 if (dyn[ndx].d_un.d_val == ldmach) { 15436206Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15446206Sab196087 MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 15456206Sab196087 dyn_name, EC_WORD(ndx), 15466206Sab196087 conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 15476206Sab196087 &buf1)); 15486206Sab196087 } else { 15496206Sab196087 elfedit_msg(ELFEDIT_MSG_DEBUG, 15506206Sab196087 MSG_INTL(MSG_DEBUG_S_CHG), 15516206Sab196087 dyn_ndx, dyn_name, EC_WORD(ndx), 15526206Sab196087 conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 15536206Sab196087 &buf1), 15546206Sab196087 conv_ehdr_mach(ldmach, 0, &buf2)); 15556206Sab196087 ret = ELFEDIT_CMDRET_MOD; 15566206Sab196087 dyn[ndx].d_un.d_val = ldmach; 15576206Sab196087 } 15586206Sab196087 } 15596206Sab196087 break; 15606206Sab196087 15615088Sab196087 } 15625088Sab196087 15635088Sab196087 /* 15645088Sab196087 * If we modified the dynamic section header, tell libelf. 15655088Sab196087 */ 15665088Sab196087 if (ret == ELFEDIT_CMDRET_MOD) 15675088Sab196087 elfedit_modified_data(argstate.dyn.sec); 15685088Sab196087 15695088Sab196087 /* Do autoprint */ 15705088Sab196087 if (do_autoprint) 15715088Sab196087 print_dyn(cmd, 1, &argstate, print_type, ndx); 15725088Sab196087 15735088Sab196087 return (ret); 15745088Sab196087 } 15755088Sab196087 15765088Sab196087 15775088Sab196087 15785088Sab196087 /* 15795088Sab196087 * Command completion functions for the commands 15805088Sab196087 */ 15815088Sab196087 15825088Sab196087 /* 15835088Sab196087 * Command completion for the first argument, which specifies 15845088Sab196087 * the dynamic element to use. Examines the options to see if 15855088Sab196087 * -dynndx is present, and if not, supplies the completion 15865088Sab196087 * strings for argument 1. 15875088Sab196087 */ 15885088Sab196087 /*ARGSUSED*/ 15895088Sab196087 static void 15905088Sab196087 cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 15915088Sab196087 const char *argv[], int num_opt) 15925088Sab196087 { 15935088Sab196087 elfedit_section_t *cache; 15945088Sab196087 Dyn *dyn; 15955088Sab196087 Word i; 15965088Sab196087 const char *s; 15975088Sab196087 char *s2; 15985088Sab196087 char buf[128]; 15995088Sab196087 16005088Sab196087 /* Make sure it's the first argument */ 16015088Sab196087 if ((argc - num_opt) != 1) 16025088Sab196087 return; 16035088Sab196087 16045088Sab196087 /* Is -dynndx present? If so, we don't complete tag types */ 16055088Sab196087 for (i = 0; i < num_opt; i++) 16065088Sab196087 if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0) 16075088Sab196087 return; 16085088Sab196087 16095088Sab196087 /* 16105088Sab196087 * If there is no object, or if there is no dynamic section, 16115088Sab196087 * then supply all possible names. 16125088Sab196087 */ 16135088Sab196087 if ((obj_state == NULL) || (obj_state->os_dynndx == SHN_UNDEF)) { 16145088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 16155088Sab196087 return; 16165088Sab196087 } 16175088Sab196087 16185088Sab196087 /* Supply completions for the tags present in the dynamic section */ 16195088Sab196087 cache = &obj_state->os_secarr[obj_state->os_dynndx]; 16205088Sab196087 dyn = (Dyn *) cache->sec_data->d_buf; 16215088Sab196087 i = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize; 16225088Sab196087 for (; i-- > 0; dyn++) { 16235088Sab196087 s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_DT, 16245088Sab196087 dyn->d_tag, 0); 16255088Sab196087 if (s == NULL) 16265088Sab196087 continue; 16275088Sab196087 elfedit_cpl_match(cpldata, s, 1); 16285088Sab196087 16295088Sab196087 /* 16305088Sab196087 * To get the informal tag names that are lowercase 16315088Sab196087 * and lack the leading DT_, we copy the string we 16325088Sab196087 * have into a buffer and process it. 16335088Sab196087 */ 16345088Sab196087 if (strlen(s) < 3) 16355088Sab196087 continue; 16365088Sab196087 (void) strlcpy(buf, s + 3, sizeof (buf)); 16375088Sab196087 for (s2 = buf; *s2 != '\0'; s2++) 16385088Sab196087 if (isupper(*s2)) 16395088Sab196087 *s2 = tolower(*s2); 16405088Sab196087 elfedit_cpl_match(cpldata, buf, 1); 16415088Sab196087 } 16425088Sab196087 } 16435088Sab196087 16445088Sab196087 16455088Sab196087 /*ARGSUSED*/ 16465088Sab196087 static void 16475088Sab196087 cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16485088Sab196087 const char *argv[], int num_opt) 16495088Sab196087 { 16505088Sab196087 /* First argument */ 16515088Sab196087 if ((argc - num_opt) == 1) { 16525088Sab196087 cpl_eltarg(obj_state, cpldata, argc, argv, num_opt); 16535088Sab196087 return; 16545088Sab196087 } 16555088Sab196087 16565088Sab196087 /* The second argument is always a tag value */ 16575088Sab196087 if ((argc - num_opt) == 2) 16585088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 16595088Sab196087 } 16605088Sab196087 16615088Sab196087 /*ARGSUSED*/ 16625088Sab196087 static void 16635088Sab196087 cpl_posflag1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 16645088Sab196087 const char *argv[], int num_opt) 16655088Sab196087 { 16666225Sab196087 /* 16676225Sab196087 * dyn:posflag1 accepts two mutually exclusive options that have 16686225Sab196087 * a corresponding value argument: -dynndx and -needed. If we 16696225Sab196087 * are being called to supply options for the value, handle that here. 16706225Sab196087 */ 16716225Sab196087 if ((num_opt > 1) && (argc == num_opt)) { 16726225Sab196087 elfedit_section_t *dynsec, *strsec; 16736225Sab196087 const char *opt = argv[num_opt - 2]; 16746225Sab196087 dyn_opt_t type; 16756225Sab196087 Dyn *dyn; 16766225Sab196087 Word i, num; 16776225Sab196087 16786225Sab196087 /* 16796225Sab196087 * If there is no object available, or if the object has no 16806225Sab196087 * dynamic section, then there is nothing to report. 16816225Sab196087 */ 16826225Sab196087 if ((obj_state == NULL) || obj_state->os_dynndx == SHN_UNDEF) 16836225Sab196087 return; 16846225Sab196087 16856225Sab196087 /* 16866225Sab196087 * Determine which option it is, bail if it isn't one of 16876225Sab196087 * the ones we are concerned with. 16886225Sab196087 */ 16896225Sab196087 if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_NEEDED)) == 0)) 16906225Sab196087 type = DYN_OPT_F_NEEDED; 16916225Sab196087 else if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0)) 16926225Sab196087 type = DYN_OPT_F_DYNNDX_VAL; 16936225Sab196087 else 16946225Sab196087 return; 16956225Sab196087 16966225Sab196087 dynsec = elfedit_sec_getdyn(obj_state, &dyn, &num); 16976225Sab196087 switch (type) { 16986225Sab196087 case DYN_OPT_F_NEEDED: 16996225Sab196087 strsec = elfedit_sec_getstr(obj_state, 17006225Sab196087 dynsec->sec_shdr->sh_link, 0); 17016225Sab196087 for (; num-- > 0; dyn++) 17026225Sab196087 if (dyn->d_tag == DT_NEEDED) 17036225Sab196087 elfedit_cpl_match(cpldata, 17046225Sab196087 elfedit_offset_to_str(strsec, 17056225Sab196087 dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 17066225Sab196087 0), 0); 17076225Sab196087 break; 17086225Sab196087 17096225Sab196087 case DYN_OPT_F_DYNNDX_VAL: 17106225Sab196087 for (i = 0; i < num; i++, dyn++) 17116225Sab196087 if (dyn->d_tag == DT_POSFLAG_1) 17126225Sab196087 elfedit_cpl_ndx(cpldata, i); 17136225Sab196087 break; 17146225Sab196087 } 17156225Sab196087 return; 17166225Sab196087 } 17176225Sab196087 17185088Sab196087 /* This routine allows multiple flags to be specified */ 17195088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_P1); 17205088Sab196087 } 17215088Sab196087 17225088Sab196087 /*ARGSUSED*/ 17235088Sab196087 static void 17245088Sab196087 cpl_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17255088Sab196087 const char *argv[], int num_opt) 17265088Sab196087 { 17275088Sab196087 /* This routine allows multiple flags to be specified */ 17285088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF); 17295088Sab196087 } 17305088Sab196087 17315088Sab196087 /*ARGSUSED*/ 17325088Sab196087 static void 17335088Sab196087 cpl_flags1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17345088Sab196087 const char *argv[], int num_opt) 17355088Sab196087 { 17365088Sab196087 /* This routine allows multiple flags to be specified */ 17375088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_1); 17385088Sab196087 } 17395088Sab196087 17405088Sab196087 /*ARGSUSED*/ 17415088Sab196087 static void 17425088Sab196087 cpl_feature1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17435088Sab196087 const char *argv[], int num_opt) 17445088Sab196087 { 17455088Sab196087 /* This routine allows multiple flags to be specified */ 17465088Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1); 17475088Sab196087 } 17485088Sab196087 17496206Sab196087 /*ARGSUSED*/ 17506206Sab196087 static void 17516206Sab196087 cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 17526206Sab196087 const char *argv[], int num_opt) 17536206Sab196087 { 17546206Sab196087 /* 17556206Sab196087 * This command doesn't accept options, so num_opt should be 17566206Sab196087 * 0. This is a defensive measure, in case that should change. 17576206Sab196087 */ 17586206Sab196087 argc -= num_opt; 17596206Sab196087 argv += num_opt; 17606206Sab196087 17616206Sab196087 if (argc == 1) 17626206Sab196087 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM); 17636206Sab196087 } 17646206Sab196087 17655088Sab196087 17665088Sab196087 /* 17675088Sab196087 * Implementation functions for the commands 17685088Sab196087 */ 17695088Sab196087 static elfedit_cmdret_t 17705088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17715088Sab196087 { 17725088Sab196087 return (cmd_body(DYN_CMD_T_DUMP, obj_state, argc, argv)); 17735088Sab196087 } 17745088Sab196087 17755088Sab196087 static elfedit_cmdret_t 17765088Sab196087 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17775088Sab196087 { 17785088Sab196087 return (cmd_body(DYN_CMD_T_TAG, obj_state, argc, argv)); 17795088Sab196087 } 17805088Sab196087 17815088Sab196087 static elfedit_cmdret_t 17825088Sab196087 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17835088Sab196087 { 17845088Sab196087 return (cmd_body(DYN_CMD_T_VALUE, obj_state, argc, argv)); 17855088Sab196087 } 17865088Sab196087 17875088Sab196087 static elfedit_cmdret_t 17885088Sab196087 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17895088Sab196087 { 17905088Sab196087 return (cmd_body(DYN_CMD_T_DELETE, obj_state, argc, argv)); 17915088Sab196087 } 17925088Sab196087 17935088Sab196087 static elfedit_cmdret_t 17945088Sab196087 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 17955088Sab196087 { 17965088Sab196087 return (cmd_body(DYN_CMD_T_MOVE, obj_state, argc, argv)); 17975088Sab196087 } 17985088Sab196087 17995088Sab196087 static elfedit_cmdret_t 18005088Sab196087 cmd_runpath(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18015088Sab196087 { 18025088Sab196087 return (cmd_body(DYN_CMD_T_RUNPATH, obj_state, argc, argv)); 18035088Sab196087 } 18045088Sab196087 18055088Sab196087 static elfedit_cmdret_t 18065088Sab196087 cmd_posflag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18075088Sab196087 { 18085088Sab196087 return (cmd_body(DYN_CMD_T_POSFLAG1, obj_state, argc, argv)); 18095088Sab196087 } 18105088Sab196087 18115088Sab196087 static elfedit_cmdret_t 18125088Sab196087 cmd_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18135088Sab196087 { 18145088Sab196087 return (cmd_body(DYN_CMD_T_FLAGS, obj_state, argc, argv)); 18155088Sab196087 } 18165088Sab196087 18175088Sab196087 static elfedit_cmdret_t 18185088Sab196087 cmd_flags1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18195088Sab196087 { 18205088Sab196087 return (cmd_body(DYN_CMD_T_FLAGS1, obj_state, argc, argv)); 18215088Sab196087 } 18225088Sab196087 18235088Sab196087 static elfedit_cmdret_t 18245088Sab196087 cmd_feature1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18255088Sab196087 { 18265088Sab196087 return (cmd_body(DYN_CMD_T_FEATURE1, obj_state, argc, argv)); 18275088Sab196087 } 18285088Sab196087 18295088Sab196087 static elfedit_cmdret_t 18305088Sab196087 cmd_checksum(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18315088Sab196087 { 18325088Sab196087 return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv)); 18335088Sab196087 } 18345088Sab196087 18356206Sab196087 static elfedit_cmdret_t 18366206Sab196087 cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 18376206Sab196087 { 18386206Sab196087 return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv)); 18396206Sab196087 } 18406206Sab196087 18415088Sab196087 18425088Sab196087 18435088Sab196087 /*ARGSUSED*/ 18445088Sab196087 elfedit_module_t * 18455088Sab196087 elfedit_init(elfedit_module_version_t version) 18465088Sab196087 { 18475088Sab196087 /* For commands that only accept -o */ 18485088Sab196087 static elfedit_cmd_optarg_t opt_ostyle[] = { 18495088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18505088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18515088Sab196087 { NULL } 18525088Sab196087 }; 18535088Sab196087 18545088Sab196087 /* For commands that only accept -and, -cmp, -o, -or */ 18555088Sab196087 static elfedit_cmd_optarg_t opt_ostyle_bitop[] = { 18565088Sab196087 { ELFEDIT_STDOA_OPT_AND, NULL, 18575088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 18585088Sab196087 { ELFEDIT_STDOA_OPT_CMP, NULL, 18595088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 18605088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18615088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 18625088Sab196087 { ELFEDIT_STDOA_OPT_OR, NULL, 18635088Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 18645088Sab196087 { NULL } 18655088Sab196087 }; 18665088Sab196087 18675088Sab196087 /* For commands that only accept -dynndx */ 18685088Sab196087 static elfedit_cmd_optarg_t opt_minus_dynndx[] = { 18695088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 18706225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 18716225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 18726225Sab196087 DYN_OPT_F_DYNNDX_ELT, 0 }, 18735088Sab196087 { NULL } 18745088Sab196087 }; 18755088Sab196087 18765088Sab196087 /* dyn:dump */ 18775088Sab196087 static const char *name_dump[] = { 18785088Sab196087 MSG_ORIG(MSG_CMD_DUMP), 18795088Sab196087 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 18805088Sab196087 NULL 18815088Sab196087 }; 18825088Sab196087 static elfedit_cmd_optarg_t arg_dump[] = { 18835088Sab196087 { MSG_ORIG(MSG_STR_ELT), 18845088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 18855088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 18865088Sab196087 ELFEDIT_CMDOA_F_OPT }, 18875088Sab196087 { NULL } 18885088Sab196087 }; 18895088Sab196087 18905088Sab196087 18915088Sab196087 /* dyn:tag */ 18925088Sab196087 static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL }; 18935088Sab196087 static elfedit_cmd_optarg_t opt_tag[] = { 18945088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 18956225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 18966225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 18976225Sab196087 DYN_OPT_F_DYNNDX_ELT, 0 }, 18985088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 18995088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 19005088Sab196087 { NULL } 19015088Sab196087 }; 19025088Sab196087 static elfedit_cmd_optarg_t arg_tag[] = { 19035088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19045088Sab196087 /* MSG_INTL(MSG_A1_TAG_ELT) */ 19055088Sab196087 ELFEDIT_I18NHDL(MSG_A1_TAG_ELT), 19065088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19075088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19085088Sab196087 /* MSG_INTL(MSG_A2_TAG_VALUE) */ 19095088Sab196087 ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE), 19105088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19115088Sab196087 { NULL } 19125088Sab196087 }; 19135088Sab196087 19145088Sab196087 19155088Sab196087 /* dyn:value */ 19165088Sab196087 static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL }; 19175088Sab196087 static elfedit_cmd_optarg_t opt_value[] = { 19185088Sab196087 { MSG_ORIG(MSG_STR_MINUS_ADD), 19195088Sab196087 /* MSG_INTL(MSG_OPTDESC_ADD) */ 19205088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_ADD), 0, 19216225Sab196087 DYN_OPT_F_ADD, DYN_OPT_F_DYNNDX_ELT }, 19225088Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 19236225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 19246225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 19256225Sab196087 DYN_OPT_F_DYNNDX_ELT, DYN_OPT_F_ADD }, 19265088Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 19275088Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 19285088Sab196087 { MSG_ORIG(MSG_STR_MINUS_S), 19295088Sab196087 /* MSG_INTL(MSG_OPTDESC_S) */ 19305088Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0, 19315088Sab196087 DYN_OPT_F_STRVAL, 0 }, 19325088Sab196087 { NULL } 19335088Sab196087 }; 19345088Sab196087 static elfedit_cmd_optarg_t arg_value[] = { 19355088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19365088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19375088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19385088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19395088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 19405088Sab196087 /* MSG_INTL(MSG_A2_VALUE_VALUE) */ 19415088Sab196087 ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE), 19425088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19435088Sab196087 { NULL } 19445088Sab196087 }; 19455088Sab196087 19465088Sab196087 /* dyn:delete */ 19475088Sab196087 static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL }; 19485088Sab196087 static elfedit_cmd_optarg_t arg_delete[] = { 19495088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19505088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19515088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19525088Sab196087 0 }, 19535088Sab196087 { MSG_ORIG(MSG_STR_COUNT), 19545088Sab196087 /* MSG_INTL(MSG_A2_DELETE_COUNT) */ 19555088Sab196087 ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT), 19565088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19575088Sab196087 { NULL } 19585088Sab196087 }; 19595088Sab196087 19605088Sab196087 /* dyn:move */ 19615088Sab196087 static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL }; 19625088Sab196087 static elfedit_cmd_optarg_t arg_move[] = { 19635088Sab196087 { MSG_ORIG(MSG_STR_ELT), 19645088Sab196087 /* MSG_INTL(MSG_ARGDESC_ELT) */ 19655088Sab196087 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 19665088Sab196087 0 }, 19675088Sab196087 { MSG_ORIG(MSG_STR_DST_INDEX), 19685088Sab196087 /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */ 19695088Sab196087 ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX), 19705088Sab196087 0 }, 19715088Sab196087 { MSG_ORIG(MSG_STR_COUNT), 19725088Sab196087 /* MSG_INTL(MSG_A3_MOVE_COUNT) */ 19735088Sab196087 ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT), 19745088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19755088Sab196087 { NULL } 19765088Sab196087 }; 19775088Sab196087 19785088Sab196087 /* dyn:runpath / dyn:rpath */ 19795088Sab196087 static const char *name_runpath[] = { MSG_ORIG(MSG_CMD_RUNPATH), 19805088Sab196087 MSG_ORIG(MSG_CMD_RUNPATH_A1), NULL }; 19815088Sab196087 static elfedit_cmd_optarg_t arg_runpath[] = { 19825088Sab196087 { MSG_ORIG(MSG_STR_NEWPATH), 19835088Sab196087 /* MSG_INTL(MSG_A1_RUNPATH_NEWPATH) */ 19845088Sab196087 ELFEDIT_I18NHDL(MSG_A1_RUNPATH_NEWPATH), 19855088Sab196087 ELFEDIT_CMDOA_F_OPT }, 19865088Sab196087 { NULL } 19875088Sab196087 }; 19885088Sab196087 19895088Sab196087 /* dyn:posflag1 */ 19905088Sab196087 static const char *name_posflag1[] = { MSG_ORIG(MSG_CMD_POSFLAG1), 19915088Sab196087 NULL }; 19926225Sab196087 static elfedit_cmd_optarg_t opt_posflag1[] = { 19936225Sab196087 { ELFEDIT_STDOA_OPT_AND, NULL, 19946225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 19956225Sab196087 { ELFEDIT_STDOA_OPT_CMP, NULL, 19966225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 19976225Sab196087 { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 19986225Sab196087 /* MSG_INTL(MSG_OPTDESC_DYNNDX_VAL) */ 19996225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_VAL), 20006225Sab196087 ELFEDIT_CMDOA_F_VALUE, 20016225Sab196087 DYN_OPT_F_DYNNDX_VAL, DYN_OPT_F_NEEDED }, 20026225Sab196087 { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 20036225Sab196087 { MSG_ORIG(MSG_STR_MINUS_NEEDED), 20046225Sab196087 /* MSG_INTL(MSG_OPTDESC_NEEDED) */ 20056225Sab196087 ELFEDIT_I18NHDL(MSG_OPTDESC_NEEDED), 20066225Sab196087 ELFEDIT_CMDOA_F_VALUE, 20076225Sab196087 DYN_OPT_F_NEEDED, DYN_OPT_F_DYNNDX_VAL }, 20086225Sab196087 { MSG_ORIG(MSG_STR_PREFIX), NULL, 0, 0 }, 20096225Sab196087 { ELFEDIT_STDOA_OPT_O, NULL, 20106225Sab196087 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 20116225Sab196087 { ELFEDIT_STDOA_OPT_OR, NULL, 20126225Sab196087 ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 20136225Sab196087 { NULL } 20146225Sab196087 }; 20155088Sab196087 static elfedit_cmd_optarg_t arg_posflag1[] = { 20165088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20175088Sab196087 /* MSG_INTL(MSG_A1_POSFLAG1_VALUE) */ 20185088Sab196087 ELFEDIT_I18NHDL(MSG_A1_POSFLAG1_VALUE), 20195088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20205088Sab196087 { NULL } 20215088Sab196087 }; 20225088Sab196087 20235088Sab196087 /* dyn:flags */ 20245088Sab196087 static const char *name_flags[] = { MSG_ORIG(MSG_CMD_FLAGS), NULL }; 20255088Sab196087 static elfedit_cmd_optarg_t arg_flags[] = { 20265088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20275088Sab196087 /* MSG_INTL(MSG_A1_FLAGS_VALUE) */ 20285088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FLAGS_VALUE), 20295088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20305088Sab196087 { NULL } 20315088Sab196087 }; 20325088Sab196087 20335088Sab196087 /* dyn:flags1 */ 20345088Sab196087 static const char *name_flags1[] = { MSG_ORIG(MSG_CMD_FLAGS1), NULL }; 20355088Sab196087 static elfedit_cmd_optarg_t arg_flags1[] = { 20365088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20375088Sab196087 /* MSG_INTL(MSG_A1_FLAGS1_VALUE) */ 20385088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FLAGS1_VALUE), 20395088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20405088Sab196087 { NULL } 20415088Sab196087 }; 20425088Sab196087 20435088Sab196087 /* dyn:feature1 */ 20445088Sab196087 static const char *name_feature1[] = { MSG_ORIG(MSG_CMD_FEATURE1), 20455088Sab196087 NULL }; 20465088Sab196087 static elfedit_cmd_optarg_t arg_feature1[] = { 20475088Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20485088Sab196087 /* MSG_INTL(MSG_A1_FEATURE1_VALUE) */ 20495088Sab196087 ELFEDIT_I18NHDL(MSG_A1_FEATURE1_VALUE), 20505088Sab196087 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 20515088Sab196087 { NULL } 20525088Sab196087 }; 20535088Sab196087 20545088Sab196087 /* dyn:checksum */ 20555088Sab196087 static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM), 20565088Sab196087 NULL }; 20575088Sab196087 20586206Sab196087 /* dyn:sunw_ldmach */ 20596206Sab196087 static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH), 20606206Sab196087 NULL }; 20616206Sab196087 static elfedit_cmd_optarg_t arg_sunw_ldmach[] = { 20626206Sab196087 { MSG_ORIG(MSG_STR_VALUE), 20636206Sab196087 /* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */ 20646206Sab196087 ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE), 20656206Sab196087 ELFEDIT_CMDOA_F_OPT }, 20666206Sab196087 { NULL } 20676206Sab196087 }; 20686206Sab196087 20695088Sab196087 20705088Sab196087 20715088Sab196087 static elfedit_cmd_t cmds[] = { 20725088Sab196087 /* dyn:dump */ 20735088Sab196087 { cmd_dump, cpl_eltarg, name_dump, 20745088Sab196087 /* MSG_INTL(MSG_DESC_DUMP) */ 20755088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 20765088Sab196087 /* MSG_INTL(MSG_HELP_DUMP) */ 20775088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 20785088Sab196087 opt_minus_dynndx, arg_dump }, 20795088Sab196087 20805088Sab196087 /* dyn:tag */ 20815088Sab196087 { cmd_tag, cpl_tag, name_tag, 20825088Sab196087 /* MSG_INTL(MSG_DESC_TAG) */ 20835088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_TAG), 20845088Sab196087 /* MSG_INTL(MSG_HELP_TAG) */ 20855088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_TAG), 20865088Sab196087 opt_tag, arg_tag }, 20875088Sab196087 20885088Sab196087 /* dyn:value */ 20895088Sab196087 { cmd_value, cpl_eltarg, name_value, 20905088Sab196087 /* MSG_INTL(MSG_DESC_VALUE) */ 20915088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_VALUE), 20925088Sab196087 /* MSG_INTL(MSG_HELP_VALUE) */ 20935088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_VALUE), 20945088Sab196087 opt_value, arg_value }, 20955088Sab196087 20965088Sab196087 /* dyn:delete */ 20975088Sab196087 { cmd_delete, cpl_eltarg, name_delete, 20985088Sab196087 /* MSG_INTL(MSG_DESC_DELETE) */ 20995088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_DELETE), 21005088Sab196087 /* MSG_INTL(MSG_HELP_DELETE) */ 21015088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_DELETE), 21025088Sab196087 opt_minus_dynndx, arg_delete }, 21035088Sab196087 21045088Sab196087 /* dyn:move */ 21055088Sab196087 { cmd_move, cpl_eltarg, name_move, 21065088Sab196087 /* MSG_INTL(MSG_DESC_MOVE) */ 21075088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_MOVE), 21085088Sab196087 /* MSG_INTL(MSG_HELP_MOVE) */ 21095088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_MOVE), 21105088Sab196087 opt_minus_dynndx, arg_move }, 21115088Sab196087 21125088Sab196087 /* dyn:runpath */ 21135088Sab196087 { cmd_runpath, NULL, name_runpath, 21145088Sab196087 /* MSG_INTL(MSG_DESC_RUNPATH) */ 21155088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_RUNPATH), 21165088Sab196087 /* MSG_INTL(MSG_HELP_RUNPATH) */ 21175088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_RUNPATH), 21185088Sab196087 opt_ostyle, arg_runpath }, 21195088Sab196087 21205088Sab196087 /* dyn:posflag1 */ 21215088Sab196087 { cmd_posflag1, cpl_posflag1, name_posflag1, 21225088Sab196087 /* MSG_INTL(MSG_DESC_POSFLAG1) */ 21235088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_POSFLAG1), 21245088Sab196087 /* MSG_INTL(MSG_HELP_POSFLAG1) */ 21255088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_POSFLAG1), 21266225Sab196087 opt_posflag1, arg_posflag1 }, 21275088Sab196087 21285088Sab196087 /* dyn:flags */ 21295088Sab196087 { cmd_flags, cpl_flags, name_flags, 21305088Sab196087 /* MSG_INTL(MSG_DESC_FLAGS) */ 21315088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FLAGS), 21325088Sab196087 /* MSG_INTL(MSG_HELP_FLAGS) */ 21335088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FLAGS), 21345088Sab196087 opt_ostyle_bitop, arg_flags }, 21355088Sab196087 21365088Sab196087 /* dyn:flags1 */ 21375088Sab196087 { cmd_flags1, cpl_flags1, name_flags1, 21385088Sab196087 /* MSG_INTL(MSG_DESC_FLAGS1) */ 21395088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FLAGS1), 21405088Sab196087 /* MSG_INTL(MSG_HELP_FLAGS1) */ 21415088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FLAGS1), 21425088Sab196087 opt_ostyle_bitop, arg_flags1 }, 21435088Sab196087 21445088Sab196087 /* dyn:feature1 */ 21455088Sab196087 { cmd_feature1, cpl_feature1, name_feature1, 21465088Sab196087 /* MSG_INTL(MSG_DESC_FEATURE1) */ 21475088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_FEATURE1), 21485088Sab196087 /* MSG_INTL(MSG_HELP_FEATURE1) */ 21495088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_FEATURE1), 21505088Sab196087 opt_ostyle_bitop, arg_feature1 }, 21515088Sab196087 21525088Sab196087 /* dyn:checksum */ 21535088Sab196087 { cmd_checksum, NULL, name_checksum, 21545088Sab196087 /* MSG_INTL(MSG_DESC_CHECKSUM) */ 21555088Sab196087 ELFEDIT_I18NHDL(MSG_DESC_CHECKSUM), 21565088Sab196087 /* MSG_INTL(MSG_HELP_CHECKSUM) */ 21575088Sab196087 ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM), 21585088Sab196087 NULL, NULL }, 21595088Sab196087 21606206Sab196087 /* dyn:sunw_ldmach */ 21616206Sab196087 { cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach, 21626206Sab196087 /* MSG_INTL(MSG_DESC_SUNW_LDMACH) */ 21636206Sab196087 ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH), 21646206Sab196087 /* MSG_INTL(MSG_HELP_SUNW_LDMACH) */ 21656206Sab196087 ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH), 21666206Sab196087 opt_ostyle, arg_sunw_ldmach }, 21676206Sab196087 21685088Sab196087 { NULL } 21695088Sab196087 }; 21705088Sab196087 21715088Sab196087 static elfedit_module_t module = { 21725088Sab196087 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 21735088Sab196087 /* MSG_INTL(MSG_MOD_DESC) */ 21745088Sab196087 ELFEDIT_I18NHDL(MSG_MOD_DESC), cmds, mod_i18nhdl_to_str }; 21755088Sab196087 21765088Sab196087 return (&module); 21775088Sab196087 } 2178