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