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