2 * Copyright (c) 2007-2013 Kai Wang
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/cdefs.h>
28 #include <sys/param.h>
37 ELFTC_VCSID("$Id: symbols.c 3019 2014-04-17 14:53:40Z jkoshy $");
39 /* Symbol table buffer structure. */
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. */
49 /* String table buffer structure. */
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. */
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);
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)))
76 is_debug_symbol(unsigned char st_info)
79 if (GELF_ST_TYPE(st_info) == STT_SECTION ||
80 GELF_ST_TYPE(st_info) == STT_FILE)
87 is_global_symbol(unsigned char st_info)
90 if (GELF_ST_BIND(st_info) == STB_GLOBAL)
97 is_weak_symbol(unsigned char st_info)
100 if (GELF_ST_BIND(st_info) == STB_WEAK)
107 is_local_symbol(unsigned char st_info)
110 if (GELF_ST_BIND(st_info) == STB_LOCAL)
117 is_local_label(const char *name)
120 /* Compiler generated local symbols that start with .L */
121 if (name[0] == '.' && name[1] == 'L')
128 * Symbols related to relocation are needed.
131 is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s)
134 /* If symbol involves relocation, it is needed. */
135 if (BIT_ISSET(ecp->v_rel, i))
139 * For relocatable files (.o files), global and weak symbols
142 if (ecp->flags & RELOCATABLE) {
143 if (is_global_symbol(s->st_info) || is_weak_symbol(s->st_info))
151 is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
160 SHN_UNDEF, /* st_shndx */
163 if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL)
166 if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL)
170 * Keep the first symbol if it is the special reserved symbol.
171 * XXX Should we generate one if it's missing?
173 if (i == 0 && !memcmp(s, &sym0, sizeof(GElf_Sym)))
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)
181 if (ecp->strip == STRIP_ALL)
184 if (ecp->v_rel == NULL)
185 mark_symbols(ecp, sc);
187 if (is_needed_symbol(ecp, i, s))
190 if (ecp->strip == STRIP_UNNEEDED)
193 if ((ecp->flags & DISCARD_LOCAL) && is_local_symbol(s->st_info) &&
194 !is_debug_symbol(s->st_info))
197 if ((ecp->flags & DISCARD_LLABEL) && is_local_symbol(s->st_info) &&
198 !is_debug_symbol(s->st_info) && is_local_label(name))
201 if (ecp->strip == STRIP_DEBUG && is_debug_symbol(s->st_info))
208 * Mark symbols refered by relocation entries.
211 mark_symbols(struct elfcopy *ecp, size_t sc)
222 ecp->v_rel = calloc((sc + 7) / 8, 1);
223 if (ecp->v_rel == NULL)
224 err(EXIT_FAILURE, "calloc failed");
226 if (elf_getshstrndx(ecp->ein, &indx) == 0)
227 errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
231 while ((s = elf_nextscn(ecp->ein, s)) != NULL) {
232 if (gelf_getshdr(s, &sh) != &sh)
233 errx(EXIT_FAILURE, "elf_getshdr failed: %s",
236 if (sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA)
240 * Skip if this reloc section won't appear in the
243 if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL)
244 errx(EXIT_FAILURE, "elf_strptr failed: %s",
246 if (is_remove_section(ecp, name) ||
247 is_remove_reloc_sec(ecp, sh.sh_info))
250 /* Skip if it's not for .symtab */
251 if (sh.sh_link != elf_ndxscn(ecp->symtab->is))
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)
262 "elf_getrel failed: %s",
264 n = GELF_R_SYM(r.r_info);
266 if (gelf_getrela(d, i, &ra) != &ra)
268 "elf_getrela failed: %s",
270 n = GELF_R_SYM(ra.r_info);
273 BIT_SET(ecp->v_rel, n);
275 warnx("invalid symbox index");
278 elferr = elf_errno();
280 errx(EXIT_FAILURE, "elf_getdata failed: %s",
283 elferr = elf_errno();
285 errx(EXIT_FAILURE, "elf_nextscn failed: %s",
290 generate_symbols(struct elfcopy *ecp)
294 struct symbuf *sy_buf;
295 struct strbuf *st_buf;
303 size_t ishstrndx, namelen, ndx, sc, symndx;
306 if (elf_getshstrndx(ecp->ein, &ishstrndx) == 0)
307 errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
309 if ((ec = gelf_getclass(ecp->eout)) == ELFCLASSNONE)
310 errx(EXIT_FAILURE, "gelf_getclass failed: %s",
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;
321 st_buf->lsz = 1; /* '\0' at start. */
326 ecp->symtab->buf = sy_buf;
327 ecp->strtab->buf = st_buf;
330 * Create bit vector v_secsym, which is used to mark sections
331 * that already have corresponding STT_SECTION symbols.
333 ecp->v_secsym = calloc((ecp->nos + 7) / 8, 1);
334 if (ecp->v_secsym == NULL)
335 err(EXIT_FAILURE, "calloc failed");
337 /* Locate .strtab of input object. */
341 while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
342 if (gelf_getshdr(is, &ish) != &ish)
343 errx(EXIT_FAILURE, "elf_getshdr failed: %s",
345 if ((name = elf_strptr(ecp->ein, ishstrndx, ish.sh_name)) ==
347 errx(EXIT_FAILURE, "elf_strptr failed: %s",
349 if (strcmp(name, ".strtab") == 0) {
350 symndx = elf_ndxscn(is);
354 elferr = elf_errno();
356 errx(EXIT_FAILURE, "elf_nextscn failed: %s",
359 /* Symbol table should exist if this function is called. */
361 warnx("can't find .strtab section");
365 /* Locate .symtab of input object. */
367 while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
368 if (gelf_getshdr(is, &ish) != &ish)
369 errx(EXIT_FAILURE, "elf_getshdr failed: %s",
371 if ((name = elf_strptr(ecp->ein, ishstrndx, ish.sh_name)) ==
373 errx(EXIT_FAILURE, "elf_strptr failed: %s",
375 if (strcmp(name, ".symtab") == 0)
378 elferr = elf_errno();
380 errx(EXIT_FAILURE, "elf_nextscn failed: %s",
383 errx(EXIT_FAILURE, "can't find .strtab section");
386 * Create bit vector gsym to mark global symbols, and symndx
387 * to keep track of symbol index changes from input object to
388 * output object, it is used by update_reloc() later to update
389 * relocation information.
392 sc = ish.sh_size / ish.sh_entsize;
394 ecp->symndx = calloc(sc, sizeof(*ecp->symndx));
395 if (ecp->symndx == NULL)
396 err(EXIT_FAILURE, "calloc failed");
397 gsym = calloc((sc + 7) / 8, sizeof(*gsym));
399 err(EXIT_FAILURE, "calloc failed");
400 if ((id = elf_getdata(is, NULL)) == NULL) {
401 elferr = elf_errno();
403 errx(EXIT_FAILURE, "elf_getdata failed: %s",
410 /* Copy/Filter each symbol. */
411 for (i = 0; (size_t)i < sc; i++) {
412 if (gelf_getsym(id, i, &sym) != &sym)
413 errx(EXIT_FAILURE, "gelf_getsym failed: %s",
415 if ((name = elf_strptr(ecp->ein, symndx, sym.st_name)) == NULL)
416 errx(EXIT_FAILURE, "elf_strptr failed: %s",
419 /* Symbol filtering. */
420 if (is_remove_symbol(ecp, sc, i, &sym, name) != 0)
423 /* Check if we need to change the binding of this symbol. */
424 if (is_global_symbol(sym.st_info) ||
425 is_weak_symbol(sym.st_info)) {
427 * XXX Binutils objcopy does not weaken certain
430 if (ecp->flags & WEAKEN_ALL ||
431 lookup_symop_list(ecp, name, SYMOP_WEAKEN) != NULL)
432 sym.st_info = GELF_ST_INFO(STB_WEAK,
433 GELF_ST_TYPE(sym.st_info));
434 /* Do not localize undefined symbols. */
435 if (sym.st_shndx != SHN_UNDEF &&
436 lookup_symop_list(ecp, name, SYMOP_LOCALIZE) !=
438 sym.st_info = GELF_ST_INFO(STB_LOCAL,
439 GELF_ST_TYPE(sym.st_info));
440 if (ecp->flags & KEEP_GLOBAL &&
441 sym.st_shndx != SHN_UNDEF &&
442 lookup_symop_list(ecp, name, SYMOP_KEEPG) == NULL)
443 sym.st_info = GELF_ST_INFO(STB_LOCAL,
444 GELF_ST_TYPE(sym.st_info));
446 /* STB_LOCAL binding. */
447 if (lookup_symop_list(ecp, name, SYMOP_GLOBALIZE) !=
449 sym.st_info = GELF_ST_INFO(STB_GLOBAL,
450 GELF_ST_TYPE(sym.st_info));
451 /* XXX We should globalize weak symbol? */
454 /* Check if we need to rename this symbol. */
455 if ((sp = lookup_symop_list(ecp, name, SYMOP_REDEF)) != NULL)
458 /* Check if we need to prefix the symbols. */
460 if (ecp->prefix_sym != NULL && name != NULL && *name != '\0') {
461 namelen = strlen(name) + strlen(ecp->prefix_sym) + 1;
462 if ((newname = malloc(namelen)) == NULL)
463 err(EXIT_FAILURE, "malloc failed");
464 snprintf(newname, namelen, "%s%s", ecp->prefix_sym,
469 /* Copy symbol, mark global/weak symbol and add to index map. */
470 if (is_global_symbol(sym.st_info) ||
471 is_weak_symbol(sym.st_info)) {
473 ecp->symndx[i] = sy_buf->ngs;
475 ecp->symndx[i] = sy_buf->nls;
476 add_to_symtab(ecp, name, sym.st_value, sym.st_size,
477 sym.st_shndx, sym.st_info, sym.st_other, 0);
483 * If the symbol is a STT_SECTION symbol, mark the section
486 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION)
487 BIT_SET(ecp->v_secsym, ecp->secndx[sym.st_shndx]);
491 * Give up if there is no real symbols inside the table.
492 * XXX The logic here needs to be improved. We need to
493 * check if that only local symbol is the reserved symbol.
495 if (sy_buf->nls <= 1 && sy_buf->ngs == 0)
499 * Create STT_SECTION symbols for sections that do not already
500 * got one. However, we do not create STT_SECTION symbol for
501 * .symtab, .strtab, .shstrtab and reloc sec of relocatables.
503 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
506 if (strcmp(s->name, ".symtab") == 0 ||
507 strcmp(s->name, ".strtab") == 0 ||
508 strcmp(s->name, ".shstrtab") == 0)
510 if ((ecp->flags & RELOCATABLE) != 0 &&
511 ((s->type == SHT_REL) || (s->type == SHT_RELA)))
514 if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF)
515 errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
518 if (!BIT_ISSET(ecp->v_secsym, ndx)) {
520 sym.st_value = s->vma;
522 sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION);
524 * Don't let add_to_symtab() touch sym.st_shndx.
525 * In this case, we know the index already.
527 add_to_symtab(ecp, NULL, sym.st_value, sym.st_size,
528 ndx, sym.st_info, sym.st_other, 1);
533 * Update st_name and index map for global/weak symbols. Note that
534 * global/weak symbols are put after local symbols.
537 for(i = 0; (size_t) i < sc; i++) {
538 if (!BIT_ISSET(gsym, i))
541 /* Update st_name. */
542 if (ec == ELFCLASS32)
543 sy_buf->g32[ecp->symndx[i]].st_name +=
546 sy_buf->g64[ecp->symndx[i]].st_name +=
549 /* Update index map. */
550 ecp->symndx[i] += sy_buf->nls;
559 create_symtab(struct elfcopy *ecp)
561 struct section *s, *sy, *st;
568 * Set section index map for .symtab and .strtab. We need to set
569 * these map because otherwise symbols which refer to .symtab and
570 * .strtab will be removed by symbol filtering unconditionally.
571 * And we have to figure out scn index this way (instead of calling
572 * elf_ndxscn) because we can not create Elf_Scn before we're certain
573 * that .symtab and .strtab will exist in the output object.
576 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
579 if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF)
580 errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
585 ecp->secndx[elf_ndxscn(sy->is)] = maxndx + 1;
586 ecp->secndx[elf_ndxscn(st->is)] = maxndx + 2;
589 * Generate symbols for output object if SYMTAB_INTACT is not set.
590 * If there is no symbol in the input object or all the symbols are
591 * stripped, then free all the resouces allotted for symbol table,
592 * and clear SYMTAB_EXIST flag.
594 if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) {
595 TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list);
596 TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list);
601 ecp->flags &= ~SYMTAB_EXIST;
605 /* Create output Elf_Scn for .symtab and .strtab. */
606 if ((sy->os = elf_newscn(ecp->eout)) == NULL ||
607 (st->os = elf_newscn(ecp->eout)) == NULL)
608 errx(EXIT_FAILURE, "elf_newscn failed: %s",
610 /* Update secndx anyway. */
611 ecp->secndx[elf_ndxscn(sy->is)] = elf_ndxscn(sy->os);
612 ecp->secndx[elf_ndxscn(st->is)] = elf_ndxscn(st->os);
615 * Copy .symtab and .strtab section headers from input to output
616 * object to start with, these will be overridden later if need.
618 copy_shdr(ecp, sy, ".symtab", 1, 0);
619 copy_shdr(ecp, st, ".strtab", 1, 0);
621 /* Copy verbatim if symbol table is intact. */
622 if (ecp->flags & SYMTAB_INTACT) {
628 create_symtab_data(ecp);
632 free_symtab(struct elfcopy *ecp)
634 struct symbuf *sy_buf;
635 struct strbuf *st_buf;
637 if (ecp->symtab != NULL && ecp->symtab->buf != NULL) {
638 sy_buf = ecp->symtab->buf;
639 if (sy_buf->l32 != NULL)
641 if (sy_buf->g32 != NULL)
643 if (sy_buf->l64 != NULL)
645 if (sy_buf->g64 != NULL)
649 if (ecp->strtab != NULL && ecp->strtab->buf != NULL) {
650 st_buf = ecp->strtab->buf;
651 if (st_buf->l != NULL)
653 if (st_buf->g != NULL)
659 create_external_symtab(struct elfcopy *ecp)
662 struct symbuf *sy_buf;
663 struct strbuf *st_buf;
667 if (ecp->oec == ELFCLASS32)
668 ecp->symtab = create_external_section(ecp, ".symtab", NULL,
669 NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 4, 0, 0);
671 ecp->symtab = create_external_section(ecp, ".symtab", NULL,
672 NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 8, 0, 0);
674 ecp->strtab = create_external_section(ecp, ".strtab", NULL, NULL, 0, 0,
675 SHT_STRTAB, ELF_T_BYTE, 0, 1, 0, 0);
677 /* Let sh_link field of .symtab section point to .strtab section. */
678 if (gelf_getshdr(ecp->symtab->os, &sh) == NULL)
679 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
681 sh.sh_link = elf_ndxscn(ecp->strtab->os);
682 if (!gelf_update_shdr(ecp->symtab->os, &sh))
683 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
686 /* Create buffers for .symtab and .strtab. */
687 if ((sy_buf = calloc(1, sizeof(*sy_buf))) == NULL)
688 err(EXIT_FAILURE, "calloc failed");
689 if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL)
690 err(EXIT_FAILURE, "calloc failed");
691 sy_buf->gcap = sy_buf->lcap = 64;
694 st_buf->lsz = 1; /* '\0' at start. */
699 ecp->symtab->buf = sy_buf;
700 ecp->strtab->buf = st_buf;
702 /* Always create the special symbol at the symtab beginning. */
703 add_to_symtab(ecp, NULL, 0, 0, SHN_UNDEF,
704 ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE), 0, 1);
706 /* Create STT_SECTION symbols. */
707 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
710 if (strcmp(s->name, ".symtab") == 0 ||
711 strcmp(s->name, ".strtab") == 0 ||
712 strcmp(s->name, ".shstrtab") == 0)
715 if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) {
716 warnx("elf_ndxscn failed: %s",
720 add_to_symtab(ecp, NULL, 0, 0, ndx,
721 GELF_ST_INFO(STB_LOCAL, STT_SECTION), 0, 1);
726 add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value,
727 uint64_t st_size, uint16_t st_shndx, unsigned char st_info,
728 unsigned char st_other, int ndx_known)
730 struct symbuf *sy_buf;
731 struct strbuf *st_buf;
735 * Convenient macro for copying global/local 32/64 bit symbols
736 * from input object to the buffer created for output object.
737 * It handles buffer growing, st_name calculating and st_shndx
738 * updating for symbols with non-special section index.
740 #define _ADDSYM(B, SZ) do { \
741 if (sy_buf->B##SZ == NULL) { \
742 sy_buf->B##SZ = malloc(sy_buf->B##cap * \
743 sizeof(Elf##SZ##_Sym)); \
744 if (sy_buf->B##SZ == NULL) \
745 err(EXIT_FAILURE, "malloc failed"); \
746 } else if (sy_buf->n##B##s >= sy_buf->B##cap) { \
747 sy_buf->B##cap *= 2; \
748 sy_buf->B##SZ = realloc(sy_buf->B##SZ, sy_buf->B##cap * \
749 sizeof(Elf##SZ##_Sym)); \
750 if (sy_buf->B##SZ == NULL) \
751 err(EXIT_FAILURE, "realloc failed"); \
753 sy_buf->B##SZ[sy_buf->n##B##s].st_info = st_info; \
754 sy_buf->B##SZ[sy_buf->n##B##s].st_other = st_other; \
755 sy_buf->B##SZ[sy_buf->n##B##s].st_value = st_value; \
756 sy_buf->B##SZ[sy_buf->n##B##s].st_size = st_size; \
758 sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx; \
759 else if (st_shndx == SHN_UNDEF || st_shndx >= SHN_LORESERVE) \
760 sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx; \
762 sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = \
763 ecp->secndx[st_shndx]; \
764 if (st_buf->B == NULL) { \
765 st_buf->B = calloc(st_buf->B##cap, sizeof(*st_buf->B)); \
766 if (st_buf->B == NULL) \
767 err(EXIT_FAILURE, "malloc failed"); \
769 if (name != NULL && *name != '\0') { \
770 pos = lookup_exact_string(st_buf->B, \
771 st_buf->B##sz, name); \
773 sy_buf->B##SZ[sy_buf->n##B##s].st_name = pos; \
775 sy_buf->B##SZ[sy_buf->n##B##s].st_name = \
777 while (st_buf->B##sz + strlen(name) >= \
778 st_buf->B##cap - 1) { \
779 st_buf->B##cap *= 2; \
780 st_buf->B = realloc(st_buf->B, \
782 if (st_buf->B == NULL) \
786 strncpy(&st_buf->B[st_buf->B##sz], name, \
788 st_buf->B[st_buf->B##sz + strlen(name)] = '\0'; \
789 st_buf->B##sz += strlen(name) + 1; \
792 sy_buf->B##SZ[sy_buf->n##B##s].st_name = 0; \
796 sy_buf = ecp->symtab->buf;
797 st_buf = ecp->strtab->buf;
799 if (ecp->oec == ELFCLASS32) {
800 if (is_local_symbol(st_info))
805 if (is_local_symbol(st_info))
811 /* Update section size. */
812 ecp->symtab->sz = (sy_buf->nls + sy_buf->ngs) *
813 (ecp->oec == ELFCLASS32 ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym));
814 ecp->strtab->sz = st_buf->lsz + st_buf->gsz;
820 finalize_external_symtab(struct elfcopy *ecp)
822 struct symbuf *sy_buf;
823 struct strbuf *st_buf;
827 * Update st_name for global/weak symbols. (global/weak symbols
828 * are put after local symbols)
830 sy_buf = ecp->symtab->buf;
831 st_buf = ecp->strtab->buf;
832 for (i = 0; (size_t) i < sy_buf->ngs; i++) {
833 if (ecp->oec == ELFCLASS32)
834 sy_buf->g32[i].st_name += st_buf->lsz;
836 sy_buf->g64[i].st_name += st_buf->lsz;
841 create_symtab_data(struct elfcopy *ecp)
843 struct section *sy, *st;
844 struct symbuf *sy_buf;
845 struct strbuf *st_buf;
846 Elf_Data *gsydata, *lsydata, *gstdata, *lstdata;
852 if (gelf_getshdr(sy->os, ­) == NULL)
853 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
855 if (gelf_getshdr(st->os, &sht) == NULL)
856 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
860 * Create two Elf_Data for .symtab section of output object, one
861 * for local symbols and another for global symbols. Note that
862 * local symbols appear first in the .symtab.
865 if (sy_buf->nls > 0) {
866 if ((lsydata = elf_newdata(sy->os)) == NULL)
867 errx(EXIT_FAILURE, "elf_newdata() failed: %s.",
869 if (ecp->oec == ELFCLASS32) {
870 lsydata->d_align = 4;
872 lsydata->d_buf = sy_buf->l32;
873 lsydata->d_size = sy_buf->nls *
875 lsydata->d_type = ELF_T_SYM;
876 lsydata->d_version = EV_CURRENT;
878 lsydata->d_align = 8;
880 lsydata->d_buf = sy_buf->l64;
881 lsydata->d_size = sy_buf->nls *
883 lsydata->d_type = ELF_T_SYM;
884 lsydata->d_version = EV_CURRENT;
887 if (sy_buf->ngs > 0) {
888 if ((gsydata = elf_newdata(sy->os)) == NULL)
889 errx(EXIT_FAILURE, "elf_newdata() failed: %s.",
891 if (ecp->oec == ELFCLASS32) {
892 gsydata->d_align = 4;
893 gsydata->d_off = sy_buf->nls *
895 gsydata->d_buf = sy_buf->g32;
896 gsydata->d_size = sy_buf->ngs *
898 gsydata->d_type = ELF_T_SYM;
899 gsydata->d_version = EV_CURRENT;
901 gsydata->d_align = 8;
902 gsydata->d_off = sy_buf->nls *
904 gsydata->d_buf = sy_buf->g64;
905 gsydata->d_size = sy_buf->ngs *
907 gsydata->d_type = ELF_T_SYM;
908 gsydata->d_version = EV_CURRENT;
913 * Create two Elf_Data for .strtab, one for local symbol name
914 * and another for globals. Same as .symtab, local symbol names
918 if ((lstdata = elf_newdata(st->os)) == NULL)
919 errx(EXIT_FAILURE, "elf_newdata() failed: %s.",
921 lstdata->d_align = 1;
923 lstdata->d_buf = st_buf->l;
924 lstdata->d_size = st_buf->lsz;
925 lstdata->d_type = ELF_T_BYTE;
926 lstdata->d_version = EV_CURRENT;
928 if (st_buf->gsz > 0) {
929 if ((gstdata = elf_newdata(st->os)) == NULL)
930 errx(EXIT_FAILURE, "elf_newdata() failed: %s.",
932 gstdata->d_align = 1;
933 gstdata->d_off = lstdata->d_size;
934 gstdata->d_buf = st_buf->g;
935 gstdata->d_size = st_buf->gsz;
936 gstdata->d_type = ELF_T_BYTE;
937 gstdata->d_version = EV_CURRENT;
941 shy.sh_addralign = (ecp->oec == ELFCLASS32 ? 4 : 8);
942 shy.sh_size = sy->sz;
943 shy.sh_type = SHT_SYMTAB;
945 shy.sh_entsize = gelf_fsize(ecp->eout, ELF_T_SYM, 1,
948 * According to SYSV abi, here sh_info is one greater than
949 * the symbol table index of the last local symbol(binding
952 shy.sh_info = sy_buf->nls;
955 sht.sh_addralign = 1;
956 sht.sh_size = st->sz;
957 sht.sh_type = SHT_STRTAB;
963 if (!gelf_update_shdr(sy->os, ­))
964 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
966 if (!gelf_update_shdr(st->os, &sht))
967 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
972 add_to_symop_list(struct elfcopy *ecp, const char *name, const char *newname,
977 if ((s = lookup_symop_list(ecp, name, ~0U)) == NULL) {
978 if ((s = calloc(1, sizeof(*s))) == NULL)
979 errx(EXIT_FAILURE, "not enough memory");
981 if (op == SYMOP_REDEF)
982 s->newname = newname;
986 STAILQ_INSERT_TAIL(&ecp->v_symop, s, symop_list);
990 match_wildcard(const char *name, const char *pattern)
995 if (*pattern == '!') {
1001 if (!fnmatch(pattern, name, 0)) {
1003 printf("string '%s' match to pattern '%s'\n", name, pattern);
1006 return (reverse ? !match : match);
1010 lookup_symop_list(struct elfcopy *ecp, const char *name, unsigned int op)
1014 STAILQ_FOREACH(s, &ecp->v_symop, symop_list) {
1015 if (name == NULL || !strcmp(name, s->name) ||
1016 ((ecp->flags & WILDCARD) && match_wildcard(name, s->name)))
1017 if ((s->op & op) != 0)
1025 lookup_exact_string(const char *buf, size_t sz, const char *s)
1031 for (b = buf; b < buf + sz; b += strlen(b) + 1) {
1032 if (strlen(b) != slen)