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