xref: /freebsd/contrib/elftoolchain/elfcopy/symbols.c (revision 788ca347b816afd83b2885e0c79aeeb88649b2ab)
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, &shy) == 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, &shy))
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