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