1 /*- 2 * Copyright (c) 2007-2013 Kai Wang 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/param.h> 28 #include <err.h> 29 #include <fnmatch.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 34 #include "elfcopy.h" 35 36 ELFTC_VCSID("$Id: symbols.c 3222 2015-05-24 23:47:23Z kaiwang27 $"); 37 38 /* Symbol table buffer structure. */ 39 struct symbuf { 40 Elf32_Sym *l32; /* 32bit local symbol */ 41 Elf32_Sym *g32; /* 32bit global symbol */ 42 Elf64_Sym *l64; /* 64bit local symbol */ 43 Elf64_Sym *g64; /* 64bit global symbol */ 44 size_t ngs, nls; /* number of each kind */ 45 size_t gcap, lcap; /* buffer capacities. */ 46 }; 47 48 struct sthash { 49 LIST_ENTRY(sthash) sh_next; 50 size_t sh_off; 51 }; 52 typedef LIST_HEAD(,sthash) hash_head; 53 #define STHASHSIZE 65536 54 55 struct strimpl { 56 char *buf; /* string table */ 57 size_t sz; /* entries */ 58 size_t cap; /* buffer capacity */ 59 hash_head hash[STHASHSIZE]; 60 }; 61 62 63 /* String table buffer structure. */ 64 struct strbuf { 65 struct strimpl l; /* local symbols */ 66 struct strimpl g; /* global symbols */ 67 }; 68 69 static int is_debug_symbol(unsigned char st_info); 70 static int is_global_symbol(unsigned char st_info); 71 static int is_local_symbol(unsigned char st_info); 72 static int is_local_label(const char *name); 73 static int is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s); 74 static int is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, 75 GElf_Sym *s, const char *name); 76 static int is_weak_symbol(unsigned char st_info); 77 static int lookup_exact_string(hash_head *hash, const char *buf, 78 const char *s); 79 static int generate_symbols(struct elfcopy *ecp); 80 static void mark_reloc_symbols(struct elfcopy *ecp, size_t sc); 81 static void mark_section_group_symbols(struct elfcopy *ecp, size_t sc); 82 static int match_wildcard(const char *name, const char *pattern); 83 uint32_t str_hash(const char *s); 84 85 /* Convenient bit vector operation macros. */ 86 #define BIT_SET(v, n) (v[(n)>>3] |= 1U << ((n) & 7)) 87 #define BIT_CLR(v, n) (v[(n)>>3] &= ~(1U << ((n) & 7))) 88 #define BIT_ISSET(v, n) (v[(n)>>3] & (1U << ((n) & 7))) 89 90 static int 91 is_debug_symbol(unsigned char st_info) 92 { 93 94 if (GELF_ST_TYPE(st_info) == STT_SECTION || 95 GELF_ST_TYPE(st_info) == STT_FILE) 96 return (1); 97 98 return (0); 99 } 100 101 static int 102 is_global_symbol(unsigned char st_info) 103 { 104 105 if (GELF_ST_BIND(st_info) == STB_GLOBAL) 106 return (1); 107 108 return (0); 109 } 110 111 static int 112 is_weak_symbol(unsigned char st_info) 113 { 114 115 if (GELF_ST_BIND(st_info) == STB_WEAK) 116 return (1); 117 118 return (0); 119 } 120 121 static int 122 is_local_symbol(unsigned char st_info) 123 { 124 125 if (GELF_ST_BIND(st_info) == STB_LOCAL) 126 return (1); 127 128 return (0); 129 } 130 131 static int 132 is_hidden_symbol(unsigned char st_other) 133 { 134 135 if (GELF_ST_VISIBILITY(st_other) == STV_HIDDEN || 136 GELF_ST_VISIBILITY(st_other) == STV_INTERNAL) 137 return (1); 138 139 return (0); 140 } 141 142 static int 143 is_local_label(const char *name) 144 { 145 146 /* Compiler generated local symbols that start with .L */ 147 if (name[0] == '.' && name[1] == 'L') 148 return (1); 149 150 return (0); 151 } 152 153 /* 154 * Symbols related to relocation are needed. 155 */ 156 static int 157 is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s) 158 { 159 160 /* If symbol involves relocation, it is needed. */ 161 if (BIT_ISSET(ecp->v_rel, i)) 162 return (1); 163 164 /* Symbols refered by COMDAT sections are needed. */ 165 if (BIT_ISSET(ecp->v_grp, i)) 166 return (1); 167 168 /* 169 * For relocatable files (.o files), global and weak symbols 170 * are needed. 171 */ 172 if (ecp->flags & RELOCATABLE) { 173 if (is_global_symbol(s->st_info) || is_weak_symbol(s->st_info)) 174 return (1); 175 } 176 177 return (0); 178 } 179 180 static int 181 is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s, 182 const char *name) 183 { 184 GElf_Sym sym0 = { 185 0, /* st_name */ 186 0, /* st_value */ 187 0, /* st_size */ 188 0, /* st_info */ 189 0, /* st_other */ 190 SHN_UNDEF, /* st_shndx */ 191 }; 192 193 if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) 194 return (0); 195 196 if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL) 197 return (1); 198 199 /* 200 * Keep the first symbol if it is the special reserved symbol. 201 * XXX Should we generate one if it's missing? 202 */ 203 if (i == 0 && !memcmp(s, &sym0, sizeof(GElf_Sym))) 204 return (0); 205 206 /* Remove the symbol if the section it refers to was removed. */ 207 if (s->st_shndx != SHN_UNDEF && s->st_shndx < SHN_LORESERVE && 208 ecp->secndx[s->st_shndx] == 0) 209 return (1); 210 211 if (ecp->strip == STRIP_ALL) 212 return (1); 213 214 if (ecp->v_rel == NULL) 215 mark_reloc_symbols(ecp, sc); 216 217 if (ecp->v_grp == NULL) 218 mark_section_group_symbols(ecp, sc); 219 220 if (is_needed_symbol(ecp, i, s)) 221 return (0); 222 223 if (ecp->strip == STRIP_UNNEEDED) 224 return (1); 225 226 if ((ecp->flags & DISCARD_LOCAL) && is_local_symbol(s->st_info) && 227 !is_debug_symbol(s->st_info)) 228 return (1); 229 230 if ((ecp->flags & DISCARD_LLABEL) && is_local_symbol(s->st_info) && 231 !is_debug_symbol(s->st_info) && is_local_label(name)) 232 return (1); 233 234 if (ecp->strip == STRIP_DEBUG && is_debug_symbol(s->st_info)) 235 return (1); 236 237 return (0); 238 } 239 240 /* 241 * Mark symbols refered by relocation entries. 242 */ 243 static void 244 mark_reloc_symbols(struct elfcopy *ecp, size_t sc) 245 { 246 const char *name; 247 Elf_Data *d; 248 Elf_Scn *s; 249 GElf_Rel r; 250 GElf_Rela ra; 251 GElf_Shdr sh; 252 size_t n, indx; 253 int elferr, i, len; 254 255 ecp->v_rel = calloc((sc + 7) / 8, 1); 256 if (ecp->v_rel == NULL) 257 err(EXIT_FAILURE, "calloc failed"); 258 259 if (elf_getshstrndx(ecp->ein, &indx) == 0) 260 errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 261 elf_errmsg(-1)); 262 263 s = NULL; 264 while ((s = elf_nextscn(ecp->ein, s)) != NULL) { 265 if (gelf_getshdr(s, &sh) != &sh) 266 errx(EXIT_FAILURE, "elf_getshdr failed: %s", 267 elf_errmsg(-1)); 268 269 if (sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA) 270 continue; 271 272 /* 273 * Skip if this reloc section won't appear in the 274 * output object. 275 */ 276 if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL) 277 errx(EXIT_FAILURE, "elf_strptr failed: %s", 278 elf_errmsg(-1)); 279 if (is_remove_section(ecp, name) || 280 is_remove_reloc_sec(ecp, sh.sh_info)) 281 continue; 282 283 /* Skip if it's not for .symtab */ 284 if (sh.sh_link != elf_ndxscn(ecp->symtab->is)) 285 continue; 286 287 d = NULL; 288 n = 0; 289 while (n < sh.sh_size && (d = elf_getdata(s, d)) != NULL) { 290 len = d->d_size / sh.sh_entsize; 291 for (i = 0; i < len; i++) { 292 if (sh.sh_type == SHT_REL) { 293 if (gelf_getrel(d, i, &r) != &r) 294 errx(EXIT_FAILURE, 295 "elf_getrel failed: %s", 296 elf_errmsg(-1)); 297 n = GELF_R_SYM(r.r_info); 298 } else { 299 if (gelf_getrela(d, i, &ra) != &ra) 300 errx(EXIT_FAILURE, 301 "elf_getrela failed: %s", 302 elf_errmsg(-1)); 303 n = GELF_R_SYM(ra.r_info); 304 } 305 if (n > 0 && n < sc) 306 BIT_SET(ecp->v_rel, n); 307 else if (n != 0) 308 warnx("invalid symbox index"); 309 } 310 } 311 elferr = elf_errno(); 312 if (elferr != 0) 313 errx(EXIT_FAILURE, "elf_getdata failed: %s", 314 elf_errmsg(elferr)); 315 } 316 elferr = elf_errno(); 317 if (elferr != 0) 318 errx(EXIT_FAILURE, "elf_nextscn failed: %s", 319 elf_errmsg(elferr)); 320 } 321 322 static void 323 mark_section_group_symbols(struct elfcopy *ecp, size_t sc) 324 { 325 const char *name; 326 Elf_Scn *s; 327 GElf_Shdr sh; 328 size_t indx; 329 int elferr; 330 331 ecp->v_grp = calloc((sc + 7) / 8, 1); 332 if (ecp->v_grp == NULL) 333 err(EXIT_FAILURE, "calloc failed"); 334 335 if (elf_getshstrndx(ecp->ein, &indx) == 0) 336 errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 337 elf_errmsg(-1)); 338 339 s = NULL; 340 while ((s = elf_nextscn(ecp->ein, s)) != NULL) { 341 if (gelf_getshdr(s, &sh) != &sh) 342 errx(EXIT_FAILURE, "elf_getshdr failed: %s", 343 elf_errmsg(-1)); 344 345 if (sh.sh_type != SHT_GROUP) 346 continue; 347 348 if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL) 349 errx(EXIT_FAILURE, "elf_strptr failed: %s", 350 elf_errmsg(-1)); 351 if (is_remove_section(ecp, name)) 352 continue; 353 354 if (sh.sh_info > 0 && sh.sh_info < sc) 355 BIT_SET(ecp->v_grp, sh.sh_info); 356 else if (sh.sh_info != 0) 357 warnx("invalid symbox index"); 358 } 359 elferr = elf_errno(); 360 if (elferr != 0) 361 errx(EXIT_FAILURE, "elf_nextscn failed: %s", 362 elf_errmsg(elferr)); 363 } 364 365 static int 366 generate_symbols(struct elfcopy *ecp) 367 { 368 struct section *s; 369 struct symop *sp; 370 struct symbuf *sy_buf; 371 struct strbuf *st_buf; 372 const char *name; 373 char *newname; 374 unsigned char *gsym; 375 GElf_Shdr ish; 376 GElf_Sym sym; 377 Elf_Data* id; 378 Elf_Scn *is; 379 size_t ishstrndx, namelen, ndx, sc, symndx; 380 int ec, elferr, i; 381 382 if (elf_getshstrndx(ecp->ein, &ishstrndx) == 0) 383 errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 384 elf_errmsg(-1)); 385 if ((ec = gelf_getclass(ecp->eout)) == ELFCLASSNONE) 386 errx(EXIT_FAILURE, "gelf_getclass failed: %s", 387 elf_errmsg(-1)); 388 389 /* Create buffers for .symtab and .strtab. */ 390 if ((sy_buf = calloc(1, sizeof(*sy_buf))) == NULL) 391 err(EXIT_FAILURE, "calloc failed"); 392 if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL) 393 err(EXIT_FAILURE, "calloc failed"); 394 sy_buf->gcap = sy_buf->lcap = 64; 395 st_buf->g.cap = 256; 396 st_buf->l.cap = 64; 397 st_buf->l.sz = 1; /* '\0' at start. */ 398 st_buf->g.sz = 0; 399 400 ecp->symtab->sz = 0; 401 ecp->strtab->sz = 0; 402 ecp->symtab->buf = sy_buf; 403 ecp->strtab->buf = st_buf; 404 405 gsym = NULL; 406 407 /* 408 * Create bit vector v_secsym, which is used to mark sections 409 * that already have corresponding STT_SECTION symbols. 410 */ 411 ecp->v_secsym = calloc((ecp->nos + 7) / 8, 1); 412 if (ecp->v_secsym == NULL) 413 err(EXIT_FAILURE, "calloc failed"); 414 415 /* Locate .strtab of input object. */ 416 symndx = 0; 417 name = NULL; 418 is = NULL; 419 while ((is = elf_nextscn(ecp->ein, is)) != NULL) { 420 if (gelf_getshdr(is, &ish) != &ish) 421 errx(EXIT_FAILURE, "elf_getshdr failed: %s", 422 elf_errmsg(-1)); 423 if ((name = elf_strptr(ecp->ein, ishstrndx, ish.sh_name)) == 424 NULL) 425 errx(EXIT_FAILURE, "elf_strptr failed: %s", 426 elf_errmsg(-1)); 427 if (strcmp(name, ".strtab") == 0) { 428 symndx = elf_ndxscn(is); 429 break; 430 } 431 } 432 elferr = elf_errno(); 433 if (elferr != 0) 434 errx(EXIT_FAILURE, "elf_nextscn failed: %s", 435 elf_errmsg(elferr)); 436 437 /* Symbol table should exist if this function is called. */ 438 if (symndx == 0) { 439 warnx("can't find .strtab section"); 440 goto clean; 441 } 442 443 /* Locate .symtab of input object. */ 444 is = NULL; 445 while ((is = elf_nextscn(ecp->ein, is)) != NULL) { 446 if (gelf_getshdr(is, &ish) != &ish) 447 errx(EXIT_FAILURE, "elf_getshdr failed: %s", 448 elf_errmsg(-1)); 449 if ((name = elf_strptr(ecp->ein, ishstrndx, ish.sh_name)) == 450 NULL) 451 errx(EXIT_FAILURE, "elf_strptr failed: %s", 452 elf_errmsg(-1)); 453 if (strcmp(name, ".symtab") == 0) 454 break; 455 } 456 elferr = elf_errno(); 457 if (elferr != 0) 458 errx(EXIT_FAILURE, "elf_nextscn failed: %s", 459 elf_errmsg(elferr)); 460 if (is == NULL) 461 errx(EXIT_FAILURE, "can't find .strtab section"); 462 463 /* 464 * Create bit vector gsym to mark global symbols, and symndx 465 * to keep track of symbol index changes from input object to 466 * output object, it is used by update_reloc() later to update 467 * relocation information. 468 */ 469 sc = ish.sh_size / ish.sh_entsize; 470 if (sc > 0) { 471 ecp->symndx = calloc(sc, sizeof(*ecp->symndx)); 472 if (ecp->symndx == NULL) 473 err(EXIT_FAILURE, "calloc failed"); 474 gsym = calloc((sc + 7) / 8, sizeof(*gsym)); 475 if (gsym == NULL) 476 err(EXIT_FAILURE, "calloc failed"); 477 if ((id = elf_getdata(is, NULL)) == NULL) { 478 elferr = elf_errno(); 479 if (elferr != 0) 480 errx(EXIT_FAILURE, "elf_getdata failed: %s", 481 elf_errmsg(elferr)); 482 goto clean; 483 } 484 } else 485 return (0); 486 487 /* Copy/Filter each symbol. */ 488 for (i = 0; (size_t)i < sc; i++) { 489 if (gelf_getsym(id, i, &sym) != &sym) 490 errx(EXIT_FAILURE, "gelf_getsym failed: %s", 491 elf_errmsg(-1)); 492 if ((name = elf_strptr(ecp->ein, symndx, sym.st_name)) == NULL) 493 errx(EXIT_FAILURE, "elf_strptr failed: %s", 494 elf_errmsg(-1)); 495 496 /* Symbol filtering. */ 497 if (is_remove_symbol(ecp, sc, i, &sym, name) != 0) 498 continue; 499 500 /* Check if we need to change the binding of this symbol. */ 501 if (is_global_symbol(sym.st_info) || 502 is_weak_symbol(sym.st_info)) { 503 /* 504 * XXX Binutils objcopy does not weaken certain 505 * symbols. 506 */ 507 if (ecp->flags & WEAKEN_ALL || 508 lookup_symop_list(ecp, name, SYMOP_WEAKEN) != NULL) 509 sym.st_info = GELF_ST_INFO(STB_WEAK, 510 GELF_ST_TYPE(sym.st_info)); 511 /* Do not localize undefined symbols. */ 512 if (sym.st_shndx != SHN_UNDEF && 513 lookup_symop_list(ecp, name, SYMOP_LOCALIZE) != 514 NULL) 515 sym.st_info = GELF_ST_INFO(STB_LOCAL, 516 GELF_ST_TYPE(sym.st_info)); 517 if (ecp->flags & KEEP_GLOBAL && 518 sym.st_shndx != SHN_UNDEF && 519 lookup_symop_list(ecp, name, SYMOP_KEEPG) == NULL) 520 sym.st_info = GELF_ST_INFO(STB_LOCAL, 521 GELF_ST_TYPE(sym.st_info)); 522 if (ecp->flags & LOCALIZE_HIDDEN && 523 sym.st_shndx != SHN_UNDEF && 524 is_hidden_symbol(sym.st_other)) 525 sym.st_info = GELF_ST_INFO(STB_LOCAL, 526 GELF_ST_TYPE(sym.st_info)); 527 } else { 528 /* STB_LOCAL binding. */ 529 if (lookup_symop_list(ecp, name, SYMOP_GLOBALIZE) != 530 NULL) 531 sym.st_info = GELF_ST_INFO(STB_GLOBAL, 532 GELF_ST_TYPE(sym.st_info)); 533 /* XXX We should globalize weak symbol? */ 534 } 535 536 /* Check if we need to rename this symbol. */ 537 if ((sp = lookup_symop_list(ecp, name, SYMOP_REDEF)) != NULL) 538 name = sp->newname; 539 540 /* Check if we need to prefix the symbols. */ 541 newname = NULL; 542 if (ecp->prefix_sym != NULL && name != NULL && *name != '\0') { 543 namelen = strlen(name) + strlen(ecp->prefix_sym) + 1; 544 if ((newname = malloc(namelen)) == NULL) 545 err(EXIT_FAILURE, "malloc failed"); 546 snprintf(newname, namelen, "%s%s", ecp->prefix_sym, 547 name); 548 name = newname; 549 } 550 551 /* Copy symbol, mark global/weak symbol and add to index map. */ 552 if (is_global_symbol(sym.st_info) || 553 is_weak_symbol(sym.st_info)) { 554 BIT_SET(gsym, i); 555 ecp->symndx[i] = sy_buf->ngs; 556 } else 557 ecp->symndx[i] = sy_buf->nls; 558 add_to_symtab(ecp, name, sym.st_value, sym.st_size, 559 sym.st_shndx, sym.st_info, sym.st_other, 0); 560 561 if (newname != NULL) 562 free(newname); 563 564 /* 565 * If the symbol is a STT_SECTION symbol, mark the section 566 * it points to. 567 */ 568 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) 569 BIT_SET(ecp->v_secsym, ecp->secndx[sym.st_shndx]); 570 } 571 572 /* 573 * Give up if there is no real symbols inside the table. 574 * XXX The logic here needs to be improved. We need to 575 * check if that only local symbol is the reserved symbol. 576 */ 577 if (sy_buf->nls <= 1 && sy_buf->ngs == 0) 578 goto clean; 579 580 /* 581 * Create STT_SECTION symbols for sections that do not already 582 * got one. However, we do not create STT_SECTION symbol for 583 * .symtab, .strtab, .shstrtab and reloc sec of relocatables. 584 */ 585 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 586 if (s->pseudo) 587 continue; 588 if (strcmp(s->name, ".symtab") == 0 || 589 strcmp(s->name, ".strtab") == 0 || 590 strcmp(s->name, ".shstrtab") == 0) 591 continue; 592 if ((ecp->flags & RELOCATABLE) != 0 && 593 ((s->type == SHT_REL) || (s->type == SHT_RELA))) 594 continue; 595 596 if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) 597 errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 598 elf_errmsg(-1)); 599 600 if (!BIT_ISSET(ecp->v_secsym, ndx)) { 601 sym.st_name = 0; 602 sym.st_value = s->vma; 603 sym.st_size = 0; 604 sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION); 605 sym.st_other = STV_DEFAULT; 606 /* 607 * Don't let add_to_symtab() touch sym.st_shndx. 608 * In this case, we know the index already. 609 */ 610 add_to_symtab(ecp, NULL, sym.st_value, sym.st_size, 611 ndx, sym.st_info, sym.st_other, 1); 612 } 613 } 614 615 /* 616 * Update st_name and index map for global/weak symbols. Note that 617 * global/weak symbols are put after local symbols. 618 */ 619 if (gsym != NULL) { 620 for(i = 0; (size_t) i < sc; i++) { 621 if (!BIT_ISSET(gsym, i)) 622 continue; 623 624 /* Update st_name. */ 625 if (ec == ELFCLASS32) 626 sy_buf->g32[ecp->symndx[i]].st_name += 627 st_buf->l.sz; 628 else 629 sy_buf->g64[ecp->symndx[i]].st_name += 630 st_buf->l.sz; 631 632 /* Update index map. */ 633 ecp->symndx[i] += sy_buf->nls; 634 } 635 free(gsym); 636 } 637 638 return (1); 639 640 clean: 641 free(gsym); 642 free_symtab(ecp); 643 644 return (0); 645 } 646 647 void 648 create_symtab(struct elfcopy *ecp) 649 { 650 struct section *s, *sy, *st; 651 size_t maxndx, ndx; 652 653 sy = ecp->symtab; 654 st = ecp->strtab; 655 656 /* 657 * Set section index map for .symtab and .strtab. We need to set 658 * these map because otherwise symbols which refer to .symtab and 659 * .strtab will be removed by symbol filtering unconditionally. 660 * And we have to figure out scn index this way (instead of calling 661 * elf_ndxscn) because we can not create Elf_Scn before we're certain 662 * that .symtab and .strtab will exist in the output object. 663 */ 664 maxndx = 0; 665 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 666 if (s->os == NULL) 667 continue; 668 if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) 669 errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 670 elf_errmsg(-1)); 671 if (ndx > maxndx) 672 maxndx = ndx; 673 } 674 ecp->secndx[elf_ndxscn(sy->is)] = maxndx + 1; 675 ecp->secndx[elf_ndxscn(st->is)] = maxndx + 2; 676 677 /* 678 * Generate symbols for output object if SYMTAB_INTACT is not set. 679 * If there is no symbol in the input object or all the symbols are 680 * stripped, then free all the resouces allotted for symbol table, 681 * and clear SYMTAB_EXIST flag. 682 */ 683 if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) { 684 TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list); 685 TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list); 686 free(ecp->symtab->buf); 687 free(ecp->symtab); 688 free(ecp->strtab->buf); 689 free(ecp->strtab); 690 ecp->symtab = NULL; 691 ecp->strtab = NULL; 692 ecp->flags &= ~SYMTAB_EXIST; 693 return; 694 } 695 696 /* Create output Elf_Scn for .symtab and .strtab. */ 697 if ((sy->os = elf_newscn(ecp->eout)) == NULL || 698 (st->os = elf_newscn(ecp->eout)) == NULL) 699 errx(EXIT_FAILURE, "elf_newscn failed: %s", 700 elf_errmsg(-1)); 701 /* Update secndx anyway. */ 702 ecp->secndx[elf_ndxscn(sy->is)] = elf_ndxscn(sy->os); 703 ecp->secndx[elf_ndxscn(st->is)] = elf_ndxscn(st->os); 704 705 /* 706 * Copy .symtab and .strtab section headers from input to output 707 * object to start with, these will be overridden later if need. 708 */ 709 copy_shdr(ecp, sy, ".symtab", 1, 0); 710 copy_shdr(ecp, st, ".strtab", 1, 0); 711 712 /* Copy verbatim if symbol table is intact. */ 713 if (ecp->flags & SYMTAB_INTACT) { 714 copy_data(sy); 715 copy_data(st); 716 return; 717 } 718 719 create_symtab_data(ecp); 720 } 721 722 void 723 free_symtab(struct elfcopy *ecp) 724 { 725 struct symbuf *sy_buf; 726 struct strbuf *st_buf; 727 struct sthash *sh, *shtmp; 728 int i; 729 730 if (ecp->symtab != NULL && ecp->symtab->buf != NULL) { 731 sy_buf = ecp->symtab->buf; 732 if (sy_buf->l32 != NULL) 733 free(sy_buf->l32); 734 if (sy_buf->g32 != NULL) 735 free(sy_buf->g32); 736 if (sy_buf->l64 != NULL) 737 free(sy_buf->l64); 738 if (sy_buf->g64 != NULL) 739 free(sy_buf->g64); 740 } 741 742 if (ecp->strtab != NULL && ecp->strtab->buf != NULL) { 743 st_buf = ecp->strtab->buf; 744 if (st_buf->l.buf != NULL) 745 free(st_buf->l.buf); 746 if (st_buf->g.buf != NULL) 747 free(st_buf->g.buf); 748 for (i = 0; i < STHASHSIZE; i++) { 749 LIST_FOREACH_SAFE(sh, &st_buf->l.hash[i], sh_next, 750 shtmp) { 751 LIST_REMOVE(sh, sh_next); 752 free(sh); 753 } 754 LIST_FOREACH_SAFE(sh, &st_buf->g.hash[i], sh_next, 755 shtmp) { 756 LIST_REMOVE(sh, sh_next); 757 free(sh); 758 } 759 } 760 } 761 762 if (ecp->symndx != NULL) { 763 free(ecp->symndx); 764 ecp->symndx = NULL; 765 } 766 if (ecp->v_rel != NULL) { 767 free(ecp->v_rel); 768 ecp->v_rel = NULL; 769 } 770 if (ecp->v_grp != NULL) { 771 free(ecp->v_grp); 772 ecp->v_grp = NULL; 773 } 774 if (ecp->v_secsym != NULL) { 775 free(ecp->v_secsym); 776 ecp->v_secsym = NULL; 777 } 778 } 779 780 void 781 create_external_symtab(struct elfcopy *ecp) 782 { 783 struct section *s; 784 struct symbuf *sy_buf; 785 struct strbuf *st_buf; 786 GElf_Shdr sh; 787 size_t ndx; 788 789 if (ecp->oec == ELFCLASS32) 790 ecp->symtab = create_external_section(ecp, ".symtab", NULL, 791 NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 4, 0, 0); 792 else 793 ecp->symtab = create_external_section(ecp, ".symtab", NULL, 794 NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 8, 0, 0); 795 796 ecp->strtab = create_external_section(ecp, ".strtab", NULL, NULL, 0, 0, 797 SHT_STRTAB, ELF_T_BYTE, 0, 1, 0, 0); 798 799 /* Let sh_link field of .symtab section point to .strtab section. */ 800 if (gelf_getshdr(ecp->symtab->os, &sh) == NULL) 801 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 802 elf_errmsg(-1)); 803 sh.sh_link = elf_ndxscn(ecp->strtab->os); 804 if (!gelf_update_shdr(ecp->symtab->os, &sh)) 805 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 806 elf_errmsg(-1)); 807 808 /* Create buffers for .symtab and .strtab. */ 809 if ((sy_buf = calloc(1, sizeof(*sy_buf))) == NULL) 810 err(EXIT_FAILURE, "calloc failed"); 811 if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL) 812 err(EXIT_FAILURE, "calloc failed"); 813 sy_buf->gcap = sy_buf->lcap = 64; 814 st_buf->g.cap = 256; 815 st_buf->l.cap = 64; 816 st_buf->l.sz = 1; /* '\0' at start. */ 817 st_buf->g.sz = 0; 818 819 ecp->symtab->sz = 0; 820 ecp->strtab->sz = 0; 821 ecp->symtab->buf = sy_buf; 822 ecp->strtab->buf = st_buf; 823 824 /* Always create the special symbol at the symtab beginning. */ 825 add_to_symtab(ecp, NULL, 0, 0, SHN_UNDEF, 826 ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE), 0, 1); 827 828 /* Create STT_SECTION symbols. */ 829 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 830 if (s->pseudo) 831 continue; 832 if (strcmp(s->name, ".symtab") == 0 || 833 strcmp(s->name, ".strtab") == 0 || 834 strcmp(s->name, ".shstrtab") == 0) 835 continue; 836 (void) elf_errno(); 837 if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) { 838 warnx("elf_ndxscn failed: %s", 839 elf_errmsg(-1)); 840 continue; 841 } 842 add_to_symtab(ecp, NULL, 0, 0, ndx, 843 GELF_ST_INFO(STB_LOCAL, STT_SECTION), 0, 1); 844 } 845 } 846 847 void 848 add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value, 849 uint64_t st_size, uint16_t st_shndx, unsigned char st_info, 850 unsigned char st_other, int ndx_known) 851 { 852 struct symbuf *sy_buf; 853 struct strbuf *st_buf; 854 struct sthash *sh; 855 uint32_t hash; 856 int pos; 857 858 /* 859 * Convenient macro for copying global/local 32/64 bit symbols 860 * from input object to the buffer created for output object. 861 * It handles buffer growing, st_name calculating and st_shndx 862 * updating for symbols with non-special section index. 863 */ 864 #define _ADDSYM(B, SZ) do { \ 865 if (sy_buf->B##SZ == NULL) { \ 866 sy_buf->B##SZ = malloc(sy_buf->B##cap * \ 867 sizeof(Elf##SZ##_Sym)); \ 868 if (sy_buf->B##SZ == NULL) \ 869 err(EXIT_FAILURE, "malloc failed"); \ 870 } else if (sy_buf->n##B##s >= sy_buf->B##cap) { \ 871 sy_buf->B##cap *= 2; \ 872 sy_buf->B##SZ = realloc(sy_buf->B##SZ, sy_buf->B##cap * \ 873 sizeof(Elf##SZ##_Sym)); \ 874 if (sy_buf->B##SZ == NULL) \ 875 err(EXIT_FAILURE, "realloc failed"); \ 876 } \ 877 sy_buf->B##SZ[sy_buf->n##B##s].st_info = st_info; \ 878 sy_buf->B##SZ[sy_buf->n##B##s].st_other = st_other; \ 879 sy_buf->B##SZ[sy_buf->n##B##s].st_value = st_value; \ 880 sy_buf->B##SZ[sy_buf->n##B##s].st_size = st_size; \ 881 if (ndx_known) \ 882 sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx; \ 883 else if (st_shndx == SHN_UNDEF || st_shndx >= SHN_LORESERVE) \ 884 sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx; \ 885 else \ 886 sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = \ 887 ecp->secndx[st_shndx]; \ 888 if (st_buf->B.buf == NULL) { \ 889 st_buf->B.buf = calloc(st_buf->B.cap, \ 890 sizeof(*st_buf->B.buf)); \ 891 if (st_buf->B.buf == NULL) \ 892 err(EXIT_FAILURE, "malloc failed"); \ 893 } \ 894 if (name != NULL && *name != '\0') { \ 895 pos = lookup_exact_string(st_buf->B.hash, st_buf->B.buf,\ 896 name); \ 897 if (pos != -1) \ 898 sy_buf->B##SZ[sy_buf->n##B##s].st_name = pos; \ 899 else { \ 900 sy_buf->B##SZ[sy_buf->n##B##s].st_name = \ 901 st_buf->B.sz; \ 902 while (st_buf->B.sz + strlen(name) >= \ 903 st_buf->B.cap - 1) { \ 904 st_buf->B.cap *= 2; \ 905 st_buf->B.buf = realloc(st_buf->B.buf, \ 906 st_buf->B.cap); \ 907 if (st_buf->B.buf == NULL) \ 908 err(EXIT_FAILURE, \ 909 "realloc failed"); \ 910 } \ 911 if ((sh = malloc(sizeof(*sh))) == NULL) \ 912 err(EXIT_FAILURE, "malloc failed"); \ 913 sh->sh_off = st_buf->B.sz; \ 914 hash = str_hash(name); \ 915 LIST_INSERT_HEAD(&st_buf->B.hash[hash], sh, \ 916 sh_next); \ 917 strncpy(&st_buf->B.buf[st_buf->B.sz], name, \ 918 strlen(name)); \ 919 st_buf->B.buf[st_buf->B.sz + strlen(name)] = '\0'; \ 920 st_buf->B.sz += strlen(name) + 1; \ 921 } \ 922 } else \ 923 sy_buf->B##SZ[sy_buf->n##B##s].st_name = 0; \ 924 sy_buf->n##B##s++; \ 925 } while (0) 926 927 sy_buf = ecp->symtab->buf; 928 st_buf = ecp->strtab->buf; 929 930 if (ecp->oec == ELFCLASS32) { 931 if (is_local_symbol(st_info)) 932 _ADDSYM(l, 32); 933 else 934 _ADDSYM(g, 32); 935 } else { 936 if (is_local_symbol(st_info)) 937 _ADDSYM(l, 64); 938 else 939 _ADDSYM(g, 64); 940 } 941 942 /* Update section size. */ 943 ecp->symtab->sz = (sy_buf->nls + sy_buf->ngs) * 944 (ecp->oec == ELFCLASS32 ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym)); 945 ecp->strtab->sz = st_buf->l.sz + st_buf->g.sz; 946 947 #undef _ADDSYM 948 } 949 950 void 951 finalize_external_symtab(struct elfcopy *ecp) 952 { 953 struct symbuf *sy_buf; 954 struct strbuf *st_buf; 955 int i; 956 957 /* 958 * Update st_name for global/weak symbols. (global/weak symbols 959 * are put after local symbols) 960 */ 961 sy_buf = ecp->symtab->buf; 962 st_buf = ecp->strtab->buf; 963 for (i = 0; (size_t) i < sy_buf->ngs; i++) { 964 if (ecp->oec == ELFCLASS32) 965 sy_buf->g32[i].st_name += st_buf->l.sz; 966 else 967 sy_buf->g64[i].st_name += st_buf->l.sz; 968 } 969 } 970 971 void 972 create_symtab_data(struct elfcopy *ecp) 973 { 974 struct section *sy, *st; 975 struct symbuf *sy_buf; 976 struct strbuf *st_buf; 977 Elf_Data *gsydata, *lsydata, *gstdata, *lstdata; 978 GElf_Shdr shy, sht; 979 980 sy = ecp->symtab; 981 st = ecp->strtab; 982 983 if (gelf_getshdr(sy->os, ­) == NULL) 984 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 985 elf_errmsg(-1)); 986 if (gelf_getshdr(st->os, &sht) == NULL) 987 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 988 elf_errmsg(-1)); 989 990 /* 991 * Create two Elf_Data for .symtab section of output object, one 992 * for local symbols and another for global symbols. Note that 993 * local symbols appear first in the .symtab. 994 */ 995 sy_buf = sy->buf; 996 if (sy_buf->nls > 0) { 997 if ((lsydata = elf_newdata(sy->os)) == NULL) 998 errx(EXIT_FAILURE, "elf_newdata() failed: %s.", 999 elf_errmsg(-1)); 1000 if (ecp->oec == ELFCLASS32) { 1001 lsydata->d_align = 4; 1002 lsydata->d_off = 0; 1003 lsydata->d_buf = sy_buf->l32; 1004 lsydata->d_size = sy_buf->nls * 1005 sizeof(Elf32_Sym); 1006 lsydata->d_type = ELF_T_SYM; 1007 lsydata->d_version = EV_CURRENT; 1008 } else { 1009 lsydata->d_align = 8; 1010 lsydata->d_off = 0; 1011 lsydata->d_buf = sy_buf->l64; 1012 lsydata->d_size = sy_buf->nls * 1013 sizeof(Elf64_Sym); 1014 lsydata->d_type = ELF_T_SYM; 1015 lsydata->d_version = EV_CURRENT; 1016 } 1017 } 1018 if (sy_buf->ngs > 0) { 1019 if ((gsydata = elf_newdata(sy->os)) == NULL) 1020 errx(EXIT_FAILURE, "elf_newdata() failed: %s.", 1021 elf_errmsg(-1)); 1022 if (ecp->oec == ELFCLASS32) { 1023 gsydata->d_align = 4; 1024 gsydata->d_off = sy_buf->nls * 1025 sizeof(Elf32_Sym); 1026 gsydata->d_buf = sy_buf->g32; 1027 gsydata->d_size = sy_buf->ngs * 1028 sizeof(Elf32_Sym); 1029 gsydata->d_type = ELF_T_SYM; 1030 gsydata->d_version = EV_CURRENT; 1031 } else { 1032 gsydata->d_align = 8; 1033 gsydata->d_off = sy_buf->nls * 1034 sizeof(Elf64_Sym); 1035 gsydata->d_buf = sy_buf->g64; 1036 gsydata->d_size = sy_buf->ngs * 1037 sizeof(Elf64_Sym); 1038 gsydata->d_type = ELF_T_SYM; 1039 gsydata->d_version = EV_CURRENT; 1040 } 1041 } 1042 1043 /* 1044 * Create two Elf_Data for .strtab, one for local symbol name 1045 * and another for globals. Same as .symtab, local symbol names 1046 * appear first. 1047 */ 1048 st_buf = st->buf; 1049 if ((lstdata = elf_newdata(st->os)) == NULL) 1050 errx(EXIT_FAILURE, "elf_newdata() failed: %s.", 1051 elf_errmsg(-1)); 1052 lstdata->d_align = 1; 1053 lstdata->d_off = 0; 1054 lstdata->d_buf = st_buf->l.buf; 1055 lstdata->d_size = st_buf->l.sz; 1056 lstdata->d_type = ELF_T_BYTE; 1057 lstdata->d_version = EV_CURRENT; 1058 1059 if (st_buf->g.sz > 0) { 1060 if ((gstdata = elf_newdata(st->os)) == NULL) 1061 errx(EXIT_FAILURE, "elf_newdata() failed: %s.", 1062 elf_errmsg(-1)); 1063 gstdata->d_align = 1; 1064 gstdata->d_off = lstdata->d_size; 1065 gstdata->d_buf = st_buf->g.buf; 1066 gstdata->d_size = st_buf->g.sz; 1067 gstdata->d_type = ELF_T_BYTE; 1068 gstdata->d_version = EV_CURRENT; 1069 } 1070 1071 shy.sh_addr = 0; 1072 shy.sh_addralign = (ecp->oec == ELFCLASS32 ? 4 : 8); 1073 shy.sh_size = sy->sz; 1074 shy.sh_type = SHT_SYMTAB; 1075 shy.sh_flags = 0; 1076 shy.sh_entsize = gelf_fsize(ecp->eout, ELF_T_SYM, 1, 1077 EV_CURRENT); 1078 /* 1079 * According to SYSV abi, here sh_info is one greater than 1080 * the symbol table index of the last local symbol(binding 1081 * STB_LOCAL). 1082 */ 1083 shy.sh_info = sy_buf->nls; 1084 1085 sht.sh_addr = 0; 1086 sht.sh_addralign = 1; 1087 sht.sh_size = st->sz; 1088 sht.sh_type = SHT_STRTAB; 1089 sht.sh_flags = 0; 1090 sht.sh_entsize = 0; 1091 sht.sh_info = 0; 1092 sht.sh_link = 0; 1093 1094 if (!gelf_update_shdr(sy->os, ­)) 1095 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1096 elf_errmsg(-1)); 1097 if (!gelf_update_shdr(st->os, &sht)) 1098 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1099 elf_errmsg(-1)); 1100 } 1101 1102 void 1103 add_to_symop_list(struct elfcopy *ecp, const char *name, const char *newname, 1104 unsigned int op) 1105 { 1106 struct symop *s; 1107 1108 if ((s = lookup_symop_list(ecp, name, ~0U)) == NULL) { 1109 if ((s = calloc(1, sizeof(*s))) == NULL) 1110 errx(EXIT_FAILURE, "not enough memory"); 1111 s->name = name; 1112 if (op == SYMOP_REDEF) 1113 s->newname = newname; 1114 } 1115 1116 s->op |= op; 1117 STAILQ_INSERT_TAIL(&ecp->v_symop, s, symop_list); 1118 } 1119 1120 static int 1121 match_wildcard(const char *name, const char *pattern) 1122 { 1123 int reverse, match; 1124 1125 reverse = 0; 1126 if (*pattern == '!') { 1127 reverse = 1; 1128 pattern++; 1129 } 1130 1131 match = 0; 1132 if (!fnmatch(pattern, name, 0)) 1133 match = 1; 1134 1135 return (reverse ? !match : match); 1136 } 1137 1138 struct symop * 1139 lookup_symop_list(struct elfcopy *ecp, const char *name, unsigned int op) 1140 { 1141 struct symop *s; 1142 1143 STAILQ_FOREACH(s, &ecp->v_symop, symop_list) { 1144 if (name == NULL || !strcmp(name, s->name) || 1145 ((ecp->flags & WILDCARD) && match_wildcard(name, s->name))) 1146 if ((s->op & op) != 0) 1147 return (s); 1148 } 1149 1150 return (NULL); 1151 } 1152 1153 static int 1154 lookup_exact_string(hash_head *buckets, const char *buf, const char *s) 1155 { 1156 struct sthash *sh; 1157 uint32_t hash; 1158 1159 hash = str_hash(s); 1160 LIST_FOREACH(sh, &buckets[hash], sh_next) 1161 if (strcmp(buf + sh->sh_off, s) == 0) 1162 return sh->sh_off; 1163 return (-1); 1164 } 1165 1166 uint32_t 1167 str_hash(const char *s) 1168 { 1169 uint32_t hash; 1170 1171 for (hash = 2166136261UL; *s; s++) 1172 hash = (hash ^ *s) * 16777619; 1173 1174 return (hash & (STHASHSIZE - 1)); 1175 } 1176