sections.c revision 295577
1/*-
2 * Copyright (c) 2007-2011,2014 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 <sys/stat.h>
29#include <err.h>
30#include <libgen.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34
35#include "elfcopy.h"
36
37ELFTC_VCSID("$Id: sections.c 3346 2016-01-17 20:09:15Z kaiwang27 $");
38
39static void	add_gnu_debuglink(struct elfcopy *ecp);
40static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
41static void	check_section_rename(struct elfcopy *ecp, struct section *s);
42static void	filter_reloc(struct elfcopy *ecp, struct section *s);
43static int	get_section_flags(struct elfcopy *ecp, const char *name);
44static void	insert_sections(struct elfcopy *ecp);
45static void	insert_to_strtab(struct section *t, const char *s);
46static int	is_append_section(struct elfcopy *ecp, const char *name);
47static int	is_compress_section(struct elfcopy *ecp, const char *name);
48static int	is_debug_section(const char *name);
49static int	is_dwo_section(const char *name);
50static int	is_modify_section(struct elfcopy *ecp, const char *name);
51static int	is_print_section(struct elfcopy *ecp, const char *name);
52static int	lookup_string(struct section *t, const char *s);
53static void	modify_section(struct elfcopy *ecp, struct section *s);
54static void	pad_section(struct elfcopy *ecp, struct section *s);
55static void	print_data(const char *d, size_t sz);
56static void	print_section(struct section *s);
57static void	*read_section(struct section *s, size_t *size);
58static void	update_reloc(struct elfcopy *ecp, struct section *s);
59static void	update_section_group(struct elfcopy *ecp, struct section *s);
60
61int
62is_remove_section(struct elfcopy *ecp, const char *name)
63{
64
65	/* Always keep section name table */
66	if (strcmp(name, ".shstrtab") == 0)
67		return 0;
68	if (strcmp(name, ".symtab") == 0 ||
69	    strcmp(name, ".strtab") == 0) {
70		if (ecp->strip == STRIP_ALL && lookup_symop_list(
71		    ecp, NULL, SYMOP_KEEP) == NULL)
72			return (1);
73		else
74			return (0);
75	}
76
77	if (ecp->strip == STRIP_DWO && is_dwo_section(name))
78		return (1);
79	if (ecp->strip == STRIP_NONDWO && !is_dwo_section(name))
80		return (1);
81
82	if (is_debug_section(name)) {
83		if (ecp->strip == STRIP_ALL ||
84		    ecp->strip == STRIP_DEBUG ||
85		    ecp->strip == STRIP_UNNEEDED ||
86		    (ecp->flags & DISCARD_LOCAL))
87			return (1);
88		if (ecp->strip == STRIP_NONDEBUG)
89			return (0);
90	}
91
92	if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) {
93		struct sec_action *sac;
94
95		sac = lookup_sec_act(ecp, name, 0);
96		if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove)
97			return (1);
98		if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy))
99			return (1);
100	}
101
102	return (0);
103}
104
105/*
106 * Relocation section needs to be removed if the section it applies to
107 * will be removed.
108 */
109int
110is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info)
111{
112	const char	*name;
113	GElf_Shdr	 ish;
114	Elf_Scn		*is;
115	size_t		 indx;
116	int		 elferr;
117
118	if (elf_getshstrndx(ecp->ein, &indx) == 0)
119		errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
120		    elf_errmsg(-1));
121
122	is = NULL;
123	while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
124		if (sh_info == elf_ndxscn(is)) {
125			if (gelf_getshdr(is, &ish) == NULL)
126				errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
127				    elf_errmsg(-1));
128			if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) ==
129			    NULL)
130				errx(EXIT_FAILURE, "elf_strptr failed: %s",
131				    elf_errmsg(-1));
132			if (is_remove_section(ecp, name))
133				return (1);
134			else
135				return (0);
136		}
137	}
138	elferr = elf_errno();
139	if (elferr != 0)
140		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
141		    elf_errmsg(elferr));
142
143	/* Remove reloc section if we can't find the target section. */
144	return (1);
145}
146
147static int
148is_append_section(struct elfcopy *ecp, const char *name)
149{
150	struct sec_action *sac;
151
152	sac = lookup_sec_act(ecp, name, 0);
153	if (sac != NULL && sac->append != 0 && sac->string != NULL)
154		return (1);
155
156	return (0);
157}
158
159static int
160is_compress_section(struct elfcopy *ecp, const char *name)
161{
162	struct sec_action *sac;
163
164	sac = lookup_sec_act(ecp, name, 0);
165	if (sac != NULL && sac->compress != 0)
166		return (1);
167
168	return (0);
169}
170
171static void
172check_section_rename(struct elfcopy *ecp, struct section *s)
173{
174	struct sec_action *sac;
175	char *prefix;
176	size_t namelen;
177
178	if (s->pseudo)
179		return;
180
181	sac = lookup_sec_act(ecp, s->name, 0);
182	if (sac != NULL && sac->rename)
183		s->name = sac->newname;
184
185	if (!strcmp(s->name, ".symtab") ||
186	    !strcmp(s->name, ".strtab") ||
187	    !strcmp(s->name, ".shstrtab"))
188		return;
189
190	prefix = NULL;
191	if (s->loadable && ecp->prefix_alloc != NULL)
192		prefix = ecp->prefix_alloc;
193	else if (ecp->prefix_sec != NULL)
194		prefix = ecp->prefix_sec;
195
196	if (prefix != NULL) {
197		namelen = strlen(s->name) + strlen(prefix) + 1;
198		if ((s->newname = malloc(namelen)) == NULL)
199			err(EXIT_FAILURE, "malloc failed");
200		snprintf(s->newname, namelen, "%s%s", prefix, s->name);
201		s->name = s->newname;
202	}
203}
204
205static int
206get_section_flags(struct elfcopy *ecp, const char *name)
207{
208	struct sec_action *sac;
209
210	sac = lookup_sec_act(ecp, name, 0);
211	if (sac != NULL && sac->flags)
212		return sac->flags;
213
214	return (0);
215}
216
217/*
218 * Determine whether the section are debugging section.
219 * According to libbfd, debugging sections are recognized
220 * only by name.
221 */
222static int
223is_debug_section(const char *name)
224{
225	const char *dbg_sec[] = {
226		".apple_",
227		".debug",
228		".gnu.linkonce.wi.",
229		".line",
230		".stab",
231		NULL
232	};
233	const char **p;
234
235	for(p = dbg_sec; *p; p++) {
236		if (strncmp(name, *p, strlen(*p)) == 0)
237			return (1);
238	}
239
240	return (0);
241}
242
243static int
244is_dwo_section(const char *name)
245{
246	size_t len;
247
248	if ((len = strlen(name)) > 4 && strcmp(name + len - 4, ".dwo") == 0)
249		return (1);
250	return (0);
251}
252
253static int
254is_print_section(struct elfcopy *ecp, const char *name)
255{
256	struct sec_action *sac;
257
258	sac = lookup_sec_act(ecp, name, 0);
259	if (sac != NULL && sac->print != 0)
260		return (1);
261
262	return (0);
263}
264
265static int
266is_modify_section(struct elfcopy *ecp, const char *name)
267{
268
269	if (is_append_section(ecp, name) ||
270	    is_compress_section(ecp, name))
271		return (1);
272
273	return (0);
274}
275
276struct sec_action*
277lookup_sec_act(struct elfcopy *ecp, const char *name, int add)
278{
279	struct sec_action *sac;
280
281	if (name == NULL)
282		return NULL;
283
284	STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) {
285		if (strcmp(name, sac->name) == 0)
286			return sac;
287	}
288
289	if (add == 0)
290		return NULL;
291
292	if ((sac = malloc(sizeof(*sac))) == NULL)
293		errx(EXIT_FAILURE, "not enough memory");
294	memset(sac, 0, sizeof(*sac));
295	sac->name = name;
296	STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list);
297
298	return (sac);
299}
300
301void
302free_sec_act(struct elfcopy *ecp)
303{
304	struct sec_action *sac, *sac_temp;
305
306	STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) {
307		STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list);
308		free(sac);
309	}
310}
311
312void
313insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail)
314{
315	struct section *s;
316
317	if (!tail) {
318		TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
319			if (sec->off < s->off) {
320				TAILQ_INSERT_BEFORE(s, sec, sec_list);
321				goto inc_nos;
322			}
323		}
324	}
325
326	TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list);
327
328inc_nos:
329	if (sec->pseudo == 0)
330		ecp->nos++;
331}
332
333/*
334 * First step of section creation: create scn and internal section
335 * structure, discard sections to be removed.
336 */
337void
338create_scn(struct elfcopy *ecp)
339{
340	struct section	*s;
341	const char	*name;
342	Elf_Scn		*is;
343	GElf_Shdr	 ish;
344	size_t		 indx;
345	uint64_t	 oldndx, newndx;
346	int		 elferr, sec_flags;
347
348	/*
349	 * Insert a pseudo section that contains the ELF header
350	 * and program header. Used as reference for section offset
351	 * or load address adjustment.
352	 */
353	if ((s = calloc(1, sizeof(*s))) == NULL)
354		err(EXIT_FAILURE, "calloc failed");
355	s->off = 0;
356	s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) +
357	    gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT);
358	s->align = 1;
359	s->pseudo = 1;
360	s->loadable = add_to_inseg_list(ecp, s);
361	insert_to_sec_list(ecp, s, 0);
362
363	/* Create internal .shstrtab section. */
364	init_shstrtab(ecp);
365
366	if (elf_getshstrndx(ecp->ein, &indx) == 0)
367		errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
368		    elf_errmsg(-1));
369
370	is = NULL;
371	while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
372		if (gelf_getshdr(is, &ish) == NULL)
373			errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
374			    elf_errmsg(-1));
375		if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL)
376			errx(EXIT_FAILURE, "elf_strptr failed: %s",
377			    elf_errmsg(-1));
378
379		/* Skip sections to be removed. */
380		if (is_remove_section(ecp, name))
381			continue;
382
383		/*
384		 * Relocation section need to be remove if the section
385		 * it applies will be removed.
386		 */
387		if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
388			if (ish.sh_info != 0 &&
389			    is_remove_reloc_sec(ecp, ish.sh_info))
390				continue;
391
392		/*
393		 * Section groups should be removed if symbol table will
394		 * be removed. (section group's signature stored in symbol
395		 * table)
396		 */
397		if (ish.sh_type == SHT_GROUP && ecp->strip == STRIP_ALL)
398			continue;
399
400		/* Get section flags set by user. */
401		sec_flags = get_section_flags(ecp, name);
402
403		/* Create internal section object. */
404		if (strcmp(name, ".shstrtab") != 0) {
405			if ((s = calloc(1, sizeof(*s))) == NULL)
406				err(EXIT_FAILURE, "calloc failed");
407			s->name		= name;
408			s->is		= is;
409			s->off		= ish.sh_offset;
410			s->sz		= ish.sh_size;
411			s->align	= ish.sh_addralign;
412			s->type		= ish.sh_type;
413			s->vma		= ish.sh_addr;
414
415			/*
416			 * Search program headers to determine whether section
417			 * is loadable, but if user explicitly set section flags
418			 * while neither "load" nor "alloc" is set, we make the
419			 * section unloadable.
420			 *
421			 * Sections in relocatable object is loadable if
422			 * section flag SHF_ALLOC is set.
423			 */
424			if (sec_flags &&
425			    (sec_flags & (SF_LOAD | SF_ALLOC)) == 0)
426				s->loadable = 0;
427			else {
428				s->loadable = add_to_inseg_list(ecp, s);
429				if ((ecp->flags & RELOCATABLE) &&
430				    (ish.sh_flags & SHF_ALLOC))
431					s->loadable = 1;
432			}
433		} else {
434			/* Assuming .shstrtab is "unloadable". */
435			s		= ecp->shstrtab;
436			s->off		= ish.sh_offset;
437		}
438
439		oldndx = newndx = SHN_UNDEF;
440		if (strcmp(name, ".symtab") != 0 &&
441		    strcmp(name, ".strtab") != 0) {
442			if (!strcmp(name, ".shstrtab")) {
443				/*
444				 * Add sections specified by --add-section and
445				 * gnu debuglink. we want these sections have
446				 * smaller index than .shstrtab section.
447				 */
448				if (ecp->debuglink != NULL)
449					add_gnu_debuglink(ecp);
450				if (ecp->flags & SEC_ADD)
451					insert_sections(ecp);
452			}
453 			if ((s->os = elf_newscn(ecp->eout)) == NULL)
454				errx(EXIT_FAILURE, "elf_newscn failed: %s",
455				    elf_errmsg(-1));
456			if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF)
457				errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
458				    elf_errmsg(-1));
459		}
460		if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF)
461			errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
462			    elf_errmsg(-1));
463		if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF)
464			ecp->secndx[oldndx] = newndx;
465
466		/*
467		 * If strip action is STRIP_NONDEBUG(only keep debug),
468		 * change sections type of loadable sections and section
469		 * groups to SHT_NOBITS, and the content of those sections
470		 * will be discarded. However, SHT_NOTE sections should
471		 * be kept.
472		 */
473		if (ecp->strip == STRIP_NONDEBUG) {
474			if (((ish.sh_flags & SHF_ALLOC) ||
475			    (ish.sh_flags & SHF_GROUP)) &&
476			    ish.sh_type != SHT_NOTE)
477				s->type = SHT_NOBITS;
478		}
479
480		check_section_rename(ecp, s);
481
482		/* create section header based on input object. */
483		if (strcmp(name, ".symtab") != 0 &&
484		    strcmp(name, ".strtab") != 0 &&
485		    strcmp(name, ".shstrtab") != 0)
486			copy_shdr(ecp, s, NULL, 0, sec_flags);
487
488		if (strcmp(name, ".symtab") == 0) {
489			ecp->flags |= SYMTAB_EXIST;
490			ecp->symtab = s;
491		}
492		if (strcmp(name, ".strtab") == 0)
493			ecp->strtab = s;
494
495		insert_to_sec_list(ecp, s, 0);
496	}
497	elferr = elf_errno();
498	if (elferr != 0)
499		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
500		    elf_errmsg(elferr));
501}
502
503struct section *
504insert_shtab(struct elfcopy *ecp, int tail)
505{
506	struct section	*s, *shtab;
507	GElf_Ehdr	 ieh;
508	int		 nsecs;
509
510	/*
511	 * Treat section header table as a "pseudo" section, insert it
512	 * into section list, so later it will get sorted and resynced
513	 * just as normal sections.
514	 */
515	if ((shtab = calloc(1, sizeof(*shtab))) == NULL)
516		errx(EXIT_FAILURE, "calloc failed");
517	if (!tail) {
518		/*
519		 * "shoff" of input object is used as a hint for section
520		 * resync later.
521		 */
522		if (gelf_getehdr(ecp->ein, &ieh) == NULL)
523			errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
524			    elf_errmsg(-1));
525		shtab->off = ieh.e_shoff;
526	} else
527		shtab->off = 0;
528	/* Calculate number of sections in the output object. */
529	nsecs = 0;
530	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
531		if (!s->pseudo)
532			nsecs++;
533	}
534	/* Remember there is always a null section, so we +1 here. */
535	shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT);
536	if (shtab->sz == 0)
537		errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1));
538	shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8);
539	shtab->loadable = 0;
540	shtab->pseudo = 1;
541	insert_to_sec_list(ecp, shtab, tail);
542
543	return (shtab);
544}
545
546void
547copy_content(struct elfcopy *ecp)
548{
549	struct section *s;
550
551	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
552		/* Skip pseudo section. */
553		if (s->pseudo)
554			continue;
555
556		/* Skip special sections. */
557		if (strcmp(s->name, ".symtab") == 0 ||
558		    strcmp(s->name, ".strtab") == 0 ||
559		    strcmp(s->name, ".shstrtab") == 0)
560			continue;
561
562		/*
563		 * If strip action is STRIP_ALL, relocation info need
564		 * to be stripped. Skip filtering otherwisw.
565		 */
566		if (ecp->strip == STRIP_ALL &&
567		    (s->type == SHT_REL || s->type == SHT_RELA))
568			filter_reloc(ecp, s);
569
570		/*
571		 * The section indices in the SHT_GROUP section needs
572		 * to be updated since we might have stripped some
573		 * sections and changed section numbering.
574		 */
575		if (s->type == SHT_GROUP)
576			update_section_group(ecp, s);
577
578		if (is_modify_section(ecp, s->name))
579			modify_section(ecp, s);
580
581		copy_data(s);
582
583		/*
584		 * If symbol table is modified, relocation info might
585		 * need update, as symbol index may have changed.
586		 */
587		if ((ecp->flags & SYMTAB_INTACT) == 0 &&
588		    (ecp->flags & SYMTAB_EXIST) &&
589		    (s->type == SHT_REL || s->type == SHT_RELA))
590			update_reloc(ecp, s);
591
592		if (is_print_section(ecp, s->name))
593			print_section(s);
594	}
595}
596
597
598/*
599 * Update section group section. The section indices in the SHT_GROUP
600 * section need update after section numbering changed.
601 */
602static void
603update_section_group(struct elfcopy *ecp, struct section *s)
604{
605	GElf_Shdr	 ish;
606	Elf_Data	*id;
607	uint32_t	*ws, *wd;
608	uint64_t	 n;
609	size_t		 ishnum;
610	int		 i, j;
611
612	if (!elf_getshnum(ecp->ein, &ishnum))
613		errx(EXIT_FAILURE, "elf_getshnum failed: %s",
614		    elf_errmsg(-1));
615
616	if (gelf_getshdr(s->is, &ish) == NULL)
617		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
618		    elf_errmsg(-1));
619
620	if ((id = elf_getdata(s->is, NULL)) == NULL)
621		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
622		    elf_errmsg(-1));
623
624	if (ish.sh_size == 0)
625		return;
626
627	if (ish.sh_entsize == 0)
628		ish.sh_entsize = 4;
629
630	ws = id->d_buf;
631
632	/* We only support COMDAT section. */
633#ifndef GRP_COMDAT
634#define	GRP_COMDAT 0x1
635#endif
636	if ((*ws & GRP_COMDAT) == 0)
637		return;
638
639	if ((s->buf = malloc(ish.sh_size)) == NULL)
640		err(EXIT_FAILURE, "malloc failed");
641
642	s->sz = ish.sh_size;
643
644	wd = s->buf;
645
646	/* Copy the flag word as-is. */
647	*wd = *ws;
648
649	/* Update the section indices. */
650	n = ish.sh_size / ish.sh_entsize;
651	for(i = 1, j = 1; (uint64_t)i < n; i++) {
652		if (ws[i] != SHN_UNDEF && ws[i] < ishnum &&
653		    ecp->secndx[ws[i]] != 0)
654			wd[j++] = ecp->secndx[ws[i]];
655		else
656			s->sz -= 4;
657	}
658
659	s->nocopy = 1;
660}
661
662/*
663 * Filter relocation entries, only keep those entries whose
664 * symbol is in the keep list.
665 */
666static void
667filter_reloc(struct elfcopy *ecp, struct section *s)
668{
669	const char	*name;
670	GElf_Shdr	 ish;
671	GElf_Rel	 rel;
672	GElf_Rela	 rela;
673	Elf32_Rel	*rel32;
674	Elf64_Rel	*rel64;
675	Elf32_Rela	*rela32;
676	Elf64_Rela	*rela64;
677	Elf_Data	*id;
678	uint64_t	 cap, n, nrels;
679	int		 elferr, i;
680
681	if (gelf_getshdr(s->is, &ish) == NULL)
682		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
683		    elf_errmsg(-1));
684
685	/* We don't want to touch relocation info for dynamic symbols. */
686	if ((ecp->flags & SYMTAB_EXIST) == 0) {
687		if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) {
688			/*
689			 * This reloc section applies to the symbol table
690			 * that was stripped, so discard whole section.
691			 */
692			s->nocopy = 1;
693			s->sz = 0;
694		}
695		return;
696	} else {
697		/* Symbol table exist, check if index equals. */
698		if (ish.sh_link != elf_ndxscn(ecp->symtab->is))
699			return;
700	}
701
702#define	COPYREL(REL, SZ) do {					\
703	if (nrels == 0) {					\
704		if ((REL##SZ = malloc(cap *			\
705		    sizeof(Elf##SZ##_Rel))) == NULL)		\
706			err(EXIT_FAILURE, "malloc failed");	\
707	}							\
708	if (nrels >= cap) {					\
709		cap *= 2;					\
710		if ((REL##SZ = realloc(REL##SZ, cap *		\
711		    sizeof(Elf##SZ##_Rel))) == NULL)		\
712			err(EXIT_FAILURE, "realloc failed");	\
713	}							\
714	REL##SZ[nrels].r_offset = REL.r_offset;			\
715	REL##SZ[nrels].r_info	= REL.r_info;			\
716	if (s->type == SHT_RELA)				\
717		rela##SZ[nrels].r_addend = rela.r_addend;	\
718	nrels++;						\
719} while (0)
720
721	nrels = 0;
722	cap = 4;		/* keep list is usually small. */
723	rel32 = NULL;
724	rel64 = NULL;
725	rela32 = NULL;
726	rela64 = NULL;
727	if ((id = elf_getdata(s->is, NULL)) == NULL)
728		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
729		    elf_errmsg(-1));
730	n = ish.sh_size / ish.sh_entsize;
731	for(i = 0; (uint64_t)i < n; i++) {
732		if (s->type == SHT_REL) {
733			if (gelf_getrel(id, i, &rel) != &rel)
734				errx(EXIT_FAILURE, "gelf_getrel failed: %s",
735				    elf_errmsg(-1));
736		} else {
737			if (gelf_getrela(id, i, &rela) != &rela)
738				errx(EXIT_FAILURE, "gelf_getrel failed: %s",
739				    elf_errmsg(-1));
740		}
741		name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is),
742		    GELF_R_SYM(rel.r_info));
743		if (name == NULL)
744			errx(EXIT_FAILURE, "elf_strptr failed: %s",
745			    elf_errmsg(-1));
746		if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) {
747			if (ecp->oec == ELFCLASS32) {
748				if (s->type == SHT_REL)
749					COPYREL(rel, 32);
750				else
751					COPYREL(rela, 32);
752			} else {
753				if (s->type == SHT_REL)
754					COPYREL(rel, 64);
755				else
756					COPYREL(rela, 64);
757			}
758		}
759	}
760	elferr = elf_errno();
761	if (elferr != 0)
762		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
763		    elf_errmsg(elferr));
764
765	if (ecp->oec == ELFCLASS32) {
766		if (s->type == SHT_REL)
767			s->buf = rel32;
768		else
769			s->buf = rela32;
770	} else {
771		if (s->type == SHT_REL)
772			s->buf = rel64;
773		else
774			s->buf = rela64;
775	}
776	s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL :
777	    ELF_T_RELA), nrels, EV_CURRENT);
778	s->nocopy = 1;
779}
780
781static void
782update_reloc(struct elfcopy *ecp, struct section *s)
783{
784	GElf_Shdr	 osh;
785	GElf_Rel	 rel;
786	GElf_Rela	 rela;
787	Elf_Data	*od;
788	uint64_t	 n;
789	int		 i;
790
791#define UPDATEREL(REL) do {						\
792	if (gelf_get##REL(od, i, &REL) != &REL)				\
793		errx(EXIT_FAILURE, "gelf_get##REL failed: %s",		\
794		    elf_errmsg(-1));					\
795	REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)],	\
796	    GELF_R_TYPE(REL.r_info));					\
797	if (!gelf_update_##REL(od, i, &REL))				\
798		errx(EXIT_FAILURE, "gelf_update_##REL failed: %s",	\
799		    elf_errmsg(-1));					\
800} while(0)
801
802	if (s->sz == 0)
803		return;
804	if (gelf_getshdr(s->os, &osh) == NULL)
805		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
806		    elf_errmsg(-1));
807	/* Only process .symtab reloc info. */
808	if (osh.sh_link != elf_ndxscn(ecp->symtab->is))
809		return;
810	if ((od = elf_getdata(s->os, NULL)) == NULL)
811		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
812		    elf_errmsg(-1));
813	n = osh.sh_size / osh.sh_entsize;
814	for(i = 0; (uint64_t)i < n; i++) {
815		if (s->type == SHT_REL)
816			UPDATEREL(rel);
817		else
818			UPDATEREL(rela);
819	}
820}
821
822static void
823pad_section(struct elfcopy *ecp, struct section *s)
824{
825	GElf_Shdr	 osh;
826	Elf_Data	*od;
827
828	if (s == NULL || s->pad_sz == 0)
829		return;
830
831	if ((s->pad = malloc(s->pad_sz)) == NULL)
832		err(EXIT_FAILURE, "malloc failed");
833	memset(s->pad, ecp->fill, s->pad_sz);
834
835	/* Create a new Elf_Data to contain the padding bytes. */
836	if ((od = elf_newdata(s->os)) == NULL)
837		errx(EXIT_FAILURE, "elf_newdata() failed: %s",
838		    elf_errmsg(-1));
839	od->d_align = 1;
840	od->d_off = s->sz;
841	od->d_buf = s->pad;
842	od->d_type = ELF_T_BYTE;
843	od->d_size = s->pad_sz;
844	od->d_version = EV_CURRENT;
845
846	/* Update section header. */
847	if (gelf_getshdr(s->os, &osh) == NULL)
848		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
849		    elf_errmsg(-1));
850	osh.sh_size = s->sz + s->pad_sz;
851	if (!gelf_update_shdr(s->os, &osh))
852		errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
853		    elf_errmsg(-1));
854}
855
856void
857resync_sections(struct elfcopy *ecp)
858{
859	struct section	*s, *ps;
860	GElf_Shdr	 osh;
861	uint64_t	 off;
862	int		 first;
863
864	ps = NULL;
865	first = 1;
866	off = 0;
867	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
868		if (first) {
869			off = s->off;
870			first = 0;
871		}
872
873		/*
874		 * Ignore TLS sections with load address 0 and without
875		 * content. We don't need to adjust their file offset or
876		 * VMA, only the size matters.
877		 */
878		if (s->seg_tls != NULL && s->type == SHT_NOBITS &&
879		    s->off == 0)
880			continue;
881
882		/* Align section offset. */
883		if (s->align == 0)
884			s->align = 1;
885		if (off <= s->off) {
886			if (!s->loadable || (ecp->flags & RELOCATABLE))
887				s->off = roundup(off, s->align);
888		} else {
889			if (s->loadable && (ecp->flags & RELOCATABLE) == 0)
890				warnx("moving loadable section %s, "
891				    "is this intentional?", s->name);
892			s->off = roundup(off, s->align);
893		}
894
895		/* Calculate next section offset. */
896		off = s->off;
897		if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL))
898			off += s->sz;
899
900		if (s->pseudo) {
901			ps = NULL;
902			continue;
903		}
904
905		/* Count padding bytes added through --pad-to. */
906		if (s->pad_sz > 0)
907			off += s->pad_sz;
908
909		/* Update section header accordingly. */
910		if (gelf_getshdr(s->os, &osh) == NULL)
911			errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
912			    elf_errmsg(-1));
913		osh.sh_addr = s->vma;
914		osh.sh_offset = s->off;
915		osh.sh_size = s->sz;
916		if (!gelf_update_shdr(s->os, &osh))
917			errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
918			    elf_errmsg(-1));
919
920		/* Add padding for previous section, if need. */
921		if (ps != NULL) {
922			if (ps->pad_sz > 0) {
923				/* Apply padding added by --pad-to. */
924				pad_section(ecp, ps);
925			} else if ((ecp->flags & GAP_FILL) &&
926			    (ps->off + ps->sz < s->off)) {
927				/*
928				 * Fill the gap between sections by padding
929				 * the section with lower address.
930				 */
931				ps->pad_sz = s->off - (ps->off + ps->sz);
932				pad_section(ecp, ps);
933			}
934		}
935
936		ps = s;
937	}
938
939	/* Pad the last section, if need. */
940	if (ps != NULL && ps->pad_sz > 0)
941		pad_section(ecp, ps);
942}
943
944static void
945modify_section(struct elfcopy *ecp, struct section *s)
946{
947	struct sec_action	*sac;
948	size_t			 srcsz, dstsz, p, len;
949	char			*b, *c, *d, *src, *end;
950	int			 dupe;
951
952	src = read_section(s, &srcsz);
953	if (src == NULL || srcsz == 0) {
954		/* For empty section, we proceed if we need to append. */
955		if (!is_append_section(ecp, s->name))
956			return;
957	}
958
959	/* Allocate buffer needed for new section data. */
960	dstsz = srcsz;
961	if (is_append_section(ecp, s->name)) {
962		sac = lookup_sec_act(ecp, s->name, 0);
963		dstsz += strlen(sac->string) + 1;
964	}
965	if ((b = malloc(dstsz)) == NULL)
966		err(EXIT_FAILURE, "malloc failed");
967	s->buf = b;
968
969	/* Compress section. */
970	p = 0;
971	if (is_compress_section(ecp, s->name)) {
972		end = src + srcsz;
973		for(c = src; c < end;) {
974			len = 0;
975			while(c + len < end && c[len] != '\0')
976				len++;
977			if (c + len == end) {
978				/* XXX should we warn here? */
979				strncpy(&b[p], c, len);
980				p += len;
981				break;
982			}
983			dupe = 0;
984			for (d = b; d < b + p; ) {
985				if (strcmp(d, c) == 0) {
986					dupe = 1;
987					break;
988				}
989				d += strlen(d) + 1;
990			}
991			if (!dupe) {
992				strncpy(&b[p], c, len);
993				b[p + len] = '\0';
994				p += len + 1;
995			}
996			c += len + 1;
997		}
998	} else {
999		memcpy(b, src, srcsz);
1000		p += srcsz;
1001	}
1002
1003	/* Append section. */
1004	if (is_append_section(ecp, s->name)) {
1005		sac = lookup_sec_act(ecp, s->name, 0);
1006		len = strlen(sac->string);
1007		strncpy(&b[p], sac->string, len);
1008		b[p + len] = '\0';
1009		p += len + 1;
1010	}
1011
1012	s->sz = p;
1013	s->nocopy = 1;
1014}
1015
1016static void
1017print_data(const char *d, size_t sz)
1018{
1019	const char *c;
1020
1021	for (c = d; c < d + sz; c++) {
1022		if (*c == '\0')
1023			putchar('\n');
1024		else
1025			putchar(*c);
1026	}
1027}
1028
1029static void
1030print_section(struct section *s)
1031{
1032	Elf_Data	*id;
1033	int		 elferr;
1034
1035	if (s->buf != NULL && s->sz > 0) {
1036		print_data(s->buf, s->sz);
1037	} else {
1038		id = NULL;
1039		while ((id = elf_getdata(s->is, id)) != NULL ||
1040		    (id = elf_rawdata(s->is, id)) != NULL) {
1041			(void) elf_errno();
1042			print_data(id->d_buf, id->d_size);
1043		}
1044		elferr = elf_errno();
1045		if (elferr != 0)
1046			errx(EXIT_FAILURE, "elf_getdata() failed: %s",
1047			    elf_errmsg(elferr));
1048	}
1049	putchar('\n');
1050}
1051
1052static void *
1053read_section(struct section *s, size_t *size)
1054{
1055	Elf_Data	*id;
1056	char		*b;
1057	size_t		 sz;
1058	int		 elferr;
1059
1060	sz = 0;
1061	b = NULL;
1062	id = NULL;
1063	while ((id = elf_getdata(s->is, id)) != NULL ||
1064	    (id = elf_rawdata(s->is, id)) != NULL) {
1065		(void) elf_errno();
1066		if (b == NULL)
1067			b = malloc(id->d_size);
1068		else
1069			b = malloc(sz + id->d_size);
1070		if (b == NULL)
1071			err(EXIT_FAILURE, "malloc or realloc failed");
1072
1073		memcpy(&b[sz], id->d_buf, id->d_size);
1074		sz += id->d_size;
1075	}
1076	elferr = elf_errno();
1077	if (elferr != 0)
1078		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
1079		    elf_errmsg(elferr));
1080
1081	*size = sz;
1082
1083	return (b);
1084}
1085
1086void
1087copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
1088    int sec_flags)
1089{
1090	GElf_Shdr ish, osh;
1091
1092	if (gelf_getshdr(s->is, &ish) == NULL)
1093		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1094		    elf_errmsg(-1));
1095	if (gelf_getshdr(s->os, &osh) == NULL)
1096		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1097		    elf_errmsg(-1));
1098
1099	if (copy)
1100		(void) memcpy(&osh, &ish, sizeof(ish));
1101	else {
1102		osh.sh_type		= s->type;
1103		osh.sh_addr		= s->vma;
1104		osh.sh_offset		= s->off;
1105		osh.sh_size		= s->sz;
1106		osh.sh_link		= ish.sh_link;
1107		osh.sh_info		= ish.sh_info;
1108		osh.sh_addralign	= s->align;
1109		osh.sh_entsize		= ish.sh_entsize;
1110
1111		if (sec_flags) {
1112			osh.sh_flags = 0;
1113			if (sec_flags & SF_ALLOC)
1114				osh.sh_flags |= SHF_ALLOC;
1115			if ((sec_flags & SF_READONLY) == 0)
1116				osh.sh_flags |= SHF_WRITE;
1117			if (sec_flags & SF_CODE)
1118				osh.sh_flags |= SHF_EXECINSTR;
1119			if ((sec_flags & SF_CONTENTS) &&
1120			    s->type == SHT_NOBITS && s->sz > 0) {
1121				/*
1122				 * Convert SHT_NOBITS section to section with
1123				 * (zero'ed) content on file.
1124				 */
1125				osh.sh_type = s->type = SHT_PROGBITS;
1126				if ((s->buf = calloc(1, s->sz)) == NULL)
1127					err(EXIT_FAILURE, "malloc failed");
1128				s->nocopy = 1;
1129			}
1130		} else {
1131			osh.sh_flags = ish.sh_flags;
1132			/*
1133			 * Newer binutils as(1) emits the section flag
1134			 * SHF_INFO_LINK for relocation sections. elfcopy
1135			 * emits this flag in the output section if it's
1136			 * missing in the input section, to remain compatible
1137			 * with binutils.
1138			 */
1139			if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
1140				osh.sh_flags |= SHF_INFO_LINK;
1141		}
1142	}
1143
1144	if (name == NULL)
1145		add_to_shstrtab(ecp, s->name);
1146	else
1147		add_to_shstrtab(ecp, name);
1148
1149	if (!gelf_update_shdr(s->os, &osh))
1150		errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
1151		    elf_errmsg(-1));
1152}
1153
1154void
1155copy_data(struct section *s)
1156{
1157	Elf_Data	*id, *od;
1158	int		 elferr;
1159
1160	if (s->nocopy && s->buf == NULL)
1161		return;
1162
1163	if ((id = elf_getdata(s->is, NULL)) == NULL) {
1164		(void) elf_errno();
1165		if ((id = elf_rawdata(s->is, NULL)) == NULL) {
1166			elferr = elf_errno();
1167			if (elferr != 0)
1168				errx(EXIT_FAILURE, "failed to read section:"
1169				    " %s", s->name);
1170			return;
1171		}
1172	}
1173
1174	if ((od = elf_newdata(s->os)) == NULL)
1175		errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1176		    elf_errmsg(-1));
1177
1178	if (s->nocopy) {
1179		/* Use s->buf as content if s->nocopy is set. */
1180		od->d_align	= id->d_align;
1181		od->d_off	= 0;
1182		od->d_buf	= s->buf;
1183		od->d_type	= id->d_type;
1184		od->d_size	= s->sz;
1185		od->d_version	= id->d_version;
1186	} else {
1187		od->d_align	= id->d_align;
1188		od->d_off	= id->d_off;
1189		od->d_buf	= id->d_buf;
1190		od->d_type	= id->d_type;
1191		od->d_size	= id->d_size;
1192		od->d_version	= id->d_version;
1193	}
1194
1195	/*
1196	 * Alignment Fixup. libelf does not allow the alignment for
1197	 * Elf_Data descriptor to be set to 0. In this case we workaround
1198	 * it by setting the alignment to 1.
1199	 *
1200	 * According to the ELF ABI, alignment 0 and 1 has the same
1201	 * meaning: the section has no alignment constraints.
1202	 */
1203	if (od->d_align == 0)
1204		od->d_align = 1;
1205}
1206
1207struct section *
1208create_external_section(struct elfcopy *ecp, const char *name, char *newname,
1209    void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype,
1210    uint64_t flags, uint64_t align, uint64_t vma, int loadable)
1211{
1212	struct section	*s;
1213	Elf_Scn		*os;
1214	Elf_Data	*od;
1215	GElf_Shdr	 osh;
1216
1217	if ((os = elf_newscn(ecp->eout)) == NULL)
1218		errx(EXIT_FAILURE, "elf_newscn() failed: %s",
1219		    elf_errmsg(-1));
1220	if ((s = calloc(1, sizeof(*s))) == NULL)
1221		err(EXIT_FAILURE, "calloc failed");
1222	s->name = name;
1223	s->newname = newname;	/* needs to be free()'ed */
1224	s->off = off;
1225	s->sz = size;
1226	s->vma = vma;
1227	s->align = align;
1228	s->loadable = loadable;
1229	s->is = NULL;
1230	s->os = os;
1231	s->type = stype;
1232	s->nocopy = 1;
1233	insert_to_sec_list(ecp, s, 1);
1234
1235	if (gelf_getshdr(os, &osh) == NULL)
1236		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1237		    elf_errmsg(-1));
1238	osh.sh_flags = flags;
1239	osh.sh_type = s->type;
1240	osh.sh_addr = s->vma;
1241	osh.sh_addralign = s->align;
1242	if (!gelf_update_shdr(os, &osh))
1243		errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1244		    elf_errmsg(-1));
1245	add_to_shstrtab(ecp, name);
1246
1247	if (buf != NULL && size != 0) {
1248		if ((od = elf_newdata(os)) == NULL)
1249			errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1250			    elf_errmsg(-1));
1251		od->d_align = align;
1252		od->d_off = 0;
1253		od->d_buf = buf;
1254		od->d_size = size;
1255		od->d_type = dtype;
1256		od->d_version = EV_CURRENT;
1257	}
1258
1259	/*
1260	 * Clear SYMTAB_INTACT, as we probably need to update/add new
1261	 * STT_SECTION symbols into the symbol table.
1262	 */
1263	ecp->flags &= ~SYMTAB_INTACT;
1264
1265	return (s);
1266}
1267
1268/*
1269 * Insert sections specified by --add-section to the end of section list.
1270 */
1271static void
1272insert_sections(struct elfcopy *ecp)
1273{
1274	struct sec_add	*sa;
1275	struct section	*s;
1276	size_t		 off;
1277	uint64_t	 stype;
1278
1279	/* Put these sections in the end of current list. */
1280	off = 0;
1281	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
1282		if (s->type != SHT_NOBITS && s->type != SHT_NULL)
1283			off = s->off + s->sz;
1284		else
1285			off = s->off;
1286	}
1287
1288	STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) {
1289
1290		/* TODO: Add section header vma/lma, flag changes here */
1291
1292		/*
1293		 * The default section type for user added section is
1294		 * SHT_PROGBITS. If the section name match certain patterns,
1295		 * elfcopy will try to set a more appropriate section type.
1296		 * However, data type is always set to ELF_T_BYTE and no
1297		 * translation is performed by libelf.
1298		 */
1299		stype = SHT_PROGBITS;
1300		if (strcmp(sa->name, ".note") == 0 ||
1301		    strncmp(sa->name, ".note.", strlen(".note.")) == 0)
1302			stype = SHT_NOTE;
1303
1304		(void) create_external_section(ecp, sa->name, NULL, sa->content,
1305		    sa->size, off, stype, ELF_T_BYTE, 0, 1, 0, 0);
1306	}
1307}
1308
1309void
1310add_to_shstrtab(struct elfcopy *ecp, const char *name)
1311{
1312	struct section *s;
1313
1314	s = ecp->shstrtab;
1315	insert_to_strtab(s, name);
1316}
1317
1318void
1319update_shdr(struct elfcopy *ecp, int update_link)
1320{
1321	struct section	*s;
1322	GElf_Shdr	 osh;
1323	int		 elferr;
1324
1325	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
1326		if (s->pseudo)
1327			continue;
1328
1329		if (gelf_getshdr(s->os, &osh) == NULL)
1330			errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
1331			    elf_errmsg(-1));
1332
1333		/* Find section name in string table and set sh_name. */
1334		osh.sh_name = lookup_string(ecp->shstrtab, s->name);
1335
1336		/*
1337		 * sh_link needs to be updated, since the index of the
1338		 * linked section might have changed.
1339		 */
1340		if (update_link && osh.sh_link != 0)
1341			osh.sh_link = ecp->secndx[osh.sh_link];
1342
1343		/*
1344		 * sh_info of relocation section links to the section to which
1345		 * its relocation info applies. So it may need update as well.
1346		 */
1347		if ((s->type == SHT_REL || s->type == SHT_RELA) &&
1348		    osh.sh_info != 0)
1349			osh.sh_info = ecp->secndx[osh.sh_info];
1350
1351		/*
1352		 * sh_info of SHT_GROUP section needs to point to the correct
1353		 * string in the symbol table.
1354		 */
1355		if (s->type == SHT_GROUP && (ecp->flags & SYMTAB_EXIST) &&
1356		    (ecp->flags & SYMTAB_INTACT) == 0)
1357			osh.sh_info = ecp->symndx[osh.sh_info];
1358
1359		if (!gelf_update_shdr(s->os, &osh))
1360			errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1361			    elf_errmsg(-1));
1362	}
1363	elferr = elf_errno();
1364	if (elferr != 0)
1365		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
1366		    elf_errmsg(elferr));
1367}
1368
1369void
1370init_shstrtab(struct elfcopy *ecp)
1371{
1372	struct section *s;
1373
1374	if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL)
1375		err(EXIT_FAILURE, "calloc failed");
1376	s = ecp->shstrtab;
1377	s->name = ".shstrtab";
1378	s->is = NULL;
1379	s->sz = 0;
1380	s->align = 1;
1381	s->loadable = 0;
1382	s->type = SHT_STRTAB;
1383	s->vma = 0;
1384
1385	insert_to_strtab(s, "");
1386	insert_to_strtab(s, ".symtab");
1387	insert_to_strtab(s, ".strtab");
1388	insert_to_strtab(s, ".shstrtab");
1389}
1390
1391void
1392set_shstrtab(struct elfcopy *ecp)
1393{
1394	struct section	*s;
1395	Elf_Data	*data;
1396	GElf_Shdr	 sh;
1397
1398	s = ecp->shstrtab;
1399
1400	if (s->os == NULL) {
1401		/* Input object does not contain .shstrtab section */
1402		if ((s->os = elf_newscn(ecp->eout)) == NULL)
1403			errx(EXIT_FAILURE, "elf_newscn failed: %s",
1404			    elf_errmsg(-1));
1405		insert_to_sec_list(ecp, s, 1);
1406	}
1407
1408	if (gelf_getshdr(s->os, &sh) == NULL)
1409		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1410		    elf_errmsg(-1));
1411	sh.sh_addr	= 0;
1412	sh.sh_addralign	= 1;
1413	sh.sh_offset	= s->off;
1414	sh.sh_type	= SHT_STRTAB;
1415	sh.sh_flags	= 0;
1416	sh.sh_entsize	= 0;
1417	sh.sh_info	= 0;
1418	sh.sh_link	= 0;
1419
1420	if ((data = elf_newdata(s->os)) == NULL)
1421		errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1422		    elf_errmsg(-1));
1423
1424	/*
1425	 * If we don't have a symbol table, skip those a few bytes
1426	 * which are reserved for this in the beginning of shstrtab.
1427	 */
1428	if (!(ecp->flags & SYMTAB_EXIST)) {
1429		s->sz -= sizeof(".symtab\0.strtab");
1430		memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"),
1431		    s->sz);
1432	}
1433
1434	sh.sh_size	= s->sz;
1435	if (!gelf_update_shdr(s->os, &sh))
1436		errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1437		    elf_errmsg(-1));
1438
1439	data->d_align	= 1;
1440	data->d_buf	= s->buf;
1441	data->d_size	= s->sz;
1442	data->d_off	= 0;
1443	data->d_type	= ELF_T_BYTE;
1444	data->d_version	= EV_CURRENT;
1445
1446	if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os)))
1447		errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s",
1448		     elf_errmsg(-1));
1449}
1450
1451void
1452add_section(struct elfcopy *ecp, const char *arg)
1453{
1454	struct sec_add	*sa;
1455	struct stat	 sb;
1456	const char	*s, *fn;
1457	FILE		*fp;
1458	int		 len;
1459
1460	if ((s = strchr(arg, '=')) == NULL)
1461		errx(EXIT_FAILURE,
1462		    "illegal format for --add-section option");
1463	if ((sa = malloc(sizeof(*sa))) == NULL)
1464		err(EXIT_FAILURE, "malloc failed");
1465
1466	len = s - arg;
1467	if ((sa->name = malloc(len + 1)) == NULL)
1468		err(EXIT_FAILURE, "malloc failed");
1469	strncpy(sa->name, arg, len);
1470	sa->name[len] = '\0';
1471
1472	fn = s + 1;
1473	if (stat(fn, &sb) == -1)
1474		err(EXIT_FAILURE, "stat failed");
1475	sa->size = sb.st_size;
1476	if (sa->size > 0) {
1477		if ((sa->content = malloc(sa->size)) == NULL)
1478			err(EXIT_FAILURE, "malloc failed");
1479		if ((fp = fopen(fn, "r")) == NULL)
1480			err(EXIT_FAILURE, "can not open %s", fn);
1481		if (fread(sa->content, 1, sa->size, fp) == 0 ||
1482		    ferror(fp))
1483			err(EXIT_FAILURE, "fread failed");
1484		fclose(fp);
1485	} else
1486		sa->content = NULL;
1487
1488	STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
1489	ecp->flags |= SEC_ADD;
1490}
1491
1492void
1493free_sec_add(struct elfcopy *ecp)
1494{
1495	struct sec_add *sa, *sa_temp;
1496
1497	STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) {
1498		STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list);
1499		free(sa->name);
1500		free(sa->content);
1501		free(sa);
1502	}
1503}
1504
1505static void
1506add_gnu_debuglink(struct elfcopy *ecp)
1507{
1508	struct sec_add	*sa;
1509	struct stat	 sb;
1510	FILE		*fp;
1511	char		*fnbase, *buf;
1512	int		 crc_off;
1513	int		 crc;
1514
1515	if (ecp->debuglink == NULL)
1516		return;
1517
1518	/* Read debug file content. */
1519	if ((sa = malloc(sizeof(*sa))) == NULL)
1520		err(EXIT_FAILURE, "malloc failed");
1521	if ((sa->name = strdup(".gnu_debuglink")) == NULL)
1522		err(EXIT_FAILURE, "strdup failed");
1523	if (stat(ecp->debuglink, &sb) == -1)
1524		err(EXIT_FAILURE, "stat failed");
1525	if ((buf = malloc(sb.st_size)) == NULL)
1526		err(EXIT_FAILURE, "malloc failed");
1527	if ((fp = fopen(ecp->debuglink, "r")) == NULL)
1528		err(EXIT_FAILURE, "can not open %s", ecp->debuglink);
1529	if (fread(buf, 1, sb.st_size, fp) == 0 ||
1530	    ferror(fp))
1531		err(EXIT_FAILURE, "fread failed");
1532	fclose(fp);
1533
1534	/* Calculate crc checksum.  */
1535	crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF);
1536	free(buf);
1537
1538	/* Calculate section size and the offset to store crc checksum. */
1539	if ((fnbase = basename(ecp->debuglink)) == NULL)
1540		err(EXIT_FAILURE, "basename failed");
1541	crc_off = roundup(strlen(fnbase) + 1, 4);
1542	sa->size = crc_off + 4;
1543
1544	/* Section content. */
1545	if ((sa->content = calloc(1, sa->size)) == NULL)
1546		err(EXIT_FAILURE, "malloc failed");
1547	strncpy(sa->content, fnbase, strlen(fnbase));
1548	if (ecp->oed == ELFDATA2LSB) {
1549		sa->content[crc_off] = crc & 0xFF;
1550		sa->content[crc_off + 1] = (crc >> 8) & 0xFF;
1551		sa->content[crc_off + 2] = (crc >> 16) & 0xFF;
1552		sa->content[crc_off + 3] = crc >> 24;
1553	} else {
1554		sa->content[crc_off] = crc >> 24;
1555		sa->content[crc_off + 1] = (crc >> 16) & 0xFF;
1556		sa->content[crc_off + 2] = (crc >> 8) & 0xFF;
1557		sa->content[crc_off + 3] = crc & 0xFF;
1558	}
1559
1560	STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
1561	ecp->flags |= SEC_ADD;
1562}
1563
1564static void
1565insert_to_strtab(struct section *t, const char *s)
1566{
1567	const char	*r;
1568	char		*b, *c;
1569	size_t		 len, slen;
1570	int		 append;
1571
1572	if (t->sz == 0) {
1573		t->cap = 512;
1574		if ((t->buf = malloc(t->cap)) == NULL)
1575			err(EXIT_FAILURE, "malloc failed");
1576	}
1577
1578	slen = strlen(s);
1579	append = 0;
1580	b = t->buf;
1581	for (c = b; c < b + t->sz;) {
1582		len = strlen(c);
1583		if (!append && len >= slen) {
1584			r = c + (len - slen);
1585			if (strcmp(r, s) == 0)
1586				return;
1587		} else if (len < slen && len != 0) {
1588			r = s + (slen - len);
1589			if (strcmp(c, r) == 0) {
1590				t->sz -= len + 1;
1591				memmove(c, c + len + 1, t->sz - (c - b));
1592				append = 1;
1593				continue;
1594			}
1595		}
1596		c += len + 1;
1597	}
1598
1599	while (t->sz + slen + 1 >= t->cap) {
1600		t->cap *= 2;
1601		if ((t->buf = realloc(t->buf, t->cap)) == NULL)
1602			err(EXIT_FAILURE, "realloc failed");
1603	}
1604	b = t->buf;
1605	strncpy(&b[t->sz], s, slen);
1606	b[t->sz + slen] = '\0';
1607	t->sz += slen + 1;
1608}
1609
1610static int
1611lookup_string(struct section *t, const char *s)
1612{
1613	const char	*b, *c, *r;
1614	size_t		 len, slen;
1615
1616	slen = strlen(s);
1617	b = t->buf;
1618	for (c = b; c < b + t->sz;) {
1619		len = strlen(c);
1620		if (len >= slen) {
1621			r = c + (len - slen);
1622			if (strcmp(r, s) == 0)
1623				return (r - b);
1624		}
1625		c += len + 1;
1626	}
1627
1628	return (-1);
1629}
1630
1631static uint32_t crctable[256] =
1632{
1633	0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
1634	0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
1635	0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
1636	0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
1637	0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
1638	0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
1639	0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
1640	0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
1641	0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
1642	0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
1643	0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
1644	0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
1645	0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
1646	0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
1647	0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
1648	0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
1649	0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
1650	0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
1651	0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
1652	0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
1653	0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
1654	0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
1655	0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
1656	0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
1657	0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
1658	0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
1659	0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
1660	0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
1661	0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
1662	0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
1663	0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
1664	0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
1665	0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
1666	0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
1667	0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
1668	0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
1669	0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
1670	0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
1671	0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
1672	0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
1673	0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
1674	0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
1675	0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
1676	0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
1677	0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
1678	0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
1679	0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
1680	0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
1681	0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
1682	0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
1683	0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
1684	0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
1685	0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
1686	0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
1687	0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
1688	0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
1689	0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
1690	0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
1691	0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
1692	0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
1693	0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
1694	0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
1695	0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
1696	0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
1697};
1698
1699static uint32_t
1700calc_crc32(const char *p, size_t len, uint32_t crc)
1701{
1702	uint32_t i;
1703
1704	for (i = 0; i < len; i++) {
1705		crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
1706	}
1707
1708	return (crc ^ 0xFFFFFFFF);
1709}
1710