Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 72 additions & 4 deletions kpatch-build/create-diff-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ struct special_section {
char *name;
enum architecture arch;
int (*group_size)(struct kpatch_elf *kelf, int offset);
bool (*group_filter)(struct lookup_table *lookup,
bool (*group_filter)(struct kpatch_elf *kelf,
struct lookup_table *lookup,
struct section *relasec, unsigned int offset,
unsigned int size);
};
Expand Down Expand Up @@ -2462,7 +2463,72 @@ static int fixup_group_size(struct kpatch_elf *kelf, int offset)
return (int)(rela->addend - offset);
}

static bool jump_table_group_filter(struct lookup_table *lookup,
/*
* Exclude function symbols absent from any rela sections (except
* .rela__bug_table) to eliminate undefined symbols modpost errors.
*/
static bool bug_table_group_filter(struct kpatch_elf *kelf,
struct lookup_table *lookup,
struct section *relasec,
unsigned int group_offset,
unsigned int group_size)
{
unsigned int i = 0, count = 0;
unsigned int *symindex;
struct section *sec;
struct symbol *sym;
struct rela *rela;
bool found;

list_for_each_entry(rela, &relasec->relas, list) {
if (rela->sym->type == STT_FUNC && rela->sym->sec &&
!rela->sym->sec->include)
count++;
}
symindex = (unsigned int *)malloc(sizeof(unsigned int) * count);
if (!symindex)
ERROR("malloc");
list_for_each_entry(rela, &relasec->relas, list) {
if (rela->sym->type == STT_FUNC && rela->sym->sec &&
!rela->sym->sec->include)
symindex[i++] = rela->sym->index;
}
for (i = 0; i < count; i++) {
found = false;
list_for_each_entry(sec, &kelf->sections, list) {
if (!is_rela_section(sec) ||
is_debug_section(sec))
continue;
if (!strcmp(sec->name, relasec->name) ||
!strcmp(sec->name, ".rela__mcount_loc") ||
!sec->include)
continue;
list_for_each_entry(rela, &sec->relas, list) {
if (symindex[i] == rela->sym->index) {
found = true;
break;
}
}
}
if (!found) {
/*
* Function symbol is present in only __bug_table.
* i.e. function symbol was included earlier, but its
* associated section is not included and not
* referenced in any relas. Exclude the function symbol
* to eliminate UND symbols modpost errors.
*/
sym = find_symbol_by_index(&kelf->symbols, symindex[i]);
if (!sym)
ERROR("could not find function symbol\n");
sym->include = 0;
}
}
return true;
}

static bool jump_table_group_filter(struct kpatch_elf *kelf,
struct lookup_table *lookup,
struct section *relasec,
unsigned int group_offset,
unsigned int group_size)
Expand Down Expand Up @@ -2563,7 +2629,8 @@ static bool jump_table_group_filter(struct lookup_table *lookup,
return true;
}

static bool static_call_sites_group_filter(struct lookup_table *lookup,
static bool static_call_sites_group_filter(struct kpatch_elf *kelf,
struct lookup_table *lookup,
struct section *relasec,
unsigned int group_offset,
unsigned int group_size)
Expand Down Expand Up @@ -2630,6 +2697,7 @@ static struct special_section special_sections[] = {
.name = "__bug_table",
.arch = AARCH64 | X86_64 | PPC64 | S390 | LOONGARCH64,
.group_size = bug_table_group_size,
.group_filter = bug_table_group_filter,
},
{
.name = ".fixup",
Expand Down Expand Up @@ -2837,7 +2905,7 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf,
continue;

if (special->group_filter &&
!special->group_filter(lookup, relasec, src_offset, group_size))
!special->group_filter(kelf, lookup, relasec, src_offset, group_size))
continue;

/*
Expand Down
Loading