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