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