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
37ELFTC_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. */
46struct 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
55struct sthash {
56	LIST_ENTRY(sthash) sh_next;
57	size_t sh_off;
58};
59typedef LIST_HEAD(,sthash) hash_head;
60#define STHASHSIZE 65536
61
62struct 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. */
71struct strbuf {
72	struct strimpl l;	/* local symbols */
73	struct strimpl g;	/* global symbols */
74};
75
76static int	is_debug_symbol(unsigned char st_info);
77static int	is_global_symbol(unsigned char st_info);
78static int	is_local_symbol(unsigned char st_info);
79static int	is_local_label(const char *name);
80static int	is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s);
81static int	is_remove_symbol(struct elfcopy *ecp, size_t sc, int i,
82		    GElf_Sym *s, const char *name);
83static int	is_weak_symbol(unsigned char st_info);
84static int	lookup_exact_string(hash_head *hash, const char *buf,
85		    const char *s);
86static int	generate_symbols(struct elfcopy *ecp);
87static void	mark_reloc_symbols(struct elfcopy *ecp, size_t sc);
88static void	mark_section_group_symbols(struct elfcopy *ecp, size_t sc);
89uint32_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
96static int
97is_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
107static int
108is_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
118static int
119is_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
128static int
129is_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
138static int
139is_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
149static int
150is_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 */
163static int
164is_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
187static int
188is_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 */
263static void
264mark_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
342static void
343mark_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
385static int
386generate_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
663clean:
664	free(gsym);
665	free_symtab(ecp);
666
667	return (0);
668}
669
670void
671create_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
747void
748free_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
805void
806create_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
872void
873add_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
980void
981finalize_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
1008void
1009create_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
1139void
1140add_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;
1154found:
1155	if (op == SYMOP_REDEF)
1156		s->newname = newname;
1157	s->op |= op;
1158}
1159
1160struct symop *
1161lookup_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
1191static int
1192lookup_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
1204uint32_t
1205str_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