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