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