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