create-kpatch-module: support unbundled symbols

The create_dynamic_rela_sections() function assumes that all dest
symbols are bundled, i.e. each symbol is located at offset 0 in its own
section.

However that may not always be the case.  Unbundled symbols can occur,
for example, when combining two .o files which have the same bundled
symbol.  They will be combined into the same section and will no longer
be considered "bundled".

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
This commit is contained in:
Josh Poimboeuf 2017-09-20 18:26:57 -05:00
parent 9836f994dc
commit 6c8e90e640

View File

@ -43,7 +43,8 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
struct kpatch_patch_dynrela *dynrelas;
struct kpatch_relocation *krelas;
struct kpatch_symbol *ksym, *ksyms;
struct section *base, *dynsec;
struct section *dynsec;
struct symbol *sym;
struct rela *rela;
int index, nr, offset, dest_offset, objname_offset, name_offset;
@ -58,19 +59,16 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
offset = index * sizeof(*krelas);
/*
* To fill in each dynrela entry, find base section (dest),
* To fill in each dynrela entry, find dest location,
* objname offset, ksym, and symbol name offset
*/
/* Get base section */
/* Get dest location */
rela = find_rela_by_offset(krelasec->rela,
offset + offsetof(struct kpatch_relocation, dest));
if (!rela)
ERROR("find_rela_by_offset");
base = rela->sym->sec;
if (!base)
ERROR("base sec of krela not found");
sym = rela->sym;
dest_offset = rela->addend;
/* Get objname offset */
@ -103,7 +101,7 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
/* dest */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = base->sym ? base->sym : base->secsym;
rela->sym = sym;
rela->type = R_X86_64_64;
rela->addend = dest_offset;
rela->offset = index * sizeof(*dynrelas);