From e241a630374e06aecdae2884af8b652d3b4d6c37 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 28 Jan 2008 20:13:13 +0100 Subject: kbuild: warn about ld added unique sections If there is a mixture of specifying sections for code in gcc and assembler then if the assembler code do not add the "ax" flags the linker will see this as two different sections and generate unique sections for each. ld does so by adding a dot and a number. Teach modpost to warn if a section shows up that match this pattern - but do this only for non-debug sections. It will result in warnings like this: WARNING: vmlinux.o (.sched.text.1): unexpected section name. The (.[number]+) following section name are ld generated and not expected. Did you forget to use "ax"/"aw" in a .S file? Note that for example contains section definitions for use in .S files. All warnings seen with a defconfig build for: x86 (32+64bit) and sparc64 has been fixed (via respective maintainers). arm, powerpc (64 bit), s390 (32 bit), ia64, alpha, sh4 checked - no warnings seen with a defconfig build. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 3cf1ba8220d2..f8efc93eb700 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -696,6 +696,43 @@ int match(const char *sym, const char * const pat[]) static const char *section_white_list[] = { ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL }; +/* + * Is this section one we do not want to check? + * This is often debug sections. + * If we are going to check this section then + * test if section name ends with a dot and a number. + * This is used to find sections where the linker have + * appended a dot-number to make the name unique. + * The cause of this is often a section specified in assembler + * without "ax" / "aw" and the same section used in .c + * code where gcc add these. + */ +static int check_section(const char *modname, const char *sec) +{ + const char *e = sec + strlen(sec) - 1; + if (match(sec, section_white_list)) + return 1; + + if (*e && isdigit(*e)) { + /* consume all digits */ + while (*e && e != sec && isdigit(*e)) + e--; + if (*e == '.') { + warn("%s (%s): unexpected section name.\n" + "The (.[number]+) following section name are " + "ld generated and not expected.\n" + "Did you forget to use \"ax\"/\"aw\" " + "in a .S file?\n" + "Note that for example contains\n" + "section definitions for use in .S files.\n\n", + modname, sec); + } + } + return 0; +} + + + #define ALL_INIT_DATA_SECTIONS \ ".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$" #define ALL_EXIT_DATA_SECTIONS \ @@ -1311,8 +1348,9 @@ static void section_rela(const char *modname, struct elf_info *elf, fromsec = sech_name(elf, sechdr); fromsec += strlen(".rela"); /* if from section (name) is know good then skip it */ - if (match(fromsec, section_white_list)) + if (check_section(modname, fromsec)) return; + for (rela = start; rela < stop; rela++) { r.r_offset = TO_NATIVE(rela->r_offset); #if KERNEL_ELFCLASS == ELFCLASS64 @@ -1354,7 +1392,7 @@ static void section_rel(const char *modname, struct elf_info *elf, fromsec = sech_name(elf, sechdr); fromsec += strlen(".rel"); /* if from section (name) is know good then skip it */ - if (match(fromsec, section_white_list)) + if (check_section(modname, fromsec)) return; for (rel = start; rel < stop; rel++) { -- cgit v1.2.3