]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/elfcopy/sections.c
MFC r357537, r357538:
[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 3646 2018-10-27 02:25:39Z 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 void
883 resync_sections(struct elfcopy *ecp)
884 {
885         struct section  *s, *ps;
886         GElf_Shdr        osh;
887         uint64_t         off;
888         int              first;
889
890         ps = NULL;
891         first = 1;
892         off = 0;
893         TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
894                 if (first) {
895                         off = s->off;
896                         first = 0;
897                 }
898
899                 /*
900                  * Ignore TLS sections with load address 0 and without
901                  * content. We don't need to adjust their file offset or
902                  * VMA, only the size matters.
903                  */
904                 if (s->seg_tls != NULL && s->type == SHT_NOBITS &&
905                     s->off == 0)
906                         continue;
907
908                 /* Align section offset. */
909                 if (s->align == 0)
910                         s->align = 1;
911                 if (off <= s->off) {
912                         if (!s->loadable || (ecp->flags & RELOCATABLE))
913                                 s->off = roundup(off, s->align);
914                 } else {
915                         if (s->loadable && (ecp->flags & RELOCATABLE) == 0)
916                                 warnx("moving loadable section %s, "
917                                     "is this intentional?", s->name);
918                         s->off = roundup(off, s->align);
919                 }
920
921                 /* Calculate next section offset. */
922                 off = s->off;
923                 if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL))
924                         off += s->sz;
925
926                 if (s->pseudo) {
927                         ps = NULL;
928                         continue;
929                 }
930
931                 /* Count padding bytes added through --pad-to. */
932                 if (s->pad_sz > 0)
933                         off += s->pad_sz;
934
935                 /* Update section header accordingly. */
936                 if (gelf_getshdr(s->os, &osh) == NULL)
937                         errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
938                             elf_errmsg(-1));
939                 osh.sh_addr = s->vma;
940                 osh.sh_offset = s->off;
941                 osh.sh_size = s->sz;
942                 if (!gelf_update_shdr(s->os, &osh))
943                         errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
944                             elf_errmsg(-1));
945
946                 /* Add padding for previous section, if need. */
947                 if (ps != NULL) {
948                         if (ps->pad_sz > 0) {
949                                 /* Apply padding added by --pad-to. */
950                                 pad_section(ecp, ps);
951                         } else if ((ecp->flags & GAP_FILL) &&
952                             (ps->off + ps->sz < s->off)) {
953                                 /*
954                                  * Fill the gap between sections by padding
955                                  * the section with lower address.
956                                  */
957                                 ps->pad_sz = s->off - (ps->off + ps->sz);
958                                 pad_section(ecp, ps);
959                         }
960                 }
961
962                 ps = s;
963         }
964
965         /* Pad the last section, if need. */
966         if (ps != NULL && ps->pad_sz > 0)
967                 pad_section(ecp, ps);
968 }
969
970 static void
971 modify_section(struct elfcopy *ecp, struct section *s)
972 {
973         struct sec_action       *sac;
974         size_t                   srcsz, dstsz, p, len;
975         char                    *b, *c, *d, *src, *end;
976         int                      dupe;
977
978         src = read_section(s, &srcsz);
979         if (src == NULL || srcsz == 0) {
980                 /* For empty section, we proceed if we need to append. */
981                 if (!is_append_section(ecp, s->name))
982                         return;
983         }
984
985         /* Allocate buffer needed for new section data. */
986         dstsz = srcsz;
987         if (is_append_section(ecp, s->name)) {
988                 sac = lookup_sec_act(ecp, s->name, 0);
989                 dstsz += strlen(sac->string) + 1;
990         }
991         if ((b = malloc(dstsz)) == NULL)
992                 err(EXIT_FAILURE, "malloc failed");
993         s->buf = b;
994
995         /* Compress section. */
996         p = 0;
997         if (is_compress_section(ecp, s->name)) {
998                 end = src + srcsz;
999                 for(c = src; c < end;) {
1000                         len = 0;
1001                         while(c + len < end && c[len] != '\0')
1002                                 len++;
1003                         if (c + len == end) {
1004                                 /* XXX should we warn here? */
1005                                 strncpy(&b[p], c, len);
1006                                 p += len;
1007                                 break;
1008                         }
1009                         dupe = 0;
1010                         for (d = b; d < b + p; ) {
1011                                 if (strcmp(d, c) == 0) {
1012                                         dupe = 1;
1013                                         break;
1014                                 }
1015                                 d += strlen(d) + 1;
1016                         }
1017                         if (!dupe) {
1018                                 strncpy(&b[p], c, len);
1019                                 b[p + len] = '\0';
1020                                 p += len + 1;
1021                         }
1022                         c += len + 1;
1023                 }
1024         } else {
1025                 memcpy(b, src, srcsz);
1026                 p += srcsz;
1027         }
1028
1029         /* Append section. */
1030         if (is_append_section(ecp, s->name)) {
1031                 sac = lookup_sec_act(ecp, s->name, 0);
1032                 len = strlen(sac->string);
1033                 strncpy(&b[p], sac->string, len);
1034                 b[p + len] = '\0';
1035                 p += len + 1;
1036         }
1037
1038         s->sz = p;
1039         s->nocopy = 1;
1040 }
1041
1042 static void
1043 print_data(const char *d, size_t sz)
1044 {
1045         const char *c;
1046
1047         for (c = d; c < d + sz; c++) {
1048                 if (*c == '\0')
1049                         putchar('\n');
1050                 else
1051                         putchar(*c);
1052         }
1053 }
1054
1055 static void
1056 print_section(struct section *s)
1057 {
1058         Elf_Data        *id;
1059         int              elferr;
1060
1061         if (s->buf != NULL && s->sz > 0) {
1062                 print_data(s->buf, s->sz);
1063         } else {
1064                 id = NULL;
1065                 while ((id = elf_getdata(s->is, id)) != NULL ||
1066                     (id = elf_rawdata(s->is, id)) != NULL) {
1067                         (void) elf_errno();
1068                         print_data(id->d_buf, id->d_size);
1069                 }
1070                 elferr = elf_errno();
1071                 if (elferr != 0)
1072                         errx(EXIT_FAILURE, "elf_getdata() failed: %s",
1073                             elf_errmsg(elferr));
1074         }
1075         putchar('\n');
1076 }
1077
1078 static void *
1079 read_section(struct section *s, size_t *size)
1080 {
1081         Elf_Data        *id;
1082         char            *b;
1083         size_t           sz;
1084         int              elferr;
1085
1086         sz = 0;
1087         b = NULL;
1088         id = NULL;
1089         while ((id = elf_getdata(s->is, id)) != NULL ||
1090             (id = elf_rawdata(s->is, id)) != NULL) {
1091                 (void) elf_errno();
1092                 if (b == NULL)
1093                         b = malloc(id->d_size);
1094                 else
1095                         b = realloc(b, sz + id->d_size);
1096                 if (b == NULL)
1097                         err(EXIT_FAILURE, "malloc or realloc failed");
1098
1099                 memcpy(&b[sz], id->d_buf, id->d_size);
1100                 sz += id->d_size;
1101         }
1102         elferr = elf_errno();
1103         if (elferr != 0)
1104                 errx(EXIT_FAILURE, "elf_getdata() failed: %s",
1105                     elf_errmsg(elferr));
1106
1107         *size = sz;
1108
1109         return (b);
1110 }
1111
1112 void
1113 copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
1114     int sec_flags)
1115 {
1116         GElf_Shdr ish, osh;
1117
1118         if (gelf_getshdr(s->is, &ish) == NULL)
1119                 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1120                     elf_errmsg(-1));
1121         if (gelf_getshdr(s->os, &osh) == NULL)
1122                 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1123                     elf_errmsg(-1));
1124
1125         if (copy)
1126                 (void) memcpy(&osh, &ish, sizeof(ish));
1127         else {
1128                 osh.sh_type             = s->type;
1129                 osh.sh_addr             = s->vma;
1130                 osh.sh_offset           = s->off;
1131                 osh.sh_size             = s->sz;
1132                 osh.sh_link             = ish.sh_link;
1133                 osh.sh_info             = ish.sh_info;
1134                 osh.sh_addralign        = s->align;
1135                 osh.sh_entsize          = ish.sh_entsize;
1136
1137                 if (sec_flags) {
1138                         osh.sh_flags = 0;
1139                         if (sec_flags & SF_ALLOC)
1140                                 osh.sh_flags |= SHF_ALLOC;
1141                         if ((sec_flags & SF_READONLY) == 0)
1142                                 osh.sh_flags |= SHF_WRITE;
1143                         if (sec_flags & SF_CODE)
1144                                 osh.sh_flags |= SHF_EXECINSTR;
1145                         if ((sec_flags & SF_CONTENTS) &&
1146                             s->type == SHT_NOBITS && s->sz > 0) {
1147                                 /*
1148                                  * Convert SHT_NOBITS section to section with
1149                                  * (zero'ed) content on file.
1150                                  */
1151                                 osh.sh_type = s->type = SHT_PROGBITS;
1152                                 if ((s->buf = calloc(1, s->sz)) == NULL)
1153                                         err(EXIT_FAILURE, "malloc failed");
1154                                 s->nocopy = 1;
1155                         }
1156                 } else {
1157                         osh.sh_flags = ish.sh_flags;
1158                         /*
1159                          * Newer binutils as(1) emits the section flag
1160                          * SHF_INFO_LINK for relocation sections. elfcopy
1161                          * emits this flag in the output section if it's
1162                          * missing in the input section, to remain compatible
1163                          * with binutils.
1164                          */
1165                         if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
1166                                 osh.sh_flags |= SHF_INFO_LINK;
1167                 }
1168         }
1169
1170         if (name == NULL)
1171                 add_to_shstrtab(ecp, s->name);
1172         else
1173                 add_to_shstrtab(ecp, name);
1174
1175         if (!gelf_update_shdr(s->os, &osh))
1176                 errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
1177                     elf_errmsg(-1));
1178 }
1179
1180 void
1181 copy_data(struct section *s)
1182 {
1183         Elf_Data        *id, *od;
1184         int              elferr;
1185
1186         if (s->nocopy && s->buf == NULL)
1187                 return;
1188
1189         if ((id = elf_getdata(s->is, NULL)) == NULL) {
1190                 (void) elf_errno();
1191                 if ((id = elf_rawdata(s->is, NULL)) == NULL) {
1192                         elferr = elf_errno();
1193                         if (elferr != 0)
1194                                 errx(EXIT_FAILURE, "failed to read section:"
1195                                     " %s", s->name);
1196                         return;
1197                 }
1198         }
1199
1200         if ((od = elf_newdata(s->os)) == NULL)
1201                 errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1202                     elf_errmsg(-1));
1203
1204         if (s->nocopy) {
1205                 /* Use s->buf as content if s->nocopy is set. */
1206                 od->d_align     = id->d_align;
1207                 od->d_off       = 0;
1208                 od->d_buf       = s->buf;
1209                 od->d_type      = id->d_type;
1210                 od->d_size      = s->sz;
1211                 od->d_version   = id->d_version;
1212         } else {
1213                 od->d_align     = id->d_align;
1214                 od->d_off       = id->d_off;
1215                 od->d_buf       = id->d_buf;
1216                 od->d_type      = id->d_type;
1217                 od->d_size      = id->d_size;
1218                 od->d_version   = id->d_version;
1219         }
1220
1221         /*
1222          * Alignment Fixup. libelf does not allow the alignment for
1223          * Elf_Data descriptor to be set to 0. In this case we workaround
1224          * it by setting the alignment to 1.
1225          *
1226          * According to the ELF ABI, alignment 0 and 1 has the same
1227          * meaning: the section has no alignment constraints.
1228          */
1229         if (od->d_align == 0)
1230                 od->d_align = 1;
1231 }
1232
1233 struct section *
1234 create_external_section(struct elfcopy *ecp, const char *name, char *newname,
1235     void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype,
1236     uint64_t flags, uint64_t align, uint64_t vma, int loadable)
1237 {
1238         struct section  *s;
1239         Elf_Scn         *os;
1240         Elf_Data        *od;
1241         GElf_Shdr        osh;
1242
1243         if ((os = elf_newscn(ecp->eout)) == NULL)
1244                 errx(EXIT_FAILURE, "elf_newscn() failed: %s",
1245                     elf_errmsg(-1));
1246         if ((s = calloc(1, sizeof(*s))) == NULL)
1247                 err(EXIT_FAILURE, "calloc failed");
1248         s->name = name;
1249         s->newname = newname;   /* needs to be free()'ed */
1250         s->off = off;
1251         s->sz = size;
1252         s->vma = vma;
1253         s->align = align;
1254         s->loadable = loadable;
1255         s->is = NULL;
1256         s->os = os;
1257         s->type = stype;
1258         s->nocopy = 1;
1259         insert_to_sec_list(ecp, s, 1);
1260
1261         if (gelf_getshdr(os, &osh) == NULL)
1262                 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1263                     elf_errmsg(-1));
1264         osh.sh_flags = flags;
1265         osh.sh_type = s->type;
1266         osh.sh_addr = s->vma;
1267         osh.sh_addralign = s->align;
1268         if (!gelf_update_shdr(os, &osh))
1269                 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1270                     elf_errmsg(-1));
1271         add_to_shstrtab(ecp, name);
1272
1273         if (buf != NULL && size != 0) {
1274                 if ((od = elf_newdata(os)) == NULL)
1275                         errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1276                             elf_errmsg(-1));
1277                 od->d_align = align;
1278                 od->d_off = 0;
1279                 od->d_buf = buf;
1280                 od->d_size = size;
1281                 od->d_type = dtype;
1282                 od->d_version = EV_CURRENT;
1283         }
1284
1285         /*
1286          * Clear SYMTAB_INTACT, as we probably need to update/add new
1287          * STT_SECTION symbols into the symbol table.
1288          */
1289         ecp->flags &= ~SYMTAB_INTACT;
1290
1291         return (s);
1292 }
1293
1294 /*
1295  * Insert sections specified by --add-section to the end of section list.
1296  */
1297 static void
1298 insert_sections(struct elfcopy *ecp)
1299 {
1300         struct sec_add  *sa;
1301         struct section  *s;
1302         size_t           off;
1303         uint64_t         stype;
1304
1305         /* Put these sections in the end of current list. */
1306         off = 0;
1307         TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
1308                 if (s->type != SHT_NOBITS && s->type != SHT_NULL)
1309                         off = s->off + s->sz;
1310                 else
1311                         off = s->off;
1312         }
1313
1314         STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) {
1315
1316                 /* TODO: Add section header vma/lma, flag changes here */
1317
1318                 /*
1319                  * The default section type for user added section is
1320                  * SHT_PROGBITS. If the section name match certain patterns,
1321                  * elfcopy will try to set a more appropriate section type.
1322                  * However, data type is always set to ELF_T_BYTE and no
1323                  * translation is performed by libelf.
1324                  */
1325                 stype = SHT_PROGBITS;
1326                 if (strcmp(sa->name, ".note") == 0 ||
1327                     strncmp(sa->name, ".note.", strlen(".note.")) == 0)
1328                         stype = SHT_NOTE;
1329
1330                 (void) create_external_section(ecp, sa->name, NULL, sa->content,
1331                     sa->size, off, stype, ELF_T_BYTE, 0, 1, 0, 0);
1332         }
1333 }
1334
1335 void
1336 add_to_shstrtab(struct elfcopy *ecp, const char *name)
1337 {
1338
1339         if (elftc_string_table_insert(ecp->shstrtab->strtab, name) == 0)
1340                 errx(EXIT_FAILURE, "elftc_string_table_insert failed");
1341 }
1342
1343 void
1344 update_shdr(struct elfcopy *ecp, int update_link)
1345 {
1346         struct section  *s;
1347         GElf_Shdr        osh;
1348         int              elferr;
1349
1350         /* Finalize the section name string table (.shstrtab). */
1351         set_shstrtab(ecp);
1352
1353         TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
1354                 if (s->pseudo)
1355                         continue;
1356
1357                 if (gelf_getshdr(s->os, &osh) == NULL)
1358                         errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
1359                             elf_errmsg(-1));
1360
1361                 /* Find section name in string table and set sh_name. */
1362                 osh.sh_name = elftc_string_table_lookup(ecp->shstrtab->strtab,
1363                     s->name);
1364
1365                 /*
1366                  * sh_link needs to be updated, since the index of the
1367                  * linked section might have changed.
1368                  */
1369                 if (update_link && osh.sh_link != 0)
1370                         osh.sh_link = ecp->secndx[osh.sh_link];
1371
1372                 /*
1373                  * sh_info of relocation section links to the section to which
1374                  * its relocation info applies. So it may need update as well.
1375                  */
1376                 if ((s->type == SHT_REL || s->type == SHT_RELA) &&
1377                     osh.sh_info != 0)
1378                         osh.sh_info = ecp->secndx[osh.sh_info];
1379
1380                 /*
1381                  * sh_info of SHT_GROUP section needs to point to the correct
1382                  * string in the symbol table.
1383                  */
1384                 if (s->type == SHT_GROUP && (ecp->flags & SYMTAB_EXIST) &&
1385                     (ecp->flags & SYMTAB_INTACT) == 0)
1386                         osh.sh_info = ecp->symndx[osh.sh_info];
1387
1388                 if (!gelf_update_shdr(s->os, &osh))
1389                         errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1390                             elf_errmsg(-1));
1391         }
1392         elferr = elf_errno();
1393         if (elferr != 0)
1394                 errx(EXIT_FAILURE, "elf_nextscn failed: %s",
1395                     elf_errmsg(elferr));
1396 }
1397
1398 void
1399 init_shstrtab(struct elfcopy *ecp)
1400 {
1401         Elf_Scn *shstrtab;
1402         GElf_Shdr shdr;
1403         struct section *s;
1404         size_t indx, sizehint;
1405
1406         if (elf_getshdrstrndx(ecp->ein, &indx) == 0) {
1407                 shstrtab = elf_getscn(ecp->ein, indx);
1408                 if (shstrtab == NULL)
1409                         errx(EXIT_FAILURE, "elf_getscn failed: %s",
1410                             elf_errmsg(-1));
1411                 if (gelf_getshdr(shstrtab, &shdr) != &shdr)
1412                         errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
1413                             elf_errmsg(-1));
1414                 sizehint = shdr.sh_size;
1415         } else {
1416                 /* Clear the error from elf_getshdrstrndx(3). */
1417                 (void)elf_errno();
1418                 sizehint = 0;
1419         }
1420
1421         if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL)
1422                 err(EXIT_FAILURE, "calloc failed");
1423         s = ecp->shstrtab;
1424         s->name = ".shstrtab";
1425         s->is = NULL;
1426         s->sz = 0;
1427         s->align = 1;
1428         s->loadable = 0;
1429         s->type = SHT_STRTAB;
1430         s->vma = 0;
1431         s->strtab = elftc_string_table_create(sizehint);
1432
1433         add_to_shstrtab(ecp, "");
1434         add_to_shstrtab(ecp, ".symtab");
1435         add_to_shstrtab(ecp, ".strtab");
1436         add_to_shstrtab(ecp, ".shstrtab");
1437 }
1438
1439 static void
1440 set_shstrtab(struct elfcopy *ecp)
1441 {
1442         struct section  *s;
1443         Elf_Data        *data;
1444         GElf_Shdr        sh;
1445         const char      *image;
1446         size_t           sz;
1447
1448         s = ecp->shstrtab;
1449
1450         if (s->os == NULL) {
1451                 /* Input object does not contain .shstrtab section */
1452                 if ((s->os = elf_newscn(ecp->eout)) == NULL)
1453                         errx(EXIT_FAILURE, "elf_newscn failed: %s",
1454                             elf_errmsg(-1));
1455                 insert_to_sec_list(ecp, s, 1);
1456         }
1457
1458         if (gelf_getshdr(s->os, &sh) == NULL)
1459                 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1460                     elf_errmsg(-1));
1461         sh.sh_addr      = 0;
1462         sh.sh_addralign = 1;
1463         sh.sh_offset    = s->off;
1464         sh.sh_type      = SHT_STRTAB;
1465         sh.sh_flags     = 0;
1466         sh.sh_entsize   = 0;
1467         sh.sh_info      = 0;
1468         sh.sh_link      = 0;
1469
1470         if ((data = elf_newdata(s->os)) == NULL)
1471                 errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1472                     elf_errmsg(-1));
1473
1474         /*
1475          * If we don't have a symbol table, skip those a few bytes
1476          * which are reserved for this in the beginning of shstrtab.
1477          */
1478         if (!(ecp->flags & SYMTAB_EXIST)) {
1479                 elftc_string_table_remove(s->strtab, ".symtab");
1480                 elftc_string_table_remove(s->strtab, ".strtab");
1481         }
1482
1483         image = elftc_string_table_image(s->strtab, &sz);
1484         s->sz = sz;
1485
1486         sh.sh_size      = sz;
1487         if (!gelf_update_shdr(s->os, &sh))
1488                 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1489                     elf_errmsg(-1));
1490
1491         data->d_align   = 1;
1492         data->d_buf     = (void *)(uintptr_t)image;
1493         data->d_size    = sz;
1494         data->d_off     = 0;
1495         data->d_type    = ELF_T_BYTE;
1496         data->d_version = EV_CURRENT;
1497
1498         if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os)))
1499                 errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s",
1500                      elf_errmsg(-1));
1501 }
1502
1503 void
1504 add_section(struct elfcopy *ecp, const char *arg)
1505 {
1506         struct sec_add  *sa;
1507         struct stat      sb;
1508         const char      *s, *fn;
1509         FILE            *fp;
1510         int              len;
1511
1512         if ((s = strchr(arg, '=')) == NULL)
1513                 errx(EXIT_FAILURE,
1514                     "illegal format for --add-section option");
1515         if ((sa = malloc(sizeof(*sa))) == NULL)
1516                 err(EXIT_FAILURE, "malloc failed");
1517
1518         len = s - arg;
1519         if ((sa->name = malloc(len + 1)) == NULL)
1520                 err(EXIT_FAILURE, "malloc failed");
1521         strncpy(sa->name, arg, len);
1522         sa->name[len] = '\0';
1523
1524         fn = s + 1;
1525         if (stat(fn, &sb) == -1)
1526                 err(EXIT_FAILURE, "stat failed");
1527         sa->size = sb.st_size;
1528         if (sa->size > 0) {
1529                 if ((sa->content = malloc(sa->size)) == NULL)
1530                         err(EXIT_FAILURE, "malloc failed");
1531                 if ((fp = fopen(fn, "r")) == NULL)
1532                         err(EXIT_FAILURE, "can not open %s", fn);
1533                 if (fread(sa->content, 1, sa->size, fp) == 0 ||
1534                     ferror(fp))
1535                         err(EXIT_FAILURE, "fread failed");
1536                 fclose(fp);
1537         } else
1538                 sa->content = NULL;
1539
1540         STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
1541         ecp->flags |= SEC_ADD;
1542 }
1543
1544 void
1545 free_sec_add(struct elfcopy *ecp)
1546 {
1547         struct sec_add *sa, *sa_temp;
1548
1549         STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) {
1550                 STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list);
1551                 free(sa->name);
1552                 free(sa->content);
1553                 free(sa);
1554         }
1555 }
1556
1557 static void
1558 add_gnu_debuglink(struct elfcopy *ecp)
1559 {
1560         struct sec_add  *sa;
1561         struct stat      sb;
1562         FILE            *fp;
1563         char            *fnbase, *buf;
1564         int              crc_off;
1565         int              crc;
1566
1567         if (ecp->debuglink == NULL)
1568                 return;
1569
1570         /* Read debug file content. */
1571         if ((sa = malloc(sizeof(*sa))) == NULL)
1572                 err(EXIT_FAILURE, "malloc failed");
1573         if ((sa->name = strdup(".gnu_debuglink")) == NULL)
1574                 err(EXIT_FAILURE, "strdup failed");
1575         if (stat(ecp->debuglink, &sb) == -1)
1576                 err(EXIT_FAILURE, "stat failed");
1577         if (sb.st_size == 0)
1578                 errx(EXIT_FAILURE, "empty debug link target %s",
1579                     ecp->debuglink);
1580         if ((buf = malloc(sb.st_size)) == NULL)
1581                 err(EXIT_FAILURE, "malloc failed");
1582         if ((fp = fopen(ecp->debuglink, "r")) == NULL)
1583                 err(EXIT_FAILURE, "can not open %s", ecp->debuglink);
1584         if (fread(buf, 1, sb.st_size, fp) == 0 ||
1585             ferror(fp))
1586                 err(EXIT_FAILURE, "fread failed");
1587         fclose(fp);
1588
1589         /* Calculate crc checksum.  */
1590         crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF);
1591         free(buf);
1592
1593         /* Calculate section size and the offset to store crc checksum. */
1594         if ((fnbase = basename(ecp->debuglink)) == NULL)
1595                 err(EXIT_FAILURE, "basename failed");
1596         crc_off = roundup(strlen(fnbase) + 1, 4);
1597         sa->size = crc_off + 4;
1598
1599         /* Section content. */
1600         if ((sa->content = calloc(1, sa->size)) == NULL)
1601                 err(EXIT_FAILURE, "malloc failed");
1602         strncpy(sa->content, fnbase, strlen(fnbase));
1603         if (ecp->oed == ELFDATA2LSB) {
1604                 sa->content[crc_off] = crc & 0xFF;
1605                 sa->content[crc_off + 1] = (crc >> 8) & 0xFF;
1606                 sa->content[crc_off + 2] = (crc >> 16) & 0xFF;
1607                 sa->content[crc_off + 3] = crc >> 24;
1608         } else {
1609                 sa->content[crc_off] = crc >> 24;
1610                 sa->content[crc_off + 1] = (crc >> 16) & 0xFF;
1611                 sa->content[crc_off + 2] = (crc >> 8) & 0xFF;
1612                 sa->content[crc_off + 3] = crc & 0xFF;
1613         }
1614
1615         STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
1616         ecp->flags |= SEC_ADD;
1617 }
1618
1619 static uint32_t crctable[256] =
1620 {
1621         0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
1622         0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
1623         0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
1624         0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
1625         0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
1626         0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
1627         0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
1628         0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
1629         0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
1630         0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
1631         0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
1632         0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
1633         0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
1634         0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
1635         0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
1636         0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
1637         0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
1638         0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
1639         0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
1640         0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
1641         0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
1642         0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
1643         0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
1644         0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
1645         0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
1646         0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
1647         0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
1648         0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
1649         0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
1650         0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
1651         0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
1652         0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
1653         0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
1654         0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
1655         0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
1656         0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
1657         0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
1658         0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
1659         0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
1660         0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
1661         0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
1662         0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
1663         0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
1664         0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
1665         0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
1666         0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
1667         0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
1668         0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
1669         0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
1670         0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
1671         0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
1672         0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
1673         0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
1674         0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
1675         0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
1676         0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
1677         0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
1678         0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
1679         0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
1680         0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
1681         0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
1682         0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
1683         0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
1684         0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
1685 };
1686
1687 static uint32_t
1688 calc_crc32(const char *p, size_t len, uint32_t crc)
1689 {
1690         uint32_t i;
1691
1692         for (i = 0; i < len; i++) {
1693                 crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
1694         }
1695
1696         return (crc ^ 0xFFFFFFFF);
1697 }