Merge pull request #353 from spartacus06/group-section-support

Group section support
This commit is contained in:
Josh Poimboeuf 2014-08-11 22:47:41 -05:00
commit 78afb8f999
1 changed files with 64 additions and 8 deletions

View File

@ -101,6 +101,7 @@ struct section {
enum status status;
int include;
int ignore;
int grouped;
union {
struct { /* if (is_rela_section()) */
struct section *base;
@ -681,6 +682,17 @@ void kpatch_correlate_sections(struct list_head *seclist1, struct list_head *sec
list_for_each_entry(sec2, seclist2, list) {
if (strcmp(sec1->name, sec2->name))
continue;
/*
* Group sections must match exactly to be correlated.
* Changed group sections are currently not supported.
*/
if (sec1->sh.sh_type == SHT_GROUP) {
if (sec1->data->d_size != sec2->data->d_size)
continue;
if (memcmp(sec1->data->d_buf, sec2->data->d_buf,
sec1->data->d_size))
continue;
}
sec1->twin = sec2;
sec2->twin = sec1;
/* set initial status, might change */
@ -696,14 +708,21 @@ void kpatch_correlate_symbols(struct list_head *symlist1, struct list_head *syml
list_for_each_entry(sym1, symlist1, list) {
list_for_each_entry(sym2, symlist2, list) {
if (!strcmp(sym1->name, sym2->name) &&
sym1->type == sym2->type) {
sym1->twin = sym2;
sym2->twin = sym1;
/* set initial status, might change */
sym1->status = sym2->status = SAME;
break;
}
if (strcmp(sym1->name, sym2->name) ||
sym1->type != sym2->type)
continue;
/* group section symbols must have correlated sections */
if (sym1->sec &&
sym1->sec->sh.sh_type == SHT_GROUP &&
sym1->sec->twin != sym2->sec)
continue;
sym1->twin = sym2;
sym2->twin = sym1;
/* set initial status, might change */
sym1->status = sym2->status = SAME;
break;
}
}
}
@ -742,6 +761,31 @@ void kpatch_check_program_headers(Elf *elf)
DIFF_FATAL("ELF contains program header");
}
void kpatch_mark_grouped_sections(struct kpatch_elf *kelf)
{
struct section *groupsec, *sec;
unsigned int *data, *end;
list_for_each_entry(groupsec, &kelf->sections, list) {
if (groupsec->sh.sh_type != SHT_GROUP)
continue;
data = groupsec->data->d_buf;
end = groupsec->data->d_buf + groupsec->data->d_size;
data++; /* skip first flag word (e.g. GRP_COMDAT) */
while (data < end) {
sec = find_section_by_index(&kelf->sections, *data);
if (!sec)
ERROR("group section not found");
sec->grouped = 1;
log_debug("marking section %s (%d) as grouped\n",
sec->name, sec->index);
data++;
}
}
}
/*
* When gcc makes compiler optimizations which affect a function's calling
* interface, it mangles the function's name. For example, sysctl_print_dir is
@ -1066,6 +1110,17 @@ void kpatch_verify_patchability(struct kpatch_elf *kelf)
errs++;
}
if (sec->status != SAME && sec->grouped) {
log_normal("changed section %s is part of a section group\n",
sec->name);
errs++;
}
if (sec->sh.sh_type == SHT_GROUP && sec->status == NEW) {
log_normal("new/changed group sections are not supported\n");
errs++;
}
/* ensure we aren't including .data.* or .bss.* */
if (sec->include &&
(!strncmp(sec->name, ".data", 5) ||
@ -2516,6 +2571,7 @@ int main(int argc, char *argv[])
kpatch_check_program_headers(kelf_base->elf);
kpatch_check_program_headers(kelf_patched->elf);
kpatch_mark_grouped_sections(kelf_patched);
kpatch_replace_sections_syms(kelf_base);
kpatch_replace_sections_syms(kelf_patched);
kpatch_rename_mangled_functions(kelf_base, kelf_patched);