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