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