Merge pull request #616 from rosslagerwall/extable-addend

create-diff-object: Update fixup offsets in .rela__ex_table
This commit is contained in:
Jessica Yu 2016-11-24 20:04:46 -08:00 committed by GitHub
commit dc3ef4d6da

View File

@ -1490,6 +1490,31 @@ 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);
}
}
void kpatch_regenerate_special_section(struct kpatch_elf *kelf,
struct special_section *special,
struct section *sec)
@ -1506,6 +1531,14 @@ 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;
@ -1533,6 +1566,13 @@ 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);
}
}