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 <stdio.h> 28 #include <unistd.h> 29 #include <elfedit.h> 30 #include <sys/elf_SPARC.h> 31 #include <sys/elf_amd64.h> 32 #include <strings.h> 33 #include <debug.h> 34 #include <conv.h> 35 #include <shdr_msg.h> 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 SHDR_CMD_T_DUMP = 0, /* shdr:dump */ 47 48 SHDR_CMD_T_SH_ADDR = 1, /* shdr:sh_addr */ 49 SHDR_CMD_T_SH_ADDRALIGN = 2, /* shdr:sh_addralign */ 50 SHDR_CMD_T_SH_ENTSIZE = 3, /* shdr:sh_entsize */ 51 SHDR_CMD_T_SH_FLAGS = 4, /* shdr:sh_flags */ 52 SHDR_CMD_T_SH_INFO = 5, /* shdr:sh_info */ 53 SHDR_CMD_T_SH_LINK = 6, /* shdr:sh_link */ 54 SHDR_CMD_T_SH_NAME = 7, /* shdr:sh_name */ 55 SHDR_CMD_T_SH_OFFSET = 8, /* shdr:sh_offset */ 56 SHDR_CMD_T_SH_SIZE = 9, /* shdr:sh_size */ 57 SHDR_CMD_T_SH_TYPE = 10 /* shdr:sh_type */ 58 } SHDR_CMD_T; 59 60 61 62 #ifndef _ELF64 63 /* 64 * We supply this function for the msg module. Only one copy is needed. 65 */ 66 const char * 67 _shdr_msg(Msg mid) 68 { 69 return (gettext(MSG_ORIG(mid))); 70 } 71 72 #endif 73 74 75 76 /* 77 * This function is supplied to elfedit through our elfedit_module_t 78 * definition. It translates the opaque elfedit_i18nhdl_t handles 79 * in our module interface into the actual strings for elfedit to 80 * use. 81 * 82 * note: 83 * This module uses Msg codes for its i18n handle type. 84 * So the translation is simply to use MSG_INTL() to turn 85 * it into a string and return it. 86 */ 87 static const char * 88 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 89 { 90 Msg msg = (Msg)hdl; 91 92 return (MSG_INTL(msg)); 93 } 94 95 96 97 /* 98 * The shdr_opt_t enum specifies a bit value for every optional 99 * argument allowed by a command in this module. 100 */ 101 typedef enum { 102 SHDR_OPT_F_AND = 1, /* -and: AND (&) values to dest */ 103 SHDR_OPT_F_CMP = 2, /* -cmp: Complement (~) values */ 104 SHDR_OPT_F_NAMOFFSET = 4, /* -name_offset: Name arg is numeric */ 105 /* ofset rather than string */ 106 SHDR_OPT_F_OR = 8, /* -or: OR (|) values to dest */ 107 SHDR_OPT_F_SHNDX = 16, /* -shndx: Section by index, not name */ 108 SHDR_OPT_F_SHTYP = 32, /* -shtyp: Section by type, not name */ 109 SHDR_OPT_F_VALUE_SHNAM = 64, /* -value_shnam: Value of sh_info or */ 110 /* sh_link given as section name */ 111 SHDR_OPT_F_VALUE_SHTYP = 128 /* -value_shtyp: Value of sh_info or */ 112 /* sh_link given as section type */ 113 } shdr_opt_t; 114 115 116 /* 117 * A variable of type ARGSTATE is used by each command to maintain 118 * information about the section headers and related things. It is 119 * initialized by process_args(), and used by the other routines. 120 */ 121 typedef struct { 122 elfedit_obj_state_t *obj_state; 123 shdr_opt_t optmask; /* Mask of options used */ 124 int argc; /* # of plain arguments */ 125 const char **argv; /* Plain arguments */ 126 } ARGSTATE; 127 128 129 130 131 /* 132 * Standard argument processing for shdr module 133 * 134 * entry 135 * obj_state, argc, argv - Standard command arguments 136 * optmask - Mask of allowed optional arguments. 137 * cmd - SHDR_CMD_T_* value giving identify of caller 138 * argstate - Address of ARGSTATE block to be initialized 139 * 140 * exit: 141 * On success, *argstate is initialized. On error, 142 * an error is issued and this routine does not return. 143 */ 144 static void 145 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 146 SHDR_CMD_T cmd, ARGSTATE *argstate) 147 { 148 elfedit_getopt_state_t getopt_state; 149 elfedit_getopt_ret_t *getopt_ret; 150 151 bzero(argstate, sizeof (*argstate)); 152 argstate->obj_state = obj_state; 153 154 elfedit_getopt_init(&getopt_state, &argc, &argv); 155 156 /* Add each new option to the options mask */ 157 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) 158 argstate->optmask |= getopt_ret->gor_idmask; 159 160 /* Are the right number of plain arguments present? */ 161 switch (cmd) { 162 case SHDR_CMD_T_DUMP: 163 if (argc > 1) 164 elfedit_command_usage(); 165 break; 166 case SHDR_CMD_T_SH_FLAGS: 167 /* shdr:sh_flags allows an arbitrary number of arguments */ 168 break; 169 default: 170 /* The remaining commands accept 2 plain arguments */ 171 if (argc > 2) 172 elfedit_command_usage(); 173 break; 174 } 175 176 /* If there may be an arbitrary amount of output, use a pager */ 177 if (argc == 0) 178 elfedit_pager_init(); 179 180 /* Return the updated values of argc/argv */ 181 argstate->argc = argc; 182 argstate->argv = argv; 183 } 184 185 186 187 /* 188 * Options for deciding which items print_shdr() displays. 189 */ 190 typedef enum { 191 PRINT_SHDR_ALL, /* Print all shdr[ndx:ndx+cnt-1] */ 192 PRINT_SHDR_TYPE, /* Print all shdr[ndx:ndx+cnt-1] with type */ 193 /* of shdr[ndx] */ 194 PRINT_SHDR_NAME, /* Print all shdr[ndx:ndx+cnt-1] with name */ 195 /* of shdr[ndx] */ 196 } PRINT_SHDR_T; 197 198 /* 199 * Print section header values, taking the calling command, and output style 200 * into account. 201 * 202 * entry: 203 * autoprint - If True, output is only produced if the elfedit 204 * autoprint flag is set. If False, output is always produced. 205 * cmd - SHDR_CMD_T_* value giving identify of caller 206 * argstate - State block for section header array 207 * ndx - Index of first section to display 208 * cnt - Number of sections to display 209 * print_type - Specifies which items are shown 210 */ 211 static void 212 print_shdr(SHDR_CMD_T cmd, int autoprint, ARGSTATE *argstate, 213 Word ndx, Word cnt, PRINT_SHDR_T print_type) 214 { 215 elfedit_outstyle_t outstyle; 216 Ehdr *ehdr = argstate->obj_state->os_ehdr; 217 uchar_t osabi = ehdr->e_ident[EI_OSABI]; 218 Half mach = ehdr->e_machine; 219 elfedit_section_t *ref_sec = &argstate->obj_state->os_secarr[ndx]; 220 221 222 if ((autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) || 223 (cnt == 0)) 224 return; 225 226 /* 227 * Pick an output style. shdr:dump is required to use the default 228 * style. The other commands use the current output style. 229 */ 230 outstyle = (cmd == SHDR_CMD_T_DUMP) ? 231 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 232 233 for (; cnt--; ndx++) { 234 elfedit_section_t *sec = &argstate->obj_state->os_secarr[ndx]; 235 Shdr *shdr = sec->sec_shdr; 236 237 switch (print_type) { 238 case PRINT_SHDR_TYPE: 239 if (shdr->sh_type != ref_sec->sec_shdr->sh_type) 240 continue; 241 break; 242 243 case PRINT_SHDR_NAME: 244 if (strcmp(sec->sec_name, ref_sec->sec_name) != 0) 245 continue; 246 break; 247 } 248 249 /* 250 * If doing default output, use elfdump style where we 251 * show all section header attributes. In this case, the 252 * command that called us doesn't matter 253 */ 254 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 255 elfedit_printf(MSG_ORIG(MSG_STR_NL)); 256 elfedit_printf(MSG_INTL(MSG_ELF_SHDR), ndx, 257 sec->sec_name); 258 Elf_shdr(NULL, osabi, mach, sec->sec_shdr); 259 continue; 260 } 261 262 /* Non-default output is handled case by case */ 263 switch (cmd) { 264 case SHDR_CMD_T_SH_ADDR: 265 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL), 266 EC_XWORD(shdr->sh_addr)); 267 break; 268 269 case SHDR_CMD_T_SH_ADDRALIGN: 270 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL), 271 EC_XWORD(shdr->sh_addralign)); 272 break; 273 274 case SHDR_CMD_T_SH_ENTSIZE: 275 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL), 276 EC_XWORD(shdr->sh_entsize)); 277 break; 278 279 case SHDR_CMD_T_SH_FLAGS: 280 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 281 Conv_sec_flags_buf_t sec_flags_buf; 282 283 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 284 conv_sec_flags(osabi, mach, shdr->sh_flags, 285 CONV_FMT_NOBKT, &sec_flags_buf)); 286 } else { 287 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL), 288 EC_XWORD(shdr->sh_flags)); 289 } 290 break; 291 292 case SHDR_CMD_T_SH_INFO: 293 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 294 EC_WORD(shdr->sh_info)); 295 break; 296 297 case SHDR_CMD_T_SH_LINK: 298 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 299 EC_WORD(shdr->sh_link)); 300 break; 301 302 case SHDR_CMD_T_SH_NAME: 303 /* 304 * In simple output mode, we show the string. In 305 * numeric mode, we show the string table offset. 306 */ 307 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 308 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 309 sec->sec_name); 310 } else { 311 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 312 EC_WORD(shdr->sh_name)); 313 } 314 break; 315 316 case SHDR_CMD_T_SH_OFFSET: 317 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL), 318 EC_XWORD(shdr->sh_offset)); 319 break; 320 321 case SHDR_CMD_T_SH_SIZE: 322 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDHEXNL), 323 EC_XWORD(shdr->sh_size)); 324 break; 325 326 case SHDR_CMD_T_SH_TYPE: 327 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 328 Conv_inv_buf_t inv_buf; 329 330 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 331 conv_sec_type(osabi, mach, shdr->sh_type, 0, 332 &inv_buf)); 333 } else { 334 elfedit_printf(MSG_ORIG(MSG_FMT_WORDHEXNL), 335 EC_WORD(shdr->sh_type)); 336 } 337 break; 338 } 339 } 340 } 341 342 343 /* 344 * Common body for the shdr: module commands. These commands 345 * share a large amount of common behavior, so it is convenient 346 * to centralize things and use the cmd argument to handle the 347 * small differences. 348 * 349 * entry: 350 * cmd - One of the SHDR_CMD_T_* constants listed above, specifying 351 * which command to implement. 352 * obj_state, argc, argv - Standard command arguments 353 */ 354 static elfedit_cmdret_t 355 cmd_body(SHDR_CMD_T cmd, elfedit_obj_state_t *obj_state, 356 int argc, const char *argv[]) 357 { 358 Ehdr *ehdr = obj_state->os_ehdr; 359 uchar_t osabi = ehdr->e_ident[EI_OSABI]; 360 Half mach = ehdr->e_machine; 361 ARGSTATE argstate; 362 Word ndx; 363 elfedit_section_t *shdr_sec; 364 Shdr *shdr; 365 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 366 PRINT_SHDR_T print_type; 367 368 process_args(obj_state, argc, argv, cmd, &argstate); 369 370 /* If there are no arguments, dump the whole table and return */ 371 if (argstate.argc == 0) { 372 print_shdr(cmd, 0, &argstate, 0, obj_state->os_shnum, 373 PRINT_SHDR_ALL); 374 return (ELFEDIT_CMDRET_NONE); 375 } 376 377 /* 378 * The first argument gives the section to use. This can be a 379 * name (default), section index, or section type, depending on 380 * the options used. 381 */ 382 if (argstate.optmask & SHDR_OPT_F_SHNDX) { 383 ndx = elfedit_atoshndx(argstate.argv[0], obj_state->os_shnum); 384 print_type = PRINT_SHDR_ALL; 385 } else if (argstate.optmask & SHDR_OPT_F_SHTYP) { 386 ndx = elfedit_type_to_shndx(obj_state, 387 elfedit_atoconst(argstate.argv[0], ELFEDIT_CONST_SHT)); 388 print_type = PRINT_SHDR_TYPE; 389 } else { 390 ndx = elfedit_name_to_shndx(obj_state, argstate.argv[0]); 391 print_type = PRINT_SHDR_NAME; 392 } 393 394 /* If there is a single argument, display that item and return */ 395 if (argstate.argc == 1) { 396 Word cnt; 397 398 cnt = (print_type == PRINT_SHDR_ALL) ? 399 1 : obj_state->os_shnum - ndx; 400 print_shdr(cmd, 0, &argstate, ndx, cnt, print_type); 401 return (ELFEDIT_CMDRET_NONE); 402 } 403 404 /* 405 * Section [0] is supposed to be all zero unless extended sections 406 * are in force. Rather than setting extended values directly, 407 * it is expected to be handled by libelf. So, a direct change here 408 * is probably not what was intended. 409 */ 410 if (ndx == 0) 411 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSHDR0)); 412 413 /* The second value is an integer giving a new value */ 414 shdr_sec = &obj_state->os_secarr[ndx]; 415 shdr = shdr_sec->sec_shdr; 416 switch (cmd) { 417 /* 418 * SHDR_CMD_T_DUMP can't get here: It never has more than 419 * one argument, and is handled above. 420 */ 421 422 case SHDR_CMD_T_SH_ADDR: 423 { 424 Addr sh_addr = elfedit_atoui(argstate.argv[1], NULL); 425 426 if (shdr->sh_addr == sh_addr) { 427 elfedit_msg(ELFEDIT_MSG_DEBUG, 428 MSG_INTL(MSG_DEBUG_LLX_OK), 429 ndx, shdr_sec->sec_name, 430 MSG_ORIG(MSG_CMD_SH_ADDR), 431 EC_ADDR(shdr->sh_addr)); 432 } else { 433 elfedit_msg(ELFEDIT_MSG_DEBUG, 434 MSG_INTL(MSG_DEBUG_LLX_CHG), 435 ndx, shdr_sec->sec_name, 436 MSG_ORIG(MSG_CMD_SH_ADDR), 437 EC_ADDR(shdr->sh_addr), EC_ADDR(sh_addr)); 438 ret = ELFEDIT_CMDRET_MOD; 439 shdr->sh_addr = sh_addr; 440 } 441 } 442 break; 443 444 case SHDR_CMD_T_SH_ADDRALIGN: 445 { 446 Xword sh_addralign; 447 448 sh_addralign = elfedit_atoui(argstate.argv[1], NULL); 449 if (elfedit_bits_set(sh_addralign, 450 sizeof (sh_addralign)) > 1) 451 elfedit_msg(ELFEDIT_MSG_DEBUG, 452 MSG_INTL(MSG_DEBUG_ADDRALIGN), 453 argstate.argv[1]); 454 if (shdr->sh_addralign == sh_addralign) { 455 elfedit_msg(ELFEDIT_MSG_DEBUG, 456 MSG_INTL(MSG_DEBUG_LLX_OK), 457 ndx, shdr_sec->sec_name, 458 MSG_ORIG(MSG_CMD_SH_ADDRALIGN), 459 EC_XWORD(shdr->sh_addralign)); 460 } else { 461 elfedit_msg(ELFEDIT_MSG_DEBUG, 462 MSG_INTL(MSG_DEBUG_LLX_CHG), 463 ndx, shdr_sec->sec_name, 464 MSG_ORIG(MSG_CMD_SH_ADDRALIGN), 465 EC_XWORD(shdr->sh_addralign), 466 EC_XWORD(sh_addralign)); 467 ret = ELFEDIT_CMDRET_MOD; 468 shdr->sh_addralign = sh_addralign; 469 } 470 } 471 break; 472 473 case SHDR_CMD_T_SH_ENTSIZE: 474 { 475 Xword sh_entsize; 476 477 sh_entsize = elfedit_atoui(argstate.argv[1], NULL); 478 if (shdr->sh_entsize == sh_entsize) { 479 elfedit_msg(ELFEDIT_MSG_DEBUG, 480 MSG_INTL(MSG_DEBUG_LLX_OK), 481 ndx, shdr_sec->sec_name, 482 MSG_ORIG(MSG_CMD_SH_ENTSIZE), 483 EC_XWORD(shdr->sh_entsize)); 484 } else { 485 elfedit_msg(ELFEDIT_MSG_DEBUG, 486 MSG_INTL(MSG_DEBUG_LLX_CHG), 487 ndx, shdr_sec->sec_name, 488 MSG_ORIG(MSG_CMD_SH_ENTSIZE), 489 EC_XWORD(shdr->sh_entsize), 490 EC_XWORD(sh_entsize)); 491 ret = ELFEDIT_CMDRET_MOD; 492 shdr->sh_entsize = sh_entsize; 493 } 494 } 495 break; 496 497 case SHDR_CMD_T_SH_FLAGS: 498 { 499 Conv_sec_flags_buf_t buf1, buf2; 500 Word sh_flags = 0; 501 int i; 502 503 /* Collect the flag arguments */ 504 for (i = 1; i < argstate.argc; i++) 505 sh_flags |= 506 (Word) elfedit_atoconst(argstate.argv[i], 507 ELFEDIT_CONST_SHF); 508 509 /* Complement the value? */ 510 if (argstate.optmask & SHDR_OPT_F_CMP) 511 sh_flags = ~sh_flags; 512 513 /* Perform any requested bit operations */ 514 if (argstate.optmask & SHDR_OPT_F_AND) 515 sh_flags &= shdr->sh_flags; 516 else if (argstate.optmask & SHDR_OPT_F_OR) 517 sh_flags |= shdr->sh_flags; 518 519 /* Set the value */ 520 if (shdr->sh_flags == sh_flags) { 521 elfedit_msg(ELFEDIT_MSG_DEBUG, 522 MSG_INTL(MSG_DEBUG_S_OK), 523 ndx, shdr_sec->sec_name, 524 MSG_ORIG(MSG_CMD_SH_FLAGS), 525 conv_sec_flags(osabi, mach, 526 shdr->sh_flags, 0, &buf1)); 527 } else { 528 elfedit_msg(ELFEDIT_MSG_DEBUG, 529 MSG_INTL(MSG_DEBUG_S_CHG), 530 ndx, shdr_sec->sec_name, 531 MSG_ORIG(MSG_CMD_SH_FLAGS), 532 conv_sec_flags(osabi, mach, 533 shdr->sh_flags, 0, &buf1), 534 conv_sec_flags(osabi, mach, 535 sh_flags, 0, &buf2)); 536 ret = ELFEDIT_CMDRET_MOD; 537 shdr->sh_flags = sh_flags; 538 } 539 } 540 break; 541 542 case SHDR_CMD_T_SH_INFO: 543 { 544 Word sh_info; 545 546 if (argstate.optmask & SHDR_OPT_F_VALUE_SHNAM) 547 sh_info = elfedit_name_to_shndx(obj_state, 548 argstate.argv[1]); 549 else if (argstate.optmask & SHDR_OPT_F_VALUE_SHTYP) 550 sh_info = elfedit_type_to_shndx(obj_state, 551 elfedit_atoconst(argstate.argv[1], 552 ELFEDIT_CONST_SHT)); 553 else 554 sh_info = elfedit_atoui(argstate.argv[1], NULL); 555 556 if (shdr->sh_info == sh_info) { 557 elfedit_msg(ELFEDIT_MSG_DEBUG, 558 MSG_INTL(MSG_DEBUG_D_OK), 559 ndx, shdr_sec->sec_name, 560 MSG_ORIG(MSG_CMD_SH_INFO), 561 EC_WORD(shdr->sh_info)); 562 } else { 563 elfedit_msg(ELFEDIT_MSG_DEBUG, 564 MSG_INTL(MSG_DEBUG_D_CHG), 565 ndx, shdr_sec->sec_name, 566 MSG_ORIG(MSG_CMD_SH_INFO), 567 EC_WORD(shdr->sh_info), EC_WORD(sh_info)); 568 ret = ELFEDIT_CMDRET_MOD; 569 shdr->sh_info = sh_info; 570 } 571 } 572 break; 573 574 case SHDR_CMD_T_SH_LINK: 575 { 576 Word sh_link; 577 578 if (argstate.optmask & SHDR_OPT_F_VALUE_SHNAM) 579 sh_link = elfedit_name_to_shndx(obj_state, 580 argstate.argv[1]); 581 else if (argstate.optmask & SHDR_OPT_F_VALUE_SHTYP) 582 sh_link = elfedit_type_to_shndx(obj_state, 583 elfedit_atoconst(argstate.argv[1], 584 ELFEDIT_CONST_SHT)); 585 else 586 sh_link = elfedit_atoui(argstate.argv[1], NULL); 587 588 if (shdr->sh_link == sh_link) { 589 elfedit_msg(ELFEDIT_MSG_DEBUG, 590 MSG_INTL(MSG_DEBUG_D_OK), 591 ndx, shdr_sec->sec_name, 592 MSG_ORIG(MSG_CMD_SH_LINK), 593 EC_WORD(shdr->sh_link)); 594 } else { 595 elfedit_msg(ELFEDIT_MSG_DEBUG, 596 MSG_INTL(MSG_DEBUG_D_CHG), 597 ndx, shdr_sec->sec_name, 598 MSG_ORIG(MSG_CMD_SH_LINK), 599 EC_WORD(shdr->sh_link), EC_WORD(sh_link)); 600 ret = ELFEDIT_CMDRET_MOD; 601 shdr->sh_link = sh_link; 602 } 603 } 604 break; 605 606 case SHDR_CMD_T_SH_NAME: 607 { 608 elfedit_section_t *shstr_sec = 609 &obj_state->os_secarr[obj_state->os_shstrndx]; 610 Word sh_name; 611 612 /* 613 * If -name_offset was specified, this is an offset 614 * into the string table. Otherwise it is a string 615 * we need to turn into an offset. 616 */ 617 sh_name = (argstate.optmask & SHDR_OPT_F_NAMOFFSET) ? 618 elfedit_atoui(argstate.argv[1], NULL) : 619 elfedit_strtab_insert(obj_state, 620 shstr_sec, NULL, argstate.argv[1]); 621 if (shdr->sh_name == sh_name) { 622 elfedit_msg(ELFEDIT_MSG_DEBUG, 623 MSG_INTL(MSG_DEBUG_D_OK), 624 ndx, shdr_sec->sec_name, 625 MSG_ORIG(MSG_CMD_SH_NAME), 626 EC_WORD(shdr->sh_name)); 627 } else { 628 /* 629 * The section name is cached, so we must 630 * also update that value. This call will 631 * warn if the offset is out of range, and 632 * will supply a safe string in that case. 633 */ 634 shdr_sec->sec_name = 635 elfedit_offset_to_str(shstr_sec, 636 sh_name, ELFEDIT_MSG_DEBUG, 1); 637 638 elfedit_msg(ELFEDIT_MSG_DEBUG, 639 MSG_INTL(MSG_DEBUG_D_CHG), 640 ndx, shdr_sec->sec_name, 641 MSG_ORIG(MSG_CMD_SH_NAME), 642 EC_WORD(shdr->sh_name), EC_WORD(sh_name)); 643 ret = ELFEDIT_CMDRET_MOD; 644 shdr->sh_name = sh_name; 645 } 646 } 647 break; 648 649 case SHDR_CMD_T_SH_OFFSET: 650 { 651 Off sh_offset; 652 653 sh_offset = elfedit_atoui(argstate.argv[1], NULL); 654 if (shdr->sh_offset == sh_offset) { 655 elfedit_msg(ELFEDIT_MSG_DEBUG, 656 MSG_INTL(MSG_DEBUG_LLX_OK), 657 ndx, shdr_sec->sec_name, 658 MSG_ORIG(MSG_CMD_SH_OFFSET), 659 EC_XWORD(shdr->sh_offset)); 660 } else { 661 elfedit_msg(ELFEDIT_MSG_DEBUG, 662 MSG_INTL(MSG_DEBUG_LLX_CHG), 663 ndx, shdr_sec->sec_name, 664 MSG_ORIG(MSG_CMD_SH_OFFSET), 665 EC_XWORD(shdr->sh_offset), 666 EC_XWORD(sh_offset)); 667 ret = ELFEDIT_CMDRET_MOD; 668 shdr->sh_offset = sh_offset; 669 } 670 } 671 break; 672 673 case SHDR_CMD_T_SH_SIZE: 674 { 675 Xword sh_size; 676 677 sh_size = elfedit_atoui(argstate.argv[1], NULL); 678 if (shdr->sh_size == sh_size) { 679 elfedit_msg(ELFEDIT_MSG_DEBUG, 680 MSG_INTL(MSG_DEBUG_LLX_OK), 681 ndx, shdr_sec->sec_name, 682 MSG_ORIG(MSG_CMD_SH_SIZE), 683 EC_XWORD(shdr->sh_size)); 684 } else { 685 elfedit_msg(ELFEDIT_MSG_DEBUG, 686 MSG_INTL(MSG_DEBUG_LLX_CHG), 687 ndx, shdr_sec->sec_name, 688 MSG_ORIG(MSG_CMD_SH_SIZE), 689 EC_XWORD(shdr->sh_size), 690 EC_XWORD(sh_size)); 691 ret = ELFEDIT_CMDRET_MOD; 692 shdr->sh_size = sh_size; 693 } 694 } 695 break; 696 697 case SHDR_CMD_T_SH_TYPE: 698 { 699 Word sh_type = elfedit_atoconst(argstate.argv[1], 700 ELFEDIT_CONST_SHT); 701 Conv_inv_buf_t inv_buf1, inv_buf2; 702 703 if (shdr->sh_type == sh_type) { 704 elfedit_msg(ELFEDIT_MSG_DEBUG, 705 MSG_INTL(MSG_DEBUG_S_OK), 706 ndx, shdr_sec->sec_name, 707 MSG_ORIG(MSG_CMD_SH_TYPE), 708 conv_sec_type(osabi, mach, shdr->sh_type, 709 0, &inv_buf1)); 710 } else { 711 elfedit_msg(ELFEDIT_MSG_DEBUG, 712 MSG_INTL(MSG_DEBUG_S_CHG), 713 ndx, shdr_sec->sec_name, 714 MSG_ORIG(MSG_CMD_SH_TYPE), 715 conv_sec_type(osabi, mach, shdr->sh_type, 716 0, &inv_buf1), 717 conv_sec_type(osabi, mach, sh_type, 718 0, &inv_buf2)); 719 ret = ELFEDIT_CMDRET_MOD; 720 shdr->sh_type = sh_type; 721 } 722 } 723 break; 724 } 725 726 /* 727 * If we modified the section header array, tell libelf. 728 */ 729 if (ret == ELFEDIT_CMDRET_MOD) 730 elfedit_modified_shdr(shdr_sec); 731 732 /* Do autoprint */ 733 print_shdr(cmd, 1, &argstate, ndx, 1, PRINT_SHDR_ALL); 734 735 return (ret); 736 } 737 738 739 740 741 /* 742 * Command completion functions for the various commands 743 */ 744 745 /* 746 * All of the commands accept the same first argument (sec) that 747 * specifies the section. This argument can be a section name 748 * (default), section index, or section type, depending on the 749 * options used. This routine determines which case is current, 750 * and then supplies completion for the first argument. 751 */ 752 static void 753 cpl_1starg_sec(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 754 const char *argv[], int num_opt) 755 { 756 elfedit_section_t *sec; 757 enum { NAME, INDEX, TYPE } op; 758 Word ndx; 759 760 if (argc != (num_opt + 1)) 761 return; 762 763 op = NAME; 764 for (ndx = 0; ndx < num_opt; ndx++) { 765 if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) 766 op = INDEX; 767 else if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) 768 op = TYPE; 769 } 770 771 switch (op) { 772 case NAME: 773 if (obj_state == NULL) 774 break; 775 sec = obj_state->os_secarr; 776 for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++) 777 elfedit_cpl_match(cpldata, sec->sec_name, 0); 778 break; 779 780 case INDEX: 781 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHN); 782 break; 783 784 case TYPE: 785 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT); 786 break; 787 } 788 } 789 790 791 /*ARGSUSED*/ 792 static void 793 cpl_sh_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 794 const char *argv[], int num_opt) 795 { 796 /* Handle -shXXX options */ 797 cpl_1starg_sec(obj_state, cpldata, argc, argv, num_opt); 798 799 /* The second and following arguments can be an SHF_ value */ 800 if (argc >= (num_opt + 2)) 801 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHF); 802 } 803 804 /* 805 * For shdr:sh_info and shdr:sh_link: The value argument can be an 806 * integer, section name, or section type. 807 */ 808 /*ARGSUSED*/ 809 static void 810 cpl_sh_infolink(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 811 const char *argv[], int num_opt) 812 { 813 elfedit_section_t *sec; 814 enum { NAME, INTVAL, TYPE } op; 815 Word ndx; 816 817 /* Handle -shXXX options */ 818 cpl_1starg_sec(obj_state, cpldata, argc, argv, num_opt); 819 820 if (argc != (num_opt + 2)) 821 return; 822 823 op = INTVAL; 824 for (ndx = 0; ndx < num_opt; ndx++) { 825 if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_VALUE_SHNAM)) == 0) 826 op = NAME; 827 else if (strcmp(argv[ndx], 828 MSG_ORIG(MSG_STR_MINUS_VALUE_SHTYP)) == 0) 829 op = TYPE; 830 } 831 832 switch (op) { 833 case NAME: 834 if (obj_state == NULL) 835 break; 836 sec = obj_state->os_secarr; 837 for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++) 838 elfedit_cpl_match(cpldata, sec->sec_name, 0); 839 break; 840 841 case TYPE: 842 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT); 843 break; 844 } 845 } 846 847 /*ARGSUSED*/ 848 static void 849 cpl_sh_type(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 850 const char *argv[], int num_opt) 851 { 852 /* Handle -shXXX options */ 853 cpl_1starg_sec(obj_state, cpldata, argc, argv, num_opt); 854 855 /* The second argument can be an SHT_ value */ 856 if (argc == (num_opt + 2)) 857 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT); 858 } 859 860 861 862 /* 863 * Implementation functions for the commands 864 */ 865 static elfedit_cmdret_t 866 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 867 { 868 return (cmd_body(SHDR_CMD_T_DUMP, obj_state, argc, argv)); 869 } 870 871 872 static elfedit_cmdret_t 873 cmd_sh_addr(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 874 { 875 return (cmd_body(SHDR_CMD_T_SH_ADDR, obj_state, argc, argv)); 876 } 877 878 879 static elfedit_cmdret_t 880 cmd_sh_addralign(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 881 { 882 return (cmd_body(SHDR_CMD_T_SH_ADDRALIGN, obj_state, argc, argv)); 883 } 884 885 886 static elfedit_cmdret_t 887 cmd_sh_entsize(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 888 { 889 return (cmd_body(SHDR_CMD_T_SH_ENTSIZE, obj_state, argc, argv)); 890 } 891 892 static elfedit_cmdret_t 893 cmd_sh_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 894 { 895 return (cmd_body(SHDR_CMD_T_SH_FLAGS, obj_state, argc, argv)); 896 } 897 898 static elfedit_cmdret_t 899 cmd_sh_info(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 900 { 901 return (cmd_body(SHDR_CMD_T_SH_INFO, obj_state, argc, argv)); 902 } 903 904 static elfedit_cmdret_t 905 cmd_sh_link(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 906 { 907 return (cmd_body(SHDR_CMD_T_SH_LINK, obj_state, argc, argv)); 908 } 909 910 static elfedit_cmdret_t 911 cmd_sh_name(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 912 { 913 return (cmd_body(SHDR_CMD_T_SH_NAME, obj_state, argc, argv)); 914 } 915 916 static elfedit_cmdret_t 917 cmd_sh_offset(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 918 { 919 return (cmd_body(SHDR_CMD_T_SH_OFFSET, obj_state, argc, argv)); 920 } 921 922 static elfedit_cmdret_t 923 cmd_sh_size(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 924 { 925 return (cmd_body(SHDR_CMD_T_SH_SIZE, obj_state, argc, argv)); 926 } 927 928 static elfedit_cmdret_t 929 cmd_sh_type(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 930 { 931 return (cmd_body(SHDR_CMD_T_SH_TYPE, obj_state, argc, argv)); 932 } 933 934 935 936 /*ARGSUSED*/ 937 elfedit_module_t * 938 elfedit_init(elfedit_module_version_t version) 939 { 940 /* Multiple commands accept only the standard set of options */ 941 static elfedit_cmd_optarg_t opt_std[] = { 942 { ELFEDIT_STDOA_OPT_O, 0, 943 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 944 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 945 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 946 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0, 947 SHDR_OPT_F_SHNDX, SHDR_OPT_F_SHTYP }, 948 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 949 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 950 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0, 951 SHDR_OPT_F_SHTYP, SHDR_OPT_F_SHNDX }, 952 { NULL } 953 }; 954 955 /* 956 * sh_info and sh_link accept the standard options above, 957 * plus -value_shnam and -value_shtyp. 958 */ 959 static elfedit_cmd_optarg_t opt_infolink[] = { 960 { ELFEDIT_STDOA_OPT_O, 0, 961 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 962 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 963 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 964 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0, 965 SHDR_OPT_F_SHNDX, SHDR_OPT_F_SHTYP }, 966 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 967 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 968 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0, 969 SHDR_OPT_F_SHTYP, SHDR_OPT_F_SHNDX }, 970 { MSG_ORIG(MSG_STR_MINUS_VALUE_SHNAM), 971 /* MSG_INTL(MSG_OPTDESC_VALUE_SHNAM) */ 972 ELFEDIT_I18NHDL(MSG_OPTDESC_VALUE_SHNAM), 0, 973 SHDR_OPT_F_VALUE_SHNAM, SHDR_OPT_F_VALUE_SHNAM }, 974 { MSG_ORIG(MSG_STR_MINUS_VALUE_SHTYP), 975 /* MSG_INTL(MSG_OPTDESC_VALUE_SHTYP) */ 976 ELFEDIT_I18NHDL(MSG_OPTDESC_VALUE_SHTYP), 0, 977 SHDR_OPT_F_VALUE_SHTYP, SHDR_OPT_F_VALUE_SHTYP }, 978 { NULL } 979 }; 980 981 /* shdr:sh_addr */ 982 static const char *name_sh_addr[] = { 983 MSG_ORIG(MSG_CMD_SH_ADDR), NULL }; 984 static elfedit_cmd_optarg_t arg_sh_addr[] = { 985 { MSG_ORIG(MSG_STR_SEC), 986 /* MSG_INTL(MSG_A1_SEC) */ 987 ELFEDIT_I18NHDL(MSG_A1_SEC), 988 ELFEDIT_CMDOA_F_OPT }, 989 { MSG_ORIG(MSG_STR_VALUE), 990 /* MSG_INTL(MSG_A2_DESC_SH_ADDR) */ 991 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_ADDR), 992 ELFEDIT_CMDOA_F_OPT }, 993 { NULL } 994 }; 995 996 /* shdr:dump */ 997 static const char *name_dump[] = { 998 MSG_ORIG(MSG_CMD_DUMP), 999 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 1000 NULL 1001 }; 1002 static elfedit_cmd_optarg_t opt_dump[] = { 1003 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1004 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1005 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0, 1006 SHDR_OPT_F_SHNDX, SHDR_OPT_F_SHTYP }, 1007 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1008 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1009 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0, 1010 SHDR_OPT_F_SHTYP, SHDR_OPT_F_SHNDX }, 1011 { NULL } 1012 }; 1013 static elfedit_cmd_optarg_t arg_dump[] = { 1014 { MSG_ORIG(MSG_STR_SEC), 1015 /* MSG_INTL(MSG_A1_SEC) */ 1016 ELFEDIT_I18NHDL(MSG_A1_SEC), 1017 ELFEDIT_CMDOA_F_OPT }, 1018 { NULL } 1019 }; 1020 1021 /* shdr:sh_addralign */ 1022 static const char *name_sh_addralign[] = { 1023 MSG_ORIG(MSG_CMD_SH_ADDRALIGN), NULL }; 1024 static elfedit_cmd_optarg_t arg_sh_addralign[] = { 1025 { MSG_ORIG(MSG_STR_SEC), 1026 /* MSG_INTL(MSG_A1_SEC) */ 1027 ELFEDIT_I18NHDL(MSG_A1_SEC), 1028 ELFEDIT_CMDOA_F_OPT }, 1029 { MSG_ORIG(MSG_STR_VALUE), 1030 /* MSG_INTL(MSG_A2_DESC_SH_ADDRALIGN) */ 1031 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_ADDRALIGN), 1032 ELFEDIT_CMDOA_F_OPT }, 1033 { NULL } 1034 }; 1035 1036 /* shdr:sh_entsize */ 1037 static const char *name_sh_entsize[] = { 1038 MSG_ORIG(MSG_CMD_SH_ENTSIZE), NULL }; 1039 static elfedit_cmd_optarg_t arg_sh_entsize[] = { 1040 { MSG_ORIG(MSG_STR_SEC), 1041 /* MSG_INTL(MSG_A1_SEC) */ 1042 ELFEDIT_I18NHDL(MSG_A1_SEC), 1043 ELFEDIT_CMDOA_F_OPT }, 1044 { MSG_ORIG(MSG_STR_VALUE), 1045 /* MSG_INTL(MSG_A2_DESC_SH_ENTSIZE) */ 1046 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_ENTSIZE), 1047 ELFEDIT_CMDOA_F_OPT }, 1048 { NULL } 1049 }; 1050 1051 /* shdr:sh_flags */ 1052 static const char *name_sh_flags[] = { 1053 MSG_ORIG(MSG_CMD_SH_FLAGS), NULL }; 1054 static elfedit_cmd_optarg_t opt_sh_flags[] = { 1055 { ELFEDIT_STDOA_OPT_AND, 0, 1056 ELFEDIT_CMDOA_F_INHERIT, SHDR_OPT_F_AND, SHDR_OPT_F_OR }, 1057 { ELFEDIT_STDOA_OPT_CMP, 0, 1058 ELFEDIT_CMDOA_F_INHERIT, SHDR_OPT_F_CMP, 0 }, 1059 { ELFEDIT_STDOA_OPT_O, 0, 1060 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1061 { ELFEDIT_STDOA_OPT_OR, 0, 1062 ELFEDIT_CMDOA_F_INHERIT, SHDR_OPT_F_OR, SHDR_OPT_F_AND }, 1063 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1064 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1065 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0, 1066 SHDR_OPT_F_SHNDX, SHDR_OPT_F_SHTYP }, 1067 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1068 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1069 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0, 1070 SHDR_OPT_F_SHTYP, SHDR_OPT_F_SHNDX }, 1071 { NULL } 1072 }; 1073 static elfedit_cmd_optarg_t arg_sh_flags[] = { 1074 { MSG_ORIG(MSG_STR_SEC), 1075 /* MSG_INTL(MSG_A1_SEC) */ 1076 ELFEDIT_I18NHDL(MSG_A1_SEC), 1077 ELFEDIT_CMDOA_F_OPT }, 1078 { MSG_ORIG(MSG_STR_VALUE), 1079 /* MSG_INTL(MSG_A2_DESC_SH_FLAGS) */ 1080 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_FLAGS), 1081 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 1082 { NULL } 1083 }; 1084 1085 /* shdr:sh_info */ 1086 static const char *name_sh_info[] = { 1087 MSG_ORIG(MSG_CMD_SH_INFO), NULL }; 1088 static elfedit_cmd_optarg_t arg_sh_info[] = { 1089 { MSG_ORIG(MSG_STR_SEC), 1090 /* MSG_INTL(MSG_A1_SEC) */ 1091 ELFEDIT_I18NHDL(MSG_A1_SEC), 1092 ELFEDIT_CMDOA_F_OPT }, 1093 { MSG_ORIG(MSG_STR_VALUE), 1094 /* MSG_INTL(MSG_A2_DESC_SH_INFO) */ 1095 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_INFO), 1096 ELFEDIT_CMDOA_F_OPT }, 1097 { NULL } 1098 }; 1099 1100 /* shdr:sh_link */ 1101 static const char *name_sh_link[] = { 1102 MSG_ORIG(MSG_CMD_SH_LINK), NULL }; 1103 static elfedit_cmd_optarg_t arg_sh_link[] = { 1104 { MSG_ORIG(MSG_STR_SEC), 1105 /* MSG_INTL(MSG_A1_SEC) */ 1106 ELFEDIT_I18NHDL(MSG_A1_SEC), 1107 ELFEDIT_CMDOA_F_OPT }, 1108 { MSG_ORIG(MSG_STR_VALUE), 1109 /* MSG_INTL(MSG_A2_DESC_SH_LINK) */ 1110 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_LINK), 1111 ELFEDIT_CMDOA_F_OPT }, 1112 { NULL } 1113 }; 1114 1115 /* shdr:sh_name */ 1116 static const char *name_sh_name[] = { 1117 MSG_ORIG(MSG_CMD_SH_NAME), NULL }; 1118 static elfedit_cmd_optarg_t opt_sh_name[] = { 1119 { MSG_ORIG(MSG_STR_MINUS_NAME_OFFSET), 1120 /* MSG_INTL(MSG_OPTDESC_NAME_OFFSET) */ 1121 ELFEDIT_I18NHDL(MSG_OPTDESC_NAME_OFFSET), 0, 1122 SHDR_OPT_F_NAMOFFSET, 0 }, 1123 { ELFEDIT_STDOA_OPT_O, 0, 1124 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1125 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1126 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1127 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), 0, 1128 SHDR_OPT_F_SHNDX, SHDR_OPT_F_SHTYP }, 1129 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1130 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1131 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), 0, 1132 SHDR_OPT_F_SHTYP, SHDR_OPT_F_SHNDX }, 1133 { NULL } 1134 }; 1135 static elfedit_cmd_optarg_t arg_sh_name[] = { 1136 { MSG_ORIG(MSG_STR_SEC), 1137 /* MSG_INTL(MSG_A1_SEC) */ 1138 ELFEDIT_I18NHDL(MSG_A1_SEC), 1139 ELFEDIT_CMDOA_F_OPT }, 1140 { MSG_ORIG(MSG_STR_NAME), 1141 /* MSG_INTL(MSG_A2_DESC_SH_NAME) */ 1142 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_NAME), 1143 ELFEDIT_CMDOA_F_OPT }, 1144 { NULL } 1145 }; 1146 1147 /* shdr:sh_offset */ 1148 static const char *name_sh_offset[] = { 1149 MSG_ORIG(MSG_CMD_SH_OFFSET), NULL }; 1150 static elfedit_cmd_optarg_t arg_sh_offset[] = { 1151 { MSG_ORIG(MSG_STR_SEC), 1152 /* MSG_INTL(MSG_A1_SEC) */ 1153 ELFEDIT_I18NHDL(MSG_A1_SEC), 1154 ELFEDIT_CMDOA_F_OPT }, 1155 { MSG_ORIG(MSG_STR_VALUE), 1156 /* MSG_INTL(MSG_A2_DESC_SH_OFFSET) */ 1157 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_OFFSET), 1158 ELFEDIT_CMDOA_F_OPT }, 1159 { NULL } 1160 }; 1161 1162 /* shdr:sh_size */ 1163 static const char *name_sh_size[] = { 1164 MSG_ORIG(MSG_CMD_SH_SIZE), NULL }; 1165 static elfedit_cmd_optarg_t arg_sh_size[] = { 1166 { MSG_ORIG(MSG_STR_SEC), 1167 /* MSG_INTL(MSG_A1_SEC) */ 1168 ELFEDIT_I18NHDL(MSG_A1_SEC), 1169 ELFEDIT_CMDOA_F_OPT }, 1170 { MSG_ORIG(MSG_STR_VALUE), 1171 /* MSG_INTL(MSG_A2_DESC_SH_SIZE) */ 1172 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_SIZE), 1173 ELFEDIT_CMDOA_F_OPT }, 1174 { NULL } 1175 }; 1176 1177 /* shdr:sh_type */ 1178 static const char *name_sh_type[] = { 1179 MSG_ORIG(MSG_CMD_SH_TYPE), NULL }; 1180 static elfedit_cmd_optarg_t arg_sh_type[] = { 1181 { MSG_ORIG(MSG_STR_SEC), 1182 /* MSG_INTL(MSG_A1_SEC) */ 1183 ELFEDIT_I18NHDL(MSG_A1_SEC), 1184 ELFEDIT_CMDOA_F_OPT }, 1185 { MSG_ORIG(MSG_STR_VALUE), 1186 /* MSG_INTL(MSG_A2_DESC_SH_TYPE) */ 1187 ELFEDIT_I18NHDL(MSG_A2_DESC_SH_TYPE), 1188 ELFEDIT_CMDOA_F_OPT }, 1189 { NULL } 1190 }; 1191 1192 static elfedit_cmd_t cmds[] = { 1193 /* shdr:dump */ 1194 { cmd_dump, cpl_1starg_sec, name_dump, 1195 /* MSG_INTL(MSG_DESC_DUMP) */ 1196 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 1197 /* MSG_INTL(MSG_HELP_DUMP) */ 1198 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 1199 opt_dump, arg_dump }, 1200 1201 /* shdr:sh_addr */ 1202 { cmd_sh_addr, cpl_1starg_sec, name_sh_addr, 1203 /* MSG_INTL(MSG_DESC_SH_ADDR) */ 1204 ELFEDIT_I18NHDL(MSG_DESC_SH_ADDR), 1205 /* MSG_INTL(MSG_HELP_SH_ADDR) */ 1206 ELFEDIT_I18NHDL(MSG_HELP_SH_ADDR), 1207 opt_std, arg_sh_addr }, 1208 1209 /* shdr:sh_addralign */ 1210 { cmd_sh_addralign, cpl_1starg_sec, name_sh_addralign, 1211 /* MSG_INTL(MSG_DESC_SH_ADDRALIGN) */ 1212 ELFEDIT_I18NHDL(MSG_DESC_SH_ADDRALIGN), 1213 /* MSG_INTL(MSG_HELP_SH_ADDRALIGN) */ 1214 ELFEDIT_I18NHDL(MSG_HELP_SH_ADDRALIGN), 1215 opt_std, arg_sh_addralign }, 1216 1217 /* shdr:sh_entsize */ 1218 { cmd_sh_entsize, cpl_1starg_sec, name_sh_entsize, 1219 /* MSG_INTL(MSG_DESC_SH_ENTSIZE) */ 1220 ELFEDIT_I18NHDL(MSG_DESC_SH_ENTSIZE), 1221 /* MSG_INTL(MSG_HELP_SH_ENTSIZE) */ 1222 ELFEDIT_I18NHDL(MSG_HELP_SH_ENTSIZE), 1223 opt_std, arg_sh_entsize }, 1224 1225 /* shdr:sh_flags */ 1226 { cmd_sh_flags, cpl_sh_flags, name_sh_flags, 1227 /* MSG_INTL(MSG_DESC_SH_FLAGS) */ 1228 ELFEDIT_I18NHDL(MSG_DESC_SH_FLAGS), 1229 /* MSG_INTL(MSG_HELP_SH_FLAGS) */ 1230 ELFEDIT_I18NHDL(MSG_HELP_SH_FLAGS), 1231 opt_sh_flags, arg_sh_flags }, 1232 1233 /* shdr:sh_info */ 1234 { cmd_sh_info, cpl_sh_infolink, name_sh_info, 1235 /* MSG_INTL(MSG_DESC_SH_INFO) */ 1236 ELFEDIT_I18NHDL(MSG_DESC_SH_INFO), 1237 /* MSG_INTL(MSG_HELP_SH_INFO) */ 1238 ELFEDIT_I18NHDL(MSG_HELP_SH_INFO), 1239 opt_infolink, arg_sh_info }, 1240 1241 /* shdr:sh_link */ 1242 { cmd_sh_link, cpl_sh_infolink, name_sh_link, 1243 /* MSG_INTL(MSG_DESC_SH_LINK) */ 1244 ELFEDIT_I18NHDL(MSG_DESC_SH_LINK), 1245 /* MSG_INTL(MSG_HELP_SH_LINK) */ 1246 ELFEDIT_I18NHDL(MSG_HELP_SH_LINK), 1247 opt_infolink, arg_sh_link }, 1248 1249 /* shdr:sh_name */ 1250 { cmd_sh_name, cpl_1starg_sec, name_sh_name, 1251 /* MSG_INTL(MSG_DESC_SH_NAME) */ 1252 ELFEDIT_I18NHDL(MSG_DESC_SH_NAME), 1253 /* MSG_INTL(MSG_HELP_SH_NAME) */ 1254 ELFEDIT_I18NHDL(MSG_HELP_SH_NAME), 1255 opt_sh_name, arg_sh_name }, 1256 1257 /* shdr:sh_offset */ 1258 { cmd_sh_offset, cpl_1starg_sec, name_sh_offset, 1259 /* MSG_INTL(MSG_DESC_SH_OFFSET) */ 1260 ELFEDIT_I18NHDL(MSG_DESC_SH_OFFSET), 1261 /* MSG_INTL(MSG_HELP_SH_OFFSET) */ 1262 ELFEDIT_I18NHDL(MSG_HELP_SH_OFFSET), 1263 opt_std, arg_sh_offset }, 1264 1265 /* shdr:sh_size */ 1266 { cmd_sh_size, cpl_1starg_sec, name_sh_size, 1267 /* MSG_INTL(MSG_DESC_SH_SIZE) */ 1268 ELFEDIT_I18NHDL(MSG_DESC_SH_SIZE), 1269 /* MSG_INTL(MSG_HELP_SH_SIZE) */ 1270 ELFEDIT_I18NHDL(MSG_HELP_SH_SIZE), 1271 opt_std, arg_sh_size }, 1272 1273 /* shdr:sh_type */ 1274 { cmd_sh_type, cpl_sh_type, name_sh_type, 1275 /* MSG_INTL(MSG_DESC_SH_TYPE) */ 1276 ELFEDIT_I18NHDL(MSG_DESC_SH_TYPE), 1277 /* MSG_INTL(MSG_HELP_SH_TYPE) */ 1278 ELFEDIT_I18NHDL(MSG_HELP_SH_TYPE), 1279 opt_std, arg_sh_type }, 1280 1281 { NULL } 1282 }; 1283 1284 static elfedit_module_t module = { 1285 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 1286 /* MSG_INTL(MSG_MOD_DESC) */ 1287 ELFEDIT_I18NHDL(MSG_MOD_DESC), 1288 cmds, mod_i18nhdl_to_str }; 1289 1290 return (&module); 1291 } 1292