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