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