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