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