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 /* 23ba2be530Sab * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24d29b2c44Sab * Use is subject to license terms. 25d29b2c44Sab */ 26d29b2c44Sab #pragma ident "%Z%%M% %I% %E% SMI" 27d29b2c44Sab 28d29b2c44Sab #include <ctype.h> 29d29b2c44Sab #include <elfedit.h> 30d29b2c44Sab #include <sys/elf_SPARC.h> 31d29b2c44Sab #include <strings.h> 32d29b2c44Sab #include <debug.h> 33d29b2c44Sab #include <conv.h> 34d29b2c44Sab #include <dyn_msg.h> 35d29b2c44Sab 36d29b2c44Sab 37d29b2c44Sab /* 38d29b2c44Sab * Dynamic section 39d29b2c44Sab */ 40d29b2c44Sab 41d29b2c44Sab 42d29b2c44Sab 43d29b2c44Sab 44d29b2c44Sab /* 45d29b2c44Sab * This module uses shared code for several of the commands. 46d29b2c44Sab * It is sometimes necessary to know which specific command 47d29b2c44Sab * is active. 48d29b2c44Sab */ 49d29b2c44Sab typedef enum { 50d29b2c44Sab /* Dump command, used as module default to display dynamic section */ 51d29b2c44Sab DYN_CMD_T_DUMP = 0, /* dyn:dump */ 52d29b2c44Sab 53d29b2c44Sab /* Commands that do not correspond directly to a specific DT tag */ 54d29b2c44Sab DYN_CMD_T_TAG = 1, /* dyn:tag */ 55d29b2c44Sab DYN_CMD_T_VALUE = 2, /* dyn:value */ 56d29b2c44Sab DYN_CMD_T_DELETE = 3, /* dyn:delete */ 57d29b2c44Sab DYN_CMD_T_MOVE = 4, /* dyn:shift */ 58d29b2c44Sab 59d29b2c44Sab /* Commands that embody tag specific knowledge */ 60d29b2c44Sab DYN_CMD_T_RUNPATH = 5, /* dyn:runpath/rpath */ 61d29b2c44Sab DYN_CMD_T_POSFLAG1 = 6, /* dyn:posflag1 */ 62d29b2c44Sab DYN_CMD_T_FLAGS = 7, /* dyn:flags */ 63d29b2c44Sab DYN_CMD_T_FLAGS1 = 8, /* dyn:flags1 */ 64d29b2c44Sab DYN_CMD_T_FEATURE1 = 9, /* dyn:feature1 */ 65ba2be530Sab DYN_CMD_T_CHECKSUM = 10, /* dyn:checksum */ 66ba2be530Sab DYN_CMD_T_SUNW_LDMACH = 11 /* dyn:sunw_ldmach */ 67d29b2c44Sab } DYN_CMD_T; 68d29b2c44Sab 69d29b2c44Sab 70d29b2c44Sab 71d29b2c44Sab #ifndef _ELF64 72d29b2c44Sab /* 73d29b2c44Sab * We supply this function for the msg module 74d29b2c44Sab */ 75d29b2c44Sab const char * 76d29b2c44Sab _dyn_msg(Msg mid) 77d29b2c44Sab { 78d29b2c44Sab return (gettext(MSG_ORIG(mid))); 79d29b2c44Sab } 80d29b2c44Sab #endif 81d29b2c44Sab 82d29b2c44Sab 83d29b2c44Sab /* 84d29b2c44Sab * This function is supplied to elfedit through our elfedit_module_t 85d29b2c44Sab * definition. It translates the opaque elfedit_i18nhdl_t handles 86d29b2c44Sab * in our module interface into the actual strings for elfedit to 87d29b2c44Sab * use. 88d29b2c44Sab * 89d29b2c44Sab * note: 90d29b2c44Sab * This module uses Msg codes for its i18n handle type. 91d29b2c44Sab * So the translation is simply to use MSG_INTL() to turn 92d29b2c44Sab * it into a string and return it. 93d29b2c44Sab */ 94d29b2c44Sab static const char * 95d29b2c44Sab mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 96d29b2c44Sab { 97d29b2c44Sab Msg msg = (Msg)hdl; 98d29b2c44Sab 99d29b2c44Sab return (MSG_INTL(msg)); 100d29b2c44Sab } 101d29b2c44Sab 102d29b2c44Sab 103d29b2c44Sab 104d29b2c44Sab /* 105d29b2c44Sab * The dyn_opt_t enum specifies a bit value for every optional 106d29b2c44Sab * argument allowed by a command in this module. 107d29b2c44Sab */ 108d29b2c44Sab typedef enum { 109d29b2c44Sab DYN_OPT_F_ADD = 1, /* -add: Add new elt rather than */ 110d29b2c44Sab /* modifying an existing one */ 111d29b2c44Sab DYN_OPT_F_AND = 2, /* -and: AND (&) values to dest */ 112d29b2c44Sab DYN_OPT_F_CMP = 4, /* -cmp: Complement (~) values */ 11355ef6355Sab DYN_OPT_F_DYNNDX_ELT = 8, /* -dynndx: 1st plain arg is tag */ 11455ef6355Sab /* index, not name */ 11555ef6355Sab DYN_OPT_F_DYNNDX_VAL = 16, /* -dynndx ndx: Index is value to */ 11655ef6355Sab /* option rather than 1st plain */ 11755ef6355Sab /* arg. Used for dyn:posflag1 */ 11855ef6355Sab DYN_OPT_F_NEEDED = 32, /* -needed str: Locate DT_POSFLAG_1 */ 11955ef6355Sab /* relative to DT_NEEDED element */ 12055ef6355Sab DYN_OPT_F_OR = 64, /* -or: OR (|) values to dest */ 12155ef6355Sab DYN_OPT_F_STRVAL = 128 /* -s: value is string, not integer */ 122d29b2c44Sab } dyn_opt_t; 123d29b2c44Sab 124d29b2c44Sab 125d29b2c44Sab /* 126d29b2c44Sab * A variable of type ARGSTATE is used by each command to maintain 127d29b2c44Sab * information about the arguments and related things. It is 128d29b2c44Sab * initialized by process_args(), and used by the other routines. 129d29b2c44Sab */ 130d29b2c44Sab typedef struct { 131d29b2c44Sab elfedit_obj_state_t *obj_state; 132d29b2c44Sab elfedit_section_t *strsec; /* Dynamic string table ref */ 133d29b2c44Sab struct { 134d29b2c44Sab elfedit_section_t *sec; /* Dynamic section reference */ 135d29b2c44Sab Dyn *data; /* Start dynamic section data */ 136d29b2c44Sab Word num; /* # dynamic elts */ 137d29b2c44Sab Word null_ndx; /* Index of first DT_NULL */ 138d29b2c44Sab Word num_null_ndx; /* # of DT_NULL elements */ 139d29b2c44Sab } dyn; 140d29b2c44Sab dyn_opt_t optmask; /* Mask of options used */ 141d29b2c44Sab int argc; /* # of plain arguments */ 142d29b2c44Sab const char **argv; /* Plain arguments */ 14355ef6355Sab const char *dyn_elt_str; /* Value string for */ 14455ef6355Sab /* DYN_OPT_F_DYNNDX_VAL */ 14555ef6355Sab /* or DYN_OPT_F_NEEDED */ 146d29b2c44Sab } ARGSTATE; 147d29b2c44Sab 148d29b2c44Sab 149d29b2c44Sab 150d29b2c44Sab /* 151d29b2c44Sab * Set argstate null_ndx field for current dynamic area 152d29b2c44Sab */ 153d29b2c44Sab static void 154d29b2c44Sab set_null_ndx(ARGSTATE *argstate) 155d29b2c44Sab { 156d29b2c44Sab Word num, null_ndx; 157d29b2c44Sab 158d29b2c44Sab num = argstate->dyn.num; 159d29b2c44Sab argstate->dyn.num_null_ndx = 0; 160d29b2c44Sab for (null_ndx = 0; null_ndx < num; null_ndx++) 161d29b2c44Sab if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) { 162d29b2c44Sab argstate->dyn.num_null_ndx++; 163d29b2c44Sab break; 164d29b2c44Sab } 165d29b2c44Sab argstate->dyn.null_ndx = null_ndx; 166d29b2c44Sab 167d29b2c44Sab /* Count the number of remaining DT_NULL items */ 168d29b2c44Sab for (; null_ndx < num; null_ndx++) 169d29b2c44Sab if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) 170d29b2c44Sab argstate->dyn.num_null_ndx++; 171d29b2c44Sab } 172d29b2c44Sab 173d29b2c44Sab 174d29b2c44Sab /* 175d29b2c44Sab * Convert the first available DT_NULL slot in the dynamic section 176d29b2c44Sab * into something else. 177d29b2c44Sab * 178d29b2c44Sab * entry: 179d29b2c44Sab * argstate - Argument state block 180d29b2c44Sab * d_tag, d_val - Values to be set in new element 181d29b2c44Sab * 182d29b2c44Sab * exit: 183d29b2c44Sab * If an extra DT_NULL slot is available, a debug message is 184d29b2c44Sab * issued, the slot is converted to its new use, and the argstate 185d29b2c44Sab * block state related to DT_NULL slots is updated. 186d29b2c44Sab * 187d29b2c44Sab * if no extra DT_NULL slot is present, an error is issued and 188d29b2c44Sab * this routine does not return to the caller. 189d29b2c44Sab */ 190d29b2c44Sab static Word 191d29b2c44Sab convert_dt_null(ARGSTATE *argstate, Word d_tag, Xword d_val) 192d29b2c44Sab { 193d29b2c44Sab Conv_inv_buf_t inv_buf; 194d29b2c44Sab Word ndx; 195d29b2c44Sab Dyn *dyn; 196d29b2c44Sab 197d29b2c44Sab /* If we lack an extra element, we can't continue */ 198d29b2c44Sab if (argstate->dyn.num_null_ndx <= 1) 199d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 200d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), 201d29b2c44Sab argstate->dyn.sec->sec_name); 202d29b2c44Sab 203d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL), 204d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), argstate->dyn.sec->sec_name, 205d29b2c44Sab EC_WORD(argstate->dyn.null_ndx), conv_dyn_tag(d_tag, 206d29b2c44Sab argstate->obj_state->os_ehdr->e_machine, 0, &inv_buf)); 207d29b2c44Sab 208d29b2c44Sab ndx = argstate->dyn.null_ndx; 209d29b2c44Sab dyn = &argstate->dyn.data[ndx]; 210d29b2c44Sab dyn->d_tag = d_tag; 211d29b2c44Sab dyn->d_un.d_val = d_val; 212d29b2c44Sab 213d29b2c44Sab /* Recompute the DT_NULL situation */ 214d29b2c44Sab set_null_ndx(argstate); 215d29b2c44Sab 216d29b2c44Sab return (ndx); 217d29b2c44Sab } 218d29b2c44Sab 219d29b2c44Sab 220d29b2c44Sab /* 221d29b2c44Sab * Standard argument processing for dyn module 222d29b2c44Sab * 223d29b2c44Sab * entry 224d29b2c44Sab * obj_state, argc, argv - Standard command arguments 225d29b2c44Sab * argstate - Address of ARGSTATE block to be initialized 226d29b2c44Sab * 227d29b2c44Sab * exit: 228d29b2c44Sab * On success, *argstate is initialized. On error, 229d29b2c44Sab * an error is issued and this routine does not return. 230d29b2c44Sab */ 231d29b2c44Sab static void 232d29b2c44Sab process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 233d29b2c44Sab ARGSTATE *argstate) 234d29b2c44Sab { 235d29b2c44Sab elfedit_getopt_state_t getopt_state; 236d29b2c44Sab elfedit_getopt_ret_t *getopt_ret; 237d29b2c44Sab 238d29b2c44Sab bzero(argstate, sizeof (*argstate)); 239d29b2c44Sab argstate->obj_state = obj_state; 240d29b2c44Sab 241d29b2c44Sab elfedit_getopt_init(&getopt_state, &argc, &argv); 242d29b2c44Sab 243d29b2c44Sab /* Add each new option to the options mask */ 24455ef6355Sab while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) { 245d29b2c44Sab argstate->optmask |= getopt_ret->gor_idmask; 24655ef6355Sab switch (getopt_ret->gor_idmask) { 24755ef6355Sab case DYN_OPT_F_DYNNDX_VAL: 24855ef6355Sab case DYN_OPT_F_NEEDED: 24955ef6355Sab argstate->dyn_elt_str = getopt_ret->gor_value; 25055ef6355Sab break; 25155ef6355Sab } 25255ef6355Sab } 253d29b2c44Sab 254d29b2c44Sab /* If there may be an arbitrary amount of output, use a pager */ 255d29b2c44Sab if (argc == 0) 256d29b2c44Sab elfedit_pager_init(); 257d29b2c44Sab 258d29b2c44Sab /* Return the updated values of argc/argv */ 259d29b2c44Sab argstate->argc = argc; 260d29b2c44Sab argstate->argv = argv; 261d29b2c44Sab 262d29b2c44Sab /* Locate the dynamic section, and the assocated string table */ 263d29b2c44Sab argstate->dyn.sec = elfedit_sec_getdyn(obj_state, &argstate->dyn.data, 264d29b2c44Sab &argstate->dyn.num); 265d29b2c44Sab argstate->strsec = elfedit_sec_getstr(obj_state, 26655ef6355Sab argstate->dyn.sec->sec_shdr->sh_link, 0); 267d29b2c44Sab 268d29b2c44Sab /* Index of first DT_NULL */ 269d29b2c44Sab set_null_ndx(argstate); 270d29b2c44Sab } 271d29b2c44Sab 272d29b2c44Sab 273d29b2c44Sab 274d29b2c44Sab /* 275d29b2c44Sab * Print ELF header values, taking the calling command, and output style 276d29b2c44Sab * into account. 277d29b2c44Sab * 278d29b2c44Sab * entry: 279d29b2c44Sab * cmd - DYN_CMD_T_* value giving identify of caller 280d29b2c44Sab * autoprint - If True, output is only produced if the elfedit 281d29b2c44Sab * autoprint flag is set. If False, output is always produced. 282d29b2c44Sab * argstate - Argument state block 283d29b2c44Sab * print_type - Specifies which dynamic elements to display. 284d29b2c44Sab * ndx = If print_type is PRINT_DYN_T_NDX, displays the index specified. 285d29b2c44Sab * Otherwise ignored. 286d29b2c44Sab */ 287d29b2c44Sab typedef enum { 288d29b2c44Sab PRINT_DYN_T_ALL = 0, /* Show all indexes */ 289d29b2c44Sab PRINT_DYN_T_NDX = 1, /* Show dynamic[arg] only */ 290d29b2c44Sab PRINT_DYN_T_TAG = 2, /* Show all elts with tag type */ 291d29b2c44Sab /* given by arg */ 292d29b2c44Sab PRINT_DYN_T_RUNPATH = 3 /* Show all runpath/rpath elts */ 293d29b2c44Sab 294d29b2c44Sab } PRINT_DYN_T; 295d29b2c44Sab 296d29b2c44Sab static void 297d29b2c44Sab print_dyn(DYN_CMD_T cmd, int autoprint, ARGSTATE *argstate, 298d29b2c44Sab PRINT_DYN_T print_type, Word arg) 299d29b2c44Sab { 300d29b2c44Sab elfedit_outstyle_t outstyle; 301d29b2c44Sab Conv_fmt_flags_t flags_fmt_flags; 302*c6c9aed4Sab Word end_ndx, ndx, printed = 0; 303d29b2c44Sab Dyn *dyn; 304d29b2c44Sab int header_done = 0; 305d29b2c44Sab Xword last_d_val; 30655ef6355Sab int one_shot; 307d29b2c44Sab 308d29b2c44Sab if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) 309d29b2c44Sab return; 310d29b2c44Sab 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 325*c6c9aed4Sab /* 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]; 343*c6c9aed4Sab 344*c6c9aed4Sab /* 345*c6c9aed4Sab * Loop predicate explanation: 346*c6c9aed4Sab * Normally, we want to iterate from the starting index 347*c6c9aed4Sab * to the end. However, in the case of PRINT_DYN_T_NDX, we 348*c6c9aed4Sab * only want to display one item (ndx == arg) and then quit, 349*c6c9aed4Sab * with the exception that if we've been through the loop 350*c6c9aed4Sab * and encountered a one_shot situation, we want to continue 351*c6c9aed4Sab * iterating until the one-shot situation is cleared. 352*c6c9aed4Sab */ 353*c6c9aed4Sab for (; (ndx < argstate->dyn.num) && 354*c6c9aed4Sab ((print_type != PRINT_DYN_T_NDX) || ((ndx == arg) || one_shot)); 355*c6c9aed4Sab 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 case DT_SUNW_AUXILIARY: 432d29b2c44Sab case DT_SUNW_FILTER: 433d29b2c44Sab name = elfedit_offset_to_str(argstate->strsec, 434d29b2c44Sab dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 435d29b2c44Sab break; 436d29b2c44Sab 437d29b2c44Sab case DT_FLAGS: 438d29b2c44Sab name = conv_dyn_flag(dyn->d_un.d_val, 439d29b2c44Sab flags_fmt_flags, &c_buf.flag); 440d29b2c44Sab break; 441d29b2c44Sab case DT_FLAGS_1: 442d29b2c44Sab name = conv_dyn_flag1(dyn->d_un.d_val, 443d29b2c44Sab flags_fmt_flags, &c_buf.flag1); 444d29b2c44Sab break; 445d29b2c44Sab case DT_POSFLAG_1: 44655ef6355Sab /* 44755ef6355Sab * If this is dyn:posflag1, and the print_type 44855ef6355Sab * is PRINT_DYN_T_TAG, and the -needed option is 44955ef6355Sab * used, then don't show any DT_POSFLAG_1 elements 45055ef6355Sab * that are not followed by a DT_NEEDED element 45155ef6355Sab * that matches the -needed string. 45255ef6355Sab */ 45355ef6355Sab if ((cmd == DYN_CMD_T_POSFLAG1) && 45455ef6355Sab (print_type == PRINT_DYN_T_TAG) && 45555ef6355Sab ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) && 45655ef6355Sab ((ndx + 1) < argstate->dyn.num)) { 45755ef6355Sab Dyn *dyn1 = &argstate->dyn.data[ndx + 1]; 45855ef6355Sab 45955ef6355Sab if (dyn1->d_tag != DT_NEEDED) 46055ef6355Sab continue; 46155ef6355Sab name = elfedit_offset_to_str(argstate->strsec, 46255ef6355Sab dyn1->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 46355ef6355Sab if (strncmp(name, argstate->dyn_elt_str, 46455ef6355Sab strlen(argstate->dyn_elt_str)) != 0) 46555ef6355Sab continue; 46655ef6355Sab } 46755ef6355Sab 468d29b2c44Sab name = conv_dyn_posflag1(dyn->d_un.d_val, 469d29b2c44Sab flags_fmt_flags, &c_buf.posflag1); 47055ef6355Sab /* 47155ef6355Sab * DT_POSFLAG_1 is a positional element that affects 47255ef6355Sab * the following item. If using the default output 47355ef6355Sab * style, then show the following item as well. 47455ef6355Sab */ 47555ef6355Sab one_shot = (outstyle == ELFEDIT_OUTSTYLE_DEFAULT); 476d29b2c44Sab break; 477d29b2c44Sab case DT_FEATURE_1: 478d29b2c44Sab name = conv_dyn_feature1(dyn->d_un.d_val, 479d29b2c44Sab flags_fmt_flags, &c_buf.feature1); 480d29b2c44Sab break; 481d29b2c44Sab case DT_DEPRECATED_SPARC_REGISTER: 482d29b2c44Sab name = MSG_INTL(MSG_STR_DEPRECATED); 483d29b2c44Sab break; 484ba2be530Sab case DT_SUNW_LDMACH: 485ba2be530Sab name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0, 486ba2be530Sab &c_buf.inv); 487ba2be530Sab break; 488d29b2c44Sab } 489d29b2c44Sab 490d29b2c44Sab if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 491d29b2c44Sab if (header_done == 0) { 492d29b2c44Sab header_done = 1; 493d29b2c44Sab Elf_dyn_title(0); 494d29b2c44Sab } 495d29b2c44Sab if (name == NULL) 496d29b2c44Sab name = MSG_ORIG(MSG_STR_EMPTY); 497d29b2c44Sab Elf_dyn_entry(0, dyn, ndx, name, 498d29b2c44Sab argstate->obj_state->os_ehdr->e_machine); 499d29b2c44Sab } else { 500d29b2c44Sab /* 501d29b2c44Sab * In simple or numeric mode under a print type 502d29b2c44Sab * that is based on tag type rather than on index, 503d29b2c44Sab * quietly: If we've already printed this value, 504d29b2c44Sab * don't print it again. A common example of this 505d29b2c44Sab * is PRINT_DYN_T_RUNPATH when both DT_RPATH and 506d29b2c44Sab * DT_RUNPATH are present with the same value. 507d29b2c44Sab */ 508d29b2c44Sab switch (print_type) { 509d29b2c44Sab case PRINT_DYN_T_TAG: 51055ef6355Sab /* 51155ef6355Sab * Positional flags don't count, because 51255ef6355Sab * each one affects a different item. So don't 51355ef6355Sab * skip those. 51455ef6355Sab */ 51555ef6355Sab if (dyn->d_tag != DT_POSFLAG_1) 51655ef6355Sab continue; 51755ef6355Sab break; 51855ef6355Sab 519d29b2c44Sab case PRINT_DYN_T_RUNPATH: 520d29b2c44Sab if (printed && (last_d_val == dyn->d_un.d_val)) 521d29b2c44Sab continue; 52255ef6355Sab break; 523d29b2c44Sab } 524d29b2c44Sab 525d29b2c44Sab if ((name != NULL) && 526d29b2c44Sab (outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) { 527d29b2c44Sab elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name); 528d29b2c44Sab } else { 529d29b2c44Sab elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), 530d29b2c44Sab dyn->d_un.d_val); 531d29b2c44Sab } 532d29b2c44Sab } 533d29b2c44Sab printed = 1; 534d29b2c44Sab last_d_val = dyn->d_un.d_val; 535d29b2c44Sab } 536d29b2c44Sab 537d29b2c44Sab /* 538d29b2c44Sab * If nothing was output under the print types that are 539d29b2c44Sab * based on tag type, issue an error saying it doesn't exist. 540d29b2c44Sab */ 541d29b2c44Sab if (!printed) { 542d29b2c44Sab if (print_type == PRINT_DYN_T_TAG) { 543d29b2c44Sab Conv_inv_buf_t inv_buf; 544d29b2c44Sab 545d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, 546d29b2c44Sab MSG_INTL(MSG_ERR_NODYNELT), 547d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), 548d29b2c44Sab argstate->dyn.sec->sec_name, conv_dyn_tag(arg, 549d29b2c44Sab argstate->obj_state->os_ehdr->e_machine, 550d29b2c44Sab 0, &inv_buf)); 551d29b2c44Sab } 552d29b2c44Sab 553d29b2c44Sab if (print_type == PRINT_DYN_T_RUNPATH) 554d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, 555d29b2c44Sab MSG_INTL(MSG_ERR_NORUNPATH), 556d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), 557d29b2c44Sab argstate->dyn.sec->sec_name); 558d29b2c44Sab } 559d29b2c44Sab } 560d29b2c44Sab 561d29b2c44Sab 562d29b2c44Sab /* 56355ef6355Sab * Determine the index(s) of the dynamic element(s) to be displayed and/or 56455ef6355Sab * manipulated. 565d29b2c44Sab * 566d29b2c44Sab * entry: 567d29b2c44Sab * argstate - Argument state block 56855ef6355Sab * arg - If the command being called accepts a first plain argument 56955ef6355Sab * named 'elt' which is used to specify the dynamic element, 57055ef6355Sab * arg is the value of argv[0] for that command. If the 57155ef6355Sab * command does not accept an 'elt' argument and instead 57255ef6355Sab * implicitly assumes a tag type, arg is the constant string 57355ef6355Sab * for that type (e.g. "DT_POSFLAG_1"). 574d29b2c44Sab * print_request - True if the command is to print the current 575d29b2c44Sab * value(s) and return without changing anything. 576d29b2c44Sab * print_type - Address of variable containing PRINT_DYN_T_ 577d29b2c44Sab * code specifying how the elements will be displayed. 578d29b2c44Sab * 579d29b2c44Sab * exit: 58055ef6355Sab * If print_request is False: This routine always returns the index 58155ef6355Sab * of a single dynamic element. *print_type is set to PRINT_DYN_T_NDX. 58255ef6355Sab * The 'elt' argument as well as any modifier options (-dynndx, -needed) 58355ef6355Sab * are examined to determine this index. If there are no modifier options, 58455ef6355Sab * the dynamic section contains no element of the desired type, and there 58555ef6355Sab * is an extra DT_NULL element in the section, then a new element of 58655ef6355Sab * the desired type is created and its index returned. Otherwise an 58755ef6355Sab * error is issued. 588d29b2c44Sab * 58955ef6355Sab * If print_request is True: If a modifier (-dynndx, -needed) was used, 59055ef6355Sab * *print_type is set to PRINT_DYN_T_NDX and the index of the 59155ef6355Sab * corresponding single dynamic element is returned. If no modifier 59255ef6355Sab * was used, *print_type is set to PRINT_DYN_T_TAG, and the tag 59355ef6355Sab * type code is returned. 594d29b2c44Sab */ 595d29b2c44Sab static Word 59655ef6355Sab arg_to_index(ARGSTATE *argstate, const char *arg, 597d29b2c44Sab int print_request, PRINT_DYN_T *print_type) 598d29b2c44Sab { 599d29b2c44Sab Word ndx, dt_value; 60055ef6355Sab Dyn *dyn; 601d29b2c44Sab 602d29b2c44Sab 603d29b2c44Sab /* Assume we are returning an index, alter as needed below */ 604d29b2c44Sab *print_type = PRINT_DYN_T_NDX; 605d29b2c44Sab 60655ef6355Sab /* 60755ef6355Sab * All the commands that accept the DYN_OPT_F_DYNNDX_ELT form 60855ef6355Sab * of -dynndx require a plain argument named 'elt' as their first 60955ef6355Sab * argument. -dynndx is a modifier that means that 'elt' is a 61055ef6355Sab * simple numeric section index. Routines that accept this form 61155ef6355Sab * of -dynndx are willing to handle any tag type, so all we need 61255ef6355Sab * to check is that the value is in range. 61355ef6355Sab */ 61455ef6355Sab if ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0) 61555ef6355Sab return ((Word) elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_ELT), 61655ef6355Sab 0, argstate->dyn.num - 1, NULL)); 617d29b2c44Sab 61855ef6355Sab /* arg is a DT_ tag type, not a numeric index */ 619d29b2c44Sab dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT); 620d29b2c44Sab 62155ef6355Sab /* 62255ef6355Sab * Commands that accept the DYN_OPT_F_DYNNDX_VAL form of 62355ef6355Sab * dynndx do not accept the 'elt' argument. The index is a 62455ef6355Sab * value that follows the option, and was saved in argstate by 62555ef6355Sab * process_args(). Routines that accept this form of -dynndx 62655ef6355Sab * require the specified element to have a specific tag type, 62755ef6355Sab * so we test for this as well as for the index being in range. 62855ef6355Sab */ 62955ef6355Sab if ((argstate->optmask & DYN_OPT_F_DYNNDX_VAL) != 0) { 63055ef6355Sab ndx = ((Word) elfedit_atoui_range(argstate->dyn_elt_str, 63155ef6355Sab MSG_ORIG(MSG_STR_INDEX), 0, argstate->dyn.num - 1, NULL)); 63255ef6355Sab if (argstate->dyn.data[ndx].d_tag != dt_value) { 63355ef6355Sab Half mach = argstate->obj_state->os_ehdr->e_machine; 63455ef6355Sab Conv_inv_buf_t is, want; 63555ef6355Sab 63655ef6355Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_WRONGTAG), 63755ef6355Sab EC_WORD(argstate->dyn.sec->sec_shndx), 63855ef6355Sab argstate->dyn.sec->sec_name, ndx, 63955ef6355Sab conv_dyn_tag(dt_value, mach, 0, &want), 64055ef6355Sab conv_dyn_tag(argstate->dyn.data[ndx].d_tag, mach, 64155ef6355Sab 0, &is)); 64255ef6355Sab } 64355ef6355Sab return (ndx); 64455ef6355Sab } 64555ef6355Sab 646d29b2c44Sab /* 647d29b2c44Sab * If this is a printing request, then we let print_dyn() show 648d29b2c44Sab * all the items with this tag type. 649d29b2c44Sab */ 650d29b2c44Sab if (print_request) { 651d29b2c44Sab *print_type = PRINT_DYN_T_TAG; 652d29b2c44Sab return (dt_value); 653d29b2c44Sab } 654d29b2c44Sab 65555ef6355Sab /* 65655ef6355Sab * Commands that accept -needed are looking for the dt_value element 65755ef6355Sab * (usually DT_POSFLAG_1) that immediately preceeds the DT_NEEDED 65855ef6355Sab * element with the string given by argstate->dyn_elt_str. 65955ef6355Sab */ 66055ef6355Sab if ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) { 66155ef6355Sab Word retndx = argstate->dyn.num; /* Out of range value */ 66255ef6355Sab const char *name; 66355ef6355Sab size_t len; 66455ef6355Sab 66555ef6355Sab len = strlen(argstate->dyn_elt_str); 66655ef6355Sab for (ndx = 0, dyn = argstate->dyn.data; 66755ef6355Sab ndx < argstate->dyn.num; dyn++, ndx++) { 66855ef6355Sab /* 66955ef6355Sab * If the immediately preceeding item has the 67055ef6355Sab * tag type we're looking for, and the current item 67155ef6355Sab * is a DT_NEEDED with a string that matches, 67255ef6355Sab * then the preceeding item is the one we want. 67355ef6355Sab */ 67455ef6355Sab if ((dyn->d_tag == DT_NEEDED) && 67555ef6355Sab (ndx > 0) && (retndx == (ndx - 1))) { 67655ef6355Sab name = elfedit_offset_to_str(argstate->strsec, 67755ef6355Sab dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0); 67855ef6355Sab 67955ef6355Sab if (strncmp(name, 68055ef6355Sab argstate->dyn_elt_str, len) == 0) 68155ef6355Sab return (retndx); 68255ef6355Sab continue; 68355ef6355Sab } 68455ef6355Sab 68555ef6355Sab /* 68655ef6355Sab * If the current item has the tag type we're 68755ef6355Sab * looking for, make it our current candidate. 68855ef6355Sab * If the next item is a DT_NEEDED with the right 68955ef6355Sab * string value, we'll use it then. 69055ef6355Sab */ 69155ef6355Sab if (dyn->d_tag == dt_value) 69255ef6355Sab retndx = ndx; 69355ef6355Sab } 69455ef6355Sab 69555ef6355Sab /* If we get here, no matching DT_NEEDED was found */ 69655ef6355Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEDNOMATCH), 69755ef6355Sab EC_WORD(argstate->dyn.sec->sec_shndx), 69855ef6355Sab argstate->dyn.sec->sec_name, argstate->dyn_elt_str); 69955ef6355Sab } 70055ef6355Sab 701d29b2c44Sab /* Locate the first entry with the given tag type */ 702d29b2c44Sab for (ndx = 0; ndx < argstate->dyn.num; ndx++) { 703d29b2c44Sab if (argstate->dyn.data[ndx].d_tag == dt_value) { 704d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 705d29b2c44Sab MSG_INTL(MSG_DEBUG_DT2NDX), 706d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), 707d29b2c44Sab argstate->dyn.sec->sec_name, EC_WORD(ndx), arg); 708d29b2c44Sab return (ndx); 709d29b2c44Sab } 710d29b2c44Sab } 711d29b2c44Sab 712d29b2c44Sab /* Not found. Can we create one? */ 713d29b2c44Sab if (argstate->dyn.num_null_ndx > 1) 714d29b2c44Sab return (convert_dt_null(argstate, dt_value, 0)); 715d29b2c44Sab 716d29b2c44Sab /* No room to create one, so we're out of options and must fail */ 717d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT), 718d29b2c44Sab EC_WORD(argstate->dyn.sec->sec_shndx), 719d29b2c44Sab argstate->dyn.sec->sec_name, arg); 720d29b2c44Sab 721d29b2c44Sab /*NOTREACHED*/ 722d29b2c44Sab return (0); /* For lint */ 723d29b2c44Sab } 724d29b2c44Sab 725d29b2c44Sab 726d29b2c44Sab /* 727d29b2c44Sab * Called by cmd_body() for dyn:value. Implements the core functionality 728d29b2c44Sab * for that command. 729d29b2c44Sab * 730d29b2c44Sab * This routine expects that both the index and value arguments are 731d29b2c44Sab * present. 732d29b2c44Sab */ 733d29b2c44Sab static elfedit_cmdret_t 734d29b2c44Sab cmd_body_value(ARGSTATE *argstate, Word *ret_ndx) 735d29b2c44Sab { 736d29b2c44Sab elfedit_section_t *dynsec = argstate->dyn.sec; 737d29b2c44Sab elfedit_section_t *strsec = argstate->strsec; 738d29b2c44Sab elfedit_dyn_elt_t strpad_elt; 739d29b2c44Sab Word i; 740d29b2c44Sab Dyn *dyn = argstate->dyn.data; 741d29b2c44Sab Word numdyn = argstate->dyn.num; 74255ef6355Sab int minus_add, minus_s, minus_dynndx; 743d29b2c44Sab Word arg1, tmp_val; 744d29b2c44Sab Xword arg2; 745d29b2c44Sab int arg2_known = 1; 746d29b2c44Sab 74755ef6355Sab minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0); 74855ef6355Sab minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0); 74955ef6355Sab minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0); 750d29b2c44Sab 751d29b2c44Sab elfedit_dyn_elt_init(&strpad_elt); 752d29b2c44Sab 753d29b2c44Sab /* 754d29b2c44Sab * The first argument is an index if -dynndx is used, and is a 755d29b2c44Sab * tag value otherwise. 756d29b2c44Sab */ 757d29b2c44Sab arg1 = minus_dynndx ? 758d29b2c44Sab elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT), 759d29b2c44Sab 0, numdyn - 1, NULL) : 760d29b2c44Sab elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT); 761d29b2c44Sab 762d29b2c44Sab if (minus_s) { 763d29b2c44Sab /* 764d29b2c44Sab * Don't allow the user to specify -s when manipulating a 765d29b2c44Sab * DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to 766d29b2c44Sab * manage the extra space used for strings, this would break 767d29b2c44Sab * our ability to add the string. 768d29b2c44Sab */ 769d29b2c44Sab if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) || 770d29b2c44Sab (minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD))) 771d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, 772d29b2c44Sab MSG_INTL(MSG_ERR_STRPADSTRVAL), 773d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 774d29b2c44Sab 775d29b2c44Sab /* Locate DT_SUNW_STRPAD element if present */ 776d29b2c44Sab strpad_elt.dn_dyn.d_un.d_val = 0; 777d29b2c44Sab (void) elfedit_dynstr_getpad(argstate->dyn.sec, &strpad_elt); 778d29b2c44Sab 779d29b2c44Sab /* 780d29b2c44Sab * Look up the string: If the user specified the -dynndx 781d29b2c44Sab * -option, then we will insert it if possible, and 782d29b2c44Sab * fail with an error if not. However, if they did not 783d29b2c44Sab * specify -dynndx, we want to look up the string if it is 784d29b2c44Sab * already there, but defer the insertion. The reason for 785d29b2c44Sab * this is that we may have to grab an unused DT_NULL element 786d29b2c44Sab * below, and if there are none available, we won't want 787d29b2c44Sab * to have modified the string table. 788d29b2c44Sab * 789d29b2c44Sab * This isn't a problem, because if the string isn't 790d29b2c44Sab * in the string table, it can't be used by a dynamic element. 791d29b2c44Sab * Hence, we don't need to insert it to know that there is 792d29b2c44Sab * no match. 793d29b2c44Sab */ 794d29b2c44Sab if (minus_dynndx == 0) { 795d29b2c44Sab if (elfedit_sec_findstr(strsec, 796d29b2c44Sab strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1], 797d29b2c44Sab &tmp_val) == 0) { 798d29b2c44Sab arg2_known = 0; 799d29b2c44Sab } else { 800d29b2c44Sab arg2 = tmp_val; 801d29b2c44Sab } 802d29b2c44Sab } else { 803d29b2c44Sab arg2 = elfedit_dynstr_insert(dynsec, strsec, 804d29b2c44Sab &strpad_elt, argstate->argv[1]); 805d29b2c44Sab } 806d29b2c44Sab } else { /* Argument 2 is an integer */ 807d29b2c44Sab arg2 = elfedit_atoui(argstate->argv[1], NULL); 808d29b2c44Sab } 809d29b2c44Sab 810d29b2c44Sab 811d29b2c44Sab if (!minus_dynndx && !(minus_add && !arg2_known)) { 812d29b2c44Sab /* 813d29b2c44Sab * Search the dynamic section and see if an item with the 814d29b2c44Sab * specified tag value already exists. We can reduce this 815d29b2c44Sab * to a simple update of an existing value if -add is not 816d29b2c44Sab * specified or the existing d_un value matches the new one. 817d29b2c44Sab * 818d29b2c44Sab * In either of these cases, we will change arg1 to be the 819d29b2c44Sab * index, and set minus_dynndx, causing the simple update to 820d29b2c44Sab * happen immediately below. 821d29b2c44Sab */ 822d29b2c44Sab for (i = 0; i < numdyn; i++) { 823d29b2c44Sab if ((dyn[i].d_tag == arg1) && 824d29b2c44Sab (!minus_add || (dyn[i].d_un.d_val == arg2))) { 825d29b2c44Sab arg1 = i; 826d29b2c44Sab minus_dynndx = 1; 827d29b2c44Sab break; 828d29b2c44Sab } 829d29b2c44Sab } 830d29b2c44Sab } 831d29b2c44Sab 832d29b2c44Sab /* 833d29b2c44Sab * If -dynndx is used, then this is a relatively simple 834d29b2c44Sab * operation, as we simply write over the specified index. 835d29b2c44Sab */ 836d29b2c44Sab if (minus_dynndx) { 837d29b2c44Sab /* 838d29b2c44Sab * If we held back from inserting a new string into 839d29b2c44Sab * the dynstr above, we insert it now, because we 840d29b2c44Sab * have a slot in the dynamic section, and we need 841d29b2c44Sab * the string offset ot finish. 842d29b2c44Sab */ 843d29b2c44Sab if (!arg2_known) 844d29b2c44Sab arg2 = elfedit_dynstr_insert(dynsec, strsec, 845d29b2c44Sab &strpad_elt, argstate->argv[1]); 846d29b2c44Sab 847d29b2c44Sab *ret_ndx = arg1; 848d29b2c44Sab if (dyn[arg1].d_un.d_val == arg2) { 849d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 850d29b2c44Sab MSG_INTL(MSG_DEBUG_X_OK), 851d29b2c44Sab dynsec->sec_shndx, dynsec->sec_name, 852d29b2c44Sab EC_WORD(arg1), EC_XWORD(arg2)); 853d29b2c44Sab return (ELFEDIT_CMDRET_NONE); 854d29b2c44Sab } else { 855d29b2c44Sab /* Warn if setting DT_NULL value to non-zero */ 856d29b2c44Sab if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0)) 857d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 858d29b2c44Sab MSG_INTL(MSG_DEBUG_DTNULLVALUE), 859d29b2c44Sab dynsec->sec_shndx, dynsec->sec_name, 860d29b2c44Sab EC_WORD(arg1), EC_XWORD(arg2)); 861d29b2c44Sab 862d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 863d29b2c44Sab MSG_INTL(MSG_DEBUG_X_CHG), 864d29b2c44Sab dynsec->sec_shndx, dynsec->sec_name, 865d29b2c44Sab EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val), 866d29b2c44Sab EC_XWORD(arg2)); 867d29b2c44Sab dyn[arg1].d_un.d_val = arg2; 868d29b2c44Sab return (ELFEDIT_CMDRET_MOD); 869d29b2c44Sab } 870d29b2c44Sab } 871d29b2c44Sab 872d29b2c44Sab /* 873d29b2c44Sab * We need a new slot in the dynamic section. If we can't have 874d29b2c44Sab * one, then we fail. 875d29b2c44Sab */ 876d29b2c44Sab if (argstate->dyn.num_null_ndx <= 1) 877d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 878d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 879d29b2c44Sab 880d29b2c44Sab /* 881d29b2c44Sab * If we still need to insert a new string into the dynstr, 882d29b2c44Sab * then it is safe now, because if we succeed, we know that 883d29b2c44Sab * there is an available slot to receive it. If we fail, we 884d29b2c44Sab * haven't claimed the extra slot yet, and it will be unharmed. 885d29b2c44Sab */ 886d29b2c44Sab if (!arg2_known) 887d29b2c44Sab arg2 = elfedit_dynstr_insert(dynsec, strsec, 888d29b2c44Sab &strpad_elt, argstate->argv[1]); 889d29b2c44Sab 890d29b2c44Sab /* Use an extra DT_NULL slot and enter the new element */ 891d29b2c44Sab *ret_ndx = convert_dt_null(argstate, arg1, arg2); 892d29b2c44Sab return (ELFEDIT_CMDRET_MOD); 893d29b2c44Sab } 894d29b2c44Sab 895d29b2c44Sab 896d29b2c44Sab 897d29b2c44Sab /* 898d29b2c44Sab * Called by cmd_body() for dyn:runpath. Implements the core functionality 899d29b2c44Sab * for that command. 900d29b2c44Sab * 901d29b2c44Sab * History Lesson And Strategy: 902d29b2c44Sab * 903d29b2c44Sab * This routine handles both DT_RPATH and DT_RUNPATH entries, altering 904d29b2c44Sab * either or both if they are present. 905d29b2c44Sab * 906d29b2c44Sab * The original SYSV ABI only had DT_RPATH, and the runtime loader used 907d29b2c44Sab * it to search for things in the following order: 908d29b2c44Sab * 909d29b2c44Sab * DT_RPATH, LD_LIBRARY_PATH, defaults 910d29b2c44Sab * 911d29b2c44Sab * Solaris did not follow this rule, an extremely rare deviation from 912d29b2c44Sab * the ABI. Environment variables should supercede everything else, 913d29b2c44Sab * otherwise they are not very useful. This decision was made at the 914d29b2c44Sab * very beginning of the SunOS 5.x development, so we have always 915d29b2c44Sab * deviated from the ABI and and instead search in the order 916d29b2c44Sab * 917d29b2c44Sab * LD_LIBRARY_PATH, DT_RPATH, defaults 918d29b2c44Sab * 919d29b2c44Sab * Other Unix variants initially followed the ABI, but in recent years 920d29b2c44Sab * have come to agree with the early Solaris folks that it was a mistake. 921d29b2c44Sab * Hence, DT_RUNPATH was invented, with the search order: 922d29b2c44Sab * 923d29b2c44Sab * LD_LIBRARY_PATH, DT_RUNPATH, defaults 924d29b2c44Sab * 925d29b2c44Sab * So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both 926d29b2c44Sab * are present (which does happen), we set them both to the new 927d29b2c44Sab * value. If either one is present, we set that one. If neither is 928d29b2c44Sab * present, and we have a spare DT_NULL slot, we create a DT_RUNPATH, but 929d29b2c44Sab * not a DT_RPATH, to conserve available slots for other uses. 930d29b2c44Sab */ 931d29b2c44Sab static elfedit_cmdret_t 932d29b2c44Sab cmd_body_runpath(ARGSTATE *argstate) 933d29b2c44Sab { 934d29b2c44Sab elfedit_section_t *dynsec = argstate->dyn.sec; 935d29b2c44Sab elfedit_section_t *strsec = argstate->strsec; 936d29b2c44Sab elfedit_dyn_elt_t rpath_elt; 937d29b2c44Sab elfedit_dyn_elt_t runpath_elt; 938d29b2c44Sab elfedit_dyn_elt_t strpad_elt; 939d29b2c44Sab Word i; 940d29b2c44Sab Dyn *dyn = argstate->dyn.data; 941d29b2c44Sab Word numdyn = argstate->dyn.num; 942d29b2c44Sab 943d29b2c44Sab /* Go through the tags and gather what we need */ 944d29b2c44Sab elfedit_dyn_elt_init(&rpath_elt); 945d29b2c44Sab elfedit_dyn_elt_init(&runpath_elt); 946d29b2c44Sab elfedit_dyn_elt_init(&strpad_elt); 947d29b2c44Sab for (i = 0; i < numdyn; i++) { 948d29b2c44Sab switch (dyn[i].d_tag) { 949d29b2c44Sab case DT_RPATH: 950d29b2c44Sab elfedit_dyn_elt_save(&rpath_elt, i, &dyn[i]); 951d29b2c44Sab break; 952d29b2c44Sab 953d29b2c44Sab case DT_RUNPATH: 954d29b2c44Sab elfedit_dyn_elt_save(&runpath_elt, i, &dyn[i]); 955d29b2c44Sab break; 956d29b2c44Sab 957d29b2c44Sab case DT_SUNW_STRPAD: 958d29b2c44Sab elfedit_dyn_elt_save(&strpad_elt, i, &dyn[i]); 959d29b2c44Sab break; 960d29b2c44Sab } 961d29b2c44Sab } 962d29b2c44Sab 963d29b2c44Sab /* Do we have an available dynamic section entry to use? */ 964d29b2c44Sab if (rpath_elt.dn_seen || runpath_elt.dn_seen) { 965d29b2c44Sab /* 966d29b2c44Sab * We have seen a DT_RPATH, or a DT_RUNPATH, or both. 967d29b2c44Sab * If all of these have the same string as the desired 968d29b2c44Sab * new value, then we don't need to alter anything and can 969d29b2c44Sab * simply return. Otherwise, we'll modify them all to have 970d29b2c44Sab * the new string (below). 971d29b2c44Sab */ 972d29b2c44Sab if ((!rpath_elt.dn_seen || 973d29b2c44Sab (strcmp(elfedit_dyn_offset_to_str(strsec, &rpath_elt), 974d29b2c44Sab argstate->argv[0]) == 0)) && 975d29b2c44Sab (!runpath_elt.dn_seen || 976d29b2c44Sab (strcmp(elfedit_dyn_offset_to_str(strsec, &runpath_elt), 977d29b2c44Sab argstate->argv[0]) == 0))) { 978d29b2c44Sab if (rpath_elt.dn_seen) 979d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 980d29b2c44Sab MSG_INTL(MSG_DEBUG_OLDRPATHOK), 981d29b2c44Sab EC_WORD(dynsec->sec_shndx), 982d29b2c44Sab dynsec->sec_name, EC_WORD(rpath_elt.dn_ndx), 983d29b2c44Sab elfedit_atoconst_value_to_str( 984d29b2c44Sab ELFEDIT_CONST_DT, DT_RPATH, 1)); 985d29b2c44Sab if (runpath_elt.dn_seen) 986d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 987d29b2c44Sab MSG_INTL(MSG_DEBUG_OLDRPATHOK), 988d29b2c44Sab EC_WORD(dynsec->sec_shndx), 989d29b2c44Sab dynsec->sec_name, 990d29b2c44Sab EC_WORD(runpath_elt.dn_ndx), 991d29b2c44Sab elfedit_atoconst_value_to_str( 992d29b2c44Sab ELFEDIT_CONST_DT, DT_RUNPATH, 1)); 993d29b2c44Sab return (ELFEDIT_CMDRET_NONE); 994d29b2c44Sab } 995d29b2c44Sab } else if (argstate->dyn.num_null_ndx <= 1) { 996d29b2c44Sab /* 997d29b2c44Sab * There is no DT_RPATH or DT_RUNPATH in the dynamic array, 998d29b2c44Sab * and there are no extra DT_NULL entries that we can 999d29b2c44Sab * convert into one. We cannot proceed. 1000d29b2c44Sab */ 1001d29b2c44Sab elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL), 1002d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name); 1003d29b2c44Sab } 1004d29b2c44Sab 1005d29b2c44Sab /* Does the string exist in the table already, or can we add it? */ 1006d29b2c44Sab rpath_elt.dn_dyn.d_un.d_val = runpath_elt.dn_dyn.d_un.d_val = 1007d29b2c44Sab elfedit_dynstr_insert(dynsec, strsec, &strpad_elt, 1008d29b2c44Sab argstate->argv[0]); 1009d29b2c44Sab 1010d29b2c44Sab /* Update DT_RPATH entry if present */ 1011d29b2c44Sab if (rpath_elt.dn_seen) { 1012d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_PREVRPATH), 1013d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 1014d29b2c44Sab EC_WORD(rpath_elt.dn_ndx), 1015d29b2c44Sab elfedit_atoconst_value_to_str( 1016d29b2c44Sab ELFEDIT_CONST_DT, DT_RPATH, 1), 1017d29b2c44Sab elfedit_dyn_offset_to_str(strsec, &rpath_elt)); 1018d29b2c44Sab dyn[rpath_elt.dn_ndx] = rpath_elt.dn_dyn; 1019d29b2c44Sab } 1020d29b2c44Sab 1021d29b2c44Sab /* 1022d29b2c44Sab * Update the DT_RUNPATH entry in the dynamic section, if present. 1023d29b2c44Sab * If one is not present, and there is also no DT_RPATH, then 1024d29b2c44Sab * we use a spare DT_NULL entry to create a new DT_RUNPATH. 1025d29b2c44Sab */ 1026d29b2c44Sab if (runpath_elt.dn_seen || !rpath_elt.dn_seen) { 1027d29b2c44Sab if (runpath_elt.dn_seen) { 1028d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1029d29b2c44Sab MSG_INTL(MSG_DEBUG_PREVRPATH), 1030d29b2c44Sab EC_WORD(dynsec->sec_shndx), dynsec->sec_name, 1031d29b2c44Sab EC_WORD(runpath_elt.dn_ndx), 1032d29b2c44Sab elfedit_atoconst_value_to_str( 1033d29b2c44Sab ELFEDIT_CONST_DT, DT_RUNPATH, 1), 1034d29b2c44Sab elfedit_dyn_offset_to_str(strsec, &runpath_elt)); 1035d29b2c44Sab dyn[runpath_elt.dn_ndx] = runpath_elt.dn_dyn; 1036d29b2c44Sab } else { /* Using a spare DT_NULL entry */ 1037d29b2c44Sab (void) convert_dt_null(argstate, DT_RUNPATH, 1038d29b2c44Sab runpath_elt.dn_dyn.d_un.d_val); 1039d29b2c44Sab } 1040d29b2c44Sab } 1041d29b2c44Sab 1042d29b2c44Sab return (ELFEDIT_CMDRET_MOD); 1043d29b2c44Sab } 1044d29b2c44Sab 1045d29b2c44Sab 1046d29b2c44Sab 1047d29b2c44Sab /* 1048d29b2c44Sab * Argument processing for the bitmask commands. Convert the arguments 1049d29b2c44Sab * to integer form, apply -and/-cmp/-or, and return the resulting value. 1050d29b2c44Sab * 1051d29b2c44Sab * entry: 1052d29b2c44Sab * argstate - Argument state block 1053d29b2c44Sab * orig - Value of original bitmask 1054d29b2c44Sab * const_type - ELFEDIT_CONST_* value for type of constants 1055d29b2c44Sab */ 1056d29b2c44Sab static Word 1057d29b2c44Sab flag_bitop(ARGSTATE *argstate, Word orig, elfedit_const_t const_type) 1058d29b2c44Sab { 1059d29b2c44Sab Word flags = 0; 1060d29b2c44Sab int i; 1061d29b2c44Sab 1062d29b2c44Sab /* Collect the arguments */ 1063d29b2c44Sab for (i = 0; i < argstate->argc; i++) 1064d29b2c44Sab flags |= (Word) elfedit_atoconst(argstate->argv[i], const_type); 1065d29b2c44Sab 1066d29b2c44Sab /* Complement the value? */ 1067d29b2c44Sab if (argstate->optmask & DYN_OPT_F_CMP) 1068d29b2c44Sab flags = ~flags; 1069d29b2c44Sab 1070d29b2c44Sab /* Perform any requested bit operations */ 1071d29b2c44Sab if (argstate->optmask & DYN_OPT_F_AND) 1072d29b2c44Sab flags &= orig; 1073d29b2c44Sab else if (argstate->optmask & DYN_OPT_F_OR) 1074d29b2c44Sab flags |= orig; 1075d29b2c44Sab 1076d29b2c44Sab return (flags); 1077d29b2c44Sab } 1078d29b2c44Sab 1079d29b2c44Sab 1080d29b2c44Sab 1081d29b2c44Sab /* 1082d29b2c44Sab * Common body for the dyn: module commands. These commands 1083d29b2c44Sab * share a large amount of common behavior, so it is convenient 1084d29b2c44Sab * to centralize things and use the cmd argument to handle the 1085d29b2c44Sab * small differences. 1086d29b2c44Sab * 1087d29b2c44Sab * entry: 1088d29b2c44Sab * cmd - One of the DYN_CMD_T_* constants listed above, specifying 1089d29b2c44Sab * which command to implement. 1090d29b2c44Sab * obj_state, argc, argv - Standard command arguments 1091d29b2c44Sab */ 1092d29b2c44Sab static elfedit_cmdret_t 1093d29b2c44Sab cmd_body(DYN_CMD_T cmd, elfedit_obj_state_t *obj_state, 1094d29b2c44Sab int argc, const char *argv[]) 1095d29b2c44Sab { 1096d29b2c44Sab ARGSTATE argstate; 1097d29b2c44Sab Dyn *dyn; 1098d29b2c44Sab const char *dyn_name; 1099d29b2c44Sab Word dyn_ndx, dyn_num, null_ndx; 1100d29b2c44Sab elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 1101d29b2c44Sab PRINT_DYN_T print_type = PRINT_DYN_T_ALL; 1102d29b2c44Sab Word ndx; 1103d29b2c44Sab int print_only = 0; 1104d29b2c44Sab int do_autoprint = 1; 1105d29b2c44Sab 1106d29b2c44Sab /* Process the optional arguments */ 1107d29b2c44Sab process_args(obj_state, argc, argv, &argstate); 1108d29b2c44Sab 1109d29b2c44Sab dyn = argstate.dyn.data; 1110d29b2c44Sab dyn_num = argstate.dyn.num; 1111d29b2c44Sab dyn_name = argstate.dyn.sec->sec_name; 1112d29b2c44Sab dyn_ndx = argstate.dyn.sec->sec_shndx; 1113d29b2c44Sab 1114d29b2c44Sab /* Check number of arguments, gather information */ 1115d29b2c44Sab switch (cmd) { 1116d29b2c44Sab case DYN_CMD_T_DUMP: 1117d29b2c44Sab /* dyn:dump can accept an optional index argument */ 1118d29b2c44Sab if (argstate.argc > 1) 1119d29b2c44Sab elfedit_command_usage(); 1120d29b2c44Sab print_only = 1; 1121d29b2c44Sab if (argstate.argc == 1) 1122d29b2c44Sab ndx = arg_to_index(&argstate, argstate.argv[0], 112355ef6355Sab print_only, &print_type); 1124d29b2c44Sab break; 1125d29b2c44Sab 1126d29b2c44Sab case DYN_CMD_T_TAG: 1127d29b2c44Sab print_only = (argstate.argc != 2); 1128d29b2c44Sab if (argstate.argc > 0) { 1129d29b2c44Sab if (argstate.argc > 2) 1130d29b2c44Sab elfedit_command_usage(); 1131d29b2c44Sab ndx = arg_to_index(&argstate, argstate.argv[0], 113255ef6355Sab print_only, &print_type); 1133d29b2c44Sab } 1134d29b2c44Sab break; 1135d29b2c44Sab 1136d29b2c44Sab case DYN_CMD_T_VALUE: 1137d29b2c44Sab print_only = (argstate.argc != 2); 1138d29b2c44Sab if (argstate.argc > 2) 1139d29b2c44Sab elfedit_command_usage(); 1140d29b2c44Sab if (argstate.argc > 0) { 1141d29b2c44Sab if (print_only) { 1142d29b2c44Sab ndx = arg_to_index(&argstate, argstate.argv[0], 1143d29b2c44Sab print_only, &print_type); 1144d29b2c44Sab } else { 1145d29b2c44Sab print_type = PRINT_DYN_T_NDX; 1146d29b2c44Sab } 1147d29b2c44Sab } 1148d29b2c44Sab break; 1149d29b2c44Sab 1150d29b2c44Sab case DYN_CMD_T_DELETE: 1151d29b2c44Sab if ((argstate.argc < 1) || (argstate.argc > 2)) 1152d29b2c44Sab elfedit_command_usage(); 1153d29b2c44Sab ndx = arg_to_index(&argstate, argstate.argv[0], 1154d29b2c44Sab 0, &print_type); 1155d29b2c44Sab do_autoprint = 0; 1156d29b2c44Sab break; 1157d29b2c44Sab 1158d29b2c44Sab case DYN_CMD_T_MOVE: 1159d29b2c44Sab if ((argstate.argc < 2) || (argstate.argc > 3)) 1160d29b2c44Sab elfedit_command_usage(); 1161d29b2c44Sab ndx = arg_to_index(&argstate, argstate.argv[0], 116255ef6355Sab 0, &print_type); 1163d29b2c44Sab do_autoprint = 0; 1164d29b2c44Sab break; 1165d29b2c44Sab 1166d29b2c44Sab case DYN_CMD_T_RUNPATH: 1167d29b2c44Sab if (argstate.argc > 1) 1168d29b2c44Sab elfedit_command_usage(); 1169d29b2c44Sab /* 1170d29b2c44Sab * dyn:runpath does not accept an explicit index 1171d29b2c44Sab * argument, so we implicitly only show the DT_RPATH and 1172d29b2c44Sab * DT_RUNPATH elements. 1173d29b2c44Sab */ 1174d29b2c44Sab print_type = PRINT_DYN_T_RUNPATH; 1175d29b2c44Sab print_only = (argstate.argc == 0); 1176d29b2c44Sab break; 1177d29b2c44Sab 1178d29b2c44Sab case DYN_CMD_T_POSFLAG1: 1179d29b2c44Sab print_only = (argstate.argc == 0); 1180d29b2c44Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1181d29b2c44Sab ELFEDIT_CONST_DT, DT_POSFLAG_1, 1), 118255ef6355Sab print_only, &print_type); 1183d29b2c44Sab break; 1184d29b2c44Sab 1185d29b2c44Sab case DYN_CMD_T_FLAGS: 1186d29b2c44Sab print_only = (argstate.argc == 0); 1187d29b2c44Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1188d29b2c44Sab ELFEDIT_CONST_DT, DT_FLAGS, 1), 118955ef6355Sab print_only, &print_type); 1190d29b2c44Sab break; 1191d29b2c44Sab 1192d29b2c44Sab case DYN_CMD_T_FLAGS1: 1193d29b2c44Sab print_only = (argstate.argc == 0); 1194d29b2c44Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1195d29b2c44Sab ELFEDIT_CONST_DT, DT_FLAGS_1, 1), 119655ef6355Sab print_only, &print_type); 1197d29b2c44Sab break; 1198d29b2c44Sab 1199d29b2c44Sab case DYN_CMD_T_FEATURE1: 1200d29b2c44Sab print_only = (argstate.argc == 0); 1201d29b2c44Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1202d29b2c44Sab ELFEDIT_CONST_DT, DT_FEATURE_1, 1), 120355ef6355Sab print_only, &print_type); 1204d29b2c44Sab break; 1205d29b2c44Sab 1206d29b2c44Sab case DYN_CMD_T_CHECKSUM: 1207d29b2c44Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1208d29b2c44Sab ELFEDIT_CONST_DT, DT_CHECKSUM, 1), 120955ef6355Sab print_only, &print_type); 1210d29b2c44Sab break; 1211d29b2c44Sab 1212ba2be530Sab case DYN_CMD_T_SUNW_LDMACH: 1213ba2be530Sab if (argstate.argc > 1) 1214ba2be530Sab elfedit_command_usage(); 1215ba2be530Sab print_only = (argstate.argc == 0); 1216ba2be530Sab ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 1217ba2be530Sab ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1), 121855ef6355Sab print_only, &print_type); 1219ba2be530Sab break; 1220ba2be530Sab 1221d29b2c44Sab default: 1222d29b2c44Sab /* Note expected: All commands should have been caught above */ 1223d29b2c44Sab elfedit_command_usage(); 1224d29b2c44Sab break; 1225d29b2c44Sab } 1226d29b2c44Sab 1227d29b2c44Sab 1228d29b2c44Sab /* If this is a request to print current values, do it and return */ 1229d29b2c44Sab if (print_only) { 1230d29b2c44Sab print_dyn(cmd, 0, &argstate, print_type, ndx); 1231d29b2c44Sab return (ELFEDIT_CMDRET_NONE); 1232d29b2c44Sab } 1233d29b2c44Sab 1234d29b2c44Sab 1235d29b2c44Sab switch (cmd) { 1236d29b2c44Sab /* 1237d29b2c44Sab * DYN_CMD_T_DUMP can't get here: It is a print-only 1238d29b2c44Sab * command. 1239d29b2c44Sab */ 1240d29b2c44Sab 1241d29b2c44Sab case DYN_CMD_T_TAG: 1242d29b2c44Sab { 1243d29b2c44Sab Conv_inv_buf_t inv_buf1, inv_buf2; 1244d29b2c44Sab Half mach = argstate.obj_state->os_ehdr->e_machine; 1245d29b2c44Sab Word d_tag = (Word) elfedit_atoconst(argstate.argv[1], 1246d29b2c44Sab ELFEDIT_CONST_DT); 1247d29b2c44Sab 1248d29b2c44Sab if (dyn[ndx].d_tag == d_tag) { 1249d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1250d29b2c44Sab MSG_INTL(MSG_DEBUG_S_OK), 1251d29b2c44Sab dyn_ndx, 1252d29b2c44Sab dyn_name, EC_WORD(ndx), 1253d29b2c44Sab conv_dyn_tag(d_tag, mach, 0, &inv_buf1)); 1254d29b2c44Sab } else { 1255d29b2c44Sab Word orig_d_tag = dyn[ndx].d_tag; 1256d29b2c44Sab 1257d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1258d29b2c44Sab dyn[ndx].d_tag = d_tag; 1259d29b2c44Sab 1260d29b2c44Sab /* 1261d29b2c44Sab * Update null termination index. Warn if we 1262d29b2c44Sab * just clobbered the only DT_NULL termination 1263d29b2c44Sab * for the array. 1264d29b2c44Sab */ 1265d29b2c44Sab null_ndx = argstate.dyn.null_ndx; 1266d29b2c44Sab set_null_ndx(&argstate); 1267d29b2c44Sab if ((argstate.dyn.null_ndx >= 1268d29b2c44Sab argstate.dyn.num) && 1269d29b2c44Sab (null_ndx != argstate.dyn.null_ndx)) 1270d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1271d29b2c44Sab MSG_INTL(MSG_DEBUG_NULLTERM), 1272d29b2c44Sab dyn_ndx, dyn_name, 1273d29b2c44Sab EC_WORD(ndx), 1274d29b2c44Sab conv_dyn_tag(d_tag, mach, 1275d29b2c44Sab 0, &inv_buf1)); 1276d29b2c44Sab 1277d29b2c44Sab /* 1278d29b2c44Sab * Warning if 1279d29b2c44Sab * - Inserting a DT_NULL cuts off following 1280d29b2c44Sab * non-null elements. 1281d29b2c44Sab * - Inserting a non-DT_NULL after the 1282d29b2c44Sab * first null element, will be 1283d29b2c44Sab * ignored by rtld. 1284d29b2c44Sab */ 1285d29b2c44Sab if (d_tag == DT_NULL) { 1286d29b2c44Sab if ((ndx + 1) < null_ndx) 1287d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1288d29b2c44Sab MSG_INTL(MSG_DEBUG_NULCLIP), 1289d29b2c44Sab dyn_ndx, dyn_name, 1290d29b2c44Sab EC_WORD(ndx), 1291d29b2c44Sab conv_dyn_tag(d_tag, mach, 1292d29b2c44Sab 0, &inv_buf1)); 1293d29b2c44Sab } else { 1294d29b2c44Sab if ((ndx + 1) > argstate.dyn.null_ndx) 1295d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1296d29b2c44Sab MSG_INTL(MSG_DEBUG_NULHIDE), 1297d29b2c44Sab dyn_ndx, dyn_name, 1298d29b2c44Sab EC_WORD(ndx), 1299d29b2c44Sab conv_dyn_tag(d_tag, mach, 1300d29b2c44Sab 0, &inv_buf1)); 1301d29b2c44Sab } 1302d29b2c44Sab 1303d29b2c44Sab /* Debug message that we changed it */ 1304d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1305d29b2c44Sab MSG_INTL(MSG_DEBUG_S_CHG), 1306d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1307d29b2c44Sab conv_dyn_tag(orig_d_tag, mach, 0, 1308d29b2c44Sab &inv_buf1), 1309d29b2c44Sab conv_dyn_tag(d_tag, mach, 0, &inv_buf2)); 1310d29b2c44Sab } 1311d29b2c44Sab } 1312d29b2c44Sab break; 1313d29b2c44Sab 1314d29b2c44Sab case DYN_CMD_T_VALUE: 1315d29b2c44Sab ret = cmd_body_value(&argstate, &ndx); 1316d29b2c44Sab break; 1317d29b2c44Sab 1318d29b2c44Sab case DYN_CMD_T_DELETE: 1319d29b2c44Sab { 1320d29b2c44Sab Word cnt = (argstate.argc == 1) ? 1 : 1321d29b2c44Sab (Word) elfedit_atoui_range(argstate.argv[1], 1322d29b2c44Sab MSG_ORIG(MSG_STR_COUNT), 1, dyn_num - ndx, NULL); 1323d29b2c44Sab const char *msg_prefix = 1324d29b2c44Sab elfedit_sec_msgprefix(argstate.dyn.sec); 1325d29b2c44Sab 1326d29b2c44Sab elfedit_array_elts_delete(msg_prefix, argstate.dyn.data, 1327d29b2c44Sab sizeof (Dyn), dyn_num, ndx, cnt); 1328d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1329d29b2c44Sab } 1330d29b2c44Sab break; 1331d29b2c44Sab 1332d29b2c44Sab case DYN_CMD_T_MOVE: 1333d29b2c44Sab { 1334d29b2c44Sab Dyn save; 1335d29b2c44Sab Word cnt; 1336d29b2c44Sab Word dstndx; 1337d29b2c44Sab const char *msg_prefix = 1338d29b2c44Sab elfedit_sec_msgprefix(argstate.dyn.sec); 1339d29b2c44Sab 1340d29b2c44Sab dstndx = (Word) 1341d29b2c44Sab elfedit_atoui_range(argstate.argv[1], 1342d29b2c44Sab MSG_ORIG(MSG_STR_DST_INDEX), 0, dyn_num - 1, 1343d29b2c44Sab NULL); 1344d29b2c44Sab if (argstate.argc == 2) { 1345d29b2c44Sab cnt = 1; 1346d29b2c44Sab } else { 1347d29b2c44Sab cnt = (Word) elfedit_atoui_range( 1348d29b2c44Sab argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), 1349d29b2c44Sab 1, dyn_num, NULL); 1350d29b2c44Sab } 1351d29b2c44Sab elfedit_array_elts_move(msg_prefix, argstate.dyn.data, 1352d29b2c44Sab sizeof (save), dyn_num, ndx, dstndx, cnt, &save); 1353d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1354d29b2c44Sab } 1355d29b2c44Sab break; 1356d29b2c44Sab 1357d29b2c44Sab 1358d29b2c44Sab case DYN_CMD_T_RUNPATH: 1359d29b2c44Sab ret = cmd_body_runpath(&argstate); 1360d29b2c44Sab break; 1361d29b2c44Sab 1362d29b2c44Sab case DYN_CMD_T_POSFLAG1: 1363d29b2c44Sab { 1364d29b2c44Sab Conv_dyn_posflag1_buf_t buf1, buf2; 1365d29b2c44Sab Word flags; 1366d29b2c44Sab 1367d29b2c44Sab flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 1368d29b2c44Sab ELFEDIT_CONST_DF_P1); 1369d29b2c44Sab 1370d29b2c44Sab /* Set the value */ 1371d29b2c44Sab if (dyn[ndx].d_un.d_val == flags) { 1372d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1373d29b2c44Sab MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1374d29b2c44Sab dyn_name, EC_WORD(ndx), 1375d29b2c44Sab conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 1376d29b2c44Sab &buf1)); 1377d29b2c44Sab } else { 1378d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1379d29b2c44Sab MSG_INTL(MSG_DEBUG_S_CHG), 1380d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1381d29b2c44Sab conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0, 1382d29b2c44Sab &buf1), 1383d29b2c44Sab conv_dyn_posflag1(flags, 0, &buf2)); 1384d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1385d29b2c44Sab dyn[ndx].d_un.d_val = flags; 1386d29b2c44Sab } 1387d29b2c44Sab } 1388d29b2c44Sab break; 1389d29b2c44Sab 1390d29b2c44Sab case DYN_CMD_T_FLAGS: 1391d29b2c44Sab { 1392d29b2c44Sab Conv_dyn_flag_buf_t buf1, buf2; 1393d29b2c44Sab Word flags; 1394d29b2c44Sab 1395d29b2c44Sab flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 1396d29b2c44Sab ELFEDIT_CONST_DF); 1397d29b2c44Sab 1398d29b2c44Sab /* Set the value */ 1399d29b2c44Sab if (dyn[ndx].d_un.d_val == flags) { 1400d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1401d29b2c44Sab MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1402d29b2c44Sab dyn_name, EC_WORD(ndx), 1403d29b2c44Sab conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 1404d29b2c44Sab &buf1)); 1405d29b2c44Sab } else { 1406d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1407d29b2c44Sab MSG_INTL(MSG_DEBUG_S_CHG), 1408d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1409d29b2c44Sab conv_dyn_flag(dyn[ndx].d_un.d_val, 0, 1410d29b2c44Sab &buf1), 1411d29b2c44Sab conv_dyn_flag(flags, 0, &buf2)); 1412d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1413d29b2c44Sab dyn[ndx].d_un.d_val = flags; 1414d29b2c44Sab } 1415d29b2c44Sab } 1416d29b2c44Sab break; 1417d29b2c44Sab 1418d29b2c44Sab case DYN_CMD_T_FLAGS1: 1419d29b2c44Sab { 1420d29b2c44Sab Conv_dyn_flag1_buf_t buf1, buf2; 1421d29b2c44Sab Word flags1; 1422d29b2c44Sab 1423d29b2c44Sab flags1 = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 1424d29b2c44Sab ELFEDIT_CONST_DF_1); 1425d29b2c44Sab 1426d29b2c44Sab /* Set the value */ 1427d29b2c44Sab if (dyn[ndx].d_un.d_val == flags1) { 1428d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1429d29b2c44Sab MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1430d29b2c44Sab dyn_name, EC_WORD(ndx), 1431d29b2c44Sab conv_dyn_flag1(dyn[ndx].d_un.d_val, 1432d29b2c44Sab 0, &buf1)); 1433d29b2c44Sab } else { 1434d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1435d29b2c44Sab MSG_INTL(MSG_DEBUG_S_CHG), 1436d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1437d29b2c44Sab conv_dyn_flag1(dyn[ndx].d_un.d_val, 1438d29b2c44Sab 0, &buf1), 1439d29b2c44Sab conv_dyn_flag1(flags1, 0, &buf2)); 1440d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1441d29b2c44Sab dyn[ndx].d_un.d_val = flags1; 1442d29b2c44Sab } 1443d29b2c44Sab } 1444d29b2c44Sab break; 1445d29b2c44Sab 1446d29b2c44Sab case DYN_CMD_T_FEATURE1: 1447d29b2c44Sab { 1448d29b2c44Sab Conv_dyn_feature1_buf_t buf1, buf2; 1449d29b2c44Sab Word flags; 1450d29b2c44Sab 1451d29b2c44Sab flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val, 1452d29b2c44Sab ELFEDIT_CONST_DTF_1); 1453d29b2c44Sab 1454d29b2c44Sab /* Set the value */ 1455d29b2c44Sab if (dyn[ndx].d_un.d_val == flags) { 1456d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1457d29b2c44Sab MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1458d29b2c44Sab dyn_name, EC_WORD(ndx), 1459d29b2c44Sab conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 1460d29b2c44Sab &buf1)); 1461d29b2c44Sab } else { 1462d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1463d29b2c44Sab MSG_INTL(MSG_DEBUG_S_CHG), 1464d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1465d29b2c44Sab conv_dyn_feature1(dyn[ndx].d_un.d_val, 0, 1466d29b2c44Sab &buf1), 1467d29b2c44Sab conv_dyn_feature1(flags, 0, &buf2)); 1468d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1469d29b2c44Sab dyn[ndx].d_un.d_val = flags; 1470d29b2c44Sab } 1471d29b2c44Sab } 1472d29b2c44Sab break; 1473d29b2c44Sab 1474d29b2c44Sab case DYN_CMD_T_CHECKSUM: 1475d29b2c44Sab { 1476d29b2c44Sab long checksum = elf_checksum(obj_state->os_elf); 1477d29b2c44Sab 1478d29b2c44Sab /* Set the value */ 1479d29b2c44Sab if (dyn[ndx].d_un.d_val == checksum) { 1480d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1481d29b2c44Sab MSG_INTL(MSG_DEBUG_X_OK), dyn_ndx, 1482d29b2c44Sab dyn_name, EC_WORD(ndx), EC_XWORD(checksum)); 1483d29b2c44Sab } else { 1484d29b2c44Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1485d29b2c44Sab MSG_INTL(MSG_DEBUG_X_CHG), 1486d29b2c44Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1487d29b2c44Sab EC_XWORD(dyn[ndx].d_un.d_val), 1488d29b2c44Sab EC_XWORD(checksum)); 1489d29b2c44Sab ret = ELFEDIT_CMDRET_MOD; 1490d29b2c44Sab dyn[ndx].d_un.d_val = checksum; 1491d29b2c44Sab } 1492d29b2c44Sab 1493d29b2c44Sab } 1494ba2be530Sab break; 1495ba2be530Sab 1496ba2be530Sab case DYN_CMD_T_SUNW_LDMACH: 1497ba2be530Sab { 1498ba2be530Sab Conv_inv_buf_t buf1, buf2; 1499ba2be530Sab Half ldmach; 1500ba2be530Sab 1501ba2be530Sab ldmach = (Half) elfedit_atoconst(argstate.argv[0], 1502ba2be530Sab ELFEDIT_CONST_EM); 1503ba2be530Sab 1504ba2be530Sab /* Set the value */ 1505ba2be530Sab if (dyn[ndx].d_un.d_val == ldmach) { 1506ba2be530Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1507ba2be530Sab MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, 1508ba2be530Sab dyn_name, EC_WORD(ndx), 1509ba2be530Sab conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 1510ba2be530Sab &buf1)); 1511ba2be530Sab } else { 1512ba2be530Sab elfedit_msg(ELFEDIT_MSG_DEBUG, 1513ba2be530Sab MSG_INTL(MSG_DEBUG_S_CHG), 1514ba2be530Sab dyn_ndx, dyn_name, EC_WORD(ndx), 1515ba2be530Sab conv_ehdr_mach(dyn[ndx].d_un.d_val, 0, 1516ba2be530Sab &buf1), 1517ba2be530Sab conv_ehdr_mach(ldmach, 0, &buf2)); 1518ba2be530Sab ret = ELFEDIT_CMDRET_MOD; 1519ba2be530Sab dyn[ndx].d_un.d_val = ldmach; 1520ba2be530Sab } 1521ba2be530Sab } 1522ba2be530Sab break; 1523ba2be530Sab 1524d29b2c44Sab } 1525d29b2c44Sab 1526d29b2c44Sab /* 1527d29b2c44Sab * If we modified the dynamic section header, tell libelf. 1528d29b2c44Sab */ 1529d29b2c44Sab if (ret == ELFEDIT_CMDRET_MOD) 1530d29b2c44Sab elfedit_modified_data(argstate.dyn.sec); 1531d29b2c44Sab 1532d29b2c44Sab /* Do autoprint */ 1533d29b2c44Sab if (do_autoprint) 1534d29b2c44Sab print_dyn(cmd, 1, &argstate, print_type, ndx); 1535d29b2c44Sab 1536d29b2c44Sab return (ret); 1537d29b2c44Sab } 1538d29b2c44Sab 1539d29b2c44Sab 1540d29b2c44Sab 1541d29b2c44Sab /* 1542d29b2c44Sab * Command completion functions for the commands 1543d29b2c44Sab */ 1544d29b2c44Sab 1545d29b2c44Sab /* 1546d29b2c44Sab * Command completion for the first argument, which specifies 1547d29b2c44Sab * the dynamic element to use. Examines the options to see if 1548d29b2c44Sab * -dynndx is present, and if not, supplies the completion 1549d29b2c44Sab * strings for argument 1. 1550d29b2c44Sab */ 1551d29b2c44Sab /*ARGSUSED*/ 1552d29b2c44Sab static void 1553d29b2c44Sab cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1554d29b2c44Sab const char *argv[], int num_opt) 1555d29b2c44Sab { 1556d29b2c44Sab elfedit_section_t *cache; 1557d29b2c44Sab Dyn *dyn; 1558d29b2c44Sab Word i; 1559d29b2c44Sab const char *s; 1560d29b2c44Sab char *s2; 1561d29b2c44Sab char buf[128]; 1562d29b2c44Sab 1563d29b2c44Sab /* Make sure it's the first argument */ 1564d29b2c44Sab if ((argc - num_opt) != 1) 1565d29b2c44Sab return; 1566d29b2c44Sab 1567d29b2c44Sab /* Is -dynndx present? If so, we don't complete tag types */ 1568d29b2c44Sab for (i = 0; i < num_opt; i++) 1569d29b2c44Sab if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0) 1570d29b2c44Sab return; 1571d29b2c44Sab 1572d29b2c44Sab /* 1573d29b2c44Sab * If there is no object, or if there is no dynamic section, 1574d29b2c44Sab * then supply all possible names. 1575d29b2c44Sab */ 1576d29b2c44Sab if ((obj_state == NULL) || (obj_state->os_dynndx == SHN_UNDEF)) { 1577d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 1578d29b2c44Sab return; 1579d29b2c44Sab } 1580d29b2c44Sab 1581d29b2c44Sab /* Supply completions for the tags present in the dynamic section */ 1582d29b2c44Sab cache = &obj_state->os_secarr[obj_state->os_dynndx]; 1583d29b2c44Sab dyn = (Dyn *) cache->sec_data->d_buf; 1584d29b2c44Sab i = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize; 1585d29b2c44Sab for (; i-- > 0; dyn++) { 1586d29b2c44Sab s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_DT, 1587d29b2c44Sab dyn->d_tag, 0); 1588d29b2c44Sab if (s == NULL) 1589d29b2c44Sab continue; 1590d29b2c44Sab elfedit_cpl_match(cpldata, s, 1); 1591d29b2c44Sab 1592d29b2c44Sab /* 1593d29b2c44Sab * To get the informal tag names that are lowercase 1594d29b2c44Sab * and lack the leading DT_, we copy the string we 1595d29b2c44Sab * have into a buffer and process it. 1596d29b2c44Sab */ 1597d29b2c44Sab if (strlen(s) < 3) 1598d29b2c44Sab continue; 1599d29b2c44Sab (void) strlcpy(buf, s + 3, sizeof (buf)); 1600d29b2c44Sab for (s2 = buf; *s2 != '\0'; s2++) 1601d29b2c44Sab if (isupper(*s2)) 1602d29b2c44Sab *s2 = tolower(*s2); 1603d29b2c44Sab elfedit_cpl_match(cpldata, buf, 1); 1604d29b2c44Sab } 1605d29b2c44Sab } 1606d29b2c44Sab 1607d29b2c44Sab 1608d29b2c44Sab /*ARGSUSED*/ 1609d29b2c44Sab static void 1610d29b2c44Sab cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1611d29b2c44Sab const char *argv[], int num_opt) 1612d29b2c44Sab { 1613d29b2c44Sab /* First argument */ 1614d29b2c44Sab if ((argc - num_opt) == 1) { 1615d29b2c44Sab cpl_eltarg(obj_state, cpldata, argc, argv, num_opt); 1616d29b2c44Sab return; 1617d29b2c44Sab } 1618d29b2c44Sab 1619d29b2c44Sab /* The second argument is always a tag value */ 1620d29b2c44Sab if ((argc - num_opt) == 2) 1621d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT); 1622d29b2c44Sab } 1623d29b2c44Sab 1624d29b2c44Sab /*ARGSUSED*/ 1625d29b2c44Sab static void 1626d29b2c44Sab cpl_posflag1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1627d29b2c44Sab const char *argv[], int num_opt) 1628d29b2c44Sab { 162955ef6355Sab /* 163055ef6355Sab * dyn:posflag1 accepts two mutually exclusive options that have 163155ef6355Sab * a corresponding value argument: -dynndx and -needed. If we 163255ef6355Sab * are being called to supply options for the value, handle that here. 163355ef6355Sab */ 163455ef6355Sab if ((num_opt > 1) && (argc == num_opt)) { 163555ef6355Sab elfedit_section_t *dynsec, *strsec; 163655ef6355Sab const char *opt = argv[num_opt - 2]; 163755ef6355Sab dyn_opt_t type; 163855ef6355Sab Dyn *dyn; 163955ef6355Sab Word i, num; 164055ef6355Sab 164155ef6355Sab /* 164255ef6355Sab * If there is no object available, or if the object has no 164355ef6355Sab * dynamic section, then there is nothing to report. 164455ef6355Sab */ 164555ef6355Sab if ((obj_state == NULL) || obj_state->os_dynndx == SHN_UNDEF) 164655ef6355Sab return; 164755ef6355Sab 164855ef6355Sab /* 164955ef6355Sab * Determine which option it is, bail if it isn't one of 165055ef6355Sab * the ones we are concerned with. 165155ef6355Sab */ 165255ef6355Sab if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_NEEDED)) == 0)) 165355ef6355Sab type = DYN_OPT_F_NEEDED; 165455ef6355Sab else if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0)) 165555ef6355Sab type = DYN_OPT_F_DYNNDX_VAL; 165655ef6355Sab else 165755ef6355Sab return; 165855ef6355Sab 165955ef6355Sab dynsec = elfedit_sec_getdyn(obj_state, &dyn, &num); 166055ef6355Sab switch (type) { 166155ef6355Sab case DYN_OPT_F_NEEDED: 166255ef6355Sab strsec = elfedit_sec_getstr(obj_state, 166355ef6355Sab dynsec->sec_shdr->sh_link, 0); 166455ef6355Sab for (; num-- > 0; dyn++) 166555ef6355Sab if (dyn->d_tag == DT_NEEDED) 166655ef6355Sab elfedit_cpl_match(cpldata, 166755ef6355Sab elfedit_offset_to_str(strsec, 166855ef6355Sab dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 166955ef6355Sab 0), 0); 167055ef6355Sab break; 167155ef6355Sab 167255ef6355Sab case DYN_OPT_F_DYNNDX_VAL: 167355ef6355Sab for (i = 0; i < num; i++, dyn++) 167455ef6355Sab if (dyn->d_tag == DT_POSFLAG_1) 167555ef6355Sab elfedit_cpl_ndx(cpldata, i); 167655ef6355Sab break; 167755ef6355Sab } 167855ef6355Sab return; 167955ef6355Sab } 168055ef6355Sab 1681d29b2c44Sab /* This routine allows multiple flags to be specified */ 1682d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_P1); 1683d29b2c44Sab } 1684d29b2c44Sab 1685d29b2c44Sab /*ARGSUSED*/ 1686d29b2c44Sab static void 1687d29b2c44Sab cpl_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1688d29b2c44Sab const char *argv[], int num_opt) 1689d29b2c44Sab { 1690d29b2c44Sab /* This routine allows multiple flags to be specified */ 1691d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF); 1692d29b2c44Sab } 1693d29b2c44Sab 1694d29b2c44Sab /*ARGSUSED*/ 1695d29b2c44Sab static void 1696d29b2c44Sab cpl_flags1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1697d29b2c44Sab const char *argv[], int num_opt) 1698d29b2c44Sab { 1699d29b2c44Sab /* This routine allows multiple flags to be specified */ 1700d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_1); 1701d29b2c44Sab } 1702d29b2c44Sab 1703d29b2c44Sab /*ARGSUSED*/ 1704d29b2c44Sab static void 1705d29b2c44Sab cpl_feature1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1706d29b2c44Sab const char *argv[], int num_opt) 1707d29b2c44Sab { 1708d29b2c44Sab /* This routine allows multiple flags to be specified */ 1709d29b2c44Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1); 1710d29b2c44Sab } 1711d29b2c44Sab 1712ba2be530Sab /*ARGSUSED*/ 1713ba2be530Sab static void 1714ba2be530Sab cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1715ba2be530Sab const char *argv[], int num_opt) 1716ba2be530Sab { 1717ba2be530Sab /* 1718ba2be530Sab * This command doesn't accept options, so num_opt should be 1719ba2be530Sab * 0. This is a defensive measure, in case that should change. 1720ba2be530Sab */ 1721ba2be530Sab argc -= num_opt; 1722ba2be530Sab argv += num_opt; 1723ba2be530Sab 1724ba2be530Sab if (argc == 1) 1725ba2be530Sab elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM); 1726ba2be530Sab } 1727ba2be530Sab 1728d29b2c44Sab 1729d29b2c44Sab /* 1730d29b2c44Sab * Implementation functions for the commands 1731d29b2c44Sab */ 1732d29b2c44Sab static elfedit_cmdret_t 1733d29b2c44Sab cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1734d29b2c44Sab { 1735d29b2c44Sab return (cmd_body(DYN_CMD_T_DUMP, obj_state, argc, argv)); 1736d29b2c44Sab } 1737d29b2c44Sab 1738d29b2c44Sab static elfedit_cmdret_t 1739d29b2c44Sab cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1740d29b2c44Sab { 1741d29b2c44Sab return (cmd_body(DYN_CMD_T_TAG, obj_state, argc, argv)); 1742d29b2c44Sab } 1743d29b2c44Sab 1744d29b2c44Sab static elfedit_cmdret_t 1745d29b2c44Sab cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1746d29b2c44Sab { 1747d29b2c44Sab return (cmd_body(DYN_CMD_T_VALUE, obj_state, argc, argv)); 1748d29b2c44Sab } 1749d29b2c44Sab 1750d29b2c44Sab static elfedit_cmdret_t 1751d29b2c44Sab cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1752d29b2c44Sab { 1753d29b2c44Sab return (cmd_body(DYN_CMD_T_DELETE, obj_state, argc, argv)); 1754d29b2c44Sab } 1755d29b2c44Sab 1756d29b2c44Sab static elfedit_cmdret_t 1757d29b2c44Sab cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1758d29b2c44Sab { 1759d29b2c44Sab return (cmd_body(DYN_CMD_T_MOVE, obj_state, argc, argv)); 1760d29b2c44Sab } 1761d29b2c44Sab 1762d29b2c44Sab static elfedit_cmdret_t 1763d29b2c44Sab cmd_runpath(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1764d29b2c44Sab { 1765d29b2c44Sab return (cmd_body(DYN_CMD_T_RUNPATH, obj_state, argc, argv)); 1766d29b2c44Sab } 1767d29b2c44Sab 1768d29b2c44Sab static elfedit_cmdret_t 1769d29b2c44Sab cmd_posflag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1770d29b2c44Sab { 1771d29b2c44Sab return (cmd_body(DYN_CMD_T_POSFLAG1, obj_state, argc, argv)); 1772d29b2c44Sab } 1773d29b2c44Sab 1774d29b2c44Sab static elfedit_cmdret_t 1775d29b2c44Sab cmd_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1776d29b2c44Sab { 1777d29b2c44Sab return (cmd_body(DYN_CMD_T_FLAGS, obj_state, argc, argv)); 1778d29b2c44Sab } 1779d29b2c44Sab 1780d29b2c44Sab static elfedit_cmdret_t 1781d29b2c44Sab cmd_flags1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1782d29b2c44Sab { 1783d29b2c44Sab return (cmd_body(DYN_CMD_T_FLAGS1, obj_state, argc, argv)); 1784d29b2c44Sab } 1785d29b2c44Sab 1786d29b2c44Sab static elfedit_cmdret_t 1787d29b2c44Sab cmd_feature1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1788d29b2c44Sab { 1789d29b2c44Sab return (cmd_body(DYN_CMD_T_FEATURE1, obj_state, argc, argv)); 1790d29b2c44Sab } 1791d29b2c44Sab 1792d29b2c44Sab static elfedit_cmdret_t 1793d29b2c44Sab cmd_checksum(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1794d29b2c44Sab { 1795d29b2c44Sab return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv)); 1796d29b2c44Sab } 1797d29b2c44Sab 1798ba2be530Sab static elfedit_cmdret_t 1799ba2be530Sab cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1800ba2be530Sab { 1801ba2be530Sab return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv)); 1802ba2be530Sab } 1803ba2be530Sab 1804d29b2c44Sab 1805d29b2c44Sab 1806d29b2c44Sab /*ARGSUSED*/ 1807d29b2c44Sab elfedit_module_t * 1808d29b2c44Sab elfedit_init(elfedit_module_version_t version) 1809d29b2c44Sab { 1810d29b2c44Sab /* For commands that only accept -o */ 1811d29b2c44Sab static elfedit_cmd_optarg_t opt_ostyle[] = { 1812d29b2c44Sab { ELFEDIT_STDOA_OPT_O, NULL, 1813d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1814d29b2c44Sab { NULL } 1815d29b2c44Sab }; 1816d29b2c44Sab 1817d29b2c44Sab /* For commands that only accept -and, -cmp, -o, -or */ 1818d29b2c44Sab static elfedit_cmd_optarg_t opt_ostyle_bitop[] = { 1819d29b2c44Sab { ELFEDIT_STDOA_OPT_AND, NULL, 1820d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 1821d29b2c44Sab { ELFEDIT_STDOA_OPT_CMP, NULL, 1822d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 1823d29b2c44Sab { ELFEDIT_STDOA_OPT_O, NULL, 1824d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1825d29b2c44Sab { ELFEDIT_STDOA_OPT_OR, NULL, 1826d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 1827d29b2c44Sab { NULL } 1828d29b2c44Sab }; 1829d29b2c44Sab 1830d29b2c44Sab /* For commands that only accept -dynndx */ 1831d29b2c44Sab static elfedit_cmd_optarg_t opt_minus_dynndx[] = { 1832d29b2c44Sab { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 183355ef6355Sab /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 183455ef6355Sab ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 183555ef6355Sab DYN_OPT_F_DYNNDX_ELT, 0 }, 1836d29b2c44Sab { NULL } 1837d29b2c44Sab }; 1838d29b2c44Sab 1839d29b2c44Sab /* dyn:dump */ 1840d29b2c44Sab static const char *name_dump[] = { 1841d29b2c44Sab MSG_ORIG(MSG_CMD_DUMP), 1842d29b2c44Sab MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 1843d29b2c44Sab NULL 1844d29b2c44Sab }; 1845d29b2c44Sab static elfedit_cmd_optarg_t arg_dump[] = { 1846d29b2c44Sab { MSG_ORIG(MSG_STR_ELT), 1847d29b2c44Sab /* MSG_INTL(MSG_ARGDESC_ELT) */ 1848d29b2c44Sab ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 1849d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1850d29b2c44Sab { NULL } 1851d29b2c44Sab }; 1852d29b2c44Sab 1853d29b2c44Sab 1854d29b2c44Sab /* dyn:tag */ 1855d29b2c44Sab static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL }; 1856d29b2c44Sab static elfedit_cmd_optarg_t opt_tag[] = { 1857d29b2c44Sab { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 185855ef6355Sab /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 185955ef6355Sab ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 186055ef6355Sab DYN_OPT_F_DYNNDX_ELT, 0 }, 1861d29b2c44Sab { ELFEDIT_STDOA_OPT_O, NULL, 1862d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1863d29b2c44Sab { NULL } 1864d29b2c44Sab }; 1865d29b2c44Sab static elfedit_cmd_optarg_t arg_tag[] = { 1866d29b2c44Sab { MSG_ORIG(MSG_STR_ELT), 1867d29b2c44Sab /* MSG_INTL(MSG_A1_TAG_ELT) */ 1868d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_TAG_ELT), 1869d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1870d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 1871d29b2c44Sab /* MSG_INTL(MSG_A2_TAG_VALUE) */ 1872d29b2c44Sab ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE), 1873d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1874d29b2c44Sab { NULL } 1875d29b2c44Sab }; 1876d29b2c44Sab 1877d29b2c44Sab 1878d29b2c44Sab /* dyn:value */ 1879d29b2c44Sab static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL }; 1880d29b2c44Sab static elfedit_cmd_optarg_t opt_value[] = { 1881d29b2c44Sab { MSG_ORIG(MSG_STR_MINUS_ADD), 1882d29b2c44Sab /* MSG_INTL(MSG_OPTDESC_ADD) */ 1883d29b2c44Sab ELFEDIT_I18NHDL(MSG_OPTDESC_ADD), 0, 188455ef6355Sab DYN_OPT_F_ADD, DYN_OPT_F_DYNNDX_ELT }, 1885d29b2c44Sab { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 188655ef6355Sab /* MSG_INTL(MSG_OPTDESC_DYNNDX_ELT) */ 188755ef6355Sab ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0, 188855ef6355Sab DYN_OPT_F_DYNNDX_ELT, DYN_OPT_F_ADD }, 1889d29b2c44Sab { ELFEDIT_STDOA_OPT_O, NULL, 1890d29b2c44Sab ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1891d29b2c44Sab { MSG_ORIG(MSG_STR_MINUS_S), 1892d29b2c44Sab /* MSG_INTL(MSG_OPTDESC_S) */ 1893d29b2c44Sab ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0, 1894d29b2c44Sab DYN_OPT_F_STRVAL, 0 }, 1895d29b2c44Sab { NULL } 1896d29b2c44Sab }; 1897d29b2c44Sab static elfedit_cmd_optarg_t arg_value[] = { 1898d29b2c44Sab { MSG_ORIG(MSG_STR_ELT), 1899d29b2c44Sab /* MSG_INTL(MSG_ARGDESC_ELT) */ 1900d29b2c44Sab ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 1901d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1902d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 1903d29b2c44Sab /* MSG_INTL(MSG_A2_VALUE_VALUE) */ 1904d29b2c44Sab ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE), 1905d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1906d29b2c44Sab { NULL } 1907d29b2c44Sab }; 1908d29b2c44Sab 1909d29b2c44Sab /* dyn:delete */ 1910d29b2c44Sab static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL }; 1911d29b2c44Sab static elfedit_cmd_optarg_t arg_delete[] = { 1912d29b2c44Sab { MSG_ORIG(MSG_STR_ELT), 1913d29b2c44Sab /* MSG_INTL(MSG_ARGDESC_ELT) */ 1914d29b2c44Sab ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 1915d29b2c44Sab 0 }, 1916d29b2c44Sab { MSG_ORIG(MSG_STR_COUNT), 1917d29b2c44Sab /* MSG_INTL(MSG_A2_DELETE_COUNT) */ 1918d29b2c44Sab ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT), 1919d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1920d29b2c44Sab { NULL } 1921d29b2c44Sab }; 1922d29b2c44Sab 1923d29b2c44Sab /* dyn:move */ 1924d29b2c44Sab static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL }; 1925d29b2c44Sab static elfedit_cmd_optarg_t arg_move[] = { 1926d29b2c44Sab { MSG_ORIG(MSG_STR_ELT), 1927d29b2c44Sab /* MSG_INTL(MSG_ARGDESC_ELT) */ 1928d29b2c44Sab ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 1929d29b2c44Sab 0 }, 1930d29b2c44Sab { MSG_ORIG(MSG_STR_DST_INDEX), 1931d29b2c44Sab /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */ 1932d29b2c44Sab ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX), 1933d29b2c44Sab 0 }, 1934d29b2c44Sab { MSG_ORIG(MSG_STR_COUNT), 1935d29b2c44Sab /* MSG_INTL(MSG_A3_MOVE_COUNT) */ 1936d29b2c44Sab ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT), 1937d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1938d29b2c44Sab { NULL } 1939d29b2c44Sab }; 1940d29b2c44Sab 1941d29b2c44Sab /* dyn:runpath / dyn:rpath */ 1942d29b2c44Sab static const char *name_runpath[] = { MSG_ORIG(MSG_CMD_RUNPATH), 1943d29b2c44Sab MSG_ORIG(MSG_CMD_RUNPATH_A1), NULL }; 1944d29b2c44Sab static elfedit_cmd_optarg_t arg_runpath[] = { 1945d29b2c44Sab { MSG_ORIG(MSG_STR_NEWPATH), 1946d29b2c44Sab /* MSG_INTL(MSG_A1_RUNPATH_NEWPATH) */ 1947d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_RUNPATH_NEWPATH), 1948d29b2c44Sab ELFEDIT_CMDOA_F_OPT }, 1949d29b2c44Sab { NULL } 1950d29b2c44Sab }; 1951d29b2c44Sab 1952d29b2c44Sab /* dyn:posflag1 */ 1953d29b2c44Sab static const char *name_posflag1[] = { MSG_ORIG(MSG_CMD_POSFLAG1), 1954d29b2c44Sab NULL }; 195555ef6355Sab static elfedit_cmd_optarg_t opt_posflag1[] = { 195655ef6355Sab { ELFEDIT_STDOA_OPT_AND, NULL, 195755ef6355Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR }, 195855ef6355Sab { ELFEDIT_STDOA_OPT_CMP, NULL, 195955ef6355Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 }, 196055ef6355Sab { MSG_ORIG(MSG_STR_MINUS_DYNNDX), 196155ef6355Sab /* MSG_INTL(MSG_OPTDESC_DYNNDX_VAL) */ 196255ef6355Sab ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_VAL), 196355ef6355Sab ELFEDIT_CMDOA_F_VALUE, 196455ef6355Sab DYN_OPT_F_DYNNDX_VAL, DYN_OPT_F_NEEDED }, 196555ef6355Sab { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 196655ef6355Sab { MSG_ORIG(MSG_STR_MINUS_NEEDED), 196755ef6355Sab /* MSG_INTL(MSG_OPTDESC_NEEDED) */ 196855ef6355Sab ELFEDIT_I18NHDL(MSG_OPTDESC_NEEDED), 196955ef6355Sab ELFEDIT_CMDOA_F_VALUE, 197055ef6355Sab DYN_OPT_F_NEEDED, DYN_OPT_F_DYNNDX_VAL }, 197155ef6355Sab { MSG_ORIG(MSG_STR_PREFIX), NULL, 0, 0 }, 197255ef6355Sab { ELFEDIT_STDOA_OPT_O, NULL, 197355ef6355Sab ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 197455ef6355Sab { ELFEDIT_STDOA_OPT_OR, NULL, 197555ef6355Sab ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND }, 197655ef6355Sab { NULL } 197755ef6355Sab }; 1978d29b2c44Sab static elfedit_cmd_optarg_t arg_posflag1[] = { 1979d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 1980d29b2c44Sab /* MSG_INTL(MSG_A1_POSFLAG1_VALUE) */ 1981d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_POSFLAG1_VALUE), 1982d29b2c44Sab ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 1983d29b2c44Sab { NULL } 1984d29b2c44Sab }; 1985d29b2c44Sab 1986d29b2c44Sab /* dyn:flags */ 1987d29b2c44Sab static const char *name_flags[] = { MSG_ORIG(MSG_CMD_FLAGS), NULL }; 1988d29b2c44Sab static elfedit_cmd_optarg_t arg_flags[] = { 1989d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 1990d29b2c44Sab /* MSG_INTL(MSG_A1_FLAGS_VALUE) */ 1991d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_FLAGS_VALUE), 1992d29b2c44Sab ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 1993d29b2c44Sab { NULL } 1994d29b2c44Sab }; 1995d29b2c44Sab 1996d29b2c44Sab /* dyn:flags1 */ 1997d29b2c44Sab static const char *name_flags1[] = { MSG_ORIG(MSG_CMD_FLAGS1), NULL }; 1998d29b2c44Sab static elfedit_cmd_optarg_t arg_flags1[] = { 1999d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 2000d29b2c44Sab /* MSG_INTL(MSG_A1_FLAGS1_VALUE) */ 2001d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_FLAGS1_VALUE), 2002d29b2c44Sab ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 2003d29b2c44Sab { NULL } 2004d29b2c44Sab }; 2005d29b2c44Sab 2006d29b2c44Sab /* dyn:feature1 */ 2007d29b2c44Sab static const char *name_feature1[] = { MSG_ORIG(MSG_CMD_FEATURE1), 2008d29b2c44Sab NULL }; 2009d29b2c44Sab static elfedit_cmd_optarg_t arg_feature1[] = { 2010d29b2c44Sab { MSG_ORIG(MSG_STR_VALUE), 2011d29b2c44Sab /* MSG_INTL(MSG_A1_FEATURE1_VALUE) */ 2012d29b2c44Sab ELFEDIT_I18NHDL(MSG_A1_FEATURE1_VALUE), 2013d29b2c44Sab ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 2014d29b2c44Sab { NULL } 2015d29b2c44Sab }; 2016d29b2c44Sab 2017d29b2c44Sab /* dyn:checksum */ 2018d29b2c44Sab static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM), 2019d29b2c44Sab NULL }; 2020d29b2c44Sab 2021ba2be530Sab /* dyn:sunw_ldmach */ 2022ba2be530Sab static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH), 2023ba2be530Sab NULL }; 2024ba2be530Sab static elfedit_cmd_optarg_t arg_sunw_ldmach[] = { 2025ba2be530Sab { MSG_ORIG(MSG_STR_VALUE), 2026ba2be530Sab /* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */ 2027ba2be530Sab ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE), 2028ba2be530Sab ELFEDIT_CMDOA_F_OPT }, 2029ba2be530Sab { NULL } 2030ba2be530Sab }; 2031ba2be530Sab 2032d29b2c44Sab 2033d29b2c44Sab 2034d29b2c44Sab static elfedit_cmd_t cmds[] = { 2035d29b2c44Sab /* dyn:dump */ 2036d29b2c44Sab { cmd_dump, cpl_eltarg, name_dump, 2037d29b2c44Sab /* MSG_INTL(MSG_DESC_DUMP) */ 2038d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_DUMP), 2039d29b2c44Sab /* MSG_INTL(MSG_HELP_DUMP) */ 2040d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_DUMP), 2041d29b2c44Sab opt_minus_dynndx, arg_dump }, 2042d29b2c44Sab 2043d29b2c44Sab /* dyn:tag */ 2044d29b2c44Sab { cmd_tag, cpl_tag, name_tag, 2045d29b2c44Sab /* MSG_INTL(MSG_DESC_TAG) */ 2046d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_TAG), 2047d29b2c44Sab /* MSG_INTL(MSG_HELP_TAG) */ 2048d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_TAG), 2049d29b2c44Sab opt_tag, arg_tag }, 2050d29b2c44Sab 2051d29b2c44Sab /* dyn:value */ 2052d29b2c44Sab { cmd_value, cpl_eltarg, name_value, 2053d29b2c44Sab /* MSG_INTL(MSG_DESC_VALUE) */ 2054d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_VALUE), 2055d29b2c44Sab /* MSG_INTL(MSG_HELP_VALUE) */ 2056d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_VALUE), 2057d29b2c44Sab opt_value, arg_value }, 2058d29b2c44Sab 2059d29b2c44Sab /* dyn:delete */ 2060d29b2c44Sab { cmd_delete, cpl_eltarg, name_delete, 2061d29b2c44Sab /* MSG_INTL(MSG_DESC_DELETE) */ 2062d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_DELETE), 2063d29b2c44Sab /* MSG_INTL(MSG_HELP_DELETE) */ 2064d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_DELETE), 2065d29b2c44Sab opt_minus_dynndx, arg_delete }, 2066d29b2c44Sab 2067d29b2c44Sab /* dyn:move */ 2068d29b2c44Sab { cmd_move, cpl_eltarg, name_move, 2069d29b2c44Sab /* MSG_INTL(MSG_DESC_MOVE) */ 2070d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_MOVE), 2071d29b2c44Sab /* MSG_INTL(MSG_HELP_MOVE) */ 2072d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_MOVE), 2073d29b2c44Sab opt_minus_dynndx, arg_move }, 2074d29b2c44Sab 2075d29b2c44Sab /* dyn:runpath */ 2076d29b2c44Sab { cmd_runpath, NULL, name_runpath, 2077d29b2c44Sab /* MSG_INTL(MSG_DESC_RUNPATH) */ 2078d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_RUNPATH), 2079d29b2c44Sab /* MSG_INTL(MSG_HELP_RUNPATH) */ 2080d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_RUNPATH), 2081d29b2c44Sab opt_ostyle, arg_runpath }, 2082d29b2c44Sab 2083d29b2c44Sab /* dyn:posflag1 */ 2084d29b2c44Sab { cmd_posflag1, cpl_posflag1, name_posflag1, 2085d29b2c44Sab /* MSG_INTL(MSG_DESC_POSFLAG1) */ 2086d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_POSFLAG1), 2087d29b2c44Sab /* MSG_INTL(MSG_HELP_POSFLAG1) */ 2088d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_POSFLAG1), 208955ef6355Sab opt_posflag1, arg_posflag1 }, 2090d29b2c44Sab 2091d29b2c44Sab /* dyn:flags */ 2092d29b2c44Sab { cmd_flags, cpl_flags, name_flags, 2093d29b2c44Sab /* MSG_INTL(MSG_DESC_FLAGS) */ 2094d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_FLAGS), 2095d29b2c44Sab /* MSG_INTL(MSG_HELP_FLAGS) */ 2096d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_FLAGS), 2097d29b2c44Sab opt_ostyle_bitop, arg_flags }, 2098d29b2c44Sab 2099d29b2c44Sab /* dyn:flags1 */ 2100d29b2c44Sab { cmd_flags1, cpl_flags1, name_flags1, 2101d29b2c44Sab /* MSG_INTL(MSG_DESC_FLAGS1) */ 2102d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_FLAGS1), 2103d29b2c44Sab /* MSG_INTL(MSG_HELP_FLAGS1) */ 2104d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_FLAGS1), 2105d29b2c44Sab opt_ostyle_bitop, arg_flags1 }, 2106d29b2c44Sab 2107d29b2c44Sab /* dyn:feature1 */ 2108d29b2c44Sab { cmd_feature1, cpl_feature1, name_feature1, 2109d29b2c44Sab /* MSG_INTL(MSG_DESC_FEATURE1) */ 2110d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_FEATURE1), 2111d29b2c44Sab /* MSG_INTL(MSG_HELP_FEATURE1) */ 2112d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_FEATURE1), 2113d29b2c44Sab opt_ostyle_bitop, arg_feature1 }, 2114d29b2c44Sab 2115d29b2c44Sab /* dyn:checksum */ 2116d29b2c44Sab { cmd_checksum, NULL, name_checksum, 2117d29b2c44Sab /* MSG_INTL(MSG_DESC_CHECKSUM) */ 2118d29b2c44Sab ELFEDIT_I18NHDL(MSG_DESC_CHECKSUM), 2119d29b2c44Sab /* MSG_INTL(MSG_HELP_CHECKSUM) */ 2120d29b2c44Sab ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM), 2121d29b2c44Sab NULL, NULL }, 2122d29b2c44Sab 2123ba2be530Sab /* dyn:sunw_ldmach */ 2124ba2be530Sab { cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach, 2125ba2be530Sab /* MSG_INTL(MSG_DESC_SUNW_LDMACH) */ 2126ba2be530Sab ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH), 2127ba2be530Sab /* MSG_INTL(MSG_HELP_SUNW_LDMACH) */ 2128ba2be530Sab ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH), 2129ba2be530Sab opt_ostyle, arg_sunw_ldmach }, 2130ba2be530Sab 2131d29b2c44Sab { NULL } 2132d29b2c44Sab }; 2133d29b2c44Sab 2134d29b2c44Sab static elfedit_module_t module = { 2135d29b2c44Sab ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 2136d29b2c44Sab /* MSG_INTL(MSG_MOD_DESC) */ 2137d29b2c44Sab ELFEDIT_I18NHDL(MSG_MOD_DESC), cmds, mod_i18nhdl_to_str }; 2138d29b2c44Sab 2139d29b2c44Sab return (&module); 2140d29b2c44Sab } 2141