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