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