create-diff-object: fix ppc64le kpatch_replace_sections_syms() bundling assumption

kpatch_replace_sections_syms() assumes that all bundled symbols start at
section offset zero.  With ppc64le and GCC 6+, that assumption is no
longer accurate.  When replacing a rela symbol section with its
corresponding symbol, adjust the addend as necessary.

Also, with this fix in place, the workaround in
create_klp_relasecs_and_syms() can be removed.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
This commit is contained in:
Josh Poimboeuf 2017-11-08 13:31:46 -06:00
parent bc2d5aa815
commit f0518ef58a
2 changed files with 8 additions and 14 deletions

View File

@ -1113,6 +1113,13 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
*/
if (rela->sym->sec && rela->sym->sec->sym) {
rela->sym = rela->sym->sec->sym;
/*
* ppc64le: a GCC 6+ bundled function is at
* offset 8 in its section.
*/
rela->addend -= rela->sym->sym.st_value;
continue;
}

View File

@ -238,25 +238,12 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
/* Add the rela to the .klp.rela. section */
ALLOC_LINK(rela, &klp_relasec->relas);
rela->sym = sym;
rela->addend = krelas[index].addend;
rela->type = krelas[index].type;
if (!strcmp(dest->sec->name, ".toc"))
rela->offset = toc_offset;
else
rela->offset = krelas[index].offset + dest->sym.st_value;
/*
* GCC 6+ adds 0x8 to the offset of every local function entry
* in the .toc section, for avoiding the setup of the toc when
* the function is called locally. But when the previously
* local function becomes global, we don't want to skip the
* .toc setup anymore.
*/
if (!strcmp(dest->sec->name, ".toc") &&
rela->sym->type == STT_FUNC && rela->sym->bind == STB_LOCAL) {
rela->addend = 0;
} else {
rela->addend = krelas[index].addend;
}
}
}