1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdlib.h> 28 #include <stdio.h> 29 #include <unistd.h> 30 #include <libintl.h> 31 #include <_machelf.h> 32 #include <libelf.h> 33 #include <link.h> 34 #include <strings.h> 35 #include <ctype.h> 36 #include "msg.h" 37 #include <elfedit.h> 38 #include <conv.h> 39 #include <sys/elf_SPARC.h> 40 #include <sys/elf_amd64.h> 41 42 43 44 /* 45 * ELFCLASS specific code that would otherwise be found in util.c 46 */ 47 48 49 50 51 /* 52 * When you modify ELF constructs, you need to tell libelf that you've 53 * done so. Otherwise, the changes may not be flushed back to the 54 * output file. 55 * 56 * The elfedit_modified_*() functions exist to simplify the calls to 57 * the underlying elf_flag*() functions. 58 */ 59 void 60 elfedit_modified_ehdr(elfedit_obj_state_t *obj_state) 61 { 62 (void) elf_flagehdr(obj_state->os_elf, ELF_C_SET, ELF_F_DIRTY); 63 } 64 65 void 66 elfedit_modified_phdr(elfedit_obj_state_t *obj_state) 67 { 68 (void) elf_flagphdr(obj_state->os_elf, ELF_C_SET, ELF_F_DIRTY); 69 } 70 71 void 72 elfedit_modified_shdr(elfedit_section_t *s) 73 { 74 (void) elf_flagshdr(s->sec_scn, ELF_C_SET, ELF_F_DIRTY); 75 } 76 77 void 78 elfedit_modified_data(elfedit_section_t *s) 79 { 80 (void) elf_flagdata(s->sec_data, ELF_C_SET, ELF_F_DIRTY); 81 } 82 83 84 85 /* 86 * Prepare an elfedit_dyn_elt_t structure for use. 87 */ 88 void 89 elfedit_dyn_elt_init(elfedit_dyn_elt_t *elt) 90 { 91 elt->dn_seen = 0; 92 } 93 94 /* 95 * Given a dynamic section item, save it in the given elfedit_dyn_elt_t 96 * structure and mark that structure to show that it is present. 97 */ 98 void 99 elfedit_dyn_elt_save(elfedit_dyn_elt_t *elt, Word ndx, Dyn *dyn) 100 { 101 elt->dn_seen = 1; 102 elt->dn_ndx = ndx; 103 elt->dn_dyn = *dyn; 104 } 105 106 107 /* 108 * Return the index of the first section that has the given name. 109 * 110 * entry: 111 * obj_state - Object state. 112 * shnam - Name of desired section 113 * 114 * exit: 115 * On success, returns the section index. On failure, an error 116 * is issued, and this routine does not return to the caller. 117 */ 118 Word 119 elfedit_name_to_shndx(elfedit_obj_state_t *obj_state, const char *shnam) 120 { 121 elfedit_section_t *sec = obj_state->os_secarr; 122 Word ndx; 123 Word shnum = obj_state->os_shnum; 124 125 for (ndx = 0; ndx < shnum; ndx++, sec++) { 126 if (strcmp(shnam, sec->sec_name) == 0) { 127 elfedit_msg(ELFEDIT_MSG_DEBUG, 128 MSG_INTL(MSG_DEBUG_SHNAM2NDX), 129 EC_WORD(sec->sec_shndx), sec->sec_name, shnam); 130 return (ndx); 131 } 132 } 133 134 /* If didn't return in loop above, the name doesn't match */ 135 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSECNAM), shnam); 136 /*NOTREACHED*/ 137 return (SHN_UNDEF); 138 } 139 140 141 142 /* 143 * Return the index of the first section that has the given type. 144 * 145 * entry: 146 * obj_state - Object state. 147 * shtype - Type of desired section 148 * 149 * exit: 150 * On success, returns the section index. On failure, an error 151 * is issued, and this routine does not return to the caller. 152 */ 153 Word 154 elfedit_type_to_shndx(elfedit_obj_state_t *obj_state, Word shtype) 155 { 156 Conv_inv_buf_t inv_buf; 157 elfedit_section_t *sec = obj_state->os_secarr; 158 Word ndx; 159 Word shnum = obj_state->os_shnum; 160 161 for (ndx = 0; ndx < shnum; ndx++, sec++) { 162 if (shtype == sec->sec_shdr->sh_type) { 163 elfedit_msg(ELFEDIT_MSG_DEBUG, 164 MSG_INTL(MSG_DEBUG_SHNAM2NDX), 165 EC_WORD(sec->sec_shndx), sec->sec_name, 166 conv_sec_type( 167 obj_state->os_ehdr->e_ident[EI_OSABI], 168 obj_state->os_ehdr->e_machine, 169 shtype, 0, &inv_buf)); 170 return (ndx); 171 } 172 } 173 174 /* If didn't return in loop above, the name doesn't match */ 175 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSECTYP), 176 conv_sec_type(obj_state->os_ehdr->e_ident[EI_OSABI], 177 obj_state->os_ehdr->e_machine, shtype, 0, &inv_buf)); 178 /*NOTREACHED*/ 179 return (SHN_UNDEF); 180 } 181 182 183 184 /* 185 * Locate the index of the first symbol that has the given name 186 * 187 * entry: 188 * obj_state - Object state. 189 * symsec - Symbol section 190 * strsec = String section 191 * name - String giving name of symbol to lookup 192 * msg_type - ELFEDIT_MSG_ type code to use with message 193 * issued if name does not exist in symbol table. 194 * ret_symndx - Address of variable to receive index. 195 * 196 * exit: 197 * On success, issues debug message, sets *ret_symndx, and returns 198 * True (1). 199 * 200 * On failure, issues a message using msg_type to determine 201 * the type of message sent. If the message does not take control away 202 * from the caller, False (0) is returned. 203 * 204 * note: 205 * Although the string table is referenced by the sh_link field of 206 * the symbol table, we require the user to supply it rather than 207 * look it up. The reason for this is that the caller will usually 208 * have looked it up, and we wish to avoid multiple debug messages 209 * from being issued to that effect. 210 */ 211 int 212 elfedit_name_to_symndx(elfedit_section_t *symsec, elfedit_section_t *strsec, 213 const char *name, elfedit_msg_t msg_type, Word *ret_symndx) 214 215 { 216 Sym *sym = (Sym *) symsec->sec_data->d_buf; 217 Word cnt = symsec->sec_shdr->sh_size / symsec->sec_shdr->sh_entsize; 218 Word ndx, offset; 219 const char *curname; 220 221 for (ndx = 0; ndx < cnt; ndx++) { 222 offset = sym[ndx].st_name; 223 224 curname = elfedit_offset_to_str(strsec, offset, 225 ELFEDIT_MSG_ERR, 0); 226 if (strcmp(curname, name) == 0) { 227 elfedit_msg(ELFEDIT_MSG_DEBUG, 228 MSG_INTL(MSG_DEBUG_SYMNAM2NDX), 229 EC_WORD(symsec->sec_shndx), 230 symsec->sec_name, EC_WORD(ndx), name); 231 *ret_symndx = ndx; 232 return (1); 233 } 234 } 235 236 /* If didn't return in loop above, the name doesn't match */ 237 elfedit_msg(msg_type, MSG_INTL(MSG_ERR_NOSYM), 238 EC_WORD(symsec->sec_shndx), symsec->sec_name, name); 239 /*NOTREACHED*/ 240 return (0); /* lint */ 241 } 242 243 244 /* 245 * Given a section index, turn it into a descriptive string. 246 * - If it is one of the special reserved indexes, the 247 * symbolic name is returned. 248 * - If it is a regular section, in range for the file, 249 * the name associated with the section is returned. 250 * - Otherwise, the number is formatted as numeric ASCII. 251 * 252 * exit: 253 * A pointer to the static buffer containing the name is 254 * returned. This pointer is valid until the next call 255 * to elfedit_shndx_to_name(), and which point it may 256 * be overwritten. 257 */ 258 const char * 259 elfedit_shndx_to_name(elfedit_obj_state_t *obj_state, Word shndx) 260 { 261 /* 262 * This routine can be called twice within a single C statement, 263 * so we use alternating buffers on each call to allow this 264 * without requiring the caller to supply a buffer (the size of 265 * which they don't know). 266 */ 267 static Conv_inv_buf_t buf1, buf2; 268 static Conv_inv_buf_t *buf; 269 270 /* 271 * If it is outside of the reserved area, and inside the 272 * range of section indexes in the ELF file, then show 273 * the section name. 274 */ 275 if ((shndx < obj_state->os_shnum) && 276 ((shndx < SHN_LORESERVE) || (shndx > SHN_HIRESERVE)) && 277 (shndx != SHN_UNDEF)) 278 return (obj_state->os_secarr[shndx].sec_name); 279 280 /* 281 * Anything else is handled by libconv. It will return standard 282 * names for known items, or format as a number otherwise. 283 */ 284 buf = (buf == &buf1) ? &buf2 : &buf1; /* Switch buffers */ 285 return (conv_sym_shndx(obj_state->os_ehdr->e_ident[EI_OSABI], 286 obj_state->os_ehdr->e_machine, shndx, 287 CONV_FMT_ALT_CF | CONV_FMT_DECIMAL, buf)); 288 } 289 290 291 /* 292 * Locate the arbitrary section specified by shndx for this object. 293 * 294 * exit: 295 * Returns section descriptor on success. On failure, does not return. 296 */ 297 elfedit_section_t * 298 elfedit_sec_get(elfedit_obj_state_t *obj_state, Word shndx) 299 { 300 elfedit_section_t *sec; 301 302 if ((shndx == 0) || (shndx >= obj_state->os_shnum)) 303 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADSECNDX), 304 EC_WORD(shndx), EC_WORD(obj_state->os_shnum - 1)); 305 306 sec = &obj_state->os_secarr[shndx]; 307 308 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSEC), 309 EC_WORD(shndx), sec->sec_name); 310 return (sec); 311 } 312 313 314 315 /* 316 * Compare the a specified osabi with that of the current object. 317 * 318 * entry: 319 * obj_state - Object state for open object to query. 320 * issue_err - True if this routine should issue an error and 321 * not return to the caller if osabi is not native. 322 * 323 * exit: 324 * If current osabi is the one specified, True (1) is returned. 325 * 326 * Otherwise, if issue_err is True, an error is issued and this 327 * routine does not return to the caller. If issue_err is False, 328 * False (0) is returned. 329 * 330 * note: 331 * ELFOSABI_NONE is considered to be equivalent to ELFOSABI_SOLARIS. 332 */ 333 int 334 elfedit_test_osabi(elfedit_obj_state_t *obj_state, uchar_t osabi, 335 int issue_err) 336 { 337 uchar_t obj_osabi = obj_state->os_ehdr->e_ident[EI_OSABI]; 338 Conv_inv_buf_t inv_buf; 339 340 if (obj_osabi == ELFOSABI_NONE) 341 obj_osabi = ELFOSABI_SOLARIS; 342 343 if (osabi == obj_osabi) 344 return (1); 345 346 if (issue_err) 347 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADOSABI), 348 conv_ehdr_osabi(osabi, 0, &inv_buf)); 349 return (0); 350 } 351 352 /* 353 * Locate the capabilities section for this object 354 * 355 * entry: 356 * obj_state - Object state for open object to query. 357 * cap - Address of variable to recieve pointer to capabilities 358 * section data buffer. 359 * num - Address of variable to receive number of items 360 * referenced by cap. 361 * 362 * exit: 363 * On success, returns section descriptor, and sets the 364 * variables referenced by cap and num. On failure, 365 * does not return. 366 */ 367 elfedit_section_t * 368 elfedit_sec_getcap(elfedit_obj_state_t *obj_state, Cap **cap, Word *num) 369 { 370 Word cnt; 371 elfedit_section_t *cache; 372 373 (void) elfedit_test_osabi(obj_state, ELFOSABI_SOLARIS, 1); 374 375 for (cnt = 1; cnt < obj_state->os_shnum; cnt++) { 376 cache = &obj_state->os_secarr[cnt]; 377 if (cache->sec_shdr->sh_type == SHT_SUNW_cap) { 378 elfedit_msg(ELFEDIT_MSG_DEBUG, 379 MSG_INTL(MSG_DEBUG_FNDCAP), 380 EC_WORD(cnt), cache->sec_name); 381 *cap = (Cap *) cache->sec_data->d_buf; 382 *num = cache->sec_shdr->sh_size / 383 cache->sec_shdr->sh_entsize; 384 return (cache); 385 } 386 } 387 388 /* If here, this object has no capabilities section */ 389 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAP)); 390 391 /*NOTREACHED*/ 392 return (NULL); 393 } 394 395 396 /* 397 * Locate the dynamic section for this object 398 * 399 * entry: 400 * obj_state - Object state for open object to query. 401 * dyn - Address of variable to recieve pointer to dynamic 402 * section data buffer. 403 * numdyn - Address of variable to receive number of items 404 * referenced by dyn. 405 * 406 * exit: 407 * On success, returns section descriptor, and sets the 408 * variables referenced by dyn and numdyn. On failure, 409 * does not return. 410 */ 411 elfedit_section_t * 412 elfedit_sec_getdyn(elfedit_obj_state_t *obj_state, Dyn **dyn, Word *num) 413 { 414 elfedit_section_t *cache; 415 416 if (obj_state->os_dynndx != SHN_UNDEF) { 417 cache = &obj_state->os_secarr[obj_state->os_dynndx]; 418 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDDYN), 419 EC_WORD(cache->sec_shndx), cache->sec_name); 420 *dyn = (Dyn *) cache->sec_data->d_buf; 421 *num = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize; 422 return (cache); 423 } 424 425 /* If here, this object has no dynamic section */ 426 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODYN)); 427 428 /*NOTREACHED*/ 429 return (NULL); 430 } 431 432 433 /* 434 * Locate the syminfo section for this object 435 * 436 * entry: 437 * obj_state - Object state for open object to query. 438 * syminfo - Address of variable to recieve pointer to syminfo 439 * section data buffer. 440 * num - Address of variable to receive number of items 441 * referenced by syminfo. 442 * 443 * exit: 444 * On success, returns section descriptor, and sets the 445 * variables referenced by syminfo and num. On failure, 446 * does not return. 447 */ 448 elfedit_section_t * 449 elfedit_sec_getsyminfo(elfedit_obj_state_t *obj_state, Syminfo **syminfo, 450 Word *num) 451 { 452 Word cnt; 453 elfedit_section_t *cache; 454 455 for (cnt = 1; cnt < obj_state->os_shnum; cnt++) { 456 cache = &obj_state->os_secarr[cnt]; 457 if (cache->sec_shdr->sh_type == SHT_SUNW_syminfo) { 458 elfedit_msg(ELFEDIT_MSG_DEBUG, 459 MSG_INTL(MSG_DEBUG_FNDSYMINFO), 460 EC_WORD(cnt), cache->sec_name); 461 *syminfo = (Syminfo *) cache->sec_data->d_buf; 462 *num = cache->sec_shdr->sh_size / 463 cache->sec_shdr->sh_entsize; 464 return (cache); 465 } 466 } 467 468 /* If here, this object has no syminfo section */ 469 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMINFO)); 470 471 /*NOTREACHED*/ 472 return (NULL); 473 } 474 475 476 /* 477 * Check the given section to see if it is a known symbol table type. 478 * 479 * entry: 480 * obj_state - Object state for open object to query. 481 * sec - Section to check 482 * issue_err - True if this routine should issue an error and 483 * not return to the caller if sec is not a symbol table. 484 * atoui_list - NULL, or address of variable to receive a pointer to 485 * an array of elfedit_atoui_sym_t items describing the 486 * type of symbol table found. This array is useful for 487 * doing command completion. 488 * 489 * exit: 490 * If sec is a symbol table: 491 * - If atoui_list is non-NULL, *atoui_list is set to the 492 * appropriate ELFEDIT_CONST_xx list of items. 493 * - True (1) is returned 494 * If sec is not a symbol table and issue_err is True: 495 * - An error is issued, and this routine does not 496 * return to the caller. 497 * Otherwise: 498 * - If atoui_list is non-NULL, *atoui_list is set to NULL. 499 * - False (0) is returned 500 */ 501 int 502 elfedit_sec_issymtab(elfedit_obj_state_t *obj_state, elfedit_section_t *sec, 503 int issue_err, elfedit_atoui_sym_t **atoui_list) 504 { 505 elfedit_const_t const_type; 506 int ret = 1; 507 508 /* Is the section a symbol table? */ 509 switch (sec->sec_shdr->sh_type) { 510 case SHT_SYMTAB: 511 const_type = ELFEDIT_CONST_SHT_SYMTAB; 512 break; 513 case SHT_DYNSYM: 514 const_type = ELFEDIT_CONST_SHT_DYNSYM; 515 break; 516 case SHT_SUNW_LDYNSYM: 517 /* 518 * These sections are only known to be symbol tables 519 * if the osabi is Solaris. 520 */ 521 if (elfedit_test_osabi(obj_state, ELFOSABI_SOLARIS, 0)) { 522 const_type = ELFEDIT_CONST_SHT_LDYNSYM; 523 break; 524 } 525 /*FALLTHROUGH*/ 526 default: 527 if (issue_err) 528 elfedit_msg(ELFEDIT_MSG_ERR, 529 MSG_INTL(MSG_ERR_NOTSYMTAB), 530 EC_WORD(sec->sec_shndx), sec->sec_name); 531 ret = 0; 532 break; 533 } 534 535 if (atoui_list != NULL) 536 *atoui_list = (ret == 0) ? NULL : 537 elfedit_const_to_atoui(const_type); 538 539 return (ret); 540 } 541 542 543 544 /* 545 * Locate a symbol table section for this object 546 * 547 * entry: 548 * obj_state - Object state for open object to query. 549 * by_index - If True, we want to locate the section with the 550 * section index given by index. If False, we return 551 * the section with the name given by name. 552 * index, name - Key to search for. See by_index. 553 * sym - Address of variable to recieve pointer to symbol 554 * section data buffer. 555 * numsym - Address of variable to receive number of symbols 556 * referenced by sym. 557 * aux_info - Address of variable to receive pointer to the 558 * elfedit_symtab_t struct that ties the symbol table and 559 * its related auxiliary sections together. NULL if this 560 * information is not required. 561 * 562 * exit: 563 * On success, returns section descriptor, and sets the 564 * variables referenced by sym, and numsym. On failure, 565 * does not return. 566 */ 567 elfedit_section_t * 568 elfedit_sec_getsymtab(elfedit_obj_state_t *obj_state, int by_index, 569 Word index, const char *name, Sym **sym, Word *num, 570 elfedit_symtab_t **aux_info) 571 { 572 Word ndx; 573 elfedit_section_t *symsec = NULL; 574 elfedit_symtab_t *symtab; 575 const char *type_name; 576 577 /* If looking it up by index, make sure the index is in range */ 578 if (by_index && (index >= obj_state->os_shnum)) 579 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADSECNDX), 580 EC_WORD(index), EC_WORD(obj_state->os_shnum - 1)); 581 582 /* 583 * Look at each known symbol table in turn until the desired 584 * one is hit, or there are no more. 585 */ 586 symtab = obj_state->os_symtab; 587 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) { 588 elfedit_section_t *s = 589 &obj_state->os_secarr[symtab->symt_shndx]; 590 591 if ((by_index && (symtab->symt_shndx == index)) || 592 (!by_index && (strcmp(s->sec_name, name) == 0))) { 593 symsec = s; 594 break; 595 } 596 } 597 598 /* Did we get a section? */ 599 if (symsec == NULL) 600 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSYMTAB)); 601 602 /* Got it. Report to the user and return the necessary data */ 603 (void) elfedit_sec_issymtab(obj_state, symsec, 1, NULL); 604 type_name = elfedit_atoconst_value_to_str(ELFEDIT_CONST_SHT_ALLSYMTAB, 605 symsec->sec_shdr->sh_type, 1); 606 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSYMTAB), 607 EC_WORD(symsec->sec_shndx), symsec->sec_name, type_name); 608 *sym = (Sym *) symsec->sec_data->d_buf; 609 *num = symsec->sec_shdr->sh_size / symsec->sec_shdr->sh_entsize; 610 if (aux_info != NULL) 611 *aux_info = symtab; 612 return (symsec); 613 } 614 615 616 617 /* 618 * Locate the extended symbol index section associated with a symbol 619 * table section. 620 * 621 * entry: 622 * obj_state - Object state for open object to query. 623 * symsec - Symbol table section for which extended index 624 * index section is required. 625 * xshndx - Address of variable to recieve pointer to section index 626 * array data buffer. 627 * numxshndx - Address of variable to receive number of indices 628 * referenced by ndx. 629 * 630 * exit: 631 * On success, returns extended index section descriptor, and sets the 632 * variables referenced by xshndx, and numxshndx. On failure, 633 * does not return. 634 * 635 * note: 636 * Since the extended section index is found in the sec_xshndx field 637 * of the elfedit_section_t, the caller may be tempted to bypass this 638 * routine and access it directly. That temptation should be resisted, 639 * as this routine performs useful error checking, and also handles 640 * the issuing of the standard MSG_DEBUG messages. 641 */ 642 elfedit_section_t * 643 elfedit_sec_getxshndx(elfedit_obj_state_t *obj_state, 644 elfedit_section_t *symsec, Word **xshndx, Word *num) 645 { 646 elfedit_section_t *xshndxsec; 647 elfedit_symtab_t *symtab; 648 Word ndx; 649 650 /* Sanity check: symsec must be a symbol table */ 651 (void) elfedit_sec_issymtab(obj_state, symsec, 1, NULL); 652 653 symtab = obj_state->os_symtab; 654 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) 655 if (symsec->sec_shndx == symtab->symt_shndx) 656 break; 657 658 /* 659 * Issue error if the symbol table lacks an extended index section. 660 * The caller won't ask unless they encounter an SHN_XINDEX value, 661 * in which case the lack of the index section denotes a corrupt 662 * ELF file. 663 */ 664 if ((ndx == obj_state->os_symtabnum) || 665 (symtab->symt_xshndx == SHN_UNDEF)) 666 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOXSHSEC), 667 EC_WORD(symsec->sec_shndx), symsec->sec_name); 668 669 /* Got it. Report to the user and return the necessary data */ 670 xshndxsec = &obj_state->os_secarr[symtab->symt_xshndx]; 671 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDXSHNDX), 672 EC_WORD(symsec->sec_shndx), symsec->sec_name, 673 EC_WORD(xshndxsec->sec_shndx), xshndxsec->sec_name); 674 *xshndx = (Word *) xshndxsec->sec_data->d_buf; 675 *num = xshndxsec->sec_shdr->sh_size / xshndxsec->sec_shdr->sh_entsize; 676 return (xshndxsec); 677 } 678 679 680 681 /* 682 * Locate the versym section associated with a symbol table section. 683 * 684 * entry: 685 * obj_state - Object state for open object to query. 686 * symsec - Symbol table section for which extended index 687 * index section is required. 688 * versym - Address of variable to recieve pointer to section index 689 * array data buffer. 690 * numversym - Address of variable to receive number of indices 691 * referenced by ndx. 692 * 693 * exit: 694 * On success, returns versym section descriptor, and sets the 695 * variables referenced by versym, and numversym. On failure, 696 * does not return. 697 * 698 * note: 699 * Since the versym section index is found in the sec_versym field 700 * of the elfedit_section_t, the caller may be tempted to bypass this 701 * routine and access it directly. That temptation should be resisted, 702 * as this routine performs useful error checking, and also handles 703 * the issuing of the standard MSG_DEBUG messages. 704 */ 705 elfedit_section_t * 706 elfedit_sec_getversym(elfedit_obj_state_t *obj_state, 707 elfedit_section_t *symsec, Versym **versym, Word *num) 708 { 709 elfedit_section_t *versymsec; 710 elfedit_symtab_t *symtab; 711 Word ndx; 712 713 /* Sanity check: symsec must be a symbol table */ 714 (void) elfedit_sec_issymtab(obj_state, symsec, 1, NULL); 715 716 symtab = obj_state->os_symtab; 717 for (ndx = 0; ndx < obj_state->os_symtabnum; ndx++, symtab++) 718 if (symsec->sec_shndx == symtab->symt_shndx) 719 break; 720 /* 721 * Issue error if the symbol table lacks a versym section. 722 * The caller won't ask unless they see a non-null 723 * aux.symtab.sec_versym, so this should not be a problem. 724 */ 725 if ((ndx == obj_state->os_symtabnum) || 726 (symtab->symt_versym == SHN_UNDEF)) 727 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOVERSYMSEC), 728 EC_WORD(symsec->sec_shndx), symsec->sec_name); 729 730 /* Got it. Report to the user and return the necessary data */ 731 versymsec = &obj_state->os_secarr[symtab->symt_versym]; 732 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDVERSYM), 733 EC_WORD(symsec->sec_shndx), symsec->sec_name, 734 EC_WORD(versymsec->sec_shndx), versymsec->sec_name); 735 *versym = (Versym *) versymsec->sec_data->d_buf; 736 *num = versymsec->sec_shdr->sh_size / versymsec->sec_shdr->sh_entsize; 737 return (versymsec); 738 } 739 740 741 742 /* 743 * Locate the string table specified by shndx for this object. 744 * 745 * entry: 746 * obj_state - Object state. 747 * shndx - Section index for string table section 748 * allow_shflags - If False (0), only sections of type SHT_STRTAB 749 * are accepted as being string tables, and any other type 750 * will fail. If True (1), non-stringtable sections with 751 * their SHF_STRINGS flag set are also accepted. 752 * 753 * exit: 754 * Returns section descriptor on success. On failure, does not return. 755 * 756 * note: 757 * At this time, we can only support SHF_STRINGS sections that 758 * use single byte characters and which do not require alignment >1. 759 * SHF_STRINGS sections that have multi-byte characters or alignment 760 * are not currently supported and will draw an error even if 761 * allow_shflags is True. 762 */ 763 elfedit_section_t * 764 elfedit_sec_getstr(elfedit_obj_state_t *obj_state, Word shndx, 765 int allow_shflags) 766 { 767 elfedit_section_t *strsec; 768 769 if ((shndx == 0) || (shndx >= obj_state->os_shnum)) 770 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_STRSHNDX), 771 EC_WORD(shndx), EC_WORD(obj_state->os_shnum - 1)); 772 773 strsec = &obj_state->os_secarr[shndx]; 774 if (strsec->sec_shdr->sh_type == SHT_STRTAB) { 775 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTRTAB), 776 EC_WORD(shndx), strsec->sec_name); 777 } else if (allow_shflags && 778 ((strsec->sec_shdr->sh_flags & SHF_STRINGS) != 0) && 779 (strsec->sec_shdr->sh_entsize <= 1) && 780 (strsec->sec_shdr->sh_addralign <= 1)) { 781 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTRTABFL), 782 EC_WORD(shndx), strsec->sec_name); 783 } else { 784 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOTSTRSH), 785 EC_WORD(shndx), strsec->sec_name); 786 } 787 788 return (strsec); 789 } 790 791 792 /* 793 * Returns the offset of the specified string from within 794 * the given section. 795 * 796 * entry: 797 * sec - Descriptor for section 798 * tail_ign - If non-zero, the # of characters at the end of the 799 * section that should be ignored and not searched. 800 * str - String we are looking for. 801 * ret_offset - Address of variable to receive result 802 * 803 * exit: 804 * Returns 1 for success, and 0 for failure. If successful, *ret_offset 805 * is set to the offset of the found string within the section. 806 */ 807 int 808 elfedit_sec_findstr(elfedit_section_t *sec, Word tail_ign, 809 const char *str, Word *ret_offset) 810 { 811 int str_fch = *str; /* First character in str */ 812 Word len; /* # characters in table */ 813 char *s; /* ptr to strings within table */ 814 const char *tail; /* 1 past final character of table */ 815 816 817 /* Size of the section, minus the reserved part (if any) at the end */ 818 len = sec->sec_shdr->sh_size - tail_ign; 819 820 /* 821 * Move through the section character by character looking for 822 * a match. Moving character by character instead of skipping 823 * from NULL terminated string to string allows us to use 824 * the tails longer strings (i.e. we want "bar", and "foobar" exists). 825 * We look at the first character manually before calling strcmp() 826 * to lower the cost of this approach. 827 */ 828 s = (char *)sec->sec_data->d_buf; 829 tail = s + len; 830 for (; s <= tail; s++) { 831 if ((*s == str_fch) && (strcmp(s, str) == 0)) { 832 *ret_offset = s - (char *)sec->sec_data->d_buf; 833 elfedit_msg(ELFEDIT_MSG_DEBUG, 834 MSG_INTL(MSG_DEBUG_EXISTSTR), 835 EC_WORD(sec->sec_shndx), sec->sec_name, 836 EC_WORD(*ret_offset), s); 837 return (1); 838 } 839 } 840 841 /* Didn't find it. Report failure */ 842 return (0); 843 } 844 845 846 /* 847 * Locate the DT_SUNW_STRPAD element of the given dynamic section if 848 * it exists. 849 * 850 * entry: 851 * obj_state - Object state for open object to query. 852 * dynsec - Dynamic section descriptor 853 * dyn_strpad - Address of variable to receive the results. 854 * The caller is responsible for calling elfedit_dyn_elt_init() 855 * on this variable beforehand. 856 * 857 * exit: 858 * The dynamic section is searched, and if a DT_SUNW_STRPAD element 859 * is found, dyn_strpad is updated via elfedit_dyn_elt_save() to 860 * reference it. 861 * 862 * Returns the final value of dyn_strpad->dn_seen. 863 */ 864 int 865 elfedit_dynstr_getpad(elfedit_obj_state_t *obj_state, elfedit_section_t *dynsec, 866 elfedit_dyn_elt_t *dyn_strpad) 867 { 868 Word numdyn = dynsec->sec_shdr->sh_size / dynsec->sec_shdr->sh_entsize; 869 Dyn *dyn = (Dyn *) dynsec->sec_data->d_buf; 870 Word i; 871 872 /* 873 * DT_SUNW_STRPAD is specific to the Solaris OSABI. 874 * If the object is tagged otherwise, don't even look. 875 */ 876 if (!elfedit_test_osabi(obj_state, ELFOSABI_SOLARIS, 0)) 877 return (dyn_strpad->dn_seen); 878 879 /* Go through dynamic section tags and find the STRPAD entry */ 880 for (i = 0; i < numdyn; i++) { 881 if (dyn[i].d_tag == DT_SUNW_STRPAD) { 882 elfedit_dyn_elt_save(dyn_strpad, i, &dyn[i]); 883 break; 884 } 885 } 886 887 return (dyn_strpad->dn_seen); 888 } 889 890 891 892 /* 893 * Given references to the dynamic section, its string table, 894 * and the DT_SUNW_STRPAD entry of the dynamic section, returns 895 * the offset of the specified string from within the given string table, 896 * adding it if possible. 897 * 898 * entry: 899 * dynsec - Dynamic section descriptor 900 * strsec - Descriptor for string table assocated with dynamic section 901 * dyn_strpad - DT_SUNW_STRPAD element from dynamic section 902 * str - String we are looking for. 903 * 904 * exit: 905 * On success, the offset of the given string within the string 906 * table is returned. If the string does not exist within the table, 907 * but there is a valid DT_SUNW_STRPAD reserved section, then we 908 * add the string, and update the dynamic section STRPAD element 909 * to reflect the space we use. 910 * 911 * This routine does not return on failure. 912 */ 913 Word 914 elfedit_dynstr_insert(elfedit_section_t *dynsec, elfedit_section_t *strsec, 915 elfedit_dyn_elt_t *dyn_strpad, const char *str) 916 { 917 Word ins_off; /* Table offset to 1st reserved byte */ 918 char *s; /* ptr to strings within table */ 919 Word len; /* Length of str inc. NULL byte */ 920 Word tail_ign; /* # reserved bytes at end of strtab */ 921 922 923 tail_ign = dyn_strpad->dn_seen ? dyn_strpad->dn_dyn.d_un.d_val : 0; 924 925 /* Does the string already existin the string table? */ 926 if (elfedit_sec_findstr(strsec, tail_ign, str, &len)) 927 return (len); 928 929 /* 930 * The desired string does not already exist. Do we have 931 * room to add it? 932 */ 933 len = strlen(str) + 1; 934 if (!dyn_strpad->dn_seen || (len > dyn_strpad->dn_dyn.d_un.d_val)) 935 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD), 936 EC_WORD(strsec->sec_shdr->sh_link), 937 strsec->sec_name); 938 939 940 /* 941 * We will add the string at the first byte of the reserved NULL 942 * area at the end. The DT_SUNW_STRPAD dynamic element gives us 943 * the size of that reserved space. 944 */ 945 ins_off = strsec->sec_shdr->sh_size - tail_ign; 946 s = ((char *)strsec->sec_data->d_buf) + ins_off; 947 948 /* Announce the operation */ 949 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_ADDSTR), 950 EC_WORD(strsec->sec_shndx), strsec->sec_name, 951 EC_WORD(ins_off), EC_WORD(len), 952 EC_WORD(dyn_strpad->dn_dyn.d_un.d_val), str); 953 954 /* 955 * Copy the string into the pad area at the end, and 956 * mark the data area as dirty so libelf will flush our 957 * changes to the string data. 958 */ 959 (void) strncpy(s, str, dyn_strpad->dn_dyn.d_un.d_val); 960 elfedit_modified_data(strsec); 961 962 /* Update the DT_STRPAD dynamic entry */ 963 dyn_strpad->dn_dyn.d_un.d_val -= len; 964 ((Dyn *) dynsec->sec_data->d_buf)[dyn_strpad->dn_ndx] = 965 dyn_strpad->dn_dyn; 966 elfedit_modified_data(dynsec); 967 968 return (ins_off); 969 } 970 971 972 /* 973 * Test to see if a call to elfedit_strtab_insert() will succeed. 974 * 975 * entry: 976 * obj_state - Object state for open object to query. 977 * strsec - Descriptor for string table 978 * dynsec - NULL, or descriptor for dynamic section. Providing 979 * a non-NULL value here will prevent elfedit_strtab_insert() 980 * from looking it up, and the duplicate debug message that 981 * would result. 982 * str - String we are looking for. 983 * 984 * exit: 985 * If the string exists within the string table, or if an attempt 986 * to insert it will be successful, quietly return. Otherwise, throw 987 * the error elfedit_strtab_insert() would throw under the 988 * same circumstances. 989 * 990 */ 991 void 992 elfedit_strtab_insert_test(elfedit_obj_state_t *obj_state, 993 elfedit_section_t *strsec, elfedit_section_t *dynsec, const char *str) 994 { 995 Word len; /* Length of str inc. NULL byte */ 996 int is_dynstr = 0; 997 Word tail_ign = 0; 998 999 1000 /* 1001 * The dynstr is a special case, because we can add strings 1002 * to it under certain circumstances. So, we look for the 1003 * dynamic section, and if it exists, compare its sh_link to 1004 * the string section index. If they match, it is the dynstr, 1005 * and we use elfedit_dynstr_insert() to do the work. 1006 */ 1007 if (dynsec == NULL) { 1008 if (obj_state->os_dynndx != SHN_UNDEF) { 1009 dynsec = &obj_state->os_secarr[obj_state->os_dynndx]; 1010 if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) && 1011 (strsec->sec_shndx == dynsec->sec_shdr->sh_link)) { 1012 is_dynstr = 1; 1013 elfedit_msg(ELFEDIT_MSG_DEBUG, 1014 MSG_INTL(MSG_DEBUG_FNDDYN), 1015 EC_WORD(dynsec->sec_shndx), 1016 dynsec->sec_name); 1017 } 1018 } 1019 } else { 1020 if (strsec->sec_shndx == dynsec->sec_shdr->sh_link) 1021 is_dynstr = 1; 1022 } 1023 1024 1025 if (is_dynstr) { 1026 elfedit_dyn_elt_t dyn_strpad; 1027 1028 /* Determine the size of the STRPAD area, if any */ 1029 elfedit_dyn_elt_init(&dyn_strpad); 1030 if (elfedit_dynstr_getpad(obj_state, dynsec, &dyn_strpad) != 0) 1031 tail_ign = dyn_strpad.dn_dyn.d_un.d_val; 1032 } 1033 1034 /* 1035 * If the string is already in the string table, we 1036 * can't fail. 1037 */ 1038 if (elfedit_sec_findstr(strsec, tail_ign, str, &len) != 0) 1039 return; 1040 1041 /* 1042 * It's not in the table, but if this is the dynstr, and 1043 * there is enough room, we will be able to add it. 1044 */ 1045 if (is_dynstr && (tail_ign > strlen(str))) 1046 return; 1047 1048 /* Can't do it. Issue error */ 1049 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD), 1050 EC_WORD(strsec->sec_shdr->sh_link), strsec->sec_name); 1051 } 1052 1053 1054 /* 1055 * Returns the offset of the specified string from within 1056 * the given string table, adding it if possible. 1057 * 1058 * entry: 1059 * obj_state - Object state for open object to query. 1060 * strsec - Descriptor for string table 1061 * dynsec - NULL, or descriptor for dynamic section. Providing 1062 * a non-NULL value here will prevent elfedit_strtab_insert() 1063 * from looking it up, and the duplicate debug message that 1064 * would result. 1065 * str - String we are looking for. 1066 * 1067 * exit: 1068 * On success, the offset of the given string within the string 1069 * table is returned. If the string does not exist within the table, 1070 * and it is possible to add it, elfedit_strtab_insert() will 1071 * add the string, and then return the offset. 1072 * 1073 * If the string does not exist in the string table, and cannot 1074 * be added, this routine issues an error message and does not 1075 * return to the caller. 1076 */ 1077 Word 1078 elfedit_strtab_insert(elfedit_obj_state_t *obj_state, elfedit_section_t *strsec, 1079 elfedit_section_t *dynsec, const char *str) 1080 { 1081 Word len; /* Length of str inc. NULL byte */ 1082 int is_dynstr = 0; 1083 elfedit_dyn_elt_t dyn_strpad; 1084 1085 1086 /* 1087 * The dynstr is a special case, because we can add strings 1088 * to it under certain circumstances. So, we look for the 1089 * dynamic section, and if it exists, compare its sh_link to 1090 * the string section index. If they match, it is the dynstr, 1091 * and we use elfedit_dynstr_insert() to do the work. 1092 */ 1093 if (dynsec == NULL) { 1094 if (obj_state->os_dynndx != SHN_UNDEF) { 1095 dynsec = &obj_state->os_secarr[obj_state->os_dynndx]; 1096 if ((dynsec->sec_shdr->sh_type == SHT_DYNAMIC) && 1097 (strsec->sec_shndx == dynsec->sec_shdr->sh_link)) { 1098 is_dynstr = 1; 1099 elfedit_msg(ELFEDIT_MSG_DEBUG, 1100 MSG_INTL(MSG_DEBUG_FNDDYN), 1101 EC_WORD(dynsec->sec_shndx), 1102 dynsec->sec_name); 1103 } 1104 } 1105 } else { 1106 if (strsec->sec_shndx == dynsec->sec_shdr->sh_link) 1107 is_dynstr = 1; 1108 } 1109 1110 if (is_dynstr) { 1111 elfedit_dyn_elt_init(&dyn_strpad); 1112 (void) elfedit_dynstr_getpad(obj_state, dynsec, &dyn_strpad); 1113 return (elfedit_dynstr_insert(dynsec, strsec, 1114 &dyn_strpad, str)); 1115 } 1116 1117 /* 1118 * This is not the dynstr, so we are limited to strings that 1119 * already exist within it. Try to find one. 1120 */ 1121 if (elfedit_sec_findstr(strsec, 0, str, &len)) 1122 return (len); 1123 1124 /* Can't do it. Issue error */ 1125 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRPAD), 1126 EC_WORD(strsec->sec_shdr->sh_link), strsec->sec_name); 1127 /*NOTREACHED*/ 1128 1129 return (0); 1130 } 1131 1132 1133 /* 1134 * Return the string found at the given offset within the specified 1135 * string table. 1136 * 1137 * entry: 1138 * strsec - Section descriptor for string table section 1139 * offset - Offset of desired string in string table 1140 * msg_type - ELFEDIT_MSG_ type code to use with message 1141 * issued if offset is out of range for the symbol table. 1142 * debug_msg - True if should issue debug message for string found. 1143 * 1144 * exit: 1145 * If the offset is within the section, the string pointer 1146 * is returned. Otherwise an error is issued using msg_type 1147 * to determine the type of message. If this routine retains 1148 * control after the message is issued, a safe string is returned. 1149 */ 1150 const char * 1151 elfedit_offset_to_str(elfedit_section_t *strsec, Word offset, 1152 elfedit_msg_t msg_type, int debug_msg) 1153 { 1154 const char *str; 1155 1156 /* Make sure it is a string table section */ 1157 if (strsec->sec_shdr->sh_type != SHT_STRTAB) 1158 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOTSTRSH), 1159 EC_WORD(strsec->sec_shndx), strsec->sec_name); 1160 1161 /* Ensure the offset is in range */ 1162 if (offset >= strsec->sec_data->d_size) { 1163 elfedit_msg(msg_type, MSG_INTL(MSG_ERR_BADSTROFF), 1164 EC_WORD(strsec->sec_shndx), strsec->sec_name, 1165 EC_WORD(offset), EC_WORD(strsec->sec_data->d_size - 1)); 1166 /* 1167 * If the msg_type is a type that returns, give the 1168 * user a safe string to use. 1169 */ 1170 str = MSG_INTL(MSG_BADSYMOFFSETNAM); 1171 } else { 1172 /* Return the string */ 1173 str = ((const char *)strsec->sec_data->d_buf) + offset; 1174 } 1175 1176 if (debug_msg) 1177 elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_FNDSTR), 1178 EC_WORD(strsec->sec_shndx), strsec->sec_name, 1179 EC_WORD(offset), str); 1180 return (str); 1181 } 1182 1183 1184 /* 1185 * Given a string table section, and a dynamic section entry 1186 * that supplies a string offset, return the string found at 1187 * the given offset. This routine is a convenience wrapper on 1188 * elfedit_offset_to_str(). 1189 * 1190 * exit: 1191 * As per elfedit_offset_to_str(). 1192 */ 1193 const char * 1194 elfedit_dyn_offset_to_str(elfedit_section_t *strsec, elfedit_dyn_elt_t *dynelt) 1195 { 1196 return (elfedit_offset_to_str(strsec, dynelt->dn_dyn.d_un.d_val, 1197 ELFEDIT_MSG_ERR, 0)); 1198 } 1199 1200 1201 /* 1202 * Given a section, fabricate a string for the form: 1203 * 1204 * "[#: name]" 1205 * 1206 * as used at the beginning of debug messages. A pointer to static 1207 * memory is returned, and is good until the next such call. 1208 */ 1209 const char * 1210 elfedit_sec_msgprefix(elfedit_section_t *sec) 1211 { 1212 static char *buf; 1213 static size_t bufsize; 1214 1215 size_t need; 1216 1217 need = 64 + strlen(sec->sec_name); 1218 if (need > bufsize) { 1219 buf = elfedit_realloc(MSG_INTL(MSG_ALLOC_SECMSGPRE), buf, need); 1220 bufsize = need; 1221 } 1222 1223 (void) snprintf(buf, bufsize, MSG_ORIG(MSG_FMT_SECMSGPRE), 1224 EC_WORD(sec->sec_shndx), sec->sec_name); 1225 1226 return (buf); 1227 } 1228