From bdfffa42592d99ccd6a9152235fe030b79e46824 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Tue, 17 Nov 2015 08:06:41 +0000 Subject: [PATCH] Backport "handle reference to end of section" Backport fffbb85b811e21d92f4517e78ead5fb3373185e6: create-diff-object: handle reference to end of section from upstream. Also edit it to work with Xen's code because it is compiled with -fpic. --- create-diff-object.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/create-diff-object.c b/create-diff-object.c index 686834f..6153e7b 100644 --- a/create-diff-object.c +++ b/create-diff-object.c @@ -174,8 +174,47 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf) start = sym->sym.st_value; end = sym->sym.st_value + sym->sym.st_size; - if (rela->addend + add_off < start || - rela->addend + add_off >= end) + if (!is_text_section(sym->sec) && + (rela->type == R_X86_64_32S || + rela->type == R_X86_64_PC32 || + rela->type == R_X86_64_PLT32) && + (rela->addend + add_off) == sym->sec->sh.sh_size && + end == sym->sec->sh.sh_size) { + + /* + * A special case where gcc needs a + * pointer to the address at the end of + * a data section. + * + * This is usually used with a compare + * instruction to determine when to end + * a loop. The code doesn't actually + * dereference the pointer so this is + * "normal" and we just replace the + * section reference with a reference + * to the last symbol in the section. + * + * Note that this only catches the + * issue when it happens at the end of + * a section. It can also happen in + * the middle of a section. In that + * case, the wrong symbol will be + * associated with the reference. But + * that's ok because: + * + * 1) This situation only occurs when + * gcc is trying to get the address + * of the symbol, not the contents + * of its data; and + * + * 2) Because kpatch doesn't allow data + * sections to change, + * &(var1+sizeof(var1)) will always + * be the same as &var2. + */ + + } else if (rela->addend + add_off < start || + rela->addend + add_off >= end) continue; log_debug("%s: replacing %s+%d reference with %s+%d\n", -- 2.39.5