1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <elfedit.h> 28 #include <strings.h> 29 #include <conv.h> 30 #include <debug.h> 31 #include <phdr_msg.h> 32 33 34 /* 35 * Program headers 36 */ 37 38 39 40 /* 41 * This module uses shared code for several of the commands. 42 * It is sometimes necessary to know which specific command 43 * is active. 44 */ 45 typedef enum { 46 /* Dump command, used as module default to display dynamic section */ 47 PHDR_CMD_T_DUMP = 0, /* phdr:dump */ 48 49 /* Commands that correspond directly to program header fields */ 50 PHDR_CMD_T_P_TYPE = 1, /* phdr:p_type */ 51 PHDR_CMD_T_P_OFFSET = 2, /* phdr:p_offset */ 52 PHDR_CMD_T_P_VADDR = 3, /* phdr:p_vaddr */ 53 PHDR_CMD_T_P_PADDR = 4, /* phdr:p_paddr */ 54 PHDR_CMD_T_P_FILESZ = 5, /* phdr:p_filesz */ 55 PHDR_CMD_T_P_MEMSZ = 6, /* phdr:p_memsz */ 56 PHDR_CMD_T_P_FLAGS = 7, /* phdr:p_flags */ 57 PHDR_CMD_T_P_ALIGN = 8, /* phdr:p_align */ 58 59 /* Commands that do not correspond directly to a specific phdr tag */ 60 PHDR_CMD_T_INTERP = 9, /* phdr:interp */ 61 PHDR_CMD_T_DELETE = 10, /* phdr:delete */ 62 PHDR_CMD_T_MOVE = 11 /* phdr:move */ 63 } PHDR_CMD_T; 64 65 66 67 /* 68 * The following type is ued by locate_interp() to return 69 * information about the interpreter program header. 70 */ 71 typedef struct { 72 Word phndx; /* Index of PT_INTERP header */ 73 Phdr *phdr; /* PT_INTERP header */ 74 elfedit_section_t *sec; /* Section containing string */ 75 Word stroff; /* Offset into string section */ 76 const char *str; /* Interpreter string */ 77 } INTERP_STATE; 78 79 80 #ifndef _ELF64 81 /* 82 * We supply this function for the msg module 83 */ 84 const char * 85 _phdr_msg(Msg mid) 86 { 87 return (gettext(MSG_ORIG(mid))); 88 } 89 #endif 90 91 92 /* 93 * This function is supplied to elfedit through our elfedit_module_t 94 * definition. It translates the opaque elfedit_i18nhdl_t handles 95 * in our module interface into the actual strings for elfedit to 96 * use. 97 * 98 * note: 99 * This module uses Msg codes for its i18n handle type. 100 * So the translation is simply to use MSG_INTL() to turn 101 * it into a string and return it. 102 */ 103 static const char * 104 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 105 { 106 Msg msg = (Msg)hdl; 107 108 return (MSG_INTL(msg)); 109 } 110 111 112 113 /* 114 * The phdr_opt_t enum specifies a bit value for every optional 115 * argument allowed by a command in this module. 116 */ 117 typedef enum { 118 PHDR_OPT_F_AND = 1, /* -and: AND (&) values to dest */ 119 PHDR_OPT_F_CMP = 2, /* -cmp: Complement (~) values */ 120 PHDR_OPT_F_PHNDX = 4, /* -phndx: Program header by index, */ 121 /* not by name */ 122 PHDR_OPT_F_OR = 8 /* -or: OR (|) values to dest */ 123 } phdr_opt_t; 124 125 126 /* 127 * A variable of type ARGSTATE is used by each command to maintain 128 * information about the section headers and related things. It is 129 * initialized by process_args(), and used by the other routines. 130 */ 131 typedef struct { 132 elfedit_obj_state_t *obj_state; 133 phdr_opt_t optmask; /* Mask of options used */ 134 int argc; /* # of plain arguments */ 135 const char **argv; /* Plain arguments */ 136 int ndx_set; /* True if ndx is valid */ 137 Word ndx; /* Index of header if cmd */ 138 /* accepts it */ 139 int print_req; /* Call is a print request */ 140 } ARGSTATE; 141 142 143 /* 144 * Standard argument processing for phdr module 145 * 146 * entry 147 * obj_state, argc, argv - Standard command arguments 148 * optmask - Mask of allowed optional arguments. 149 * cmd - PHDR_CMD_T_* value giving identify of caller 150 * argstate - Address of ARGSTATE block to be initialized 151 * 152 * exit: 153 * On success, *argstate is initialized. On error, 154 * an error is issued and this routine does not return. 155 */ 156 static void 157 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 158 PHDR_CMD_T cmd, ARGSTATE *argstate) 159 { 160 elfedit_getopt_state_t getopt_state; 161 elfedit_getopt_ret_t *getopt_ret; 162 163 bzero(argstate, sizeof (*argstate)); 164 argstate->obj_state = obj_state; 165 166 elfedit_getopt_init(&getopt_state, &argc, &argv); 167 168 /* Add each new option to the options mask */ 169 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) 170 argstate->optmask |= getopt_ret->gor_idmask; 171 172 /* Are the right number of plain arguments present? */ 173 switch (cmd) { 174 case PHDR_CMD_T_DUMP: 175 if (argc > 1) 176 elfedit_command_usage(); 177 argstate->print_req = 1; 178 break; 179 case PHDR_CMD_T_P_FLAGS: 180 /* phdr:sh_flags allows an arbitrary number of arguments */ 181 argstate->print_req = (argc < 2); 182 break; 183 case PHDR_CMD_T_INTERP: 184 if (argc > 1) 185 elfedit_command_usage(); 186 argstate->print_req = (argc == 0); 187 break; 188 case PHDR_CMD_T_DELETE: 189 if ((argc < 1) || (argc > 2)) 190 elfedit_command_usage(); 191 argstate->print_req = 0; 192 break; 193 case PHDR_CMD_T_MOVE: 194 if ((argc < 2) || (argc > 3)) 195 elfedit_command_usage(); 196 argstate->print_req = 0; 197 break; 198 199 default: 200 /* The remaining commands accept 2 plain arguments */ 201 if (argc > 2) 202 elfedit_command_usage(); 203 argstate->print_req = (argc < 2); 204 break; 205 } 206 207 /* Return the updated values of argc/argv */ 208 argstate->argc = argc; 209 argstate->argv = argv; 210 211 argstate->ndx_set = 0; 212 if ((argc > 0) && (cmd != PHDR_CMD_T_INTERP)) { 213 /* 214 * If the -phndx option is present, the first argument is 215 * the index of the header to use. Otherwise, it is a 216 * name corresponding to its type, similar to the way 217 * elfdump works with its -N option. 218 */ 219 if (argstate->optmask & PHDR_OPT_F_PHNDX) { 220 argstate->ndx = (Word) elfedit_atoui_range( 221 argstate->argv[0], MSG_ORIG(MSG_STR_ELEMENT), 0, 222 argstate->obj_state->os_phnum - 1, NULL); 223 argstate->ndx_set = 1; 224 } else { 225 Conv_inv_buf_t inv_buf; 226 Ehdr *ehdr = obj_state->os_ehdr; 227 Half mach = ehdr->e_machine; 228 uchar_t osabi = ehdr->e_ident[EI_OSABI]; 229 Word i; 230 Phdr *phdr; 231 232 argstate->ndx = (Word) elfedit_atoconst( 233 argstate->argv[0], ELFEDIT_CONST_PT); 234 phdr = obj_state->os_phdr; 235 for (i = 0; i < obj_state->os_phnum; i++, phdr++) { 236 if (phdr->p_type == argstate->ndx) { 237 argstate->ndx = i; 238 argstate->ndx_set = 1; 239 elfedit_msg(ELFEDIT_MSG_DEBUG, 240 MSG_INTL(MSG_DEBUG_PHDR), 241 EC_WORD(i), conv_phdr_type(osabi, 242 mach, phdr->p_type, 0, &inv_buf)); 243 break; 244 } 245 } 246 if (i == argstate->obj_state->os_phnum) 247 elfedit_msg(ELFEDIT_MSG_ERR, 248 MSG_INTL(MSG_ERR_NOPHDR), conv_phdr_type( 249 osabi, mach, argstate->ndx, 0, &inv_buf)); 250 } 251 } 252 253 /* If there may be an arbitrary amount of output, use a pager */ 254 if (argc == 0) 255 elfedit_pager_init(); 256 257 } 258 259 260 261 /* 262 * Locate the interpreter string for the object and related information 263 * 264 * entry: 265 * obj_state - Object state 266 * interp - NULL, or variable to be filled in with information 267 * about the interpteter string. 268 */ 269 static const char * 270 locate_interp(elfedit_obj_state_t *obj_state, INTERP_STATE *interp) 271 { 272 INTERP_STATE local_interp; 273 elfedit_section_t *strsec; /* String table */ 274 size_t phnum; /* # of program headers */ 275 int phndx; /* Index of PT_INTERP program header */ 276 Phdr *phdr; /* Program header array */ 277 Word i; 278 279 if (interp == NULL) 280 interp = &local_interp; 281 282 /* Locate the PT_INTERP program header */ 283 phnum = obj_state->os_phnum; 284 phdr = obj_state->os_phdr; 285 286 for (phndx = 0; phndx < phnum; phndx++) { 287 if (phdr[phndx].p_type == PT_INTERP) { 288 interp->phndx = phndx; 289 interp->phdr = phdr + phndx; 290 break; 291 } 292 } 293 /* If no PT_INTERP program header found, we cannot proceed */ 294 if (phndx == phnum) 295 elfedit_elferr(obj_state->os_file, 296 MSG_INTL(MSG_ERR_NOINTERPPHDR)); 297 298 /* 299 * Locate the section containing the interpteter string as well 300 * as the string itself. 301 * 302 * The program header contains a direct offset to the string, so 303 * we find the section by walking through the them looking for 304 * the one with a base and size that would contain the string. 305 * Note that this target section cannot be in a NOBITS section. 306 */ 307 for (i = 1; i < obj_state->os_shnum; i++) { 308 strsec = &obj_state->os_secarr[i]; 309 310 if ((strsec->sec_shdr->sh_type != SHT_NOBITS) && 311 (interp->phdr->p_offset >= strsec->sec_shdr->sh_offset) && 312 ((interp->phdr->p_offset + interp->phdr->p_filesz) <= 313 (strsec->sec_shdr->sh_offset + 314 strsec->sec_shdr->sh_size))) { 315 interp->sec = strsec; 316 317 interp->stroff = interp->phdr->p_offset - 318 strsec->sec_shdr->sh_offset; 319 interp->str = ((char *)strsec->sec_data->d_buf) + 320 interp->stroff; 321 return (interp->str); 322 } 323 } 324 325 /* 326 * We don't expect to get here: If there is a PT_INTERP header, 327 * we fully expect the string to exist. 328 */ 329 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOINTERPSEC)); 330 /*NOTREACHED*/ 331 332 return (NULL); /* For lint */ 333 } 334 335 /* 336 * Print program header values, taking the calling command, and output style 337 * into account. 338 * 339 * entry: 340 * autoprint - If True, output is only produced if the elfedit 341 * autoprint flag is set. If False, output is always produced. 342 * cmd - PHDR_CMD_T_* value giving identify of caller 343 * argstate - State block for section header array. The following 344 * fields are examined in order to determine the form 345 * of output: ndx_set, ndx, print_req. 346 */ 347 static void 348 print_phdr(PHDR_CMD_T cmd, int autoprint, ARGSTATE *argstate) 349 { 350 elfedit_outstyle_t outstyle; 351 Ehdr *ehdr = argstate->obj_state->os_ehdr; 352 uchar_t osabi = ehdr->e_ident[EI_OSABI]; 353 Half mach = ehdr->e_machine; 354 Word ndx, cnt, by_type, type; 355 Phdr *phdr; 356 357 if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) 358 return; 359 360 /* 361 * Determine which indexes to display: 362 * 363 * - If the user specified an index, the display starts 364 * with that item. If it was a print_request, and the 365 * index was specified by type, then all items of the 366 * same type are shown. If not a print request, or the index 367 * was given numerically, then just the single item is shown. 368 * 369 * - If no index is specified, every program header is shown. 370 */ 371 by_type = 0; 372 if (argstate->ndx_set) { 373 ndx = argstate->ndx; 374 if (argstate->print_req && 375 ((argstate->optmask & PHDR_OPT_F_PHNDX) == 0)) { 376 by_type = 1; 377 type = argstate->obj_state->os_phdr[ndx].p_type; 378 cnt = argstate->obj_state->os_phnum - ndx; 379 } else { 380 cnt = 1; 381 } 382 } else { 383 ndx = 0; 384 cnt = argstate->obj_state->os_phnum; 385 } 386 phdr = argstate->obj_state->os_phdr + ndx; 387 388 /* 389 * Pick an output style. phdr:dump is required to use the default 390 * style. The other commands use the current output style. 391 */ 392 outstyle = (cmd == PHDR_CMD_T_DUMP) ? 393 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 394 395 /* 396 * If doing default output, use elfdump style where we 397 * show all program header attributes. In this case, the 398 * command that called us doesn't matter. 399 * 400 * Exclude PHDR_CMD_T_INTERP from this: It isn't per-phdr like 401 * the other commands. 402 */ 403 if ((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) && 404 (cmd != PHDR_CMD_T_INTERP)) { 405 for (; cnt--; ndx++, phdr++) { 406 if (by_type && (type != phdr->p_type)) 407 continue; 408 409 elfedit_printf(MSG_ORIG(MSG_STR_NL)); 410 elfedit_printf(MSG_INTL(MSG_ELF_PHDR), EC_WORD(ndx)); 411 Elf_phdr(0, osabi, mach, phdr); 412 } 413 return; 414 } 415 416 if (cmd == PHDR_CMD_T_INTERP) { 417 INTERP_STATE interp; 418 419 (void) locate_interp(argstate->obj_state, &interp); 420 switch (outstyle) { 421 case ELFEDIT_OUTSTYLE_DEFAULT: 422 elfedit_printf(MSG_INTL(MSG_FMT_ELF_INTERP), 423 interp.sec->sec_name, interp.str); 424 break; 425 case ELFEDIT_OUTSTYLE_SIMPLE: 426 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), interp.str); 427 break; 428 case ELFEDIT_OUTSTYLE_NUM: 429 elfedit_printf(MSG_ORIG(MSG_FMT_U_NL), 430 EC_WORD(interp.stroff)); 431 break; 432 } 433 return; 434 } 435 436 /* Handle the remaining commands */ 437 for (; cnt--; ndx++, phdr++) { 438 if (by_type && (type != phdr->p_type)) 439 continue; 440 441 switch (cmd) { 442 case PHDR_CMD_T_P_TYPE: 443 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 444 Conv_inv_buf_t inv_buf; 445 446 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 447 conv_phdr_type(osabi, 448 argstate->obj_state->os_ehdr->e_machine, 449 phdr->p_type, 0, &inv_buf)); 450 } else { 451 elfedit_printf(MSG_ORIG(MSG_FMT_X_NL), 452 EC_WORD(phdr->p_type)); 453 } 454 break; 455 456 case PHDR_CMD_T_P_OFFSET: 457 elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL), 458 EC_OFF(phdr->p_offset)); 459 break; 460 461 case PHDR_CMD_T_P_VADDR: 462 elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL), 463 EC_ADDR(phdr->p_vaddr)); 464 break; 465 466 case PHDR_CMD_T_P_PADDR: 467 elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL), 468 EC_ADDR(phdr->p_paddr)); 469 break; 470 471 case PHDR_CMD_T_P_FILESZ: 472 elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL), 473 EC_XWORD(phdr->p_filesz)); 474 break; 475 476 case PHDR_CMD_T_P_MEMSZ: 477 elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL), 478 EC_XWORD(phdr->p_memsz)); 479 break; 480 481 case PHDR_CMD_T_P_FLAGS: 482 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 483 Conv_phdr_flags_buf_t phdr_flags_buf; 484 485 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 486 conv_phdr_flags(osabi, phdr->p_flags, 487 CONV_FMT_NOBKT, &phdr_flags_buf)); 488 } else { 489 elfedit_printf(MSG_ORIG(MSG_FMT_X_NL), 490 EC_WORD(phdr->p_flags)); 491 } 492 break; 493 494 case PHDR_CMD_T_P_ALIGN: 495 elfedit_printf(MSG_ORIG(MSG_FMT_LLX_NL), 496 EC_XWORD(phdr->p_align)); 497 break; 498 } 499 } 500 } 501 502 503 /* 504 * Called from cmd_body() in the case where a plain argument 505 * is given to phdr:interp to change the interpreter. 506 */ 507 static elfedit_cmdret_t 508 cmd_body_set_interp(ARGSTATE *argstate) 509 { 510 elfedit_obj_state_t *obj_state = argstate->obj_state; 511 elfedit_section_t *strsec; /* String table */ 512 INTERP_STATE interp; 513 Word numdyn; /* # of elements in dyn arr */ 514 size_t phnum; /* # of program headers */ 515 Phdr *phdr; /* Program header array */ 516 Word i, j; 517 Word str_offset; /* Offset in strsec to new interp str */ 518 int str_found = 0; /* True when we have new interp str */ 519 Word str_size; /* Size of new interp string + NULL */ 520 521 phnum = obj_state->os_phnum; 522 phdr = obj_state->os_phdr; 523 524 /* Locate the PT_INTERP program header */ 525 (void) locate_interp(obj_state, &interp); 526 strsec = interp.sec; 527 str_offset = interp.stroff; 528 529 /* 530 * If the given string is the same as the existing interpreter 531 * string, say so and return. 532 */ 533 if (strcmp(interp.str, argstate->argv[0]) == 0) { 534 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_OLDINTERPOK), 535 EC_WORD(strsec->sec_shndx), strsec->sec_name, 536 EC_WORD(str_offset), interp.str); 537 return (ELFEDIT_CMDRET_NONE); 538 } 539 540 /* 541 * An ELF PT_INTERP usually references its own special section 542 * instead of some other string table. The ELF ABI says that this 543 * section must be named ".interp". Hence, this is a rare case 544 * in which the name of a section can be taken as an indication 545 * of its contents. .interp is typically sized to just fit 546 * the original string, including its NULL termination. You can 547 * treat it as a string table with one string. 548 * 549 * Thanks to 'elfedit', it may be that we encounter a file where 550 * PT_INTERP does not reference the .interp section. This will happen 551 * if elfedit is used to change the interpreter to a string that is 552 * too big to fit in .interp, in which case we will use the 553 * .dynstr string table (That code is below, in this function). 554 * 555 * Given the above facts, our next step is to locate the .interp 556 * section and see if our new string will fit in it. Since we can't 557 * depend on PT_INTERP, we search the section headers to find a 558 * section whith the following characteristics: 559 * - The name is ".interp". 560 * - Section is allocable (SHF_ALLOC) and SHT_PROGBITS. 561 * - It is not part of a writable segment. 562 * If we find such a section, and the new string fits, we will 563 * write it there. 564 */ 565 str_size = strlen(argstate->argv[0]) + 1; 566 for (i = 1; i < obj_state->os_shnum; i++) { 567 strsec = &obj_state->os_secarr[i]; 568 if ((strcmp(strsec->sec_name, MSG_ORIG(MSG_SEC_INTERP)) == 0) && 569 (strsec->sec_shdr->sh_flags & SHF_ALLOC) && 570 (strsec->sec_shdr->sh_type & SHT_PROGBITS)) { 571 for (j = 0; j < phnum; j++) { 572 Phdr *tphdr = &phdr[j]; 573 if ((strsec->sec_shdr->sh_offset >= 574 tphdr->p_offset) && 575 ((strsec->sec_shdr->sh_offset + 576 strsec->sec_shdr->sh_size) <= 577 (tphdr->p_offset + tphdr->p_filesz)) && 578 (tphdr->p_flags & PF_W)) { 579 break; 580 } 581 } 582 if ((j == phnum) && 583 (str_size <= strsec->sec_shdr->sh_size)) { 584 /* .interp section found, and has room */ 585 str_found = 1; 586 str_offset = 0; 587 elfedit_msg(ELFEDIT_MSG_DEBUG, 588 MSG_INTL(MSG_DEBUG_NEWISTR), EC_WORD(j), 589 strsec->sec_name, EC_WORD(str_offset), 590 argstate->argv[0]); 591 /* Put new value in section */ 592 (void) strncpy((char *)strsec->sec_data->d_buf, 593 argstate->argv[0], 594 strsec->sec_shdr->sh_size); 595 /* Set libelf dirty bit so change is flushed */ 596 elfedit_modified_data(strsec); 597 break; 598 } else { 599 elfedit_msg(ELFEDIT_MSG_DEBUG, 600 MSG_INTL(MSG_DEBUG_LNGISTR), EC_WORD(j), 601 strsec->sec_name, EC_WORD(str_offset), 602 EC_WORD(str_size), 603 EC_WORD(strsec->sec_shdr->sh_size), 604 argstate->argv[0]); 605 } 606 } 607 } 608 609 /* 610 * If the above did not find a string within the .interp section, 611 * then we have a second option. If this ELF object has a dynamic 612 * section, then we are willing to use strings from within the 613 * associated .dynstr string table. And if there is reserved space 614 * in .dynstr (as reported by the DT_SUNW_STRPAD dynamic entry), 615 * then we are even willing to add a new string to .dynstr. 616 */ 617 if (!str_found) { 618 elfedit_section_t *dynsec; 619 Dyn *dyn; 620 621 dynsec = elfedit_sec_getdyn(obj_state, &dyn, &numdyn); 622 strsec = elfedit_sec_getstr(obj_state, 623 dynsec->sec_shdr->sh_link, 0); 624 625 /* Does string exist in the table already, or can we add it? */ 626 str_offset = elfedit_strtab_insert(obj_state, strsec, 627 dynsec, argstate->argv[0]); 628 } 629 630 631 /* 632 * If we are here, we know we have a replacement string, because 633 * the errors from checking .dynamic/.dynstr will not allow 634 * things to get here otherwise. 635 * 636 * The PT_INTERP program header references the string directly, 637 * so we add the section offset to the string offset. 638 */ 639 interp.phdr->p_offset = strsec->sec_shdr->sh_offset + str_offset; 640 interp.phdr->p_filesz = str_size; 641 elfedit_modified_phdr(obj_state); 642 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_SETPHINTERP), 643 EC_WORD(interp.phndx), EC_XWORD(interp.phdr->p_offset), 644 EC_XWORD(interp.phdr->p_filesz)); 645 646 return (ELFEDIT_CMDRET_MOD); 647 } 648 649 650 /* 651 * Common body for the phdr: module commands. These commands 652 * share a large amount of common behavior, so it is convenient 653 * to centralize things and use the cmd argument to handle the 654 * small differences. 655 * 656 * entry: 657 * cmd - One of the PHDR_CMD_T_* constants listed above, specifying 658 * which command to implement. 659 * obj_state, argc, argv - Standard command arguments 660 */ 661 static elfedit_cmdret_t 662 cmd_body(PHDR_CMD_T cmd, elfedit_obj_state_t *obj_state, 663 int argc, const char *argv[]) 664 { 665 ARGSTATE argstate; 666 Phdr *phdr; 667 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 668 int do_autoprint = 1; 669 670 process_args(obj_state, argc, argv, cmd, &argstate); 671 672 /* If this is a printing request, print and return */ 673 if (argstate.print_req) { 674 print_phdr(cmd, 0, &argstate); 675 return (ELFEDIT_CMDRET_NONE); 676 } 677 678 679 if (argstate.ndx_set) 680 phdr = &argstate.obj_state->os_phdr[argstate.ndx]; 681 682 switch (cmd) { 683 /* 684 * PHDR_CMD_T_DUMP can't get here: It never has more than 685 * one argument, and is handled above. 686 */ 687 688 case PHDR_CMD_T_P_TYPE: 689 { 690 Ehdr *ehdr = obj_state->os_ehdr; 691 uchar_t osabi = ehdr->e_ident[EI_OSABI]; 692 Half mach = ehdr->e_machine; 693 Word p_type = elfedit_atoconst(argstate.argv[1], 694 ELFEDIT_CONST_PT); 695 Conv_inv_buf_t inv_buf1, inv_buf2; 696 697 if (phdr->p_type == p_type) { 698 elfedit_msg(ELFEDIT_MSG_DEBUG, 699 MSG_INTL(MSG_DEBUG_S_OK), 700 argstate.ndx, MSG_ORIG(MSG_CMD_P_TYPE), 701 conv_phdr_type(osabi, mach, phdr->p_type, 702 0, &inv_buf1)); 703 } else { 704 elfedit_msg(ELFEDIT_MSG_DEBUG, 705 MSG_INTL(MSG_DEBUG_S_CHG), 706 argstate.ndx, MSG_ORIG(MSG_CMD_P_TYPE), 707 conv_phdr_type(osabi, mach, 708 phdr->p_type, 0, &inv_buf1), 709 conv_phdr_type(osabi, mach, 710 p_type, 0, &inv_buf2)); 711 ret = ELFEDIT_CMDRET_MOD; 712 phdr->p_type = p_type; 713 } 714 } 715 break; 716 717 case PHDR_CMD_T_P_OFFSET: 718 { 719 Off p_offset; 720 721 p_offset = elfedit_atoui(argstate.argv[1], NULL); 722 if (phdr->p_offset == p_offset) { 723 elfedit_msg(ELFEDIT_MSG_DEBUG, 724 MSG_INTL(MSG_DEBUG_LLX_OK), 725 argstate.ndx, MSG_ORIG(MSG_CMD_P_OFFSET), 726 EC_XWORD(phdr->p_offset)); 727 } else { 728 elfedit_msg(ELFEDIT_MSG_DEBUG, 729 MSG_INTL(MSG_DEBUG_LLX_CHG), 730 argstate.ndx, MSG_ORIG(MSG_CMD_P_OFFSET), 731 EC_XWORD(phdr->p_offset), 732 EC_XWORD(p_offset)); 733 ret = ELFEDIT_CMDRET_MOD; 734 phdr->p_offset = p_offset; 735 } 736 } 737 break; 738 739 case PHDR_CMD_T_P_VADDR: 740 { 741 Addr p_vaddr = elfedit_atoui(argstate.argv[1], NULL); 742 743 if (phdr->p_vaddr == p_vaddr) { 744 elfedit_msg(ELFEDIT_MSG_DEBUG, 745 MSG_INTL(MSG_DEBUG_LLX_OK), 746 argstate.ndx, MSG_ORIG(MSG_CMD_P_VADDR), 747 EC_ADDR(phdr->p_vaddr)); 748 } else { 749 elfedit_msg(ELFEDIT_MSG_DEBUG, 750 MSG_INTL(MSG_DEBUG_LLX_CHG), 751 argstate.ndx, MSG_ORIG(MSG_CMD_P_VADDR), 752 EC_ADDR(phdr->p_vaddr), EC_ADDR(p_vaddr)); 753 ret = ELFEDIT_CMDRET_MOD; 754 phdr->p_vaddr = p_vaddr; 755 } 756 } 757 break; 758 759 case PHDR_CMD_T_P_PADDR: 760 { 761 Addr p_paddr = elfedit_atoui(argstate.argv[1], NULL); 762 763 if (phdr->p_paddr == p_paddr) { 764 elfedit_msg(ELFEDIT_MSG_DEBUG, 765 MSG_INTL(MSG_DEBUG_LLX_OK), 766 argstate.ndx, MSG_ORIG(MSG_CMD_P_PADDR), 767 EC_ADDR(phdr->p_paddr)); 768 } else { 769 elfedit_msg(ELFEDIT_MSG_DEBUG, 770 MSG_INTL(MSG_DEBUG_LLX_CHG), 771 argstate.ndx, MSG_ORIG(MSG_CMD_P_PADDR), 772 EC_ADDR(phdr->p_paddr), EC_ADDR(p_paddr)); 773 ret = ELFEDIT_CMDRET_MOD; 774 phdr->p_paddr = p_paddr; 775 } 776 } 777 break; 778 779 case PHDR_CMD_T_P_FILESZ: 780 { 781 Xword p_filesz = elfedit_atoui(argstate.argv[1], NULL); 782 783 if (phdr->p_filesz == p_filesz) { 784 elfedit_msg(ELFEDIT_MSG_DEBUG, 785 MSG_INTL(MSG_DEBUG_LLX_OK), 786 argstate.ndx, MSG_ORIG(MSG_CMD_P_FILESZ), 787 EC_XWORD(phdr->p_filesz)); 788 } else { 789 elfedit_msg(ELFEDIT_MSG_DEBUG, 790 MSG_INTL(MSG_DEBUG_LLX_CHG), 791 argstate.ndx, MSG_ORIG(MSG_CMD_P_FILESZ), 792 EC_XWORD(phdr->p_filesz), 793 EC_XWORD(p_filesz)); 794 ret = ELFEDIT_CMDRET_MOD; 795 phdr->p_filesz = p_filesz; 796 } 797 } 798 break; 799 800 case PHDR_CMD_T_P_MEMSZ: 801 { 802 Xword p_memsz = elfedit_atoui(argstate.argv[1], NULL); 803 804 if (phdr->p_memsz == p_memsz) { 805 elfedit_msg(ELFEDIT_MSG_DEBUG, 806 MSG_INTL(MSG_DEBUG_LLX_OK), 807 argstate.ndx, MSG_ORIG(MSG_CMD_P_MEMSZ), 808 EC_XWORD(phdr->p_memsz)); 809 } else { 810 elfedit_msg(ELFEDIT_MSG_DEBUG, 811 MSG_INTL(MSG_DEBUG_LLX_CHG), 812 argstate.ndx, MSG_ORIG(MSG_CMD_P_MEMSZ), 813 EC_XWORD(phdr->p_memsz), 814 EC_XWORD(p_memsz)); 815 ret = ELFEDIT_CMDRET_MOD; 816 phdr->p_memsz = p_memsz; 817 } 818 } 819 break; 820 821 case PHDR_CMD_T_P_FLAGS: 822 { 823 Ehdr *ehdr = obj_state->os_ehdr; 824 uchar_t osabi = ehdr->e_ident[EI_OSABI]; 825 Conv_phdr_flags_buf_t buf1, buf2; 826 Word p_flags = 0; 827 int i; 828 829 /* Collect the flag arguments */ 830 for (i = 1; i < argstate.argc; i++) 831 p_flags |= 832 (Word) elfedit_atoconst(argstate.argv[i], 833 ELFEDIT_CONST_PF); 834 835 /* Complement the value? */ 836 if (argstate.optmask & PHDR_OPT_F_CMP) 837 p_flags = ~p_flags; 838 839 /* Perform any requested bit operations */ 840 if (argstate.optmask & PHDR_OPT_F_AND) 841 p_flags &= phdr->p_flags; 842 else if (argstate.optmask & PHDR_OPT_F_OR) 843 p_flags |= phdr->p_flags; 844 845 /* Set the value */ 846 if (phdr->p_flags == p_flags) { 847 elfedit_msg(ELFEDIT_MSG_DEBUG, 848 MSG_INTL(MSG_DEBUG_S_OK), 849 argstate.ndx, MSG_ORIG(MSG_CMD_P_FLAGS), 850 conv_phdr_flags(osabi, phdr->p_flags, 851 0, &buf1)); 852 } else { 853 elfedit_msg(ELFEDIT_MSG_DEBUG, 854 MSG_INTL(MSG_DEBUG_S_CHG), 855 argstate.ndx, MSG_ORIG(MSG_CMD_P_FLAGS), 856 conv_phdr_flags(osabi, phdr->p_flags, 857 0, &buf1), 858 conv_phdr_flags(osabi, p_flags, 0, &buf2)); 859 ret = ELFEDIT_CMDRET_MOD; 860 phdr->p_flags = p_flags; 861 } 862 } 863 break; 864 865 case PHDR_CMD_T_P_ALIGN: 866 { 867 Xword p_align = elfedit_atoui(argstate.argv[1], NULL); 868 869 if (phdr->p_align == p_align) { 870 elfedit_msg(ELFEDIT_MSG_DEBUG, 871 MSG_INTL(MSG_DEBUG_LLX_OK), 872 argstate.ndx, MSG_ORIG(MSG_CMD_P_ALIGN), 873 EC_XWORD(phdr->p_align)); 874 } else { 875 elfedit_msg(ELFEDIT_MSG_DEBUG, 876 MSG_INTL(MSG_DEBUG_LLX_CHG), 877 argstate.ndx, MSG_ORIG(MSG_CMD_P_ALIGN), 878 EC_XWORD(phdr->p_align), 879 EC_XWORD(p_align)); 880 ret = ELFEDIT_CMDRET_MOD; 881 phdr->p_align = p_align; 882 } 883 } 884 break; 885 886 case PHDR_CMD_T_INTERP: 887 ret = cmd_body_set_interp(&argstate); 888 break; 889 890 case PHDR_CMD_T_DELETE: 891 { 892 Word cnt = (argstate.argc == 1) ? 1 : 893 (Word) elfedit_atoui_range(argstate.argv[1], 894 MSG_ORIG(MSG_STR_COUNT), 1, 895 obj_state->os_phnum - argstate.ndx, NULL); 896 897 elfedit_array_elts_delete(MSG_ORIG(MSG_MOD_NAME), 898 obj_state->os_phdr, sizeof (Phdr), 899 obj_state->os_phnum, argstate.ndx, cnt); 900 do_autoprint = 0; 901 ret = ELFEDIT_CMDRET_MOD; 902 } 903 break; 904 905 case PHDR_CMD_T_MOVE: 906 { 907 Phdr save; 908 Word cnt; 909 Word dstndx; 910 911 do_autoprint = 0; 912 dstndx = (Word) 913 elfedit_atoui_range(argstate.argv[1], 914 MSG_ORIG(MSG_STR_DST_INDEX), 0, 915 obj_state->os_phnum - 1, NULL); 916 if (argstate.argc == 2) { 917 cnt = 1; 918 } else { 919 cnt = (Word) elfedit_atoui_range( 920 argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), 921 1, obj_state->os_phnum, NULL); 922 } 923 elfedit_array_elts_move(MSG_ORIG(MSG_MOD_NAME), 924 obj_state->os_phdr, sizeof (save), 925 obj_state->os_phnum, argstate.ndx, dstndx, 926 cnt, &save); 927 ret = ELFEDIT_CMDRET_MOD; 928 } 929 break; 930 } 931 932 /* 933 * If we modified the section header array, tell libelf. 934 */ 935 if (ret == ELFEDIT_CMDRET_MOD) 936 elfedit_modified_phdr(obj_state); 937 938 /* Do autoprint */ 939 if (do_autoprint) 940 print_phdr(cmd, 1, &argstate); 941 942 return (ret); 943 } 944 945 946 947 /* 948 * Command completion functions for the various commands 949 */ 950 951 /* 952 * A number of the commands accept a PT_ constant as their first 953 * argument as long as the -phndx option is not used. 954 */ 955 /*ARGSUSED*/ 956 static void 957 cpl_1starg_pt(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 958 const char *argv[], int num_opt) 959 { 960 int i; 961 962 for (i = 0; i < num_opt; i++) 963 if (strcmp(MSG_ORIG(MSG_STR_MINUS_PHNDX), argv[i]) == 0) 964 return; 965 966 if (argc == (num_opt + 1)) 967 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_PT); 968 } 969 970 /*ARGSUSED*/ 971 static void 972 cpl_p_type(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 973 const char *argv[], int num_opt) 974 { 975 /* The first argument follows the standard rules */ 976 cpl_1starg_pt(obj_state, cpldata, argc, argv, num_opt); 977 978 /* The second argument can be a PT_ value */ 979 if (argc == (num_opt + 2)) 980 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_PT); 981 } 982 983 984 /*ARGSUSED*/ 985 static void 986 cpl_p_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 987 const char *argv[], int num_opt) 988 { 989 /* The first argument follows the standard rules */ 990 cpl_1starg_pt(obj_state, cpldata, argc, argv, num_opt); 991 992 /* The second and following arguments can be an PF_ value */ 993 if (argc >= (num_opt + 2)) 994 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_PF); 995 } 996 997 998 999 /* 1000 * Implementation functions for the commands 1001 */ 1002 static elfedit_cmdret_t 1003 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1004 { 1005 return (cmd_body(PHDR_CMD_T_DUMP, obj_state, argc, argv)); 1006 } 1007 1008 static elfedit_cmdret_t 1009 cmd_p_type(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1010 { 1011 return (cmd_body(PHDR_CMD_T_P_TYPE, obj_state, argc, argv)); 1012 } 1013 1014 static elfedit_cmdret_t 1015 cmd_p_offset(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1016 { 1017 return (cmd_body(PHDR_CMD_T_P_OFFSET, obj_state, argc, argv)); 1018 } 1019 1020 static elfedit_cmdret_t 1021 cmd_p_vaddr(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1022 { 1023 return (cmd_body(PHDR_CMD_T_P_VADDR, obj_state, argc, argv)); 1024 } 1025 1026 static elfedit_cmdret_t 1027 cmd_p_paddr(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1028 { 1029 return (cmd_body(PHDR_CMD_T_P_PADDR, obj_state, argc, argv)); 1030 } 1031 1032 static elfedit_cmdret_t 1033 cmd_p_filesz(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1034 { 1035 return (cmd_body(PHDR_CMD_T_P_FILESZ, obj_state, argc, argv)); 1036 } 1037 1038 static elfedit_cmdret_t 1039 cmd_p_memsz(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1040 { 1041 return (cmd_body(PHDR_CMD_T_P_MEMSZ, obj_state, argc, argv)); 1042 } 1043 1044 static elfedit_cmdret_t 1045 cmd_p_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1046 { 1047 return (cmd_body(PHDR_CMD_T_P_FLAGS, obj_state, argc, argv)); 1048 } 1049 1050 static elfedit_cmdret_t 1051 cmd_p_align(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1052 { 1053 return (cmd_body(PHDR_CMD_T_P_ALIGN, obj_state, argc, argv)); 1054 } 1055 1056 static elfedit_cmdret_t 1057 cmd_interp(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1058 { 1059 return (cmd_body(PHDR_CMD_T_INTERP, obj_state, argc, argv)); 1060 } 1061 1062 static elfedit_cmdret_t 1063 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1064 { 1065 return (cmd_body(PHDR_CMD_T_DELETE, obj_state, argc, argv)); 1066 } 1067 1068 static elfedit_cmdret_t 1069 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1070 { 1071 return (cmd_body(PHDR_CMD_T_MOVE, obj_state, argc, argv)); 1072 } 1073 1074 1075 /*ARGSUSED*/ 1076 elfedit_module_t * 1077 elfedit_init(elfedit_module_version_t version) 1078 { 1079 /* Multiple commands accept a standard set of options */ 1080 static elfedit_cmd_optarg_t opt_std[] = { 1081 { ELFEDIT_STDOA_OPT_O, NULL, 1082 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1083 { MSG_ORIG(MSG_STR_MINUS_PHNDX), 1084 /* MSG_INTL(MSG_OPTDESC_PHNDX) */ 1085 ELFEDIT_I18NHDL(MSG_OPTDESC_PHNDX), 0, 1086 PHDR_OPT_F_PHNDX, 0 }, 1087 { NULL } 1088 }; 1089 1090 /* For commands that only accept -phndx */ 1091 static elfedit_cmd_optarg_t opt_minus_phndx[] = { 1092 { MSG_ORIG(MSG_STR_MINUS_PHNDX), 1093 /* MSG_INTL(MSG_OPTDESC_PHNDX) */ 1094 ELFEDIT_I18NHDL(MSG_OPTDESC_PHNDX), 0, 1095 PHDR_OPT_F_PHNDX, 0 }, 1096 { NULL } 1097 }; 1098 1099 1100 /* phdr:dump */ 1101 static const char *name_dump[] = { 1102 MSG_ORIG(MSG_CMD_DUMP), 1103 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 1104 NULL 1105 }; 1106 static elfedit_cmd_optarg_t arg_dump[] = { 1107 { MSG_ORIG(MSG_STR_ELEMENT), 1108 /* MSG_INTL(MSG_A1_ELEMENT) */ 1109 ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1110 ELFEDIT_CMDOA_F_OPT }, 1111 { NULL } 1112 }; 1113 1114 /* phdr:p_type */ 1115 static const char *name_p_type[] = { MSG_ORIG(MSG_CMD_P_TYPE), NULL }; 1116 static elfedit_cmd_optarg_t arg_p_type[] = { 1117 { MSG_ORIG(MSG_STR_ELEMENT), 1118 /* MSG_INTL(MSG_A1_ELEMENT) */ 1119 ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1120 ELFEDIT_CMDOA_F_OPT }, 1121 { MSG_ORIG(MSG_STR_TYPE), 1122 /* MSG_INTL(MSG_A2_P_TYPE_TYPE) */ 1123 ELFEDIT_I18NHDL(MSG_A2_P_TYPE_TYPE), 1124 ELFEDIT_CMDOA_F_OPT }, 1125 { NULL } 1126 }; 1127 1128 /* phdr:p_offset */ 1129 static const char *name_p_offset[] = { MSG_ORIG(MSG_CMD_P_OFFSET), 1130 NULL }; 1131 static elfedit_cmd_optarg_t arg_p_offset[] = { 1132 { MSG_ORIG(MSG_STR_ELEMENT), 1133 /* MSG_INTL(MSG_A1_ELEMENT) */ 1134 ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1135 ELFEDIT_CMDOA_F_OPT }, 1136 { MSG_ORIG(MSG_STR_VALUE), 1137 /* MSG_INTL(MSG_A2_P_OFFSET_VALUE) */ 1138 ELFEDIT_I18NHDL(MSG_A2_P_OFFSET_VALUE), 1139 ELFEDIT_CMDOA_F_OPT }, 1140 { NULL } 1141 }; 1142 1143 /* phdr:p_vaddr */ 1144 static const char *name_p_vaddr[] = { MSG_ORIG(MSG_CMD_P_VADDR), 1145 NULL }; 1146 static elfedit_cmd_optarg_t arg_p_vaddr[] = { 1147 { MSG_ORIG(MSG_STR_ELEMENT), 1148 /* MSG_INTL(MSG_A1_ELEMENT) */ 1149 ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1150 ELFEDIT_CMDOA_F_OPT }, 1151 { MSG_ORIG(MSG_STR_ADDR), 1152 /* MSG_INTL(MSG_A2_P_VADDR_ADDR) */ 1153 ELFEDIT_I18NHDL(MSG_A2_P_VADDR_ADDR), 1154 ELFEDIT_CMDOA_F_OPT }, 1155 { NULL } 1156 }; 1157 1158 /* phdr:p_paddr */ 1159 static const char *name_p_paddr[] = { MSG_ORIG(MSG_CMD_P_PADDR), 1160 NULL }; 1161 static elfedit_cmd_optarg_t arg_p_paddr[] = { 1162 { MSG_ORIG(MSG_STR_ELEMENT), 1163 /* MSG_INTL(MSG_A1_ELEMENT) */ 1164 ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1165 ELFEDIT_CMDOA_F_OPT }, 1166 { MSG_ORIG(MSG_STR_ADDR), 1167 /* MSG_INTL(MSG_A2_P_PADDR_ADDR) */ 1168 ELFEDIT_I18NHDL(MSG_A2_P_PADDR_ADDR), 1169 ELFEDIT_CMDOA_F_OPT }, 1170 { NULL } 1171 }; 1172 1173 /* phdr:p_filesz */ 1174 static const char *name_p_filesz[] = { MSG_ORIG(MSG_CMD_P_FILESZ), 1175 NULL }; 1176 static elfedit_cmd_optarg_t arg_p_filesz[] = { 1177 /* MSG_INTL(MSG_A1_ELEMENT) */ 1178 { MSG_ORIG(MSG_STR_ELEMENT), ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1179 ELFEDIT_CMDOA_F_OPT }, 1180 { MSG_ORIG(MSG_STR_SIZE), 1181 /* MSG_INTL(MSG_A2_P_FILESZ_SIZE) */ 1182 ELFEDIT_I18NHDL(MSG_A2_P_FILESZ_SIZE), 1183 ELFEDIT_CMDOA_F_OPT }, 1184 { NULL } 1185 }; 1186 1187 /* phdr:p_memsz */ 1188 static const char *name_p_memsz[] = { MSG_ORIG(MSG_CMD_P_MEMSZ), 1189 NULL }; 1190 static elfedit_cmd_optarg_t arg_p_memsz[] = { 1191 { MSG_ORIG(MSG_STR_ELEMENT), 1192 /* MSG_INTL(MSG_A1_ELEMENT) */ 1193 ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1194 ELFEDIT_CMDOA_F_OPT }, 1195 { MSG_ORIG(MSG_STR_SIZE), 1196 /* MSG_INTL(MSG_A2_P_MEMSZ_SIZE) */ 1197 ELFEDIT_I18NHDL(MSG_A2_P_MEMSZ_SIZE), 1198 ELFEDIT_CMDOA_F_OPT }, 1199 { NULL } 1200 }; 1201 1202 /* shdr:p_flags */ 1203 static const char *name_p_flags[] = { 1204 MSG_ORIG(MSG_CMD_P_FLAGS), NULL }; 1205 static elfedit_cmd_optarg_t opt_p_flags[] = { 1206 { ELFEDIT_STDOA_OPT_AND, NULL, 1207 ELFEDIT_CMDOA_F_INHERIT, PHDR_OPT_F_AND, PHDR_OPT_F_OR }, 1208 { ELFEDIT_STDOA_OPT_CMP, NULL, 1209 ELFEDIT_CMDOA_F_INHERIT, PHDR_OPT_F_CMP, 0 }, 1210 { MSG_ORIG(MSG_STR_MINUS_PHNDX), 1211 /* MSG_INTL(MSG_OPTDESC_PHNDX) */ 1212 ELFEDIT_I18NHDL(MSG_OPTDESC_PHNDX), 0, 1213 PHDR_OPT_F_PHNDX, 0 }, 1214 { ELFEDIT_STDOA_OPT_O, NULL, 1215 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1216 { ELFEDIT_STDOA_OPT_OR, NULL, 1217 ELFEDIT_CMDOA_F_INHERIT, PHDR_OPT_F_OR, PHDR_OPT_F_AND }, 1218 { NULL } 1219 }; 1220 static elfedit_cmd_optarg_t arg_p_flags[] = { 1221 { MSG_ORIG(MSG_STR_ELEMENT), 1222 /* MSG_INTL(MSG_A1_ELEMENT) */ 1223 ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1224 ELFEDIT_CMDOA_F_OPT }, 1225 { MSG_ORIG(MSG_STR_VALUE), 1226 /* MSG_INTL(MSG_A2_P_FLAGS_VALUE) */ 1227 ELFEDIT_I18NHDL(MSG_A2_P_FLAGS_VALUE), 1228 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 1229 { NULL } 1230 }; 1231 1232 /* phdr:p_align */ 1233 static const char *name_p_align[] = { MSG_ORIG(MSG_CMD_P_ALIGN), 1234 NULL }; 1235 static elfedit_cmd_optarg_t arg_p_align[] = { 1236 { MSG_ORIG(MSG_STR_ELEMENT), 1237 /* MSG_INTL(MSG_A1_ELEMENT) */ 1238 ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1239 ELFEDIT_CMDOA_F_OPT }, 1240 { MSG_ORIG(MSG_STR_ALIGN), 1241 /* MSG_INTL(MSG_A2_P_ALIGN_ALIGN) */ 1242 ELFEDIT_I18NHDL(MSG_A2_P_ALIGN_ALIGN), 1243 ELFEDIT_CMDOA_F_OPT }, 1244 { NULL } 1245 }; 1246 1247 /* phdr:interp */ 1248 static const char *name_interp[] = { MSG_ORIG(MSG_CMD_INTERP), NULL }; 1249 static elfedit_cmd_optarg_t opt_interp[] = { 1250 { ELFEDIT_STDOA_OPT_O, NULL, 1251 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1252 { NULL } 1253 }; 1254 static elfedit_cmd_optarg_t arg_interp[] = { 1255 { MSG_ORIG(MSG_STR_NEWPATH), 1256 /* MSG_INTL(MSG_A1_INTERP_NEWPATH) */ 1257 ELFEDIT_I18NHDL(MSG_A1_INTERP_NEWPATH), 1258 ELFEDIT_CMDOA_F_OPT }, 1259 { NULL } 1260 }; 1261 1262 /* phdr:delete */ 1263 static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL }; 1264 static elfedit_cmd_optarg_t arg_delete[] = { 1265 { MSG_ORIG(MSG_STR_ELEMENT), 1266 /* MSG_INTL(MSG_A1_ELEMENT) */ 1267 ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1268 0 }, 1269 { MSG_ORIG(MSG_STR_COUNT), 1270 /* MSG_INTL(MSG_A2_DELETE_COUNT) */ 1271 ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT), 1272 ELFEDIT_CMDOA_F_OPT }, 1273 { NULL } 1274 }; 1275 1276 /* phdr:move */ 1277 static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL }; 1278 static elfedit_cmd_optarg_t arg_move[] = { 1279 { MSG_ORIG(MSG_STR_ELEMENT), 1280 /* MSG_INTL(MSG_A1_ELEMENT) */ 1281 ELFEDIT_I18NHDL(MSG_A1_ELEMENT), 1282 ELFEDIT_CMDOA_F_OPT }, 1283 { MSG_ORIG(MSG_STR_DST_INDEX), 1284 /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */ 1285 ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX), 1286 0 }, 1287 { MSG_ORIG(MSG_STR_COUNT), 1288 /* MSG_INTL(MSG_A3_MOVE_COUNT) */ 1289 ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT), 1290 ELFEDIT_CMDOA_F_OPT }, 1291 { NULL } 1292 }; 1293 1294 static elfedit_cmd_t cmds[] = { 1295 /* phdr:dump */ 1296 { cmd_dump, cpl_1starg_pt, name_dump, 1297 /* MSG_INTL(MSG_DESC_DUMP) */ 1298 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 1299 /* MSG_INTL(MSG_HELP_DUMP) */ 1300 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 1301 opt_minus_phndx, arg_dump }, 1302 1303 /* phdr:p_type */ 1304 { cmd_p_type, cpl_p_type, name_p_type, 1305 /* MSG_INTL(MSG_DESC_P_TYPE) */ 1306 ELFEDIT_I18NHDL(MSG_DESC_P_TYPE), 1307 /* MSG_INTL(MSG_HELP_P_TYPE) */ 1308 ELFEDIT_I18NHDL(MSG_HELP_P_TYPE), 1309 opt_std, arg_p_type }, 1310 1311 /* phdr:p_offset */ 1312 { cmd_p_offset, cpl_1starg_pt, name_p_offset, 1313 /* MSG_INTL(MSG_DESC_P_OFFSET) */ 1314 ELFEDIT_I18NHDL(MSG_DESC_P_OFFSET), 1315 /* MSG_INTL(MSG_HELP_P_OFFSET) */ 1316 ELFEDIT_I18NHDL(MSG_HELP_P_OFFSET), 1317 opt_std, arg_p_offset }, 1318 1319 /* phdr:p_vaddr */ 1320 { cmd_p_vaddr, cpl_1starg_pt, name_p_vaddr, 1321 /* MSG_INTL(MSG_DESC_P_VADDR) */ 1322 ELFEDIT_I18NHDL(MSG_DESC_P_VADDR), 1323 /* MSG_INTL(MSG_HELP_P_VADDR) */ 1324 ELFEDIT_I18NHDL(MSG_HELP_P_VADDR), 1325 opt_std, arg_p_vaddr }, 1326 1327 /* phdr:p_paddr */ 1328 { cmd_p_paddr, cpl_1starg_pt, name_p_paddr, 1329 /* MSG_INTL(MSG_DESC_P_PADDR) */ 1330 ELFEDIT_I18NHDL(MSG_DESC_P_PADDR), 1331 /* MSG_INTL(MSG_HELP_P_PADDR) */ 1332 ELFEDIT_I18NHDL(MSG_HELP_P_PADDR), 1333 opt_std, arg_p_paddr }, 1334 1335 /* phdr:p_filesz */ 1336 { cmd_p_filesz, cpl_1starg_pt, name_p_filesz, 1337 /* MSG_INTL(MSG_DESC_P_FILESZ) */ 1338 ELFEDIT_I18NHDL(MSG_DESC_P_FILESZ), 1339 /* MSG_INTL(MSG_HELP_P_FILESZ) */ 1340 ELFEDIT_I18NHDL(MSG_HELP_P_FILESZ), 1341 opt_std, arg_p_filesz }, 1342 1343 /* phdr:p_memsz */ 1344 { cmd_p_memsz, cpl_1starg_pt, name_p_memsz, 1345 /* MSG_INTL(MSG_DESC_P_MEMSZ) */ 1346 ELFEDIT_I18NHDL(MSG_DESC_P_MEMSZ), 1347 /* MSG_INTL(MSG_HELP_P_MEMSZ) */ 1348 ELFEDIT_I18NHDL(MSG_HELP_P_MEMSZ), 1349 opt_std, arg_p_memsz }, 1350 1351 /* phdr:p_flags */ 1352 { cmd_p_flags, cpl_p_flags, name_p_flags, 1353 /* MSG_INTL(MSG_DESC_P_FLAGS) */ 1354 ELFEDIT_I18NHDL(MSG_DESC_P_FLAGS), 1355 /* MSG_INTL(MSG_HELP_P_FLAGS) */ 1356 ELFEDIT_I18NHDL(MSG_HELP_P_FLAGS), 1357 opt_p_flags, arg_p_flags }, 1358 1359 /* phdr:p_align */ 1360 { cmd_p_align, cpl_1starg_pt, name_p_align, 1361 /* MSG_INTL(MSG_DESC_P_ALIGN) */ 1362 ELFEDIT_I18NHDL(MSG_DESC_P_ALIGN), 1363 /* MSG_INTL(MSG_HELP_P_ALIGN) */ 1364 ELFEDIT_I18NHDL(MSG_HELP_P_ALIGN), 1365 opt_std, arg_p_align }, 1366 1367 /* phdr:interp */ 1368 { cmd_interp, NULL, name_interp, 1369 /* MSG_INTL(MSG_DESC_INTERP) */ 1370 ELFEDIT_I18NHDL(MSG_DESC_INTERP), 1371 /* MSG_INTL(MSG_HELP_INTERP) */ 1372 ELFEDIT_I18NHDL(MSG_HELP_INTERP), 1373 opt_interp, arg_interp }, 1374 1375 /* phdr:delete */ 1376 { cmd_delete, cpl_1starg_pt, name_delete, 1377 /* MSG_INTL(MSG_DESC_DELETE) */ 1378 ELFEDIT_I18NHDL(MSG_DESC_DELETE), 1379 /* MSG_INTL(MSG_HELP_DELETE) */ 1380 ELFEDIT_I18NHDL(MSG_HELP_DELETE), 1381 opt_minus_phndx, arg_delete }, 1382 1383 /* phdr:move */ 1384 { cmd_move, cpl_1starg_pt, name_move, 1385 /* MSG_INTL(MSG_DESC_MOVE) */ 1386 ELFEDIT_I18NHDL(MSG_DESC_MOVE), 1387 /* MSG_INTL(MSG_HELP_MOVE) */ 1388 ELFEDIT_I18NHDL(MSG_HELP_MOVE), 1389 opt_minus_phndx, arg_move }, 1390 1391 { NULL } 1392 }; 1393 1394 static elfedit_module_t module = { 1395 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 1396 /* MSG_INTL(MSG_MOD_DESC) */ 1397 ELFEDIT_I18NHDL(MSG_MOD_DESC), 1398 cmds, mod_i18nhdl_to_str }; 1399 1400 return (&module); 1401 } 1402