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