From: Ross Lagerwall Date: Thu, 10 Nov 2016 14:37:39 +0000 (+0000) Subject: create-diff-object: Update fixup offsets in .rela.ex_table X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=6327ab9c01f6663309cf55f8752492843c070825;p=livepatch-build-tools.git create-diff-object: Update fixup offsets in .rela.ex_table 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. This is a port of kpatch's commit 13d61012f9b2 ("create-diff-object: Update fixup offsets in .rela__ex_table"). Signed-off-by: Ross Lagerwall --- diff --git a/create-diff-object.c b/create-diff-object.c index 69bcd88..bda0014 100644 --- a/create-diff-object.c +++ b/create-diff-object.c @@ -1057,6 +1057,31 @@ 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; + + 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 +1098,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 +1133,12 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf, rela->rela.r_offset = rela->offset; rela->sym->include = 1; + + if (!strcmp(special->name, ".fixup")) + kpatch_update_ex_table_addend(kelf, special, + src_offset, + dest_offset, + group_size); } }