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