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