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