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