1260684Skaiw/*-
2276398Semaste * Copyright (c) 2007-2011,2014 Kai Wang
3260684Skaiw * All rights reserved.
4260684Skaiw *
5260684Skaiw * Redistribution and use in source and binary forms, with or without
6260684Skaiw * modification, are permitted provided that the following conditions
7260684Skaiw * are met:
8260684Skaiw * 1. Redistributions of source code must retain the above copyright
9260684Skaiw *    notice, this list of conditions and the following disclaimer.
10260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
11260684Skaiw *    notice, this list of conditions and the following disclaimer in the
12260684Skaiw *    documentation and/or other materials provided with the distribution.
13260684Skaiw *
14260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17260684Skaiw * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24260684Skaiw * SUCH DAMAGE.
25260684Skaiw */
26260684Skaiw
27260684Skaiw#include <sys/param.h>
28260684Skaiw#include <sys/stat.h>
29260684Skaiw#include <err.h>
30260684Skaiw#include <libgen.h>
31367466Sdim#include <stdbool.h>
32260684Skaiw#include <stdio.h>
33260684Skaiw#include <stdlib.h>
34260684Skaiw#include <string.h>
35260684Skaiw
36260684Skaiw#include "elfcopy.h"
37260684Skaiw
38367466SdimELFTC_VCSID("$Id: sections.c 3758 2019-06-28 01:16:50Z emaste $");
39260684Skaiw
40260684Skaiwstatic void	add_gnu_debuglink(struct elfcopy *ecp);
41260684Skaiwstatic uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
42260684Skaiwstatic void	check_section_rename(struct elfcopy *ecp, struct section *s);
43260684Skaiwstatic void	filter_reloc(struct elfcopy *ecp, struct section *s);
44260684Skaiwstatic int	get_section_flags(struct elfcopy *ecp, const char *name);
45260684Skaiwstatic void	insert_sections(struct elfcopy *ecp);
46260684Skaiwstatic int	is_append_section(struct elfcopy *ecp, const char *name);
47260684Skaiwstatic int	is_compress_section(struct elfcopy *ecp, const char *name);
48260684Skaiwstatic int	is_debug_section(const char *name);
49280932Semastestatic int	is_dwo_section(const char *name);
50260684Skaiwstatic int	is_modify_section(struct elfcopy *ecp, const char *name);
51260684Skaiwstatic int	is_print_section(struct elfcopy *ecp, const char *name);
52260684Skaiwstatic void	modify_section(struct elfcopy *ecp, struct section *s);
53260684Skaiwstatic void	pad_section(struct elfcopy *ecp, struct section *s);
54260684Skaiwstatic void	print_data(const char *d, size_t sz);
55260684Skaiwstatic void	print_section(struct section *s);
56260684Skaiwstatic void	*read_section(struct section *s, size_t *size);
57367466Sdimstatic void	set_shstrtab(struct elfcopy *ecp);
58260684Skaiwstatic void	update_reloc(struct elfcopy *ecp, struct section *s);
59283616Semastestatic void	update_section_group(struct elfcopy *ecp, struct section *s);
60260684Skaiw
61260684Skaiwint
62260684Skaiwis_remove_section(struct elfcopy *ecp, const char *name)
63260684Skaiw{
64260684Skaiw
65260684Skaiw	/* Always keep section name table */
66260684Skaiw	if (strcmp(name, ".shstrtab") == 0)
67260684Skaiw		return 0;
68260684Skaiw	if (strcmp(name, ".symtab") == 0 ||
69260684Skaiw	    strcmp(name, ".strtab") == 0) {
70260684Skaiw		if (ecp->strip == STRIP_ALL && lookup_symop_list(
71260684Skaiw		    ecp, NULL, SYMOP_KEEP) == NULL)
72260684Skaiw			return (1);
73260684Skaiw		else
74260684Skaiw			return (0);
75260684Skaiw	}
76260684Skaiw
77280932Semaste	if (ecp->strip == STRIP_DWO && is_dwo_section(name))
78280932Semaste		return (1);
79280932Semaste	if (ecp->strip == STRIP_NONDWO && !is_dwo_section(name))
80280932Semaste		return (1);
81280932Semaste
82260684Skaiw	if (is_debug_section(name)) {
83260684Skaiw		if (ecp->strip == STRIP_ALL ||
84260684Skaiw		    ecp->strip == STRIP_DEBUG ||
85260684Skaiw		    ecp->strip == STRIP_UNNEEDED ||
86260684Skaiw		    (ecp->flags & DISCARD_LOCAL))
87260684Skaiw			return (1);
88260684Skaiw		if (ecp->strip == STRIP_NONDEBUG)
89260684Skaiw			return (0);
90260684Skaiw	}
91260684Skaiw
92260684Skaiw	if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) {
93260684Skaiw		struct sec_action *sac;
94260684Skaiw
95260684Skaiw		sac = lookup_sec_act(ecp, name, 0);
96260684Skaiw		if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove)
97260684Skaiw			return (1);
98260684Skaiw		if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy))
99260684Skaiw			return (1);
100260684Skaiw	}
101260684Skaiw
102260684Skaiw	return (0);
103260684Skaiw}
104260684Skaiw
105260684Skaiw/*
106260684Skaiw * Relocation section needs to be removed if the section it applies to
107260684Skaiw * will be removed.
108260684Skaiw */
109260684Skaiwint
110260684Skaiwis_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info)
111260684Skaiw{
112260684Skaiw	const char	*name;
113260684Skaiw	GElf_Shdr	 ish;
114260684Skaiw	Elf_Scn		*is;
115260684Skaiw	size_t		 indx;
116260684Skaiw	int		 elferr;
117260684Skaiw
118260684Skaiw	if (elf_getshstrndx(ecp->ein, &indx) == 0)
119260684Skaiw		errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
120260684Skaiw		    elf_errmsg(-1));
121260684Skaiw
122367466Sdim	is = elf_getscn(ecp->ein, sh_info);
123367466Sdim	if (is != NULL) {
124367466Sdim		if (gelf_getshdr(is, &ish) == NULL)
125367466Sdim			errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
126367466Sdim			    elf_errmsg(-1));
127367466Sdim		if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) ==
128367466Sdim		    NULL)
129367466Sdim			errx(EXIT_FAILURE, "elf_strptr failed: %s",
130367466Sdim			    elf_errmsg(-1));
131367466Sdim		if (is_remove_section(ecp, name))
132367466Sdim			return (1);
133367466Sdim		else
134367466Sdim			return (0);
135260684Skaiw	}
136260684Skaiw	elferr = elf_errno();
137260684Skaiw	if (elferr != 0)
138260684Skaiw		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
139260684Skaiw		    elf_errmsg(elferr));
140260684Skaiw
141260684Skaiw	/* Remove reloc section if we can't find the target section. */
142260684Skaiw	return (1);
143260684Skaiw}
144260684Skaiw
145260684Skaiwstatic int
146260684Skaiwis_append_section(struct elfcopy *ecp, const char *name)
147260684Skaiw{
148260684Skaiw	struct sec_action *sac;
149260684Skaiw
150260684Skaiw	sac = lookup_sec_act(ecp, name, 0);
151260684Skaiw	if (sac != NULL && sac->append != 0 && sac->string != NULL)
152260684Skaiw		return (1);
153260684Skaiw
154260684Skaiw	return (0);
155260684Skaiw}
156260684Skaiw
157260684Skaiwstatic int
158260684Skaiwis_compress_section(struct elfcopy *ecp, const char *name)
159260684Skaiw{
160260684Skaiw	struct sec_action *sac;
161260684Skaiw
162260684Skaiw	sac = lookup_sec_act(ecp, name, 0);
163260684Skaiw	if (sac != NULL && sac->compress != 0)
164260684Skaiw		return (1);
165260684Skaiw
166260684Skaiw	return (0);
167260684Skaiw}
168260684Skaiw
169260684Skaiwstatic void
170260684Skaiwcheck_section_rename(struct elfcopy *ecp, struct section *s)
171260684Skaiw{
172260684Skaiw	struct sec_action *sac;
173260684Skaiw	char *prefix;
174260684Skaiw	size_t namelen;
175260684Skaiw
176260684Skaiw	if (s->pseudo)
177260684Skaiw		return;
178260684Skaiw
179260684Skaiw	sac = lookup_sec_act(ecp, s->name, 0);
180260684Skaiw	if (sac != NULL && sac->rename)
181260684Skaiw		s->name = sac->newname;
182260684Skaiw
183260684Skaiw	if (!strcmp(s->name, ".symtab") ||
184260684Skaiw	    !strcmp(s->name, ".strtab") ||
185260684Skaiw	    !strcmp(s->name, ".shstrtab"))
186260684Skaiw		return;
187260684Skaiw
188260684Skaiw	prefix = NULL;
189260684Skaiw	if (s->loadable && ecp->prefix_alloc != NULL)
190260684Skaiw		prefix = ecp->prefix_alloc;
191260684Skaiw	else if (ecp->prefix_sec != NULL)
192260684Skaiw		prefix = ecp->prefix_sec;
193260684Skaiw
194260684Skaiw	if (prefix != NULL) {
195260684Skaiw		namelen = strlen(s->name) + strlen(prefix) + 1;
196260684Skaiw		if ((s->newname = malloc(namelen)) == NULL)
197260684Skaiw			err(EXIT_FAILURE, "malloc failed");
198260684Skaiw		snprintf(s->newname, namelen, "%s%s", prefix, s->name);
199260684Skaiw		s->name = s->newname;
200260684Skaiw	}
201260684Skaiw}
202260684Skaiw
203260684Skaiwstatic int
204260684Skaiwget_section_flags(struct elfcopy *ecp, const char *name)
205260684Skaiw{
206260684Skaiw	struct sec_action *sac;
207260684Skaiw
208260684Skaiw	sac = lookup_sec_act(ecp, name, 0);
209260684Skaiw	if (sac != NULL && sac->flags)
210260684Skaiw		return sac->flags;
211260684Skaiw
212260684Skaiw	return (0);
213260684Skaiw}
214260684Skaiw
215260684Skaiw/*
216260684Skaiw * Determine whether the section are debugging section.
217260684Skaiw * According to libbfd, debugging sections are recognized
218260684Skaiw * only by name.
219260684Skaiw */
220260684Skaiwstatic int
221260684Skaiwis_debug_section(const char *name)
222260684Skaiw{
223260684Skaiw	const char *dbg_sec[] = {
224295577Semaste		".apple_",
225260684Skaiw		".debug",
226260684Skaiw		".gnu.linkonce.wi.",
227260684Skaiw		".line",
228260684Skaiw		".stab",
229260684Skaiw		NULL
230260684Skaiw	};
231260684Skaiw	const char **p;
232260684Skaiw
233260684Skaiw	for(p = dbg_sec; *p; p++) {
234260684Skaiw		if (strncmp(name, *p, strlen(*p)) == 0)
235260684Skaiw			return (1);
236260684Skaiw	}
237260684Skaiw
238260684Skaiw	return (0);
239260684Skaiw}
240260684Skaiw
241260684Skaiwstatic int
242280932Semasteis_dwo_section(const char *name)
243280932Semaste{
244280932Semaste	size_t len;
245280932Semaste
246280932Semaste	if ((len = strlen(name)) > 4 && strcmp(name + len - 4, ".dwo") == 0)
247280932Semaste		return (1);
248280932Semaste	return (0);
249280932Semaste}
250280932Semaste
251280932Semastestatic int
252260684Skaiwis_print_section(struct elfcopy *ecp, const char *name)
253260684Skaiw{
254260684Skaiw	struct sec_action *sac;
255260684Skaiw
256260684Skaiw	sac = lookup_sec_act(ecp, name, 0);
257260684Skaiw	if (sac != NULL && sac->print != 0)
258260684Skaiw		return (1);
259260684Skaiw
260260684Skaiw	return (0);
261260684Skaiw}
262260684Skaiw
263260684Skaiwstatic int
264260684Skaiwis_modify_section(struct elfcopy *ecp, const char *name)
265260684Skaiw{
266260684Skaiw
267260684Skaiw	if (is_append_section(ecp, name) ||
268260684Skaiw	    is_compress_section(ecp, name))
269260684Skaiw		return (1);
270260684Skaiw
271260684Skaiw	return (0);
272260684Skaiw}
273260684Skaiw
274260684Skaiwstruct sec_action*
275260684Skaiwlookup_sec_act(struct elfcopy *ecp, const char *name, int add)
276260684Skaiw{
277260684Skaiw	struct sec_action *sac;
278260684Skaiw
279260684Skaiw	if (name == NULL)
280260684Skaiw		return NULL;
281260684Skaiw
282260684Skaiw	STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) {
283260684Skaiw		if (strcmp(name, sac->name) == 0)
284260684Skaiw			return sac;
285260684Skaiw	}
286260684Skaiw
287260684Skaiw	if (add == 0)
288260684Skaiw		return NULL;
289260684Skaiw
290260684Skaiw	if ((sac = malloc(sizeof(*sac))) == NULL)
291260684Skaiw		errx(EXIT_FAILURE, "not enough memory");
292260684Skaiw	memset(sac, 0, sizeof(*sac));
293260684Skaiw	sac->name = name;
294260684Skaiw	STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list);
295260684Skaiw
296260684Skaiw	return (sac);
297260684Skaiw}
298260684Skaiw
299260684Skaiwvoid
300260684Skaiwfree_sec_act(struct elfcopy *ecp)
301260684Skaiw{
302260684Skaiw	struct sec_action *sac, *sac_temp;
303260684Skaiw
304260684Skaiw	STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) {
305260684Skaiw		STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list);
306260684Skaiw		free(sac);
307260684Skaiw	}
308260684Skaiw}
309260684Skaiw
310260684Skaiwvoid
311260684Skaiwinsert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail)
312260684Skaiw{
313260684Skaiw	struct section *s;
314260684Skaiw
315367466Sdim	if (tail || TAILQ_EMPTY(&ecp->v_sec) ||
316367466Sdim	    TAILQ_LAST(&ecp->v_sec, sectionlist)->off <= sec->off) {
317367466Sdim		TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list);
318367466Sdim	} else {
319260684Skaiw		TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
320260684Skaiw			if (sec->off < s->off) {
321260684Skaiw				TAILQ_INSERT_BEFORE(s, sec, sec_list);
322367466Sdim				break;
323260684Skaiw			}
324260684Skaiw		}
325260684Skaiw	}
326260684Skaiw
327260684Skaiw	if (sec->pseudo == 0)
328260684Skaiw		ecp->nos++;
329260684Skaiw}
330260684Skaiw
331260684Skaiw/*
332260684Skaiw * First step of section creation: create scn and internal section
333260684Skaiw * structure, discard sections to be removed.
334260684Skaiw */
335260684Skaiwvoid
336260684Skaiwcreate_scn(struct elfcopy *ecp)
337260684Skaiw{
338260684Skaiw	struct section	*s;
339260684Skaiw	const char	*name;
340260684Skaiw	Elf_Scn		*is;
341260684Skaiw	GElf_Shdr	 ish;
342260684Skaiw	size_t		 indx;
343260684Skaiw	uint64_t	 oldndx, newndx;
344298085Semaste	int		 elferr, sec_flags, reorder;
345367466Sdim	bool		 sections_added;
346260684Skaiw
347260684Skaiw	/*
348260684Skaiw	 * Insert a pseudo section that contains the ELF header
349260684Skaiw	 * and program header. Used as reference for section offset
350260684Skaiw	 * or load address adjustment.
351260684Skaiw	 */
352260684Skaiw	if ((s = calloc(1, sizeof(*s))) == NULL)
353260684Skaiw		err(EXIT_FAILURE, "calloc failed");
354260684Skaiw	s->off = 0;
355260684Skaiw	s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) +
356260684Skaiw	    gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT);
357260684Skaiw	s->align = 1;
358260684Skaiw	s->pseudo = 1;
359260684Skaiw	s->loadable = add_to_inseg_list(ecp, s);
360260684Skaiw	insert_to_sec_list(ecp, s, 0);
361260684Skaiw
362260684Skaiw	/* Create internal .shstrtab section. */
363260684Skaiw	init_shstrtab(ecp);
364260684Skaiw
365260684Skaiw	if (elf_getshstrndx(ecp->ein, &indx) == 0)
366260684Skaiw		errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
367260684Skaiw		    elf_errmsg(-1));
368260684Skaiw
369367466Sdim	sections_added = false;
370298085Semaste	reorder = 0;
371260684Skaiw	is = NULL;
372260684Skaiw	while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
373260684Skaiw		if (gelf_getshdr(is, &ish) == NULL)
374295577Semaste			errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
375260684Skaiw			    elf_errmsg(-1));
376260684Skaiw		if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL)
377260684Skaiw			errx(EXIT_FAILURE, "elf_strptr failed: %s",
378260684Skaiw			    elf_errmsg(-1));
379260684Skaiw
380260684Skaiw		/* Skip sections to be removed. */
381260684Skaiw		if (is_remove_section(ecp, name))
382260684Skaiw			continue;
383260684Skaiw
384260684Skaiw		/*
385260684Skaiw		 * Relocation section need to be remove if the section
386260684Skaiw		 * it applies will be removed.
387260684Skaiw		 */
388260684Skaiw		if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
389260684Skaiw			if (ish.sh_info != 0 &&
390260684Skaiw			    is_remove_reloc_sec(ecp, ish.sh_info))
391260684Skaiw				continue;
392260684Skaiw
393276371Semaste		/*
394276371Semaste		 * Section groups should be removed if symbol table will
395276371Semaste		 * be removed. (section group's signature stored in symbol
396276371Semaste		 * table)
397276371Semaste		 */
398276371Semaste		if (ish.sh_type == SHT_GROUP && ecp->strip == STRIP_ALL)
399276371Semaste			continue;
400276371Semaste
401260684Skaiw		/* Get section flags set by user. */
402260684Skaiw		sec_flags = get_section_flags(ecp, name);
403260684Skaiw
404260684Skaiw		/* Create internal section object. */
405260684Skaiw		if (strcmp(name, ".shstrtab") != 0) {
406260684Skaiw			if ((s = calloc(1, sizeof(*s))) == NULL)
407260684Skaiw				err(EXIT_FAILURE, "calloc failed");
408260684Skaiw			s->name		= name;
409260684Skaiw			s->is		= is;
410260684Skaiw			s->off		= ish.sh_offset;
411260684Skaiw			s->sz		= ish.sh_size;
412260684Skaiw			s->align	= ish.sh_addralign;
413260684Skaiw			s->type		= ish.sh_type;
414333770Smarius			s->flags	= ish.sh_flags;
415260684Skaiw			s->vma		= ish.sh_addr;
416260684Skaiw
417260684Skaiw			/*
418260684Skaiw			 * Search program headers to determine whether section
419260684Skaiw			 * is loadable, but if user explicitly set section flags
420260684Skaiw			 * while neither "load" nor "alloc" is set, we make the
421260684Skaiw			 * section unloadable.
422295577Semaste			 *
423295577Semaste			 * Sections in relocatable object is loadable if
424295577Semaste			 * section flag SHF_ALLOC is set.
425260684Skaiw			 */
426260684Skaiw			if (sec_flags &&
427260684Skaiw			    (sec_flags & (SF_LOAD | SF_ALLOC)) == 0)
428260684Skaiw				s->loadable = 0;
429295577Semaste			else {
430260684Skaiw				s->loadable = add_to_inseg_list(ecp, s);
431295577Semaste				if ((ecp->flags & RELOCATABLE) &&
432295577Semaste				    (ish.sh_flags & SHF_ALLOC))
433295577Semaste					s->loadable = 1;
434295577Semaste			}
435260684Skaiw		} else {
436260684Skaiw			/* Assuming .shstrtab is "unloadable". */
437260684Skaiw			s		= ecp->shstrtab;
438260684Skaiw			s->off		= ish.sh_offset;
439260684Skaiw		}
440260684Skaiw
441260684Skaiw		oldndx = newndx = SHN_UNDEF;
442260684Skaiw		if (strcmp(name, ".symtab") != 0 &&
443260684Skaiw		    strcmp(name, ".strtab") != 0) {
444367466Sdim			/* Add new sections before .shstrtab if we have one. */
445260684Skaiw			if (!strcmp(name, ".shstrtab")) {
446260684Skaiw				/*
447260684Skaiw				 * Add sections specified by --add-section and
448260684Skaiw				 * gnu debuglink. we want these sections have
449260684Skaiw				 * smaller index than .shstrtab section.
450260684Skaiw				 */
451367466Sdim				sections_added = true;
452260684Skaiw				if (ecp->debuglink != NULL)
453260684Skaiw					add_gnu_debuglink(ecp);
454260684Skaiw				if (ecp->flags & SEC_ADD)
455260684Skaiw					insert_sections(ecp);
456260684Skaiw			}
457260684Skaiw 			if ((s->os = elf_newscn(ecp->eout)) == NULL)
458260684Skaiw				errx(EXIT_FAILURE, "elf_newscn failed: %s",
459260684Skaiw				    elf_errmsg(-1));
460260684Skaiw			if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF)
461260684Skaiw				errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
462260684Skaiw				    elf_errmsg(-1));
463260684Skaiw		}
464260684Skaiw		if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF)
465260684Skaiw			errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
466260684Skaiw			    elf_errmsg(-1));
467260684Skaiw		if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF)
468260684Skaiw			ecp->secndx[oldndx] = newndx;
469260684Skaiw
470260684Skaiw		/*
471260684Skaiw		 * If strip action is STRIP_NONDEBUG(only keep debug),
472292120Semaste		 * change sections type of loadable sections and section
473292120Semaste		 * groups to SHT_NOBITS, and the content of those sections
474292120Semaste		 * will be discarded. However, SHT_NOTE sections should
475292120Semaste		 * be kept.
476260684Skaiw		 */
477292120Semaste		if (ecp->strip == STRIP_NONDEBUG) {
478292120Semaste			if (((ish.sh_flags & SHF_ALLOC) ||
479292120Semaste			    (ish.sh_flags & SHF_GROUP)) &&
480292120Semaste			    ish.sh_type != SHT_NOTE)
481292120Semaste				s->type = SHT_NOBITS;
482292120Semaste		}
483260684Skaiw
484260684Skaiw		check_section_rename(ecp, s);
485260684Skaiw
486260684Skaiw		/* create section header based on input object. */
487260684Skaiw		if (strcmp(name, ".symtab") != 0 &&
488260684Skaiw		    strcmp(name, ".strtab") != 0 &&
489298085Semaste		    strcmp(name, ".shstrtab") != 0) {
490260684Skaiw			copy_shdr(ecp, s, NULL, 0, sec_flags);
491298085Semaste			/*
492298085Semaste			 * elfcopy puts .symtab, .strtab and .shstrtab
493298085Semaste			 * sections in the end of the output object.
494298085Semaste			 * If the input objects have more sections
495298085Semaste			 * after any of these 3 sections, the section
496298085Semaste			 * table will be reordered. section symbols
497298085Semaste			 * should be regenerated for relocations.
498298085Semaste			 */
499298085Semaste			if (reorder)
500298085Semaste				ecp->flags &= ~SYMTAB_INTACT;
501298085Semaste		} else
502298085Semaste			reorder = 1;
503260684Skaiw
504260684Skaiw		if (strcmp(name, ".symtab") == 0) {
505260684Skaiw			ecp->flags |= SYMTAB_EXIST;
506260684Skaiw			ecp->symtab = s;
507260684Skaiw		}
508260684Skaiw		if (strcmp(name, ".strtab") == 0)
509260684Skaiw			ecp->strtab = s;
510260684Skaiw
511260684Skaiw		insert_to_sec_list(ecp, s, 0);
512260684Skaiw	}
513367466Sdim	if (!sections_added) {
514367466Sdim		if (ecp->debuglink != NULL)
515367466Sdim			add_gnu_debuglink(ecp);
516367466Sdim		if (ecp->flags & SEC_ADD)
517367466Sdim			insert_sections(ecp);
518367466Sdim	}
519260684Skaiw	elferr = elf_errno();
520260684Skaiw	if (elferr != 0)
521260684Skaiw		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
522260684Skaiw		    elf_errmsg(elferr));
523260684Skaiw}
524260684Skaiw
525260684Skaiwstruct section *
526260684Skaiwinsert_shtab(struct elfcopy *ecp, int tail)
527260684Skaiw{
528260684Skaiw	struct section	*s, *shtab;
529260684Skaiw	GElf_Ehdr	 ieh;
530260684Skaiw	int		 nsecs;
531260684Skaiw
532260684Skaiw	/*
533260684Skaiw	 * Treat section header table as a "pseudo" section, insert it
534260684Skaiw	 * into section list, so later it will get sorted and resynced
535260684Skaiw	 * just as normal sections.
536260684Skaiw	 */
537260684Skaiw	if ((shtab = calloc(1, sizeof(*shtab))) == NULL)
538260684Skaiw		errx(EXIT_FAILURE, "calloc failed");
539260684Skaiw	if (!tail) {
540276398Semaste		/*
541276398Semaste		 * "shoff" of input object is used as a hint for section
542276398Semaste		 * resync later.
543276398Semaste		 */
544260684Skaiw		if (gelf_getehdr(ecp->ein, &ieh) == NULL)
545260684Skaiw			errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
546260684Skaiw			    elf_errmsg(-1));
547260684Skaiw		shtab->off = ieh.e_shoff;
548260684Skaiw	} else
549260684Skaiw		shtab->off = 0;
550260684Skaiw	/* Calculate number of sections in the output object. */
551260684Skaiw	nsecs = 0;
552260684Skaiw	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
553260684Skaiw		if (!s->pseudo)
554260684Skaiw			nsecs++;
555260684Skaiw	}
556260684Skaiw	/* Remember there is always a null section, so we +1 here. */
557260684Skaiw	shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT);
558260684Skaiw	if (shtab->sz == 0)
559260684Skaiw		errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1));
560260684Skaiw	shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8);
561260684Skaiw	shtab->loadable = 0;
562260684Skaiw	shtab->pseudo = 1;
563260684Skaiw	insert_to_sec_list(ecp, shtab, tail);
564260684Skaiw
565260684Skaiw	return (shtab);
566260684Skaiw}
567260684Skaiw
568260684Skaiwvoid
569260684Skaiwcopy_content(struct elfcopy *ecp)
570260684Skaiw{
571260684Skaiw	struct section *s;
572260684Skaiw
573260684Skaiw	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
574260684Skaiw		/* Skip pseudo section. */
575260684Skaiw		if (s->pseudo)
576260684Skaiw			continue;
577260684Skaiw
578260684Skaiw		/* Skip special sections. */
579260684Skaiw		if (strcmp(s->name, ".symtab") == 0 ||
580260684Skaiw		    strcmp(s->name, ".strtab") == 0 ||
581260684Skaiw		    strcmp(s->name, ".shstrtab") == 0)
582260684Skaiw			continue;
583260684Skaiw
584260684Skaiw		/*
585260684Skaiw		 * If strip action is STRIP_ALL, relocation info need
586260684Skaiw		 * to be stripped. Skip filtering otherwisw.
587260684Skaiw		 */
588260684Skaiw		if (ecp->strip == STRIP_ALL &&
589260684Skaiw		    (s->type == SHT_REL || s->type == SHT_RELA))
590260684Skaiw			filter_reloc(ecp, s);
591260684Skaiw
592283616Semaste		/*
593283616Semaste		 * The section indices in the SHT_GROUP section needs
594283616Semaste		 * to be updated since we might have stripped some
595283616Semaste		 * sections and changed section numbering.
596283616Semaste		 */
597283616Semaste		if (s->type == SHT_GROUP)
598283616Semaste			update_section_group(ecp, s);
599283616Semaste
600260684Skaiw		if (is_modify_section(ecp, s->name))
601260684Skaiw			modify_section(ecp, s);
602260684Skaiw
603260684Skaiw		copy_data(s);
604260684Skaiw
605260684Skaiw		/*
606260684Skaiw		 * If symbol table is modified, relocation info might
607260684Skaiw		 * need update, as symbol index may have changed.
608260684Skaiw		 */
609260684Skaiw		if ((ecp->flags & SYMTAB_INTACT) == 0 &&
610260684Skaiw		    (ecp->flags & SYMTAB_EXIST) &&
611260684Skaiw		    (s->type == SHT_REL || s->type == SHT_RELA))
612260684Skaiw			update_reloc(ecp, s);
613260684Skaiw
614260684Skaiw		if (is_print_section(ecp, s->name))
615260684Skaiw			print_section(s);
616260684Skaiw	}
617260684Skaiw}
618260684Skaiw
619283616Semaste
620260684Skaiw/*
621283616Semaste * Update section group section. The section indices in the SHT_GROUP
622283616Semaste * section need update after section numbering changed.
623283616Semaste */
624283616Semastestatic void
625283616Semasteupdate_section_group(struct elfcopy *ecp, struct section *s)
626283616Semaste{
627283616Semaste	GElf_Shdr	 ish;
628283616Semaste	Elf_Data	*id;
629283616Semaste	uint32_t	*ws, *wd;
630283616Semaste	uint64_t	 n;
631283616Semaste	size_t		 ishnum;
632283616Semaste	int		 i, j;
633283616Semaste
634283616Semaste	if (!elf_getshnum(ecp->ein, &ishnum))
635283616Semaste		errx(EXIT_FAILURE, "elf_getshnum failed: %s",
636283616Semaste		    elf_errmsg(-1));
637283616Semaste
638283616Semaste	if (gelf_getshdr(s->is, &ish) == NULL)
639283616Semaste		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
640283616Semaste		    elf_errmsg(-1));
641283616Semaste
642283616Semaste	if ((id = elf_getdata(s->is, NULL)) == NULL)
643283616Semaste		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
644283616Semaste		    elf_errmsg(-1));
645283616Semaste
646283616Semaste	if (ish.sh_size == 0)
647283616Semaste		return;
648283616Semaste
649283616Semaste	if (ish.sh_entsize == 0)
650283616Semaste		ish.sh_entsize = 4;
651283616Semaste
652283616Semaste	ws = id->d_buf;
653283616Semaste
654283616Semaste	/* We only support COMDAT section. */
655283616Semaste#ifndef GRP_COMDAT
656283616Semaste#define	GRP_COMDAT 0x1
657283616Semaste#endif
658283616Semaste	if ((*ws & GRP_COMDAT) == 0)
659283616Semaste		return;
660283616Semaste
661283616Semaste	if ((s->buf = malloc(ish.sh_size)) == NULL)
662283616Semaste		err(EXIT_FAILURE, "malloc failed");
663283616Semaste
664283616Semaste	s->sz = ish.sh_size;
665283616Semaste
666283616Semaste	wd = s->buf;
667283616Semaste
668283616Semaste	/* Copy the flag word as-is. */
669283616Semaste	*wd = *ws;
670283616Semaste
671283616Semaste	/* Update the section indices. */
672283616Semaste	n = ish.sh_size / ish.sh_entsize;
673283616Semaste	for(i = 1, j = 1; (uint64_t)i < n; i++) {
674283616Semaste		if (ws[i] != SHN_UNDEF && ws[i] < ishnum &&
675283616Semaste		    ecp->secndx[ws[i]] != 0)
676283616Semaste			wd[j++] = ecp->secndx[ws[i]];
677283616Semaste		else
678283616Semaste			s->sz -= 4;
679283616Semaste	}
680283616Semaste
681283616Semaste	s->nocopy = 1;
682283616Semaste}
683283616Semaste
684283616Semaste/*
685260684Skaiw * Filter relocation entries, only keep those entries whose
686260684Skaiw * symbol is in the keep list.
687260684Skaiw */
688260684Skaiwstatic void
689260684Skaiwfilter_reloc(struct elfcopy *ecp, struct section *s)
690260684Skaiw{
691260684Skaiw	const char	*name;
692260684Skaiw	GElf_Shdr	 ish;
693260684Skaiw	GElf_Rel	 rel;
694260684Skaiw	GElf_Rela	 rela;
695260684Skaiw	Elf32_Rel	*rel32;
696260684Skaiw	Elf64_Rel	*rel64;
697260684Skaiw	Elf32_Rela	*rela32;
698260684Skaiw	Elf64_Rela	*rela64;
699260684Skaiw	Elf_Data	*id;
700339710Semaste	uint64_t	 cap, n, nrels, sym;
701260684Skaiw	int		 elferr, i;
702260684Skaiw
703260684Skaiw	if (gelf_getshdr(s->is, &ish) == NULL)
704260684Skaiw		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
705260684Skaiw		    elf_errmsg(-1));
706260684Skaiw
707260684Skaiw	/* We don't want to touch relocation info for dynamic symbols. */
708260684Skaiw	if ((ecp->flags & SYMTAB_EXIST) == 0) {
709339710Semaste		/*
710339710Semaste		 * No symbol table in output.  If sh_link points to a section
711339710Semaste		 * that exists in the output object, this relocation section
712339710Semaste		 * is for dynamic symbols.  Don't touch it.
713339710Semaste		 */
714339710Semaste		if (ish.sh_link != 0 && ecp->secndx[ish.sh_link] != 0)
715339710Semaste			return;
716260684Skaiw	} else {
717260684Skaiw		/* Symbol table exist, check if index equals. */
718260684Skaiw		if (ish.sh_link != elf_ndxscn(ecp->symtab->is))
719260684Skaiw			return;
720260684Skaiw	}
721260684Skaiw
722260684Skaiw#define	COPYREL(REL, SZ) do {					\
723260684Skaiw	if (nrels == 0) {					\
724260684Skaiw		if ((REL##SZ = malloc(cap *			\
725336521Smarkj		    sizeof(*REL##SZ))) == NULL)			\
726260684Skaiw			err(EXIT_FAILURE, "malloc failed");	\
727260684Skaiw	}							\
728260684Skaiw	if (nrels >= cap) {					\
729260684Skaiw		cap *= 2;					\
730260684Skaiw		if ((REL##SZ = realloc(REL##SZ, cap *		\
731336521Smarkj		    sizeof(*REL##SZ))) == NULL)			\
732260684Skaiw			err(EXIT_FAILURE, "realloc failed");	\
733260684Skaiw	}							\
734260684Skaiw	REL##SZ[nrels].r_offset = REL.r_offset;			\
735260684Skaiw	REL##SZ[nrels].r_info	= REL.r_info;			\
736260684Skaiw	if (s->type == SHT_RELA)				\
737260684Skaiw		rela##SZ[nrels].r_addend = rela.r_addend;	\
738260684Skaiw	nrels++;						\
739260684Skaiw} while (0)
740260684Skaiw
741260684Skaiw	nrels = 0;
742260684Skaiw	cap = 4;		/* keep list is usually small. */
743260684Skaiw	rel32 = NULL;
744260684Skaiw	rel64 = NULL;
745260684Skaiw	rela32 = NULL;
746260684Skaiw	rela64 = NULL;
747260684Skaiw	if ((id = elf_getdata(s->is, NULL)) == NULL)
748260684Skaiw		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
749260684Skaiw		    elf_errmsg(-1));
750260684Skaiw	n = ish.sh_size / ish.sh_entsize;
751260684Skaiw	for(i = 0; (uint64_t)i < n; i++) {
752260684Skaiw		if (s->type == SHT_REL) {
753260684Skaiw			if (gelf_getrel(id, i, &rel) != &rel)
754260684Skaiw				errx(EXIT_FAILURE, "gelf_getrel failed: %s",
755260684Skaiw				    elf_errmsg(-1));
756339710Semaste			sym = GELF_R_SYM(rel.r_info);
757260684Skaiw		} else {
758260684Skaiw			if (gelf_getrela(id, i, &rela) != &rela)
759260684Skaiw				errx(EXIT_FAILURE, "gelf_getrel failed: %s",
760260684Skaiw				    elf_errmsg(-1));
761339710Semaste			sym = GELF_R_SYM(rela.r_info);
762260684Skaiw		}
763339710Semaste		/*
764339710Semaste		 * If a relocation references a symbol and we are omitting
765339710Semaste		 * either that symbol or the entire symbol table we cannot
766339710Semaste		 * produce valid output, and so just omit the relocation.
767339710Semaste		 * Broken output like this is generally not useful, but some
768339710Semaste		 * uses of elfcopy/strip rely on it - for example, GCC's build
769339710Semaste		 * process uses it to check for build reproducibility by
770339710Semaste		 * stripping objects and comparing them.
771339710Semaste		 *
772339710Semaste		 * Relocations that do not reference a symbol are retained.
773339710Semaste		 */
774339710Semaste		if (sym != 0) {
775339710Semaste			if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0)
776339710Semaste				continue;
777339710Semaste			name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is),
778339710Semaste			    sym);
779339710Semaste			if (name == NULL)
780339710Semaste				errx(EXIT_FAILURE, "elf_strptr failed: %s",
781339710Semaste				    elf_errmsg(-1));
782339710Semaste			if (lookup_symop_list(ecp, name, SYMOP_KEEP) == NULL)
783339710Semaste				continue;
784260684Skaiw		}
785339710Semaste		if (ecp->oec == ELFCLASS32) {
786339710Semaste			if (s->type == SHT_REL)
787339710Semaste				COPYREL(rel, 32);
788339710Semaste			else
789339710Semaste				COPYREL(rela, 32);
790339710Semaste		} else {
791339710Semaste			if (s->type == SHT_REL)
792339710Semaste				COPYREL(rel, 64);
793339710Semaste			else
794339710Semaste				COPYREL(rela, 64);
795339710Semaste		}
796260684Skaiw	}
797260684Skaiw	elferr = elf_errno();
798260684Skaiw	if (elferr != 0)
799260684Skaiw		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
800260684Skaiw		    elf_errmsg(elferr));
801260684Skaiw
802260684Skaiw	if (ecp->oec == ELFCLASS32) {
803260684Skaiw		if (s->type == SHT_REL)
804260684Skaiw			s->buf = rel32;
805260684Skaiw		else
806260684Skaiw			s->buf = rela32;
807260684Skaiw	} else {
808260684Skaiw		if (s->type == SHT_REL)
809260684Skaiw			s->buf = rel64;
810260684Skaiw		else
811260684Skaiw			s->buf = rela64;
812260684Skaiw	}
813260684Skaiw	s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL :
814260684Skaiw	    ELF_T_RELA), nrels, EV_CURRENT);
815260684Skaiw	s->nocopy = 1;
816260684Skaiw}
817260684Skaiw
818260684Skaiwstatic void
819260684Skaiwupdate_reloc(struct elfcopy *ecp, struct section *s)
820260684Skaiw{
821260684Skaiw	GElf_Shdr	 osh;
822260684Skaiw	GElf_Rel	 rel;
823260684Skaiw	GElf_Rela	 rela;
824260684Skaiw	Elf_Data	*od;
825260684Skaiw	uint64_t	 n;
826260684Skaiw	int		 i;
827260684Skaiw
828260684Skaiw#define UPDATEREL(REL) do {						\
829260684Skaiw	if (gelf_get##REL(od, i, &REL) != &REL)				\
830260684Skaiw		errx(EXIT_FAILURE, "gelf_get##REL failed: %s",		\
831260684Skaiw		    elf_errmsg(-1));					\
832260684Skaiw	REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)],	\
833260684Skaiw	    GELF_R_TYPE(REL.r_info));					\
834260684Skaiw	if (!gelf_update_##REL(od, i, &REL))				\
835260684Skaiw		errx(EXIT_FAILURE, "gelf_update_##REL failed: %s",	\
836260684Skaiw		    elf_errmsg(-1));					\
837260684Skaiw} while(0)
838260684Skaiw
839260684Skaiw	if (s->sz == 0)
840260684Skaiw		return;
841260684Skaiw	if (gelf_getshdr(s->os, &osh) == NULL)
842260684Skaiw		errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
843260684Skaiw		    elf_errmsg(-1));
844260684Skaiw	/* Only process .symtab reloc info. */
845260684Skaiw	if (osh.sh_link != elf_ndxscn(ecp->symtab->is))
846260684Skaiw		return;
847260684Skaiw	if ((od = elf_getdata(s->os, NULL)) == NULL)
848260684Skaiw		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
849260684Skaiw		    elf_errmsg(-1));
850260684Skaiw	n = osh.sh_size / osh.sh_entsize;
851260684Skaiw	for(i = 0; (uint64_t)i < n; i++) {
852260684Skaiw		if (s->type == SHT_REL)
853260684Skaiw			UPDATEREL(rel);
854260684Skaiw		else
855260684Skaiw			UPDATEREL(rela);
856260684Skaiw	}
857260684Skaiw}
858260684Skaiw
859260684Skaiwstatic void
860260684Skaiwpad_section(struct elfcopy *ecp, struct section *s)
861260684Skaiw{
862260684Skaiw	GElf_Shdr	 osh;
863260684Skaiw	Elf_Data	*od;
864260684Skaiw
865260684Skaiw	if (s == NULL || s->pad_sz == 0)
866260684Skaiw		return;
867260684Skaiw
868260684Skaiw	if ((s->pad = malloc(s->pad_sz)) == NULL)
869260684Skaiw		err(EXIT_FAILURE, "malloc failed");
870260684Skaiw	memset(s->pad, ecp->fill, s->pad_sz);
871260684Skaiw
872260684Skaiw	/* Create a new Elf_Data to contain the padding bytes. */
873260684Skaiw	if ((od = elf_newdata(s->os)) == NULL)
874260684Skaiw		errx(EXIT_FAILURE, "elf_newdata() failed: %s",
875260684Skaiw		    elf_errmsg(-1));
876260684Skaiw	od->d_align = 1;
877260684Skaiw	od->d_off = s->sz;
878260684Skaiw	od->d_buf = s->pad;
879260684Skaiw	od->d_type = ELF_T_BYTE;
880260684Skaiw	od->d_size = s->pad_sz;
881260684Skaiw	od->d_version = EV_CURRENT;
882260684Skaiw
883260684Skaiw	/* Update section header. */
884260684Skaiw	if (gelf_getshdr(s->os, &osh) == NULL)
885260684Skaiw		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
886260684Skaiw		    elf_errmsg(-1));
887260684Skaiw	osh.sh_size = s->sz + s->pad_sz;
888260684Skaiw	if (!gelf_update_shdr(s->os, &osh))
889260684Skaiw		errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
890260684Skaiw		    elf_errmsg(-1));
891260684Skaiw}
892260684Skaiw
893367466Sdimstatic int
894367466Sdimsection_type_alignment(int sht, int class)
895367466Sdim{
896367466Sdim	switch (sht)
897367466Sdim	{
898367466Sdim	case SHT_DYNAMIC:
899367466Sdim	case SHT_DYNSYM:
900367466Sdim	case SHT_FINI_ARRAY:
901367466Sdim	case SHT_GNU_HASH:
902367466Sdim	case SHT_INIT_ARRAY:
903367466Sdim	case SHT_PREINIT_ARRAY:
904367466Sdim	case SHT_REL:
905367466Sdim	case SHT_RELA:
906367466Sdim	case SHT_SYMTAB:
907367466Sdim		return (class == ELFCLASS64 ? 8 : 4);
908367466Sdim	case SHT_SUNW_move:
909367466Sdim		return (8);
910367466Sdim	case SHT_GNU_LIBLIST:
911367466Sdim	case SHT_GROUP:
912367466Sdim	case SHT_HASH:
913367466Sdim	case SHT_NOTE:
914367466Sdim	case SHT_SUNW_verdef:	/* == SHT_GNU_verdef */
915367466Sdim	case SHT_SUNW_verneed:	/* == SHT_GNU_verneed */
916367466Sdim	case SHT_SYMTAB_SHNDX:
917367466Sdim		return (4);
918367466Sdim	case SHT_SUNW_syminfo:
919367466Sdim	case SHT_SUNW_versym:	/* == SHT_GNU_versym */
920367466Sdim		return (2);
921367466Sdim	case SHT_NOBITS:
922367466Sdim	case SHT_PROGBITS:
923367466Sdim	case SHT_STRTAB:
924367466Sdim	case SHT_SUNW_dof:
925367466Sdim		return (1);
926367466Sdim	}
927367466Sdim	return (1);
928367466Sdim}
929367466Sdim
930260684Skaiwvoid
931260684Skaiwresync_sections(struct elfcopy *ecp)
932260684Skaiw{
933260684Skaiw	struct section	*s, *ps;
934260684Skaiw	GElf_Shdr	 osh;
935260684Skaiw	uint64_t	 off;
936260684Skaiw	int		 first;
937367466Sdim	int		 min_alignment;
938260684Skaiw
939260684Skaiw	ps = NULL;
940260684Skaiw	first = 1;
941260684Skaiw	off = 0;
942260684Skaiw	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
943260684Skaiw		if (first) {
944260684Skaiw			off = s->off;
945260684Skaiw			first = 0;
946260684Skaiw		}
947260684Skaiw
948276398Semaste		/*
949276398Semaste		 * Ignore TLS sections with load address 0 and without
950276398Semaste		 * content. We don't need to adjust their file offset or
951276398Semaste		 * VMA, only the size matters.
952276398Semaste		 */
953276398Semaste		if (s->seg_tls != NULL && s->type == SHT_NOBITS &&
954276398Semaste		    s->off == 0)
955276398Semaste			continue;
956276398Semaste
957260684Skaiw		/* Align section offset. */
958277181Semaste		if (s->align == 0)
959277181Semaste			s->align = 1;
960367466Sdim		min_alignment = section_type_alignment(s->type, ecp->oec);
961367466Sdim		if (s->align < INT_MAX && (int)s->align < min_alignment) {
962367466Sdim			warnx("section %s alignment %d increased to %d",
963367466Sdim			    s->name, (int)s->align, min_alignment);
964367466Sdim			s->align = min_alignment;
965367466Sdim		}
966260684Skaiw		if (off <= s->off) {
967295577Semaste			if (!s->loadable || (ecp->flags & RELOCATABLE))
968260684Skaiw				s->off = roundup(off, s->align);
969260684Skaiw		} else {
970295577Semaste			if (s->loadable && (ecp->flags & RELOCATABLE) == 0)
971275916Semaste				warnx("moving loadable section %s, "
972275916Semaste				    "is this intentional?", s->name);
973260684Skaiw			s->off = roundup(off, s->align);
974260684Skaiw		}
975260684Skaiw
976260684Skaiw		/* Calculate next section offset. */
977260684Skaiw		off = s->off;
978260684Skaiw		if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL))
979260684Skaiw			off += s->sz;
980260684Skaiw
981260684Skaiw		if (s->pseudo) {
982260684Skaiw			ps = NULL;
983260684Skaiw			continue;
984260684Skaiw		}
985260684Skaiw
986260684Skaiw		/* Count padding bytes added through --pad-to. */
987260684Skaiw		if (s->pad_sz > 0)
988260684Skaiw			off += s->pad_sz;
989260684Skaiw
990260684Skaiw		/* Update section header accordingly. */
991260684Skaiw		if (gelf_getshdr(s->os, &osh) == NULL)
992260684Skaiw			errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
993260684Skaiw			    elf_errmsg(-1));
994260684Skaiw		osh.sh_addr = s->vma;
995367466Sdim		osh.sh_addralign = s->align;
996260684Skaiw		osh.sh_offset = s->off;
997260684Skaiw		osh.sh_size = s->sz;
998260684Skaiw		if (!gelf_update_shdr(s->os, &osh))
999260684Skaiw			errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
1000260684Skaiw			    elf_errmsg(-1));
1001260684Skaiw
1002260684Skaiw		/* Add padding for previous section, if need. */
1003260684Skaiw		if (ps != NULL) {
1004260684Skaiw			if (ps->pad_sz > 0) {
1005260684Skaiw				/* Apply padding added by --pad-to. */
1006260684Skaiw				pad_section(ecp, ps);
1007260684Skaiw			} else if ((ecp->flags & GAP_FILL) &&
1008260684Skaiw			    (ps->off + ps->sz < s->off)) {
1009260684Skaiw				/*
1010260684Skaiw				 * Fill the gap between sections by padding
1011260684Skaiw				 * the section with lower address.
1012260684Skaiw				 */
1013260684Skaiw				ps->pad_sz = s->off - (ps->off + ps->sz);
1014260684Skaiw				pad_section(ecp, ps);
1015260684Skaiw			}
1016260684Skaiw		}
1017260684Skaiw
1018260684Skaiw		ps = s;
1019260684Skaiw	}
1020260684Skaiw
1021260684Skaiw	/* Pad the last section, if need. */
1022260684Skaiw	if (ps != NULL && ps->pad_sz > 0)
1023260684Skaiw		pad_section(ecp, ps);
1024260684Skaiw}
1025260684Skaiw
1026260684Skaiwstatic void
1027260684Skaiwmodify_section(struct elfcopy *ecp, struct section *s)
1028260684Skaiw{
1029260684Skaiw	struct sec_action	*sac;
1030260684Skaiw	size_t			 srcsz, dstsz, p, len;
1031260684Skaiw	char			*b, *c, *d, *src, *end;
1032260684Skaiw	int			 dupe;
1033260684Skaiw
1034260684Skaiw	src = read_section(s, &srcsz);
1035260684Skaiw	if (src == NULL || srcsz == 0) {
1036260684Skaiw		/* For empty section, we proceed if we need to append. */
1037260684Skaiw		if (!is_append_section(ecp, s->name))
1038260684Skaiw			return;
1039260684Skaiw	}
1040260684Skaiw
1041260684Skaiw	/* Allocate buffer needed for new section data. */
1042260684Skaiw	dstsz = srcsz;
1043260684Skaiw	if (is_append_section(ecp, s->name)) {
1044260684Skaiw		sac = lookup_sec_act(ecp, s->name, 0);
1045260684Skaiw		dstsz += strlen(sac->string) + 1;
1046260684Skaiw	}
1047260684Skaiw	if ((b = malloc(dstsz)) == NULL)
1048260684Skaiw		err(EXIT_FAILURE, "malloc failed");
1049260684Skaiw	s->buf = b;
1050260684Skaiw
1051260684Skaiw	/* Compress section. */
1052260684Skaiw	p = 0;
1053260684Skaiw	if (is_compress_section(ecp, s->name)) {
1054260684Skaiw		end = src + srcsz;
1055260684Skaiw		for(c = src; c < end;) {
1056260684Skaiw			len = 0;
1057260684Skaiw			while(c + len < end && c[len] != '\0')
1058260684Skaiw				len++;
1059260684Skaiw			if (c + len == end) {
1060260684Skaiw				/* XXX should we warn here? */
1061260684Skaiw				strncpy(&b[p], c, len);
1062260684Skaiw				p += len;
1063260684Skaiw				break;
1064260684Skaiw			}
1065260684Skaiw			dupe = 0;
1066260684Skaiw			for (d = b; d < b + p; ) {
1067260684Skaiw				if (strcmp(d, c) == 0) {
1068260684Skaiw					dupe = 1;
1069260684Skaiw					break;
1070260684Skaiw				}
1071260684Skaiw				d += strlen(d) + 1;
1072260684Skaiw			}
1073260684Skaiw			if (!dupe) {
1074260684Skaiw				strncpy(&b[p], c, len);
1075260684Skaiw				b[p + len] = '\0';
1076260684Skaiw				p += len + 1;
1077260684Skaiw			}
1078260684Skaiw			c += len + 1;
1079260684Skaiw		}
1080260684Skaiw	} else {
1081260684Skaiw		memcpy(b, src, srcsz);
1082260684Skaiw		p += srcsz;
1083260684Skaiw	}
1084260684Skaiw
1085260684Skaiw	/* Append section. */
1086260684Skaiw	if (is_append_section(ecp, s->name)) {
1087260684Skaiw		sac = lookup_sec_act(ecp, s->name, 0);
1088260684Skaiw		len = strlen(sac->string);
1089260684Skaiw		strncpy(&b[p], sac->string, len);
1090260684Skaiw		b[p + len] = '\0';
1091260684Skaiw		p += len + 1;
1092260684Skaiw	}
1093260684Skaiw
1094260684Skaiw	s->sz = p;
1095260684Skaiw	s->nocopy = 1;
1096260684Skaiw}
1097260684Skaiw
1098260684Skaiwstatic void
1099260684Skaiwprint_data(const char *d, size_t sz)
1100260684Skaiw{
1101260684Skaiw	const char *c;
1102260684Skaiw
1103260684Skaiw	for (c = d; c < d + sz; c++) {
1104260684Skaiw		if (*c == '\0')
1105260684Skaiw			putchar('\n');
1106260684Skaiw		else
1107260684Skaiw			putchar(*c);
1108260684Skaiw	}
1109260684Skaiw}
1110260684Skaiw
1111260684Skaiwstatic void
1112260684Skaiwprint_section(struct section *s)
1113260684Skaiw{
1114260684Skaiw	Elf_Data	*id;
1115260684Skaiw	int		 elferr;
1116260684Skaiw
1117260684Skaiw	if (s->buf != NULL && s->sz > 0) {
1118260684Skaiw		print_data(s->buf, s->sz);
1119260684Skaiw	} else {
1120260684Skaiw		id = NULL;
1121295577Semaste		while ((id = elf_getdata(s->is, id)) != NULL ||
1122295577Semaste		    (id = elf_rawdata(s->is, id)) != NULL) {
1123295577Semaste			(void) elf_errno();
1124260684Skaiw			print_data(id->d_buf, id->d_size);
1125295577Semaste		}
1126260684Skaiw		elferr = elf_errno();
1127260684Skaiw		if (elferr != 0)
1128260684Skaiw			errx(EXIT_FAILURE, "elf_getdata() failed: %s",
1129260684Skaiw			    elf_errmsg(elferr));
1130260684Skaiw	}
1131260684Skaiw	putchar('\n');
1132260684Skaiw}
1133260684Skaiw
1134260684Skaiwstatic void *
1135260684Skaiwread_section(struct section *s, size_t *size)
1136260684Skaiw{
1137260684Skaiw	Elf_Data	*id;
1138260684Skaiw	char		*b;
1139260684Skaiw	size_t		 sz;
1140260684Skaiw	int		 elferr;
1141260684Skaiw
1142260684Skaiw	sz = 0;
1143260684Skaiw	b = NULL;
1144260684Skaiw	id = NULL;
1145295577Semaste	while ((id = elf_getdata(s->is, id)) != NULL ||
1146295577Semaste	    (id = elf_rawdata(s->is, id)) != NULL) {
1147295577Semaste		(void) elf_errno();
1148260684Skaiw		if (b == NULL)
1149260684Skaiw			b = malloc(id->d_size);
1150260684Skaiw		else
1151367466Sdim			b = realloc(b, sz + id->d_size);
1152260684Skaiw		if (b == NULL)
1153260684Skaiw			err(EXIT_FAILURE, "malloc or realloc failed");
1154260684Skaiw
1155260684Skaiw		memcpy(&b[sz], id->d_buf, id->d_size);
1156260684Skaiw		sz += id->d_size;
1157260684Skaiw	}
1158260684Skaiw	elferr = elf_errno();
1159260684Skaiw	if (elferr != 0)
1160260684Skaiw		errx(EXIT_FAILURE, "elf_getdata() failed: %s",
1161260684Skaiw		    elf_errmsg(elferr));
1162260684Skaiw
1163260684Skaiw	*size = sz;
1164260684Skaiw
1165260684Skaiw	return (b);
1166260684Skaiw}
1167260684Skaiw
1168260684Skaiwvoid
1169260684Skaiwcopy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
1170260684Skaiw    int sec_flags)
1171260684Skaiw{
1172260684Skaiw	GElf_Shdr ish, osh;
1173260684Skaiw
1174260684Skaiw	if (gelf_getshdr(s->is, &ish) == NULL)
1175295577Semaste		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1176260684Skaiw		    elf_errmsg(-1));
1177260684Skaiw	if (gelf_getshdr(s->os, &osh) == NULL)
1178295577Semaste		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1179260684Skaiw		    elf_errmsg(-1));
1180260684Skaiw
1181260684Skaiw	if (copy)
1182260684Skaiw		(void) memcpy(&osh, &ish, sizeof(ish));
1183260684Skaiw	else {
1184260684Skaiw		osh.sh_type		= s->type;
1185260684Skaiw		osh.sh_addr		= s->vma;
1186260684Skaiw		osh.sh_offset		= s->off;
1187260684Skaiw		osh.sh_size		= s->sz;
1188260684Skaiw		osh.sh_link		= ish.sh_link;
1189260684Skaiw		osh.sh_info		= ish.sh_info;
1190260684Skaiw		osh.sh_addralign	= s->align;
1191260684Skaiw		osh.sh_entsize		= ish.sh_entsize;
1192260684Skaiw
1193260684Skaiw		if (sec_flags) {
1194260684Skaiw			osh.sh_flags = 0;
1195295577Semaste			if (sec_flags & SF_ALLOC)
1196260684Skaiw				osh.sh_flags |= SHF_ALLOC;
1197260684Skaiw			if ((sec_flags & SF_READONLY) == 0)
1198260684Skaiw				osh.sh_flags |= SHF_WRITE;
1199260684Skaiw			if (sec_flags & SF_CODE)
1200260684Skaiw				osh.sh_flags |= SHF_EXECINSTR;
1201295577Semaste			if ((sec_flags & SF_CONTENTS) &&
1202295577Semaste			    s->type == SHT_NOBITS && s->sz > 0) {
1203295577Semaste				/*
1204295577Semaste				 * Convert SHT_NOBITS section to section with
1205295577Semaste				 * (zero'ed) content on file.
1206295577Semaste				 */
1207295577Semaste				osh.sh_type = s->type = SHT_PROGBITS;
1208295577Semaste				if ((s->buf = calloc(1, s->sz)) == NULL)
1209295577Semaste					err(EXIT_FAILURE, "malloc failed");
1210295577Semaste				s->nocopy = 1;
1211295577Semaste			}
1212283616Semaste		} else {
1213260684Skaiw			osh.sh_flags = ish.sh_flags;
1214295577Semaste			/*
1215295577Semaste			 * Newer binutils as(1) emits the section flag
1216295577Semaste			 * SHF_INFO_LINK for relocation sections. elfcopy
1217295577Semaste			 * emits this flag in the output section if it's
1218295577Semaste			 * missing in the input section, to remain compatible
1219295577Semaste			 * with binutils.
1220295577Semaste			 */
1221283616Semaste			if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
1222283616Semaste				osh.sh_flags |= SHF_INFO_LINK;
1223283616Semaste		}
1224260684Skaiw	}
1225260684Skaiw
1226260684Skaiw	if (name == NULL)
1227260684Skaiw		add_to_shstrtab(ecp, s->name);
1228260684Skaiw	else
1229260684Skaiw		add_to_shstrtab(ecp, name);
1230260684Skaiw
1231260684Skaiw	if (!gelf_update_shdr(s->os, &osh))
1232260684Skaiw		errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
1233260684Skaiw		    elf_errmsg(-1));
1234260684Skaiw}
1235260684Skaiw
1236260684Skaiwvoid
1237260684Skaiwcopy_data(struct section *s)
1238260684Skaiw{
1239260684Skaiw	Elf_Data	*id, *od;
1240260684Skaiw	int		 elferr;
1241260684Skaiw
1242260684Skaiw	if (s->nocopy && s->buf == NULL)
1243260684Skaiw		return;
1244260684Skaiw
1245260684Skaiw	if ((id = elf_getdata(s->is, NULL)) == NULL) {
1246295577Semaste		(void) elf_errno();
1247295577Semaste		if ((id = elf_rawdata(s->is, NULL)) == NULL) {
1248295577Semaste			elferr = elf_errno();
1249295577Semaste			if (elferr != 0)
1250295577Semaste				errx(EXIT_FAILURE, "failed to read section:"
1251295577Semaste				    " %s", s->name);
1252295577Semaste			return;
1253295577Semaste		}
1254260684Skaiw	}
1255260684Skaiw
1256260684Skaiw	if ((od = elf_newdata(s->os)) == NULL)
1257260684Skaiw		errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1258260684Skaiw		    elf_errmsg(-1));
1259260684Skaiw
1260260684Skaiw	if (s->nocopy) {
1261260684Skaiw		/* Use s->buf as content if s->nocopy is set. */
1262260684Skaiw		od->d_align	= id->d_align;
1263260684Skaiw		od->d_off	= 0;
1264260684Skaiw		od->d_buf	= s->buf;
1265260684Skaiw		od->d_type	= id->d_type;
1266260684Skaiw		od->d_size	= s->sz;
1267260684Skaiw		od->d_version	= id->d_version;
1268260684Skaiw	} else {
1269260684Skaiw		od->d_align	= id->d_align;
1270260684Skaiw		od->d_off	= id->d_off;
1271260684Skaiw		od->d_buf	= id->d_buf;
1272260684Skaiw		od->d_type	= id->d_type;
1273260684Skaiw		od->d_size	= id->d_size;
1274260684Skaiw		od->d_version	= id->d_version;
1275260684Skaiw	}
1276276398Semaste
1277276398Semaste	/*
1278276398Semaste	 * Alignment Fixup. libelf does not allow the alignment for
1279276398Semaste	 * Elf_Data descriptor to be set to 0. In this case we workaround
1280276398Semaste	 * it by setting the alignment to 1.
1281276398Semaste	 *
1282276398Semaste	 * According to the ELF ABI, alignment 0 and 1 has the same
1283276398Semaste	 * meaning: the section has no alignment constraints.
1284276398Semaste	 */
1285276398Semaste	if (od->d_align == 0)
1286276398Semaste		od->d_align = 1;
1287260684Skaiw}
1288260684Skaiw
1289260684Skaiwstruct section *
1290260684Skaiwcreate_external_section(struct elfcopy *ecp, const char *name, char *newname,
1291260684Skaiw    void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype,
1292260684Skaiw    uint64_t flags, uint64_t align, uint64_t vma, int loadable)
1293260684Skaiw{
1294260684Skaiw	struct section	*s;
1295260684Skaiw	Elf_Scn		*os;
1296260684Skaiw	Elf_Data	*od;
1297260684Skaiw	GElf_Shdr	 osh;
1298260684Skaiw
1299260684Skaiw	if ((os = elf_newscn(ecp->eout)) == NULL)
1300260684Skaiw		errx(EXIT_FAILURE, "elf_newscn() failed: %s",
1301260684Skaiw		    elf_errmsg(-1));
1302260684Skaiw	if ((s = calloc(1, sizeof(*s))) == NULL)
1303260684Skaiw		err(EXIT_FAILURE, "calloc failed");
1304260684Skaiw	s->name = name;
1305260684Skaiw	s->newname = newname;	/* needs to be free()'ed */
1306260684Skaiw	s->off = off;
1307260684Skaiw	s->sz = size;
1308260684Skaiw	s->vma = vma;
1309260684Skaiw	s->align = align;
1310260684Skaiw	s->loadable = loadable;
1311260684Skaiw	s->is = NULL;
1312260684Skaiw	s->os = os;
1313260684Skaiw	s->type = stype;
1314260684Skaiw	s->nocopy = 1;
1315260684Skaiw	insert_to_sec_list(ecp, s, 1);
1316260684Skaiw
1317260684Skaiw	if (gelf_getshdr(os, &osh) == NULL)
1318260684Skaiw		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1319260684Skaiw		    elf_errmsg(-1));
1320260684Skaiw	osh.sh_flags = flags;
1321260684Skaiw	osh.sh_type = s->type;
1322260684Skaiw	osh.sh_addr = s->vma;
1323260684Skaiw	osh.sh_addralign = s->align;
1324260684Skaiw	if (!gelf_update_shdr(os, &osh))
1325260684Skaiw		errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1326260684Skaiw		    elf_errmsg(-1));
1327260684Skaiw	add_to_shstrtab(ecp, name);
1328260684Skaiw
1329260684Skaiw	if (buf != NULL && size != 0) {
1330260684Skaiw		if ((od = elf_newdata(os)) == NULL)
1331260684Skaiw			errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1332260684Skaiw			    elf_errmsg(-1));
1333260684Skaiw		od->d_align = align;
1334260684Skaiw		od->d_off = 0;
1335260684Skaiw		od->d_buf = buf;
1336260684Skaiw		od->d_size = size;
1337260684Skaiw		od->d_type = dtype;
1338260684Skaiw		od->d_version = EV_CURRENT;
1339260684Skaiw	}
1340260684Skaiw
1341260684Skaiw	/*
1342260684Skaiw	 * Clear SYMTAB_INTACT, as we probably need to update/add new
1343260684Skaiw	 * STT_SECTION symbols into the symbol table.
1344260684Skaiw	 */
1345260684Skaiw	ecp->flags &= ~SYMTAB_INTACT;
1346260684Skaiw
1347260684Skaiw	return (s);
1348260684Skaiw}
1349260684Skaiw
1350260684Skaiw/*
1351260684Skaiw * Insert sections specified by --add-section to the end of section list.
1352260684Skaiw */
1353260684Skaiwstatic void
1354260684Skaiwinsert_sections(struct elfcopy *ecp)
1355260684Skaiw{
1356260684Skaiw	struct sec_add	*sa;
1357260684Skaiw	struct section	*s;
1358260684Skaiw	size_t		 off;
1359295577Semaste	uint64_t	 stype;
1360260684Skaiw
1361260684Skaiw	/* Put these sections in the end of current list. */
1362260684Skaiw	off = 0;
1363260684Skaiw	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
1364260684Skaiw		if (s->type != SHT_NOBITS && s->type != SHT_NULL)
1365260684Skaiw			off = s->off + s->sz;
1366260684Skaiw		else
1367260684Skaiw			off = s->off;
1368260684Skaiw	}
1369260684Skaiw
1370260684Skaiw	STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) {
1371260684Skaiw
1372260684Skaiw		/* TODO: Add section header vma/lma, flag changes here */
1373260684Skaiw
1374295577Semaste		/*
1375295577Semaste		 * The default section type for user added section is
1376295577Semaste		 * SHT_PROGBITS. If the section name match certain patterns,
1377295577Semaste		 * elfcopy will try to set a more appropriate section type.
1378295577Semaste		 * However, data type is always set to ELF_T_BYTE and no
1379295577Semaste		 * translation is performed by libelf.
1380295577Semaste		 */
1381295577Semaste		stype = SHT_PROGBITS;
1382295577Semaste		if (strcmp(sa->name, ".note") == 0 ||
1383295577Semaste		    strncmp(sa->name, ".note.", strlen(".note.")) == 0)
1384295577Semaste			stype = SHT_NOTE;
1385295577Semaste
1386260684Skaiw		(void) create_external_section(ecp, sa->name, NULL, sa->content,
1387295577Semaste		    sa->size, off, stype, ELF_T_BYTE, 0, 1, 0, 0);
1388260684Skaiw	}
1389260684Skaiw}
1390260684Skaiw
1391260684Skaiwvoid
1392260684Skaiwadd_to_shstrtab(struct elfcopy *ecp, const char *name)
1393260684Skaiw{
1394260684Skaiw
1395367466Sdim	if (elftc_string_table_insert(ecp->shstrtab->strtab, name) == 0)
1396367466Sdim		errx(EXIT_FAILURE, "elftc_string_table_insert failed");
1397260684Skaiw}
1398260684Skaiw
1399260684Skaiwvoid
1400260684Skaiwupdate_shdr(struct elfcopy *ecp, int update_link)
1401260684Skaiw{
1402260684Skaiw	struct section	*s;
1403260684Skaiw	GElf_Shdr	 osh;
1404260684Skaiw	int		 elferr;
1405260684Skaiw
1406367466Sdim	/* Finalize the section name string table (.shstrtab). */
1407367466Sdim	set_shstrtab(ecp);
1408367466Sdim
1409260684Skaiw	TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
1410260684Skaiw		if (s->pseudo)
1411260684Skaiw			continue;
1412260684Skaiw
1413260684Skaiw		if (gelf_getshdr(s->os, &osh) == NULL)
1414295577Semaste			errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
1415260684Skaiw			    elf_errmsg(-1));
1416260684Skaiw
1417260684Skaiw		/* Find section name in string table and set sh_name. */
1418367466Sdim		osh.sh_name = elftc_string_table_lookup(ecp->shstrtab->strtab,
1419367466Sdim		    s->name);
1420260684Skaiw
1421260684Skaiw		/*
1422260684Skaiw		 * sh_link needs to be updated, since the index of the
1423260684Skaiw		 * linked section might have changed.
1424260684Skaiw		 */
1425260684Skaiw		if (update_link && osh.sh_link != 0)
1426260684Skaiw			osh.sh_link = ecp->secndx[osh.sh_link];
1427260684Skaiw
1428260684Skaiw		/*
1429260684Skaiw		 * sh_info of relocation section links to the section to which
1430260684Skaiw		 * its relocation info applies. So it may need update as well.
1431260684Skaiw		 */
1432260684Skaiw		if ((s->type == SHT_REL || s->type == SHT_RELA) &&
1433260684Skaiw		    osh.sh_info != 0)
1434260684Skaiw			osh.sh_info = ecp->secndx[osh.sh_info];
1435260684Skaiw
1436282918Semaste		/*
1437282918Semaste		 * sh_info of SHT_GROUP section needs to point to the correct
1438282918Semaste		 * string in the symbol table.
1439282918Semaste		 */
1440282918Semaste		if (s->type == SHT_GROUP && (ecp->flags & SYMTAB_EXIST) &&
1441282918Semaste		    (ecp->flags & SYMTAB_INTACT) == 0)
1442282918Semaste			osh.sh_info = ecp->symndx[osh.sh_info];
1443282918Semaste
1444260684Skaiw		if (!gelf_update_shdr(s->os, &osh))
1445260684Skaiw			errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1446260684Skaiw			    elf_errmsg(-1));
1447260684Skaiw	}
1448260684Skaiw	elferr = elf_errno();
1449260684Skaiw	if (elferr != 0)
1450260684Skaiw		errx(EXIT_FAILURE, "elf_nextscn failed: %s",
1451260684Skaiw		    elf_errmsg(elferr));
1452260684Skaiw}
1453260684Skaiw
1454260684Skaiwvoid
1455260684Skaiwinit_shstrtab(struct elfcopy *ecp)
1456260684Skaiw{
1457367466Sdim	Elf_Scn *shstrtab;
1458367466Sdim	GElf_Shdr shdr;
1459260684Skaiw	struct section *s;
1460367466Sdim	size_t indx, sizehint;
1461260684Skaiw
1462367466Sdim	if (elf_getshdrstrndx(ecp->ein, &indx) == 0) {
1463367466Sdim		shstrtab = elf_getscn(ecp->ein, indx);
1464367466Sdim		if (shstrtab == NULL)
1465367466Sdim			errx(EXIT_FAILURE, "elf_getscn failed: %s",
1466367466Sdim			    elf_errmsg(-1));
1467367466Sdim		if (gelf_getshdr(shstrtab, &shdr) != &shdr)
1468367466Sdim			errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
1469367466Sdim			    elf_errmsg(-1));
1470367466Sdim		sizehint = shdr.sh_size;
1471367466Sdim	} else {
1472367466Sdim		/* Clear the error from elf_getshdrstrndx(3). */
1473367466Sdim		(void)elf_errno();
1474367466Sdim		sizehint = 0;
1475367466Sdim	}
1476367466Sdim
1477260684Skaiw	if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL)
1478260684Skaiw		err(EXIT_FAILURE, "calloc failed");
1479260684Skaiw	s = ecp->shstrtab;
1480260684Skaiw	s->name = ".shstrtab";
1481260684Skaiw	s->is = NULL;
1482260684Skaiw	s->sz = 0;
1483260684Skaiw	s->align = 1;
1484260684Skaiw	s->loadable = 0;
1485260684Skaiw	s->type = SHT_STRTAB;
1486260684Skaiw	s->vma = 0;
1487367466Sdim	s->strtab = elftc_string_table_create(sizehint);
1488276061Semaste
1489367466Sdim	add_to_shstrtab(ecp, "");
1490367466Sdim	add_to_shstrtab(ecp, ".symtab");
1491367466Sdim	add_to_shstrtab(ecp, ".strtab");
1492367466Sdim	add_to_shstrtab(ecp, ".shstrtab");
1493260684Skaiw}
1494260684Skaiw
1495367466Sdimstatic void
1496260684Skaiwset_shstrtab(struct elfcopy *ecp)
1497260684Skaiw{
1498260684Skaiw	struct section	*s;
1499260684Skaiw	Elf_Data	*data;
1500260684Skaiw	GElf_Shdr	 sh;
1501367466Sdim	const char	*image;
1502367466Sdim	size_t		 sz;
1503260684Skaiw
1504260684Skaiw	s = ecp->shstrtab;
1505260684Skaiw
1506284339Semaste	if (s->os == NULL) {
1507284339Semaste		/* Input object does not contain .shstrtab section */
1508284339Semaste		if ((s->os = elf_newscn(ecp->eout)) == NULL)
1509284339Semaste			errx(EXIT_FAILURE, "elf_newscn failed: %s",
1510284339Semaste			    elf_errmsg(-1));
1511284339Semaste		insert_to_sec_list(ecp, s, 1);
1512284339Semaste	}
1513284339Semaste
1514260684Skaiw	if (gelf_getshdr(s->os, &sh) == NULL)
1515295577Semaste		errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1516260684Skaiw		    elf_errmsg(-1));
1517260684Skaiw	sh.sh_addr	= 0;
1518260684Skaiw	sh.sh_addralign	= 1;
1519260684Skaiw	sh.sh_offset	= s->off;
1520260684Skaiw	sh.sh_type	= SHT_STRTAB;
1521260684Skaiw	sh.sh_flags	= 0;
1522260684Skaiw	sh.sh_entsize	= 0;
1523260684Skaiw	sh.sh_info	= 0;
1524260684Skaiw	sh.sh_link	= 0;
1525260684Skaiw
1526260684Skaiw	if ((data = elf_newdata(s->os)) == NULL)
1527260684Skaiw		errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1528260684Skaiw		    elf_errmsg(-1));
1529260684Skaiw
1530260684Skaiw	/*
1531260684Skaiw	 * If we don't have a symbol table, skip those a few bytes
1532260684Skaiw	 * which are reserved for this in the beginning of shstrtab.
1533260684Skaiw	 */
1534260684Skaiw	if (!(ecp->flags & SYMTAB_EXIST)) {
1535367466Sdim		elftc_string_table_remove(s->strtab, ".symtab");
1536367466Sdim		elftc_string_table_remove(s->strtab, ".strtab");
1537260684Skaiw	}
1538260684Skaiw
1539367466Sdim	image = elftc_string_table_image(s->strtab, &sz);
1540367466Sdim	s->sz = sz;
1541367466Sdim
1542367466Sdim	sh.sh_size	= sz;
1543260684Skaiw	if (!gelf_update_shdr(s->os, &sh))
1544260684Skaiw		errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1545260684Skaiw		    elf_errmsg(-1));
1546260684Skaiw
1547260684Skaiw	data->d_align	= 1;
1548367466Sdim	data->d_buf	= (void *)(uintptr_t)image;
1549367466Sdim	data->d_size	= sz;
1550260684Skaiw	data->d_off	= 0;
1551260684Skaiw	data->d_type	= ELF_T_BYTE;
1552260684Skaiw	data->d_version	= EV_CURRENT;
1553260684Skaiw
1554260684Skaiw	if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os)))
1555260684Skaiw		errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s",
1556260684Skaiw		     elf_errmsg(-1));
1557260684Skaiw}
1558260684Skaiw
1559260684Skaiwvoid
1560260684Skaiwadd_section(struct elfcopy *ecp, const char *arg)
1561260684Skaiw{
1562260684Skaiw	struct sec_add	*sa;
1563260684Skaiw	struct stat	 sb;
1564260684Skaiw	const char	*s, *fn;
1565260684Skaiw	FILE		*fp;
1566260684Skaiw	int		 len;
1567260684Skaiw
1568260684Skaiw	if ((s = strchr(arg, '=')) == NULL)
1569260684Skaiw		errx(EXIT_FAILURE,
1570260684Skaiw		    "illegal format for --add-section option");
1571260684Skaiw	if ((sa = malloc(sizeof(*sa))) == NULL)
1572260684Skaiw		err(EXIT_FAILURE, "malloc failed");
1573260684Skaiw
1574260684Skaiw	len = s - arg;
1575260684Skaiw	if ((sa->name = malloc(len + 1)) == NULL)
1576260684Skaiw		err(EXIT_FAILURE, "malloc failed");
1577260684Skaiw	strncpy(sa->name, arg, len);
1578260684Skaiw	sa->name[len] = '\0';
1579260684Skaiw
1580260684Skaiw	fn = s + 1;
1581260684Skaiw	if (stat(fn, &sb) == -1)
1582260684Skaiw		err(EXIT_FAILURE, "stat failed");
1583260684Skaiw	sa->size = sb.st_size;
1584295577Semaste	if (sa->size > 0) {
1585295577Semaste		if ((sa->content = malloc(sa->size)) == NULL)
1586295577Semaste			err(EXIT_FAILURE, "malloc failed");
1587295577Semaste		if ((fp = fopen(fn, "r")) == NULL)
1588295577Semaste			err(EXIT_FAILURE, "can not open %s", fn);
1589295577Semaste		if (fread(sa->content, 1, sa->size, fp) == 0 ||
1590295577Semaste		    ferror(fp))
1591295577Semaste			err(EXIT_FAILURE, "fread failed");
1592295577Semaste		fclose(fp);
1593295577Semaste	} else
1594295577Semaste		sa->content = NULL;
1595260684Skaiw
1596260684Skaiw	STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
1597260684Skaiw	ecp->flags |= SEC_ADD;
1598260684Skaiw}
1599260684Skaiw
1600260684Skaiwvoid
1601260684Skaiwfree_sec_add(struct elfcopy *ecp)
1602260684Skaiw{
1603260684Skaiw	struct sec_add *sa, *sa_temp;
1604260684Skaiw
1605260684Skaiw	STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) {
1606260684Skaiw		STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list);
1607260684Skaiw		free(sa->name);
1608260684Skaiw		free(sa->content);
1609260684Skaiw		free(sa);
1610260684Skaiw	}
1611260684Skaiw}
1612260684Skaiw
1613260684Skaiwstatic void
1614260684Skaiwadd_gnu_debuglink(struct elfcopy *ecp)
1615260684Skaiw{
1616260684Skaiw	struct sec_add	*sa;
1617260684Skaiw	struct stat	 sb;
1618260684Skaiw	FILE		*fp;
1619260684Skaiw	char		*fnbase, *buf;
1620260684Skaiw	int		 crc_off;
1621260684Skaiw	int		 crc;
1622260684Skaiw
1623260684Skaiw	if (ecp->debuglink == NULL)
1624260684Skaiw		return;
1625260684Skaiw
1626260684Skaiw	/* Read debug file content. */
1627260684Skaiw	if ((sa = malloc(sizeof(*sa))) == NULL)
1628260684Skaiw		err(EXIT_FAILURE, "malloc failed");
1629260684Skaiw	if ((sa->name = strdup(".gnu_debuglink")) == NULL)
1630260684Skaiw		err(EXIT_FAILURE, "strdup failed");
1631260684Skaiw	if (stat(ecp->debuglink, &sb) == -1)
1632260684Skaiw		err(EXIT_FAILURE, "stat failed");
1633296391Semaste	if (sb.st_size == 0)
1634296391Semaste		errx(EXIT_FAILURE, "empty debug link target %s",
1635296391Semaste		    ecp->debuglink);
1636260684Skaiw	if ((buf = malloc(sb.st_size)) == NULL)
1637260684Skaiw		err(EXIT_FAILURE, "malloc failed");
1638260684Skaiw	if ((fp = fopen(ecp->debuglink, "r")) == NULL)
1639260684Skaiw		err(EXIT_FAILURE, "can not open %s", ecp->debuglink);
1640260684Skaiw	if (fread(buf, 1, sb.st_size, fp) == 0 ||
1641260684Skaiw	    ferror(fp))
1642260684Skaiw		err(EXIT_FAILURE, "fread failed");
1643260684Skaiw	fclose(fp);
1644260684Skaiw
1645260684Skaiw	/* Calculate crc checksum.  */
1646260684Skaiw	crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF);
1647260684Skaiw	free(buf);
1648260684Skaiw
1649260684Skaiw	/* Calculate section size and the offset to store crc checksum. */
1650260684Skaiw	if ((fnbase = basename(ecp->debuglink)) == NULL)
1651260684Skaiw		err(EXIT_FAILURE, "basename failed");
1652260684Skaiw	crc_off = roundup(strlen(fnbase) + 1, 4);
1653260684Skaiw	sa->size = crc_off + 4;
1654260684Skaiw
1655260684Skaiw	/* Section content. */
1656260684Skaiw	if ((sa->content = calloc(1, sa->size)) == NULL)
1657260684Skaiw		err(EXIT_FAILURE, "malloc failed");
1658260684Skaiw	strncpy(sa->content, fnbase, strlen(fnbase));
1659260684Skaiw	if (ecp->oed == ELFDATA2LSB) {
1660260684Skaiw		sa->content[crc_off] = crc & 0xFF;
1661260684Skaiw		sa->content[crc_off + 1] = (crc >> 8) & 0xFF;
1662260684Skaiw		sa->content[crc_off + 2] = (crc >> 16) & 0xFF;
1663260684Skaiw		sa->content[crc_off + 3] = crc >> 24;
1664260684Skaiw	} else {
1665260684Skaiw		sa->content[crc_off] = crc >> 24;
1666260684Skaiw		sa->content[crc_off + 1] = (crc >> 16) & 0xFF;
1667260684Skaiw		sa->content[crc_off + 2] = (crc >> 8) & 0xFF;
1668260684Skaiw		sa->content[crc_off + 3] = crc & 0xFF;
1669260684Skaiw	}
1670260684Skaiw
1671260684Skaiw	STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
1672260684Skaiw	ecp->flags |= SEC_ADD;
1673260684Skaiw}
1674260684Skaiw
1675260684Skaiwstatic uint32_t crctable[256] =
1676260684Skaiw{
1677260684Skaiw	0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
1678260684Skaiw	0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
1679260684Skaiw	0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
1680260684Skaiw	0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
1681260684Skaiw	0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
1682260684Skaiw	0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
1683260684Skaiw	0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
1684260684Skaiw	0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
1685260684Skaiw	0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
1686260684Skaiw	0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
1687260684Skaiw	0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
1688260684Skaiw	0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
1689260684Skaiw	0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
1690260684Skaiw	0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
1691260684Skaiw	0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
1692260684Skaiw	0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
1693260684Skaiw	0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
1694260684Skaiw	0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
1695260684Skaiw	0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
1696260684Skaiw	0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
1697260684Skaiw	0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
1698260684Skaiw	0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
1699260684Skaiw	0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
1700260684Skaiw	0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
1701260684Skaiw	0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
1702260684Skaiw	0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
1703260684Skaiw	0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
1704260684Skaiw	0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
1705260684Skaiw	0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
1706260684Skaiw	0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
1707260684Skaiw	0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
1708260684Skaiw	0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
1709260684Skaiw	0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
1710260684Skaiw	0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
1711260684Skaiw	0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
1712260684Skaiw	0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
1713260684Skaiw	0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
1714260684Skaiw	0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
1715260684Skaiw	0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
1716260684Skaiw	0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
1717260684Skaiw	0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
1718260684Skaiw	0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
1719260684Skaiw	0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
1720260684Skaiw	0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
1721260684Skaiw	0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
1722260684Skaiw	0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
1723260684Skaiw	0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
1724260684Skaiw	0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
1725260684Skaiw	0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
1726260684Skaiw	0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
1727260684Skaiw	0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
1728260684Skaiw	0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
1729260684Skaiw	0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
1730260684Skaiw	0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
1731260684Skaiw	0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
1732260684Skaiw	0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
1733260684Skaiw	0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
1734260684Skaiw	0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
1735260684Skaiw	0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
1736260684Skaiw	0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
1737260684Skaiw	0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
1738260684Skaiw	0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
1739260684Skaiw	0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
1740260684Skaiw	0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
1741260684Skaiw};
1742260684Skaiw
1743260684Skaiwstatic uint32_t
1744260684Skaiwcalc_crc32(const char *p, size_t len, uint32_t crc)
1745260684Skaiw{
1746260684Skaiw	uint32_t i;
1747260684Skaiw
1748260684Skaiw	for (i = 0; i < len; i++) {
1749260684Skaiw		crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
1750260684Skaiw	}
1751260684Skaiw
1752260684Skaiw	return (crc ^ 0xFFFFFFFF);
1753260684Skaiw}
1754