From 5888f316e63a2cc460180e8ace12d45820cd0d19 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Wed, 20 Sep 2017 23:36:44 -0500 Subject: [PATCH] create-klp-module: support unbundled symbols The create_klp_relasecs_and_syms() 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 --- kpatch-build/create-klp-module.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/kpatch-build/create-klp-module.c b/kpatch-build/create-klp-module.c index 73ceb0e..b18cbe6 100644 --- a/kpatch-build/create-klp-module.c +++ b/kpatch-build/create-klp-module.c @@ -155,9 +155,9 @@ static struct section *find_or_add_klp_relasec(struct kpatch_elf *kelf, static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section *krelasec, struct section *ksymsec, char *strings) { - struct section *base, *klp_relasec; + struct section *klp_relasec; struct kpatch_relocation *krelas; - struct symbol *sym; + struct symbol *sym, *dest; struct rela *rela; char *objname; int nr, index, offset, toc_offset; @@ -207,9 +207,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section */ toc_offset = rela->addend; - base = rela->sym->sec; - if (!base) - ERROR("base sec of krela not found"); + dest = rela->sym; /* Get the name of the object the rela belongs to */ rela = find_rela_by_offset(krelasec->rela, @@ -232,8 +230,8 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section if (!sym) ERROR("error finding or adding ksym to symtab"); - /* Create (or find) the .klp.rela. section for this base sec and object */ - klp_relasec = find_or_add_klp_relasec(kelf, base, objname); + /* Create (or find) the .klp.rela. section for this dest sec and object */ + klp_relasec = find_or_add_klp_relasec(kelf, dest->sec, objname); if (!klp_relasec) ERROR("error finding or adding klp relasec"); @@ -241,10 +239,10 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section ALLOC_LINK(rela, &klp_relasec->relas); rela->sym = sym; rela->type = krelas[index].type; - if (!strcmp(base->name, ".toc")) + if (!strcmp(dest->sec->name, ".toc")) rela->offset = toc_offset; else - rela->offset = krelas[index].offset; + rela->offset = krelas[index].offset + dest->sym.st_value; /* * GCC 6+ adds 0x8 to the offset of every local function entry @@ -253,7 +251,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section * local function becomes global, we don't want to skip the * .toc setup anymore. */ - if (!strcmp(base->name, ".toc") && + if (!strcmp(dest->sec->name, ".toc") && rela->sym->type == STT_FUNC && rela->sym->bind == STB_LOCAL) { rela->addend = 0; } else {