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