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