Message ID | 1481554354-1992-1-git-send-email-ross.lagerwall@citrix.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, Dec 12, 2016 at 02:52:34PM +0000, Ross Lagerwall wrote: > 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 <ross.lagerwall@citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Thanks! > --- > > Changed in v2: > * Updated to match the patch which went into kpatch. > > create-diff-object.c | 39 +++++++++++++++++++++++++++++++++++++++ > 1 file changed, 39 insertions(+) > > diff --git a/create-diff-object.c b/create-diff-object.c > index b0d1348..f07e727 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); > } > } > > -- > 2.7.4 >
diff --git a/create-diff-object.c b/create-diff-object.c index b0d1348..f07e727 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); } }
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 <ross.lagerwall@citrix.com> --- Changed in v2: * Updated to match the patch which went into kpatch. create-diff-object.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)