replace all unbundled section references with symbols

Currently we're checking for several special cases when deciding whether
to convert unbundled section references to their corresponding symbol
references.  We do it for all unbundled text sections as well as three
specific data sections.

There's no reason I can think of for why we shouldn't just do it for
_all_ unbundled sections.
This commit is contained in:
Josh Poimboeuf 2014-09-12 14:26:37 -05:00
parent a042dc1bbc
commit dbecef6e91

View File

@ -1081,6 +1081,8 @@ void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
struct symbol *sym;
int add_off;
log_debug("\n");
list_for_each_entry(sec, &kelf->sections, list) {
if (!is_rela_section(sec) ||
is_debug_section(sec))
@ -1088,28 +1090,22 @@ void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
list_for_each_entry(rela, &sec->relas, list) {
if (rela->sym->type != STT_SECTION)
continue;
/*
* Replace references to bundled sections with their
* symbols.
*/
if (rela->sym->type == STT_SECTION &&
rela->sym->sec && rela->sym->sec->sym) {
if (rela->sym->sec && rela->sym->sec->sym) {
rela->sym = rela->sym->sec->sym;
continue;
}
/*
* These are special data sections whose data symbols
* aren't bundled with sections when using
* -fdata-sections. We need to replace the section
* references with their corresponding objects.
* Attempt to replace references to unbundled sections
* with their symbols.
*/
if (strcmp(rela->sym->name, ".data..percpu") &&
strcmp(rela->sym->name, ".data..read_mostly") &&
strcmp(rela->sym->name, ".data.unlikely") &&
!(rela->sym->type == STT_SECTION && rela->sym->sec &&
is_text_section(rela->sym->sec)))
continue;
list_for_each_entry(sym, &kelf->symbols, list) {
if (sym->type == STT_SECTION ||
@ -1131,12 +1127,18 @@ void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
if (sym->sym.st_value != rela->addend + add_off)
continue;
log_debug("%s: replacing %s+%d reference with %s+%d\n",
sec->name,
rela->sym->name, rela->addend,
sym->name, rela->addend - add_off);
rela->sym = sym;
rela->addend = -add_off;
break;
}
}
}
log_debug("\n");
}
void kpatch_dump_kelf(struct kpatch_elf *kelf)