1d29b2c44Sab /* 2d29b2c44Sab * CDDL HEADER START 3d29b2c44Sab * 4d29b2c44Sab * The contents of this file are subject to the terms of the 5d29b2c44Sab * Common Development and Distribution License (the "License"). 6d29b2c44Sab * You may not use this file except in compliance with the License. 7d29b2c44Sab * 8d29b2c44Sab * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9d29b2c44Sab * or http://www.opensolaris.org/os/licensing. 10d29b2c44Sab * See the License for the specific language governing permissions 11d29b2c44Sab * and limitations under the License. 12d29b2c44Sab * 13d29b2c44Sab * When distributing Covered Code, include this CDDL HEADER in each 14d29b2c44Sab * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15d29b2c44Sab * If applicable, add the following below this CDDL HEADER, with the 16d29b2c44Sab * fields enclosed by brackets "[]" replaced with your own identifying 17d29b2c44Sab * information: Portions Copyright [yyyy] [name of copyright owner] 18d29b2c44Sab * 19d29b2c44Sab * CDDL HEADER END 20d29b2c44Sab */ 21d29b2c44Sab 22d29b2c44Sab /* 23*4f680cc6SAli Bahrami * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24d29b2c44Sab * Use is subject to license terms. 25d29b2c44Sab */ 26d29b2c44Sab 27d29b2c44Sab #include <ctype.h> 28d29b2c44Sab #include <elfedit.h> 29d29b2c44Sab #include <sys/elf_SPARC.h> 30d29b2c44Sab #include <strings.h> 31d29b2c44Sab #include <debug.h> 32d29b2c44Sab #include <conv.h> 33d29b2c44Sab #include <dyn_msg.h> 34d29b2c44Sab 35d29b2c44Sab 36d29b2c44Sab /* 37d29b2c44Sab * Dynamic section 38d29b2c44Sab */ 39d29b2c44Sab 40d29b2c44Sab /* 41d29b2c44Sab * This module uses shared code for several of the commands. 42d29b2c44Sab * It is sometimes necessary to know which specific command 43d29b2c44Sab * is active. 44d29b2c44Sab */ 45d29b2c44Sab typedef enum { 46d29b2c44Sab /* Dump command, used as module default to display dynamic section */ 47d29b2c44Sab DYN_CMD_T_DUMP = 0, /* dyn:dump */ 48d29b2c44Sab 49d29b2c44Sab /* Commands that do not correspond directly to a specific DT tag */ 50d29b2c44Sab DYN_CMD_T_TAG = 1, /* dyn:tag */ 51d29b2c44Sab DYN_CMD_T_VALUE = 2, /* dyn:value */ 52d29b2c44Sab DYN_CMD_T_DELETE = 3, /* dyn:delete */ 53d29b2c44Sab DYN_CMD_T_MOVE = 4, /* dyn:shift */ 54d29b2c44Sab 55d29b2c44Sab /* Commands that embody tag specific knowledge */ 56d29b2c44Sab DYN_CMD_T_RUNPATH = 5, /* dyn:runpath/rpath */ 57d29b2c44Sab DYN_CMD_T_POSFLAG1 = 6, /* dyn:posflag1 */ 58d29b2c44Sab DYN_CMD_T_FLAGS = 7, /* dyn:flags */ 59d29b2c44Sab DYN_CMD_T_FLAGS1 = 8, /* dyn:flags1 */ 60d29b2c44Sab DYN_CMD_T_FEATURE1 = 9, /* dyn:feature1 */ 61ba2be530Sab DYN_CMD_T_CHECKSUM = 10, /* dyn:checksum */ 62ba2be530Sab DYN_CMD_T_SUNW_LDMACH = 11 /* dyn:sunw_ldmach */ 63d29b2c44Sab } DYN_CMD_T; 64d29b2c44Sab 65d29b2c44Sab 66d29b2c44Sab 67d29b2c44Sab #ifndef _ELF64 68d29b2c44Sab /* 69d29b2c44Sab * We supply this function for the msg module 70d29b2c44Sab */ 71d29b2c44Sab const char * 72d29b2c44Sab _dyn_msg(Msg mid) 73d29b2c44Sab { 74d29b2c44Sab return (gettext(MSG_ORIG(mid))); 75d29b2c44Sab } 76d29b2c44Sab #endif 77d29b2c44Sab 78d29b2c44Sab 79d29b2c44Sab /* 80d29b2c44Sab * This function is supplied to elfedit through our elfedit_module_t 81d29b2c44Sab * definition. It translates the opaque elfedit_i18nhdl_t handles 82d29b2c44Sab * in our module interface into the actual strings for elfedit to 83d29b2c44Sab * use. 84d29b2c44Sab * 85d29b2c44Sab * note: 86d29b2c44Sab * This module uses Msg codes for its i18n handle type. 87d29b2c44Sab * So the translation is simply to use MSG_INTL() to turn 88d29b2c44Sab * it into a string and return it. 89d29b2c44Sab */ 90d29b2c44Sab static const char * 91d29b2c44Sab mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 92d29b2c44Sab { 93d29b2c44Sab Msg msg = (Msg)hdl; 94d29b2c44Sab 95d29b2c44Sab return (MSG_INTL(msg)); 96d29b2c44Sab } 97d29b2c44Sab 98d29b2c44Sab 99d29b2c44Sab 100d29b2c44Sab /* 101d29b2c44Sab * The dyn_opt_t enum specifies a bit value for every optional 102d29b2c44Sab * argument allowed by a command in this module. 103d29b2c44Sab */ 104d29b2c44Sab typedef enum { 105d29b2c44Sab DYN_OPT_F_ADD = 1, /* -add: Add new elt rather than */ 106d29b2c44Sab /* modifying an existing one */ 107d29b2c44Sab DYN_OPT_F_AND = 2, /* -and: AND (&) values to dest */ 108d29b2c44Sab DYN_OPT_F_CMP = 4, /* -cmp: Complement (~) values */ 10955ef6355Sab DYN_OPT_F_DYNNDX_ELT = 8, /* -dynndx: 1st plain arg is tag */ 11055ef6355Sab /* index, not name */ 11155ef6355Sab DYN_OPT_F_DYNNDX_VAL = 16, /* -dynndx ndx: Index is value to */ 11255ef6355Sab /* option rather than 1st plain */ 11355ef6355Sab /* arg. Used for dyn:posflag1 */ 11455ef6355Sab DYN_OPT_F_NEEDED = 32, /* -needed str: Locate DT_POSFLAG_1 */ 11555ef6355Sab /* relative to DT_NEEDED element */ 11655ef6355Sab DYN_OPT_F_OR = 64, /* -or: OR (|) values to dest */ 11755ef6355Sab DYN_OPT_F_STRVAL = 128 /* -s: value is string, not integer */ 118d29b2c44Sab } dyn_opt_t; 119d29b2c44Sab 120d29b2c44Sab 121d29b2c44Sab /* 122d29b2c44Sab * A variable of type ARGSTATE is used by each command to maintain 123d29b2c44Sab * information about the arguments and related things. It is 124d29b2c44Sab * initialized by process_args(), and used by the other routines. 125d29b2c44Sab */ 126d29b2c44Sab typedef struct { 127d29b2c44Sab elfedit_obj_state_t *obj_state; 128d29b2c44Sab elfedit_section_t *strsec; /* Dynamic string table ref */ 129d29b2c44Sab struct { 130d29b2c44Sab elfedit_section_t *sec; /* Dynamic section reference */ 131d29b2c44Sab Dyn *data; /* Start dynamic section data */ 132d29b2c44Sab Word num; /* # dynamic elts */ 133d29b2c44Sab Word null_ndx; /* Index of first DT_NULL */ 134d29b2c44Sab Word num_null_ndx; /* # of DT_NULL elements */ 135d29b2c44Sab } dyn; 136d29b2c44Sab dyn_opt_t optmask; /* Mask of options used */ 137d29b2c44Sab int argc; /* # of plain arguments */ 138d29b2c44Sab const char **argv; /* Plain arguments */ 13955ef6355Sab const char *dyn_elt_str; /* Value string for */ 14055ef6355Sab /* DYN_OPT_F_DYNNDX_VAL */ 14155ef6355Sab /* or DYN_OPT_F_NEEDED */ 142d29b2c44Sab } ARGSTATE; 143d29b2c44Sab 144d29b2c44Sab 145d29b2c44Sab 146d29b2c44Sab /* 147d29b2c44Sab * Set argstate null_ndx field for current dynamic area 148d29b2c44Sab */ 149d29b2c44Sab static void 150d29b2c44Sab set_null_ndx(ARGSTATE *argstate) 151d29b2c44Sab { 152d29b2c44Sab Word num, null_ndx; 153d29b2c44Sab 154d29b2c44Sab num = argstate->dyn.num; 155d29b2c44Sab argstate->dyn.num_null_ndx = 0; 156d29b2c44Sab for (null_ndx = 0; null_ndx < num; null_ndx++) 157d29b2c44Sab if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) { 158d29b2c44Sab argstate->dyn.num_null_ndx++; 159d29b2c44Sab break; 160d29b2c44Sab } 161d29b2c44Sab argstate->dyn.null_ndx = null_ndx; 162d29b2c44Sab 163d29b2c44Sab /* Count the number of remaining DT_NULL items */ 164d29b2c44Sab for (; null_ndx < num; null_ndx++) 165d29b2c44Sab if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) 166d29b2c44Sab argstate->dyn.num_null_ndx++; 167d29b2c44Sab } 168d29b2c44Sab 169d29b2c44Sab 170d29b2c44Sab /* 171d29b2c44Sab * Convert the first available DT_NULL slot in the dynamic section 172d29b2c44Sab * into something else. 173d29b2c44Sab * 174d29b2c44Sab * entry: 175d29b2c44Sab * argstate - Argument state block 176d29b2c44Sab * d_tag, d_val - Values to be set in new element 177d29b2c44Sab * 178d29b2c44Sab * exit: 179d29b2c44Sab * If an extra DT_NULL slot is available, a debug message is 180d29b2c44Sab * issued, the slot is converted to its new use, and the argstate 181d29b2c44Sab * block state related to DT_NULL slots is updated. 182d29b2c44Sab * 183d29b2c44Sab * if no extra DT_NULL slot is present, an error is issued and 184d29b2c44Sab * this routine does not return to the caller. 185d29b2c44Sab */ 186d29b2c44Sab static Word 187*4f680cc6SAli Bahrami convert_dt_null(ARGSTATE *argstate, Xword d_tag, Xword d_val) 188d29b2c44Sab { 189d29b2c44Sab Conv_inv_buf_t inv_buf; 190d29b2c44Sab Word ndx; 191d29b2c44Sab Dyn *dyn; 192*4f680cc6SAli Bahrami Ehdr *ehdr; 193d29b2c44Sab 194d29b2c44Sab /* If we lack an extra element, we can't continue */ 195d29b2c44Sab if (argstate->dyn.num_null_ndx <= 1) 196d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 197d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), 198d29b2c44Sab argstate->dyn.sec->sec_name); 199d29b2c44Sab 200*4f680cc6SAli Bahrami ehdr = argstate->obj_state->os_ehdr; 201d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL), 202d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), argstate->dyn.sec->sec_name, 203d29b2c44Sab EC_WORD(argstate->dyn.null_ndx), conv_dyn_tag(d_tag, 204*4f680cc6SAli Bahrami ehdr->e_ident[EI_OSABI], ehdr->e_machine, 0, &inv_buf)); 205d29b2c44Sab 206d29b2c44Sab ndx = argstate->dyn.null_ndx; 207d29b2c44Sab dyn = &argstate->dyn.data[ndx]; 208d29b2c44Sab dyn->d_tag = d_tag; 209d29b2c44Sab dyn->d_un.d_val = d_val; 210d29b2c44Sab 211d29b2c44Sab /* Recompute the DT_NULL situation */ 212d29b2c44Sab set_null_ndx(argstate); 213d29b2c44Sab 214d29b2c44Sab return (ndx); 215d29b2c44Sab } 216d29b2c44Sab 217d29b2c44Sab 218d29b2c44Sab /* 219d29b2c44Sab * Standard argument processing for dyn module 220d29b2c44Sab * 221d29b2c44Sab * entry 222d29b2c44Sab * obj_state, argc, argv - Standard command arguments 223d29b2c44Sab * argstate - Address of ARGSTATE block to be initialized 224d29b2c44Sab * 225d29b2c44Sab * exit: 226d29b2c44Sab * On success, *argstate is initialized. On error, 227d29b2c44Sab * an error is issued and this routine does not return. 228d29b2c44Sab */ 229d29b2c44Sab static void 230d29b2c44Sab process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 231d29b2c44Sab ARGSTATE *argstate) 232d29b2c44Sab { 233d29b2c44Sab elfedit_getopt_state_t getopt_state; 234d29b2c44Sab elfedit_getopt_ret_t *getopt_ret; 235d29b2c44Sab 236d29b2c44Sab bzero(argstate, sizeof (*argstate)); 237d29b2c44Sab argstate->obj_state = obj_state; 238d29b2c44Sab 239d29b2c44Sab elfedit_getopt_init(&getopt_state, &argc, &argv); 240d29b2c44Sab 241d29b2c44Sab /* Add each new option to the options mask */ 24255ef6355Sab while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) { 243d29b2c44Sab argstate->optmask |= getopt_ret->gor_idmask; 24455ef6355Sab switch (getopt_ret->gor_idmask) { 24555ef6355Sab case DYN_OPT_F_DYNNDX_VAL: 24655ef6355Sab case DYN_OPT_F_NEEDED: 24755ef6355Sab argstate->dyn_elt_str = getopt_ret->gor_value; 24855ef6355Sab break; 24955ef6355Sab } 25055ef6355Sab } 251d29b2c44Sab 252d29b2c44Sab /* If there may be an arbitrary amount of output, use a pager */ 253d29b2c44Sab if (argc == 0) 254d29b2c44Sab elfedit_pager_init(); 255d29b2c44Sab 256d29b2c44Sab /* Return the updated values of argc/argv */ 257d29b2c44Sab argstate->argc = argc; 258d29b2c44Sab argstate->argv = argv; 259d29b2c44Sab 260d29b2c44Sab /* Locate the dynamic section, and the assocated string table */ 261d29b2c44Sab argstate->dyn.sec = elfedit_sec_getdyn(obj_state, &argstate->dyn.data, 262d29b2c44Sab &argstate->dyn.num); 263d29b2c44Sab argstate->strsec = elfedit_sec_getstr(obj_state, 26455ef6355Sab argstate->dyn.sec->sec_shdr->sh_link, 0); 265d29b2c44Sab 266d29b2c44Sab /* Index of first DT_NULL */ 267d29b2c44Sab set_null_ndx(argstate); 268d29b2c44Sab } 269d29b2c44Sab 270d29b2c44Sab /* 271d29b2c44Sab * Print ELF header values, taking the calling command, and output style 272d29b2c44Sab * into account. 273d29b2c44Sab * 274d29b2c44Sab * entry: 275d29b2c44Sab * cmd - DYN_CMD_T_* value giving identify of caller 276d29b2c44Sab * autoprint - If True, output is only produced if the elfedit 277d29b2c44Sab * autoprint flag is set. If False, output is always produced. 278d29b2c44Sab * argstate - Argument state block 279d29b2c44Sab * print_type - Specifies which dynamic elements to display. 280*4f680cc6SAli Bahrami * arg - If print_type is PRINT_DYN_T_NDX, displays the index specified. 281d29b2c44Sab * Otherwise ignored. 282d29b2c44Sab */ 283d29b2c44Sab typedef enum { 284d29b2c44Sab PRINT_DYN_T_ALL = 0, /* Show all indexes */ 285d29b2c44Sab PRINT_DYN_T_NDX = 1, /* Show dynamic[arg] only */ 286d29b2c44Sab PRINT_DYN_T_TAG = 2, /* Show all elts with tag type */ 287d29b2c44Sab /* given by arg */ 288d29b2c44Sab PRINT_DYN_T_RUNPATH = 3 /* Show all runpath/rpath elts */ 289d29b2c44Sab 290d29b2c44Sab } PRINT_DYN_T; 291d29b2c44Sab 292d29b2c44Sab static void 293d29b2c44Sab print_dyn(DYN_CMD_T cmd, int autoprint, ARGSTATE *argstate, 294d29b2c44Sab PRINT_DYN_T print_type, Word arg) 295d29b2c44Sab { 296d29b2c44Sab elfedit_outstyle_t outstyle; 297d29b2c44Sab Conv_fmt_flags_t flags_fmt_flags; 298c6c9aed4Sab Word end_ndx, ndx, printed = 0; 299d29b2c44Sab Dyn *dyn; 300d29b2c44Sab int header_done = 0; 301d29b2c44Sab Xword last_d_val; 30255ef6355Sab int one_shot; 303*4f680cc6SAli Bahrami int osabi_solaris; 304d29b2c44Sab 305d29b2c44Sab if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) 306d29b2c44Sab return; 307d29b2c44Sab 308*4f680cc6SAli Bahrami osabi_solaris = 309*4f680cc6SAli Bahrami elfedit_test_osabi(argstate->obj_state, ELFOSABI_SOLARIS, 0); 310*4f680cc6SAli Bahrami 311d29b2c44Sab /* 312d29b2c44Sab * Pick an output style. dyn:dump is required to use the default 313d29b2c44Sab * style. The other commands use the current output style. 314d29b2c44Sab */ 315d29b2c44Sab outstyle = (cmd == DYN_CMD_T_DUMP) ? 316d29b2c44Sab ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 317d29b2c44Sab 318d29b2c44Sab /* 319d29b2c44Sab * When using the simple output style, omit the 320d29b2c44Sab * brackets from around the values. 321d29b2c44Sab */ 322d29b2c44Sab flags_fmt_flags = (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) ? 323d29b2c44Sab CONV_FMT_NOBKT : 0; 324d29b2c44Sab 325c6c9aed4Sab /* Starting index */ 326d29b2c44Sab if (print_type == PRINT_DYN_T_NDX) { 327d29b2c44Sab if (arg >= argstate->dyn.num) 328d29b2c44Sab return; /* Out of range */ 329d29b2c44Sab ndx = arg; 330d29b2c44Sab } else { 331d29b2c44Sab ndx = 0; 332d29b2c44Sab } 333d29b2c44Sab 33455ef6355Sab /* 33555ef6355Sab * one_shot is used by positional elements (e.g. DT_POSFLAG_1) 33655ef6355Sab * to get the item following them to be shown even if they 33755ef6355Sab * are not of the desired tag type or the count of elements 33855ef6355Sab * to be displayed is only 1. 33955ef6355Sab */ 34055ef6355Sab one_shot = 0; 34155ef6355Sab 342d29b2c44Sab dyn = &argstate->dyn.data[ndx]; 343c6c9aed4Sab 344c6c9aed4Sab /* 345c6c9aed4Sab * Loop predicate explanation: 346c6c9aed4Sab * Normally, we want to iterate from the starting index 347c6c9aed4Sab * to the end. However, in the case of PRINT_DYN_T_NDX, we 348c6c9aed4Sab * only want to display one item (ndx == arg) and then quit, 349c6c9aed4Sab * with the exception that if we've been through the loop 350c6c9aed4Sab * and encountered a one_shot situation, we want to continue 351c6c9aed4Sab * iterating until the one-shot situation is cleared. 352c6c9aed4Sab */ 353c6c9aed4Sab for (; (ndx < argstate->dyn.num) && 354c6c9aed4Sab ((print_type != PRINT_DYN_T_NDX) || ((ndx == arg) || one_shot)); 355c6c9aed4Sab dyn++, ndx++) { 356d29b2c44Sab union { 357ba2be530Sab Conv_inv_buf_t inv; 358d29b2c44Sab Conv_dyn_flag_buf_t flag; 359d29b2c44Sab Conv_dyn_flag1_buf_t flag1; 360d29b2c44Sab Conv_dyn_posflag1_buf_t posflag1; 361d29b2c44Sab Conv_dyn_feature1_buf_t feature1; 362d29b2c44Sab } c_buf; 363d29b2c44Sab const char *name; 364d29b2c44Sab 36555ef6355Sab if (one_shot) { 36655ef6355Sab one_shot = 0; 36755ef6355Sab } else { 36855ef6355Sab /* 36955ef6355Sab * If we are only displaying certain tag types and 37055ef6355Sab * this isn't one of those, move on to next element. 37155ef6355Sab */ 37255ef6355Sab switch (print_type) { 37355ef6355Sab case PRINT_DYN_T_TAG: 37455ef6355Sab if (dyn->d_tag != arg) 37555ef6355Sab continue; 37655ef6355Sab break; 37755ef6355Sab case PRINT_DYN_T_RUNPATH: 37855ef6355Sab if ((dyn->d_tag != DT_RPATH) && 37955ef6355Sab (dyn->d_tag != DT_RUNPATH)) 38055ef6355Sab continue; 38155ef6355Sab break; 38255ef6355Sab } 383d29b2c44Sab } 384d29b2c44Sab 385d29b2c44Sab /* 386d29b2c44Sab * Print the information numerically, and if possible 387d29b2c44Sab * as a string. 388d29b2c44Sab */ 389d29b2c44Sab name = NULL; 390d29b2c44Sab switch (dyn->d_tag) { 391d29b2c44Sab case DT_NULL: 392d29b2c44Sab if (!((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) && 393d29b2c44Sab (print_type == PRINT_DYN_T_ALL) && 394d29b2c44Sab (dyn->d_un.d_val == 0))) 395d29b2c44Sab break; 396d29b2c44Sab end_ndx = ndx; 397d29b2c44Sab /* 398d29b2c44Sab * Special case: DT_NULLs can come in groups 399d29b2c44Sab * that we prefer to reduce to a single line. 400d29b2c44Sab */ 401d29b2c44Sab while ((end_ndx < (argstate->dyn.num - 1)) && 402d29b2c44Sab ((dyn + 1)->d_tag == DT_NULL) && 403d29b2c44Sab ((dyn + 1)->d_un.d_val == 0)) { 404d29b2c44Sab dyn++; 405d29b2c44Sab end_ndx++; 406d29b2c44Sab } 407d29b2c44Sab if (header_done == 0) { 408d29b2c44Sab header_done = 1; 409d29b2c44Sab Elf_dyn_title(0); 410d29b2c44Sab } 411d29b2c44Sab Elf_dyn_null_entry(0, dyn, ndx, end_ndx); 412d29b2c44Sab ndx = end_ndx; 413d29b2c44Sab printed = 1; 414d29b2c44Sab last_d_val = dyn->d_un.d_val; 415d29b2c44Sab continue; 416d29b2c44Sab 417d29b2c44Sab /* 418d29b2c44Sab * Print the information numerically, and if possible 419d29b2c44Sab * as a string. 420d29b2c44Sab */ 421d29b2c44Sab case DT_NEEDED: 422d29b2c44Sab case DT_SONAME: 423d29b2c44Sab case DT_FILTER: 424d29b2c44Sab case DT_AUXILIARY: 425d29b2c44Sab case DT_CONFIG: 426d29b2c44Sab case DT_RPATH: 427d29b2c44Sab case DT_RUNPATH: 428d29b2c44Sab case DT_USED: 429d29b2c44Sab case DT_DEPAUDIT: 430d29b2c44Sab case DT_AUDIT: 431d29b2c44Sab name = elfedit_offset_to_str(argstate->strsec, 432d29b2c44Sab dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 433d29b2c44Sab break; 434*4f680cc6SAli Bahrami case DT_SUNW_AUXILIARY: 435*4f680cc6SAli Bahrami case DT_SUNW_FILTER: 436*4f680cc6SAli Bahrami if (osabi_solaris) 437*4f680cc6SAli Bahrami name = elfedit_offset_to_str(argstate->strsec, 438*4f680cc6SAli Bahrami dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 439*4f680cc6SAli Bahrami break; 440d29b2c44Sab 441d29b2c44Sab case DT_FLAGS: 442d29b2c44Sab name = conv_dyn_flag(dyn->d_un.d_val, 443d29b2c44Sab flags_fmt_flags, &c_buf.flag); 444d29b2c44Sab break; 445d29b2c44Sab case DT_FLAGS_1: 446d29b2c44Sab name = conv_dyn_flag1(dyn->d_un.d_val, 447d29b2c44Sab flags_fmt_flags, &c_buf.flag1); 448d29b2c44Sab break; 449d29b2c44Sab case DT_POSFLAG_1: 45055ef6355Sab /* 45155ef6355Sab * If this is dyn:posflag1, and the print_type 45255ef6355Sab * is PRINT_DYN_T_TAG, and the -needed option is 45355ef6355Sab * used, then don't show any DT_POSFLAG_1 elements 45455ef6355Sab * that are not followed by a DT_NEEDED element 45555ef6355Sab * that matches the -needed string. 45655ef6355Sab */ 45755ef6355Sab if ((cmd == DYN_CMD_T_POSFLAG1) && 45855ef6355Sab (print_type == PRINT_DYN_T_TAG) && 45955ef6355Sab ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) && 46055ef6355Sab ((ndx + 1) < argstate->dyn.num)) { 46155ef6355Sab Dyn *dyn1 = &argstate->dyn.data[ndx + 1]; 46255ef6355Sab 46355ef6355Sab if (dyn1->d_tag != DT_NEEDED) 46455ef6355Sab continue; 46555ef6355Sab name = elfedit_offset_to_str(argstate->strsec, 46655ef6355Sab dyn1->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 46755ef6355Sab if (strncmp(name, argstate->dyn_elt_str, 46855ef6355Sab strlen(argstate->dyn_elt_str)) != 0) 46955ef6355Sab continue; 47055ef6355Sab } 47155ef6355Sab 472d29b2c44Sab name = conv_dyn_posflag1(dyn->d_un.d_val, 473d29b2c44Sab flags_fmt_flags, &c_buf.posflag1); 47455ef6355Sab /* 47555ef6355Sab * DT_POSFLAG_1 is a positional element that affects 47655ef6355Sab * the following item. If using the default output 47755ef6355Sab * style, then show the following item as well. 47855ef6355Sab */ 47955ef6355Sab one_shot = (outstyle == ELFEDIT_OUTSTYLE_DEFAULT); 480d29b2c44Sab break; 481d29b2c44Sab case DT_FEATURE_1: 482d29b2c44Sab name = conv_dyn_feature1(dyn->d_un.d_val, 483d29b2c44Sab flags_fmt_flags, &c_buf.feature1); 484d29b2c44Sab break; 485d29b2c44Sab case DT_DEPRECATED_SPARC_REGISTER: 486d29b2c44Sab name = MSG_INTL(MSG_STR_DEPRECATED); 487d29b2c44Sab break; 488ba2be530Sab case DT_SUNW_LDMACH: 489*4f680cc6SAli Bahrami if (osabi_solaris) 490*4f680cc6SAli Bahrami name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0, 491*4f680cc6SAli Bahrami &c_buf.inv); 492ba2be530Sab break; 493d29b2c44Sab } 494d29b2c44Sab 495d29b2c44Sab if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 496*4f680cc6SAli Bahrami Ehdr *ehdr; 497*4f680cc6SAli Bahrami 498d29b2c44Sab if (header_done == 0) { 499d29b2c44Sab header_done = 1; 500d29b2c44Sab Elf_dyn_title(0); 501d29b2c44Sab } 502d29b2c44Sab if (name == NULL) 503d29b2c44Sab name = MSG_ORIG(MSG_STR_EMPTY); 504*4f680cc6SAli Bahrami ehdr = argstate->obj_state->os_ehdr; 505d29b2c44Sab Elf_dyn_entry(0, dyn, ndx, name, 506*4f680cc6SAli Bahrami ehdr->e_ident[EI_OSABI], ehdr->e_machine); 507d29b2c44Sab } else { 508d29b2c44Sab /* 509d29b2c44Sab * In simple or numeric mode under a print type 510d29b2c44Sab * that is based on tag type rather than on index, 5115c02782fSAli Bahrami * if there are more than one qualifying tag, we 5125c02782fSAli Bahrami * want to skip printing redundant information. 513d29b2c44Sab */ 514d29b2c44Sab switch (print_type) { 515d29b2c44Sab case PRINT_DYN_T_TAG: 5165c02782fSAli Bahrami switch (dyn->d_tag) { 5175c02782fSAli Bahrami case DT_NEEDED: 5185c02782fSAli Bahrami /* Multiple NEEDED entries are normal */ 5195c02782fSAli Bahrami break; 5205c02782fSAli Bahrami case DT_POSFLAG_1: 5215c02782fSAli Bahrami /* 5225c02782fSAli Bahrami * Positional flags don't count, 5235c02782fSAli Bahrami * because each one affects a different 5245c02782fSAli Bahrami * item. Don't skip those even if they 5255c02782fSAli Bahrami * have duplicate values. 5265c02782fSAli Bahrami */ 5275c02782fSAli Bahrami break; 5285c02782fSAli Bahrami default: 5295c02782fSAli Bahrami /* 5305c02782fSAli Bahrami * Anything else: If we've already 5315c02782fSAli Bahrami * printed this value, don't print 5325c02782fSAli Bahrami * it again. 5335c02782fSAli Bahrami */ 5345c02782fSAli Bahrami if (printed && 5355c02782fSAli Bahrami (last_d_val == dyn->d_un.d_val)) 5365c02782fSAli Bahrami continue; 5375c02782fSAli Bahrami } 53855ef6355Sab break; 539d29b2c44Sab case PRINT_DYN_T_RUNPATH: 5405c02782fSAli Bahrami /* 5415c02782fSAli Bahrami * If we've already printed this value, 5425c02782fSAli Bahrami * don't print it again. This commonly 5435c02782fSAli Bahrami * happens when both DT_RPATH and DT_RUNPATH 5445c02782fSAli Bahrami * are present with the same value. 5455c02782fSAli Bahrami */ 546d29b2c44Sab if (printed && (last_d_val == dyn->d_un.d_val)) 547d29b2c44Sab continue; 54855ef6355Sab break; 549d29b2c44Sab } 550d29b2c44Sab 551d29b2c44Sab if ((name != NULL) && 552d29b2c44Sab (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) { 553d29b2c44Sab elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name); 554d29b2c44Sab } else { 555d29b2c44Sab elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), 556d29b2c44Sab dyn->d_un.d_val); 557d29b2c44Sab } 558d29b2c44Sab } 559d29b2c44Sab printed = 1; 560d29b2c44Sab last_d_val = dyn->d_un.d_val; 561d29b2c44Sab } 562d29b2c44Sab 563d29b2c44Sab /* 564d29b2c44Sab * If nothing was output under the print types that are 565d29b2c44Sab * based on tag type, issue an error saying it doesn't exist. 566d29b2c44Sab */ 567d29b2c44Sab if (!printed) { 568d29b2c44Sab if (print_type == PRINT_DYN_T_TAG) { 569*4f680cc6SAli Bahrami Conv_inv_buf_t inv_buf; 570*4f680cc6SAli Bahrami Ehdr *ehdr = argstate->obj_state->os_ehdr; 571d29b2c44Sab 572d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, 573d29b2c44Sab MSG_INTL(MSG_ERR_NODYNELT), 574d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), 575d29b2c44Sab argstate->dyn.sec->sec_name, conv_dyn_tag(arg, 576*4f680cc6SAli Bahrami ehdr->e_ident[EI_OSABI], ehdr->e_machine, 577d29b2c44Sab 0, &inv_buf)); 578d29b2c44Sab } 579d29b2c44Sab 580d29b2c44Sab if (print_type == PRINT_DYN_T_RUNPATH) 581d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, 582d29b2c44Sab MSG_INTL(MSG_ERR_NORUNPATH), 583d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), 584d29b2c44Sab argstate->dyn.sec->sec_name); 585d29b2c44Sab } 586d29b2c44Sab } 587d29b2c44Sab 588d29b2c44Sab 589d29b2c44Sab /* 59055ef6355Sab * Determine the index(s) of the dynamic element(s) to be displayed and/or 59155ef6355Sab * manipulated. 592d29b2c44Sab * 593d29b2c44Sab * entry: 594d29b2c44Sab * argstate - Argument state block 59555ef6355Sab * arg - If the command being called accepts a first plain argument 59655ef6355Sab * named 'elt' which is used to specify the dynamic element, 59755ef6355Sab * arg is the value of argv[0] for that command. If the 59855ef6355Sab * command does not accept an 'elt' argument and instead 59955ef6355Sab * implicitly assumes a tag type, arg is the constant string 60055ef6355Sab * for that type (e.g. "DT_POSFLAG_1"). 601d29b2c44Sab * print_request - True if the command is to print the current 602d29b2c44Sab * value(s) and return without changing anything. 603d29b2c44Sab * print_type - Address of variable containing PRINT_DYN_T_ 604d29b2c44Sab * code specifying how the elements will be displayed. 605d29b2c44Sab * 606d29b2c44Sab * exit: 60755ef6355Sab * If print_request is False: This routine always returns the index 60855ef6355Sab * of a single dynamic element. *print_type is set to PRINT_DYN_T_NDX. 60955ef6355Sab * The 'elt' argument as well as any modifier options (-dynndx, -needed) 61055ef6355Sab * are examined to determine this index. If there are no modifier options, 61155ef6355Sab * the dynamic section contains no element of the desired type, and there 61255ef6355Sab * is an extra DT_NULL element in the section, then a new element of 61355ef6355Sab * the desired type is created and its index returned. Otherwise an 61455ef6355Sab * error is issued. 615d29b2c44Sab * 61655ef6355Sab * If print_request is True: If a modifier (-dynndx, -needed) was used, 61755ef6355Sab * *print_type is set to PRINT_DYN_T_NDX and the index of the 61855ef6355Sab * corresponding single dynamic element is returned. If no modifier 61955ef6355Sab * was used, *print_type is set to PRINT_DYN_T_TAG, and the tag 62055ef6355Sab * type code is returned. 621d29b2c44Sab */ 622d29b2c44Sab static Word 62355ef6355Sab arg_to_index(ARGSTATE *argstate, const char *arg, 624d29b2c44Sab int print_request, PRINT_DYN_T *print_type) 625d29b2c44Sab { 626*4f680cc6SAli Bahrami Word ndx; 627*4f680cc6SAli Bahrami Xword dt_value; 62855ef6355Sab Dyn *dyn; 629d29b2c44Sab 630d29b2c44Sab 631d29b2c44Sab /* Assume we are returning an index, alter as needed below */ 632d29b2c44Sab *print_type = PRINT_DYN_T_NDX; 633d29b2c44Sab 63455ef6355Sab /* 63555ef6355Sab * All the commands that accept the DYN_OPT_F_DYNNDX_ELT form 63655ef6355Sab * of -dynndx require a plain argument named 'elt' as their first 63755ef6355Sab * argument. -dynndx is a modifier that means that 'elt' is a 63855ef6355Sab * simple numeric section index. Routines that accept this form 63955ef6355Sab * of -dynndx are willing to handle any tag type, so all we need 64055ef6355Sab * to check is that the value is in range. 64155ef6355Sab */ 64255ef6355Sab if ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0) 64355ef6355Sab return ((Word) elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_ELT), 64455ef6355Sab 0, argstate->dyn.num - 1, NULL)); 645d29b2c44Sab 64655ef6355Sab /* arg is a DT_ tag type, not a numeric index */ 647d29b2c44Sab dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT); 648d29b2c44Sab 64955ef6355Sab /* 65055ef6355Sab * Commands that accept the DYN_OPT_F_DYNNDX_VAL form of 65155ef6355Sab * dynndx do not accept the 'elt' argument. The index is a 65255ef6355Sab * value that follows the option, and was saved in argstate by 65355ef6355Sab * process_args(). Routines that accept this form of -dynndx 65455ef6355Sab * require the specified element to have a specific tag type, 65555ef6355Sab * so we test for this as well as for the index being in range. 65655ef6355Sab */ 65755ef6355Sab if ((argstate->optmask & DYN_OPT_F_DYNNDX_VAL) != 0) { 65855ef6355Sab ndx = ((Word) elfedit_atoui_range(argstate->dyn_elt_str, 65955ef6355Sab MSG_ORIG(MSG_STR_INDEX), 0, argstate->dyn.num - 1, NULL)); 66055ef6355Sab if (argstate->dyn.data[ndx].d_tag != dt_value) { 661*4f680cc6SAli Bahrami Ehdr *ehdr = argstate->obj_state->os_ehdr; 662*4f680cc6SAli Bahrami uchar_t osabi = ehdr->e_ident[EI_OSABI]; 663*4f680cc6SAli Bahrami Half mach = ehdr->e_machine; 66455ef6355Sab Conv_inv_buf_t is, want; 66555ef6355Sab 66655ef6355Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_WRONGTAG), 66755ef6355Sab EC_WORD(argstate->dyn.sec->sec_shndx), 66855ef6355Sab argstate->dyn.sec->sec_name, ndx, 669*4f680cc6SAli Bahrami conv_dyn_tag(dt_value, osabi, mach, 0, &want), 670*4f680cc6SAli Bahrami conv_dyn_tag(argstate->dyn.data[ndx].d_tag, 671*4f680cc6SAli Bahrami osabi, mach, 0, &is)); 67255ef6355Sab } 67355ef6355Sab return (ndx); 67455ef6355Sab } 67555ef6355Sab 676d29b2c44Sab /* 677d29b2c44Sab * If this is a printing request, then we let print_dyn() show 678d29b2c44Sab * all the items with this tag type. 679d29b2c44Sab */ 680d29b2c44Sab if (print_request) { 681d29b2c44Sab *print_type = PRINT_DYN_T_TAG; 682d29b2c44Sab return (dt_value); 683d29b2c44Sab } 684d29b2c44Sab 68555ef6355Sab /* 68655ef6355Sab * Commands that accept -needed are looking for the dt_value element 68755ef6355Sab * (usually DT_POSFLAG_1) that immediately preceeds the DT_NEEDED 68855ef6355Sab * element with the string given by argstate->dyn_elt_str. 68955ef6355Sab */ 69055ef6355Sab if ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) { 69155ef6355Sab Word retndx = argstate->dyn.num; /* Out of range value */ 69255ef6355Sab const char *name; 69355ef6355Sab size_t len; 69455ef6355Sab 69555ef6355Sab len = strlen(argstate->dyn_elt_str); 69655ef6355Sab for (ndx = 0, dyn = argstate->dyn.data; 69755ef6355Sab ndx < argstate->dyn.num; dyn++, ndx++) { 69855ef6355Sab /* 69955ef6355Sab * If the immediately preceeding item has the 70055ef6355Sab * tag type we're looking for, and the current item 70155ef6355Sab * is a DT_NEEDED with a string that matches, 70255ef6355Sab * then the preceeding item is the one we want. 70355ef6355Sab */ 70455ef6355Sab if ((dyn->d_tag == DT_NEEDED) && 70555ef6355Sab (ndx > 0) && (retndx == (ndx - 1))) { 70655ef6355Sab name = elfedit_offset_to_str(argstate->strsec, 70755ef6355Sab dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 70855ef6355Sab 70955ef6355Sab if (strncmp(name, 71055ef6355Sab argstate->dyn_elt_str, len) == 0) 71155ef6355Sab return (retndx); 71255ef6355Sab continue; 71355ef6355Sab } 71455ef6355Sab 71555ef6355Sab /* 71655ef6355Sab * If the current item has the tag type we're 71755ef6355Sab * looking for, make it our current candidate. 71855ef6355Sab * If the next item is a DT_NEEDED with the right 71955ef6355Sab * string value, we'll use it then. 72055ef6355Sab */ 72155ef6355Sab if (dyn->d_tag == dt_value) 72255ef6355Sab retndx = ndx; 72355ef6355Sab } 72455ef6355Sab 72555ef6355Sab /* If we get here, no matching DT_NEEDED was found */ 72655ef6355Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEDNOMATCH), 72755ef6355Sab EC_WORD(argstate->dyn.sec->sec_shndx), 72855ef6355Sab argstate->dyn.sec->sec_name, argstate->dyn_elt_str); 72955ef6355Sab } 73055ef6355Sab 731d29b2c44Sab /* Locate the first entry with the given tag type */ 732d29b2c44Sab for (ndx = 0; ndx < argstate->dyn.num; ndx++) { 733d29b2c44Sab if (argstate->dyn.data[ndx].d_tag == dt_value) { 734d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 735d29b2c44Sab MSG_INTL(MSG_DEBUG_DT2NDX), 736d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), 737d29b2c44Sab argstate->dyn.sec->sec_name, EC_WORD(ndx), arg); 738d29b2c44Sab return (ndx); 739d29b2c44Sab } 740d29b2c44Sab } 741d29b2c44Sab 742d29b2c44Sab /* Not found. Can we create one? */ 743d29b2c44Sab if (argstate->dyn.num_null_ndx > 1) 744d29b2c44Sab return (convert_dt_null(argstate, dt_value, 0)); 745d29b2c44Sab 746d29b2c44Sab /* No room to create one, so we're out of options and must fail */ 747d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT), 748d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), 749d29b2c44Sab argstate->dyn.sec->sec_name, arg); 750d29b2c44Sab 751d29b2c44Sab /*NOTREACHED*/ 752d29b2c44Sab return (0); /* For lint */ 753d29b2c44Sab } 754d29b2c44Sab 755d29b2c44Sab 756d29b2c44Sab /* 757d29b2c44Sab * Called by cmd_body() for dyn:value. Implements the core functionality 758d29b2c44Sab * for that command. 759d29b2c44Sab * 760d29b2c44Sab * This routine expects that both the index and value arguments are 761d29b2c44Sab * present. 762d29b2c44Sab */ 763d29b2c44Sab static elfedit_cmdret_t 764d29b2c44Sab cmd_body_value(ARGSTATE *argstate, Word *ret_ndx) 765d29b2c44Sab { 766d29b2c44Sab elfedit_section_t *dynsec = argstate->dyn.sec; 767d29b2c44Sab elfedit_section_t *strsec = argstate->strsec; 768d29b2c44Sab elfedit_dyn_elt_t strpad_elt; 769d29b2c44Sab Word i; 770d29b2c44Sab Dyn *dyn = argstate->dyn.data; 771d29b2c44Sab Word numdyn = argstate->dyn.num; 77255ef6355Sab int minus_add, minus_s, minus_dynndx; 773*4f680cc6SAli Bahrami Word tmp_val; 774*4f680cc6SAli Bahrami Xword arg1, arg2; 775d29b2c44Sab int arg2_known = 1; 776d29b2c44Sab 77755ef6355Sab minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0); 77855ef6355Sab minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0); 77955ef6355Sab minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0); 780d29b2c44Sab 781d29b2c44Sab elfedit_dyn_elt_init(&strpad_elt); 782d29b2c44Sab 783d29b2c44Sab /* 784d29b2c44Sab * The first argument is an index if -dynndx is used, and is a 785d29b2c44Sab * tag value otherwise. 786d29b2c44Sab */ 787d29b2c44Sab arg1 = minus_dynndx ? 788d29b2c44Sab elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT), 789d29b2c44Sab 0, numdyn - 1, NULL) : 790d29b2c44Sab elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT); 791d29b2c44Sab 792d29b2c44Sab if (minus_s) { 793d29b2c44Sab /* 794d29b2c44Sab * Don't allow the user to specify -s when manipulating a 795d29b2c44Sab * DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to 796d29b2c44Sab * manage the extra space used for strings, this would break 797d29b2c44Sab * our ability to add the string. 798d29b2c44Sab */ 799d29b2c44Sab if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) || 800d29b2c44Sab (minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD))) 801d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, 802d29b2c44Sab MSG_INTL(MSG_ERR_STRPADSTRVAL), 803d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 804d29b2c44Sab 805d29b2c44Sab /* Locate DT_SUNW_STRPAD element if present */ 806d29b2c44Sab strpad_elt.dn_dyn.d_un.d_val = 0; 807*4f680cc6SAli Bahrami (void) elfedit_dynstr_getpad(argstate->obj_state, 808*4f680cc6SAli Bahrami argstate->dyn.sec, &strpad_elt); 809d29b2c44Sab 810d29b2c44Sab /* 811d29b2c44Sab * Look up the string: If the user specified the -dynndx 812d29b2c44Sab * -option, then we will insert it if possible, and 813d29b2c44Sab * fail with an error if not. However, if they did not 814d29b2c44Sab * specify -dynndx, we want to look up the string if it is 815d29b2c44Sab * already there, but defer the insertion. The reason for 816d29b2c44Sab * this is that we may have to grab an unused DT_NULL element 817d29b2c44Sab * below, and if there are none available, we won't want 818d29b2c44Sab * to have modified the string table. 819d29b2c44Sab * 820d29b2c44Sab * This isn't a problem, because if the string isn't 821d29b2c44Sab * in the string table, it can't be used by a dynamic element. 822d29b2c44Sab * Hence, we don't need to insert it to know that there is 823d29b2c44Sab * no match. 824d29b2c44Sab */ 825d29b2c44Sab if (minus_dynndx == 0) { 826d29b2c44Sab if (elfedit_sec_findstr(strsec, 827d29b2c44Sab strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1], 828d29b2c44Sab &tmp_val) == 0) { 829d29b2c44Sab arg2_known = 0; 830d29b2c44Sab } else { 831d29b2c44Sab arg2 = tmp_val; 832d29b2c44Sab } 833d29b2c44Sab } else { 834d29b2c44Sab arg2 = elfedit_dynstr_insert(dynsec, strsec, 835d29b2c44Sab &strpad_elt, argstate->argv[1]); 836d29b2c44Sab } 837d29b2c44Sab } else { /* Argument 2 is an integer */ 838d29b2c44Sab arg2 = elfedit_atoui(argstate->argv[1], NULL); 839d29b2c44Sab } 840d29b2c44Sab 841d29b2c44Sab 842d29b2c44Sab if (!minus_dynndx && !(minus_add && !arg2_known)) { 843d29b2c44Sab /* 844d29b2c44Sab * Search the dynamic section and see if an item with the 845d29b2c44Sab * specified tag value already exists. We can reduce this 846d29b2c44Sab * to a simple update of an existing value if -add is not 847d29b2c44Sab * specified or the existing d_un value matches the new one. 848d29b2c44Sab * 849d29b2c44Sab * In either of these cases, we will change arg1 to be the 850d29b2c44Sab * index, and set minus_dynndx, causing the simple update to 851d29b2c44Sab * happen immediately below. 852d29b2c44Sab */ 853d29b2c44Sab for (i = 0; i < numdyn; i++) { 854d29b2c44Sab if ((dyn[i].d_tag == arg1) && 855d29b2c44Sab (!minus_add || (dyn[i].d_un.d_val == arg2))) { 856d29b2c44Sab arg1 = i; 857d29b2c44Sab minus_dynndx = 1; 858d29b2c44Sab break; 859d29b2c44Sab } 860d29b2c44Sab } 861d29b2c44Sab } 862d29b2c44Sab 863d29b2c44Sab /* 864d29b2c44Sab * If -dynndx is used, then this is a relatively simple 865d29b2c44Sab * operation, as we simply write over the specified index. 866d29b2c44Sab */ 867d29b2c44Sab if (minus_dynndx) { 868d29b2c44Sab /* 869d29b2c44Sab * If we held back from inserting a new string into 870d29b2c44Sab * the dynstr above, we insert it now, because we 871d29b2c44Sab * have a slot in the dynamic section, and we need 872d29b2c44Sab * the string offset ot finish. 873d29b2c44Sab */ 874d29b2c44Sab if (!arg2_known) 875d29b2c44Sab arg2 = elfedit_dynstr_insert(dynsec, strsec, 876d29b2c44Sab &strpad_elt, argstate->argv[1]); 877d29b2c44Sab 878d29b2c44Sab *ret_ndx = arg1; 879d29b2c44Sab if (dyn[arg1].d_un.d_val == arg2) { 880d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 881d29b2c44Sab MSG_INTL(MSG_DEBUG_X_OK), 882d29b2c44Sab dynsec->sec_shndx, dynsec->sec_name, 883d29b2c44Sab EC_WORD(arg1), EC_XWORD(arg2)); 884d29b2c44Sab return (ELFEDIT_CMDRET_NONE); 885d29b2c44Sab } else { 886d29b2c44Sab /* Warn if setting DT_NULL value to non-zero */ 887d29b2c44Sab if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0)) 888d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 889d29b2c44Sab MSG_INTL(MSG_DEBUG_DTNULLVALUE), 890d29b2c44Sab dynsec->sec_shndx, dynsec->sec_name, 891d29b2c44Sab EC_WORD(arg1), EC_XWORD(arg2)); 892d29b2c44Sab 893d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 894d29b2c44Sab MSG_INTL(MSG_DEBUG_X_CHG), 895d29b2c44Sab dynsec->sec_shndx, dynsec->sec_name, 896d29b2c44Sab EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val), 897d29b2c44Sab EC_XWORD(arg2)); 898d29b2c44Sab dyn[arg1].d_un.d_val = arg2; 899d29b2c44Sab return (ELFEDIT_CMDRET_MOD); 900d29b2c44Sab } 901d29b2c44Sab } 902d29b2c44Sab 903d29b2c44Sab /* 904d29b2c44Sab * We need a new slot in the dynamic section. If we can't have 905d29b2c44Sab * one, then we fail. 906d29b2c44Sab */ 907d29b2c44Sab if (argstate->dyn.num_null_ndx <= 1) 908d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 909d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 910d29b2c44Sab 911d29b2c44Sab /* 912d29b2c44Sab * If we still need to insert a new string into the dynstr, 913d29b2c44Sab * then it is safe now, because if we succeed, we know that 914d29b2c44Sab * there is an available slot to receive it. If we fail, we 915d29b2c44Sab * haven't claimed the extra slot yet, and it will be unharmed. 916d29b2c44Sab */ 917d29b2c44Sab if (!arg2_known) 918d29b2c44Sab arg2 = elfedit_dynstr_insert(dynsec, strsec, 919d29b2c44Sab &strpad_elt, argstate->argv[1]); 920d29b2c44Sab 921d29b2c44Sab /* Use an extra DT_NULL slot and enter the new element */ 922d29b2c44Sab *ret_ndx = convert_dt_null(argstate, arg1, arg2); 923d29b2c44Sab return (ELFEDIT_CMDRET_MOD); 924d29b2c44Sab } 925d29b2c44Sab 926d29b2c44Sab 927d29b2c44Sab 928d29b2c44Sab /* 929d29b2c44Sab * Called by cmd_body() for dyn:runpath. Implements the core functionality 930d29b2c44Sab * for that command. 931d29b2c44Sab * 932d29b2c44Sab * History Lesson And Strategy: 933d29b2c44Sab * 934d29b2c44Sab * This routine handles both DT_RPATH and DT_RUNPATH entries, altering 935d29b2c44Sab * either or both if they are present. 936d29b2c44Sab * 937d29b2c44Sab * The original SYSV ABI only had DT_RPATH, and the runtime loader used 938d29b2c44Sab * it to search for things in the following order: 939d29b2c44Sab * 940d29b2c44Sab * DT_RPATH, LD_LIBRARY_PATH, defaults 941d29b2c44Sab * 942d29b2c44Sab * Solaris did not follow this rule, an extremely rare deviation from 943d29b2c44Sab * the ABI. Environment variables should supercede everything else, 944d29b2c44Sab * otherwise they are not very useful. This decision was made at the 945d29b2c44Sab * very beginning of the SunOS 5.x development, so we have always 946d29b2c44Sab * deviated from the ABI and and instead search in the order 947d29b2c44Sab * 948d29b2c44Sab * LD_LIBRARY_PATH, DT_RPATH, defaults 949d29b2c44Sab * 950d29b2c44Sab * Other Unix variants initially followed the ABI, but in recent years 951d29b2c44Sab * have come to agree with the early Solaris folks that it was a mistake. 952d29b2c44Sab * Hence, DT_RUNPATH was invented, with the search order: 953d29b2c44Sab * 954d29b2c44Sab * LD_LIBRARY_PATH, DT_RUNPATH, defaults 955d29b2c44Sab * 956d29b2c44Sab * So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both 957d29b2c44Sab * are present (which does happen), we set them both to the new 958d29b2c44Sab * value. If either one is present, we set that one. If neither is 959d29b2c44Sab * present, and we have a spare DT_NULL slot, we create a DT_RUNPATH, but 960d29b2c44Sab * not a DT_RPATH, to conserve available slots for other uses. 961d29b2c44Sab */ 962d29b2c44Sab static elfedit_cmdret_t 963d29b2c44Sab cmd_body_runpath(ARGSTATE *argstate) 964d29b2c44Sab { 965d29b2c44Sab elfedit_section_t *dynsec = argstate->dyn.sec; 966d29b2c44Sab elfedit_section_t *strsec = argstate->strsec; 967d29b2c44Sab elfedit_dyn_elt_t rpath_elt; 968d29b2c44Sab elfedit_dyn_elt_t runpath_elt; 969d29b2c44Sab elfedit_dyn_elt_t strpad_elt; 970d29b2c44Sab Word i; 971d29b2c44Sab Dyn *dyn = argstate->dyn.data; 972d29b2c44Sab Word numdyn = argstate->dyn.num; 973d29b2c44Sab 974d29b2c44Sab /* Go through the tags and gather what we need */ 975d29b2c44Sab elfedit_dyn_elt_init(&rpath_elt); 976d29b2c44Sab elfedit_dyn_elt_init(&runpath_elt); 977d29b2c44Sab elfedit_dyn_elt_init(&strpad_elt); 978d29b2c44Sab for (i = 0; i < numdyn; i++) { 979d29b2c44Sab switch (dyn[i].d_tag) { 980d29b2c44Sab case DT_RPATH: 981d29b2c44Sab elfedit_dyn_elt_save(&rpath_elt, i, &dyn[i]); 982d29b2c44Sab break; 983d29b2c44Sab 984d29b2c44Sab case DT_RUNPATH: 985d29b2c44Sab elfedit_dyn_elt_save(&runpath_elt, i, &dyn[i]); 986d29b2c44Sab break; 987d29b2c44Sab 988d29b2c44Sab case DT_SUNW_STRPAD: 989*4f680cc6SAli Bahrami if (elfedit_test_osabi(argstate->obj_state, 990*4f680cc6SAli Bahrami ELFOSABI_SOLARIS, 0)) 991*4f680cc6SAli Bahrami elfedit_dyn_elt_save(&strpad_elt, i, &dyn[i]); 992d29b2c44Sab break; 993d29b2c44Sab } 994d29b2c44Sab } 995d29b2c44Sab 996d29b2c44Sab /* Do we have an available dynamic section entry to use? */ 997d29b2c44Sab if (rpath_elt.dn_seen || runpath_elt.dn_seen) { 998d29b2c44Sab /* 999d29b2c44Sab * We have seen a DT_RPATH, or a DT_RUNPATH, or both. 1000d29b2c44Sab * If all of these have the same string as the desired 1001d29b2c44Sab * new value, then we don't need to alter anything and can 1002d29b2c44Sab * simply return. Otherwise, we'll modify them all to have 1003d29b2c44Sab * the new string (below). 1004d29b2c44Sab */ 1005d29b2c44Sab if ((!rpath_elt.dn_seen || 1006d29b2c44Sab (strcmp(elfedit_dyn_offset_to_str(strsec, &rpath_elt), 1007d29b2c44Sab argstate->argv[0]) == 0)) && 1008d29b2c44Sab (!runpath_elt.dn_seen || 1009d29b2c44Sab (strcmp(elfedit_dyn_offset_to_str(strsec, &runpath_elt), 1010d29b2c44Sab argstate->argv[0]) == 0))) { 1011d29b2c44Sab if (rpath_elt.dn_seen) 1012d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1013d29b2c44Sab MSG_INTL(MSG_DEBUG_OLDRPATHOK), 1014d29b2c44Sab EC_WORD(dynsec->sec_shndx), 1015d29b2c44Sab dynsec->sec_name, EC_WORD(rpath_elt.dn_ndx), 1016d29b2c44Sab elfedit_atoconst_value_to_str( 1017d29b2c44Sab ELFEDIT_CONST_DT, DT_RPATH, 1)); 1018d29b2c44Sab if (runpath_elt.dn_seen) 1019d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1020d29b2c44Sab MSG_INTL(MSG_DEBUG_OLDRPATHOK), 1021d29b2c44Sab EC_WORD(dynsec->sec_shndx), 1022d29b2c44Sab dynsec->sec_name, 1023d29b2c44Sab EC_WORD(runpath_elt.dn_ndx), 1024d29b2c44Sab elfedit_atoconst_value_to_str( 1025d29b2c44Sab ELFEDIT_CONST_DT, DT_RUNPATH, 1)); 1026d29b2c44Sab return (ELFEDIT_CMDRET_NONE); 1027d29b2c44Sab } 1028d29b2c44Sab } else if (argstate->dyn.num_null_ndx <= 1) { 1029d29b2c44Sab /* 1030d29b2c44Sab * There is no DT_RPATH or DT_RUNPATH in the dynamic array, 1031d29b2c44Sab * and there are no extra DT_NULL entries that we can 1032d29b2c44Sab * convert into one. We cannot proceed. 1033d29b2c44Sab */ 1034d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 1035d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 1036d29b2c44Sab } 1037d29b2c44Sab 1038d29b2c44Sab /* Does the string exist in the table already, or can we add it? */ 1039d29b2c44Sab rpath_elt.dn_dyn.d_un.d_val = runpath_elt.dn_dyn.d_un.d_val = 1040d29b2c44Sab elfedit_dynstr_insert(dynsec, strsec, &strpad_elt, 1041d29b2c44Sab argstate->argv[0]); 1042d29b2c44Sab 1043d29b2c44Sab /* Update DT_RPATH entry if present */ 1044d29b2c44Sab if (rpath_elt.dn_seen) { 1045d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_PREVRPATH), 1046d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 1047d29b2c44Sab EC_WORD(rpath_elt.dn_ndx), 1048d29b2c44Sab elfedit_atoconst_value_to_str( 1049d29b2c44Sab ELFEDIT_CONST_DT, DT_RPATH, 1), 1050d29b2c44Sab elfedit_dyn_offset_to_str(strsec, &rpath_elt)); 1051d29b2c44Sab dyn[rpath_elt.dn_ndx] = rpath_elt.dn_dyn; 1052d29b2c44Sab } 1053d29b2c44Sab 1054d29b2c44Sab /* 1055d29b2c44Sab * Update the DT_RUNPATH entry in the dynamic section, if present. 1056d29b2c44Sab * If one is not present, and there is also no DT_RPATH, then 1057d29b2c44Sab * we use a spare DT_NULL entry to create a new DT_RUNPATH. 1058d29b2c44Sab */ 1059d29b2c44Sab if (runpath_elt.dn_seen || !rpath_elt.dn_seen) { 1060d29b2c44Sab if (runpath_elt.dn_seen) { 1061d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1062d29b2c44Sab MSG_INTL(MSG_DEBUG_PREVRPATH), 1063d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 1064d29b2c44Sab EC_WORD(runpath_elt.dn_ndx), 1065d29b2c44Sab elfedit_atoconst_value_to_str( 1066d29b2c44Sab ELFEDIT_CONST_DT, DT_RUNPATH, 1), 1067d29b2c44Sab elfedit_dyn_offset_to_str(strsec, &runpath_elt)); 1068d29b2c44Sab dyn[runpath_elt.dn_ndx] = runpath_elt.dn_dyn; 1069d29b2c44Sab } else { /* Using a spare DT_NULL entry */ 1070d29b2c44Sab (void) convert_dt_null(argstate, DT_RUNPATH, 1071d29b2c44Sab runpath_elt.dn_dyn.d_un.d_val); 1072d29b2c44Sab } 1073d29b2c44Sab } 1074d29b2c44Sab 1075d29b2c44Sab return (ELFEDIT_CMDRET_MOD); 1076d29b2c44Sab } 1077d29b2c44Sab 1078d29b2c44Sab 1079d29b2c44Sab 1080d29b2c44Sab /* 1081d29b2c44Sab * Argument processing for the bitmask commands. Convert the arguments 1082d29b2c44Sab * to integer form, apply -and/-cmp/-or, and return the resulting value. 1083d29b2c44Sab * 1084d29b2c44Sab * entry: 1085d29b2c44Sab * argstate - Argument state block 1086d29b2c44Sab * orig - Value of original bitmask 1087d29b2c44Sab * const_type - ELFEDIT_CONST_* value for type of constants 1088d29b2c44Sab */ 1089d29b2c44Sab static Word 1090d29b2c44Sab flag_bitop(ARGSTATE *argstate, Word orig, elfedit_const_t const_type) 1091d29b2c44Sab { 1092d29b2c44Sab Word flags = 0; 1093d29b2c44Sab int i; 1094d29b2c44Sab 1095d29b2c44Sab /* Collect the arguments */ 1096d29b2c44Sab for (i = 0; i < argstate->argc; i++) 1097d29b2c44Sab flags |= (Word) elfedit_atoconst(argstate->argv[i], const_type); 1098d29b2c44Sab 1099d29b2c44Sab /* Complement the value? */ 1100d29b2c44Sab if (argstate->optmask & DYN_OPT_F_CMP) 1101d29b2c44Sab flags = ~flags; 1102d29b2c44Sab 1103d29b2c44Sab /* Perform any requested bit operations */ 1104d29b2c44Sab if (argstate->optmask & DYN_OPT_F_AND) 1105d29b2c44Sab flags &= orig; 1106d29b2c44Sab else if (argstate->optmask & DYN_OPT_F_OR) 1107d29b2c44Sab flags |= orig; 1108d29b2c44Sab 1109d29b2c44Sab return (flags); 1110d29b2c44Sab } 1111d29b2c44Sab 1112d29b2c44Sab 1113d29b2c44Sab 1114d29b2c44Sab /* 1115d29b2c44Sab * Common body for the dyn: module commands. These commands 1116d29b2c44Sab * share a large amount of common behavior, so it is convenient 1117d29b2c44Sab * to centralize things and use the cmd argument to handle the 1118d29b2c44Sab * small differences. 1119d29b2c44Sab * 1120d29b2c44Sab * entry: 1121d29b2c44Sab * cmd - One of the DYN_CMD_T_* constants listed above, specifying 1122d29b2c44Sab * which command to implement. 1123d29b2c44Sab * obj_state, argc, argv - Standard command arguments 1124d29b2c44Sab */ 1125d29b2c44Sab static elfedit_cmdret_t 1126d29b2c44Sab cmd_body(DYN_CMD_T cmd, elfedit_obj_state_t *obj_state, 1127d29b2c44Sab int argc, const char *argv[]) 1128d29b2c44Sab { 1129d29b2c44Sab ARGSTATE argstate; 1130d29b2c44Sab Dyn *dyn; 1131d29b2c44Sab const char *dyn_name; 1132d29b2c44Sab Word dyn_ndx, dyn_num, null_ndx; 1133d29b2c44Sab elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 1134d29b2c44Sab PRINT_DYN_T print_type = PRINT_DYN_T_ALL; 1135d29b2c44Sab Word ndx; 1136d29b2c44Sab int print_only = 0; 1137d29b2c44Sab int do_autoprint = 1; 1138d29b2c44Sab 1139d29b2c44Sab /* Process the optional arguments */ 1140d29b2c44Sab process_args(obj_state, argc, argv, &argstate); 1141d29b2c44Sab 1142d29b2c44Sab dyn = argstate.dyn.data; 1143d29b2c44Sab dyn_num = argstate.dyn.num; 1144d29b2c44Sab dyn_name = argstate.dyn.sec->sec_name; 1145d29b2c44Sab dyn_ndx = argstate.dyn.sec->sec_shndx; 1146d29b2c44Sab 1147d29b2c44Sab /* Check number of arguments, gather information */ 1148d29b2c44Sab switch (cmd) { 1149d29b2c44Sab case DYN_CMD_T_DUMP: 1150d29b2c44Sab /* dyn:dump can accept an optional index argument */ 1151d29b2c44Sab if (argstate.argc > 1) 1152d29b2c44Sab elfedit_command_usage(); 1153d29b2c44Sab print_only = 1; 1154d29b2c44Sab if (argstate.argc == 1) 1155d29b2c44Sab ndx = arg_to_index(&argstate, argstate.argv[0], 115655ef6355Sab print_only, &print_type); 1157d29b2c44Sab break; 1158d29b2c44Sab 1159d29b2c44Sab case DYN_CMD_T_TAG: 1160d29b2c44Sab print_only = (argstate.argc != 2); 1161d29b2c44Sab if (argstate.argc > 0) { 1162d29b2c44Sab if (argstate.argc > 2) 1163d29b2c44Sab elfedit_command_usage(); 1164d29b2c44Sab ndx = arg_to_index(&argstate, argstate.argv[0], 116555ef6355Sab print_only, &print_type); 1166d29b2c44Sab } 1167d29b2c44Sab break; 1168d29b2c44Sab 1169d29b2c44Sab case DYN_CMD_T_VALUE: 1170d29b2c44Sab print_only = (argstate.argc != 2); 1171d29b2c44Sab if (argstate.argc > 2) 1172d29b2c44Sab elfedit_command_usage(); 1173d29b2c44Sab if (argstate.argc > 0) { 1174d29b2c44Sab if (print_only) { 1175d29b2c44Sab ndx = arg_to_index(&argstate, argstate.argv[0], 1176d29b2c44Sab print_only, &print_type); 1177d29b2c44Sab } else { 1178d29b2c44Sab print_type = PRINT_DYN_T_NDX; 1179d29b2c44Sab } 1180d29b2c44Sab } 1181d29b2c44Sab break; 1182d29b2c44Sab 1183d29b2c44Sab case DYN_CMD_T_DELETE: 1184d29b2c44Sab if ((argstate.argc < 1) || (argstate.argc > 2)) 1185d29b2c44Sab elfedit_command_usage(); 1186d29b2c44Sab ndx = arg_to_index(&argstate, argstate.argv[0], 1187d29b2c44Sab 0, &print_type); 1188d29b2c44Sab do_autoprint = 0; 1189d29b2c44Sab break; 1190d29b2c44Sab 1191d29b2c44Sab case DYN_CMD_T_MOVE: 1192d29b2c44Sab if ((argstate.argc < 2) || (argstate.argc > 3)) 1193d29b2c44Sab elfedit_command_usage(); 1194d29b2c44Sab ndx = arg_to_index(&argstate, argstate.argv[0], 119555ef6355Sab 0, &print_type); 1196d29b2c44Sab do_autoprint = 0; 1197d29b2c44Sab break; 1198d29b2c44Sab 1199d29b2c44Sab case DYN_CMD_T_RUNPATH: 1200d29b2c44Sab if (argstate.argc > 1) 1201d29b2c44Sab elfedit_command_usage(); 1202d29b2c44Sab /* 1203d29b2c44Sab * dyn:runpath does not accept an explicit index 1204d29b2c44Sab * argument, so we implicitly only show the DT_RPATH and 1205d29b2c44Sab * DT_RUNPATH elements. 1206d29b2c44Sab */ 1207d29b2c44Sab print_type = PRINT_DYN_T_RUNPATH; 1208d29b2c44Sab print_only = (argstate.argc == 0); 1209d29b2c44Sab break; 1210d29b2c44Sab 1211d29b2c44Sab case DYN_CMD_T_POSFLAG1: 1212d29b2c44Sab print_only = (argstate.argc == 0); 1213d29b2c44Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1214d29b2c44Sab ELFEDIT_CONST_DT, DT_POSFLAG_1, 1), 121555ef6355Sab print_only, &print_type); 1216d29b2c44Sab break; 1217d29b2c44Sab 1218d29b2c44Sab case DYN_CMD_T_FLAGS: 1219d29b2c44Sab print_only = (argstate.argc == 0); 1220d29b2c44Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1221d29b2c44Sab ELFEDIT_CONST_DT, DT_FLAGS, 1), 122255ef6355Sab print_only, &print_type); 1223d29b2c44Sab break; 1224d29b2c44Sab 1225d29b2c44Sab case DYN_CMD_T_FLAGS1: 1226d29b2c44Sab print_only = (argstate.argc == 0); 1227d29b2c44Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1228d29b2c44Sab ELFEDIT_CONST_DT, DT_FLAGS_1, 1), 122955ef6355Sab print_only, &print_type); 1230d29b2c44Sab break; 1231d29b2c44Sab 1232d29b2c44Sab case DYN_CMD_T_FEATURE1: 1233d29b2c44Sab print_only = (argstate.argc == 0); 1234d29b2c44Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1235d29b2c44Sab ELFEDIT_CONST_DT, DT_FEATURE_1, 1), 123655ef6355Sab print_only, &print_type); 1237d29b2c44Sab break; 1238d29b2c44Sab 1239d29b2c44Sab case DYN_CMD_T_CHECKSUM: 1240d29b2c44Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1241d29b2c44Sab ELFEDIT_CONST_DT, DT_CHECKSUM, 1), 124255ef6355Sab print_only, &print_type); 1243d29b2c44Sab break; 1244d29b2c44Sab 1245ba2be530Sab case DYN_CMD_T_SUNW_LDMACH: 1246ba2be530Sab if (argstate.argc > 1) 1247ba2be530Sab elfedit_command_usage(); 1248*4f680cc6SAli Bahrami /* DT_SUNW_LDMACH is an ELFOSABI_SOLARIS feature */ 1249*4f680cc6SAli Bahrami (void) elfedit_test_osabi(argstate.obj_state, 1250*4f680cc6SAli Bahrami ELFOSABI_SOLARIS, 1); 1251ba2be530Sab print_only = (argstate.argc == 0); 1252ba2be530Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1253ba2be530Sab ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1), 125455ef6355Sab print_only, &print_type); 1255ba2be530Sab break; 1256ba2be530Sab 1257d29b2c44Sab default: 1258d29b2c44Sab /* Note expected: All commands should have been caught above */ 1259d29b2c44Sab elfedit_command_usage(); 1260d29b2c44Sab break; 1261d29b2c44Sab } 1262d29b2c44Sab 1263d29b2c44Sab 1264d29b2c44Sab /* If this is a request to print current values, do it and return */ 1265d29b2c44Sab if (print_only) { 1266d29b2c44Sab print_dyn(cmd, 0, &argstate, print_type, ndx); 1267d29b2c44Sab return (ELFEDIT_CMDRET_NONE); 1268d29b2c44Sab } 1269d29b2c44Sab 1270d29b2c44Sab 1271d29b2c44Sab switch (cmd) { 1272d29b2c44Sab /* 1273d29b2c44Sab * DYN_CMD_T_DUMP can't get here: It is a print-only 1274d29b2c44Sab * command. 1275d29b2c44Sab */ 1276d29b2c44Sab 1277d29b2c44Sab case DYN_CMD_T_TAG: 1278d29b2c44Sab { 1279*4f680cc6SAli Bahrami Ehdr *ehdr = argstate.obj_state->os_ehdr; 1280*4f680cc6SAli Bahrami uchar_t osabi = ehdr->e_ident[EI_OSABI]; 1281*4f680cc6SAli Bahrami Half mach = ehdr->e_machine; 1282d29b2c44Sab Conv_inv_buf_t inv_buf1, inv_buf2; 1283*4f680cc6SAli Bahrami Xword d_tag = (Xword) elfedit_atoconst(argstate.argv[1], 1284d29b2c44Sab ELFEDIT_CONST_DT); 1285d29b2c44Sab 1286d29b2c44Sab if (dyn[ndx].d_tag == d_tag) { 1287d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1288*4f680cc6SAli Bahrami MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, dyn_name, 1289*4f680cc6SAli Bahrami EC_WORD(ndx), conv_dyn_tag(d_tag, osabi, 1290*4f680cc6SAli Bahrami mach, 0, &inv_buf1)); 1291d29b2c44Sab } else { 1292*4f680cc6SAli Bahrami Xword orig_d_tag = dyn[ndx].d_tag; 1293d29b2c44Sab 1294d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1295d29b2c44Sab dyn[ndx].d_tag = d_tag; 1296d29b2c44Sab 1297d29b2c44Sab /* 1298d29b2c44Sab * Update null termination index. Warn if we 1299d29b2c44Sab * just clobbered the only DT_NULL termination 1300d29b2c44Sab * for the array. 1301d29b2c44Sab */ 1302d29b2c44Sab null_ndx = argstate.dyn.null_ndx; 1303d29b2c44Sab set_null_ndx(&argstate); 1304d29b2c44Sab if ((argstate.dyn.null_ndx >= 1305d29b2c44Sab argstate.dyn.num) && 1306d29b2c44Sab (null_ndx != argstate.dyn.null_ndx)) 1307d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1308d29b2c44Sab MSG_INTL(MSG_DEBUG_NULLTERM), 1309d29b2c44Sab dyn_ndx, dyn_name, 1310*4f680cc6SAli Bahrami EC_WORD(ndx), conv_dyn_tag(d_tag, 1311*4f680cc6SAli Bahrami osabi, mach, 0, &inv_buf1)); 1312d29b2c44Sab 1313d29b2c44Sab /* 1314d29b2c44Sab * Warning if 1315d29b2c44Sab * - Inserting a DT_NULL cuts off following 1316d29b2c44Sab * non-null elements. 1317d29b2c44Sab * - Inserting a non-DT_NULL after the 1318d29b2c44Sab * first null element, will be 1319d29b2c44Sab * ignored by rtld. 1320d29b2c44Sab */ 1321d29b2c44Sab if (d_tag == DT_NULL) { 1322d29b2c44Sab if ((ndx + 1) < null_ndx) 1323d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1324d29b2c44Sab MSG_INTL(MSG_DEBUG_NULCLIP), 1325d29b2c44Sab dyn_ndx, dyn_name, 1326d29b2c44Sab EC_WORD(ndx), 1327*4f680cc6SAli Bahrami conv_dyn_tag(d_tag, osabi, 1328*4f680cc6SAli Bahrami mach, 0, &inv_buf1)); 1329d29b2c44Sab } else { 1330d29b2c44Sab if ((ndx + 1) > argstate.dyn.null_ndx) 1331d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1332d29b2c44Sab MSG_INTL(MSG_DEBUG_NULHIDE), 1333d29b2c44Sab dyn_ndx, dyn_name, 1334d29b2c44Sab EC_WORD(ndx), 1335*4f680cc6SAli Bahrami conv_dyn_tag(d_tag, osabi, 1336*4f680cc6SAli Bahrami mach, 0, &inv_buf1)); 1337d29b2c44Sab } 1338d29b2c44Sab 1339d29b2c44Sab /* Debug message that we changed it */ 1340d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1341d29b2c44Sab MSG_INTL(MSG_DEBUG_S_CHG), 1342d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1343*4f680cc6SAli Bahrami conv_dyn_tag(orig_d_tag, osabi, mach, 0, 1344d29b2c44Sab &inv_buf1), 1345*4f680cc6SAli Bahrami conv_dyn_tag(d_tag, osabi, mach, 0, 1346*4f680cc6SAli Bahrami &inv_buf2)); 1347d29b2c44Sab } 1348d29b2c44Sab } 1349d29b2c44Sab break; 1350d29b2c44Sab 1351d29b2c44Sab case DYN_CMD_T_VALUE: 1352d29b2c44Sab ret = cmd_body_value(&argstate, &ndx); 1353d29b2c44Sab break; 1354d29b2c44Sab 1355d29b2c44Sab case DYN_CMD_T_DELETE: 1356d29b2c44Sab { 1357d29b2c44Sab Word cnt = (argstate.argc == 1) ? 1 : 1358d29b2c44Sab (Word) elfedit_atoui_range(argstate.argv[1], 1359d29b2c44Sab MSG_ORIG(MSG_STR_COUNT), 1, dyn_num - ndx, NULL); 1360d29b2c44Sab const char *msg_prefix = 1361d29b2c44Sab elfedit_sec_msgprefix(argstate.dyn.sec); 1362d29b2c44Sab 1363d29b2c44Sab elfedit_array_elts_delete(msg_prefix, argstate.dyn.data, 1364d29b2c44Sab sizeof (Dyn), dyn_num, ndx, cnt); 1365d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1366d29b2c44Sab } 1367d29b2c44Sab break; 1368d29b2c44Sab 1369d29b2c44Sab case DYN_CMD_T_MOVE: 1370d29b2c44Sab { 1371d29b2c44Sab Dyn save; 1372d29b2c44Sab Word cnt; 1373d29b2c44Sab Word dstndx; 1374d29b2c44Sab const char *msg_prefix = 1375d29b2c44Sab elfedit_sec_msgprefix(argstate.dyn.sec); 1376d29b2c44Sab 1377d29b2c44Sab dstndx = (Word) 1378d29b2c44Sab elfedit_atoui_range(argstate.argv[1], 1379d29b2c44Sab MSG_ORIG(MSG_STR_DST_INDEX), 0, dyn_num - 1, 1380d29b2c44Sab NULL); 1381d29b2c44Sab if (argstate.argc == 2) { 1382d29b2c44Sab cnt = 1; 1383d29b2c44Sab } else { 1384d29b2c44Sab cnt = (Word) elfedit_atoui_range( 1385d29b2c44Sab argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), 1386d29b2c44Sab 1, dyn_num, NULL); 1387d29b2c44Sab } 1388d29b2c44Sab elfedit_array_elts_move(msg_prefix, argstate.dyn.data, 1389d29b2c44Sab sizeof (save), dyn_num, ndx, dstndx, cnt, &save); 1390d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1391d29b2c44Sab } 1392d29b2c44Sab break; 1393d29b2c44Sab 1394d29b2c44Sab 1395d29b2c44Sab case DYN_CMD_T_RUNPATH: 1396d29b2c44Sab ret = cmd_body_runpath(&argstate); 1397d29b2c44Sab break; 1398d29b2c44Sab 1399d29b2c44Sab case DYN_CMD_T_POSFLAG1: 1400d29b2c44Sab { 1401d29b2c44Sab Conv_dyn_posflag1_buf_t buf1, buf2; 1402d29b2c44Sab Word flags; 1403d29b2c44Sab 1404d29b2c44Sab flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 1405d29b2c44Sab ELFEDIT_CONST_DF_P1); 1406d29b2c44Sab 1407d29b2c44Sab /* Set the value */ 1408d29b2c44Sab if (dyn[ndx].d_un.d_val == flags) { 1409d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1410d29b2c44Sab MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1411d29b2c44Sab dyn_name, EC_WORD(ndx), 1412d29b2c44Sab conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 1413d29b2c44Sab &buf1)); 1414d29b2c44Sab } else { 1415d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1416d29b2c44Sab MSG_INTL(MSG_DEBUG_S_CHG), 1417d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1418d29b2c44Sab conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 1419d29b2c44Sab &buf1), 1420d29b2c44Sab conv_dyn_posflag1(flags, 0, &buf2)); 1421d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1422d29b2c44Sab dyn[ndx].d_un.d_val = flags; 1423d29b2c44Sab } 1424d29b2c44Sab } 1425d29b2c44Sab break; 1426d29b2c44Sab 1427d29b2c44Sab case DYN_CMD_T_FLAGS: 1428d29b2c44Sab { 1429d29b2c44Sab Conv_dyn_flag_buf_t buf1, buf2; 1430d29b2c44Sab Word flags; 1431d29b2c44Sab 1432d29b2c44Sab flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 1433d29b2c44Sab ELFEDIT_CONST_DF); 1434d29b2c44Sab 1435d29b2c44Sab /* Set the value */ 1436d29b2c44Sab if (dyn[ndx].d_un.d_val == flags) { 1437d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1438d29b2c44Sab MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1439d29b2c44Sab dyn_name, EC_WORD(ndx), 1440d29b2c44Sab conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 1441d29b2c44Sab &buf1)); 1442d29b2c44Sab } else { 1443d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1444d29b2c44Sab MSG_INTL(MSG_DEBUG_S_CHG), 1445d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1446d29b2c44Sab conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 1447d29b2c44Sab &buf1), 1448d29b2c44Sab conv_dyn_flag(flags, 0, &buf2)); 1449d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1450d29b2c44Sab dyn[ndx].d_un.d_val = flags; 1451d29b2c44Sab } 1452d29b2c44Sab } 1453d29b2c44Sab break; 1454d29b2c44Sab 1455d29b2c44Sab case DYN_CMD_T_FLAGS1: 1456d29b2c44Sab { 1457d29b2c44Sab Conv_dyn_flag1_buf_t buf1, buf2; 1458d29b2c44Sab Word flags1; 1459d29b2c44Sab 1460d29b2c44Sab flags1 = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 1461d29b2c44Sab ELFEDIT_CONST_DF_1); 1462d29b2c44Sab 1463d29b2c44Sab /* Set the value */ 1464d29b2c44Sab if (dyn[ndx].d_un.d_val == flags1) { 1465d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1466d29b2c44Sab MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1467d29b2c44Sab dyn_name, EC_WORD(ndx), 1468d29b2c44Sab conv_dyn_flag1(dyn[ndx].d_un.d_val, 1469d29b2c44Sab 0, &buf1)); 1470d29b2c44Sab } else { 1471d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1472d29b2c44Sab MSG_INTL(MSG_DEBUG_S_CHG), 1473d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1474d29b2c44Sab conv_dyn_flag1(dyn[ndx].d_un.d_val, 1475d29b2c44Sab 0, &buf1), 1476d29b2c44Sab conv_dyn_flag1(flags1, 0, &buf2)); 1477d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1478d29b2c44Sab dyn[ndx].d_un.d_val = flags1; 1479d29b2c44Sab } 1480d29b2c44Sab } 1481d29b2c44Sab break; 1482d29b2c44Sab 1483d29b2c44Sab case DYN_CMD_T_FEATURE1: 1484d29b2c44Sab { 1485d29b2c44Sab Conv_dyn_feature1_buf_t buf1, buf2; 1486d29b2c44Sab Word flags; 1487d29b2c44Sab 1488d29b2c44Sab flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 1489d29b2c44Sab ELFEDIT_CONST_DTF_1); 1490d29b2c44Sab 1491d29b2c44Sab /* Set the value */ 1492d29b2c44Sab if (dyn[ndx].d_un.d_val == flags) { 1493d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1494d29b2c44Sab MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1495d29b2c44Sab dyn_name, EC_WORD(ndx), 1496d29b2c44Sab conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 1497d29b2c44Sab &buf1)); 1498d29b2c44Sab } else { 1499d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1500d29b2c44Sab MSG_INTL(MSG_DEBUG_S_CHG), 1501d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1502d29b2c44Sab conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 1503d29b2c44Sab &buf1), 1504d29b2c44Sab conv_dyn_feature1(flags, 0, &buf2)); 1505d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1506d29b2c44Sab dyn[ndx].d_un.d_val = flags; 1507d29b2c44Sab } 1508d29b2c44Sab } 1509d29b2c44Sab break; 1510d29b2c44Sab 1511d29b2c44Sab case DYN_CMD_T_CHECKSUM: 1512d29b2c44Sab { 1513d29b2c44Sab long checksum = elf_checksum(obj_state->os_elf); 1514d29b2c44Sab 1515d29b2c44Sab /* Set the value */ 1516d29b2c44Sab if (dyn[ndx].d_un.d_val == checksum) { 1517d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1518d29b2c44Sab MSG_INTL(MSG_DEBUG_X_OK), dyn_ndx, 1519d29b2c44Sab dyn_name, EC_WORD(ndx), EC_XWORD(checksum)); 1520d29b2c44Sab } else { 1521d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1522d29b2c44Sab MSG_INTL(MSG_DEBUG_X_CHG), 1523d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1524d29b2c44Sab EC_XWORD(dyn[ndx].d_un.d_val), 1525d29b2c44Sab EC_XWORD(checksum)); 1526d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1527d29b2c44Sab dyn[ndx].d_un.d_val = checksum; 1528d29b2c44Sab } 1529d29b2c44Sab 1530d29b2c44Sab } 1531ba2be530Sab break; 1532ba2be530Sab 1533ba2be530Sab case DYN_CMD_T_SUNW_LDMACH: 1534ba2be530Sab { 1535ba2be530Sab Conv_inv_buf_t buf1, buf2; 1536ba2be530Sab Half ldmach; 1537ba2be530Sab 1538ba2be530Sab ldmach = (Half) elfedit_atoconst(argstate.argv[0], 1539ba2be530Sab ELFEDIT_CONST_EM); 1540ba2be530Sab 1541ba2be530Sab /* Set the value */ 1542ba2be530Sab if (dyn[ndx].d_un.d_val == ldmach) { 1543ba2be530Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1544ba2be530Sab MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1545ba2be530Sab dyn_name, EC_WORD(ndx), 1546ba2be530Sab conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 1547ba2be530Sab &buf1)); 1548ba2be530Sab } else { 1549ba2be530Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1550ba2be530Sab MSG_INTL(MSG_DEBUG_S_CHG), 1551ba2be530Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1552ba2be530Sab conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 1553ba2be530Sab &buf1), 1554ba2be530Sab conv_ehdr_mach(ldmach, 0, &buf2)); 1555ba2be530Sab ret = ELFEDIT_CMDRET_MOD; 1556ba2be530Sab dyn[ndx].d_un.d_val = ldmach; 1557ba2be530Sab } 1558ba2be530Sab } 1559ba2be530Sab break; 1560ba2be530Sab 1561d29b2c44Sab } 1562d29b2c44Sab 1563d29b2c44Sab /* 1564d29b2c44Sab * If we modified the dynamic section header, tell libelf. 1565d29b2c44Sab */ 1566d29b2c44Sab if (ret == ELFEDIT_CMDRET_MOD) 1567d29b2c44Sab elfedit_modified_data(argstate.dyn.sec); 1568d29b2c44Sab 1569d29b2c44Sab /* Do autoprint */ 1570d29b2c44Sab if (do_autoprint) 1571d29b2c44Sab print_dyn(cmd, 1, &argstate, print_type, ndx); 1572d29b2c44Sab 1573d29b2c44Sab return (ret); 1574d29b2c44Sab } 1575d29b2c44Sab 1576d29b2c44Sab 1577d29b2c44Sab 1578d29b2c44Sab /* 1579d29b2c44Sab * Command completion functions for the commands 1580d29b2c44Sab */ 1581d29b2c44Sab 1582d29b2c44Sab /* 1583d29b2c44Sab * Command completion for the first argument, which specifies 1584d29b2c44Sab * the dynamic element to use. Examines the options to see if 1585d29b2c44Sab * -dynndx is present, and if not, supplies the completion 1586d29b2c44Sab * strings for argument 1. 1587d29b2c44Sab */ 1588d29b2c44Sab /*ARGSUSED*/ 1589d29b2c44Sab static void 1590d29b2c44Sab cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1591d29b2c44Sab const char *argv[], int num_opt) 1592d29b2c44Sab { 1593d29b2c44Sab elfedit_section_t *cache; 1594d29b2c44Sab Dyn *dyn; 1595d29b2c44Sab Word i; 1596d29b2c44Sab const char *s; 1597d29b2c44Sab char *s2; 1598d29b2c44Sab char buf[128]; 1599d29b2c44Sab 1600d29b2c44Sab /* Make sure it's the first argument */ 1601d29b2c44Sab if ((argc - num_opt) != 1) 1602d29b2c44Sab return; 1603d29b2c44Sab 1604d29b2c44Sab /* Is -dynndx present? If so, we don't complete tag types */ 1605d29b2c44Sab for (i = 0; i < num_opt; i++) 1606d29b2c44Sab if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0) 1607d29b2c44Sab return; 1608d29b2c44Sab 1609d29b2c44Sab /* 1610d29b2c44Sab * If there is no object, or if there is no dynamic section, 1611d29b2c44Sab * then supply all possible names. 1612d29b2c44Sab */ 1613d29b2c44Sab if ((obj_state == NULL) || (obj_state->os_dynndx == SHN_UNDEF)) { 1614d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 1615d29b2c44Sab return; 1616d29b2c44Sab } 1617d29b2c44Sab 1618d29b2c44Sab /* Supply completions for the tags present in the dynamic section */ 1619d29b2c44Sab cache = &obj_state->os_secarr[obj_state->os_dynndx]; 1620d29b2c44Sab dyn = (Dyn *) cache->sec_data->d_buf; 1621d29b2c44Sab i = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize; 1622d29b2c44Sab for (; i-- > 0; dyn++) { 1623d29b2c44Sab s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_DT, 1624d29b2c44Sab dyn->d_tag, 0); 1625d29b2c44Sab if (s == NULL) 1626d29b2c44Sab continue; 1627d29b2c44Sab elfedit_cpl_match(cpldata, s, 1); 1628d29b2c44Sab 1629d29b2c44Sab /* 1630d29b2c44Sab * To get the informal tag names that are lowercase 1631d29b2c44Sab * and lack the leading DT_, we copy the string we 1632d29b2c44Sab * have into a buffer and process it. 1633d29b2c44Sab */ 1634d29b2c44Sab if (strlen(s) < 3) 1635d29b2c44Sab continue; 1636d29b2c44Sab (void) strlcpy(buf, s + 3, sizeof (buf)); 1637d29b2c44Sab for (s2 = buf; *s2 != '\0'; s2++) 1638d29b2c44Sab if (isupper(*s2)) 1639d29b2c44Sab *s2 = tolower(*s2); 1640d29b2c44Sab elfedit_cpl_match(cpldata, buf, 1); 1641d29b2c44Sab } 1642d29b2c44Sab } 1643d29b2c44Sab 1644d29b2c44Sab 1645d29b2c44Sab /*ARGSUSED*/ 1646d29b2c44Sab static void 1647d29b2c44Sab cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1648d29b2c44Sab const char *argv[], int num_opt) 1649d29b2c44Sab { 1650d29b2c44Sab /* First argument */ 1651d29b2c44Sab if ((argc - num_opt) == 1) { 1652d29b2c44Sab cpl_eltarg(obj_state, cpldata, argc, argv, num_opt); 1653d29b2c44Sab return; 1654d29b2c44Sab } 1655d29b2c44Sab 1656d29b2c44Sab /* The second argument is always a tag value */ 1657d29b2c44Sab if ((argc - num_opt) == 2) 1658d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 1659d29b2c44Sab } 1660d29b2c44Sab 1661d29b2c44Sab /*ARGSUSED*/ 1662d29b2c44Sab static void 1663d29b2c44Sab cpl_posflag1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1664d29b2c44Sab const char *argv[], int num_opt) 1665d29b2c44Sab { 166655ef6355Sab /* 166755ef6355Sab * dyn:posflag1 accepts two mutually exclusive options that have 166855ef6355Sab * a corresponding value argument: -dynndx and -needed. If we 166955ef6355Sab * are being called to supply options for the value, handle that here. 167055ef6355Sab */ 167155ef6355Sab if ((num_opt > 1) && (argc == num_opt)) { 167255ef6355Sab elfedit_section_t *dynsec, *strsec; 167355ef6355Sab const char *opt = argv[num_opt - 2]; 167455ef6355Sab dyn_opt_t type; 167555ef6355Sab Dyn *dyn; 167655ef6355Sab Word i, num; 167755ef6355Sab 167855ef6355Sab /* 167955ef6355Sab * If there is no object available, or if the object has no 168055ef6355Sab * dynamic section, then there is nothing to report. 168155ef6355Sab */ 168255ef6355Sab if ((obj_state == NULL) || obj_state->os_dynndx == SHN_UNDEF) 168355ef6355Sab return; 168455ef6355Sab 168555ef6355Sab /* 168655ef6355Sab * Determine which option it is, bail if it isn't one of 168755ef6355Sab * the ones we are concerned with. 168855ef6355Sab */ 168955ef6355Sab if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_NEEDED)) == 0)) 169055ef6355Sab type = DYN_OPT_F_NEEDED; 169155ef6355Sab else if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0)) 169255ef6355Sab type = DYN_OPT_F_DYNNDX_VAL; 169355ef6355Sab else 169455ef6355Sab return; 169555ef6355Sab 169655ef6355Sab dynsec = elfedit_sec_getdyn(obj_state, &dyn, &num); 169755ef6355Sab switch (type) { 169855ef6355Sab case DYN_OPT_F_NEEDED: 169955ef6355Sab strsec = elfedit_sec_getstr(obj_state, 170055ef6355Sab dynsec->sec_shdr->sh_link, 0); 170155ef6355Sab for (; num-- > 0; dyn++) 170255ef6355Sab if (dyn->d_tag == DT_NEEDED) 170355ef6355Sab elfedit_cpl_match(cpldata, 170455ef6355Sab elfedit_offset_to_str(strsec, 170555ef6355Sab dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 170655ef6355Sab 0), 0); 170755ef6355Sab break; 170855ef6355Sab 170955ef6355Sab case DYN_OPT_F_DYNNDX_VAL: 171055ef6355Sab for (i = 0; i < num; i++, dyn++) 171155ef6355Sab if (dyn->d_tag == DT_POSFLAG_1) 171255ef6355Sab elfedit_cpl_ndx(cpldata, i); 171355ef6355Sab break; 171455ef6355Sab } 171555ef6355Sab return; 171655ef6355Sab } 171755ef6355Sab 1718d29b2c44Sab /* This routine allows multiple flags to be specified */ 1719d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_P1); 1720d29b2c44Sab } 1721d29b2c44Sab 1722d29b2c44Sab /*ARGSUSED*/ 1723d29b2c44Sab static void 1724d29b2c44Sab cpl_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1725d29b2c44Sab const char *argv[], int num_opt) 1726d29b2c44Sab { 1727d29b2c44Sab /* This routine allows multiple flags to be specified */ 1728d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF); 1729d29b2c44Sab } 1730d29b2c44Sab 1731d29b2c44Sab /*ARGSUSED*/ 1732d29b2c44Sab static void 1733d29b2c44Sab cpl_flags1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1734d29b2c44Sab const char *argv[], int num_opt) 1735d29b2c44Sab { 1736d29b2c44Sab /* This routine allows multiple flags to be specified */ 1737d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_1); 1738d29b2c44Sab } 1739d29b2c44Sab 1740d29b2c44Sab /*ARGSUSED*/ 1741d29b2c44Sab static void 1742d29b2c44Sab cpl_feature1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1743d29b2c44Sab const char *argv[], int num_opt) 1744d29b2c44Sab { 1745d29b2c44Sab /* This routine allows multiple flags to be specified */ 1746d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1); 1747d29b2c44Sab } 1748d29b2c44Sab 1749ba2be530Sab /*ARGSUSED*/ 1750ba2be530Sab static void 1751ba2be530Sab cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1752ba2be530Sab const char *argv[], int num_opt) 1753ba2be530Sab { 1754ba2be530Sab /* 1755ba2be530Sab * This command doesn't accept options, so num_opt should be 1756ba2be530Sab * 0. This is a defensive measure, in case that should change. 1757ba2be530Sab */ 1758ba2be530Sab argc -= num_opt; 1759ba2be530Sab argv += num_opt; 1760ba2be530Sab 1761ba2be530Sab if (argc == 1) 1762ba2be530Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM); 1763ba2be530Sab } 1764ba2be530Sab 1765d29b2c44Sab 1766d29b2c44Sab /* 1767d29b2c44Sab * Implementation functions for the commands 1768d29b2c44Sab */ 1769d29b2c44Sab static elfedit_cmdret_t 1770d29b2c44Sab cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1771d29b2c44Sab { 1772d29b2c44Sab return (cmd_body(DYN_CMD_T_DUMP, obj_state, argc, argv)); 1773d29b2c44Sab } 1774d29b2c44Sab 1775d29b2c44Sab static elfedit_cmdret_t 1776d29b2c44Sab cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1777d29b2c44Sab { 1778d29b2c44Sab return (cmd_body(DYN_CMD_T_TAG, obj_state, argc, argv)); 1779d29b2c44Sab } 1780d29b2c44Sab 1781d29b2c44Sab static elfedit_cmdret_t 1782d29b2c44Sab cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1783d29b2c44Sab { 1784d29b2c44Sab return (cmd_body(DYN_CMD_T_VALUE, obj_state, argc, argv)); 1785d29b2c44Sab } 1786d29b2c44Sab 1787d29b2c44Sab static elfedit_cmdret_t 1788d29b2c44Sab cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1789d29b2c44Sab { 1790d29b2c44Sab return (cmd_body(DYN_CMD_T_DELETE, obj_state, argc, argv)); 1791d29b2c44Sab } 1792d29b2c44Sab 1793d29b2c44Sab static elfedit_cmdret_t 1794d29b2c44Sab cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1795d29b2c44Sab { 1796d29b2c44Sab return (cmd_body(DYN_CMD_T_MOVE, obj_state, argc, argv)); 1797d29b2c44Sab } 1798d29b2c44Sab 1799d29b2c44Sab static elfedit_cmdret_t 1800d29b2c44Sab cmd_runpath(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1801d29b2c44Sab { 1802d29b2c44Sab return (cmd_body(DYN_CMD_T_RUNPATH, obj_state, argc, argv)); 1803d29b2c44Sab } 1804d29b2c44Sab 1805d29b2c44Sab static elfedit_cmdret_t 1806d29b2c44Sab cmd_posflag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1807d29b2c44Sab { 1808d29b2c44Sab return (cmd_body(DYN_CMD_T_POSFLAG1, obj_state, argc, argv)); 1809d29b2c44Sab } 1810d29b2c44Sab 1811d29b2c44Sab static elfedit_cmdret_t 1812d29b2c44Sab cmd_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1813d29b2c44Sab { 1814d29b2c44Sab return (cmd_body(DYN_CMD_T_FLAGS, obj_state, argc, argv)); 1815d29b2c44Sab } 1816d29b2c44Sab 1817d29b2c44Sab static elfedit_cmdret_t 1818d29b2c44Sab cmd_flags1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1819d29b2c44Sab { 1820d29b2c44Sab return (cmd_body(DYN_CMD_T_FLAGS1, obj_state, argc, argv)); 1821d29b2c44Sab } 1822d29b2c44Sab 1823d29b2c44Sab static elfedit_cmdret_t 1824d29b2c44Sab cmd_feature1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1825d29b2c44Sab { 1826d29b2c44Sab return (cmd_body(DYN_CMD_T_FEATURE1, obj_state, argc, argv)); 1827d29b2c44Sab } 1828d29b2c44Sab 1829d29b2c44Sab static elfedit_cmdret_t 1830d29b2c44Sab cmd_checksum(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1831d29b2c44Sab { 1832d29b2c44Sab return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv)); 1833d29b2c44Sab } 1834d29b2c44Sab 1835ba2be530Sab static elfedit_cmdret_t 1836ba2be530Sab cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1837ba2be530Sab { 1838ba2be530Sab return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv)); 1839ba2be530Sab } 1840ba2be530Sab 1841d29b2c44Sab 1842d29b2c44Sab 1843d29b2c44Sab /*ARGSUSED*/ 1844d29b2c44Sab elfedit_module_t * 1845d29b2c44Sab elfedit_init(elfedit_module_version_t version) 1846d29b2c44Sab { 1847d29b2c44Sab /* For commands that only accept -o */ 1848d29b2c44Sab static elfedit_cmd_optarg_t opt_ostyle[] = { 1849d29b2c44Sab { ELFEDIT_STDOA_OPT_O, NULL, 1850d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1851d29b2c44Sab { NULL } 1852d29b2c44Sab }; 1853d29b2c44Sab 1854d29b2c44Sab /* For commands that only accept -and, -cmp, -o, -or */ 1855d29b2c44Sab static elfedit_cmd_optarg_t opt_ostyle_bitop[] = { 1856d29b2c44Sab { ELFEDIT_STDOA_OPT_AND, NULL, 1857d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 1858d29b2c44Sab { ELFEDIT_STDOA_OPT_CMP, NULL, 1859d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 1860d29b2c44Sab { ELFEDIT_STDOA_OPT_O, NULL, 1861d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1862d29b2c44Sab { ELFEDIT_STDOA_OPT_OR, NULL, 1863d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 1864d29b2c44Sab { NULL } 1865d29b2c44Sab }; 1866d29b2c44Sab 1867d29b2c44Sab /* For commands that only accept -dynndx */ 1868d29b2c44Sab static elfedit_cmd_optarg_t opt_minus_dynndx[] = { 1869d29b2c44Sab { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 187055ef6355Sab /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 187155ef6355Sab ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 187255ef6355Sab DYN_OPT_F_DYNNDX_ELT, 0 }, 1873d29b2c44Sab { NULL } 1874d29b2c44Sab }; 1875d29b2c44Sab 1876d29b2c44Sab /* dyn:dump */ 1877d29b2c44Sab static const char *name_dump[] = { 1878d29b2c44Sab MSG_ORIG(MSG_CMD_DUMP), 1879d29b2c44Sab MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 1880d29b2c44Sab NULL 1881d29b2c44Sab }; 1882d29b2c44Sab static elfedit_cmd_optarg_t arg_dump[] = { 1883d29b2c44Sab { MSG_ORIG(MSG_STR_ELT), 1884d29b2c44Sab /* MSG_INTL(MSG_ARGDESC_ELT) */ 1885d29b2c44Sab ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 1886d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1887d29b2c44Sab { NULL } 1888d29b2c44Sab }; 1889d29b2c44Sab 1890d29b2c44Sab 1891d29b2c44Sab /* dyn:tag */ 1892d29b2c44Sab static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL }; 1893d29b2c44Sab static elfedit_cmd_optarg_t opt_tag[] = { 1894d29b2c44Sab { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 189555ef6355Sab /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 189655ef6355Sab ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 189755ef6355Sab DYN_OPT_F_DYNNDX_ELT, 0 }, 1898d29b2c44Sab { ELFEDIT_STDOA_OPT_O, NULL, 1899d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1900d29b2c44Sab { NULL } 1901d29b2c44Sab }; 1902d29b2c44Sab static elfedit_cmd_optarg_t arg_tag[] = { 1903d29b2c44Sab { MSG_ORIG(MSG_STR_ELT), 1904d29b2c44Sab /* MSG_INTL(MSG_A1_TAG_ELT) */ 1905d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_TAG_ELT), 1906d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1907d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 1908d29b2c44Sab /* MSG_INTL(MSG_A2_TAG_VALUE) */ 1909d29b2c44Sab ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE), 1910d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1911d29b2c44Sab { NULL } 1912d29b2c44Sab }; 1913d29b2c44Sab 1914d29b2c44Sab 1915d29b2c44Sab /* dyn:value */ 1916d29b2c44Sab static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL }; 1917d29b2c44Sab static elfedit_cmd_optarg_t opt_value[] = { 1918d29b2c44Sab { MSG_ORIG(MSG_STR_MINUS_ADD), 1919d29b2c44Sab /* MSG_INTL(MSG_OPTDESC_ADD) */ 1920d29b2c44Sab ELFEDIT_I18NHDL(MSG_OPTDESC_ADD), 0, 192155ef6355Sab DYN_OPT_F_ADD, DYN_OPT_F_DYNNDX_ELT }, 1922d29b2c44Sab { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 192355ef6355Sab /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 192455ef6355Sab ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 192555ef6355Sab DYN_OPT_F_DYNNDX_ELT, DYN_OPT_F_ADD }, 1926d29b2c44Sab { ELFEDIT_STDOA_OPT_O, NULL, 1927d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1928d29b2c44Sab { MSG_ORIG(MSG_STR_MINUS_S), 1929d29b2c44Sab /* MSG_INTL(MSG_OPTDESC_S) */ 1930d29b2c44Sab ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0, 1931d29b2c44Sab DYN_OPT_F_STRVAL, 0 }, 1932d29b2c44Sab { NULL } 1933d29b2c44Sab }; 1934d29b2c44Sab static elfedit_cmd_optarg_t arg_value[] = { 1935d29b2c44Sab { MSG_ORIG(MSG_STR_ELT), 1936d29b2c44Sab /* MSG_INTL(MSG_ARGDESC_ELT) */ 1937d29b2c44Sab ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 1938d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1939d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 1940d29b2c44Sab /* MSG_INTL(MSG_A2_VALUE_VALUE) */ 1941d29b2c44Sab ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE), 1942d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1943d29b2c44Sab { NULL } 1944d29b2c44Sab }; 1945d29b2c44Sab 1946d29b2c44Sab /* dyn:delete */ 1947d29b2c44Sab static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL }; 1948d29b2c44Sab static elfedit_cmd_optarg_t arg_delete[] = { 1949d29b2c44Sab { MSG_ORIG(MSG_STR_ELT), 1950d29b2c44Sab /* MSG_INTL(MSG_ARGDESC_ELT) */ 1951d29b2c44Sab ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 1952d29b2c44Sab 0 }, 1953d29b2c44Sab { MSG_ORIG(MSG_STR_COUNT), 1954d29b2c44Sab /* MSG_INTL(MSG_A2_DELETE_COUNT) */ 1955d29b2c44Sab ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT), 1956d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1957d29b2c44Sab { NULL } 1958d29b2c44Sab }; 1959d29b2c44Sab 1960d29b2c44Sab /* dyn:move */ 1961d29b2c44Sab static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL }; 1962d29b2c44Sab static elfedit_cmd_optarg_t arg_move[] = { 1963d29b2c44Sab { MSG_ORIG(MSG_STR_ELT), 1964d29b2c44Sab /* MSG_INTL(MSG_ARGDESC_ELT) */ 1965d29b2c44Sab ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 1966d29b2c44Sab 0 }, 1967d29b2c44Sab { MSG_ORIG(MSG_STR_DST_INDEX), 1968d29b2c44Sab /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */ 1969d29b2c44Sab ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX), 1970d29b2c44Sab 0 }, 1971d29b2c44Sab { MSG_ORIG(MSG_STR_COUNT), 1972d29b2c44Sab /* MSG_INTL(MSG_A3_MOVE_COUNT) */ 1973d29b2c44Sab ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT), 1974d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1975d29b2c44Sab { NULL } 1976d29b2c44Sab }; 1977d29b2c44Sab 1978d29b2c44Sab /* dyn:runpath / dyn:rpath */ 1979d29b2c44Sab static const char *name_runpath[] = { MSG_ORIG(MSG_CMD_RUNPATH), 1980d29b2c44Sab MSG_ORIG(MSG_CMD_RUNPATH_A1), NULL }; 1981d29b2c44Sab static elfedit_cmd_optarg_t arg_runpath[] = { 1982d29b2c44Sab { MSG_ORIG(MSG_STR_NEWPATH), 1983d29b2c44Sab /* MSG_INTL(MSG_A1_RUNPATH_NEWPATH) */ 1984d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_RUNPATH_NEWPATH), 1985d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1986d29b2c44Sab { NULL } 1987d29b2c44Sab }; 1988d29b2c44Sab 1989d29b2c44Sab /* dyn:posflag1 */ 1990d29b2c44Sab static const char *name_posflag1[] = { MSG_ORIG(MSG_CMD_POSFLAG1), 1991d29b2c44Sab NULL }; 199255ef6355Sab static elfedit_cmd_optarg_t opt_posflag1[] = { 199355ef6355Sab { ELFEDIT_STDOA_OPT_AND, NULL, 199455ef6355Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 199555ef6355Sab { ELFEDIT_STDOA_OPT_CMP, NULL, 199655ef6355Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 199755ef6355Sab { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 199855ef6355Sab /* MSG_INTL(MSG_OPTDESC_DYNNDX_VAL) */ 199955ef6355Sab ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_VAL), 200055ef6355Sab ELFEDIT_CMDOA_F_VALUE, 200155ef6355Sab DYN_OPT_F_DYNNDX_VAL, DYN_OPT_F_NEEDED }, 200255ef6355Sab { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 200355ef6355Sab { MSG_ORIG(MSG_STR_MINUS_NEEDED), 200455ef6355Sab /* MSG_INTL(MSG_OPTDESC_NEEDED) */ 200555ef6355Sab ELFEDIT_I18NHDL(MSG_OPTDESC_NEEDED), 200655ef6355Sab ELFEDIT_CMDOA_F_VALUE, 200755ef6355Sab DYN_OPT_F_NEEDED, DYN_OPT_F_DYNNDX_VAL }, 200855ef6355Sab { MSG_ORIG(MSG_STR_PREFIX), NULL, 0, 0 }, 200955ef6355Sab { ELFEDIT_STDOA_OPT_O, NULL, 201055ef6355Sab ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 201155ef6355Sab { ELFEDIT_STDOA_OPT_OR, NULL, 201255ef6355Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 201355ef6355Sab { NULL } 201455ef6355Sab }; 2015d29b2c44Sab static elfedit_cmd_optarg_t arg_posflag1[] = { 2016d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 2017d29b2c44Sab /* MSG_INTL(MSG_A1_POSFLAG1_VALUE) */ 2018d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_POSFLAG1_VALUE), 2019d29b2c44Sab ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 2020d29b2c44Sab { NULL } 2021d29b2c44Sab }; 2022d29b2c44Sab 2023d29b2c44Sab /* dyn:flags */ 2024d29b2c44Sab static const char *name_flags[] = { MSG_ORIG(MSG_CMD_FLAGS), NULL }; 2025d29b2c44Sab static elfedit_cmd_optarg_t arg_flags[] = { 2026d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 2027d29b2c44Sab /* MSG_INTL(MSG_A1_FLAGS_VALUE) */ 2028d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_FLAGS_VALUE), 2029d29b2c44Sab ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 2030d29b2c44Sab { NULL } 2031d29b2c44Sab }; 2032d29b2c44Sab 2033d29b2c44Sab /* dyn:flags1 */ 2034d29b2c44Sab static const char *name_flags1[] = { MSG_ORIG(MSG_CMD_FLAGS1), NULL }; 2035d29b2c44Sab static elfedit_cmd_optarg_t arg_flags1[] = { 2036d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 2037d29b2c44Sab /* MSG_INTL(MSG_A1_FLAGS1_VALUE) */ 2038d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_FLAGS1_VALUE), 2039d29b2c44Sab ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 2040d29b2c44Sab { NULL } 2041d29b2c44Sab }; 2042d29b2c44Sab 2043d29b2c44Sab /* dyn:feature1 */ 2044d29b2c44Sab static const char *name_feature1[] = { MSG_ORIG(MSG_CMD_FEATURE1), 2045d29b2c44Sab NULL }; 2046d29b2c44Sab static elfedit_cmd_optarg_t arg_feature1[] = { 2047d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 2048d29b2c44Sab /* MSG_INTL(MSG_A1_FEATURE1_VALUE) */ 2049d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_FEATURE1_VALUE), 2050d29b2c44Sab ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 2051d29b2c44Sab { NULL } 2052d29b2c44Sab }; 2053d29b2c44Sab 2054d29b2c44Sab /* dyn:checksum */ 2055d29b2c44Sab static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM), 2056d29b2c44Sab NULL }; 2057d29b2c44Sab 2058ba2be530Sab /* dyn:sunw_ldmach */ 2059ba2be530Sab static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH), 2060ba2be530Sab NULL }; 2061ba2be530Sab static elfedit_cmd_optarg_t arg_sunw_ldmach[] = { 2062ba2be530Sab { MSG_ORIG(MSG_STR_VALUE), 2063ba2be530Sab /* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */ 2064ba2be530Sab ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE), 2065ba2be530Sab ELFEDIT_CMDOA_F_OPT }, 2066ba2be530Sab { NULL } 2067ba2be530Sab }; 2068ba2be530Sab 2069d29b2c44Sab 2070d29b2c44Sab 2071d29b2c44Sab static elfedit_cmd_t cmds[] = { 2072d29b2c44Sab /* dyn:dump */ 2073d29b2c44Sab { cmd_dump, cpl_eltarg, name_dump, 2074d29b2c44Sab /* MSG_INTL(MSG_DESC_DUMP) */ 2075d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_DUMP), 2076d29b2c44Sab /* MSG_INTL(MSG_HELP_DUMP) */ 2077d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_DUMP), 2078d29b2c44Sab opt_minus_dynndx, arg_dump }, 2079d29b2c44Sab 2080d29b2c44Sab /* dyn:tag */ 2081d29b2c44Sab { cmd_tag, cpl_tag, name_tag, 2082d29b2c44Sab /* MSG_INTL(MSG_DESC_TAG) */ 2083d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_TAG), 2084d29b2c44Sab /* MSG_INTL(MSG_HELP_TAG) */ 2085d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_TAG), 2086d29b2c44Sab opt_tag, arg_tag }, 2087d29b2c44Sab 2088d29b2c44Sab /* dyn:value */ 2089d29b2c44Sab { cmd_value, cpl_eltarg, name_value, 2090d29b2c44Sab /* MSG_INTL(MSG_DESC_VALUE) */ 2091d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_VALUE), 2092d29b2c44Sab /* MSG_INTL(MSG_HELP_VALUE) */ 2093d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_VALUE), 2094d29b2c44Sab opt_value, arg_value }, 2095d29b2c44Sab 2096d29b2c44Sab /* dyn:delete */ 2097d29b2c44Sab { cmd_delete, cpl_eltarg, name_delete, 2098d29b2c44Sab /* MSG_INTL(MSG_DESC_DELETE) */ 2099d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_DELETE), 2100d29b2c44Sab /* MSG_INTL(MSG_HELP_DELETE) */ 2101d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_DELETE), 2102d29b2c44Sab opt_minus_dynndx, arg_delete }, 2103d29b2c44Sab 2104d29b2c44Sab /* dyn:move */ 2105d29b2c44Sab { cmd_move, cpl_eltarg, name_move, 2106d29b2c44Sab /* MSG_INTL(MSG_DESC_MOVE) */ 2107d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_MOVE), 2108d29b2c44Sab /* MSG_INTL(MSG_HELP_MOVE) */ 2109d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_MOVE), 2110d29b2c44Sab opt_minus_dynndx, arg_move }, 2111d29b2c44Sab 2112d29b2c44Sab /* dyn:runpath */ 2113d29b2c44Sab { cmd_runpath, NULL, name_runpath, 2114d29b2c44Sab /* MSG_INTL(MSG_DESC_RUNPATH) */ 2115d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_RUNPATH), 2116d29b2c44Sab /* MSG_INTL(MSG_HELP_RUNPATH) */ 2117d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_RUNPATH), 2118d29b2c44Sab opt_ostyle, arg_runpath }, 2119d29b2c44Sab 2120d29b2c44Sab /* dyn:posflag1 */ 2121d29b2c44Sab { cmd_posflag1, cpl_posflag1, name_posflag1, 2122d29b2c44Sab /* MSG_INTL(MSG_DESC_POSFLAG1) */ 2123d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_POSFLAG1), 2124d29b2c44Sab /* MSG_INTL(MSG_HELP_POSFLAG1) */ 2125d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_POSFLAG1), 212655ef6355Sab opt_posflag1, arg_posflag1 }, 2127d29b2c44Sab 2128d29b2c44Sab /* dyn:flags */ 2129d29b2c44Sab { cmd_flags, cpl_flags, name_flags, 2130d29b2c44Sab /* MSG_INTL(MSG_DESC_FLAGS) */ 2131d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_FLAGS), 2132d29b2c44Sab /* MSG_INTL(MSG_HELP_FLAGS) */ 2133d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_FLAGS), 2134d29b2c44Sab opt_ostyle_bitop, arg_flags }, 2135d29b2c44Sab 2136d29b2c44Sab /* dyn:flags1 */ 2137d29b2c44Sab { cmd_flags1, cpl_flags1, name_flags1, 2138d29b2c44Sab /* MSG_INTL(MSG_DESC_FLAGS1) */ 2139d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_FLAGS1), 2140d29b2c44Sab /* MSG_INTL(MSG_HELP_FLAGS1) */ 2141d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_FLAGS1), 2142d29b2c44Sab opt_ostyle_bitop, arg_flags1 }, 2143d29b2c44Sab 2144d29b2c44Sab /* dyn:feature1 */ 2145d29b2c44Sab { cmd_feature1, cpl_feature1, name_feature1, 2146d29b2c44Sab /* MSG_INTL(MSG_DESC_FEATURE1) */ 2147d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_FEATURE1), 2148d29b2c44Sab /* MSG_INTL(MSG_HELP_FEATURE1) */ 2149d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_FEATURE1), 2150d29b2c44Sab opt_ostyle_bitop, arg_feature1 }, 2151d29b2c44Sab 2152d29b2c44Sab /* dyn:checksum */ 2153d29b2c44Sab { cmd_checksum, NULL, name_checksum, 2154d29b2c44Sab /* MSG_INTL(MSG_DESC_CHECKSUM) */ 2155d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_CHECKSUM), 2156d29b2c44Sab /* MSG_INTL(MSG_HELP_CHECKSUM) */ 2157d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM), 2158d29b2c44Sab NULL, NULL }, 2159d29b2c44Sab 2160ba2be530Sab /* dyn:sunw_ldmach */ 2161ba2be530Sab { cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach, 2162ba2be530Sab /* MSG_INTL(MSG_DESC_SUNW_LDMACH) */ 2163ba2be530Sab ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH), 2164ba2be530Sab /* MSG_INTL(MSG_HELP_SUNW_LDMACH) */ 2165ba2be530Sab ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH), 2166ba2be530Sab opt_ostyle, arg_sunw_ldmach }, 2167ba2be530Sab 2168d29b2c44Sab { NULL } 2169d29b2c44Sab }; 2170d29b2c44Sab 2171d29b2c44Sab static elfedit_module_t module = { 2172d29b2c44Sab ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 2173d29b2c44Sab /* MSG_INTL(MSG_MOD_DESC) */ 2174d29b2c44Sab ELFEDIT_I18NHDL(MSG_MOD_DESC), cmds, mod_i18nhdl_to_str }; 2175d29b2c44Sab 2176d29b2c44Sab return (&module); 2177d29b2c44Sab } 2178