1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #define ELF_TARGET_AMD64 /* SHN_AMD64_LCOMMON */ 29 30 #include <stdio.h> 31 #include <unistd.h> 32 #include <elfedit.h> 33 #include <strings.h> 34 #include <debug.h> 35 #include <conv.h> 36 #include <sym_msg.h> 37 38 39 40 41 #define MAXNDXSIZE 10 42 43 44 45 /* 46 * This module uses shared code for several of the commands. 47 * It is sometimes necessary to know which specific command 48 * is active. 49 */ 50 typedef enum { 51 SYM_CMD_T_DUMP = 0, /* sym:dump */ 52 53 SYM_CMD_T_ST_BIND = 1, /* sym:st_bind */ 54 SYM_CMD_T_ST_INFO = 2, /* sym:st_info */ 55 SYM_CMD_T_ST_NAME = 3, /* sym:st_name */ 56 SYM_CMD_T_ST_OTHER = 4, /* sym:st_other */ 57 SYM_CMD_T_ST_SHNDX = 5, /* sym:st_shndx */ 58 SYM_CMD_T_ST_SIZE = 6, /* sym:st_size */ 59 SYM_CMD_T_ST_TYPE = 7, /* sym:st_type */ 60 SYM_CMD_T_ST_VALUE = 8, /* sym:st_value */ 61 SYM_CMD_T_ST_VISIBILITY = 9 /* sym:st_visibility */ 62 } SYM_CMD_T; 63 64 65 66 /* 67 * ELFCLASS-specific definitions 68 */ 69 #ifdef _ELF64 70 71 #define MSG_FMT_XWORDVALNL MSG_FMT_XWORDVALNL_64 72 73 #else 74 75 #define MSG_FMT_XWORDVALNL MSG_FMT_XWORDVALNL_32 76 77 /* 78 * We supply this function for the msg module. Only one copy is needed. 79 */ 80 const char * 81 _sym_msg(Msg mid) 82 { 83 return (gettext(MSG_ORIG(mid))); 84 } 85 86 #endif 87 88 89 90 /* 91 * This function is supplied to elfedit through our elfedit_module_t 92 * definition. It translates the opaque elfedit_i18nhdl_t handles 93 * in our module interface into the actual strings for elfedit to 94 * use. 95 * 96 * note: 97 * This module uses Msg codes for its i18n handle type. 98 * So the translation is simply to use MSG_INTL() to turn 99 * it into a string and return it. 100 */ 101 static const char * 102 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 103 { 104 Msg msg = (Msg)hdl; 105 106 return (MSG_INTL(msg)); 107 } 108 109 110 111 /* 112 * The sym_opt_t enum specifies a bit value for every optional 113 * argument allowed by a command in this module. 114 */ 115 typedef enum { 116 SYM_OPT_F_XSHINDEX = 1, /* -e: Force shndx update to extended */ 117 /* index section */ 118 SYM_OPT_F_NAMOFFSET = 2, /* -name_offset: sym:st_name name arg */ 119 /* is numeric offset */ 120 /* rather than ASCII string */ 121 SYM_OPT_F_SECSHNDX = 4, /* -secshndx: Section arg is */ 122 /* section index, not name */ 123 SYM_OPT_F_SECSHTYP = 8, /* -secshtyp: Section arg is */ 124 /* section type, not name */ 125 SYM_OPT_F_SHNAME = 16, /* -shnam name: section spec. by name */ 126 SYM_OPT_F_SHNDX = 32, /* -shndx ndx: section spec. by index */ 127 SYM_OPT_F_SHTYP = 64, /* -shtyp type: section spec. by type */ 128 SYM_OPT_F_SYMNDX = 128 /* -symndx: Sym specified by index */ 129 } sym_opt_t; 130 131 132 /* 133 * A variable of type ARGSTATE is used by each command to maintain 134 * the overall state for a given set of arguments and the symbol tables 135 * being managed. 136 * 137 * The state for each symbol table and the auxiliary sections that are 138 * related to it are kept in a SYMSTATE sub-struct. 139 * 140 * One benefit of ARGSTATE is that it helps us to ensure that we only 141 * fetch each section a single time: 142 * - More efficient 143 * - Prevents multiple ELFEDIT_MSG_DEBUG messages from 144 * being produced for a given section. 145 * 146 * note: The symstate array in ARGSTATE is defined as having one 147 * element, but in reality, we allocate enough room for 148 * the number of elements defined in the numsymstate field. 149 */ 150 typedef struct { 151 Word ndx; /* If argstate.argc > 0, this is the table index */ 152 struct { /* Symbol table */ 153 elfedit_section_t *sec; 154 Sym *data; 155 Word n; 156 } sym; 157 struct { /* String table */ 158 elfedit_section_t *sec; 159 } str; 160 struct { /* Versym */ 161 Word shndx; 162 elfedit_section_t *sec; 163 Versym *data; 164 Word n; 165 } versym; 166 struct { /* Extended section indices */ 167 Word shndx; 168 elfedit_section_t *sec; 169 Word *data; 170 Word n; 171 } xshndx; 172 } SYMSTATE; 173 typedef struct { 174 elfedit_obj_state_t *obj_state; 175 sym_opt_t optmask; /* Mask of options used */ 176 int argc; /* # of plain arguments */ 177 const char **argv; /* Plain arguments */ 178 int numsymstate; /* # of items in symstate[] */ 179 SYMSTATE symstate[1]; /* Symbol tables to process */ 180 } ARGSTATE; 181 182 183 /* 184 * We maintain the state of each symbol table and related associated 185 * sections in a SYMSTATE structure . We don't look those auxiliary 186 * things up unless we actually need them, both to be efficient, 187 * and to prevent duplicate ELFEDIT_MSG_DEBUG messages from being 188 * issued as they are located. Hence, process_args() is used to 189 * initialize the state block with just the symbol table, and then one 190 * of the argstate_add_XXX() functions is used as needed 191 * to fetch the additional sections. 192 * 193 * entry: 194 * argstate - Overall state block 195 * symstate - State block for current symbol table. 196 * 197 * exit: 198 * If the needed auxiliary section is not found, an error is 199 * issued and the argstate_add_XXX() routine does not return. 200 * Otherwise, the fields in argstate have been filled in, ready 201 * for use. 202 * 203 */ 204 static void 205 symstate_add_str(ARGSTATE *argstate, SYMSTATE *symstate) 206 { 207 if (symstate->str.sec != NULL) 208 return; 209 210 symstate->str.sec = elfedit_sec_getstr(argstate->obj_state, 211 symstate->sym.sec->sec_shdr->sh_link, 0); 212 } 213 static void 214 symstate_add_versym(ARGSTATE *argstate, SYMSTATE *symstate) 215 { 216 if (symstate->versym.sec != NULL) 217 return; 218 219 symstate->versym.sec = elfedit_sec_getversym(argstate->obj_state, 220 symstate->sym.sec, &symstate->versym.data, &symstate->versym.n); 221 } 222 static void 223 symstate_add_xshndx(ARGSTATE *argstate, SYMSTATE *symstate) 224 { 225 if (symstate->xshndx.sec != NULL) 226 return; 227 228 symstate->xshndx.sec = elfedit_sec_getxshndx(argstate->obj_state, 229 symstate->sym.sec, &symstate->xshndx.data, &symstate->xshndx.n); 230 } 231 232 233 234 /* 235 * Display symbol table entries in the style used by elfdump. 236 * 237 * entry: 238 * argstate - Overall state block 239 * symstate - State block for current symbol table. 240 * ndx - Index of first symbol to display 241 * cnt - Number of symbols to display 242 */ 243 static void 244 dump_symtab(ARGSTATE *argstate, SYMSTATE *symstate, Word ndx, Word cnt) 245 { 246 char index[MAXNDXSIZE]; 247 Word shndx; 248 const char *shndx_name; 249 elfedit_section_t *symsec; 250 elfedit_section_t *strsec; 251 Sym *sym; 252 elfedit_obj_state_t *obj_state = argstate->obj_state; 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, 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_FULLNAME, &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_FULLNAME, &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_FULLNAME, &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_FULLNAME, &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_FULLNAME, 730 &inv_buf1), 731 conv_sym_info_bind(bind, CONV_FMT_ALT_FULLNAME, &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_FULLNAME, 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_FULLNAME, 966 &inv_buf1), 967 conv_sym_info_type(mach, type, CONV_FMT_ALT_FULLNAME, 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_FULLNAME, 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_FULLNAME, 1005 &inv_buf1), 1006 conv_sym_other_vis(vis, CONV_FMT_ALT_FULLNAME, &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 needs 1114 * be a symbol table. 1115 */ 1116 if (explicit) 1117 (void) elfedit_sec_issymtab(&obj_state->os_secarr[index], 1118 1, NULL); 1119 1120 /* If there may be an arbitrary amount of output, use a pager */ 1121 if (argc == 0) 1122 elfedit_pager_init(); 1123 1124 /* Return the updated values of argc/argv */ 1125 argstate->argc = argc; 1126 argstate->argv = argv; 1127 1128 /* 1129 * Decide which symbol table(s) to use. Set up the symstate 1130 * array to contain them: 1131 * - If a symbol table was explicitly specified, we use 1132 * it, and only it. 1133 * - If no symbol table is explicitly specified, and the symbol 1134 * is given by name, we use all symbol tables that 1135 * contain a symbol with that name, throwing an error 1136 * if there isn't at least 1 such table. 1137 * - If no symbol table is specified, and no symbol is specified, 1138 * we use all the tables. 1139 */ 1140 symtab = obj_state->os_symtab; 1141 symstate = argstate->symstate; 1142 for (tblndx = 0; tblndx < obj_state->os_symtabnum; 1143 tblndx++, symtab++) { 1144 /* If explicit table specified, only that table is considered */ 1145 if (explicit && (symtab->symt_shndx != index)) 1146 continue; 1147 1148 symstate->sym.sec = elfedit_sec_getsymtab(obj_state, 1, 1149 symtab->symt_shndx, NULL, &symstate->sym.data, 1150 &symstate->sym.n, &symtab); 1151 symstate->versym.shndx = symtab->symt_versym; 1152 symstate->xshndx.shndx = symtab->symt_xshndx; 1153 if (argc > 0) { 1154 if (argstate->optmask & SYM_OPT_F_SYMNDX) { 1155 symstate->ndx = elfedit_atoui_range( 1156 argstate->argv[0], MSG_INTL(MSG_ARG_SYM), 0, 1157 symstate->sym.n - 1, NULL); 1158 } else { 1159 /* 1160 * arg is a symbol name. Use the index of 1161 * the first symbol that matches 1162 */ 1163 1164 /* 1165 * We will use debug messages for failure up 1166 * until we run out of symbol tables. If we 1167 * don't find a table with the desired symbol 1168 * before the last table, we switch to error 1169 * messages. Hence, we will jump with an error 1170 * if no table will work. 1171 */ 1172 int err_type = (!got_sym && 1173 ((tblndx + 1) == obj_state->os_symtabnum)) ? 1174 ELFEDIT_MSG_ERR : ELFEDIT_MSG_DEBUG; 1175 1176 symstate_add_str(argstate, symstate); 1177 1178 /* 1179 * If the symbol table doesn't have this 1180 * symbol, then forget it. 1181 */ 1182 if (elfedit_name_to_symndx(symstate->sym.sec, 1183 symstate->str.sec, argstate->argv[0], 1184 err_type, &symstate->ndx) == 0) { 1185 bzero(symstate, sizeof (*symstate)); 1186 continue; 1187 } 1188 } 1189 } 1190 argstate->numsymstate++; 1191 symstate++; 1192 /* 1193 * If the symbol table was given explicitly, and 1194 * we've just taken it, then there is no reason to 1195 * continue searching. 1196 */ 1197 if (explicit) 1198 break; 1199 } 1200 1201 return (argstate); 1202 } 1203 1204 1205 1206 /* 1207 * Called by cmd_body() to handle the value change for a single 1208 * symbol table. 1209 * 1210 * entry: 1211 * cmd - One of the SYM_CMD_T_* constants listed above, specifying 1212 * which command to implement. 1213 * argstate - Overall state block 1214 * symstate - State block for current symbol table. 1215 */ 1216 static elfedit_cmdret_t 1217 symstate_cmd_body(SYM_CMD_T cmd, ARGSTATE *argstate, SYMSTATE *symstate) 1218 { 1219 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 1220 Sym *sym = &symstate->sym.data[symstate->ndx]; 1221 1222 /* You're not supposed to change the value of symbol [0] */ 1223 if (symstate->ndx == 0) 1224 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CHGSYMELT0), 1225 EC_WORD(symstate->sym.sec->sec_shndx), 1226 symstate->sym.sec->sec_name, EC_WORD(symstate->ndx)); 1227 1228 /* The second value is an integer giving a new value */ 1229 switch (cmd) { 1230 /* 1231 * SYM_CMD_T_DUMP can't get here: It never has more than 1232 * one argument, and is handled above. 1233 */ 1234 1235 case SYM_CMD_T_ST_BIND: 1236 ret = cmd_body_set_st_bind(argstate, symstate); 1237 break; 1238 1239 case SYM_CMD_T_ST_INFO: 1240 { 1241 /* Treat st_info as a raw integer field */ 1242 uchar_t st_info = 1243 elfedit_atoui(argstate->argv[1], NULL); 1244 1245 if (sym->st_info == st_info) { 1246 elfedit_msg(ELFEDIT_MSG_DEBUG, 1247 MSG_INTL(MSG_DEBUG_D_OK), 1248 symstate->sym.sec->sec_shndx, 1249 symstate->sym.sec->sec_name, 1250 EC_WORD(symstate->ndx), 1251 MSG_ORIG(MSG_CMD_ST_INFO), 1252 EC_WORD(sym->st_info)); 1253 } else { 1254 elfedit_msg(ELFEDIT_MSG_DEBUG, 1255 MSG_INTL(MSG_DEBUG_D_CHG), 1256 symstate->sym.sec->sec_shndx, 1257 symstate->sym.sec->sec_name, 1258 EC_WORD(symstate->ndx), 1259 MSG_ORIG(MSG_CMD_ST_INFO), 1260 EC_WORD(sym->st_info), EC_WORD(st_info)); 1261 ret = ELFEDIT_CMDRET_MOD; 1262 sym->st_info = st_info; 1263 } 1264 } 1265 break; 1266 1267 case SYM_CMD_T_ST_NAME: 1268 ret = cmd_body_set_st_name(argstate, symstate); 1269 break; 1270 1271 case SYM_CMD_T_ST_OTHER: 1272 { 1273 /* Treat st_other as a raw integer field */ 1274 uchar_t st_other = 1275 elfedit_atoui(argstate->argv[1], NULL); 1276 1277 if (sym->st_other == st_other) { 1278 elfedit_msg(ELFEDIT_MSG_DEBUG, 1279 MSG_INTL(MSG_DEBUG_D_OK), 1280 symstate->sym.sec->sec_shndx, 1281 symstate->sym.sec->sec_name, 1282 EC_WORD(symstate->ndx), 1283 MSG_ORIG(MSG_CMD_ST_OTHER), 1284 EC_WORD(sym->st_other)); 1285 } else { 1286 elfedit_msg(ELFEDIT_MSG_DEBUG, 1287 MSG_INTL(MSG_DEBUG_D_CHG), 1288 symstate->sym.sec->sec_shndx, 1289 symstate->sym.sec->sec_name, 1290 EC_WORD(symstate->ndx), 1291 MSG_ORIG(MSG_CMD_ST_OTHER), 1292 EC_WORD(sym->st_other), EC_WORD(st_other)); 1293 ret = ELFEDIT_CMDRET_MOD; 1294 sym->st_other = st_other; 1295 } 1296 } 1297 break; 1298 1299 case SYM_CMD_T_ST_SHNDX: 1300 ret = cmd_body_set_st_shndx(argstate, symstate); 1301 break; 1302 1303 case SYM_CMD_T_ST_SIZE: 1304 { 1305 Xword st_size = elfedit_atoui(argstate->argv[1], NULL); 1306 1307 if (sym->st_size == st_size) { 1308 elfedit_msg(ELFEDIT_MSG_DEBUG, 1309 MSG_INTL(MSG_DEBUG_LLX_OK), 1310 symstate->sym.sec->sec_shndx, 1311 symstate->sym.sec->sec_name, 1312 EC_WORD(symstate->ndx), 1313 MSG_ORIG(MSG_CMD_ST_SIZE), 1314 EC_XWORD(sym->st_size)); 1315 } else { 1316 elfedit_msg(ELFEDIT_MSG_DEBUG, 1317 MSG_INTL(MSG_DEBUG_LLX_CHG), 1318 symstate->sym.sec->sec_shndx, 1319 symstate->sym.sec->sec_name, 1320 EC_WORD(symstate->ndx), 1321 MSG_ORIG(MSG_CMD_ST_SIZE), 1322 EC_XWORD(sym->st_size), EC_XWORD(st_size)); 1323 ret = ELFEDIT_CMDRET_MOD; 1324 sym->st_size = st_size; 1325 } 1326 } 1327 break; 1328 1329 case SYM_CMD_T_ST_TYPE: 1330 ret = cmd_body_set_st_type(argstate, symstate); 1331 break; 1332 1333 case SYM_CMD_T_ST_VALUE: 1334 { 1335 Addr st_value = elfedit_atoui(argstate->argv[1], NULL); 1336 1337 if (sym->st_value == st_value) { 1338 elfedit_msg(ELFEDIT_MSG_DEBUG, 1339 MSG_INTL(MSG_DEBUG_LLX_OK), 1340 symstate->sym.sec->sec_shndx, 1341 symstate->sym.sec->sec_name, 1342 EC_WORD(symstate->ndx), 1343 MSG_ORIG(MSG_CMD_ST_VALUE), 1344 EC_ADDR(sym->st_value)); 1345 } else { 1346 elfedit_msg(ELFEDIT_MSG_DEBUG, 1347 MSG_INTL(MSG_DEBUG_LLX_CHG), 1348 symstate->sym.sec->sec_shndx, 1349 symstate->sym.sec->sec_name, 1350 EC_WORD(symstate->ndx), 1351 MSG_ORIG(MSG_CMD_ST_VALUE), 1352 EC_ADDR(sym->st_value), 1353 EC_ADDR(st_value)); 1354 ret = ELFEDIT_CMDRET_MOD; 1355 ret = ELFEDIT_CMDRET_MOD; 1356 sym->st_value = st_value; 1357 } 1358 } 1359 break; 1360 1361 case SYM_CMD_T_ST_VISIBILITY: 1362 ret = cmd_body_set_st_visibility(argstate, symstate); 1363 break; 1364 } 1365 1366 /* 1367 * If we modified the symbol table, tell libelf. 1368 * Any other modified sections are the responsibility 1369 * of the cmd_body_set_st_*() function that did it, but 1370 * everyone modifies the table itself, so we handle that here. 1371 */ 1372 if (ret == ELFEDIT_CMDRET_MOD) 1373 elfedit_modified_data(symstate->sym.sec); 1374 1375 return (ret); 1376 } 1377 1378 1379 1380 1381 /* 1382 * Common body for the sym: module commands. These commands 1383 * share a large amount of common behavior, so it is convenient 1384 * to centralize things and use the cmd argument to handle the 1385 * small differences. 1386 * 1387 * entry: 1388 * cmd - One of the SYM_CMD_T_* constants listed above, specifying 1389 * which command to implement. 1390 * obj_state, argc, argv - Standard command arguments 1391 */ 1392 static elfedit_cmdret_t 1393 cmd_body(SYM_CMD_T cmd, elfedit_obj_state_t *obj_state, 1394 int argc, const char *argv[]) 1395 { 1396 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 1397 ARGSTATE *argstate; 1398 SYMSTATE *symstate; 1399 Word tblndx; 1400 1401 argstate = process_args(obj_state, argc, argv, cmd); 1402 1403 /* 1404 * If there are not 2 arguments, then this is a display request. 1405 * If no arguments are present, the full table (or tables) is 1406 * dumped. If there is one argument, then the specified item is shown. 1407 */ 1408 if (argstate->argc < 2) { 1409 print_sym(cmd, 0, argstate); 1410 return (ELFEDIT_CMDRET_NONE); 1411 } 1412 1413 /* 1414 * When processing multiple symbol tables, it is important that 1415 * any failure happen before anything is changed. Otherwise, you 1416 * can end up in a situation where things are left in an inconsistent 1417 * half done state. sym:st_name has that issue when the -name_offset 1418 * option is used, because the string may be insertable into some 1419 * (dynstr) string tables, but not all of them. So, do the tests 1420 * up front, and refuse to continue if any string insertions would 1421 * fail. 1422 */ 1423 if ((cmd == SYM_CMD_T_ST_NAME) && (argstate->numsymstate > 1) && 1424 ((argstate->optmask & SYM_OPT_F_NAMOFFSET) == 0)) { 1425 symstate = argstate->symstate; 1426 for (tblndx = 0; tblndx < argstate->numsymstate; 1427 tblndx++, symstate++) 1428 elfedit_strtab_insert_test(obj_state, symstate->str.sec, 1429 NULL, argstate->argv[1]); 1430 } 1431 1432 1433 /* Loop over the table(s) and make the specified value change */ 1434 symstate = argstate->symstate; 1435 for (tblndx = 0; tblndx < argstate->numsymstate; tblndx++, symstate++) 1436 if (symstate_cmd_body(cmd, argstate, symstate) == 1437 ELFEDIT_CMDRET_MOD) 1438 ret = ELFEDIT_CMDRET_MOD; 1439 1440 /* Do autoprint */ 1441 print_sym(cmd, 1, argstate); 1442 1443 return (ret); 1444 } 1445 1446 1447 1448 1449 /* 1450 * Command completion functions for the various commands 1451 */ 1452 1453 /* 1454 * Handle filling in the values for -shnam, -shndx, and -shtyp options. 1455 */ 1456 /*ARGSUSED*/ 1457 static void 1458 cpl_sh_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1459 const char *argv[], int num_opt) 1460 { 1461 enum { NAME, INDEX, TYPE } op; 1462 elfedit_symtab_t *symtab; 1463 Word tblndx; 1464 1465 if ((argc != num_opt) || (argc < 2)) 1466 return; 1467 1468 if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNAM)) == 0) { 1469 op = NAME; 1470 } else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHNDX)) == 0) { 1471 op = INDEX; 1472 1473 } else if (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_SHTYP)) == 0) { 1474 op = TYPE; 1475 if (obj_state == NULL) /* No object available */ 1476 elfedit_cpl_atoconst(cpldata, 1477 ELFEDIT_CONST_SHT_ALLSYMTAB); 1478 } else { 1479 return; 1480 } 1481 1482 if (obj_state == NULL) /* No object available */ 1483 return; 1484 1485 /* 1486 * Loop over the symbol tables and supply command completion 1487 * for the items in the file. 1488 */ 1489 symtab = obj_state->os_symtab; 1490 for (tblndx = 0; tblndx < obj_state->os_symtabnum; 1491 tblndx++, symtab++) { 1492 elfedit_section_t *sec = 1493 &obj_state->os_secarr[symtab->symt_shndx]; 1494 1495 switch (op) { 1496 case NAME: 1497 elfedit_cpl_match(cpldata, sec->sec_name, 0); 1498 break; 1499 case INDEX: 1500 elfedit_cpl_ndx(cpldata, symtab->symt_shndx); 1501 break; 1502 case TYPE: 1503 { 1504 elfedit_atoui_sym_t *cpl_list; 1505 1506 (void) elfedit_sec_issymtab(sec, 1, &cpl_list); 1507 elfedit_cpl_atoui(cpldata, cpl_list); 1508 } 1509 break; 1510 } 1511 } 1512 } 1513 1514 /*ARGSUSED*/ 1515 static void 1516 cpl_st_bind(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1517 const char *argv[], int num_opt) 1518 { 1519 /* Handle -shXXX options */ 1520 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 1521 1522 /* The second argument can be an STB_ value */ 1523 if (argc == (num_opt + 2)) 1524 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STB); 1525 } 1526 1527 /*ARGSUSED*/ 1528 static void 1529 cpl_st_shndx(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1530 const char *argv[], int num_opt) 1531 { 1532 elfedit_section_t *sec; 1533 enum { NAME, INDEX, TYPE } op; 1534 Word ndx; 1535 1536 /* Handle -shXXX options */ 1537 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 1538 1539 /* 1540 * The second argument can be a section name, a section 1541 * index (-secshndx), or a section type (-secshtyp). We 1542 * can do completions for each of these. 1543 */ 1544 if (argc != (num_opt + 2)) 1545 return; 1546 1547 op = NAME; 1548 for (ndx = 0; ndx < num_opt; ndx++) { 1549 if (strcmp(argv[ndx], MSG_ORIG(MSG_STR_MINUS_SECSHNDX)) == 0) 1550 op = INDEX; 1551 else if (strcmp(argv[ndx], 1552 MSG_ORIG(MSG_STR_MINUS_SECSHTYP)) == 0) 1553 op = TYPE; 1554 } 1555 1556 switch (op) { 1557 case NAME: 1558 if (obj_state == NULL) 1559 break; 1560 sec = obj_state->os_secarr; 1561 for (ndx = 0; ndx < obj_state->os_shnum; ndx++, sec++) 1562 elfedit_cpl_match(cpldata, sec->sec_name, 0); 1563 break; 1564 1565 case INDEX: 1566 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHN); 1567 break; 1568 1569 case TYPE: 1570 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SHT); 1571 break; 1572 } 1573 } 1574 1575 /*ARGSUSED*/ 1576 static void 1577 cpl_st_type(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1578 const char *argv[], int num_opt) 1579 { 1580 /* Handle -shXXX options */ 1581 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 1582 1583 /* The second argument can be an STT_ value */ 1584 if (argc == (num_opt + 2)) 1585 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STT); 1586 } 1587 1588 /*ARGSUSED*/ 1589 static void 1590 cpl_st_visibility(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 1591 const char *argv[], int num_opt) 1592 { 1593 /* Handle -shXXX options */ 1594 cpl_sh_opt(obj_state, cpldata, argc, argv, num_opt); 1595 1596 /* The second argument can be an STV_ value */ 1597 if (argc == (num_opt + 2)) 1598 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_STV); 1599 } 1600 1601 1602 1603 /* 1604 * Implementation functions for the commands 1605 */ 1606 static elfedit_cmdret_t 1607 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1608 { 1609 return (cmd_body(SYM_CMD_T_DUMP, obj_state, argc, argv)); 1610 } 1611 1612 1613 static elfedit_cmdret_t 1614 cmd_st_bind(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1615 { 1616 return (cmd_body(SYM_CMD_T_ST_BIND, obj_state, argc, argv)); 1617 } 1618 1619 1620 static elfedit_cmdret_t 1621 cmd_st_info(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1622 { 1623 return (cmd_body(SYM_CMD_T_ST_INFO, obj_state, argc, argv)); 1624 } 1625 1626 static elfedit_cmdret_t 1627 cmd_st_name(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1628 { 1629 return (cmd_body(SYM_CMD_T_ST_NAME, obj_state, argc, argv)); 1630 } 1631 1632 static elfedit_cmdret_t 1633 cmd_st_other(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1634 { 1635 return (cmd_body(SYM_CMD_T_ST_OTHER, obj_state, argc, argv)); 1636 } 1637 1638 static elfedit_cmdret_t 1639 cmd_st_shndx(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1640 { 1641 return (cmd_body(SYM_CMD_T_ST_SHNDX, obj_state, argc, argv)); 1642 } 1643 1644 static elfedit_cmdret_t 1645 cmd_st_size(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1646 { 1647 return (cmd_body(SYM_CMD_T_ST_SIZE, obj_state, argc, argv)); 1648 } 1649 1650 static elfedit_cmdret_t 1651 cmd_st_type(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1652 { 1653 return (cmd_body(SYM_CMD_T_ST_TYPE, obj_state, argc, argv)); 1654 } 1655 1656 static elfedit_cmdret_t 1657 cmd_st_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1658 { 1659 return (cmd_body(SYM_CMD_T_ST_VALUE, obj_state, argc, argv)); 1660 } 1661 1662 static elfedit_cmdret_t 1663 cmd_st_visibility(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 1664 { 1665 return (cmd_body(SYM_CMD_T_ST_VISIBILITY, obj_state, argc, argv)); 1666 } 1667 1668 1669 1670 /*ARGSUSED*/ 1671 elfedit_module_t * 1672 elfedit_init(elfedit_module_version_t version) 1673 { 1674 /* Multiple commands accept only the standard set of options */ 1675 static elfedit_cmd_optarg_t opt_std[] = { 1676 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 1677 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 1678 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 1679 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 1680 { MSG_ORIG(MSG_STR_NAME), NULL, 0 }, 1681 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1682 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1683 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 1684 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 1685 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 }, 1686 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1687 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1688 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 1689 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 1690 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 }, 1691 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 1692 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 1693 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, SYM_OPT_F_SYMNDX }, 1694 { ELFEDIT_STDOA_OPT_O, NULL, 1695 ELFEDIT_CMDOA_F_INHERIT, 0 }, 1696 { NULL } 1697 }; 1698 1699 /* sym:dump */ 1700 static const char *name_dump[] = { 1701 MSG_ORIG(MSG_CMD_DUMP), 1702 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 1703 NULL 1704 }; 1705 static elfedit_cmd_optarg_t opt_dump[] = { 1706 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 1707 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 1708 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 1709 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 1710 { MSG_ORIG(MSG_STR_NAME), NULL, 0 }, 1711 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1712 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1713 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 1714 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 1715 { MSG_ORIG(MSG_STR_INDEX), NULL, 0 }, 1716 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1717 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1718 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 1719 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 1720 { MSG_ORIG(MSG_STR_TYPE), NULL, 0 }, 1721 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 1722 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 1723 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, SYM_OPT_F_SYMNDX }, 1724 { NULL } 1725 }; 1726 static elfedit_cmd_optarg_t arg_dump[] = { 1727 { MSG_ORIG(MSG_STR_SYM), 1728 /* MSG_INTL(MSG_A1_SYM) */ 1729 ELFEDIT_I18NHDL(MSG_A1_SYM), 1730 ELFEDIT_CMDOA_F_OPT }, 1731 { NULL } 1732 }; 1733 1734 /* sym:st_bind */ 1735 static const char *name_st_bind[] = { 1736 MSG_ORIG(MSG_CMD_ST_BIND), NULL }; 1737 static elfedit_cmd_optarg_t arg_st_bind[] = { 1738 { MSG_ORIG(MSG_STR_SYM), 1739 /* MSG_INTL(MSG_A1_SYM) */ 1740 ELFEDIT_I18NHDL(MSG_A1_SYM), 1741 ELFEDIT_CMDOA_F_OPT }, 1742 { MSG_ORIG(MSG_STR_VALUE), 1743 /* MSG_INTL(MSG_A2_DESC_ST_BIND) */ 1744 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_BIND), 1745 ELFEDIT_CMDOA_F_OPT }, 1746 { NULL } 1747 }; 1748 1749 /* sym:st_info */ 1750 static const char *name_st_info[] = { 1751 MSG_ORIG(MSG_CMD_ST_INFO), NULL }; 1752 static elfedit_cmd_optarg_t arg_st_info[] = { 1753 { MSG_ORIG(MSG_STR_SYM), 1754 /* MSG_INTL(MSG_A1_SYM) */ 1755 ELFEDIT_I18NHDL(MSG_A1_SYM), 1756 ELFEDIT_CMDOA_F_OPT }, 1757 { MSG_ORIG(MSG_STR_VALUE), 1758 /* MSG_INTL(MSG_A2_DESC_ST_INFO) */ 1759 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_INFO), 1760 ELFEDIT_CMDOA_F_OPT }, 1761 { NULL } 1762 }; 1763 1764 /* sym:st_name */ 1765 static const char *name_st_name[] = { 1766 MSG_ORIG(MSG_CMD_ST_NAME), NULL }; 1767 static elfedit_cmd_optarg_t opt_st_name[] = { 1768 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 1769 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 1770 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 1771 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 1772 { MSG_ORIG(MSG_STR_NAME), NULL, 0, 0 }, 1773 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1774 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1775 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 1776 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 1777 { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 1778 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1779 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1780 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 1781 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 1782 { MSG_ORIG(MSG_STR_TYPE), NULL, 0, 0 }, 1783 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 1784 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 1785 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, 1786 SYM_OPT_F_SYMNDX, 0 }, 1787 { MSG_ORIG(MSG_STR_MINUS_NAME_OFFSET), 1788 /* MSG_INTL(MSG_OPTDESC_NAME_OFFSET) */ 1789 ELFEDIT_I18NHDL(MSG_OPTDESC_NAME_OFFSET), 0, 1790 SYM_OPT_F_NAMOFFSET, 0 }, 1791 { ELFEDIT_STDOA_OPT_O, NULL, 1792 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1793 { NULL } 1794 }; 1795 static elfedit_cmd_optarg_t arg_st_name[] = { 1796 { MSG_ORIG(MSG_STR_SYM), 1797 /* MSG_INTL(MSG_A1_SYM) */ 1798 ELFEDIT_I18NHDL(MSG_A1_SYM), 1799 ELFEDIT_CMDOA_F_OPT }, 1800 { MSG_ORIG(MSG_STR_NAME), 1801 /* MSG_INTL(MSG_A2_DESC_ST_NAME) */ 1802 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_NAME), 1803 ELFEDIT_CMDOA_F_OPT }, 1804 { NULL } 1805 }; 1806 1807 /* sym:st_other */ 1808 static const char *name_st_other[] = { 1809 MSG_ORIG(MSG_CMD_ST_OTHER), NULL }; 1810 static elfedit_cmd_optarg_t arg_st_other[] = { 1811 { MSG_ORIG(MSG_STR_SYM), 1812 /* MSG_INTL(MSG_A1_SYM) */ 1813 ELFEDIT_I18NHDL(MSG_A1_SYM), 1814 ELFEDIT_CMDOA_F_OPT }, 1815 { MSG_ORIG(MSG_STR_VALUE), 1816 /* MSG_INTL(MSG_A2_DESC_ST_OTHER) */ 1817 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_OTHER), 1818 ELFEDIT_CMDOA_F_OPT }, 1819 { NULL } 1820 }; 1821 1822 /* sym:st_shndx */ 1823 static const char *name_st_shndx[] = { 1824 MSG_ORIG(MSG_CMD_ST_SHNDX), NULL }; 1825 static elfedit_cmd_optarg_t opt_st_shndx[] = { 1826 { MSG_ORIG(MSG_STR_MINUS_E), 1827 /* MSG_INTL(MSG_OPTDESC_E) */ 1828 ELFEDIT_I18NHDL(MSG_OPTDESC_E), 0, SYM_OPT_F_XSHINDEX, 0 }, 1829 { MSG_ORIG(MSG_STR_MINUS_SHNAM), 1830 /* MSG_INTL(MSG_OPTDESC_SHNAM) */ 1831 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNAM), ELFEDIT_CMDOA_F_VALUE, 1832 SYM_OPT_F_SHNAME, SYM_OPT_F_SHNDX | SYM_OPT_F_SHTYP }, 1833 { MSG_ORIG(MSG_STR_NAME), NULL, 0, 0 }, 1834 { MSG_ORIG(MSG_STR_MINUS_SHNDX), 1835 /* MSG_INTL(MSG_OPTDESC_SHNDX) */ 1836 ELFEDIT_I18NHDL(MSG_OPTDESC_SHNDX), ELFEDIT_CMDOA_F_VALUE, 1837 SYM_OPT_F_SHNDX, SYM_OPT_F_SHNAME | SYM_OPT_F_SHTYP }, 1838 { MSG_ORIG(MSG_STR_INDEX), NULL, 0, 0 }, 1839 { MSG_ORIG(MSG_STR_MINUS_SHTYP), 1840 /* MSG_INTL(MSG_OPTDESC_SHTYP) */ 1841 ELFEDIT_I18NHDL(MSG_OPTDESC_SHTYP), ELFEDIT_CMDOA_F_VALUE, 1842 SYM_OPT_F_SHTYP, SYM_OPT_F_SHNAME | SYM_OPT_F_SHNDX }, 1843 { MSG_ORIG(MSG_STR_TYPE), NULL, 0, 0 }, 1844 { MSG_ORIG(MSG_STR_MINUS_SYMNDX), 1845 /* MSG_INTL(MSG_OPTDESC_SYMNDX) */ 1846 ELFEDIT_I18NHDL(MSG_OPTDESC_SYMNDX), 0, 1847 SYM_OPT_F_SYMNDX, 0 }, 1848 { ELFEDIT_STDOA_OPT_O, NULL, 1849 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 1850 { MSG_ORIG(MSG_STR_MINUS_SECSHNDX), 1851 /* MSG_INTL(MSG_OPTDESC_SECSHNDX) */ 1852 ELFEDIT_I18NHDL(MSG_OPTDESC_SECSHNDX), 1853 0, SYM_OPT_F_SECSHNDX, SYM_OPT_F_SECSHTYP }, 1854 { MSG_ORIG(MSG_STR_MINUS_SECSHTYP), 1855 /* MSG_INTL(MSG_OPTDESC_SECSHTYP) */ 1856 ELFEDIT_I18NHDL(MSG_OPTDESC_SECSHTYP), 1857 0, SYM_OPT_F_SECSHTYP, SYM_OPT_F_SECSHNDX }, 1858 { NULL } 1859 }; 1860 static elfedit_cmd_optarg_t arg_st_shndx[] = { 1861 { MSG_ORIG(MSG_STR_SYM), 1862 /* MSG_INTL(MSG_A1_SYM) */ 1863 ELFEDIT_I18NHDL(MSG_A1_SYM), 1864 ELFEDIT_CMDOA_F_OPT }, 1865 { MSG_ORIG(MSG_STR_SEC), 1866 /* MSG_INTL(MSG_A2_DESC_ST_SEC) */ 1867 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_SEC), 1868 ELFEDIT_CMDOA_F_OPT }, 1869 { NULL } 1870 }; 1871 1872 /* sym:st_size */ 1873 static const char *name_st_size[] = { 1874 MSG_ORIG(MSG_CMD_ST_SIZE), NULL }; 1875 static elfedit_cmd_optarg_t arg_st_size[] = { 1876 { MSG_ORIG(MSG_STR_SYM), 1877 /* MSG_INTL(MSG_A1_SYM) */ 1878 ELFEDIT_I18NHDL(MSG_A1_SYM), 1879 ELFEDIT_CMDOA_F_OPT }, 1880 { MSG_ORIG(MSG_STR_VALUE), 1881 /* MSG_INTL(MSG_A2_DESC_ST_SIZE) */ 1882 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_SIZE), 1883 ELFEDIT_CMDOA_F_OPT }, 1884 { NULL } 1885 }; 1886 1887 /* sym:st_type */ 1888 static const char *name_st_type[] = { 1889 MSG_ORIG(MSG_CMD_ST_TYPE), NULL }; 1890 static elfedit_cmd_optarg_t arg_st_type[] = { 1891 { MSG_ORIG(MSG_STR_SYM), 1892 /* MSG_INTL(MSG_A1_SYM) */ 1893 ELFEDIT_I18NHDL(MSG_A1_SYM), 1894 ELFEDIT_CMDOA_F_OPT }, 1895 { MSG_ORIG(MSG_STR_VALUE), 1896 /* MSG_INTL(MSG_A2_DESC_ST_TYPE) */ 1897 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_TYPE), 1898 ELFEDIT_CMDOA_F_OPT }, 1899 { NULL } 1900 }; 1901 1902 /* sym:st_value */ 1903 static const char *name_st_value[] = { 1904 MSG_ORIG(MSG_CMD_ST_VALUE), NULL }; 1905 static elfedit_cmd_optarg_t arg_st_value[] = { 1906 { MSG_ORIG(MSG_STR_SYM), 1907 /* MSG_INTL(MSG_A1_SYM) */ 1908 ELFEDIT_I18NHDL(MSG_A1_SYM), 1909 ELFEDIT_CMDOA_F_OPT }, 1910 { MSG_ORIG(MSG_STR_VALUE), 1911 /* MSG_INTL(MSG_A2_DESC_ST_VALUE) */ 1912 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_VALUE), 1913 ELFEDIT_CMDOA_F_OPT }, 1914 { NULL } 1915 }; 1916 1917 /* sym:st_visibility */ 1918 static const char *name_st_visibility[] = { 1919 MSG_ORIG(MSG_CMD_ST_VISIBILITY), NULL }; 1920 static elfedit_cmd_optarg_t arg_st_visibility[] = { 1921 { MSG_ORIG(MSG_STR_SYM), 1922 /* MSG_INTL(MSG_A1_SYM) */ 1923 ELFEDIT_I18NHDL(MSG_A1_SYM), 1924 ELFEDIT_CMDOA_F_OPT }, 1925 { MSG_ORIG(MSG_STR_VALUE), 1926 /* MSG_INTL(MSG_A2_DESC_ST_VISIBILITY) */ 1927 ELFEDIT_I18NHDL(MSG_A2_DESC_ST_VISIBILITY), 1928 ELFEDIT_CMDOA_F_OPT }, 1929 { NULL } 1930 }; 1931 1932 static elfedit_cmd_t cmds[] = { 1933 /* sym:dump */ 1934 { cmd_dump, cpl_sh_opt, name_dump, 1935 /* MSG_INTL(MSG_DESC_DUMP) */ 1936 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 1937 /* MSG_INTL(MSG_HELP_DUMP) */ 1938 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 1939 opt_dump, arg_dump }, 1940 1941 /* sym:st_bind */ 1942 { cmd_st_bind, cpl_st_bind, name_st_bind, 1943 /* MSG_INTL(MSG_DESC_ST_BIND) */ 1944 ELFEDIT_I18NHDL(MSG_DESC_ST_BIND), 1945 /* MSG_INTL(MSG_HELP_ST_BIND) */ 1946 ELFEDIT_I18NHDL(MSG_HELP_ST_BIND), 1947 opt_std, arg_st_bind }, 1948 1949 /* sym:st_info */ 1950 { cmd_st_info, cpl_sh_opt, name_st_info, 1951 /* MSG_INTL(MSG_DESC_ST_INFO) */ 1952 ELFEDIT_I18NHDL(MSG_DESC_ST_INFO), 1953 /* MSG_INTL(MSG_HELP_ST_INFO) */ 1954 ELFEDIT_I18NHDL(MSG_HELP_ST_INFO), 1955 opt_std, arg_st_info }, 1956 1957 /* sym:st_name */ 1958 { cmd_st_name, cpl_sh_opt, name_st_name, 1959 /* MSG_INTL(MSG_DESC_ST_NAME) */ 1960 ELFEDIT_I18NHDL(MSG_DESC_ST_NAME), 1961 /* MSG_INTL(MSG_HELP_ST_NAME) */ 1962 ELFEDIT_I18NHDL(MSG_HELP_ST_NAME), 1963 opt_st_name, arg_st_name }, 1964 1965 /* sym:st_other */ 1966 { cmd_st_other, cpl_sh_opt, name_st_other, 1967 /* MSG_INTL(MSG_DESC_ST_OTHER) */ 1968 ELFEDIT_I18NHDL(MSG_DESC_ST_OTHER), 1969 /* MSG_INTL(MSG_HELP_ST_OTHER) */ 1970 ELFEDIT_I18NHDL(MSG_HELP_ST_OTHER), 1971 opt_std, arg_st_other }, 1972 1973 /* sym:st_shndx */ 1974 { cmd_st_shndx, cpl_st_shndx, name_st_shndx, 1975 /* MSG_INTL(MSG_DESC_ST_SHNDX) */ 1976 ELFEDIT_I18NHDL(MSG_DESC_ST_SHNDX), 1977 /* MSG_INTL(MSG_HELP_ST_SHNDX) */ 1978 ELFEDIT_I18NHDL(MSG_HELP_ST_SHNDX), 1979 opt_st_shndx, arg_st_shndx }, 1980 1981 /* sym:st_size */ 1982 { cmd_st_size, cpl_sh_opt, name_st_size, 1983 /* MSG_INTL(MSG_DESC_ST_SIZE) */ 1984 ELFEDIT_I18NHDL(MSG_DESC_ST_SIZE), 1985 /* MSG_INTL(MSG_HELP_ST_SIZE) */ 1986 ELFEDIT_I18NHDL(MSG_HELP_ST_SIZE), 1987 opt_std, arg_st_size }, 1988 1989 /* sym:st_type */ 1990 { cmd_st_type, cpl_st_type, name_st_type, 1991 /* MSG_INTL(MSG_DESC_ST_TYPE) */ 1992 ELFEDIT_I18NHDL(MSG_DESC_ST_TYPE), 1993 /* MSG_INTL(MSG_HELP_ST_TYPE) */ 1994 ELFEDIT_I18NHDL(MSG_HELP_ST_TYPE), 1995 opt_std, arg_st_type }, 1996 1997 /* sym:st_value */ 1998 { cmd_st_value, cpl_sh_opt, name_st_value, 1999 /* MSG_INTL(MSG_DESC_ST_VALUE) */ 2000 ELFEDIT_I18NHDL(MSG_DESC_ST_VALUE), 2001 /* MSG_INTL(MSG_HELP_ST_VALUE) */ 2002 ELFEDIT_I18NHDL(MSG_HELP_ST_VALUE), 2003 opt_std, arg_st_value }, 2004 2005 /* sym:st_visibility */ 2006 { cmd_st_visibility, cpl_st_visibility, name_st_visibility, 2007 /* MSG_INTL(MSG_DESC_ST_VISIBILITY) */ 2008 ELFEDIT_I18NHDL(MSG_DESC_ST_VISIBILITY), 2009 /* MSG_INTL(MSG_HELP_ST_VISIBILITY) */ 2010 ELFEDIT_I18NHDL(MSG_HELP_ST_VISIBILITY), 2011 opt_std, arg_st_visibility }, 2012 2013 { NULL } 2014 }; 2015 2016 static elfedit_module_t module = { 2017 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 2018 /* MSG_INTL(MSG_MOD_DESC) */ 2019 ELFEDIT_I18NHDL(MSG_MOD_DESC), 2020 cmds, mod_i18nhdl_to_str }; 2021 2022 return (&module); 2023 } 2024