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