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 #define ELF_TARGET_AMD64 /* SHN_AMD64_LCOMMON */ 28 29 #include <stdio.h> 30 #include <unistd.h> 31 #include <elfedit.h> 32 #include <strings.h> 33 #include <debug.h> 34 #include <conv.h> 35 #include <sym_msg.h> 36 37 38 39 40 #define MAXNDXSIZE 10 41 42 43 44 /* 45 * This module uses shared code for several of the commands. 46 * It is sometimes necessary to know which specific command 47 * is active. 48 */ 49 typedef enum { 50 SYM_CMD_T_DUMP = 0, /* sym:dump */ 51 52 SYM_CMD_T_ST_BIND = 1, /* sym:st_bind */ 53 SYM_CMD_T_ST_INFO = 2, /* sym:st_info */ 54 SYM_CMD_T_ST_NAME = 3, /* sym:st_name */ 55 SYM_CMD_T_ST_OTHER = 4, /* sym:st_other */ 56 SYM_CMD_T_ST_SHNDX = 5, /* sym:st_shndx */ 57 SYM_CMD_T_ST_SIZE = 6, /* sym:st_size */ 58 SYM_CMD_T_ST_TYPE = 7, /* sym:st_type */ 59 SYM_CMD_T_ST_VALUE = 8, /* sym:st_value */ 60 SYM_CMD_T_ST_VISIBILITY = 9 /* sym:st_visibility */ 61 } SYM_CMD_T; 62 63 64 65 /* 66 * ELFCLASS-specific definitions 67 */ 68 #ifdef _ELF64 69 70 #define MSG_FMT_XWORDVALNL MSG_FMT_XWORDVALNL_64 71 72 #else 73 74 #define MSG_FMT_XWORDVALNL MSG_FMT_XWORDVALNL_32 75 76 /* 77 * We supply this function for the msg module. Only one copy is needed. 78 */ 79 const char * 80 _sym_msg(Msg mid) 81 { 82 return (gettext(MSG_ORIG(mid))); 83 } 84 85 #endif 86 87 88 89 /* 90 * This function is supplied to elfedit through our elfedit_module_t 91 * definition. It translates the opaque elfedit_i18nhdl_t handles 92 * in our module interface into the actual strings for elfedit to 93 * use. 94 * 95 * note: 96 * This module uses Msg codes for its i18n handle type. 97 * So the translation is simply to use MSG_INTL() to turn 98 * it into a string and return it. 99 */ 100 static const char * 101 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 102 { 103 Msg msg = (Msg)hdl; 104 105 return (MSG_INTL(msg)); 106 } 107 108 109 110 /* 111 * The sym_opt_t enum specifies a bit value for every optional 112 * argument allowed by a command in this module. 113 */ 114 typedef enum { 115 SYM_OPT_F_XSHINDEX = 1, /* -e: Force shndx update to extended */ 116 /* index section */ 117 SYM_OPT_F_NAMOFFSET = 2, /* -name_offset: sym:st_name name arg */ 118 /* is numeric offset */ 119 /* rather than ASCII string */ 120 SYM_OPT_F_SECSHNDX = 4, /* -secshndx: Section arg is */ 121 /* section index, not name */ 122 SYM_OPT_F_SECSHTYP = 8, /* -secshtyp: Section arg is */ 123 /* section type, not name */ 124 SYM_OPT_F_SHNAME = 16, /* -shnam name: section spec. by name */ 125 SYM_OPT_F_SHNDX = 32, /* -shndx ndx: section spec. by index */ 126 SYM_OPT_F_SHTYP = 64, /* -shtyp type: section spec. by type */ 127 SYM_OPT_F_SYMNDX = 128 /* -symndx: Sym specified by index */ 128 } sym_opt_t; 129 130 131 /* 132 * A variable of type ARGSTATE is used by each command to maintain 133 * the overall state for a given set of arguments and the symbol tables 134 * being managed. 135 * 136 * The state for each symbol table and the auxiliary sections that are 137 * related to it are kept in a SYMSTATE sub-struct. 138 * 139 * One benefit of ARGSTATE is that it helps us to ensure that we only 140 * fetch each section a single time: 141 * - More efficient 142 * - Prevents multiple ELFEDIT_MSG_DEBUG messages from 143 * being produced for a given section. 144 * 145 * note: The symstate array in ARGSTATE is defined as having one 146 * element, but in reality, we allocate enough room for 147 * the number of elements defined in the numsymstate field. 148 */ 149 typedef struct { 150 Word ndx; /* If argstate.argc > 0, this is the table index */ 151 struct { /* Symbol table */ 152 elfedit_section_t *sec; 153 Sym *data; 154 Word n; 155 } sym; 156 struct { /* String table */ 157 elfedit_section_t *sec; 158 } str; 159 struct { /* Versym */ 160 Word shndx; 161 elfedit_section_t *sec; 162 Versym *data; 163 Word n; 164 } versym; 165 struct { /* Extended section indices */ 166 Word shndx; 167 elfedit_section_t *sec; 168 Word *data; 169 Word n; 170 } xshndx; 171 } SYMSTATE; 172 typedef struct { 173 elfedit_obj_state_t *obj_state; 174 sym_opt_t optmask; /* Mask of options used */ 175 int argc; /* # of plain arguments */ 176 const char **argv; /* Plain arguments */ 177 int numsymstate; /* # of items in symstate[] */ 178 SYMSTATE symstate[1]; /* Symbol tables to process */ 179 } ARGSTATE; 180 181 182 /* 183 * We maintain the state of each symbol table and related associated 184 * sections in a SYMSTATE structure . We don't look those auxiliary 185 * things up unless we actually need them, both to be efficient, 186 * and to prevent duplicate ELFEDIT_MSG_DEBUG messages from being 187 * issued as they are located. Hence, process_args() is used to 188 * initialize the state block with just the symbol table, and then one 189 * of the argstate_add_XXX() functions is used as needed 190 * to fetch the additional sections. 191 * 192 * entry: 193 * argstate - Overall state block 194 * symstate - State block for current symbol table. 195 * 196 * exit: 197 * If the needed auxiliary section is not found, an error is 198 * issued and the argstate_add_XXX() routine does not return. 199 * Otherwise, the fields in argstate have been filled in, ready 200 * for use. 201 * 202 */ 203 static void 204 symstate_add_str(ARGSTATE *argstate, SYMSTATE *symstate) 205 { 206 if (symstate->str.sec != NULL) 207 return; 208 209 symstate->str.sec = elfedit_sec_getstr(argstate->obj_state, 210 symstate->sym.sec->sec_shdr->sh_link, 0); 211 } 212 static void 213 symstate_add_versym(ARGSTATE *argstate, SYMSTATE *symstate) 214 { 215 if (symstate->versym.sec != NULL) 216 return; 217 218 symstate->versym.sec = elfedit_sec_getversym(argstate->obj_state, 219 symstate->sym.sec, &symstate->versym.data, &symstate->versym.n); 220 } 221 static void 222 symstate_add_xshndx(ARGSTATE *argstate, SYMSTATE *symstate) 223 { 224 if (symstate->xshndx.sec != NULL) 225 return; 226 227 symstate->xshndx.sec = elfedit_sec_getxshndx(argstate->obj_state, 228 symstate->sym.sec, &symstate->xshndx.data, &symstate->xshndx.n); 229 } 230 231 232 233 /* 234 * Display symbol table entries in the style used by elfdump. 235 * 236 * entry: 237 * argstate - Overall state block 238 * symstate - State block for current symbol table. 239 * ndx - Index of first symbol to display 240 * cnt - Number of symbols to display 241 */ 242 static void 243 dump_symtab(ARGSTATE *argstate, SYMSTATE *symstate, Word ndx, Word cnt) 244 { 245 char index[MAXNDXSIZE]; 246 Word shndx; 247 const char *shndx_name; 248 elfedit_section_t *symsec; 249 elfedit_section_t *strsec; 250 Sym *sym; 251 elfedit_obj_state_t *obj_state = argstate->obj_state; 252 uchar_t osabi = obj_state->os_ehdr->e_ident[EI_OSABI]; 253 Half mach = obj_state->os_ehdr->e_machine; 254 const char *symname; 255 Versym versym; 256 257 symsec = symstate->sym.sec; 258 sym = symstate->sym.data + ndx; 259 260 symstate_add_str(argstate, symstate); 261 strsec = symstate->str.sec; 262 263 /* If there is a versym index section, fetch it */ 264 if (symstate->versym.shndx != SHN_UNDEF) 265 symstate_add_versym(argstate, symstate); 266 267 /* If there is an extended index section, fetch it */ 268 if (symstate->xshndx.shndx != SHN_UNDEF) 269 symstate_add_xshndx(argstate, symstate); 270 271 elfedit_printf(MSG_INTL(MSG_FMT_SYMTAB), symsec->sec_name); 272 Elf_syms_table_title(0, ELF_DBG_ELFDUMP); 273 for (; cnt-- > 0; ndx++, sym++) { 274 (void) snprintf(index, MAXNDXSIZE, 275 MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(ndx)); 276 versym = (symstate->versym.sec == NULL) ? 0 : 277 symstate->versym.data[ndx]; 278 symname = elfedit_offset_to_str(strsec, sym->st_name, 279 ELFEDIT_MSG_DEBUG, 0); 280 shndx = sym->st_shndx; 281 if ((shndx == SHN_XINDEX) && (symstate->xshndx.sec != NULL)) 282 shndx = symstate->xshndx.data[ndx]; 283 shndx_name = elfedit_shndx_to_name(obj_state, shndx); 284 Elf_syms_table_entry(NULL, ELF_DBG_ELFDUMP, index, osabi, mach, 285 sym, versym, 0, shndx_name, symname); 286 } 287 } 288 289 290 291 /* 292 * Called by print_sym() to determine if a given symbol has the same 293 * display value for the current command in every symbol table. 294 * 295 * entry: 296 * cmd - SYM_CMD_T_* value giving identify of caller 297 * argstate - Overall state block 298 * outstyle - Output style to use 299 */ 300 static int 301 all_same(SYM_CMD_T cmd, ARGSTATE *argstate, elfedit_outstyle_t outstyle) 302 { 303 Word tblndx; 304 SYMSTATE *symstate1, *symstate2; 305 Sym *sym1, *sym2; 306 307 symstate1 = argstate->symstate; 308 for (tblndx = 0; tblndx < (argstate->numsymstate - 1); 309 tblndx++, symstate1++) { 310 symstate2 = symstate1 + 1; 311 sym1 = &symstate1->sym.data[symstate1->ndx]; 312 sym2 = &symstate2->sym.data[symstate2->ndx]; 313 314 switch (cmd) { 315 case SYM_CMD_T_DUMP: 316 /* sym:dump should always show everything */ 317 return (0); 318 319 case SYM_CMD_T_ST_BIND: 320 if (ELF_ST_BIND(sym1->st_info) != 321 ELF_ST_BIND(sym2->st_info)) 322 return (0); 323 break; 324 325 case SYM_CMD_T_ST_INFO: 326 if (sym1->st_info != sym2->st_info) 327 return (0); 328 break; 329 330 case SYM_CMD_T_ST_NAME: 331 /* 332 * In simple output mode, we show the string. In 333 * numeric mode, we show the string table offset. 334 */ 335 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 336 const char *n1, *n2; 337 338 symstate_add_str(argstate, symstate1); 339 symstate_add_str(argstate, symstate2); 340 n1 = elfedit_offset_to_str(symstate1->str.sec, 341 sym1->st_name, ELFEDIT_MSG_DEBUG, 0); 342 n2 = elfedit_offset_to_str(symstate2->str.sec, 343 sym2->st_name, ELFEDIT_MSG_DEBUG, 0); 344 if (strcmp(n1, n2) != 0) 345 return (0); 346 } else { 347 if (sym1->st_name != sym2->st_name) 348 return (0); 349 } 350 break; 351 352 case SYM_CMD_T_ST_OTHER: 353 if (sym1->st_other != sym2->st_other) 354 return (0); 355 break; 356 357 case SYM_CMD_T_ST_SHNDX: 358 { 359 Word ndx1, ndx2; 360 361 ndx1 = sym1->st_shndx; 362 if ((ndx1 == SHN_XINDEX) && 363 (symstate1->xshndx.shndx != SHN_UNDEF)) { 364 symstate_add_xshndx(argstate, 365 symstate1); 366 ndx1 = symstate1->xshndx. 367 data[symstate1->ndx]; 368 } 369 ndx2 = sym2->st_shndx; 370 if ((ndx2 == SHN_XINDEX) && 371 (symstate2->xshndx.shndx != SHN_UNDEF)) { 372 symstate_add_xshndx(argstate, 373 symstate2); 374 ndx2 = symstate2->xshndx. 375 data[symstate2->ndx]; 376 } 377 if (ndx1 != ndx2) 378 return (0); 379 } 380 break; 381 382 case SYM_CMD_T_ST_SIZE: 383 if (sym1->st_size != sym2->st_size) 384 return (0); 385 break; 386 387 case SYM_CMD_T_ST_TYPE: 388 if (ELF_ST_TYPE(sym1->st_info) != 389 ELF_ST_TYPE(sym2->st_info)) 390 return (0); 391 break; 392 393 case SYM_CMD_T_ST_VALUE: 394 if (sym1->st_value != sym2->st_value) 395 return (0); 396 break; 397 398 case SYM_CMD_T_ST_VISIBILITY: 399 if (ELF_ST_VISIBILITY(sym1->st_info) != 400 ELF_ST_VISIBILITY(sym2->st_info)) 401 return (0); 402 break; 403 } 404 } 405 406 /* If we got here, there are no differences (or maybe only 1 table */ 407 return (1); 408 } 409 410 411 /* 412 * Called by print_sym() to display values for a single symbol table. 413 * 414 * entry: 415 * autoprint - If True, output is only produced if the elfedit 416 * autoprint flag is set. If False, output is always produced. 417 * cmd - SYM_CMD_T_* value giving identify of caller 418 * argstate - Overall state block 419 * symstate - State block for current symbol table. 420 * ndx - Index of first symbol to display 421 * cnt - Number of symbols to display 422 */ 423 static void 424 print_symstate(SYM_CMD_T cmd, ARGSTATE *argstate, SYMSTATE *symstate, 425 elfedit_outstyle_t outstyle, Word ndx, Word cnt) 426 { 427 Word value; 428 Sym *sym; 429 430 /* 431 * If doing default output, use elfdump style where we 432 * show all symbol attributes. In this case, the command 433 * that called us doesn't matter 434 */ 435 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 436 dump_symtab(argstate, symstate, ndx, cnt); 437 return; 438 } 439 440 sym = symstate->sym.data; 441 442 switch (cmd) { 443 case SYM_CMD_T_ST_BIND: 444 { 445 Conv_inv_buf_t inv_buf; 446 447 for (sym += ndx; cnt--; sym++) { 448 value = ELF_ST_BIND(sym->st_info); 449 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 450 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 451 conv_sym_info_bind(value, 452 CONV_FMT_ALT_CF, &inv_buf)); 453 } else { 454 elfedit_printf( 455 MSG_ORIG(MSG_FMT_WORDVALNL), 456 EC_WORD(value)); 457 } 458 } 459 } 460 return; 461 462 case SYM_CMD_T_ST_INFO: 463 for (sym += ndx; cnt-- > 0; sym++) 464 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 465 EC_WORD(sym->st_info)); 466 return; 467 468 case SYM_CMD_T_ST_NAME: 469 /* 470 * In simple output mode, we show the string. In numeric 471 * mode, we show the string table offset. 472 */ 473 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 474 symstate_add_str(argstate, symstate); 475 for (sym += ndx; cnt--; sym++) { 476 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 477 elfedit_offset_to_str(symstate->str.sec, 478 sym->st_name, ELFEDIT_MSG_ERR, 0)); 479 } 480 } else { 481 for (; cnt--; sym++) 482 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 483 EC_WORD(sym->st_name)); 484 } 485 return; 486 487 case SYM_CMD_T_ST_OTHER: 488 for (sym += ndx; cnt-- > 0; sym++) 489 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 490 EC_WORD(sym->st_other)); 491 return; 492 493 case SYM_CMD_T_ST_SHNDX: 494 /* If there is an extended index section, fetch it */ 495 if (symstate->xshndx.shndx != SHN_UNDEF) 496 symstate_add_xshndx(argstate, symstate); 497 498 for (; cnt--; ndx++) { 499 value = sym[ndx].st_shndx; 500 if ((value == SHN_XINDEX) && 501 (symstate->xshndx.sec != NULL)) 502 value = symstate->xshndx.data[ndx]; 503 504 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 505 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 506 elfedit_shndx_to_name(argstate->obj_state, 507 value)); 508 } else { 509 elfedit_printf(MSG_ORIG(MSG_FMT_WORDVALNL), 510 EC_WORD(value)); 511 } 512 } 513 return; 514 515 case SYM_CMD_T_ST_SIZE: 516 /* 517 * machine word width integers displayed in fixed width 518 * 0-filled hex format. 519 */ 520 for (sym += ndx; cnt--; sym++) 521 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDVALNL), 522 sym->st_size); 523 return; 524 525 case SYM_CMD_T_ST_TYPE: 526 { 527 Half mach = argstate->obj_state->os_ehdr->e_machine; 528 Conv_inv_buf_t inv_buf; 529 530 for (sym += ndx; cnt--; sym++) { 531 value = ELF_ST_TYPE(sym->st_info); 532 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 533 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 534 conv_sym_info_type(mach, value, 535 CONV_FMT_ALT_CF, &inv_buf)); 536 } else { 537 elfedit_printf( 538 MSG_ORIG(MSG_FMT_WORDVALNL), 539 EC_WORD(value)); 540 } 541 } 542 } 543 return; 544 545 case SYM_CMD_T_ST_VALUE: 546 /* 547 * machine word width integers displayed in fixed width 548 * 0-filled hex format. 549 */ 550 for (sym += ndx; cnt--; sym++) 551 elfedit_printf(MSG_ORIG(MSG_FMT_XWORDVALNL), 552 sym->st_value); 553 return; 554 555 case SYM_CMD_T_ST_VISIBILITY: 556 { 557 Conv_inv_buf_t inv_buf; 558 559 for (sym += ndx; cnt--; sym++) { 560 value = ELF_ST_VISIBILITY(sym->st_other); 561 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 562 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 563 conv_sym_other_vis(value, 564 CONV_FMT_ALT_CF, &inv_buf)); 565 } else { 566 elfedit_printf( 567 MSG_ORIG(MSG_FMT_WORDVALNL), 568 EC_WORD(value)); 569 } 570 } 571 } 572 return; 573 574 } 575 } 576 577 578 /* 579 * Print symbol values, taking the calling command, and output style 580 * into account. 581 * 582 * entry: 583 * autoprint - If True, output is only produced if the elfedit 584 * autoprint flag is set. If False, output is always produced. 585 * cmd - SYM_CMD_T_* value giving identify of caller 586 * argstate - Overall state block 587 * symstate - State block for current symbol table. 588 * ndx - Index of first symbol to display 589 * cnt - Number of symbols to display 590 */ 591 static void 592 print_sym(SYM_CMD_T cmd, int autoprint, ARGSTATE *argstate) 593 { 594 Word ndx, tblndx; 595 Word cnt; 596 elfedit_outstyle_t outstyle; 597 SYMSTATE *symstate; 598 int only_one; 599 600 if ((autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))) 601 return; 602 603 /* 604 * Pick an output style. sym:dump is required to use the default 605 * style. The other commands use the current output style. 606 */ 607 outstyle = (cmd == SYM_CMD_T_DUMP) ? 608 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 609 610 /* 611 * This is a nicity: Force any needed auxiliary sections to be 612 * fetched here before any output is produced. This will put all 613 * of the debug messages right at the top in a single cluster. 614 */ 615 symstate = argstate->symstate; 616 for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) { 617 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 618 symstate_add_str(argstate, symstate); 619 if (symstate->versym.shndx != SHN_UNDEF) 620 symstate_add_versym(argstate, symstate); 621 if (symstate->xshndx.shndx != SHN_UNDEF) 622 symstate_add_xshndx(argstate, symstate); 623 continue; 624 } 625 626 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 627 switch (cmd) { 628 case SYM_CMD_T_ST_NAME: 629 symstate_add_str(argstate, symstate); 630 break; 631 632 case SYM_CMD_T_ST_SHNDX: 633 if (symstate->xshndx.shndx != SHN_UNDEF) 634 symstate_add_xshndx(argstate, symstate); 635 break; 636 } 637 } 638 } 639 640 /* 641 * If there is more than one table, we are displaying a single 642 * item, we are not using the default "elfdump" style, and all 643 * the symbols have the same value for the thing we intend to 644 * display, then we only want to display it once. 645 */ 646 only_one = (argstate->numsymstate > 1) && (argstate->argc > 0) && 647 (outstyle != ELFEDIT_OUTSTYLE_DEFAULT) && 648 all_same(cmd, argstate, outstyle); 649 650 /* Run through the tables and display from each one */ 651 symstate = argstate->symstate; 652 for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) { 653 if (argstate->argc == 0) { 654 ndx = 0; 655 cnt = symstate->sym.n; 656 } else { 657 ndx = symstate->ndx; 658 cnt = 1; 659 } 660 661 if ((tblndx > 0) && ((argstate->argc == 0) || 662 (outstyle == ELFEDIT_OUTSTYLE_DEFAULT))) 663 elfedit_printf(MSG_ORIG(MSG_STR_NL)); 664 665 print_symstate(cmd, argstate, symstate, outstyle, ndx, cnt); 666 if (only_one) 667 break; 668 } 669 } 670 671 672 /* 673 * The cmd_body_set_st_XXX() functions are for use by cmd_body(). 674 * They handle the case where the second plain argument is 675 * a value to be stored in the symbol. 676 * 677 * entry: 678 * argstate - Overall state block 679 * symstate - State block for current symbol table. 680 */ 681 static elfedit_cmdret_t 682 cmd_body_set_st_bind(ARGSTATE *argstate, SYMSTATE *symstate) 683 { 684 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 685 Sym *sym = &symstate->sym.data[symstate->ndx]; 686 Word gbl_ndx; 687 uchar_t bind, type, old_bind; 688 Word symndx; 689 Conv_inv_buf_t inv_buf1, inv_buf2; 690 691 /* 692 * Use the ELF_ST_BIND() macro to access the defined bits 693 * of the st_info field related to symbol binding. 694 * Accepts STB_ symbolic names as well as integers. 695 */ 696 bind = elfedit_atoconst_range(argstate->argv[1], 697 MSG_INTL(MSG_ARG_SYMBIND), 0, 15, ELFEDIT_CONST_STB); 698 old_bind = ELF_ST_BIND(sym->st_info); 699 type = ELF_ST_TYPE(sym->st_info); 700 701 if (old_bind == bind) { 702 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK), 703 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 704 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_BIND), 705 conv_sym_info_bind(bind, CONV_FMT_ALT_CF, &inv_buf1)); 706 } else { 707 /* 708 * The sh_info field of the symbol table section header 709 * gives the index of the first non-local symbol in 710 * the table. Issue warnings if the binding we set 711 * contradicts this. 712 */ 713 gbl_ndx = symstate->sym.sec->sec_shdr->sh_info; 714 symndx = symstate->sym.sec->sec_shndx; 715 if ((bind == STB_LOCAL) && (symstate->ndx >= gbl_ndx)) 716 elfedit_msg(ELFEDIT_MSG_DEBUG, 717 MSG_INTL(MSG_DEBUG_LBINDGSYM), 718 EC_WORD(symndx), symstate->sym.sec->sec_name, 719 symstate->ndx, EC_WORD(symndx), gbl_ndx); 720 if ((bind != STB_LOCAL) && (symstate->ndx < gbl_ndx)) 721 elfedit_msg(ELFEDIT_MSG_DEBUG, 722 MSG_INTL(MSG_DEBUG_GBINDLSYM), 723 EC_WORD(symndx), symstate->sym.sec->sec_name, 724 symstate->ndx, EC_WORD(symndx), gbl_ndx); 725 726 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG), 727 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 728 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_BIND), 729 conv_sym_info_bind(old_bind, CONV_FMT_ALT_CF, 730 &inv_buf1), 731 conv_sym_info_bind(bind, CONV_FMT_ALT_CF, &inv_buf2)); 732 ret = ELFEDIT_CMDRET_MOD; 733 sym->st_info = ELF_ST_INFO(bind, type); 734 } 735 736 return (ret); 737 } 738 739 static elfedit_cmdret_t 740 cmd_body_set_st_name(ARGSTATE *argstate, SYMSTATE *symstate) 741 { 742 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 743 Sym *sym = &symstate->sym.data[symstate->ndx]; 744 Word str_offset; 745 746 /* 747 * If -n was specified, this is an offset into the string 748 * table. Otherwise it is a string we need to turn into 749 * an offset 750 */ 751 symstate_add_str(argstate, symstate); 752 if (argstate->optmask & SYM_OPT_F_NAMOFFSET) { 753 str_offset = elfedit_atoui(argstate->argv[1], NULL); 754 /* Warn if the offset is out of range */ 755 (void) elfedit_offset_to_str(symstate->str.sec, 756 str_offset, ELFEDIT_MSG_DEBUG, 1); 757 } else { 758 str_offset = elfedit_strtab_insert(argstate->obj_state, 759 symstate->str.sec, NULL, argstate->argv[1]); 760 } 761 762 if (sym->st_name == str_offset) { 763 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_D_OK), 764 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 765 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_NAME), 766 EC_WORD(sym->st_name)); 767 } else { 768 /* 769 * Warn the user: Changing the name of a symbol in the dynsym 770 * will break the hash table in this object. 771 */ 772 if (symstate->sym.sec->sec_shdr->sh_type == SHT_DYNSYM) 773 elfedit_msg(ELFEDIT_MSG_DEBUG, 774 MSG_INTL(MSG_DEBUG_DYNSYMNAMCHG), 775 EC_WORD(symstate->sym.sec->sec_shndx), 776 symstate->sym.sec->sec_name, 777 EC_WORD(symstate->ndx)); 778 779 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_D_CHG), 780 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 781 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_NAME), 782 EC_WORD(sym->st_name), 783 EC_WORD(str_offset)); 784 ret = ELFEDIT_CMDRET_MOD; 785 sym->st_name = str_offset; 786 } 787 788 return (ret); 789 } 790 791 static elfedit_cmdret_t 792 cmd_body_set_st_shndx(ARGSTATE *argstate, SYMSTATE *symstate) 793 { 794 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 795 Sym *sym = &symstate->sym.data[symstate->ndx]; 796 Word shndx, st_shndx, xshndx; 797 int use_xshndx; 798 int shndx_chg, xshndx_chg; 799 800 801 /* 802 * By default, the sec argument is a section name. If -secshndx was 803 * specified, it is a section index, and if -secshtyp is specified, 804 * it is a section type. 805 */ 806 if (argstate->optmask & SYM_OPT_F_SECSHNDX) 807 shndx = elfedit_atoshndx(argstate->argv[1], 808 argstate->obj_state->os_shnum); 809 else if (argstate->optmask & SYM_OPT_F_SECSHTYP) 810 shndx = elfedit_type_to_shndx(argstate->obj_state, 811 elfedit_atoconst(argstate->argv[1], ELFEDIT_CONST_SHT)); 812 else 813 shndx = elfedit_name_to_shndx(argstate->obj_state, 814 argstate->argv[1]); 815 816 /* 817 * We want to use an extended index section if the index is too 818 * large to be represented otherwise, or if the caller specified 819 * the -e option to make us do it anyway. However, we cannot 820 * do this if the index is in the special reserved range between 821 * SHN_LORESERVE and SHN_HIRESERVE. 822 */ 823 use_xshndx = (shndx > SHN_HIRESERVE) || 824 ((shndx < SHN_LORESERVE) && 825 (argstate->optmask & SYM_OPT_F_XSHINDEX)); 826 827 /* 828 * There are two cases where we have to touch the extended 829 * index section: 830 * 831 * 1) We have determined that we need to, as determined above. 832 * 2) We do not require it, but the file has an extended 833 * index section, in which case we should set the slot 834 * in that extended section to SHN_UNDEF (0). 835 * 836 * Fetch the extended section as required, and determine the values 837 * for st_shndx and the extended section slot. 838 */ 839 if (use_xshndx) { 840 /* We must have an extended index section, or error out */ 841 symstate_add_xshndx(argstate, symstate); 842 843 /* Set symbol to SHN_XINDEX, put index in the extended sec. */ 844 st_shndx = SHN_XINDEX; 845 xshndx = shndx; 846 } else { 847 st_shndx = shndx; 848 xshndx = SHN_UNDEF; 849 if (symstate->xshndx.shndx != SHN_UNDEF) 850 use_xshndx = 1; 851 } 852 if (use_xshndx) 853 symstate_add_xshndx(argstate, symstate); 854 shndx_chg = (sym->st_shndx != st_shndx); 855 xshndx_chg = use_xshndx && 856 (symstate->xshndx.data[symstate->ndx] != xshndx); 857 858 859 /* If anything is going to change, issue appropiate warnings */ 860 if (shndx_chg || xshndx_chg) { 861 /* 862 * Setting the first symbol to anything other than SHN_UNDEF 863 * produces a bad ELF file. 864 */ 865 if ((symstate->ndx == 0) && (shndx != SHN_UNDEF)) 866 elfedit_msg(ELFEDIT_MSG_DEBUG, 867 MSG_INTL(MSG_DEBUG_SHNDX_UNDEF0)); 868 869 /* 870 * Setting SHN_XINDEX directly, instead of providing 871 * an extended index and letting us decide to use 872 * SHN_XINDEX to implement it, is probably a mistake. 873 * Issue a warning, but go ahead and follow the directions 874 * we've been given. 875 */ 876 if (shndx == SHN_XINDEX) 877 elfedit_msg(ELFEDIT_MSG_DEBUG, 878 MSG_INTL(MSG_DEBUG_SHNDX_XINDEX)); 879 880 /* 881 * If the section index can fit in the symbol, but 882 * -e is being used to force it into the extended 883 * index section, issue a warning. 884 */ 885 if (use_xshndx && (shndx < SHN_LORESERVE) && 886 (st_shndx == SHN_XINDEX)) 887 elfedit_msg(ELFEDIT_MSG_DEBUG, 888 MSG_INTL(MSG_DEBUG_SHNDX_EFORCE), 889 EC_WORD(symstate->sym.sec->sec_shndx), 890 symstate->sym.sec->sec_name, EC_WORD(symstate->ndx), 891 EC_WORD(shndx)); 892 } 893 894 if (shndx_chg) { 895 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG), 896 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 897 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_SHNDX), 898 elfedit_shndx_to_name(argstate->obj_state, 899 sym->st_shndx), 900 elfedit_shndx_to_name(argstate->obj_state, st_shndx)); 901 ret = ELFEDIT_CMDRET_MOD; 902 sym->st_shndx = st_shndx; 903 } else { 904 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK), 905 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 906 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_SHNDX), 907 elfedit_shndx_to_name(argstate->obj_state, st_shndx)); 908 } 909 910 if (use_xshndx) { 911 if (xshndx_chg) { 912 elfedit_msg(ELFEDIT_MSG_DEBUG, 913 MSG_INTL(MSG_DEBUG_EXT_S_CHG), 914 symstate->xshndx.sec->sec_shndx, 915 symstate->xshndx.sec->sec_name, 916 EC_WORD(symstate->ndx), 917 elfedit_shndx_to_name(argstate->obj_state, 918 symstate->xshndx.data[symstate->ndx]), 919 elfedit_shndx_to_name(argstate->obj_state, xshndx)); 920 ret = ELFEDIT_CMDRET_MOD; 921 symstate->xshndx.data[symstate->ndx] = xshndx; 922 elfedit_modified_data(symstate->xshndx.sec); 923 } else { 924 elfedit_msg(ELFEDIT_MSG_DEBUG, 925 MSG_INTL(MSG_DEBUG_EXT_S_OK), 926 symstate->xshndx.sec->sec_shndx, 927 symstate->xshndx.sec->sec_name, 928 EC_WORD(symstate->ndx), 929 elfedit_shndx_to_name(argstate->obj_state, xshndx)); 930 } 931 } 932 933 return (ret); 934 } 935 936 static elfedit_cmdret_t 937 cmd_body_set_st_type(ARGSTATE *argstate, SYMSTATE *symstate) 938 { 939 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 940 Conv_inv_buf_t inv_buf1, inv_buf2; 941 Half mach = argstate->obj_state->os_ehdr->e_machine; 942 Sym *sym = &symstate->sym.data[symstate->ndx]; 943 uchar_t bind, type, old_type; 944 945 /* 946 * Use the ELF_ST_TYPE() macro to access the defined bits 947 * of the st_info field related to symbol type. 948 * Accepts STT_ symbolic names as well as integers. 949 */ 950 bind = ELF_ST_BIND(sym->st_info); 951 type = elfedit_atoconst_range(argstate->argv[1], 952 MSG_INTL(MSG_ARG_SYMBIND), 0, 15, ELFEDIT_CONST_STT); 953 old_type = ELF_ST_TYPE(sym->st_info); 954 955 if (old_type == type) { 956 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK), 957 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 958 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_TYPE), 959 conv_sym_info_type(mach, type, CONV_FMT_ALT_CF, 960 &inv_buf1)); 961 } else { 962 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG), 963 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 964 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_TYPE), 965 conv_sym_info_type(mach, old_type, CONV_FMT_ALT_CF, 966 &inv_buf1), 967 conv_sym_info_type(mach, type, CONV_FMT_ALT_CF, 968 &inv_buf2)); 969 ret = ELFEDIT_CMDRET_MOD; 970 sym->st_info = ELF_ST_INFO(bind, type); 971 } 972 973 return (ret); 974 } 975 976 static elfedit_cmdret_t 977 cmd_body_set_st_visibility(ARGSTATE *argstate, SYMSTATE *symstate) 978 { 979 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 980 Conv_inv_buf_t inv_buf1, inv_buf2; 981 Sym *sym = &symstate->sym.data[symstate->ndx]; 982 uchar_t st_other = sym->st_other; 983 uchar_t vis, old_vis; 984 985 /* 986 * Use the ELF_ST_VISIBILITY() macro to access the 987 * defined bits of the st_other field related to symbol 988 * visibility. Accepts STV_ symbolic names as well as integers. 989 */ 990 vis = elfedit_atoconst_range(argstate->argv[1], 991 MSG_INTL(MSG_ARG_SYMVIS), 0, STV_ELIMINATE, ELFEDIT_CONST_STV); 992 old_vis = st_other & MSK_SYM_VISIBILITY; 993 994 if (old_vis == vis) { 995 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK), 996 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 997 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_VISIBILITY), 998 conv_sym_other_vis(old_vis, CONV_FMT_ALT_CF, 999 &inv_buf1)); 1000 } else { 1001 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG), 1002 symstate->sym.sec->sec_shndx, symstate->sym.sec->sec_name, 1003 EC_WORD(symstate->ndx), MSG_ORIG(MSG_CMD_ST_VISIBILITY), 1004 conv_sym_other_vis(old_vis, CONV_FMT_ALT_CF, 1005 &inv_buf1), 1006 conv_sym_other_vis(vis, CONV_FMT_ALT_CF, &inv_buf2)); 1007 ret = ELFEDIT_CMDRET_MOD; 1008 st_other = (st_other & ~MSK_SYM_VISIBILITY) | 1009 ELF_ST_VISIBILITY(vis); 1010 sym->st_other = st_other; 1011 } 1012 1013 return (ret); 1014 } 1015 1016 1017 /* 1018 * Standard argument processing for sym module 1019 * 1020 * entry 1021 * obj_state, argc, argv - Standard command arguments 1022 * optmask - Mask of allowed optional arguments. 1023 * symstate - State block for current symbol table. 1024 * argstate - Address of ARGSTATE block to be initialized 1025 * 1026 * exit: 1027 * On success, *argstate is initialized. On error, 1028 * an error is issued and this routine does not return. 1029 * 1030 * note: 1031 * Only the basic symbol table is initially referenced by 1032 * argstate. Use the argstate_add_XXX() routines below to 1033 * access any auxiliary sections needed. 1034 */ 1035 static ARGSTATE * 1036 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 1037 SYM_CMD_T cmd) 1038 { 1039 /* 1040 * We reuse this same argstate, resizing it to the required 1041 * number of symbol tables on the first call, and as necessary. 1042 */ 1043 static ARGSTATE *argstate; 1044 static int argstate_size = 0; 1045 1046 elfedit_getopt_state_t getopt_state; 1047 elfedit_getopt_ret_t *getopt_ret; 1048 elfedit_symtab_t *symtab; 1049 int explicit = 0; 1050 int got_sym = 0; 1051 Word index; 1052 Word tblndx; 1053 size_t size; 1054 SYMSTATE *symstate; 1055 1056 /* If there are no symbol tables, we can't do a thing */ 1057 if (obj_state->os_symtabnum == 0) 1058 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMTAB)); 1059 1060 /* Calulate required size of argstate and realloc as necessary */ 1061 size = sizeof (ARGSTATE) + 1062 ((obj_state->os_symtabnum - 1) * sizeof (SYMSTATE)); 1063 if (argstate_size != size) { 1064 argstate = elfedit_realloc(MSG_INTL(MSG_ALLOC_ARGSTATE), 1065 argstate, size); 1066 argstate_size = size; 1067 } 1068 bzero(argstate, argstate_size); 1069 argstate->obj_state = obj_state; 1070 1071 elfedit_getopt_init(&getopt_state, &argc, &argv); 1072 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) { 1073 argstate->optmask |= getopt_ret->gor_idmask; 1074 switch (getopt_ret->gor_idmask) { 1075 case SYM_OPT_F_SHNAME: /* -shnam name */ 1076 index = elfedit_name_to_shndx(obj_state, 1077 getopt_ret->gor_value); 1078 explicit = 1; 1079 break; 1080 1081 case SYM_OPT_F_SHNDX: /* -shndx index */ 1082 index = elfedit_atoui_range(getopt_ret->gor_value, 1083 MSG_INTL(MSG_ARG_SECNDX), 1, 1084 obj_state->os_shnum - 1, NULL); 1085 explicit = 1; 1086 break; 1087 1088 case SYM_OPT_F_SHTYP: /* -shtyp type */ 1089 index = elfedit_type_to_shndx(obj_state, 1090 elfedit_atoconst(getopt_ret->gor_value, 1091 ELFEDIT_CONST_SHT)); 1092 explicit = 1; 1093 break; 1094 } 1095 } 1096 1097 /* 1098 * Usage error if there are too many plain arguments. sym:dump accepts 1099 * a single argument, while the others accept 2. 1100 */ 1101 if (((cmd == SYM_CMD_T_DUMP) && (argc > 1)) || (argc > 2)) 1102 elfedit_command_usage(); 1103 1104 /* 1105 * If the -symndx option was specified, the sym arg is an index 1106 * into the symbol table. In this case, the symbol table must be 1107 * explicitly specified (-shnam, -shndx, or -shtype). 1108 */ 1109 if ((argstate->optmask & SYM_OPT_F_SYMNDX) && !explicit) 1110 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEXPSYMTAB)); 1111 1112 /* 1113 * If a section was explicitly specified, it must be a symbol table. 1114 */ 1115 if (explicit) 1116 (void) elfedit_sec_issymtab(obj_state, 1117 &obj_state->os_secarr[index], 1, NULL); 1118 1119 /* If there may be an arbitrary amount of output, use a pager */ 1120 if (argc == 0) 1121 elfedit_pager_init(); 1122 1123 /* Return the updated values of argc/argv */ 1124 argstate->argc = argc; 1125 argstate->argv = argv; 1126 1127 /* 1128 * Decide which symbol table(s) to use. Set up the symstate 1129 * array to contain them: 1130 * - If a symbol table was explicitly specified, we use 1131 * it, and only it. 1132 * - If no symbol table is explicitly specified, and the symbol 1133 * is given by name, we use all symbol tables that 1134 * contain a symbol with that name, throwing an error 1135 * if there isn't at least 1 such table. 1136 * - If no symbol table is specified, and no symbol is specified, 1137 * we use all the tables. 1138 */ 1139 symtab = obj_state->os_symtab; 1140 symstate = argstate->symstate; 1141 for (tblndx = 0; tblndx < obj_state->os_symtabnum; 1142 tblndx++, symtab++) { 1143 /* 1144 * If an explicit table is specified, only that table is 1145 * considered. 1146 * 1147 * If no explicit table is specified, verify that table 1148 * is considered to be a symbol table by the current osabi, 1149 * and quietly skip it if not. 1150 */ 1151 if (explicit) { 1152 if (symtab->symt_shndx != index) 1153 continue; 1154 } else if (elfedit_sec_issymtab(obj_state, 1155 &obj_state->os_secarr[symtab->symt_shndx], 0, NULL) == 0) { 1156 continue; 1157 } 1158 1159 symstate->sym.sec = elfedit_sec_getsymtab(obj_state, 1, 1160 symtab->symt_shndx, NULL, &symstate->sym.data, 1161 &symstate->sym.n, &symtab); 1162 symstate->versym.shndx = symtab->symt_versym; 1163 symstate->xshndx.shndx = symtab->symt_xshndx; 1164 if (argc > 0) { 1165 if (argstate->optmask & SYM_OPT_F_SYMNDX) { 1166 symstate->ndx = elfedit_atoui_range( 1167 argstate->argv[0], MSG_INTL(MSG_ARG_SYM), 0, 1168 symstate->sym.n - 1, NULL); 1169 } else { 1170 /* 1171 * arg is a symbol name. Use the index of 1172 * the first symbol that matches 1173 */ 1174 1175 /* 1176 * We will use debug messages for failure up 1177 * until we run out of symbol tables. If we 1178 * don't find a table with the desired symbol 1179 * before the last table, we switch to error 1180 * messages. Hence, we will jump with an error 1181 * if no table will work. 1182 */ 1183 int err_type = (!got_sym && 1184 ((tblndx + 1) == obj_state->os_symtabnum)) ? 1185 ELFEDIT_MSG_ERR : ELFEDIT_MSG_DEBUG; 1186 1187 symstate_add_str(argstate, symstate); 1188 1189 /* 1190 * If the symbol table doesn't have this 1191 * symbol, then forget it. 1192 */ 1193 if (elfedit_name_to_symndx(symstate->sym.sec, 1194 symstate->str.sec, argstate->argv[0], 1195 err_type, &symstate->ndx) == 0) { 1196 bzero(symstate, sizeof (*symstate)); 1197 continue; 1198 } 1199 } 1200 } 1201 argstate->numsymstate++; 1202 symstate++; 1203 /* 1204 * If the symbol table was given explicitly, and 1205 * we've just taken it, then there is no reason to 1206 * continue searching. 1207 */ 1208 if (explicit) 1209 break; 1210 } 1211 1212 return (argstate); 1213 } 1214 1215 1216 1217 /* 1218 * Called by cmd_body() to handle the value change for a single 1219 * symbol table. 1220 * 1221 * entry: 1222 * cmd - One of the SYM_CMD_T_* constants listed above, specifying 1223 * which command to implement. 1224 * argstate - Overall state block 1225 * symstate - State block for current symbol table. 1226 */ 1227 static elfedit_cmdret_t 1228 symstate_cmd_body(SYM_CMD_T cmd, ARGSTATE *argstate, SYMSTATE *symstate) 1229 { 1230 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 1231 Sym *sym = &symstate->sym.data[symstate->ndx]; 1232 1233 /* You're not supposed to change the value of symbol [0] */ 1234 if (symstate->ndx == 0) 1235 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSYMELT0), 1236 EC_WORD(symstate->sym.sec->sec_shndx), 1237 symstate->sym.sec->sec_name, EC_WORD(symstate->ndx)); 1238 1239 /* The second value is an integer giving a new value */ 1240 switch (cmd) { 1241 /* 1242 * SYM_CMD_T_DUMP can't get here: It never has more than 1243 * one argument, and is handled above. 1244 */ 1245 1246 case SYM_CMD_T_ST_BIND: 1247 ret = cmd_body_set_st_bind(argstate, symstate); 1248 break; 1249 1250 case SYM_CMD_T_ST_INFO: 1251 { 1252 /* Treat st_info as a raw integer field */ 1253 uchar_t st_info = 1254 elfedit_atoui(argstate->argv[1], NULL); 1255 1256 if (sym->st_info == st_info) { 1257 elfedit_msg(ELFEDIT_MSG_DEBUG, 1258 MSG_INTL(MSG_DEBUG_D_OK), 1259 symstate->sym.sec->sec_shndx, 1260 symstate->sym.sec->sec_name, 1261 EC_WORD(symstate->ndx), 1262 MSG_ORIG(MSG_CMD_ST_INFO), 1263 EC_WORD(sym->st_info)); 1264 } else { 1265 elfedit_msg(ELFEDIT_MSG_DEBUG, 1266 MSG_INTL(MSG_DEBUG_D_CHG), 1267 symstate->sym.sec->sec_shndx, 1268 symstate->sym.sec->sec_name, 1269 EC_WORD(symstate->ndx), 1270 MSG_ORIG(MSG_CMD_ST_INFO), 1271 EC_WORD(sym->st_info), EC_WORD(st_info)); 1272 ret = ELFEDIT_CMDRET_MOD; 1273 sym->st_info = st_info; 1274 } 1275 } 1276 break; 1277 1278 case SYM_CMD_T_ST_NAME: 1279 ret = cmd_body_set_st_name(argstate, symstate); 1280 break; 1281 1282 case SYM_CMD_T_ST_OTHER: 1283 { 1284 /* Treat st_other as a raw integer field */ 1285 uchar_t st_other = 1286 elfedit_atoui(argstate->argv[1], NULL); 1287 1288 if (sym->st_other == st_other) { 1289 elfedit_msg(ELFEDIT_MSG_DEBUG, 1290 MSG_INTL(MSG_DEBUG_D_OK), 1291 symstate->sym.sec->sec_shndx, 1292 symstate->sym.sec->sec_name, 1293 EC_WORD(symstate->ndx), 1294 MSG_ORIG(MSG_CMD_ST_OTHER), 1295 EC_WORD(sym->st_other)); 1296 } else { 1297 elfedit_msg(ELFEDIT_MSG_DEBUG, 1298 MSG_INTL(MSG_DEBUG_D_CHG), 1299 symstate->sym.sec->sec_shndx, 1300 symstate->sym.sec->sec_name, 1301 EC_WORD(symstate->ndx), 1302 MSG_ORIG(MSG_CMD_ST_OTHER), 1303 EC_WORD(sym->st_other), EC_WORD(st_other)); 1304 ret = ELFEDIT_CMDRET_MOD; 1305 sym->st_other = st_other; 1306 } 1307 } 1308 break; 1309 1310 case SYM_CMD_T_ST_SHNDX: 1311 ret = cmd_body_set_st_shndx(argstate, symstate); 1312 break; 1313 1314 case SYM_CMD_T_ST_SIZE: 1315 { 1316 Xword st_size = elfedit_atoui(argstate->argv[1], NULL); 1317 1318 if (sym->st_size == st_size) { 1319 elfedit_msg(ELFEDIT_MSG_DEBUG, 1320 MSG_INTL(MSG_DEBUG_LLX_OK), 1321 symstate->sym.sec->sec_shndx, 1322 symstate->sym.sec->sec_name, 1323 EC_WORD(symstate->ndx), 1324 MSG_ORIG(MSG_CMD_ST_SIZE), 1325 EC_XWORD(sym->st_size)); 1326 } else { 1327 elfedit_msg(ELFEDIT_MSG_DEBUG, 1328 MSG_INTL(MSG_DEBUG_LLX_CHG), 1329 symstate->sym.sec->sec_shndx, 1330 symstate->sym.sec->sec_name, 1331 EC_WORD(symstate->ndx), 1332 MSG_ORIG(MSG_CMD_ST_SIZE), 1333 EC_XWORD(sym->st_size), EC_XWORD(st_size)); 1334 ret = ELFEDIT_CMDRET_MOD; 1335 sym->st_size = st_size; 1336 } 1337 } 1338 break; 1339 1340 case SYM_CMD_T_ST_TYPE: 1341 ret = cmd_body_set_st_type(argstate, symstate); 1342 break; 1343 1344 case SYM_CMD_T_ST_VALUE: 1345 { 1346 Addr st_value = elfedit_atoui(argstate->argv[1], NULL); 1347 1348 if (sym->st_value == st_value) { 1349 elfedit_msg(ELFEDIT_MSG_DEBUG, 1350 MSG_INTL(MSG_DEBUG_LLX_OK), 1351 symstate->sym.sec->sec_shndx, 1352 symstate->sym.sec->sec_name, 1353 EC_WORD(symstate->ndx), 1354 MSG_ORIG(MSG_CMD_ST_VALUE), 1355 EC_ADDR(sym->st_value)); 1356 } else { 1357 elfedit_msg(ELFEDIT_MSG_DEBUG, 1358 MSG_INTL(MSG_DEBUG_LLX_CHG), 1359 symstate->sym.sec->sec_shndx, 1360 symstate->sym.sec->sec_name, 1361 EC_WORD(symstate->ndx), 1362 MSG_ORIG(MSG_CMD_ST_VALUE), 1363 EC_ADDR(sym->st_value), 1364 EC_ADDR(st_value)); 1365 ret = ELFEDIT_CMDRET_MOD; 1366 ret = ELFEDIT_CMDRET_MOD; 1367 sym->st_value = st_value; 1368 } 1369 } 1370 break; 1371 1372 case SYM_CMD_T_ST_VISIBILITY: 1373 ret = cmd_body_set_st_visibility(argstate, symstate); 1374 break; 1375 } 1376 1377 /* 1378 * If we modified the symbol table, tell libelf. 1379 * Any other modified sections are the responsibility 1380 * of the cmd_body_set_st_*() function that did it, but 1381 * everyone modifies the table itself, so we handle that here. 1382 */ 1383 if (ret == ELFEDIT_CMDRET_MOD) 1384 elfedit_modified_data(symstate->sym.sec); 1385 1386 return (ret); 1387 } 1388 1389 1390 1391 1392 /* 1393 * Common body for the sym: module commands. These commands 1394 * share a large amount of common behavior, so it is convenient 1395 * to centralize things and use the cmd argument to handle the 1396 * small differences. 1397 * 1398 * entry: 1399 * cmd - One of the SYM_CMD_T_* constants listed above, specifying 1400 * which command to implement. 1401 * obj_state, argc, argv - Standard command arguments 1402 */ 1403 static elfedit_cmdret_t 1404 cmd_body(SYM_CMD_T cmd, elfedit_obj_state_t *obj_state, 1405 int argc, const char *argv[]) 1406 { 1407 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 1408 ARGSTATE *argstate; 1409 SYMSTATE *symstate; 1410 Word tblndx; 1411 1412 argstate = process_args(obj_state, argc, argv, cmd); 1413 1414 /* 1415 * If there are not 2 arguments, then this is a display request. 1416 * If no arguments are present, the full table (or tables) is 1417 * dumped. If there is one argument, then the specified item is shown. 1418 */ 1419 if (argstate->argc < 2) { 1420 print_sym(cmd, 0, argstate); 1421 return (ELFEDIT_CMDRET_NONE); 1422 } 1423 1424 /* 1425 * When processing multiple symbol tables, it is important that 1426 * any failure happen before anything is changed. Otherwise, you 1427 * can end up in a situation where things are left in an inconsistent 1428 * half done state. sym:st_name has that issue when the -name_offset 1429 * option is used, because the string may be insertable into some 1430 * (dynstr) string tables, but not all of them. So, do the tests 1431 * up front, and refuse to continue if any string insertions would 1432 * fail. 1433 */ 1434 if ((cmd == SYM_CMD_T_ST_NAME) && (argstate->numsymstate > 1) && 1435 ((argstate->optmask & SYM_OPT_F_NAMOFFSET) == 0)) { 1436 symstate = argstate->symstate; 1437 for (tblndx = 0; tblndx < argstate->numsymstate; 1438 tblndx++, symstate++) 1439 elfedit_strtab_insert_test(obj_state, symstate->str.sec, 1440 NULL, argstate->argv[1]); 1441 } 1442 1443 1444 /* Loop over the table(s) and make the specified value change */ 1445 symstate = argstate->symstate; 1446 for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) 1447 if (symstate_cmd_body(cmd, argstate, symstate) == 1448 ELFEDIT_CMDRET_MOD) 1449 ret = ELFEDIT_CMDRET_MOD; 1450 1451 /* Do autoprint */ 1452 print_sym(cmd, 1, argstate); 1453 1454 return (ret); 1455 } 1456 1457 1458 1459 1460 /* 1461 * Command completion functions for the various commands 1462 */ 1463 1464 /* 1465 * Handle filling in the values for -shnam, -shndx, and -shtyp options. 1466 */ 1467 /*ARGSUSED*/ 1468 static void 1469 cpl_sh_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1470 const char *argv[], int num_opt) 1471 { 1472 enum { NAME, INDEX, TYPE } op; 1473 elfedit_symtab_t *symtab; 1474 Word tblndx; 1475 1476 if ((argc != num_opt) || (argc < 2)) 1477 return; 1478 1479 if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) { 1480 op = NAME; 1481 } else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) { 1482 op = INDEX; 1483 1484 } else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) { 1485 op = TYPE; 1486 if (obj_state == NULL) /* No object available */ 1487 elfedit_cpl_atoconst(cpldata, 1488 ELFEDIT_CONST_SHT_ALLSYMTAB); 1489 } else { 1490 return; 1491 } 1492 1493 if (obj_state == NULL) /* No object available */ 1494 return; 1495 1496 /* 1497 * Loop over the symbol tables and supply command completion 1498 * for the items in the file. 1499 */ 1500 symtab = obj_state->os_symtab; 1501 for (tblndx = 0; tblndx < obj_state->os_symtabnum; 1502 tblndx++, symtab++) { 1503 elfedit_section_t *sec = 1504 &obj_state->os_secarr[symtab->symt_shndx]; 1505 1506 switch (op) { 1507 case NAME: 1508 elfedit_cpl_match(cpldata, sec->sec_name, 0); 1509 break; 1510 case INDEX: 1511 elfedit_cpl_ndx(cpldata, symtab->symt_shndx); 1512 break; 1513 case TYPE: 1514 { 1515 elfedit_atoui_sym_t *cpl_list; 1516 1517 (void) elfedit_sec_issymtab(obj_state, 1518 sec, 1, &cpl_list); 1519 elfedit_cpl_atoui(cpldata, cpl_list); 1520 } 1521 break; 1522 } 1523 } 1524 } 1525 1526 /*ARGSUSED*/ 1527 static void 1528 cpl_st_bind(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1529 const char *argv[], int num_opt) 1530 { 1531 /* Handle -shXXX options */ 1532 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 1533 1534 /* The second argument can be an STB_ value */ 1535 if (argc == (num_opt + 2)) 1536 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STB); 1537 } 1538 1539 /*ARGSUSED*/ 1540 static void 1541 cpl_st_shndx(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1542 const char *argv[], int num_opt) 1543 { 1544 elfedit_section_t *sec; 1545 enum { NAME, INDEX, TYPE } op; 1546 Word ndx; 1547 1548 /* Handle -shXXX options */ 1549 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 1550 1551 /* 1552 * The second argument can be a section name, a section 1553 * index (-secshndx), or a section type (-secshtyp). We 1554 * can do completions for each of these. 1555 */ 1556 if (argc != (num_opt + 2)) 1557 return; 1558 1559 op = NAME; 1560 for (ndx = 0; ndx < num_opt; ndx++) { 1561 if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SECSHNDX)) == 0) 1562 op = INDEX; 1563 else if (strcmp(argv[ndx], 1564 MSG_ORIG(MSG_STR_MINUS_SECSHTYP)) == 0) 1565 op = TYPE; 1566 } 1567 1568 switch (op) { 1569 case NAME: 1570 if (obj_state == NULL) 1571 break; 1572 sec = obj_state->os_secarr; 1573 for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++) 1574 elfedit_cpl_match(cpldata, sec->sec_name, 0); 1575 break; 1576 1577 case INDEX: 1578 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHN); 1579 break; 1580 1581 case TYPE: 1582 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT); 1583 break; 1584 } 1585 } 1586 1587 /*ARGSUSED*/ 1588 static void 1589 cpl_st_type(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1590 const char *argv[], int num_opt) 1591 { 1592 /* Handle -shXXX options */ 1593 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 1594 1595 /* The second argument can be an STT_ value */ 1596 if (argc == (num_opt + 2)) 1597 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STT); 1598 } 1599 1600 /*ARGSUSED*/ 1601 static void 1602 cpl_st_visibility(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1603 const char *argv[], int num_opt) 1604 { 1605 /* Handle -shXXX options */ 1606 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 1607 1608 /* The second argument can be an STV_ value */ 1609 if (argc == (num_opt + 2)) 1610 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STV); 1611 } 1612 1613 1614 1615 /* 1616 * Implementation functions for the commands 1617 */ 1618 static elfedit_cmdret_t 1619 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1620 { 1621 return (cmd_body(SYM_CMD_T_DUMP, obj_state, argc, argv)); 1622 } 1623 1624 1625 static elfedit_cmdret_t 1626 cmd_st_bind(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1627 { 1628 return (cmd_body(SYM_CMD_T_ST_BIND, obj_state, argc, argv)); 1629 } 1630 1631 1632 static elfedit_cmdret_t 1633 cmd_st_info(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1634 { 1635 return (cmd_body(SYM_CMD_T_ST_INFO, obj_state, argc, argv)); 1636 } 1637 1638 static elfedit_cmdret_t 1639 cmd_st_name(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1640 { 1641 return (cmd_body(SYM_CMD_T_ST_NAME, obj_state, argc, argv)); 1642 } 1643 1644 static elfedit_cmdret_t 1645 cmd_st_other(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1646 { 1647 return (cmd_body(SYM_CMD_T_ST_OTHER, obj_state, argc, argv)); 1648 } 1649 1650 static elfedit_cmdret_t 1651 cmd_st_shndx(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1652 { 1653 return (cmd_body(SYM_CMD_T_ST_SHNDX, obj_state, argc, argv)); 1654 } 1655 1656 static elfedit_cmdret_t 1657 cmd_st_size(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1658 { 1659 return (cmd_body(SYM_CMD_T_ST_SIZE, obj_state, argc, argv)); 1660 } 1661 1662 static elfedit_cmdret_t 1663 cmd_st_type(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1664 { 1665 return (cmd_body(SYM_CMD_T_ST_TYPE, obj_state, argc, argv)); 1666 } 1667 1668 static elfedit_cmdret_t 1669 cmd_st_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1670 { 1671 return (cmd_body(SYM_CMD_T_ST_VALUE, obj_state, argc, argv)); 1672 } 1673 1674 static elfedit_cmdret_t 1675 cmd_st_visibility(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1676 { 1677 return (cmd_body(SYM_CMD_T_ST_VISIBILITY, obj_state, argc, argv)); 1678 } 1679 1680 1681 1682 /*ARGSUSED*/ 1683 elfedit_module_t * 1684 elfedit_init(elfedit_module_version_t version) 1685 { 1686 /* Multiple commands accept only the standard set of options */ 1687 static elfedit_cmd_optarg_t opt_std[] = { 1688 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 1689 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 1690 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 1691 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 1692 { MSG_ORIG(MSG_STR_NAME), NULL, 0 }, 1693 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1694 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1695 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 1696 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 1697 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 }, 1698 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1699 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1700 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 1701 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 1702 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 }, 1703 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 1704 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 1705 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, SYM_OPT_F_SYMNDX }, 1706 { ELFEDIT_STDOA_OPT_O, NULL, 1707 ELFEDIT_CMDOA_F_INHERIT, 0 }, 1708 { NULL } 1709 }; 1710 1711 /* sym:dump */ 1712 static const char *name_dump[] = { 1713 MSG_ORIG(MSG_CMD_DUMP), 1714 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 1715 NULL 1716 }; 1717 static elfedit_cmd_optarg_t opt_dump[] = { 1718 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 1719 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 1720 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 1721 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 1722 { MSG_ORIG(MSG_STR_NAME), NULL, 0 }, 1723 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1724 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1725 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 1726 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 1727 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 }, 1728 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1729 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1730 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 1731 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 1732 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 }, 1733 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 1734 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 1735 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, SYM_OPT_F_SYMNDX }, 1736 { NULL } 1737 }; 1738 static elfedit_cmd_optarg_t arg_dump[] = { 1739 { MSG_ORIG(MSG_STR_SYM), 1740 /* MSG_INTL(MSG_A1_SYM) */ 1741 ELFEDIT_I18NHDL(MSG_A1_SYM), 1742 ELFEDIT_CMDOA_F_OPT }, 1743 { NULL } 1744 }; 1745 1746 /* sym:st_bind */ 1747 static const char *name_st_bind[] = { 1748 MSG_ORIG(MSG_CMD_ST_BIND), NULL }; 1749 static elfedit_cmd_optarg_t arg_st_bind[] = { 1750 { MSG_ORIG(MSG_STR_SYM), 1751 /* MSG_INTL(MSG_A1_SYM) */ 1752 ELFEDIT_I18NHDL(MSG_A1_SYM), 1753 ELFEDIT_CMDOA_F_OPT }, 1754 { MSG_ORIG(MSG_STR_VALUE), 1755 /* MSG_INTL(MSG_A2_DESC_ST_BIND) */ 1756 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_BIND), 1757 ELFEDIT_CMDOA_F_OPT }, 1758 { NULL } 1759 }; 1760 1761 /* sym:st_info */ 1762 static const char *name_st_info[] = { 1763 MSG_ORIG(MSG_CMD_ST_INFO), NULL }; 1764 static elfedit_cmd_optarg_t arg_st_info[] = { 1765 { MSG_ORIG(MSG_STR_SYM), 1766 /* MSG_INTL(MSG_A1_SYM) */ 1767 ELFEDIT_I18NHDL(MSG_A1_SYM), 1768 ELFEDIT_CMDOA_F_OPT }, 1769 { MSG_ORIG(MSG_STR_VALUE), 1770 /* MSG_INTL(MSG_A2_DESC_ST_INFO) */ 1771 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_INFO), 1772 ELFEDIT_CMDOA_F_OPT }, 1773 { NULL } 1774 }; 1775 1776 /* sym:st_name */ 1777 static const char *name_st_name[] = { 1778 MSG_ORIG(MSG_CMD_ST_NAME), NULL }; 1779 static elfedit_cmd_optarg_t opt_st_name[] = { 1780 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 1781 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 1782 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 1783 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 1784 { MSG_ORIG(MSG_STR_NAME), NULL, 0, 0 }, 1785 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1786 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1787 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 1788 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 1789 { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 1790 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1791 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1792 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 1793 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 1794 { MSG_ORIG(MSG_STR_TYPE), NULL, 0, 0 }, 1795 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 1796 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 1797 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, 1798 SYM_OPT_F_SYMNDX, 0 }, 1799 { MSG_ORIG(MSG_STR_MINUS_NAME_OFFSET), 1800 /* MSG_INTL(MSG_OPTDESC_NAME_OFFSET) */ 1801 ELFEDIT_I18NHDL(MSG_OPTDESC_NAME_OFFSET), 0, 1802 SYM_OPT_F_NAMOFFSET, 0 }, 1803 { ELFEDIT_STDOA_OPT_O, NULL, 1804 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1805 { NULL } 1806 }; 1807 static elfedit_cmd_optarg_t arg_st_name[] = { 1808 { MSG_ORIG(MSG_STR_SYM), 1809 /* MSG_INTL(MSG_A1_SYM) */ 1810 ELFEDIT_I18NHDL(MSG_A1_SYM), 1811 ELFEDIT_CMDOA_F_OPT }, 1812 { MSG_ORIG(MSG_STR_NAME), 1813 /* MSG_INTL(MSG_A2_DESC_ST_NAME) */ 1814 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_NAME), 1815 ELFEDIT_CMDOA_F_OPT }, 1816 { NULL } 1817 }; 1818 1819 /* sym:st_other */ 1820 static const char *name_st_other[] = { 1821 MSG_ORIG(MSG_CMD_ST_OTHER), NULL }; 1822 static elfedit_cmd_optarg_t arg_st_other[] = { 1823 { MSG_ORIG(MSG_STR_SYM), 1824 /* MSG_INTL(MSG_A1_SYM) */ 1825 ELFEDIT_I18NHDL(MSG_A1_SYM), 1826 ELFEDIT_CMDOA_F_OPT }, 1827 { MSG_ORIG(MSG_STR_VALUE), 1828 /* MSG_INTL(MSG_A2_DESC_ST_OTHER) */ 1829 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_OTHER), 1830 ELFEDIT_CMDOA_F_OPT }, 1831 { NULL } 1832 }; 1833 1834 /* sym:st_shndx */ 1835 static const char *name_st_shndx[] = { 1836 MSG_ORIG(MSG_CMD_ST_SHNDX), NULL }; 1837 static elfedit_cmd_optarg_t opt_st_shndx[] = { 1838 { MSG_ORIG(MSG_STR_MINUS_E), 1839 /* MSG_INTL(MSG_OPTDESC_E) */ 1840 ELFEDIT_I18NHDL(MSG_OPTDESC_E), 0, SYM_OPT_F_XSHINDEX, 0 }, 1841 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 1842 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 1843 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 1844 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 1845 { MSG_ORIG(MSG_STR_NAME), NULL, 0, 0 }, 1846 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1847 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1848 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 1849 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 1850 { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 1851 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1852 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1853 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 1854 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 1855 { MSG_ORIG(MSG_STR_TYPE), NULL, 0, 0 }, 1856 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 1857 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 1858 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, 1859 SYM_OPT_F_SYMNDX, 0 }, 1860 { ELFEDIT_STDOA_OPT_O, NULL, 1861 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1862 { MSG_ORIG(MSG_STR_MINUS_SECSHNDX), 1863 /* MSG_INTL(MSG_OPTDESC_SECSHNDX) */ 1864 ELFEDIT_I18NHDL(MSG_OPTDESC_SECSHNDX), 1865 0, SYM_OPT_F_SECSHNDX, SYM_OPT_F_SECSHTYP }, 1866 { MSG_ORIG(MSG_STR_MINUS_SECSHTYP), 1867 /* MSG_INTL(MSG_OPTDESC_SECSHTYP) */ 1868 ELFEDIT_I18NHDL(MSG_OPTDESC_SECSHTYP), 1869 0, SYM_OPT_F_SECSHTYP, SYM_OPT_F_SECSHNDX }, 1870 { NULL } 1871 }; 1872 static elfedit_cmd_optarg_t arg_st_shndx[] = { 1873 { MSG_ORIG(MSG_STR_SYM), 1874 /* MSG_INTL(MSG_A1_SYM) */ 1875 ELFEDIT_I18NHDL(MSG_A1_SYM), 1876 ELFEDIT_CMDOA_F_OPT }, 1877 { MSG_ORIG(MSG_STR_SEC), 1878 /* MSG_INTL(MSG_A2_DESC_ST_SEC) */ 1879 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_SEC), 1880 ELFEDIT_CMDOA_F_OPT }, 1881 { NULL } 1882 }; 1883 1884 /* sym:st_size */ 1885 static const char *name_st_size[] = { 1886 MSG_ORIG(MSG_CMD_ST_SIZE), NULL }; 1887 static elfedit_cmd_optarg_t arg_st_size[] = { 1888 { MSG_ORIG(MSG_STR_SYM), 1889 /* MSG_INTL(MSG_A1_SYM) */ 1890 ELFEDIT_I18NHDL(MSG_A1_SYM), 1891 ELFEDIT_CMDOA_F_OPT }, 1892 { MSG_ORIG(MSG_STR_VALUE), 1893 /* MSG_INTL(MSG_A2_DESC_ST_SIZE) */ 1894 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_SIZE), 1895 ELFEDIT_CMDOA_F_OPT }, 1896 { NULL } 1897 }; 1898 1899 /* sym:st_type */ 1900 static const char *name_st_type[] = { 1901 MSG_ORIG(MSG_CMD_ST_TYPE), NULL }; 1902 static elfedit_cmd_optarg_t arg_st_type[] = { 1903 { MSG_ORIG(MSG_STR_SYM), 1904 /* MSG_INTL(MSG_A1_SYM) */ 1905 ELFEDIT_I18NHDL(MSG_A1_SYM), 1906 ELFEDIT_CMDOA_F_OPT }, 1907 { MSG_ORIG(MSG_STR_VALUE), 1908 /* MSG_INTL(MSG_A2_DESC_ST_TYPE) */ 1909 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_TYPE), 1910 ELFEDIT_CMDOA_F_OPT }, 1911 { NULL } 1912 }; 1913 1914 /* sym:st_value */ 1915 static const char *name_st_value[] = { 1916 MSG_ORIG(MSG_CMD_ST_VALUE), NULL }; 1917 static elfedit_cmd_optarg_t arg_st_value[] = { 1918 { MSG_ORIG(MSG_STR_SYM), 1919 /* MSG_INTL(MSG_A1_SYM) */ 1920 ELFEDIT_I18NHDL(MSG_A1_SYM), 1921 ELFEDIT_CMDOA_F_OPT }, 1922 { MSG_ORIG(MSG_STR_VALUE), 1923 /* MSG_INTL(MSG_A2_DESC_ST_VALUE) */ 1924 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_VALUE), 1925 ELFEDIT_CMDOA_F_OPT }, 1926 { NULL } 1927 }; 1928 1929 /* sym:st_visibility */ 1930 static const char *name_st_visibility[] = { 1931 MSG_ORIG(MSG_CMD_ST_VISIBILITY), NULL }; 1932 static elfedit_cmd_optarg_t arg_st_visibility[] = { 1933 { MSG_ORIG(MSG_STR_SYM), 1934 /* MSG_INTL(MSG_A1_SYM) */ 1935 ELFEDIT_I18NHDL(MSG_A1_SYM), 1936 ELFEDIT_CMDOA_F_OPT }, 1937 { MSG_ORIG(MSG_STR_VALUE), 1938 /* MSG_INTL(MSG_A2_DESC_ST_VISIBILITY) */ 1939 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_VISIBILITY), 1940 ELFEDIT_CMDOA_F_OPT }, 1941 { NULL } 1942 }; 1943 1944 static elfedit_cmd_t cmds[] = { 1945 /* sym:dump */ 1946 { cmd_dump, cpl_sh_opt, name_dump, 1947 /* MSG_INTL(MSG_DESC_DUMP) */ 1948 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 1949 /* MSG_INTL(MSG_HELP_DUMP) */ 1950 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 1951 opt_dump, arg_dump }, 1952 1953 /* sym:st_bind */ 1954 { cmd_st_bind, cpl_st_bind, name_st_bind, 1955 /* MSG_INTL(MSG_DESC_ST_BIND) */ 1956 ELFEDIT_I18NHDL(MSG_DESC_ST_BIND), 1957 /* MSG_INTL(MSG_HELP_ST_BIND) */ 1958 ELFEDIT_I18NHDL(MSG_HELP_ST_BIND), 1959 opt_std, arg_st_bind }, 1960 1961 /* sym:st_info */ 1962 { cmd_st_info, cpl_sh_opt, name_st_info, 1963 /* MSG_INTL(MSG_DESC_ST_INFO) */ 1964 ELFEDIT_I18NHDL(MSG_DESC_ST_INFO), 1965 /* MSG_INTL(MSG_HELP_ST_INFO) */ 1966 ELFEDIT_I18NHDL(MSG_HELP_ST_INFO), 1967 opt_std, arg_st_info }, 1968 1969 /* sym:st_name */ 1970 { cmd_st_name, cpl_sh_opt, name_st_name, 1971 /* MSG_INTL(MSG_DESC_ST_NAME) */ 1972 ELFEDIT_I18NHDL(MSG_DESC_ST_NAME), 1973 /* MSG_INTL(MSG_HELP_ST_NAME) */ 1974 ELFEDIT_I18NHDL(MSG_HELP_ST_NAME), 1975 opt_st_name, arg_st_name }, 1976 1977 /* sym:st_other */ 1978 { cmd_st_other, cpl_sh_opt, name_st_other, 1979 /* MSG_INTL(MSG_DESC_ST_OTHER) */ 1980 ELFEDIT_I18NHDL(MSG_DESC_ST_OTHER), 1981 /* MSG_INTL(MSG_HELP_ST_OTHER) */ 1982 ELFEDIT_I18NHDL(MSG_HELP_ST_OTHER), 1983 opt_std, arg_st_other }, 1984 1985 /* sym:st_shndx */ 1986 { cmd_st_shndx, cpl_st_shndx, name_st_shndx, 1987 /* MSG_INTL(MSG_DESC_ST_SHNDX) */ 1988 ELFEDIT_I18NHDL(MSG_DESC_ST_SHNDX), 1989 /* MSG_INTL(MSG_HELP_ST_SHNDX) */ 1990 ELFEDIT_I18NHDL(MSG_HELP_ST_SHNDX), 1991 opt_st_shndx, arg_st_shndx }, 1992 1993 /* sym:st_size */ 1994 { cmd_st_size, cpl_sh_opt, name_st_size, 1995 /* MSG_INTL(MSG_DESC_ST_SIZE) */ 1996 ELFEDIT_I18NHDL(MSG_DESC_ST_SIZE), 1997 /* MSG_INTL(MSG_HELP_ST_SIZE) */ 1998 ELFEDIT_I18NHDL(MSG_HELP_ST_SIZE), 1999 opt_std, arg_st_size }, 2000 2001 /* sym:st_type */ 2002 { cmd_st_type, cpl_st_type, name_st_type, 2003 /* MSG_INTL(MSG_DESC_ST_TYPE) */ 2004 ELFEDIT_I18NHDL(MSG_DESC_ST_TYPE), 2005 /* MSG_INTL(MSG_HELP_ST_TYPE) */ 2006 ELFEDIT_I18NHDL(MSG_HELP_ST_TYPE), 2007 opt_std, arg_st_type }, 2008 2009 /* sym:st_value */ 2010 { cmd_st_value, cpl_sh_opt, name_st_value, 2011 /* MSG_INTL(MSG_DESC_ST_VALUE) */ 2012 ELFEDIT_I18NHDL(MSG_DESC_ST_VALUE), 2013 /* MSG_INTL(MSG_HELP_ST_VALUE) */ 2014 ELFEDIT_I18NHDL(MSG_HELP_ST_VALUE), 2015 opt_std, arg_st_value }, 2016 2017 /* sym:st_visibility */ 2018 { cmd_st_visibility, cpl_st_visibility, name_st_visibility, 2019 /* MSG_INTL(MSG_DESC_ST_VISIBILITY) */ 2020 ELFEDIT_I18NHDL(MSG_DESC_ST_VISIBILITY), 2021 /* MSG_INTL(MSG_HELP_ST_VISIBILITY) */ 2022 ELFEDIT_I18NHDL(MSG_HELP_ST_VISIBILITY), 2023 opt_std, arg_st_visibility }, 2024 2025 { NULL } 2026 }; 2027 2028 static elfedit_module_t module = { 2029 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 2030 /* MSG_INTL(MSG_MOD_DESC) */ 2031 ELFEDIT_I18NHDL(MSG_MOD_DESC), 2032 cmds, mod_i18nhdl_to_str }; 2033 2034 return (&module); 2035 } 2036