svn commit: r339726 - stable/12/contrib/elftoolchain/elfcopy
Ed Maste
emaste at FreeBSD.org
Thu Oct 25 15:18:55 UTC 2018
Author: emaste
Date: Thu Oct 25 15:18:54 2018
New Revision: 339726
URL: https://svnweb.freebsd.org/changeset/base/339726
Log:
MFC r339451: objcopy: restore behaviour required by GCC's build
In r339350 filter_reloc() was removed, to fix the case of stripping
statically linked binaries with relocations (which may come from ifunc
use, for example). As a side effect this changed the behaviour when
stripping object files - the output was broken both before and after
r339350, in different ways. Unfortunately GCC's build process relies
on the previous behaviour, so:
- Revert r339350, restoring filter_reloc().
- Fix an unitialized variable use (commited as r3638 in ELF Tool Chain).
- Change filter_reloc() to omit relocations referencing removed
symbols, while retaining relocations with no symbol reference.
- Retain the entire relocation section if it references the dynamic
symbol table (fix from kaiw in D17596).
PR: 232176
Approved by: re (gjb, kib)
Sponsored by: The FreeBSD Foundation
Modified:
stable/12/contrib/elftoolchain/elfcopy/sections.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/contrib/elftoolchain/elfcopy/sections.c
==============================================================================
--- stable/12/contrib/elftoolchain/elfcopy/sections.c Thu Oct 25 15:14:16 2018 (r339725)
+++ stable/12/contrib/elftoolchain/elfcopy/sections.c Thu Oct 25 15:18:54 2018 (r339726)
@@ -39,6 +39,7 @@ ELFTC_VCSID("$Id: sections.c 3443 2016-04-15 18:57:54Z
static void add_gnu_debuglink(struct elfcopy *ecp);
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 filter_reloc(struct elfcopy *ecp, struct section *s);
static int get_section_flags(struct elfcopy *ecp, const char *name);
static void insert_sections(struct elfcopy *ecp);
static void insert_to_strtab(struct section *t, const char *s);
@@ -573,6 +574,14 @@ copy_content(struct elfcopy *ecp)
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
* to be updated since we might have stripped some
* sections and changed section numbering.
@@ -661,6 +670,140 @@ update_section_group(struct elfcopy *ecp, struct secti
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;
}
More information about the svn-src-stable-12
mailing list