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*11827SRod.Evans@Sun.COM * Copyright 2010 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 *
_dyn_msg(Msg mid)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 *
mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)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
set_null_ndx(ARGSTATE * argstate)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
convert_dt_null(ARGSTATE * argstate,Xword d_tag,Xword d_val)1879273SAli.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;
1929273SAli.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
2009273SAli.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,
2049273SAli.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
process_args(elfedit_obj_state_t * obj_state,int argc,const char * argv[],ARGSTATE * argstate)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.
2809273SAli.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
print_dyn(DYN_CMD_T cmd,int autoprint,ARGSTATE * argstate,PRINT_DYN_T print_type,Word arg)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;
3039273SAli.Bahrami@Sun.COM int osabi_solaris;
3045088Sab196087
3055088Sab196087 if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
3065088Sab196087 return;
3075088Sab196087
3089273SAli.Bahrami@Sun.COM osabi_solaris =
3099273SAli.Bahrami@Sun.COM elfedit_test_osabi(argstate->obj_state, ELFOSABI_SOLARIS, 0);
3109273SAli.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:
4319273SAli.Bahrami@Sun.COM name = elfedit_offset_to_str(argstate->strsec,
4329273SAli.Bahrami@Sun.COM dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
4339273SAli.Bahrami@Sun.COM break;
4345088Sab196087 case DT_SUNW_AUXILIARY:
4355088Sab196087 case DT_SUNW_FILTER:
4369273SAli.Bahrami@Sun.COM if (osabi_solaris)
4379273SAli.Bahrami@Sun.COM name = elfedit_offset_to_str(argstate->strsec,
4389273SAli.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:
4899273SAli.Bahrami@Sun.COM if (osabi_solaris)
4909273SAli.Bahrami@Sun.COM name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0,
4919273SAli.Bahrami@Sun.COM &c_buf.inv);
4926206Sab196087 break;
4935088Sab196087 }
4945088Sab196087
4955088Sab196087 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
4969273SAli.Bahrami@Sun.COM Ehdr *ehdr;
4979273SAli.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);
5049273SAli.Bahrami@Sun.COM ehdr = argstate->obj_state->os_ehdr;
5055088Sab196087 Elf_dyn_entry(0, dyn, ndx, name,
5069273SAli.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),
556*11827SRod.Evans@Sun.COM EC_XWORD(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) {
5699273SAli.Bahrami@Sun.COM Conv_inv_buf_t inv_buf;
5709273SAli.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,
5769273SAli.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
arg_to_index(ARGSTATE * argstate,const char * arg,int print_request,PRINT_DYN_T * print_type)6236225Sab196087 arg_to_index(ARGSTATE *argstate, const char *arg,
6245088Sab196087 int print_request, PRINT_DYN_T *print_type)
6255088Sab196087 {
6269273SAli.Bahrami@Sun.COM Word ndx;
6279273SAli.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) {
6619273SAli.Bahrami@Sun.COM Ehdr *ehdr = argstate->obj_state->os_ehdr;
6629273SAli.Bahrami@Sun.COM uchar_t osabi = ehdr->e_ident[EI_OSABI];
6639273SAli.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,
6699273SAli.Bahrami@Sun.COM conv_dyn_tag(dt_value, osabi, mach, 0, &want),
6709273SAli.Bahrami@Sun.COM conv_dyn_tag(argstate->dyn.data[ndx].d_tag,
6719273SAli.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
cmd_body_value(ARGSTATE * argstate,Word * ret_ndx)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;
7739273SAli.Bahrami@Sun.COM Word tmp_val;
7749273SAli.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;
8079273SAli.Bahrami@Sun.COM (void) elfedit_dynstr_getpad(argstate->obj_state,
8089273SAli.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
cmd_body_runpath(ARGSTATE * argstate)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:
9899273SAli.Bahrami@Sun.COM if (elfedit_test_osabi(argstate->obj_state,
9909273SAli.Bahrami@Sun.COM ELFOSABI_SOLARIS, 0))
9919273SAli.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
flag_bitop(ARGSTATE * argstate,Word orig,elfedit_const_t const_type)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
cmd_body(DYN_CMD_T cmd,elfedit_obj_state_t * obj_state,int argc,const char * argv[])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();
12489273SAli.Bahrami@Sun.COM /* DT_SUNW_LDMACH is an ELFOSABI_SOLARIS feature */
12499273SAli.Bahrami@Sun.COM (void) elfedit_test_osabi(argstate.obj_state,
12509273SAli.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 {
12799273SAli.Bahrami@Sun.COM Ehdr *ehdr = argstate.obj_state->os_ehdr;
12809273SAli.Bahrami@Sun.COM uchar_t osabi = ehdr->e_ident[EI_OSABI];
12819273SAli.Bahrami@Sun.COM Half mach = ehdr->e_machine;
12825088Sab196087 Conv_inv_buf_t inv_buf1, inv_buf2;
12839273SAli.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,
12889273SAli.Bahrami@Sun.COM MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, dyn_name,
12899273SAli.Bahrami@Sun.COM EC_WORD(ndx), conv_dyn_tag(d_tag, osabi,
12909273SAli.Bahrami@Sun.COM mach, 0, &inv_buf1));
12915088Sab196087 } else {
12929273SAli.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,
13109273SAli.Bahrami@Sun.COM EC_WORD(ndx), conv_dyn_tag(d_tag,
13119273SAli.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),
13279273SAli.Bahrami@Sun.COM conv_dyn_tag(d_tag, osabi,
13289273SAli.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),
13359273SAli.Bahrami@Sun.COM conv_dyn_tag(d_tag, osabi,
13369273SAli.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),
13439273SAli.Bahrami@Sun.COM conv_dyn_tag(orig_d_tag, osabi, mach, 0,
13445088Sab196087 &inv_buf1),
13459273SAli.Bahrami@Sun.COM conv_dyn_tag(d_tag, osabi, mach, 0,
13469273SAli.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
cpl_eltarg(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)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
cpl_tag(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)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
cpl_posflag1(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)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
cpl_flags(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)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
cpl_flags1(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)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
cpl_feature1(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)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
cpl_sunw_ldmach(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)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
cmd_dump(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_tag(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_value(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_delete(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_move(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_runpath(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_posflag1(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_flags(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_flags1(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_feature1(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_checksum(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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
cmd_sunw_ldmach(elfedit_obj_state_t * obj_state,int argc,const char * argv[])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 *
elfedit_init(elfedit_module_version_t version)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