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