]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/elfcopy/sections.c
Merge ACPICA 20200326.
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / elfcopy / sections.c
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
62 is_remove_section(struct elfcopy *ecp, const char *name)
63 {
64
65         /* Always keep section name table */
66         if (strcmp(name, ".shstrtab") == 0)
67                 return 0;
68         if (strcmp(name, ".symtab") == 0 ||
69             strcmp(name, ".strtab") == 0) {
70                 if (ecp->strip == STRIP_ALL && lookup_symop_list(
71                     ecp, NULL, SYMOP_KEEP) == NULL)
72                         return (1);
73                 else
74                         return (0);
75         }
76
77         if (ecp->strip == STRIP_DWO && is_dwo_section(name))
78                 return (1);
79         if (ecp->strip == STRIP_NONDWO && !is_dwo_section(name))
80                 return (1);
81
82         if (is_debug_section(name)) {
83                 if (ecp->strip == STRIP_ALL ||
84                     ecp->strip == STRIP_DEBUG ||
85                     ecp->strip == STRIP_UNNEEDED ||
86                     (ecp->flags & DISCARD_LOCAL))
87                         return (1);
88                 if (ecp->strip == STRIP_NONDEBUG)
89                         return (0);
90         }
91
92         if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) {
93                 struct sec_action *sac;
94
95                 sac = lookup_sec_act(ecp, name, 0);
96                 if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove)
97                         return (1);
98                 if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy))
99                         return (1);
100         }
101
102         return (0);
103 }
104
105 /*
106  * Relocation section needs to be removed if the section it applies to
107  * will be removed.
108  */
109 int
110 is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info)
111 {
112         const char      *name;
113         GElf_Shdr        ish;
114         Elf_Scn         *is;
115         size_t           indx;
116         int              elferr;
117
118         if (elf_getshstrndx(ecp->ein, &indx) == 0)
119                 errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
120                     elf_errmsg(-1));
121
122         is = 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
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
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
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
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
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
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
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
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*
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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 *
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
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
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
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
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
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
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
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
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
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 }