From 2560120997403581dd824e5bd2389c719edcbf12 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 10 May 2007 23:03:25 +0100 Subject: kbuild: make modpost section warnings clearer Change modpost section mismatch warnings to be less confusing; model them on the binutils linker warnings which we all know how to interpret. Also, fix the wrong ordering of arguments for the final case - fromsec and refsymname were reversed. Signed-off-by: Russell King Acked-by: Acked-by: David S. Miller Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'scripts/mod/modpost.c') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 113dc77b9f60..2fcdbc7a1ee5 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -885,29 +885,28 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, return; if (before && after) { - warn("%s - Section mismatch: reference to %s:%s from %s " - "between '%s' (at offset 0x%llx) and '%s'\n", - modname, secname, refsymname, fromsec, + warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " + "(between '%s' and '%s')\n", + modname, fromsec, (unsigned long long)r.r_offset, + secname, refsymname, elf->strtab + before->st_name, - (long long)r.r_offset, elf->strtab + after->st_name); } else if (before) { - warn("%s - Section mismatch: reference to %s:%s from %s " - "after '%s' (at offset 0x%llx)\n", - modname, secname, refsymname, fromsec, - elf->strtab + before->st_name, - (long long)r.r_offset); + warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " + "(after '%s')\n", + modname, fromsec, (unsigned long long)r.r_offset, + secname, refsymname, + elf->strtab + before->st_name); } else if (after) { - warn("%s - Section mismatch: reference to %s:%s from %s " + warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " "before '%s' (at offset -0x%llx)\n", - modname, secname, refsymname, fromsec, - elf->strtab + after->st_name, - (long long)r.r_offset); + modname, fromsec, (unsigned long long)r.r_offset, + secname, refsymname, + elf->strtab + after->st_name); } else { - warn("%s - Section mismatch: reference to %s:%s from %s " - "(offset 0x%llx)\n", - modname, secname, fromsec, refsymname, - (long long)r.r_offset); + warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n", + modname, fromsec, (unsigned long long)r.r_offset, + secname, refsymname); } } -- cgit v1.2.3 From f892b7d480eec809a5dfbd6e65742b3f3155e50e Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 17 May 2007 01:14:38 +0900 Subject: kbuild: make better section mismatch reports on i386, arm and mips On i386, ARM and MIPS, warn_sec_mismatch() sometimes fails to show usefull symbol name. This is because empty 'refsym' due to 0 r_addend value. This patch is to adjust r_addend value, consulting with apply_relocate() routine in kernel code. Without this patch: MODPOST vmlinux WARNING: init/built-in.o - Section mismatch: reference to .init.text: from .text between 'rest_init' (at offset 0xf4) and 'try_name' WARNING: mm/built-in.o - Section mismatch: reference to .init.text: from .text between 'kmem_cache_create' (at offset 0x18a39) and 'cache_reap' WARNING: mm/built-in.o - Section mismatch: reference to .init.text: from .text between 'kmem_cache_create' (at offset 0x18a6b) and 'cache_reap' With this patch: MODPOST vmlinux WARNING: mm/built-in.o - Section mismatch: reference to .init.text:set_up_list3s from .text between 'kmem_cache_create' (at offset 0x18a39) and 'cache_reap' WARNING: mm/built-in.o - Section mismatch: reference to .init.text:set_up_list3s from .text between 'kmem_cache_create' (at offset 0x18a6b) and 'cache_reap' Now modpost can detect "kernel_init" name (and whitelist it) and show "set_up_list3s" name. Signed-off-by: Atsushi Nemoto Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'scripts/mod/modpost.c') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2fcdbc7a1ee5..ce7e0d17bae2 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -384,6 +384,7 @@ static int parse_elf(struct elf_info *info, const char *filename) sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); + sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); } /* Find symbol table. */ for (i = 1; i < hdr->e_shnum; i++) { @@ -773,6 +774,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr, for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { if (sym->st_shndx != relsym->st_shndx) continue; + if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) + continue; if (sym->st_value == addr) return sym; } @@ -910,6 +913,68 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, } } +static void addend_386_rel(struct elf_info *elf, int section, Elf_Rela *r) +{ + Elf_Shdr *sechdrs = elf->sechdrs; + unsigned int r_typ; + unsigned int *location; + + r_typ = ELF_R_TYPE(r->r_info); + location = (void *)elf->hdr + + sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; + switch (r_typ) { + case R_386_32: + r->r_addend = TO_NATIVE(*location); + break; + case R_386_PC32: + r->r_addend = TO_NATIVE(*location) + 4; + break; + } +} + +static void addend_arm_rel(struct elf_info *elf, int section, Elf_Rela *r) +{ + Elf_Shdr *sechdrs = elf->sechdrs; + unsigned int r_typ; + unsigned int *location; + + r_typ = ELF_R_TYPE(r->r_info); + location = (void *)elf->hdr + + sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; + switch (r_typ) { + case R_ARM_ABS32: + r->r_addend = TO_NATIVE(*location); + break; + case R_ARM_PC24: + r->r_addend = ((TO_NATIVE(*location) & 0x00ffffff) << 2) + 8; + break; + } +} + +static int addend_mips_rel(struct elf_info *elf, int section, Elf_Rela *r) +{ + Elf_Shdr *sechdrs = elf->sechdrs; + unsigned int r_typ; + unsigned int *location; + unsigned int inst; + + r_typ = ELF_R_TYPE(r->r_info); + if (r_typ == R_MIPS_HI16) + return 1; /* skip this */ + location = (void *)elf->hdr + + sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; + inst = TO_NATIVE(*location); + switch (r_typ) { + case R_MIPS_LO16: + r->r_addend = ((inst & 0xffff) ^ 0x8000) - 0x8000; + break; + case R_MIPS_26: + r->r_addend = (inst & 0x03ffffff) << 2; + break; + } + return 0; +} + /** * A module includes a number of sections that are discarded * either when loaded or when used as built-in. @@ -953,8 +1018,11 @@ static void check_sec_ref(struct module *mod, const char *modname, r.r_offset = TO_NATIVE(rela->r_offset); #if KERNEL_ELFCLASS == ELFCLASS64 if (hdr->e_machine == EM_MIPS) { + unsigned int r_typ; r_sym = ELF64_MIPS_R_SYM(rela->r_info); r_sym = TO_NATIVE(r_sym); + r_typ = ELF64_MIPS_R_TYPE(rela->r_info); + r.r_info = ELF64_R_INFO(r_sym, r_typ); } else { r.r_info = TO_NATIVE(rela->r_info); r_sym = ELF_R_SYM(r.r_info); @@ -987,8 +1055,11 @@ static void check_sec_ref(struct module *mod, const char *modname, r.r_offset = TO_NATIVE(rel->r_offset); #if KERNEL_ELFCLASS == ELFCLASS64 if (hdr->e_machine == EM_MIPS) { + unsigned int r_typ; r_sym = ELF64_MIPS_R_SYM(rel->r_info); r_sym = TO_NATIVE(r_sym); + r_typ = ELF64_MIPS_R_TYPE(rel->r_info); + r.r_info = ELF64_R_INFO(r_sym, r_typ); } else { r.r_info = TO_NATIVE(rel->r_info); r_sym = ELF_R_SYM(r.r_info); @@ -998,6 +1069,14 @@ static void check_sec_ref(struct module *mod, const char *modname, r_sym = ELF_R_SYM(r.r_info); #endif r.r_addend = 0; + if (hdr->e_machine == EM_386) + addend_386_rel(elf, i, &r); + else if (hdr->e_machine == EM_ARM) + addend_arm_rel(elf, i, &r); + else if (hdr->e_machine == EM_MIPS) { + if (addend_mips_rel(elf, i, &r)) + continue; + } sym = elf->symtab_start + r_sym; /* Skip special sections */ if (sym->st_shndx >= SHN_LORESERVE) -- cgit v1.2.3 From cd5477911fc9f5cc64678e2b95cdd606c59a11b5 Mon Sep 17 00:00:00 2001 From: Li Yang Date: Mon, 14 May 2007 18:04:28 +0800 Subject: kbuild: add "Section mismatch" warning whitelist for powerpc This patch fixes the following class of "Section mismatch" warnings when building powerpc platforms. WARNING: arch/powerpc/kernel/built-in.o - Section mismatch: reference to .init.data:.got2 from prom_entry (offset 0x0) WARNING: arch/powerpc/platforms/built-in.o - Section mismatch: reference to .init.text:mpc8313_rdb_probe from .machine.desc after 'mach_mpc8313_rdb' (at offset 0x4) .... Signed-off-by: Li Yang Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'scripts/mod/modpost.c') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index ce7e0d17bae2..2909391a8035 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -650,9 +650,10 @@ static int strrcmp(const char *s, const char *sub) * tosec = .init.text * * Pattern 10: - * ia64 has machvec table for each platform. It is mixture of function - * pointer of .init.text and .text. - * fromsec = .machvec + * ia64 has machvec table for each platform and + * powerpc has a machine desc table for each platform. + * It is mixture of function pointers of .init.text and .text. + * fromsec = .machvec | .machine.desc **/ static int secref_whitelist(const char *modname, const char *tosec, const char *fromsec, const char *atsym, @@ -751,7 +752,8 @@ static int secref_whitelist(const char *modname, const char *tosec, return 1; /* Check for pattern 10 */ - if (strcmp(fromsec, ".machvec") == 0) + if ((strcmp(fromsec, ".machvec") == 0) || + (strcmp(fromsec, ".machine.desc") == 0)) return 1; return 0; @@ -887,6 +889,11 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, elf->strtab + before->st_name, refsymname)) return; + /* fromsec whitelist - without a valid 'before' + * powerpc has a GOT table in .got2 section */ + if (strcmp(fromsec, ".got2") == 0) + return; + if (before && after) { warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " "(between '%s' and '%s')\n", -- cgit v1.2.3 From 0e0d314e6a01bb14d303e35e6f7ba24b17020044 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Thu, 17 May 2007 20:14:48 +0200 Subject: kbuild: introduce __init_refok/__initdata_refok to supress section mismatch warnings Throughout the kernel there are a few legitimite references to init or exit sections. Most of these are covered by the patterns included in modpost but a few nees special attention. To avoid hardcoding a lot of function names in modpost introduce a marker so relevant function/data can be marked. When modpost see a reference to a init/exit function from a function/data marked no warning will be issued. Idea from: Andrew Morton Signed-off-by: Sam Ravnborg Cc: Andrew Morton --- scripts/mod/modpost.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'scripts/mod/modpost.c') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2909391a8035..7c87267b6ff0 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -583,6 +583,12 @@ static int strrcmp(const char *s, const char *sub) /** * Whitelist to allow certain references to pass with no warning. + * + * Pattern 0: + * Do not warn if funtion/data are marked with __init_refok/__initdata_refok. + * The pattern is identified by: + * fromsec = .text.init.refok | .data.init.refok + * * Pattern 1: * If a module parameter is declared __initdata and permissions=0 * then this is legal despite the warning generated. @@ -686,6 +692,11 @@ static int secref_whitelist(const char *modname, const char *tosec, NULL }; + /* Check for pattern 0 */ + if ((strcmp(fromsec, ".text.init.refok") == 0) || + (strcmp(fromsec, ".data.init.refok") == 0)) + return 1; + /* Check for pattern 1 */ if (strcmp(tosec, ".init.data") != 0) f1 = 0; -- cgit v1.2.3 From 92080309df1975729a9f8b45fd56528817e34db8 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Thu, 17 May 2007 20:43:54 +0200 Subject: init/main: use __init_refok to fix section mismatch Kill a special case in modpost by introducing the __init_refok marker. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'scripts/mod/modpost.c') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 7c87267b6ff0..40fb7b6a00b1 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -626,14 +626,6 @@ static int strrcmp(const char *s, const char *sub) * This pattern is identified by * refsymname = __init_begin, _sinittext, _einittext * - * Pattern 6: - * During the early init phase we have references from .init.text to - * .text we have an intended section mismatch - do not warn about it. - * See kernel_init() in init/main.c - * tosec = .init.text - * fromsec = .text - * atsym = kernel_init - * * Pattern 7: * Logos used in drivers/video/logo reside in __initdata but the * funtion that references them are EXPORT_SYMBOL() so cannot be @@ -738,12 +730,6 @@ static int secref_whitelist(const char *modname, const char *tosec, if (strcmp(refsymname, *s) == 0) return 1; - /* Check for pattern 6 */ - if ((strcmp(tosec, ".init.text") == 0) && - (strcmp(fromsec, ".text") == 0) && - (strcmp(refsymname, "kernel_init") == 0)) - return 1; - /* Check for pattern 7 */ if ((strcmp(tosec, ".init.data") == 0) && (strncmp(fromsec, ".text", strlen(".text")) == 0) && -- cgit v1.2.3 From 577a32f620271416d05f852477151fb51c790bc6 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Thu, 17 May 2007 23:29:25 +0200 Subject: mm: fix section mismatch warnings modpost had two cases hardcoded for mm/ Shift over to __init_refok and kill the hardcoded function names in modpost. This has the drawback that the functions will always be kept no matter configuration. With previous code the function were placed in init section if configuration allowed it. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'scripts/mod/modpost.c') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 40fb7b6a00b1..8424d1f53bbe 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -641,12 +641,6 @@ static int strrcmp(const char *s, const char *sub) * tosec = .init.text * fromsec = .paravirtprobe * - * Pattern 9: - * Some of functions are common code between boot time and hotplug - * time. The bootmem allocater is called only boot time in its - * functions. So it's ok to reference. - * tosec = .init.text - * * Pattern 10: * ia64 has machvec table for each platform and * powerpc has a machine desc table for each platform. @@ -678,12 +672,6 @@ static int secref_whitelist(const char *modname, const char *tosec, NULL }; - const char *pat4sym[] = { - "sparse_index_alloc", - "zone_wait_table_init", - NULL - }; - /* Check for pattern 0 */ if ((strcmp(fromsec, ".text.init.refok") == 0) || (strcmp(fromsec, ".data.init.refok") == 0)) @@ -741,13 +729,6 @@ static int secref_whitelist(const char *modname, const char *tosec, (strcmp(fromsec, ".paravirtprobe") == 0)) return 1; - /* Check for pattern 9 */ - if ((strcmp(tosec, ".init.text") == 0) && - (strcmp(fromsec, ".text") == 0)) - for (s = pat4sym; *s; s++) - if (strcmp(atsym, *s) == 0) - return 1; - /* Check for pattern 10 */ if ((strcmp(fromsec, ".machvec") == 0) || (strcmp(fromsec, ".machine.desc") == 0)) -- cgit v1.2.3 From efa5bf1dd2cf3cdee0bfe97cfd76ff2296179ae4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 21 May 2007 18:41:17 -0700 Subject: Revert "kbuild: make better section mismatch reports on i386, arm and mips" This reverts commit f892b7d480eec809a5dfbd6e65742b3f3155e50e, which totally broke the build on x86 with CONFIG_RELOCATABLE (which, as far as I can tell, is the only case where it should even matter!) due to a SIGSEGV in modpost. Cc: Sam Ravnborg Cc: Atsushi Nemoto Signed-off-by: Linus Torvalds --- scripts/mod/modpost.c | 79 --------------------------------------------------- 1 file changed, 79 deletions(-) (limited to 'scripts/mod/modpost.c') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 8424d1f53bbe..8e5610d428c5 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -384,7 +384,6 @@ static int parse_elf(struct elf_info *info, const char *filename) sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); - sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); } /* Find symbol table. */ for (i = 1; i < hdr->e_shnum; i++) { @@ -754,8 +753,6 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr, for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { if (sym->st_shndx != relsym->st_shndx) continue; - if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) - continue; if (sym->st_value == addr) return sym; } @@ -898,68 +895,6 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, } } -static void addend_386_rel(struct elf_info *elf, int section, Elf_Rela *r) -{ - Elf_Shdr *sechdrs = elf->sechdrs; - unsigned int r_typ; - unsigned int *location; - - r_typ = ELF_R_TYPE(r->r_info); - location = (void *)elf->hdr + - sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; - switch (r_typ) { - case R_386_32: - r->r_addend = TO_NATIVE(*location); - break; - case R_386_PC32: - r->r_addend = TO_NATIVE(*location) + 4; - break; - } -} - -static void addend_arm_rel(struct elf_info *elf, int section, Elf_Rela *r) -{ - Elf_Shdr *sechdrs = elf->sechdrs; - unsigned int r_typ; - unsigned int *location; - - r_typ = ELF_R_TYPE(r->r_info); - location = (void *)elf->hdr + - sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; - switch (r_typ) { - case R_ARM_ABS32: - r->r_addend = TO_NATIVE(*location); - break; - case R_ARM_PC24: - r->r_addend = ((TO_NATIVE(*location) & 0x00ffffff) << 2) + 8; - break; - } -} - -static int addend_mips_rel(struct elf_info *elf, int section, Elf_Rela *r) -{ - Elf_Shdr *sechdrs = elf->sechdrs; - unsigned int r_typ; - unsigned int *location; - unsigned int inst; - - r_typ = ELF_R_TYPE(r->r_info); - if (r_typ == R_MIPS_HI16) - return 1; /* skip this */ - location = (void *)elf->hdr + - sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; - inst = TO_NATIVE(*location); - switch (r_typ) { - case R_MIPS_LO16: - r->r_addend = ((inst & 0xffff) ^ 0x8000) - 0x8000; - break; - case R_MIPS_26: - r->r_addend = (inst & 0x03ffffff) << 2; - break; - } - return 0; -} - /** * A module includes a number of sections that are discarded * either when loaded or when used as built-in. @@ -1003,11 +938,8 @@ static void check_sec_ref(struct module *mod, const char *modname, r.r_offset = TO_NATIVE(rela->r_offset); #if KERNEL_ELFCLASS == ELFCLASS64 if (hdr->e_machine == EM_MIPS) { - unsigned int r_typ; r_sym = ELF64_MIPS_R_SYM(rela->r_info); r_sym = TO_NATIVE(r_sym); - r_typ = ELF64_MIPS_R_TYPE(rela->r_info); - r.r_info = ELF64_R_INFO(r_sym, r_typ); } else { r.r_info = TO_NATIVE(rela->r_info); r_sym = ELF_R_SYM(r.r_info); @@ -1040,11 +972,8 @@ static void check_sec_ref(struct module *mod, const char *modname, r.r_offset = TO_NATIVE(rel->r_offset); #if KERNEL_ELFCLASS == ELFCLASS64 if (hdr->e_machine == EM_MIPS) { - unsigned int r_typ; r_sym = ELF64_MIPS_R_SYM(rel->r_info); r_sym = TO_NATIVE(r_sym); - r_typ = ELF64_MIPS_R_TYPE(rel->r_info); - r.r_info = ELF64_R_INFO(r_sym, r_typ); } else { r.r_info = TO_NATIVE(rel->r_info); r_sym = ELF_R_SYM(r.r_info); @@ -1054,14 +983,6 @@ static void check_sec_ref(struct module *mod, const char *modname, r_sym = ELF_R_SYM(r.r_info); #endif r.r_addend = 0; - if (hdr->e_machine == EM_386) - addend_386_rel(elf, i, &r); - else if (hdr->e_machine == EM_ARM) - addend_arm_rel(elf, i, &r); - else if (hdr->e_machine == EM_MIPS) { - if (addend_mips_rel(elf, i, &r)) - continue; - } sym = elf->symtab_start + r_sym; /* Skip special sections */ if (sym->st_shndx >= SHN_LORESERVE) -- cgit v1.2.3