Changeset View
Changeset View
Standalone View
Standalone View
contrib/elftoolchain/elfcopy/sections.c
Show All 33 Lines | |||||
#include "elfcopy.h" | #include "elfcopy.h" | ||||
ELFTC_VCSID("$Id: sections.c 3443 2016-04-15 18:57:54Z kaiwang27 $"); | ELFTC_VCSID("$Id: sections.c 3443 2016-04-15 18:57:54Z kaiwang27 $"); | ||||
static void add_gnu_debuglink(struct elfcopy *ecp); | static void add_gnu_debuglink(struct elfcopy *ecp); | ||||
static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); | static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); | ||||
static void check_section_rename(struct elfcopy *ecp, struct section *s); | static void check_section_rename(struct elfcopy *ecp, struct section *s); | ||||
static void filter_reloc(struct elfcopy *ecp, struct section *s); | |||||
static int get_section_flags(struct elfcopy *ecp, const char *name); | static int get_section_flags(struct elfcopy *ecp, const char *name); | ||||
static void insert_sections(struct elfcopy *ecp); | static void insert_sections(struct elfcopy *ecp); | ||||
static void insert_to_strtab(struct section *t, const char *s); | static void insert_to_strtab(struct section *t, const char *s); | ||||
static int is_append_section(struct elfcopy *ecp, const char *name); | static int is_append_section(struct elfcopy *ecp, const char *name); | ||||
static int is_compress_section(struct elfcopy *ecp, const char *name); | static int is_compress_section(struct elfcopy *ecp, const char *name); | ||||
static int is_debug_section(const char *name); | static int is_debug_section(const char *name); | ||||
static int is_dwo_section(const char *name); | static int is_dwo_section(const char *name); | ||||
static int is_modify_section(struct elfcopy *ecp, const char *name); | static int is_modify_section(struct elfcopy *ecp, const char *name); | ||||
▲ Show 20 Lines • Show All 518 Lines • ▼ Show 20 Lines | TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { | ||||
/* Skip special sections. */ | /* Skip special sections. */ | ||||
if (strcmp(s->name, ".symtab") == 0 || | if (strcmp(s->name, ".symtab") == 0 || | ||||
strcmp(s->name, ".strtab") == 0 || | strcmp(s->name, ".strtab") == 0 || | ||||
strcmp(s->name, ".shstrtab") == 0) | strcmp(s->name, ".shstrtab") == 0) | ||||
continue; | continue; | ||||
/* | /* | ||||
* If strip action is STRIP_ALL, relocation info need | |||||
* to be stripped. Skip filtering otherwisw. | |||||
*/ | |||||
if (ecp->strip == STRIP_ALL && | |||||
(s->type == SHT_REL || s->type == SHT_RELA)) | |||||
filter_reloc(ecp, s); | |||||
/* | |||||
* The section indices in the SHT_GROUP section needs | * The section indices in the SHT_GROUP section needs | ||||
* to be updated since we might have stripped some | * to be updated since we might have stripped some | ||||
* sections and changed section numbering. | * sections and changed section numbering. | ||||
*/ | */ | ||||
if (s->type == SHT_GROUP) | if (s->type == SHT_GROUP) | ||||
update_section_group(ecp, s); | update_section_group(ecp, s); | ||||
if (is_modify_section(ecp, s->name)) | if (is_modify_section(ecp, s->name)) | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | #endif | ||||
for(i = 1, j = 1; (uint64_t)i < n; i++) { | for(i = 1, j = 1; (uint64_t)i < n; i++) { | ||||
if (ws[i] != SHN_UNDEF && ws[i] < ishnum && | if (ws[i] != SHN_UNDEF && ws[i] < ishnum && | ||||
ecp->secndx[ws[i]] != 0) | ecp->secndx[ws[i]] != 0) | ||||
wd[j++] = ecp->secndx[ws[i]]; | wd[j++] = ecp->secndx[ws[i]]; | ||||
else | else | ||||
s->sz -= 4; | s->sz -= 4; | ||||
} | } | ||||
s->nocopy = 1; | |||||
} | |||||
/* | |||||
* Filter relocation entries, only keep those entries whose | |||||
* symbol is in the keep list. | |||||
*/ | |||||
static void | |||||
filter_reloc(struct elfcopy *ecp, struct section *s) | |||||
{ | |||||
const char *name; | |||||
GElf_Shdr ish; | |||||
GElf_Rel rel; | |||||
GElf_Rela rela; | |||||
Elf32_Rel *rel32; | |||||
Elf64_Rel *rel64; | |||||
Elf32_Rela *rela32; | |||||
Elf64_Rela *rela64; | |||||
Elf_Data *id; | |||||
uint64_t cap, n, nrels, sym; | |||||
int elferr, i; | |||||
if (gelf_getshdr(s->is, &ish) == NULL) | |||||
errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", | |||||
elf_errmsg(-1)); | |||||
/* We don't want to touch relocation info for dynamic symbols. */ | |||||
if ((ecp->flags & SYMTAB_EXIST) == 0) { | |||||
/* | |||||
* No symbol table in output. If sh_link points to a section | |||||
* that exists in the output object, this relocation section | |||||
* is for dynamic symbols. Don't touch it. | |||||
*/ | |||||
if (ish.sh_link != 0 && ecp->secndx[ish.sh_link] != 0) | |||||
return; | |||||
} else { | |||||
/* Symbol table exist, check if index equals. */ | |||||
if (ish.sh_link != elf_ndxscn(ecp->symtab->is)) | |||||
return; | |||||
} | |||||
#define COPYREL(REL, SZ) do { \ | |||||
if (nrels == 0) { \ | |||||
if ((REL##SZ = malloc(cap * \ | |||||
sizeof(*REL##SZ))) == NULL) \ | |||||
err(EXIT_FAILURE, "malloc failed"); \ | |||||
} \ | |||||
if (nrels >= cap) { \ | |||||
cap *= 2; \ | |||||
if ((REL##SZ = realloc(REL##SZ, cap * \ | |||||
sizeof(*REL##SZ))) == NULL) \ | |||||
err(EXIT_FAILURE, "realloc failed"); \ | |||||
} \ | |||||
REL##SZ[nrels].r_offset = REL.r_offset; \ | |||||
REL##SZ[nrels].r_info = REL.r_info; \ | |||||
if (s->type == SHT_RELA) \ | |||||
rela##SZ[nrels].r_addend = rela.r_addend; \ | |||||
nrels++; \ | |||||
} while (0) | |||||
nrels = 0; | |||||
cap = 4; /* keep list is usually small. */ | |||||
rel32 = NULL; | |||||
rel64 = NULL; | |||||
rela32 = NULL; | |||||
rela64 = NULL; | |||||
if ((id = elf_getdata(s->is, NULL)) == NULL) | |||||
errx(EXIT_FAILURE, "elf_getdata() failed: %s", | |||||
elf_errmsg(-1)); | |||||
n = ish.sh_size / ish.sh_entsize; | |||||
for(i = 0; (uint64_t)i < n; i++) { | |||||
if (s->type == SHT_REL) { | |||||
if (gelf_getrel(id, i, &rel) != &rel) | |||||
errx(EXIT_FAILURE, "gelf_getrel failed: %s", | |||||
elf_errmsg(-1)); | |||||
sym = GELF_R_SYM(rel.r_info); | |||||
} else { | |||||
if (gelf_getrela(id, i, &rela) != &rela) | |||||
errx(EXIT_FAILURE, "gelf_getrel failed: %s", | |||||
elf_errmsg(-1)); | |||||
sym = GELF_R_SYM(rela.r_info); | |||||
} | |||||
/* | |||||
* If a relocation references a symbol and we are omitting | |||||
* either that symbol or the entire symbol table we cannot | |||||
* produce valid output, and so just omit the relocation. | |||||
* Broken output like this is generally not useful, but some | |||||
* uses of elfcopy/strip rely on it - for example, GCC's build | |||||
* process uses it to check for build reproducibility by | |||||
* stripping objects and comparing them. | |||||
* | |||||
* Relocations that do not reference a symbol are retained. | |||||
*/ | |||||
if (sym != 0) { | |||||
if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) | |||||
continue; | |||||
name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is), | |||||
sym); | |||||
if (name == NULL) | |||||
errx(EXIT_FAILURE, "elf_strptr failed: %s", | |||||
elf_errmsg(-1)); | |||||
if (lookup_symop_list(ecp, name, SYMOP_KEEP) == NULL) | |||||
continue; | |||||
} | |||||
if (ecp->oec == ELFCLASS32) { | |||||
if (s->type == SHT_REL) | |||||
COPYREL(rel, 32); | |||||
else | |||||
COPYREL(rela, 32); | |||||
} else { | |||||
if (s->type == SHT_REL) | |||||
COPYREL(rel, 64); | |||||
else | |||||
COPYREL(rela, 64); | |||||
} | |||||
} | |||||
elferr = elf_errno(); | |||||
if (elferr != 0) | |||||
errx(EXIT_FAILURE, "elf_getdata() failed: %s", | |||||
elf_errmsg(elferr)); | |||||
if (ecp->oec == ELFCLASS32) { | |||||
if (s->type == SHT_REL) | |||||
s->buf = rel32; | |||||
else | |||||
s->buf = rela32; | |||||
} else { | |||||
if (s->type == SHT_REL) | |||||
s->buf = rel64; | |||||
else | |||||
s->buf = rela64; | |||||
} | |||||
s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL : | |||||
ELF_T_RELA), nrels, EV_CURRENT); | |||||
s->nocopy = 1; | s->nocopy = 1; | ||||
} | } | ||||
static void | static void | ||||
update_reloc(struct elfcopy *ecp, struct section *s) | update_reloc(struct elfcopy *ecp, struct section *s) | ||||
{ | { | ||||
GElf_Shdr osh; | GElf_Shdr osh; | ||||
GElf_Rel rel; | GElf_Rel rel; | ||||
▲ Show 20 Lines • Show All 927 Lines • Show Last 20 Lines |