From de10550faeec030366d240e4035a871ea345fa9f Mon Sep 17 00:00:00 2001 From: Joe Lawrence Date: Tue, 29 May 2018 10:50:46 -0400 Subject: [PATCH] create-klp-module: group .kpatch.symbols with like-scope From Oracle's Linker and Libraries Guide [1]: "The symbols in a symbol table are written in the following order ... The global symbols immediately follow the local symbols in the symbol table. The first global symbol is identified by the symbol table sh_info value. Local and global symbols are always kept separate in this manner, and cannot be mixed together." [1] https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/chapter6-79797/index.html Fixes #854. Signed-off-by: Joe Lawrence --- kpatch-build/create-klp-module.c | 21 ++++++++++++++++++++- kpatch-build/kpatch-elf.h | 3 ++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/kpatch-build/create-klp-module.c b/kpatch-build/create-klp-module.c index 00f8f8f..253704b 100644 --- a/kpatch-build/create-klp-module.c +++ b/kpatch-build/create-klp-module.c @@ -81,7 +81,7 @@ static struct symbol *find_or_add_ksym_to_symbols(struct kpatch_elf *kelf, return sym; } - ALLOC_LINK(sym, &kelf->symbols); + ALLOC_LINK(sym, NULL); sym->name = strdup(buf); if (!sym->name) ERROR("strdup"); @@ -93,6 +93,25 @@ static struct symbol *find_or_add_ksym_to_symbols(struct kpatch_elf *kelf, */ sym->sym.st_shndx = SHN_LIVEPATCH; sym->sym.st_info = GELF_ST_INFO(sym->bind, sym->type); + /* + * Figure out where to put the new symbol: + * a) locals need to be grouped together, before globals + * b) globals can be tacked into the end of the list + */ + if (is_local_sym(sym)) { + struct list_head *head; + struct symbol *s; + + head = &kelf->symbols; + list_for_each_entry(s, &kelf->symbols, list) { + if (!is_local_sym(s)) + break; + head = &s->list; + } + list_add_tail(&sym->list, head); + } else { + list_add_tail(&sym->list, &kelf->symbols); + } return sym; } diff --git a/kpatch-build/kpatch-elf.h b/kpatch-build/kpatch-elf.h index 0db35b6..bec6398 100644 --- a/kpatch-build/kpatch-elf.h +++ b/kpatch-build/kpatch-elf.h @@ -128,7 +128,8 @@ struct rela *find_rela_by_offset(struct section *relasec, unsigned int offset); ERROR("malloc"); \ memset((_new), 0, sizeof(*(_new))); \ INIT_LIST_HEAD(&(_new)->list); \ - list_add_tail(&(_new)->list, (_list)); \ + if (_list) \ + list_add_tail(&(_new)->list, (_list)); \ } int offset_of_string(struct list_head *list, char *name);