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 3376 2016-01-26 18:41:39Z emaste $"); 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 refered 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 refered 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 /* 680 * Set section index map for .symtab and .strtab. We need to set 681 * these map because otherwise symbols which refer to .symtab and 682 * .strtab will be removed by symbol filtering unconditionally. 683 * And we have to figure out scn index this way (instead of calling 684 * elf_ndxscn) because we can not create Elf_Scn before we're certain 685 * that .symtab and .strtab will exist in the output object. 686 */ 687 maxndx = 0; 688 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 689 if (s->os == NULL) 690 continue; 691 if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) 692 errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 693 elf_errmsg(-1)); 694 if (ndx > maxndx) 695 maxndx = ndx; 696 } 697 ecp->secndx[elf_ndxscn(sy->is)] = maxndx + 1; 698 ecp->secndx[elf_ndxscn(st->is)] = maxndx + 2; 699 700 /* 701 * Generate symbols for output object if SYMTAB_INTACT is not set. 702 * If there is no symbol in the input object or all the symbols are 703 * stripped, then free all the resouces allotted for symbol table, 704 * and clear SYMTAB_EXIST flag. 705 */ 706 if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) { 707 TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list); 708 TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list); 709 free(ecp->symtab->buf); 710 free(ecp->symtab); 711 free(ecp->strtab->buf); 712 free(ecp->strtab); 713 ecp->symtab = NULL; 714 ecp->strtab = NULL; 715 ecp->flags &= ~SYMTAB_EXIST; 716 return; 717 } 718 719 /* Create output Elf_Scn for .symtab and .strtab. */ 720 if ((sy->os = elf_newscn(ecp->eout)) == NULL || 721 (st->os = elf_newscn(ecp->eout)) == NULL) 722 errx(EXIT_FAILURE, "elf_newscn failed: %s", 723 elf_errmsg(-1)); 724 /* Update secndx anyway. */ 725 ecp->secndx[elf_ndxscn(sy->is)] = elf_ndxscn(sy->os); 726 ecp->secndx[elf_ndxscn(st->is)] = elf_ndxscn(st->os); 727 728 /* 729 * Copy .symtab and .strtab section headers from input to output 730 * object to start with, these will be overridden later if need. 731 */ 732 copy_shdr(ecp, sy, ".symtab", 1, 0); 733 copy_shdr(ecp, st, ".strtab", 1, 0); 734 735 /* Copy verbatim if symbol table is intact. */ 736 if (ecp->flags & SYMTAB_INTACT) { 737 copy_data(sy); 738 copy_data(st); 739 return; 740 } 741 742 create_symtab_data(ecp); 743 } 744 745 void 746 free_symtab(struct elfcopy *ecp) 747 { 748 struct symbuf *sy_buf; 749 struct strbuf *st_buf; 750 struct sthash *sh, *shtmp; 751 int i; 752 753 if (ecp->symtab != NULL && ecp->symtab->buf != NULL) { 754 sy_buf = ecp->symtab->buf; 755 if (sy_buf->l32 != NULL) 756 free(sy_buf->l32); 757 if (sy_buf->g32 != NULL) 758 free(sy_buf->g32); 759 if (sy_buf->l64 != NULL) 760 free(sy_buf->l64); 761 if (sy_buf->g64 != NULL) 762 free(sy_buf->g64); 763 } 764 765 if (ecp->strtab != NULL && ecp->strtab->buf != NULL) { 766 st_buf = ecp->strtab->buf; 767 if (st_buf->l.buf != NULL) 768 free(st_buf->l.buf); 769 if (st_buf->g.buf != NULL) 770 free(st_buf->g.buf); 771 for (i = 0; i < STHASHSIZE; i++) { 772 LIST_FOREACH_SAFE(sh, &st_buf->l.hash[i], sh_next, 773 shtmp) { 774 LIST_REMOVE(sh, sh_next); 775 free(sh); 776 } 777 LIST_FOREACH_SAFE(sh, &st_buf->g.hash[i], sh_next, 778 shtmp) { 779 LIST_REMOVE(sh, sh_next); 780 free(sh); 781 } 782 } 783 } 784 785 if (ecp->symndx != NULL) { 786 free(ecp->symndx); 787 ecp->symndx = NULL; 788 } 789 if (ecp->v_rel != NULL) { 790 free(ecp->v_rel); 791 ecp->v_rel = NULL; 792 } 793 if (ecp->v_grp != NULL) { 794 free(ecp->v_grp); 795 ecp->v_grp = NULL; 796 } 797 if (ecp->v_secsym != NULL) { 798 free(ecp->v_secsym); 799 ecp->v_secsym = NULL; 800 } 801 } 802 803 void 804 create_external_symtab(struct elfcopy *ecp) 805 { 806 struct section *s; 807 struct symbuf *sy_buf; 808 struct strbuf *st_buf; 809 GElf_Shdr sh; 810 size_t ndx; 811 812 if (ecp->oec == ELFCLASS32) 813 ecp->symtab = create_external_section(ecp, ".symtab", NULL, 814 NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 4, 0, 0); 815 else 816 ecp->symtab = create_external_section(ecp, ".symtab", NULL, 817 NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 8, 0, 0); 818 819 ecp->strtab = create_external_section(ecp, ".strtab", NULL, NULL, 0, 0, 820 SHT_STRTAB, ELF_T_BYTE, 0, 1, 0, 0); 821 822 /* Let sh_link field of .symtab section point to .strtab section. */ 823 if (gelf_getshdr(ecp->symtab->os, &sh) == NULL) 824 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 825 elf_errmsg(-1)); 826 sh.sh_link = elf_ndxscn(ecp->strtab->os); 827 if (!gelf_update_shdr(ecp->symtab->os, &sh)) 828 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 829 elf_errmsg(-1)); 830 831 /* Create buffers for .symtab and .strtab. */ 832 if ((sy_buf = calloc(1, sizeof(*sy_buf))) == NULL) 833 err(EXIT_FAILURE, "calloc failed"); 834 if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL) 835 err(EXIT_FAILURE, "calloc failed"); 836 sy_buf->gcap = sy_buf->lcap = 64; 837 st_buf->g.cap = 256; 838 st_buf->l.cap = 64; 839 st_buf->l.sz = 1; /* '\0' at start. */ 840 st_buf->g.sz = 0; 841 842 ecp->symtab->sz = 0; 843 ecp->strtab->sz = 0; 844 ecp->symtab->buf = sy_buf; 845 ecp->strtab->buf = st_buf; 846 847 /* Always create the special symbol at the symtab beginning. */ 848 add_to_symtab(ecp, NULL, 0, 0, SHN_UNDEF, 849 ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE), 0, 1); 850 851 /* Create STT_SECTION symbols. */ 852 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 853 if (s->pseudo) 854 continue; 855 if (strcmp(s->name, ".symtab") == 0 || 856 strcmp(s->name, ".strtab") == 0 || 857 strcmp(s->name, ".shstrtab") == 0) 858 continue; 859 (void) elf_errno(); 860 if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) { 861 warnx("elf_ndxscn failed: %s", 862 elf_errmsg(-1)); 863 continue; 864 } 865 add_to_symtab(ecp, NULL, 0, 0, ndx, 866 GELF_ST_INFO(STB_LOCAL, STT_SECTION), 0, 1); 867 } 868 } 869 870 void 871 add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value, 872 uint64_t st_size, uint16_t st_shndx, unsigned char st_info, 873 unsigned char st_other, int ndx_known) 874 { 875 struct symbuf *sy_buf; 876 struct strbuf *st_buf; 877 struct sthash *sh; 878 uint32_t hash; 879 int pos; 880 881 /* 882 * Convenient macro for copying global/local 32/64 bit symbols 883 * from input object to the buffer created for output object. 884 * It handles buffer growing, st_name calculating and st_shndx 885 * updating for symbols with non-special section index. 886 */ 887 #define _ST_NAME_EMPTY_l 0 888 #define _ST_NAME_EMPTY_g -1 889 #define _ADDSYM(B, SZ) do { \ 890 if (sy_buf->B##SZ == NULL) { \ 891 sy_buf->B##SZ = malloc(sy_buf->B##cap * \ 892 sizeof(Elf##SZ##_Sym)); \ 893 if (sy_buf->B##SZ == NULL) \ 894 err(EXIT_FAILURE, "malloc failed"); \ 895 } else if (sy_buf->n##B##s >= sy_buf->B##cap) { \ 896 sy_buf->B##cap *= 2; \ 897 sy_buf->B##SZ = realloc(sy_buf->B##SZ, sy_buf->B##cap * \ 898 sizeof(Elf##SZ##_Sym)); \ 899 if (sy_buf->B##SZ == NULL) \ 900 err(EXIT_FAILURE, "realloc failed"); \ 901 } \ 902 sy_buf->B##SZ[sy_buf->n##B##s].st_info = st_info; \ 903 sy_buf->B##SZ[sy_buf->n##B##s].st_other = st_other; \ 904 sy_buf->B##SZ[sy_buf->n##B##s].st_value = st_value; \ 905 sy_buf->B##SZ[sy_buf->n##B##s].st_size = st_size; \ 906 if (ndx_known) \ 907 sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx; \ 908 else if (st_shndx == SHN_UNDEF || st_shndx >= SHN_LORESERVE) \ 909 sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx; \ 910 else \ 911 sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = \ 912 ecp->secndx[st_shndx]; \ 913 if (st_buf->B.buf == NULL) { \ 914 st_buf->B.buf = calloc(st_buf->B.cap, \ 915 sizeof(*st_buf->B.buf)); \ 916 if (st_buf->B.buf == NULL) \ 917 err(EXIT_FAILURE, "malloc failed"); \ 918 } \ 919 if (name != NULL && *name != '\0') { \ 920 pos = lookup_exact_string(st_buf->B.hash, st_buf->B.buf,\ 921 name); \ 922 if (pos != -1) \ 923 sy_buf->B##SZ[sy_buf->n##B##s].st_name = pos; \ 924 else { \ 925 sy_buf->B##SZ[sy_buf->n##B##s].st_name = \ 926 st_buf->B.sz; \ 927 while (st_buf->B.sz + strlen(name) >= \ 928 st_buf->B.cap - 1) { \ 929 st_buf->B.cap *= 2; \ 930 st_buf->B.buf = realloc(st_buf->B.buf, \ 931 st_buf->B.cap); \ 932 if (st_buf->B.buf == NULL) \ 933 err(EXIT_FAILURE, \ 934 "realloc failed"); \ 935 } \ 936 if ((sh = malloc(sizeof(*sh))) == NULL) \ 937 err(EXIT_FAILURE, "malloc failed"); \ 938 sh->sh_off = st_buf->B.sz; \ 939 hash = str_hash(name); \ 940 LIST_INSERT_HEAD(&st_buf->B.hash[hash], sh, \ 941 sh_next); \ 942 strncpy(&st_buf->B.buf[st_buf->B.sz], name, \ 943 strlen(name)); \ 944 st_buf->B.buf[st_buf->B.sz + strlen(name)] = '\0'; \ 945 st_buf->B.sz += strlen(name) + 1; \ 946 } \ 947 } else \ 948 sy_buf->B##SZ[sy_buf->n##B##s].st_name = \ 949 (Elf##SZ##_Word)_ST_NAME_EMPTY_##B; \ 950 sy_buf->n##B##s++; \ 951 } while (0) 952 953 sy_buf = ecp->symtab->buf; 954 st_buf = ecp->strtab->buf; 955 956 if (ecp->oec == ELFCLASS32) { 957 if (is_local_symbol(st_info)) 958 _ADDSYM(l, 32); 959 else 960 _ADDSYM(g, 32); 961 } else { 962 if (is_local_symbol(st_info)) 963 _ADDSYM(l, 64); 964 else 965 _ADDSYM(g, 64); 966 } 967 968 /* Update section size. */ 969 ecp->symtab->sz = (sy_buf->nls + sy_buf->ngs) * 970 (ecp->oec == ELFCLASS32 ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym)); 971 ecp->strtab->sz = st_buf->l.sz + st_buf->g.sz; 972 973 #undef _ADDSYM 974 #undef _ST_NAME_EMPTY_l 975 #undef _ST_NAME_EMPTY_g 976 } 977 978 void 979 finalize_external_symtab(struct elfcopy *ecp) 980 { 981 struct symbuf *sy_buf; 982 struct strbuf *st_buf; 983 int i; 984 985 /* 986 * Update st_name for global/weak symbols. (global/weak symbols 987 * are put after local symbols) 988 */ 989 sy_buf = ecp->symtab->buf; 990 st_buf = ecp->strtab->buf; 991 for (i = 0; (size_t) i < sy_buf->ngs; i++) { 992 if (ecp->oec == ELFCLASS32) { 993 if (sy_buf->g32[i].st_name == (Elf32_Word)-1) 994 sy_buf->g32[i].st_name = 0; 995 else 996 sy_buf->g32[i].st_name += st_buf->l.sz; 997 } else { 998 if (sy_buf->g64[i].st_name == (Elf64_Word)-1) 999 sy_buf->g64[i].st_name = 0; 1000 else 1001 sy_buf->g64[i].st_name += st_buf->l.sz; 1002 } 1003 } 1004 } 1005 1006 void 1007 create_symtab_data(struct elfcopy *ecp) 1008 { 1009 struct section *sy, *st; 1010 struct symbuf *sy_buf; 1011 struct strbuf *st_buf; 1012 Elf_Data *gsydata, *lsydata, *gstdata, *lstdata; 1013 GElf_Shdr shy, sht; 1014 1015 sy = ecp->symtab; 1016 st = ecp->strtab; 1017 1018 if (gelf_getshdr(sy->os, ­) == NULL) 1019 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1020 elf_errmsg(-1)); 1021 if (gelf_getshdr(st->os, &sht) == NULL) 1022 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1023 elf_errmsg(-1)); 1024 1025 /* 1026 * Create two Elf_Data for .symtab section of output object, one 1027 * for local symbols and another for global symbols. Note that 1028 * local symbols appear first in the .symtab. 1029 */ 1030 sy_buf = sy->buf; 1031 if (sy_buf->nls > 0) { 1032 if ((lsydata = elf_newdata(sy->os)) == NULL) 1033 errx(EXIT_FAILURE, "elf_newdata() failed: %s.", 1034 elf_errmsg(-1)); 1035 if (ecp->oec == ELFCLASS32) { 1036 lsydata->d_align = 4; 1037 lsydata->d_off = 0; 1038 lsydata->d_buf = sy_buf->l32; 1039 lsydata->d_size = sy_buf->nls * 1040 sizeof(Elf32_Sym); 1041 lsydata->d_type = ELF_T_SYM; 1042 lsydata->d_version = EV_CURRENT; 1043 } else { 1044 lsydata->d_align = 8; 1045 lsydata->d_off = 0; 1046 lsydata->d_buf = sy_buf->l64; 1047 lsydata->d_size = sy_buf->nls * 1048 sizeof(Elf64_Sym); 1049 lsydata->d_type = ELF_T_SYM; 1050 lsydata->d_version = EV_CURRENT; 1051 } 1052 } 1053 if (sy_buf->ngs > 0) { 1054 if ((gsydata = elf_newdata(sy->os)) == NULL) 1055 errx(EXIT_FAILURE, "elf_newdata() failed: %s.", 1056 elf_errmsg(-1)); 1057 if (ecp->oec == ELFCLASS32) { 1058 gsydata->d_align = 4; 1059 gsydata->d_off = sy_buf->nls * 1060 sizeof(Elf32_Sym); 1061 gsydata->d_buf = sy_buf->g32; 1062 gsydata->d_size = sy_buf->ngs * 1063 sizeof(Elf32_Sym); 1064 gsydata->d_type = ELF_T_SYM; 1065 gsydata->d_version = EV_CURRENT; 1066 } else { 1067 gsydata->d_align = 8; 1068 gsydata->d_off = sy_buf->nls * 1069 sizeof(Elf64_Sym); 1070 gsydata->d_buf = sy_buf->g64; 1071 gsydata->d_size = sy_buf->ngs * 1072 sizeof(Elf64_Sym); 1073 gsydata->d_type = ELF_T_SYM; 1074 gsydata->d_version = EV_CURRENT; 1075 } 1076 } 1077 1078 /* 1079 * Create two Elf_Data for .strtab, one for local symbol name 1080 * and another for globals. Same as .symtab, local symbol names 1081 * appear first. 1082 */ 1083 st_buf = st->buf; 1084 if ((lstdata = elf_newdata(st->os)) == NULL) 1085 errx(EXIT_FAILURE, "elf_newdata() failed: %s.", 1086 elf_errmsg(-1)); 1087 lstdata->d_align = 1; 1088 lstdata->d_off = 0; 1089 lstdata->d_buf = st_buf->l.buf; 1090 lstdata->d_size = st_buf->l.sz; 1091 lstdata->d_type = ELF_T_BYTE; 1092 lstdata->d_version = EV_CURRENT; 1093 1094 if (st_buf->g.sz > 0) { 1095 if ((gstdata = elf_newdata(st->os)) == NULL) 1096 errx(EXIT_FAILURE, "elf_newdata() failed: %s.", 1097 elf_errmsg(-1)); 1098 gstdata->d_align = 1; 1099 gstdata->d_off = lstdata->d_size; 1100 gstdata->d_buf = st_buf->g.buf; 1101 gstdata->d_size = st_buf->g.sz; 1102 gstdata->d_type = ELF_T_BYTE; 1103 gstdata->d_version = EV_CURRENT; 1104 } 1105 1106 shy.sh_addr = 0; 1107 shy.sh_addralign = (ecp->oec == ELFCLASS32 ? 4 : 8); 1108 shy.sh_size = sy->sz; 1109 shy.sh_type = SHT_SYMTAB; 1110 shy.sh_flags = 0; 1111 shy.sh_entsize = gelf_fsize(ecp->eout, ELF_T_SYM, 1, 1112 EV_CURRENT); 1113 /* 1114 * According to SYSV abi, here sh_info is one greater than 1115 * the symbol table index of the last local symbol(binding 1116 * STB_LOCAL). 1117 */ 1118 shy.sh_info = sy_buf->nls; 1119 1120 sht.sh_addr = 0; 1121 sht.sh_addralign = 1; 1122 sht.sh_size = st->sz; 1123 sht.sh_type = SHT_STRTAB; 1124 sht.sh_flags = 0; 1125 sht.sh_entsize = 0; 1126 sht.sh_info = 0; 1127 sht.sh_link = 0; 1128 1129 if (!gelf_update_shdr(sy->os, ­)) 1130 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1131 elf_errmsg(-1)); 1132 if (!gelf_update_shdr(st->os, &sht)) 1133 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1134 elf_errmsg(-1)); 1135 } 1136 1137 void 1138 add_to_symop_list(struct elfcopy *ecp, const char *name, const char *newname, 1139 unsigned int op) 1140 { 1141 struct symop *s; 1142 1143 assert (name != NULL); 1144 STAILQ_FOREACH(s, &ecp->v_symop, symop_list) 1145 if (!strcmp(name, s->name)) 1146 goto found; 1147 1148 if ((s = calloc(1, sizeof(*s))) == NULL) 1149 errx(EXIT_FAILURE, "not enough memory"); 1150 STAILQ_INSERT_TAIL(&ecp->v_symop, s, symop_list); 1151 s->name = name; 1152 found: 1153 if (op == SYMOP_REDEF) 1154 s->newname = newname; 1155 s->op |= op; 1156 } 1157 1158 struct symop * 1159 lookup_symop_list(struct elfcopy *ecp, const char *name, unsigned int op) 1160 { 1161 struct symop *s, *ret; 1162 const char *pattern; 1163 1164 STAILQ_FOREACH(s, &ecp->v_symop, symop_list) { 1165 if ((s->op & op) == 0) 1166 continue; 1167 if (name == NULL || !strcmp(name, s->name)) 1168 return (s); 1169 if ((ecp->flags & WILDCARD) == 0) 1170 continue; 1171 1172 /* Handle wildcards. */ 1173 pattern = s->name; 1174 if (pattern[0] == '!') { 1175 /* Negative match. */ 1176 pattern++; 1177 ret = NULL; 1178 } else { 1179 /* Regular wildcard match. */ 1180 ret = s; 1181 } 1182 if (!fnmatch(pattern, name, 0)) 1183 return (ret); 1184 } 1185 1186 return (NULL); 1187 } 1188 1189 static int 1190 lookup_exact_string(hash_head *buckets, const char *buf, const char *s) 1191 { 1192 struct sthash *sh; 1193 uint32_t hash; 1194 1195 hash = str_hash(s); 1196 LIST_FOREACH(sh, &buckets[hash], sh_next) 1197 if (strcmp(buf + sh->sh_off, s) == 0) 1198 return sh->sh_off; 1199 return (-1); 1200 } 1201 1202 uint32_t 1203 str_hash(const char *s) 1204 { 1205 uint32_t hash; 1206 1207 for (hash = 2166136261UL; *s; s++) 1208 hash = (hash ^ *s) * 16777619; 1209 1210 return (hash & (STHASHSIZE - 1)); 1211 } 1212