On 11/24/2016 01:08 AM, Konrad Rzeszutek Wilk wrote:
From: Ross Lagerwall <ross.lagerw...@citrix.com>
When pruning entries from the fixup table, update the offsets in
.rela.ex_table otherwise the relas might point to the wrong fixup entry
or even out of the .fixup section.
Signed-off-by: Ross Lagerwall <ross.lagerw...@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <kon...@kernel.org>
---
v2: Squashed fix from kpatch upstream
[see https://github.com/dynup/kpatch/pull/616]
---
create-diff-object.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/create-diff-object.c b/create-diff-object.c
index 69bcd88..58f7c4c 100644
--- a/create-diff-object.c
+++ b/create-diff-object.c
@@ -1057,6 +1057,34 @@ static int should_keep_rela_group(struct section *sec,
int start, int size)
return found;
}
+/*
+ * When updating .fixup, the corresponding addends in .ex_table need to be
+ * updated too. Stash the result in rela.r_addend so that the calculation in
+ * fixup_group_size() is not affected.
+ */
+void kpatch_update_ex_table_addend(struct kpatch_elf *kelf,
+ struct special_section *special,
+ int src_offset, int dest_offset,
+ int group_size)
+{
+ struct rela *rela;
+ struct section *sec;
+
+ if (strcmp(special->name, ".fixup"))
+ return;
As suggested by kpatch upstream, the code would be clearer if the above
check is in kpatch_regenerate_special_section() rather than this function.
I'll update and resend.
+
+ sec = find_section_by_name(&kelf->sections, ".rela.ex_table");
+ if (!sec)
+ ERROR("missing .rela.ex_table section");
+
+ list_for_each_entry(rela, &sec->relas, list) {
+ if (!strcmp(rela->sym->name, ".fixup") &&
+ rela->addend >= src_offset &&
+ rela->addend < src_offset + group_size)
+ rela->rela.r_addend = rela->addend - (src_offset -
dest_offset);
+ }
+}
+
static void kpatch_regenerate_special_section(struct kpatch_elf *kelf,
struct special_section *special,
struct section *sec)
@@ -1073,6 +1101,14 @@ static void kpatch_regenerate_special_section(struct
kpatch_elf *kelf,
if (!dest)
ERROR("malloc");
+ /* Restore the stashed r_addend from kpatch_update_ex_table_addend. */
+ if (!strcmp(special->name, ".ex_table")) {
+ list_for_each_entry(rela, &sec->relas, list) {
+ if (!strcmp(rela->sym->name, ".fixup"))
+ rela->addend = rela->rela.r_addend;
+ }
+ }
+
group_size = 0;
src_offset = 0;
dest_offset = 0;
@@ -1100,6 +1136,11 @@ static void kpatch_regenerate_special_section(struct
kpatch_elf *kelf,
rela->rela.r_offset = rela->offset;
rela->sym->include = 1;
+
+ kpatch_update_ex_table_addend(kelf, special,
+ src_offset,
+ dest_offset,
+ group_size);
}
}
--
Ross Lagerwall
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel