2008-01-20 20:05:30

by Sam Ravnborg

[permalink] [raw]
Subject: kbuild: improved Section mismatch detection

I have spent the last week (the time I can afford to
Linux stuff anyway) to improve the Section mismatch
warnings detected by modpost.

The problem until now has been that the Section
mismatch warnings were dependent on the actual
configuration of HOTPLUG, HOTPLUG_CPU and MEMORY_HOTPLUG.
In the default configuration with HOTPLUG enbaled most
of the remaining Section mismatch warnings were not
seen and thus many of us thought that everything was great.

Adrian reminded us that KCFLAGS=-fno-inline told
another story with more than 100 Section mismatch
warnings on 64 bit x86 with an allyesconfig build.

As this was not acceptable I set out to make it
less configuration dependent. To do so I quikly
relaised that modpost had to be prepared before this
was a feasible thing to implment.

This serie of patches is:

1) kbuild: fix so modpost can now check any .o file
2) kbuild: try harder to find symbol names in modpost
3) kbuild: code refactoring in modpost
4) kbuild: introduce blacklisting in modpost
5) kbuild: check section names consistently in modpost
6) all archs: consolidate init and exit sections in vmlinux.lds.h
7) compiler.h: introduce __section()
8) Use separate sections for __dev/__cpu/__mem code/data

Patch 6) makse a set of trivial changes in all arch vmlinux.lds.S files
and the reason why I copid linux-arch on this mail.

Patch 4) is a major change in modpost where we no longer try to
find all the good guys but instead look for the bad combinations.
This should result in a lot less false warnings and for example got
rid of an irritating warning on sparc64.

Patch 2) is important - previously modpost failed to find the
correct symbol based on address lookup because it wanted an exact
match. Allowing up to 20 bytes offset we now locate almost all
symbols and the warnings are much easier to fix.

Randy and Adrian among others have done a great job fixing
many Section mismatch warnngs over the last month.
But frankly much more people should do this and I can see people
ignoring the warnings.

Therefore the plan is to turn the warnings into hard build errors
at -rc1 time.
This should force people to actually fix the warnings they introduce.

But to do so we need the warnings we have today gettign fixed and
the new improved modpost should help you here.
To further help the plans are to:
- add a config option to enable -fno-inline (or a similar option)
- make the warnings from modpost more descriptive but longer
- maybe to spend a few hours to fix some of the obvious candidates
Less than half an hour for each warning for the trivial cases
- Maybe start using __INIT and friends in assembler code
xen had two bugs in this area recently for example.

It has been questions if it is worth the effort to fix these warnings.
Randy just fixed three oops candidates - do anyone need more facts?

And the cpu code looks rather fragile in the dead/removed CPU cases.
I see several references that will oops and is easy to fix.

Sam



2008-01-20 20:09:14

by Sam Ravnborg

[permalink] [raw]
Subject: [PATCH] kbuild: try harder to find symbol names in modpost

The relocation record sometimes contained an address
which was not an exactly match for a symbol.

Implment some simple logic such that if there
is a symbol within 20 bytes of the address contained
in the relocation record then print the name of this
symbol.

With this change modpost could find symbol names
for the remaining .init.text symbols in my
allyesconfig build for x86_64.

Signed-off-by: Sam Ravnborg <[email protected]>
---
scripts/mod/modpost.c | 19 +++++++++++++++++--
scripts/mod/modpost.h | 2 ++
2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 46660a4..902ee55 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -776,10 +776,13 @@ static int secref_whitelist(const char *modname, const char *tosec,
* In other cases the symbol needs to be looked up in the symbol table
* based on section and address.
* **/
-static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
+static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
Elf_Sym *relsym)
{
Elf_Sym *sym;
+ Elf_Sym *near = NULL;
+ Elf64_Sword distance = 20;
+ Elf64_Sword d;

if (relsym->st_name != 0)
return relsym;
@@ -790,8 +793,20 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
continue;
if (sym->st_value == addr)
return sym;
+ /* Find a symbol nearby - addr are maybe negative */
+ d = sym->st_value - addr;
+ if (d < 0)
+ d = addr - sym->st_value;
+ if (d < distance) {
+ distance = d;
+ near = sym;
+ }
}
- return NULL;
+ /* We need a close match */
+ if (distance < 20)
+ return near;
+ else
+ return NULL;
}

static inline int is_arm_mapping_symbol(const char *str)
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 0ffed17..999f15e 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -17,6 +17,7 @@
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Addr Elf32_Addr
+#define Elf_Sword Elf64_Sword
#define Elf_Section Elf32_Half
#define ELF_ST_BIND ELF32_ST_BIND
#define ELF_ST_TYPE ELF32_ST_TYPE
@@ -31,6 +32,7 @@
#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
#define Elf_Addr Elf64_Addr
+#define Elf_Sword Elf64_Sxword
#define Elf_Section Elf64_Half
#define ELF_ST_BIND ELF64_ST_BIND
#define ELF_ST_TYPE ELF64_ST_TYPE
--
1.5.4.rc3.14.g44397

2008-01-20 20:09:41

by Sam Ravnborg

[permalink] [raw]
Subject: [PATCH] kbuild: fix so modpost can now check any .o file

It is very convinient to say:
scripts/mod/modpost mm/built-in.o

to check if any section mismatch errors occured
in mm/ (as an example).
Fix it so this is possible again.

Signed-off-by: Sam Ravnborg <[email protected]>
---
scripts/mod/modpost.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 696d2a5..46660a4 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1299,7 +1299,8 @@ static void read_symbols(char *modname)
handle_modversions(mod, &info, sym, symname);
handle_moddevtable(mod, &info, sym, symname);
}
- if (is_vmlinux(modname) && vmlinux_section_warnings) {
+ if (!is_vmlinux(modname) ||
+ (is_vmlinux(modname) && vmlinux_section_warnings)) {
check_sec_ref(mod, modname, &info, init_section, init_section_ref_ok);
check_sec_ref(mod, modname, &info, exit_section, exit_section_ref_ok);
}
--
1.5.4.rc3.14.g44397

2008-01-20 20:09:55

by Sam Ravnborg

[permalink] [raw]
Subject: [PATCH] kbuild: code refactoring in modpost

Split a too long function up in smaller bits to make
prgram logic easier to follow.
A few related changes done due to parameter
changes.

No functional changes.

Signed-off-by: Sam Ravnborg <[email protected]>
---
scripts/mod/modpost.c | 242 ++++++++++++++++++++++++++++---------------------
1 files changed, 137 insertions(+), 105 deletions(-)

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 902ee55..e463013 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -937,19 +937,19 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
}

static unsigned int *reloc_location(struct elf_info *elf,
- int rsection, Elf_Rela *r)
+ Elf_Shdr *sechdr, Elf_Rela *r)
{
Elf_Shdr *sechdrs = elf->sechdrs;
- int section = sechdrs[rsection].sh_info;
+ int section = sechdr->sh_info;

return (void *)elf->hdr + sechdrs[section].sh_offset +
(r->r_offset - sechdrs[section].sh_addr);
}

-static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
+static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
{
unsigned int r_typ = ELF_R_TYPE(r->r_info);
- unsigned int *location = reloc_location(elf, rsection, r);
+ unsigned int *location = reloc_location(elf, sechdr, r);

switch (r_typ) {
case R_386_32:
@@ -965,7 +965,7 @@ static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
return 0;
}

-static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
+static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
{
unsigned int r_typ = ELF_R_TYPE(r->r_info);

@@ -978,8 +978,8 @@ static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
case R_ARM_PC24:
/* From ARM ABI: ((S + A) | T) - P */
r->r_addend = (int)(long)(elf->hdr +
- elf->sechdrs[rsection].sh_offset +
- (r->r_offset - elf->sechdrs[rsection].sh_addr));
+ sechdr->sh_offset +
+ (r->r_offset - sechdr->sh_addr));
break;
default:
return 1;
@@ -987,10 +987,10 @@ static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
return 0;
}

-static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
+static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
{
unsigned int r_typ = ELF_R_TYPE(r->r_info);
- unsigned int *location = reloc_location(elf, rsection, r);
+ unsigned int *location = reloc_location(elf, sechdr, r);
unsigned int inst;

if (r_typ == R_MIPS_HI16)
@@ -1010,6 +1010,128 @@ static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
return 0;
}

+static void section_rela(const char *modname, struct elf_info *elf,
+ Elf_Shdr *sechdr, int section(const char *),
+ int section_ref_ok(const char *))
+{
+ Elf_Sym *sym;
+ Elf_Rela *rela;
+ Elf_Rela r;
+ unsigned int r_sym;
+ const char *fromsec;
+ const char * tosec;
+
+ Elf_Ehdr *hdr = elf->hdr;
+ Elf_Rela *start = (void *)hdr + sechdr->sh_offset;
+ Elf_Rela *stop = (void *)start + sechdr->sh_size;
+
+ const char *secstrings = (void *)hdr +
+ elf->sechdrs[hdr->e_shstrndx].sh_offset;
+
+ fromsec = secstrings + sechdr->sh_name;
+ fromsec += strlen(".rela");
+ /* if from section (name) is know good then skip it */
+ if (section_ref_ok(fromsec))
+ return;
+
+ for (rela = start; rela < stop; rela++) {
+ 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);
+ }
+#else
+ r.r_info = TO_NATIVE(rela->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+#endif
+ r.r_addend = TO_NATIVE(rela->r_addend);
+ sym = elf->symtab_start + r_sym;
+ /* Skip special sections */
+ if (sym->st_shndx >= SHN_LORESERVE)
+ continue;
+
+ tosec = secstrings +
+ elf->sechdrs[sym->st_shndx].sh_name;
+ if (section(tosec))
+ warn_sec_mismatch(modname, fromsec, elf, sym, r);
+ }
+}
+
+static void section_rel(const char *modname, struct elf_info *elf,
+ Elf_Shdr *sechdr, int section(const char *),
+ int section_ref_ok(const char *))
+{
+ Elf_Sym *sym;
+ Elf_Rel *rel;
+ Elf_Rela r;
+ unsigned int r_sym;
+ const char *fromsec;
+ const char * tosec;
+
+ Elf_Ehdr *hdr = elf->hdr;
+ Elf_Rel *start = (void *)hdr + sechdr->sh_offset;
+ Elf_Rel *stop = (void *)start + sechdr->sh_size;
+
+ const char *secstrings = (void *)hdr +
+ elf->sechdrs[hdr->e_shstrndx].sh_offset;
+
+ fromsec = secstrings + sechdr->sh_name;
+ fromsec += strlen(".rel");
+ /* if from section (name) is know good then skip it */
+ if (section_ref_ok(fromsec))
+ return;
+
+ for (rel = start; rel < stop; rel++) {
+ 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);
+ }
+#else
+ r.r_info = TO_NATIVE(rel->r_info);
+ r_sym = ELF_R_SYM(r.r_info);
+#endif
+ r.r_addend = 0;
+ switch (hdr->e_machine) {
+ case EM_386:
+ if (addend_386_rel(elf, sechdr, &r))
+ continue;
+ break;
+ case EM_ARM:
+ if (addend_arm_rel(elf, sechdr, &r))
+ continue;
+ break;
+ case EM_MIPS:
+ if (addend_mips_rel(elf, sechdr, &r))
+ continue;
+ break;
+ }
+ sym = elf->symtab_start + r_sym;
+ /* Skip special sections */
+ if (sym->st_shndx >= SHN_LORESERVE)
+ continue;
+
+ tosec = secstrings +
+ elf->sechdrs[sym->st_shndx].sh_name;
+ if (section(tosec))
+ warn_sec_mismatch(modname, fromsec, elf, sym, r);
+ }
+}
+
/**
* A module includes a number of sections that are discarded
* either when loaded or when used as built-in.
@@ -1028,108 +1150,18 @@ static void check_sec_ref(struct module *mod, const char *modname,
int section_ref_ok(const char *))
{
int i;
- Elf_Sym *sym;
Elf_Ehdr *hdr = elf->hdr;
Elf_Shdr *sechdrs = elf->sechdrs;
- const char *secstrings = (void *)hdr +
- sechdrs[hdr->e_shstrndx].sh_offset;

/* Walk through all sections */
for (i = 0; i < hdr->e_shnum; i++) {
- const char *name = secstrings + sechdrs[i].sh_name;
- const char *secname;
- Elf_Rela r;
- unsigned int r_sym;
/* We want to process only relocation sections and not .init */
- if (sechdrs[i].sh_type == SHT_RELA) {
- Elf_Rela *rela;
- Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset;
- Elf_Rela *stop = (void *)start + sechdrs[i].sh_size;
- name += strlen(".rela");
- if (section_ref_ok(name))
- continue;
-
- for (rela = start; rela < stop; rela++) {
- 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);
- }
-#else
- r.r_info = TO_NATIVE(rela->r_info);
- r_sym = ELF_R_SYM(r.r_info);
-#endif
- r.r_addend = TO_NATIVE(rela->r_addend);
- sym = elf->symtab_start + r_sym;
- /* Skip special sections */
- if (sym->st_shndx >= SHN_LORESERVE)
- continue;
-
- secname = secstrings +
- sechdrs[sym->st_shndx].sh_name;
- if (section(secname))
- warn_sec_mismatch(modname, name,
- elf, sym, r);
- }
- } else if (sechdrs[i].sh_type == SHT_REL) {
- Elf_Rel *rel;
- Elf_Rel *start = (void *)hdr + sechdrs[i].sh_offset;
- Elf_Rel *stop = (void *)start + sechdrs[i].sh_size;
- name += strlen(".rel");
- if (section_ref_ok(name))
- continue;
-
- for (rel = start; rel < stop; rel++) {
- 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);
- }
-#else
- r.r_info = TO_NATIVE(rel->r_info);
- r_sym = ELF_R_SYM(r.r_info);
-#endif
- r.r_addend = 0;
- switch (hdr->e_machine) {
- case EM_386:
- if (addend_386_rel(elf, i, &r))
- continue;
- break;
- case EM_ARM:
- if (addend_arm_rel(elf, i, &r))
- continue;
- break;
- case EM_MIPS:
- if (addend_mips_rel(elf, i, &r))
- continue;
- break;
- }
- sym = elf->symtab_start + r_sym;
- /* Skip special sections */
- if (sym->st_shndx >= SHN_LORESERVE)
- continue;
-
- secname = secstrings +
- sechdrs[sym->st_shndx].sh_name;
- if (section(secname))
- warn_sec_mismatch(modname, name,
- elf, sym, r);
- }
- }
+ if (sechdrs[i].sh_type == SHT_RELA)
+ section_rela(modname, elf, &elf->sechdrs[i],
+ section, section_ref_ok);
+ else if (sechdrs[i].sh_type == SHT_REL)
+ section_rel(modname, elf, &elf->sechdrs[i],
+ section, section_ref_ok);
}
}

--
1.5.4.rc3.14.g44397

2008-01-20 20:10:18

by Sam Ravnborg

[permalink] [raw]
Subject: [PATCH] kbuild: introduce blacklisting in modpost

Change the logic in modpost so we identify all the
bad combinations of sections that refer to other
sections.
Compared to the previous approach we are much less
dependent on knowledge of what additional sections
the tool chain uses and thus we can keep the false
positives low.

The implmentation is changed to use a table based
lookup and we now check all combinations in first
pass so we no longer need separate passes for init
and exit sections.

Tested that the same warnings are generated for
an allyesconfig build without CONFIG_HOTPLUG.

Signed-off-by: Sam Ravnborg <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Adrian Bunk <[email protected]>
---
scripts/mod/modpost.c | 305 +++++++++++++++++++++----------------------------
1 files changed, 128 insertions(+), 177 deletions(-)

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index e463013..6c206b9 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -605,6 +605,61 @@ static int strrcmp(const char *s, const char *sub)
return memcmp(s + slen - sublen, sub, sublen);
}

+/* if sym is empty or point to a string
+ * like ".[0-9]+" then return 1.
+ * This is the optional prefix added by ld to some sections
+ */
+static int number_prefix(const char *sym)
+{
+ if (*sym++ == '\0')
+ return 1;
+ if (*sym != '.')
+ return 0;
+ do {
+ char c = *sym++;
+ if (c < '0' || c > '9')
+ return 0;
+ } while (*sym);
+ return 1;
+}
+
+/* The pattern is an array of simple patterns.
+ * "foo" will match an exact string equal to "foo"
+ * "foo*" will match a string that begins with "foo"
+ * "foo$" will match a string equal to "foo" or "foo.1"
+ * where the '1' can be any number including several digits.
+ * The $ syntax is for sections where ld append a dot number
+ * to make section name unique.
+ */
+int match(const char *sym, const char * const pat[])
+{
+ const char *p;
+ while (*pat) {
+ p = *pat++;
+ const char *endp = p + strlen(p) - 1;
+
+ /* "foo*" */
+ if (*endp == '*') {
+ if (strncmp(sym, p, strlen(p) - 1) == 0)
+ return 1;
+ }
+ /* "foo$" */
+ else if (*endp == '$') {
+ if (strncmp(sym, p, strlen(p) - 1) == 0) {
+ if (number_prefix(sym + strlen(p) - 1))
+ return 1;
+ }
+ }
+ /* no wildcards */
+ else {
+ if (strcmp(p, sym) == 0)
+ return 1;
+ }
+ }
+ /* no match */
+ return 0;
+}
+
/*
* Functions used only during module init is marked __init and is stored in
* a .init.text section. Likewise data is marked __initdata and stored in
@@ -653,6 +708,68 @@ static int data_section(const char *name)
return 0;
}

+/* sections that we do not want to do full section mismatch check on */
+static const char *section_white_list[] =
+ { ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL };
+
+#define INIT_DATA_SECTIONS ".init.data$"
+#define EXIT_DATA_SECTIONS ".exit.data$"
+
+#define INIT_TEXT_SECTIONS ".init.text$"
+#define EXIT_TEXT_SECTIONS ".exit.text$"
+
+#define INIT_SECTIONS INIT_DATA_SECTIONS, INIT_TEXT_SECTIONS
+#define EXIT_SECTIONS EXIT_DATA_SECTIONS, EXIT_TEXT_SECTIONS
+
+#define DATA_SECTIONS ".data$"
+#define TEXT_SECTIONS ".text$"
+
+struct sectioncheck {
+ const char *fromsec[20];
+ const char *tosec[20];
+};
+
+const struct sectioncheck sectioncheck[] = {
+/* Do not reference init/exit code/data from
+ * normal code and data
+ */
+{
+ .fromsec = { TEXT_SECTIONS, DATA_SECTIONS, NULL },
+ .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }
+},
+/* Do not use exit code/data from init code */
+{
+ .fromsec = { INIT_SECTIONS, NULL },
+ .tosec = { EXIT_SECTIONS, NULL },
+},
+/* Do not use init code/data from exit code */
+{
+ .fromsec = { EXIT_SECTIONS, NULL },
+ .tosec = { INIT_SECTIONS, NULL }
+},
+/* Do not export init/exit functions or data */
+{
+ .fromsec = { "__ksymtab*", NULL },
+ .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }
+}
+};
+
+static int section_mismatch(const char *fromsec, const char *tosec)
+{
+ int i;
+ int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck);
+ const struct sectioncheck *check = &sectioncheck[0];
+
+ for (i = 0; i < elems; i++) {
+ if (match(fromsec, check->fromsec) &&
+ match(tosec, check->tosec))
+ return 1;
+ check++;
+ }
+ return 0;
+}
+
+
/**
* Whitelist to allow certain references to pass with no warning.
*
@@ -695,18 +812,11 @@ static int data_section(const char *name)
* This pattern is identified by
* refsymname = __init_begin, _sinittext, _einittext
*
- * Pattern 5:
- * Xtensa uses literal sections for constants that are accessed PC-relative.
- * Literal sections may safely reference their text sections.
- * (Note that the name for the literal section omits any trailing '.text')
- * tosec = <section>[.text]
- * fromsec = <section>.literal
**/
static int secref_whitelist(const char *modname, const char *tosec,
const char *fromsec, const char *atsym,
const char *refsymname)
{
- int len;
const char **s;
const char *pat2sym[] = {
"driver",
@@ -757,15 +867,6 @@ static int secref_whitelist(const char *modname, const char *tosec,
if (strcmp(refsymname, *s) == 0)
return 1;

- /* Check for pattern 5 */
- if (strrcmp(tosec, ".text") == 0)
- len = strlen(tosec) - strlen(".text");
- else
- len = strlen(tosec);
- if ((strncmp(tosec, fromsec, len) == 0) && (strlen(fromsec) > len) &&
- (strcmp(fromsec + len, ".literal") == 0))
- return 1;
-
return 0;
}

@@ -1011,8 +1112,7 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
}

static void section_rela(const char *modname, struct elf_info *elf,
- Elf_Shdr *sechdr, int section(const char *),
- int section_ref_ok(const char *))
+ Elf_Shdr *sechdr)
{
Elf_Sym *sym;
Elf_Rela *rela;
@@ -1031,7 +1131,7 @@ static void section_rela(const char *modname, struct elf_info *elf,
fromsec = secstrings + sechdr->sh_name;
fromsec += strlen(".rela");
/* if from section (name) is know good then skip it */
- if (section_ref_ok(fromsec))
+ if (match(fromsec, section_white_list))
return;

for (rela = start; rela < stop; rela++) {
@@ -1059,14 +1159,13 @@ static void section_rela(const char *modname, struct elf_info *elf,

tosec = secstrings +
elf->sechdrs[sym->st_shndx].sh_name;
- if (section(tosec))
+ if (section_mismatch(fromsec, tosec))
warn_sec_mismatch(modname, fromsec, elf, sym, r);
}
}

static void section_rel(const char *modname, struct elf_info *elf,
- Elf_Shdr *sechdr, int section(const char *),
- int section_ref_ok(const char *))
+ Elf_Shdr *sechdr)
{
Elf_Sym *sym;
Elf_Rel *rel;
@@ -1085,7 +1184,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
fromsec = secstrings + sechdr->sh_name;
fromsec += strlen(".rel");
/* if from section (name) is know good then skip it */
- if (section_ref_ok(fromsec))
+ if (match(fromsec, section_white_list))
return;

for (rel = start; rel < stop; rel++) {
@@ -1127,7 +1226,7 @@ static void section_rel(const char *modname, struct elf_info *elf,

tosec = secstrings +
elf->sechdrs[sym->st_shndx].sh_name;
- if (section(tosec))
+ if (section_mismatch(fromsec, tosec))
warn_sec_mismatch(modname, fromsec, elf, sym, r);
}
}
@@ -1145,9 +1244,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
* be discarded and warns about it.
**/
static void check_sec_ref(struct module *mod, const char *modname,
- struct elf_info *elf,
- int section(const char *),
- int section_ref_ok(const char *))
+ struct elf_info *elf)
{
int i;
Elf_Ehdr *hdr = elf->hdr;
@@ -1157,156 +1254,12 @@ static void check_sec_ref(struct module *mod, const char *modname,
for (i = 0; i < hdr->e_shnum; i++) {
/* We want to process only relocation sections and not .init */
if (sechdrs[i].sh_type == SHT_RELA)
- section_rela(modname, elf, &elf->sechdrs[i],
- section, section_ref_ok);
+ section_rela(modname, elf, &elf->sechdrs[i]);
else if (sechdrs[i].sh_type == SHT_REL)
- section_rel(modname, elf, &elf->sechdrs[i],
- section, section_ref_ok);
+ section_rel(modname, elf, &elf->sechdrs[i]);
}
}

-/*
- * Identify sections from which references to either a
- * .init or a .exit section is OK.
- *
- * [OPD] Keith Ownes <[email protected]> commented:
- * For our future {in}sanity, add a comment that this is the ppc .opd
- * section, not the ia64 .opd section.
- * ia64 .opd should not point to discarded sections.
- * [.rodata] like for .init.text we ignore .rodata references -same reason
- */
-static int initexit_section_ref_ok(const char *name)
-{
- const char **s;
- /* Absolute section names */
- const char *namelist1[] = {
- "__bug_table", /* used by powerpc for BUG() */
- "__ex_table",
- ".altinstructions",
- ".cranges", /* used by sh64 */
- ".fixup",
- ".machvec", /* ia64 + powerpc uses these */
- ".machine.desc",
- ".opd", /* See comment [OPD] */
- "__dbe_table",
- ".parainstructions",
- ".pdr",
- ".plt", /* seen on ARCH=um build on x86_64. Harmless */
- ".smp_locks",
- ".stab",
- ".m68k_fixup",
- ".xt.prop", /* xtensa informational section */
- ".xt.lit", /* xtensa informational section */
- NULL
- };
- /* Start of section names */
- const char *namelist2[] = {
- ".debug",
- ".eh_frame",
- ".note", /* ignore ELF notes - may contain anything */
- ".got", /* powerpc - global offset table */
- ".toc", /* powerpc - table of contents */
- NULL
- };
- /* part of section name */
- const char *namelist3 [] = {
- ".unwind", /* Sample: IA_64.unwind.exit.text */
- NULL
- };
-
- for (s = namelist1; *s; s++)
- if (strcmp(*s, name) == 0)
- return 1;
- for (s = namelist2; *s; s++)
- if (strncmp(*s, name, strlen(*s)) == 0)
- return 1;
- for (s = namelist3; *s; s++)
- if (strstr(name, *s) != NULL)
- return 1;
- return 0;
-}
-
-
-/*
- * Identify sections from which references to a .init section is OK.
- *
- * Unfortunately references to read only data that referenced .init
- * sections had to be excluded. Almost all of these are false
- * positives, they are created by gcc. The downside of excluding rodata
- * is that there really are some user references from rodata to
- * init code, e.g. drivers/video/vgacon.c:
- *
- * const struct consw vga_con = {
- * con_startup: vgacon_startup,
- *
- * where vgacon_startup is __init. If you want to wade through the false
- * positives, take out the check for rodata.
- */
-static int init_section_ref_ok(const char *name)
-{
- const char **s;
- /* Absolute section names */
- const char *namelist1[] = {
- "__dbe_table", /* MIPS generate these */
- "__ftr_fixup", /* powerpc cpu feature fixup */
- "__fw_ftr_fixup", /* powerpc firmware feature fixup */
- "__param",
- ".data.rel.ro", /* used by parisc64 */
- ".init",
- ".text.lock",
- NULL
- };
- /* Start of section names */
- const char *namelist2[] = {
- ".init.",
- ".pci_fixup",
- ".rodata",
- NULL
- };
-
- if (initexit_section_ref_ok(name))
- return 1;
-
- for (s = namelist1; *s; s++)
- if (strcmp(*s, name) == 0)
- return 1;
- for (s = namelist2; *s; s++)
- if (strncmp(*s, name, strlen(*s)) == 0)
- return 1;
-
- /* If section name ends with ".init" we allow references
- * as is the case with .initcallN.init, .early_param.init,
- * .taglist.init etc
- */
- if (strrcmp(name, ".init") == 0)
- return 1;
- return 0;
-}
-
-/*
- * Identify sections from which references to a .exit section is OK.
- */
-static int exit_section_ref_ok(const char *name)
-{
- const char **s;
- /* Absolute section names */
- const char *namelist1[] = {
- ".exit.data",
- ".exit.text",
- ".exitcall.exit",
- ".rodata",
- NULL
- };
-
- if (initexit_section_ref_ok(name))
- return 1;
-
- for (s = namelist1; *s; s++)
- if (strcmp(*s, name) == 0)
- return 1;
- return 0;
-}
-
static void read_symbols(char *modname)
{
const char *symname;
@@ -1347,10 +1300,8 @@ static void read_symbols(char *modname)
handle_moddevtable(mod, &info, sym, symname);
}
if (!is_vmlinux(modname) ||
- (is_vmlinux(modname) && vmlinux_section_warnings)) {
- check_sec_ref(mod, modname, &info, init_section, init_section_ref_ok);
- check_sec_ref(mod, modname, &info, exit_section, exit_section_ref_ok);
- }
+ (is_vmlinux(modname) && vmlinux_section_warnings))
+ check_sec_ref(mod, modname, &info);

version = get_modinfo(info.modinfo, info.modinfo_len, "version");
if (version)
--
1.5.4.rc3.14.g44397

2008-01-20 20:10:42

by Sam Ravnborg

[permalink] [raw]
Subject: [PATCH] kbuild: check section names consistently in modpost

Now that match() is introduced use it consistently so
we can share the section name definitions.

Signed-off-by: Sam Ravnborg <[email protected]>
---
scripts/mod/modpost.c | 146 ++++++++++++++++++++-----------------------------
1 files changed, 60 insertions(+), 86 deletions(-)

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 6c206b9..986513d 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -625,6 +625,7 @@ static int number_prefix(const char *sym)

/* The pattern is an array of simple patterns.
* "foo" will match an exact string equal to "foo"
+ * "*foo" will match a string that ends with "foo"
* "foo*" will match a string that begins with "foo"
* "foo$" will match a string equal to "foo" or "foo.1"
* where the '1' can be any number including several digits.
@@ -638,8 +639,13 @@ int match(const char *sym, const char * const pat[])
p = *pat++;
const char *endp = p + strlen(p) - 1;

+ /* "*foo" */
+ if (*p == '*') {
+ if (strrcmp(sym, p + 1) == 0)
+ return 1;
+ }
/* "foo*" */
- if (*endp == '*') {
+ else if (*endp == '*') {
if (strncmp(sym, p, strlen(p) - 1) == 0)
return 1;
}
@@ -660,54 +666,6 @@ int match(const char *sym, const char * const pat[])
return 0;
}

-/*
- * Functions used only during module init is marked __init and is stored in
- * a .init.text section. Likewise data is marked __initdata and stored in
- * a .init.data section.
- * If this section is one of these sections return 1
- * See include/linux/init.h for the details
- */
-static int init_section(const char *name)
-{
- if (strcmp(name, ".init") == 0)
- return 1;
- if (strncmp(name, ".init.", strlen(".init.")) == 0)
- return 1;
- return 0;
-}
-
-/*
- * Functions used only during module exit is marked __exit and is stored in
- * a .exit.text section. Likewise data is marked __exitdata and stored in
- * a .exit.data section.
- * If this section is one of these sections return 1
- * See include/linux/init.h for the details
- **/
-static int exit_section(const char *name)
-{
- if (strcmp(name, ".exit.text") == 0)
- return 1;
- if (strcmp(name, ".exit.data") == 0)
- return 1;
- return 0;
-
-}
-
-/*
- * Data sections are named like this:
- * .data | .data.rel | .data.rel.*
- * Return 1 if the specified section is a data section
- */
-static int data_section(const char *name)
-{
- if ((strcmp(name, ".data") == 0) ||
- (strcmp(name, ".data.rel") == 0) ||
- (strncmp(name, ".data.rel.", strlen(".data.rel.")) == 0))
- return 1;
- else
- return 0;
-}
-
/* sections that we do not want to do full section mismatch check on */
static const char *section_white_list[] =
{ ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL };
@@ -721,9 +679,50 @@ static const char *section_white_list[] =
#define INIT_SECTIONS INIT_DATA_SECTIONS, INIT_TEXT_SECTIONS
#define EXIT_SECTIONS EXIT_DATA_SECTIONS, EXIT_TEXT_SECTIONS

-#define DATA_SECTIONS ".data$"
+#define DATA_SECTIONS ".data$", ".data.rel$"
#define TEXT_SECTIONS ".text$"

+/* init data sections */
+static const char *init_data_sections[] = { INIT_DATA_SECTIONS, NULL };
+
+/* all init sections */
+static const char *init_sections[] = { INIT_SECTIONS, NULL };
+
+/* All init and exit sections (code + data) */
+static const char *init_exit_sections[] =
+ {INIT_SECTIONS, EXIT_SECTIONS, NULL };
+
+/* data section */
+static const char *data_sections[] = { DATA_SECTIONS, NULL };
+
+/* sections that may refer to an init/exit section with no warning */
+static const char *initref_sections[] =
+{
+ ".text.init.refok*",
+ ".exit.text.refok*",
+ ".data.init.refok*",
+ NULL
+};
+
+
+/* symbols in .data that may refer to init/exit sections */
+static const char *symbol_white_list[] =
+{
+ "*driver",
+ "*_template", /* scsi uses *_template a lot */
+ "*_timer", /* arm uses ops structures named _timer a lot */
+ "*_sht", /* scsi also used *_sht to some extent */
+ "*_ops",
+ "*_probe",
+ "*_probe_one",
+ "*_console",
+ NULL
+};
+
+static const char *head_sections[] = { ".head.text*", NULL };
+static const char *linker_symbols[] =
+ { "__init_begin", "_sinittext", "_einittext", NULL };
+
struct sectioncheck {
const char *fromsec[20];
const char *tosec[20];
@@ -817,55 +816,30 @@ static int secref_whitelist(const char *modname, const char *tosec,
const char *fromsec, const char *atsym,
const char *refsymname)
{
- const char **s;
- const char *pat2sym[] = {
- "driver",
- "_template", /* scsi uses *_template a lot */
- "_timer", /* arm uses ops structures named _timer a lot */
- "_sht", /* scsi also used *_sht to some extent */
- "_ops",
- "_probe",
- "_probe_one",
- "_console",
- NULL
- };
-
- const char *pat3refsym[] = {
- "__init_begin",
- "_sinittext",
- "_einittext",
- NULL
- };
-
/* Check for pattern 0 */
- if ((strncmp(fromsec, ".text.init.refok", strlen(".text.init.refok")) == 0) ||
- (strncmp(fromsec, ".exit.text.refok", strlen(".exit.text.refok")) == 0) ||
- (strncmp(fromsec, ".data.init.refok", strlen(".data.init.refok")) == 0))
+ if (match(fromsec, initref_sections))
return 1;

/* Check for pattern 1 */
- if ((strcmp(tosec, ".init.data") == 0) &&
- (strncmp(fromsec, ".data", strlen(".data")) == 0) &&
+ if (match(tosec, init_data_sections) &&
+ match(fromsec, data_sections) &&
(strncmp(atsym, "__param", strlen("__param")) == 0))
return 1;

/* Check for pattern 2 */
- if ((init_section(tosec) || exit_section(tosec))
- && data_section(fromsec))
- for (s = pat2sym; *s; s++)
- if (strrcmp(atsym, *s) == 0)
- return 1;
+ if (match(tosec, init_exit_sections) &&
+ match(fromsec, data_sections) &&
+ match(atsym, symbol_white_list))
+ return 1;

/* Check for pattern 3 */
- if ((strcmp(fromsec, ".text.head") == 0) &&
- ((strcmp(tosec, ".init.data") == 0) ||
- (strcmp(tosec, ".init.text") == 0)))
+ if (match(fromsec, head_sections) &&
+ match(tosec, init_sections))
return 1;

/* Check for pattern 4 */
- for (s = pat3refsym; *s; s++)
- if (strcmp(refsymname, *s) == 0)
- return 1;
+ if (match(refsymname, linker_symbols))
+ return 1;

return 0;
}
--
1.5.4.rc3.14.g44397

2008-01-20 20:10:56

by Sam Ravnborg

[permalink] [raw]
Subject: [PATCH] all archs: consolidate init and exit sections in vmlinux.lds.h

This patch consolidate all definitions of .init.text, .init.data
and .exit.text, .exit.data section definitions in
the generic vmlinux.lds.h.

This is a preparational patch - alone it does not buy
us much good.

Signed-off-by: Sam Ravnborg <[email protected]>
---
arch/alpha/kernel/vmlinux.lds.S | 8 ++++----
arch/arm/kernel/vmlinux.lds.S | 10 +++++-----
arch/avr32/kernel/vmlinux.lds.S | 8 ++++----
arch/blackfin/kernel/vmlinux.lds.S | 8 ++++----
arch/cris/arch-v10/vmlinux.lds.S | 8 ++++----
arch/cris/arch-v32/vmlinux.lds.S | 8 ++++----
arch/frv/kernel/vmlinux.lds.S | 14 +++++++-------
arch/h8300/kernel/vmlinux.lds.S | 8 ++++----
arch/ia64/kernel/vmlinux.lds.S | 8 ++++----
arch/m32r/kernel/vmlinux.lds.S | 12 ++++++------
arch/m68k/kernel/vmlinux-std.lds | 8 ++++----
arch/m68k/kernel/vmlinux-sun3.lds | 8 ++++----
arch/m68knommu/kernel/vmlinux.lds.S | 8 ++++----
arch/mips/kernel/vmlinux.lds.S | 8 ++++----
arch/parisc/kernel/vmlinux.lds.S | 8 ++++----
arch/powerpc/kernel/vmlinux.lds.S | 10 ++++++----
arch/ppc/kernel/vmlinux.lds.S | 8 ++++----
arch/s390/kernel/vmlinux.lds.S | 8 ++++----
arch/sh/kernel/vmlinux.lds.S | 8 ++++----
arch/sh64/kernel/vmlinux.lds.S | 8 ++++----
arch/sparc/kernel/vmlinux.lds.S | 8 ++++----
arch/sparc64/kernel/vmlinux.lds.S | 8 ++++----
arch/um/kernel/dyn.lds.S | 4 ++--
arch/um/kernel/uml.lds.S | 4 ++--
arch/v850/kernel/vmlinux.lds.S | 10 +++++-----
arch/x86/kernel/vmlinux_32.lds.S | 14 ++++++++++----
arch/x86/kernel/vmlinux_64.lds.S | 19 +++++++++++++------
arch/xtensa/kernel/vmlinux.lds.S | 9 +++++----
include/asm-generic/vmlinux.lds.h | 7 +++++++
29 files changed, 140 insertions(+), 117 deletions(-)

diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index 55c05b5..f13249b 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -46,11 +46,11 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
.init.data : {
- *(.init.data)
+ INIT_DATA
}

. = ALIGN(16);
@@ -136,8 +136,8 @@ SECTIONS

/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 5ff5406..52221ef 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -30,7 +30,7 @@ SECTIONS
}

.init : { /* Init code and data */
- *(.init.text)
+ INIT_TEXT
_einittext = .;
__proc_info_begin = .;
*(.proc.info.init)
@@ -70,15 +70,15 @@ SECTIONS
__per_cpu_end = .;
#ifndef CONFIG_XIP_KERNEL
__init_begin = _stext;
- *(.init.data)
+ INIT_DATA
. = ALIGN(4096);
__init_end = .;
#endif
}

/DISCARD/ : { /* Exit code and data */
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
#ifndef CONFIG_MMU
*(.fixup)
@@ -129,7 +129,7 @@ SECTIONS
#ifdef CONFIG_XIP_KERNEL
. = ALIGN(4096);
__init_begin = .;
- *(.init.data)
+ INIT_DATA
. = ALIGN(4096);
__init_end = .;
#endif
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 11f08e3..481cfd4 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -27,19 +27,19 @@ SECTIONS
__init_begin = .;
_sinittext = .;
*(.text.reset)
- *(.init.text)
+ INIT_TEXT
/*
* .exit.text is discarded at runtime, not
* link time, to deal with references from
* __bug_table
*/
- *(.exit.text)
+ EXIT_TEXT
_einittext = .;
. = ALIGN(4);
__tagtable_begin = .;
*(.taglist.init)
__tagtable_end = .;
- *(.init.data)
+ INIT_DATA
. = ALIGN(16);
__setup_start = .;
*(.init.setup)
@@ -135,7 +135,7 @@ SECTIONS
* thrown away, as cleanup code is never called unless it's a module.
*/
/DISCARD/ : {
- *(.exit.data)
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 9b75bc8..8587224 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -91,13 +91,13 @@ SECTIONS
{
. = ALIGN(PAGE_SIZE);
__sinittext = .;
- *(.init.text)
+ INIT_TEXT
__einittext = .;
}
.init.data :
{
. = ALIGN(16);
- *(.init.data)
+ INIT_DATA
}
.init.setup :
{
@@ -198,8 +198,8 @@ SECTIONS

/DISCARD/ :
{
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}
}
diff --git a/arch/cris/arch-v10/vmlinux.lds.S b/arch/cris/arch-v10/vmlinux.lds.S
index 9859d49..a9d2b36 100644
--- a/arch/cris/arch-v10/vmlinux.lds.S
+++ b/arch/cris/arch-v10/vmlinux.lds.S
@@ -56,10 +56,10 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
- .init.data : { *(.init.data) }
+ .init.data : { INIT_DATA }
. = ALIGN(16);
__setup_start = .;
.init.setup : { *(.init.setup) }
@@ -112,8 +112,8 @@ SECTIONS

/* Sections to be discarded */
/DISCARD/ : {
- *(.text.exit)
- *(.data.exit)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/cris/arch-v32/vmlinux.lds.S b/arch/cris/arch-v32/vmlinux.lds.S
index b076c13..fead8c5 100644
--- a/arch/cris/arch-v32/vmlinux.lds.S
+++ b/arch/cris/arch-v32/vmlinux.lds.S
@@ -61,10 +61,10 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
- .init.data : { *(.init.data) }
+ .init.data : { INIT_DATA }
. = ALIGN(16);
__setup_start = .;
.init.setup : { *(.init.setup) }
@@ -124,8 +124,8 @@ SECTIONS

/* Sections to be discarded */
/DISCARD/ : {
- *(.text.exit)
- *(.data.exit)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index a17a81d..f42b328 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -28,14 +28,14 @@ SECTIONS
.init.text : {
*(.text.head)
#ifndef CONFIG_DEBUG_INFO
- *(.init.text)
- *(.exit.text)
- *(.exit.data)
+ INIT_TEXT
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
#endif
}
_einittext = .;
- .init.data : { *(.init.data) }
+ .init.data : { INIT_DATA }

. = ALIGN(8);
__setup_start = .;
@@ -106,8 +106,8 @@ SECTIONS
LOCK_TEXT
#ifdef CONFIG_DEBUG_INFO
*(
- .init.text
- .exit.text
+ INIT_TEXT
+ EXIT_TEXT
.exitcall.exit
)
#endif
@@ -138,7 +138,7 @@ SECTIONS
.data : { /* Data */
DATA_DATA
*(.data.*)
- *(.exit.data)
+ EXIT_DATA
CONSTRUCTORS
}

diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
index a2e72d4..43a87b9 100644
--- a/arch/h8300/kernel/vmlinux.lds.S
+++ b/arch/h8300/kernel/vmlinux.lds.S
@@ -110,9 +110,9 @@ SECTIONS
. = ALIGN(0x4) ;
___init_begin = .;
__sinittext = .;
- *(.init.text)
+ INIT_TEXT
__einittext = .;
- *(.init.data)
+ INIT_DATA
. = ALIGN(0x4) ;
___setup_start = .;
*(.init.setup)
@@ -124,8 +124,8 @@ SECTIONS
___con_initcall_start = .;
*(.con_initcall.init)
___con_initcall_end = .;
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
#if defined(CONFIG_BLK_DEV_INITRD)
. = ALIGN(4);
___initramfs_start = .;
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 757e419..80622ac 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -27,8 +27,8 @@ SECTIONS
{
/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
*(.IA_64.unwind.exit.text)
*(.IA_64.unwind_info.exit.text)
@@ -119,12 +119,12 @@ SECTIONS
.init.text : AT(ADDR(.init.text) - LOAD_OFFSET)
{
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}

.init.data : AT(ADDR(.init.data) - LOAD_OFFSET)
- { *(.init.data) }
+ { INIT_DATA }

#ifdef CONFIG_BLK_DEV_INITRD
.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET)
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
index 942a8c7..41b0785 100644
--- a/arch/m32r/kernel/vmlinux.lds.S
+++ b/arch/m32r/kernel/vmlinux.lds.S
@@ -76,10 +76,10 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
- .init.data : { *(.init.data) }
+ .init.data : { INIT_DATA }
. = ALIGN(16);
__setup_start = .;
.init.setup : { *(.init.setup) }
@@ -100,8 +100,8 @@ SECTIONS
.altinstr_replacement : { *(.altinstr_replacement) }
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
- .exit.text : { *(.exit.text) }
- .exit.data : { *(.exit.data) }
+ .exit.text : { EXIT_TEXT }
+ .exit.data : { EXIT_DATA }

#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(4096);
@@ -124,8 +124,8 @@ SECTIONS

/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index 59fe285..7537cc5 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -45,10 +45,10 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
- .init.data : { *(.init.data) }
+ .init.data : { INIT_DATA }
. = ALIGN(16);
__setup_start = .;
.init.setup : { *(.init.setup) }
@@ -82,8 +82,8 @@ SECTIONS

/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index 4adffef..cdc313e 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -38,10 +38,10 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
- .init.data : { *(.init.data) }
+ .init.data : { INIT_DATA }
. = ALIGN(16);
__setup_start = .;
.init.setup : { *(.init.setup) }
@@ -77,8 +77,8 @@ __init_begin = .;

/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 07a0055..b44edb0 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -143,9 +143,9 @@ SECTIONS {
. = ALIGN(4096);
__init_begin = .;
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
- *(.init.data)
+ INIT_DATA
. = ALIGN(16);
__setup_start = .;
*(.init.setup)
@@ -170,8 +170,8 @@ SECTIONS {
} > INIT

/DISCARD/ : {
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 5fc2398..b5470ce 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -114,11 +114,11 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
.init.data : {
- *(.init.data)
+ INIT_DATA
}
. = ALIGN(16);
.init.setup : {
@@ -144,10 +144,10 @@ SECTIONS
* references from .rodata
*/
.exit.text : {
- *(.exit.text)
+ EXIT_TEXT
}
.exit.data : {
- *(.exit.data)
+ EXIT_DATA
}
#if defined(CONFIG_BLK_DEV_INITRD)
. = ALIGN(_PAGE_SIZE);
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 40d0ff9..50b4a3a 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -172,11 +172,11 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
.init.data : {
- *(.init.data)
+ INIT_DATA
}
. = ALIGN(16);
.init.setup : {
@@ -215,10 +215,10 @@ SECTIONS
* from .altinstructions and .eh_frame
*/
.exit.text : {
- *(.exit.text)
+ EXIT_TEXT
}
.exit.data : {
- *(.exit.data)
+ EXIT_DATA
}
#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(PAGE_SIZE);
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index f66fa5d..0afb9e3 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -23,7 +23,7 @@ SECTIONS
/* Sections to be discarded. */
/DISCARD/ : {
*(.exitcall.exit)
- *(.exit.data)
+ EXIT_DATA
}

. = KERNELBASE;
@@ -76,17 +76,19 @@ SECTIONS

.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}

/* .exit.text is discarded at runtime, not link time,
* to deal with references from __bug_table
*/
- .exit.text : { *(.exit.text) }
+ .exit.text : {
+ EXIT_TEXT
+ }

.init.data : {
- *(.init.data);
+ INIT_DATA
__vtop_table_begin = .;
*(.vtop_fixup);
__vtop_table_end = .;
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 98c1212..52b64fc 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -97,14 +97,14 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
/* .exit.text is discarded at runtime, not link time,
to deal with references from __bug_table */
- .exit.text : { *(.exit.text) }
+ .exit.text : { EXIT_TEXT }
.init.data : {
- *(.init.data);
+ INIT_DATA
__vtop_table_begin = .;
*(.vtop_fixup);
__vtop_table_end = .;
@@ -164,6 +164,6 @@ SECTIONS
/* Sections to be discarded. */
/DISCARD/ : {
*(.exitcall.exit)
- *(.exit.data)
+ EXIT_DATA
}
}
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 849120e..c62795f 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -91,7 +91,7 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
/*
@@ -99,11 +99,11 @@ SECTIONS
* to deal with references from __bug_table
*/
.exit.text : {
- *(.exit.text)
+ EXIT_TEXT
}

.init.data : {
- *(.init.data)
+ INIT_DATA
}
. = ALIGN(0x100);
.init.setup : {
@@ -150,7 +150,7 @@ SECTIONS

/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.data)
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 0956fb3..4c20dd9 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -70,9 +70,9 @@ SECTIONS
. = ALIGN(PAGE_SIZE); /* Init code and data */
__init_begin = .;
_sinittext = .;
- .init.text : { *(.init.text) }
+ .init.text : { INIT_TEXT }
_einittext = .;
- .init.data : { *(.init.data) }
+ .init.data : { INIT_DATA }

. = ALIGN(16);
__setup_start = .;
@@ -108,8 +108,8 @@ SECTIONS
* .exit.text is discarded at runtime, not link time, to deal with
* references from __bug_table
*/
- .exit.text : { *(.exit.text) }
- .exit.data : { *(.exit.data) }
+ .exit.text : { EXIT_TEXT }
+ .exit.data : { EXIT_DATA }

. = ALIGN(PAGE_SIZE);
.bss : {
diff --git a/arch/sh64/kernel/vmlinux.lds.S b/arch/sh64/kernel/vmlinux.lds.S
index f533a06..1696803 100644
--- a/arch/sh64/kernel/vmlinux.lds.S
+++ b/arch/sh64/kernel/vmlinux.lds.S
@@ -93,9 +93,9 @@ SECTIONS
. = ALIGN(PAGE_SIZE); /* Init code and data */
__init_begin = .;
_sinittext = .;
- .init.text : C_PHYS(.init.text) { *(.init.text) }
+ .init.text : C_PHYS(.init.text) { INIT_TEXT }
_einittext = .;
- .init.data : C_PHYS(.init.data) { *(.init.data) }
+ .init.data : C_PHYS(.init.data) { INIT_DATA }
. = ALIGN(L1_CACHE_BYTES); /* Better if Cache Line aligned */
__setup_start = .;
.init.setup : C_PHYS(.init.setup) { *(.init.setup) }
@@ -130,8 +130,8 @@ SECTIONS

/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index a8b4200..216147d 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -48,12 +48,12 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
__init_text_end = .;
.init.data : {
- *(.init.data)
+ INIT_DATA
}
. = ALIGN(16);
.init.setup : {
@@ -102,8 +102,8 @@ SECTIONS
_end = . ;
PROVIDE (end = .);
/DISCARD/ : {
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
index 9fcd503..01f8096 100644
--- a/arch/sparc64/kernel/vmlinux.lds.S
+++ b/arch/sparc64/kernel/vmlinux.lds.S
@@ -56,11 +56,11 @@ SECTIONS
.init.text : {
__init_begin = .;
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
.init.data : {
- *(.init.data)
+ INIT_DATA
}
. = ALIGN(16);
.init.setup : {
@@ -137,8 +137,8 @@ SECTIONS
PROVIDE (end = .);

/DISCARD/ : {
- *(.exit.text)
- *(.exit.data)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 3866f49..26090b7 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -17,7 +17,7 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}

@@ -84,7 +84,7 @@ SECTIONS

#include "asm/common.lds.S"

- init.data : { *(.init.data) }
+ init.data : { INIT_DATA }

/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 13df191..5828c1d 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -23,7 +23,7 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
. = ALIGN(4096);
@@ -48,7 +48,7 @@ SECTIONS

#include "asm/common.lds.S"

- init.data : { *(init.data) }
+ init.data : { INIT_DATA }
.data :
{
. = ALIGN(KERNEL_STACK_SIZE); /* init_task */
diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
index 6172599..d08cd1d 100644
--- a/arch/v850/kernel/vmlinux.lds.S
+++ b/arch/v850/kernel/vmlinux.lds.S
@@ -114,7 +114,7 @@
#define DATA_CONTENTS \
__sdata = . ; \
DATA_DATA \
- *(.exit.data) /* 2.5 convention */ \
+ EXIT_DATA /* 2.5 convention */ \
*(.data.exit) /* 2.4 convention */ \
. = ALIGN (16) ; \
*(.data.cacheline_aligned) \
@@ -157,9 +157,9 @@
. = ALIGN (4096) ; \
__init_start = . ; \
__sinittext = .; \
- *(.init.text) /* 2.5 convention */ \
+ INIT_TEXT /* 2.5 convention */ \
__einittext = .; \
- *(.init.data) \
+ INIT_DATA \
*(.text.init) /* 2.4 convention */ \
*(.data.init) \
INITCALL_CONTENTS \
@@ -170,7 +170,7 @@
#define ROMK_INIT_RAM_CONTENTS \
. = ALIGN (4096) ; \
__init_start = . ; \
- *(.init.data) /* 2.5 convention */ \
+ INIT_DATA /* 2.5 convention */ \
*(.data.init) /* 2.4 convention */ \
__init_end = . ; \
. = ALIGN (4096) ;
@@ -179,7 +179,7 @@
should go into ROM. */
#define ROMK_INIT_ROM_CONTENTS \
_sinittext = .; \
- *(.init.text) /* 2.5 convention */ \
+ INIT_TEXT /* 2.5 convention */ \
_einittext = .; \
*(.text.init) /* 2.4 convention */ \
INITCALL_CONTENTS \
diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S
index 7d72cce..84c913f 100644
--- a/arch/x86/kernel/vmlinux_32.lds.S
+++ b/arch/x86/kernel/vmlinux_32.lds.S
@@ -131,10 +131,12 @@ SECTIONS
.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
__init_begin = .;
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
- .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
+ INIT_DATA
+ }
. = ALIGN(16);
.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
__setup_start = .;
@@ -169,8 +171,12 @@ SECTIONS
}
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
- .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
- .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
+ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
+ EXIT_TEXT
+ }
+ .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
+ EXIT_DATA
+ }
#if defined(CONFIG_BLK_DEV_INITRD)
. = ALIGN(4096);
.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S
index ba8ea97..ea53869 100644
--- a/arch/x86/kernel/vmlinux_64.lds.S
+++ b/arch/x86/kernel/vmlinux_64.lds.S
@@ -155,12 +155,15 @@ SECTIONS
__init_begin = .;
.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
_sinittext = .;
- *(.init.text)
+ INIT_TEXT
_einittext = .;
}
- __initdata_begin = .;
- .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
- __initdata_end = .;
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
+ __initdata_begin = .;
+ INIT_DATA
+ __initdata_end = .;
+ }
+
. = ALIGN(16);
__setup_start = .;
.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) }
@@ -187,8 +190,12 @@ SECTIONS
}
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
- .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
- .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
+ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
+ EXIT_TEXT
+ }
+ .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
+ EXIT_DATA
+ }

/* vdso blob that is mapped into user space */
vdso_start = . ;
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index ac4ed52..7d0f55a 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -136,13 +136,13 @@ SECTIONS
__init_begin = .;
.init.text : {
_sinittext = .;
- *(.init.literal) *(.init.text)
+ *(.init.literal) INIT_TEXT
_einittext = .;
}

.init.data :
{
- *(.init.data)
+ INIT_DATA
. = ALIGN(0x4);
__tagtable_begin = .;
*(.taglist)
@@ -278,8 +278,9 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ :
{
- *(.exit.literal .exit.text)
- *(.exit.data)
+ *(.exit.literal)
+ EXIT_TEXT
+ EXIT_DATA
*(.exitcall.exit)
}

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 9f584cc..ded7ca2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -183,6 +183,13 @@
*(.kprobes.text) \
VMLINUX_SYMBOL(__kprobes_text_end) = .;

+/* init and exit section handling */
+#define INIT_TEXT *(init.text)
+#define INIT_DATA *(init.data)
+#define EXIT_TEXT *(exit.text)
+#define EXIT_DATA *(exit.data)
+
+
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to
the beginning of the section so we begin them at 0. */
--
1.5.4.rc3.14.g44397

2008-01-20 20:11:20

by Sam Ravnborg

[permalink] [raw]
Subject: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

Introducing separate sections for __dev* (HOTPLUG),
__cpu* (HOTPLUG_CPU) and __mem* (MEMORY_HOTPLUG)
allows us to do a much more reliable Section mismatch
check in modpost. We are no longer dependent on the actual
configuration of for example HOTPLUG.

This has the effect that all users see much more
Section mismatch warnings than before because they
were almost all hidden when HOTPLUG was enabled.
The advantage of this is that when building a piece
of code then it is much more likely that the Section
mismatch errors are spotted and the warnings will be
felt less random of nature.

Signed-off-by: Sam Ravnborg <[email protected]>
Cc: Greg KH <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Adrian Bunk <[email protected]>
---
include/asm-generic/vmlinux.lds.h | 88 ++++++++++++++++++++++++++++++++++---
include/linux/init.h | 77 ++++++++++++++++----------------
scripts/mod/modpost.c | 54 ++++++++++++++++------
3 files changed, 159 insertions(+), 60 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ded7ca2..e0a56fb 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -9,10 +9,46 @@
/* Align . to a 8 byte boundary equals to maximum function alignment. */
#define ALIGN_FUNCTION() . = ALIGN(8)

+/* The actual configuration determine if the init/exit sections
+ * are handled as text/data or they can be discarded (which
+ * often happens at runtime)
+ */
+#ifdef CONFIG_HOTPLUG
+#define DEV_KEEP(sec) *(.dev##sec)
+#define DEV_DISCARD(sec)
+#else
+#define DEV_KEEP(sec)
+#define DEV_DISCARD(sec) *(.dev##sec)
+#endif
+
+#ifdef CONFIG_HOTPLUG_CPU
+#define CPU_KEEP(sec) *(.cpu##sec)
+#define CPU_DISCARD(sec)
+#else
+#define CPU_KEEP(sec)
+#define CPU_DISCARD(sec) *(.cpu##sec)
+#endif
+
+#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
+ || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
+#define MEM_KEEP(sec) *(.mem##sec)
+#define MEM_DISCARD(sec)
+#else
+#define MEM_KEEP(sec)
+#define MEM_DISCARD(sec) *(.mem##sec)
+#endif
+
+
/* .data section */
#define DATA_DATA \
*(.data) \
*(.data.init.refok) \
+ DEV_KEEP(init.data) \
+ DEV_KEEP(exit.data) \
+ CPU_KEEP(init.data) \
+ CPU_KEEP(exit.data) \
+ MEM_KEEP(init.data) \
+ MEM_KEEP(exit.data) \
. = ALIGN(8); \
VMLINUX_SYMBOL(__start___markers) = .; \
*(__markers) \
@@ -132,6 +168,16 @@
*(__ksymtab_strings) \
} \
\
+ /* __*init sections */ \
+ __init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) { \
+ DEV_KEEP(init.rodata) \
+ DEV_KEEP(exit.rodata) \
+ CPU_KEEP(init.rodata) \
+ CPU_KEEP(exit.rodata) \
+ MEM_KEEP(init.rodata) \
+ MEM_KEEP(exit.rodata) \
+ } \
+ \
/* Built-in module parameters. */ \
__param : AT(ADDR(__param) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___param) = .; \
@@ -139,7 +185,6 @@
VMLINUX_SYMBOL(__stop___param) = .; \
VMLINUX_SYMBOL(__end_rodata) = .; \
} \
- \
. = ALIGN((align));

/* RODATA provided for backward compatibility.
@@ -159,7 +204,14 @@
ALIGN_FUNCTION(); \
*(.text) \
*(.text.init.refok) \
- *(.exit.text.refok)
+ *(.exit.text.refok) \
+ DEV_KEEP(init.text) \
+ DEV_KEEP(exit.text) \
+ CPU_KEEP(init.text) \
+ CPU_KEEP(exit.text) \
+ MEM_KEEP(init.text) \
+ MEM_KEEP(exit.text)
+

/* sched.text is aling to function alignment to secure we have same
* address even at second ld pass when generating System.map */
@@ -184,11 +236,35 @@
VMLINUX_SYMBOL(__kprobes_text_end) = .;

/* init and exit section handling */
-#define INIT_TEXT *(init.text)
-#define INIT_DATA *(init.data)
-#define EXIT_TEXT *(exit.text)
-#define EXIT_DATA *(exit.data)
+#define INIT_DATA \
+ *(.init.data) \
+ DEV_DISCARD(init.data) \
+ DEV_DISCARD(init.rodata) \
+ CPU_DISCARD(init.data) \
+ CPU_DISCARD(init.rodata) \
+ MEM_DISCARD(init.data) \
+ MEM_DISCARD(init.rodata)
+
+#define INIT_TEXT \
+ *(.init.text) \
+ DEV_DISCARD(init.text) \
+ CPU_DISCARD(init.text) \
+ MEM_DISCARD(init.text)
+
+#define EXIT_DATA \
+ *(.exit.data) \
+ DEV_DISCARD(exit.data) \
+ DEV_DISCARD(exit.rodata) \
+ CPU_DISCARD(exit.data) \
+ CPU_DISCARD(exit.rodata) \
+ MEM_DISCARD(exit.data) \
+ MEM_DISCARD(exit.rodata)

+#define EXIT_TEXT \
+ *(.exit.text) \
+ DEV_DISCARD(exit.text) \
+ CPU_DISCARD(exit.text) \
+ MEM_DISCARD(exit.text)

/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to
diff --git a/include/linux/init.h b/include/linux/init.h
index 9980768..dcb66c7 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -60,18 +60,54 @@
#define __exit_refok noinline __section(.exit.text.refok)

#ifdef MODULE
-#define __exit __section(.exit.text) __cold
+#define __exitused
#else
-#define __exit __attribute_used__ __section(.exit.text) __cold
+#define __exitused __used
#endif

+#define __exit __section(.exit.text) __exitused __cold
+
+/* Used for HOTPLUG */
+#define __devinit __section(.devinit.text) __cold
+#define __devinitdata __section(.devinit.data)
+#define __devinitconst __section(.devinit.rodata)
+#define __devexit __section(.devexit.text) __exitused __cold
+#define __devexitdata __section(.devexit.data)
+#define __devexitconst __section(.devexit.rodata)
+
+/* Used for HOTPLUG_CPU */
+#define __cpuinit __section(.cpuinit.text) __cold
+#define __cpuinitdata __section(.cpuinit.data)
+#define __cpuinitconst __section(.cpuinit.rodata)
+#define __cpuexit __section(.cpuexit.text) __exitused __cold
+#define __cpuexitdata __section(.cpuexit.data)
+#define __cpuexitconst __section(.cpuexit.rodata)
+
+/* Used for MEMORY_HOTPLUG */
+#define __meminit __section(.meminit.text) __cold
+#define __meminitdata __section(.meminit.data)
+#define __meminitconst __section(.meminit.rodata)
+#define __memexit __section(.memexit.text) __exitused __cold
+#define __memexitdata __section(.memexit.data)
+#define __memexitconst __section(.memexit.rodata)
+
/* For assembly routines */
#define __INIT .section ".init.text","ax"
#define __INIT_REFOK .section ".text.init.refok","ax"
#define __FINIT .previous
+
#define __INITDATA .section ".init.data","aw"
#define __INITDATA_REFOK .section ".data.init.refok","aw"

+#define __DEVINIT .section ".devinit.text", "ax"
+#define __DEVINITDATA .section ".devinit.data", "aw"
+
+#define __CPUINIT .section ".cpuinit.text", "ax"
+#define __CPUINITDATA .section ".cpuinit.data", "aw"
+
+#define __MEMINIT .section ".meminit.text", "ax"
+#define __MEMINITDATA .section ".meminit.data", "aw"
+
#ifndef __ASSEMBLY__
/*
* Used for initialization calls..
@@ -254,43 +290,6 @@ void __init parse_early_param(void);
#define __initdata_or_module __initdata
#endif /*CONFIG_MODULES*/

-#ifdef CONFIG_HOTPLUG
-#define __devinit
-#define __devinitdata
-#define __devexit
-#define __devexitdata
-#else
-#define __devinit __init
-#define __devinitdata __initdata
-#define __devexit __exit
-#define __devexitdata __exitdata
-#endif
-
-#ifdef CONFIG_HOTPLUG_CPU
-#define __cpuinit
-#define __cpuinitdata
-#define __cpuexit
-#define __cpuexitdata
-#else
-#define __cpuinit __init
-#define __cpuinitdata __initdata
-#define __cpuexit __exit
-#define __cpuexitdata __exitdata
-#endif
-
-#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
- || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
-#define __meminit
-#define __meminitdata
-#define __memexit
-#define __memexitdata
-#else
-#define __meminit __init
-#define __meminitdata __initdata
-#define __memexit __exit
-#define __memexitdata __exitdata
-#endif
-
/* Functions marked as __devexit may be discarded at kernel link time, depending
on config options. Newer versions of binutils detect references from
retained sections to discarded sections and flag an error. Pointers to
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 986513d..730b321 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -670,27 +670,41 @@ int match(const char *sym, const char * const pat[])
static const char *section_white_list[] =
{ ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL };

-#define INIT_DATA_SECTIONS ".init.data$"
-#define EXIT_DATA_SECTIONS ".exit.data$"
+#define ALL_INIT_DATA_SECTIONS \
+ ".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$"
+#define ALL_EXIT_DATA_SECTIONS \
+ ".exit.data$", ".devexit.data$", ".cpuexit.data$", ".memexit.data$"

-#define INIT_TEXT_SECTIONS ".init.text$"
-#define EXIT_TEXT_SECTIONS ".exit.text$"
+#define ALL_INIT_TEXT_SECTIONS \
+ ".init.text$", ".devinit.text$", ".cpuinit.text$", ".meminit.text$"
+#define ALL_EXIT_TEXT_SECTIONS \
+ ".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$"

-#define INIT_SECTIONS INIT_DATA_SECTIONS, INIT_TEXT_SECTIONS
-#define EXIT_SECTIONS EXIT_DATA_SECTIONS, EXIT_TEXT_SECTIONS
+#define ALL_INIT_SECTIONS ALL_INIT_DATA_SECTIONS, ALL_INIT_TEXT_SECTIONS
+#define ALL_EXIT_SECTIONS ALL_EXIT_DATA_SECTIONS, ALL_EXIT_TEXT_SECTIONS

#define DATA_SECTIONS ".data$", ".data.rel$"
#define TEXT_SECTIONS ".text$"

+#define INIT_SECTIONS ".init.data$", ".init.text$"
+#define DEV_INIT_SECTIONS ".devinit.data$", ".devinit.text$"
+#define CPU_INIT_SECTIONS ".cpuinit.data$", ".cpuinit.text$"
+#define MEM_INIT_SECTIONS ".meminit.data$", ".meminit.text$"
+
+#define EXIT_SECTIONS ".exit.data$", ".exit.text$"
+#define DEV_EXIT_SECTIONS ".devexit.data$", ".devexit.text$"
+#define CPU_EXIT_SECTIONS ".cpuexit.data$", ".cpuexit.text$"
+#define MEM_EXIT_SECTIONS ".memexit.data$", ".memexit.text$"
+
/* init data sections */
-static const char *init_data_sections[] = { INIT_DATA_SECTIONS, NULL };
+static const char *init_data_sections[] = { ALL_INIT_DATA_SECTIONS, NULL };

/* all init sections */
-static const char *init_sections[] = { INIT_SECTIONS, NULL };
+static const char *init_sections[] = { ALL_INIT_SECTIONS, NULL };

/* All init and exit sections (code + data) */
static const char *init_exit_sections[] =
- {INIT_SECTIONS, EXIT_SECTIONS, NULL };
+ {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL };

/* data section */
static const char *data_sections[] = { DATA_SECTIONS, NULL };
@@ -734,22 +748,32 @@ const struct sectioncheck sectioncheck[] = {
*/
{
.fromsec = { TEXT_SECTIONS, DATA_SECTIONS, NULL },
- .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }
+ .tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }
+},
+/* Do not reference init code/data from devinit/cpuinit/meminit code/data */
+{
+ .fromsec = { DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, MEM_INIT_SECTIONS, NULL },
+ .tosec = { INIT_SECTIONS, NULL }
+},
+/* Do not reference exit code/data from devexit/cpuexit/memexit code/data */
+{
+ .fromsec = { DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS, NULL },
+ .tosec = { EXIT_SECTIONS, NULL }
},
/* Do not use exit code/data from init code */
{
- .fromsec = { INIT_SECTIONS, NULL },
- .tosec = { EXIT_SECTIONS, NULL },
+ .fromsec = { ALL_INIT_SECTIONS, NULL },
+ .tosec = { ALL_EXIT_SECTIONS, NULL },
},
/* Do not use init code/data from exit code */
{
- .fromsec = { EXIT_SECTIONS, NULL },
- .tosec = { INIT_SECTIONS, NULL }
+ .fromsec = { ALL_EXIT_SECTIONS, NULL },
+ .tosec = { ALL_INIT_SECTIONS, NULL }
},
/* Do not export init/exit functions or data */
{
.fromsec = { "__ksymtab*", NULL },
- .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }
+ .tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }
}
};

--
1.5.4.rc3.14.g44397

2008-01-20 20:11:34

by Sam Ravnborg

[permalink] [raw]
Subject: [PATCH] compiler.h: introduce __section()

Add a new helper: __section() that makes a section definition
much shorter and more readable.

Signed-off-by: Sam Ravnborg <[email protected]>
---
include/linux/compiler.h | 5 +++++
include/linux/init.h | 26 +++++++++++++-------------
2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index c68b67b..e0114a6 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -175,4 +175,9 @@ extern void __chk_io_ptr(const volatile void __iomem *);
#define __cold
#endif

+/* Simple shorthand for a section definition */
+#ifndef __section
+# define __section(S) __attribute__ ((__section__(#S)))
+#endif
+
#endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/init.h b/include/linux/init.h
index 5141381..9980768 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -40,10 +40,10 @@

/* These are for everybody (although not all archs will actually
discard it in modules) */
-#define __init __attribute__ ((__section__ (".init.text"))) __cold
-#define __initdata __attribute__ ((__section__ (".init.data")))
-#define __exitdata __attribute__ ((__section__(".exit.data")))
-#define __exit_call __attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
+#define __init __section(.init.text) __cold
+#define __initdata __section(.init.data)
+#define __exitdata __section(.exit.data)
+#define __exit_call __attribute_used__ __section(.exitcall.exit)

/* modpost check for section mismatches during the kernel build.
* A section mismatch happens when there are references from a
@@ -55,14 +55,14 @@
* the init/exit section (code or data) is valid and will teach modpost
* not to issue a warning.
* The markers follow same syntax rules as __init / __initdata. */
-#define __init_refok noinline __attribute__ ((__section__ (".text.init.refok")))
-#define __initdata_refok __attribute__ ((__section__ (".data.init.refok")))
-#define __exit_refok noinline __attribute__ ((__section__ (".exit.text.refok")))
+#define __init_refok noinline __section(.text.init.refok)
+#define __initdata_refok __section(.data.init.refok)
+#define __exit_refok noinline __section(.exit.text.refok)

#ifdef MODULE
-#define __exit __attribute__ ((__section__(".exit.text"))) __cold
+#define __exit __section(.exit.text) __cold
#else
-#define __exit __attribute_used__ __attribute__ ((__section__(".exit.text"))) __cold
+#define __exit __attribute_used__ __section(.exit.text) __cold
#endif

/* For assembly routines */
@@ -142,11 +142,11 @@ void prepare_namespace(void);

#define console_initcall(fn) \
static initcall_t __initcall_##fn \
- __attribute_used__ __attribute__((__section__(".con_initcall.init")))=fn
+ __attribute_used__ __section(.con_initcall.init)=fn

#define security_initcall(fn) \
static initcall_t __initcall_##fn \
- __attribute_used__ __attribute__((__section__(".security_initcall.init"))) = fn
+ __attribute_used__ __section(.security_initcall.init) = fn

struct obs_kernel_param {
const char *str;
@@ -164,7 +164,7 @@ struct obs_kernel_param {
static char __setup_str_##unique_id[] __initdata __aligned(1) = str; \
static struct obs_kernel_param __setup_##unique_id \
__attribute_used__ \
- __attribute__((__section__(".init.setup"))) \
+ __section(.init.setup) \
__attribute__((aligned((sizeof(long))))) \
= { __setup_str_##unique_id, fn, early }

@@ -242,7 +242,7 @@ void __init parse_early_param(void);
#endif

/* Data marked not to be saved by software suspend */
-#define __nosavedata __attribute__ ((__section__ (".data.nosave")))
+#define __nosavedata __section(.data.nosave)

/* This means "can be init if no module support, otherwise module load
may call it." */
--
1.5.4.rc3.14.g44397

2008-01-20 21:33:41

by Sam Ravnborg

[permalink] [raw]
Subject: Re: kbuild: improved Section mismatch detection

On Sun, Jan 20, 2008 at 09:05:27PM +0100, Sam Ravnborg wrote:
> I have spent the last week (the time I can afford to
> Linux stuff anyway) to improve the Section mismatch
> warnings detected by modpost.

Forgot to mention that all patches are made on top of
kbuild.git but I expect then to apply to mainline with
minimal effort.

They are all pushed out to the kbuild.git tree
for easy git retrival.

Please note that I often rebase kbuild.git
without any notice.

Sam

2008-01-20 22:29:23

by Adrian Bunk

[permalink] [raw]
Subject: Re: kbuild: improved Section mismatch detection

On Sun, Jan 20, 2008 at 09:05:27PM +0100, Sam Ravnborg wrote:
>...
> Adrian reminded us that KCFLAGS=-fno-inline told
> another story with more than 100 Section mismatch
> warnings on 64 bit x86 with an allyesconfig build.
>...

Not -fno-inline but -fno-inline-functions-called-once
(completely different option).

> Sam

cu
Adrian

--

"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed

2008-01-21 02:51:19

by Sam Ravnborg

[permalink] [raw]
Subject: Re: kbuild: improved Section mismatch detection

On Mon, Jan 21, 2008 at 12:27:54AM +0200, Adrian Bunk wrote:
> On Sun, Jan 20, 2008 at 09:05:27PM +0100, Sam Ravnborg wrote:
> >...
> > Adrian reminded us that KCFLAGS=-fno-inline told
> > another story with more than 100 Section mismatch
> > warnings on 64 bit x86 with an allyesconfig build.
> >...
>
> Not -fno-inline but -fno-inline-functions-called-once
> (completely different option).

Yep - looked that up after sending the mail.
A quick test shows no diference in # of generated Section mismatch
warnings for the two - which is good.

Sam

2008-01-21 03:03:52

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] kbuild: fix so modpost can now check any .o file

On Monday 21 January 2008 07:08:56 Sam Ravnborg wrote:
> It is very convinient to say:
> scripts/mod/modpost mm/built-in.o
>
> to check if any section mismatch errors occured
> in mm/ (as an example).

Hi Sam,

In an ideal world, wouldn't it be better to split out section analysis into a
different helper program?

Cheers,
Rusty.

2008-01-21 03:04:14

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH] kbuild: introduce blacklisting in modpost

On Monday 21 January 2008 07:08:59 Sam Ravnborg wrote:
> Change the logic in modpost so we identify all the
> bad combinations of sections that refer to other
> sections.
...
> +/* The pattern is an array of simple patterns.
> + * "foo" will match an exact string equal to "foo"
> + * "foo*" will match a string that begins with "foo"
> + * "foo$" will match a string equal to "foo" or "foo.1"
> + * where the '1' can be any number including several digits.
> + * The $ syntax is for sections where ld append a dot number
> + * to make section name unique.

Dumb question: would it be easier to canonicalize all the section names by
removing trailing .[num]*, then using fnmatch() and standard wildcards?

The rest of the patches look really nice: thanks for doing this cleanup!

Rusty.

2008-01-21 06:11:41

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH] kbuild: fix so modpost can now check any .o file

On Mon, Jan 21, 2008 at 11:56:31AM +1100, Rusty Russell wrote:
> On Monday 21 January 2008 07:08:56 Sam Ravnborg wrote:
> > It is very convinient to say:
> > scripts/mod/modpost mm/built-in.o
> >
> > to check if any section mismatch errors occured
> > in mm/ (as an example).
>
> Hi Sam,
>
> In an ideal world, wouldn't it be better to split out section analysis into a
> different helper program?

Now whats an ideal world ;-)
But otherwise yes - I have not just got around to it.

Sam

2008-01-21 07:34:45

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

On Sun, Jan 20, 2008 at 09:09:03PM +0100, Sam Ravnborg wrote:
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index ded7ca2..e0a56fb 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -9,10 +9,46 @@
> /* Align . to a 8 byte boundary equals to maximum function alignment. */
> #define ALIGN_FUNCTION() . = ALIGN(8)
>
> +/* The actual configuration determine if the init/exit sections
> + * are handled as text/data or they can be discarded (which
> + * often happens at runtime)
> + */
> +#ifdef CONFIG_HOTPLUG
> +#define DEV_KEEP(sec) *(.dev##sec)
> +#define DEV_DISCARD(sec)
> +#else
> +#define DEV_KEEP(sec)
> +#define DEV_DISCARD(sec) *(.dev##sec)
> +#endif
> +
Using your kbuild.git, these blow up for me:

LD .tmp_vmlinux1
sh4-linux-ld:arch/sh/kernel/vmlinux.lds:364: ignoring invalid character `#' in script
sh4-linux-ld:arch/sh/kernel/vmlinux.lds:364: ignoring invalid character `#' in script
sh4-linux-ld:arch/sh/kernel/vmlinux.lds:364: ignoring invalid character `#' in script
sh4-linux-ld:arch/sh/kernel/vmlinux.lds:364: ignoring invalid character `#' in script
sh4-linux-ld:arch/sh/kernel/vmlinux.lds:381: ignoring invalid character `#' in script
sh4-linux-ld:arch/sh/kernel/vmlinux.lds:381: ignoring invalid character `#' in script
sh4-linux-ld:arch/sh/kernel/vmlinux.lds:381: ignoring invalid character `#' in script
...

This comes out as:

.text : {
*(.text.head)
. = ALIGN(8); *(.text) *(.text.init.refok) *(.exit.text.refok) *(.dev##init.text)
*(.dev##exit.text)

. = ALIGN(8); __sched_text_start = .; *(.sched.text)
__sched_text_end = .;
. = ALIGN(8); __lock_text_start = .; *(.spinlock.text)
__lock_text_end = .;
. = ALIGN(8); __kprobes_text_start = .; *(.kprobes.text)
__kprobes_text_end = .;
*(.fixup)
*(.gnu.warning)
...

so the ## is being taken directly rather than acting as a concatenation.

2008-01-21 09:57:25

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

On Mon, Jan 21, 2008 at 04:33:41PM +0900, Paul Mundt wrote:
> On Sun, Jan 20, 2008 at 09:09:03PM +0100, Sam Ravnborg wrote:
> > diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> > index ded7ca2..e0a56fb 100644
> > --- a/include/asm-generic/vmlinux.lds.h
> > +++ b/include/asm-generic/vmlinux.lds.h
> > @@ -9,10 +9,46 @@
> > /* Align . to a 8 byte boundary equals to maximum function alignment. */
> > #define ALIGN_FUNCTION() . = ALIGN(8)
> >
> > +/* The actual configuration determine if the init/exit sections
> > + * are handled as text/data or they can be discarded (which
> > + * often happens at runtime)
> > + */
> > +#ifdef CONFIG_HOTPLUG
> > +#define DEV_KEEP(sec) *(.dev##sec)
> > +#define DEV_DISCARD(sec)
> > +#else
> > +#define DEV_KEEP(sec)
> > +#define DEV_DISCARD(sec) *(.dev##sec)
> > +#endif
> > +
> Using your kbuild.git, these blow up for me:
>
> LD .tmp_vmlinux1
> sh4-linux-ld:arch/sh/kernel/vmlinux.lds:364: ignoring invalid character `#' in script
> sh4-linux-ld:arch/sh/kernel/vmlinux.lds:364: ignoring invalid character `#' in script
> sh4-linux-ld:arch/sh/kernel/vmlinux.lds:364: ignoring invalid character `#' in script
> sh4-linux-ld:arch/sh/kernel/vmlinux.lds:364: ignoring invalid character `#' in script
> sh4-linux-ld:arch/sh/kernel/vmlinux.lds:381: ignoring invalid character `#' in script
> sh4-linux-ld:arch/sh/kernel/vmlinux.lds:381: ignoring invalid character `#' in script
> sh4-linux-ld:arch/sh/kernel/vmlinux.lds:381: ignoring invalid character `#' in script
> ...
>
> This comes out as:
>
> .text : {
> *(.text.head)
> . = ALIGN(8); *(.text) *(.text.init.refok) *(.exit.text.refok) *(.dev##init.text)
> *(.dev##exit.text)
>
> . = ALIGN(8); __sched_text_start = .; *(.sched.text)
> __sched_text_end = .;
> . = ALIGN(8); __lock_text_start = .; *(.spinlock.text)
> __lock_text_end = .;
> . = ALIGN(8); __kprobes_text_start = .; *(.kprobes.text)
> __kprobes_text_end = .;
> *(.fixup)
> *(.gnu.warning)
> ...
>
> so the ## is being taken directly rather than acting as a concatenation.

Strange...
I can reproduce with gcc 3.4.5 here - will fix.

Setting CONFIG_HOTPLUG=n for sparc64 also cause troubles. Something with local symbols discarded.
So more work is needed.

Sam

2008-01-21 10:30:11

by Andreas Schwab

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

Sam Ravnborg <[email protected]> writes:

> On Mon, Jan 21, 2008 at 04:33:41PM +0900, Paul Mundt wrote:
>> so the ## is being taken directly rather than acting as a concatenation.
>
> Strange...
> I can reproduce with gcc 3.4.5 here - will fix.

The ## operator does not work with -traditional.

Andreas.

--
Andreas Schwab, SuSE Labs, [email protected]
SuSE Linux Products GmbH, Maxfeldstra?e 5, 90409 N?rnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."

2008-01-21 10:45:17

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

On Mon, Jan 21, 2008 at 11:29:52AM +0100, Andreas Schwab wrote:
> Sam Ravnborg <[email protected]> writes:
>
> > On Mon, Jan 21, 2008 at 04:33:41PM +0900, Paul Mundt wrote:
> >> so the ## is being taken directly rather than acting as a concatenation.
> >
> > Strange...
> > I can reproduce with gcc 3.4.5 here - will fix.
>
> The ## operator does not work with -traditional.

Crap - then it breaks at the following architectures:
sh64, s390, m68k, m32r

Thanks Andreas.

Sam

2008-01-21 10:47:46

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

On Mon, Jan 21, 2008 at 11:45:06AM +0100, Sam Ravnborg wrote:
> On Mon, Jan 21, 2008 at 11:29:52AM +0100, Andreas Schwab wrote:
> > Sam Ravnborg <[email protected]> writes:
> >
> > > On Mon, Jan 21, 2008 at 04:33:41PM +0900, Paul Mundt wrote:
> > >> so the ## is being taken directly rather than acting as a concatenation.
> > >
> > > Strange...
> > > I can reproduce with gcc 3.4.5 here - will fix.
> >
> > The ## operator does not work with -traditional.
>
> Crap - then it breaks at the following architectures:
> sh64, s390, m68k, m32r
>
> Thanks Andreas.

OK - I was too quick it seem.
sh has:
arch/sh/Makefile:CPPFLAGS_vmlinux.lds := -traditional

So this needs to be ripped out as it is not needed.

Sam

2008-01-21 10:53:51

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

On Mon, Jan 21, 2008 at 11:47:45AM +0100, Sam Ravnborg wrote:
> On Mon, Jan 21, 2008 at 11:45:06AM +0100, Sam Ravnborg wrote:
> > On Mon, Jan 21, 2008 at 11:29:52AM +0100, Andreas Schwab wrote:
> > > Sam Ravnborg <[email protected]> writes:
> > >
> > > > On Mon, Jan 21, 2008 at 04:33:41PM +0900, Paul Mundt wrote:
> > > >> so the ## is being taken directly rather than acting as a concatenation.
> > > >
> > > > Strange...
> > > > I can reproduce with gcc 3.4.5 here - will fix.
> > >
> > > The ## operator does not work with -traditional.
> >
> > Crap - then it breaks at the following architectures:
> > sh64, s390, m68k, m32r
> >
> > Thanks Andreas.
>
> OK - I was too quick it seem.
> sh has:
> arch/sh/Makefile:CPPFLAGS_vmlinux.lds := -traditional
>
> So this needs to be ripped out as it is not needed.
>
Yes, that can be killed. If this is aimed at 2.6.25, I'll just kill it
off in my tree. Otherwise, feel free to roll this in to your patch set.

Your kbuild.git works fine with this applied.

Signed-off-by: Paul Mundt <[email protected]>

---

diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index e189fae..6a0eb7d 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -151,8 +151,6 @@ drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/

boot := arch/sh/boot

-CPPFLAGS_vmlinux.lds := -traditional
-
incdir-prefix := $(srctree)/include/asm-sh/

# Update machine arch and proc symlinks if something which affects

2008-01-21 12:06:44

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

On Mon, Jan 21, 2008 at 07:52:57PM +0900, Paul Mundt wrote:
> On Mon, Jan 21, 2008 at 11:47:45AM +0100, Sam Ravnborg wrote:
> > On Mon, Jan 21, 2008 at 11:45:06AM +0100, Sam Ravnborg wrote:
> > > On Mon, Jan 21, 2008 at 11:29:52AM +0100, Andreas Schwab wrote:
> > > > Sam Ravnborg <[email protected]> writes:
> > > >
> > > > > On Mon, Jan 21, 2008 at 04:33:41PM +0900, Paul Mundt wrote:
> > > > >> so the ## is being taken directly rather than acting as a concatenation.
> > > > >
> > > > > Strange...
> > > > > I can reproduce with gcc 3.4.5 here - will fix.
> > > >
> > > > The ## operator does not work with -traditional.
> > >
> > > Crap - then it breaks at the following architectures:
> > > sh64, s390, m68k, m32r
> > >
> > > Thanks Andreas.
> >
> > OK - I was too quick it seem.
> > sh has:
> > arch/sh/Makefile:CPPFLAGS_vmlinux.lds := -traditional
> >
> > So this needs to be ripped out as it is not needed.
> >
> Yes, that can be killed. If this is aimed at 2.6.25, I'll just kill it
> off in my tree. Otherwise, feel free to roll this in to your patch set.

It is aimed for 2.6.25 and it looks reasonable to reach that goal.
So please take this patch in your tree.

Thanks,

Sam

2008-01-21 20:33:41

by Sam Ravnborg

[permalink] [raw]
Subject: Re: kbuild: improved Section mismatch detection

On Mon, Jan 21, 2008 at 12:27:54AM +0200, Adrian Bunk wrote:
> On Sun, Jan 20, 2008 at 09:05:27PM +0100, Sam Ravnborg wrote:
> >...
> > Adrian reminded us that KCFLAGS=-fno-inline told
> > another story with more than 100 Section mismatch
> > warnings on 64 bit x86 with an allyesconfig build.
> >...
>
> Not -fno-inline but -fno-inline-functions-called-once
> (completely different option).

Do you know when gcc started to support
-fno-inline-functions-called-once?

I do not have anything older than 3.4.5 build here.

I should have a gcc 3.2 (Documentation/Changes)
but no at the moment.

Sam

2008-01-21 20:57:33

by Adrian Bunk

[permalink] [raw]
Subject: Re: kbuild: improved Section mismatch detection

On Mon, Jan 21, 2008 at 09:31:17PM +0100, Sam Ravnborg wrote:
> On Mon, Jan 21, 2008 at 12:27:54AM +0200, Adrian Bunk wrote:
> > On Sun, Jan 20, 2008 at 09:05:27PM +0100, Sam Ravnborg wrote:
> > >...
> > > Adrian reminded us that KCFLAGS=-fno-inline told
> > > another story with more than 100 Section mismatch
> > > warnings on 64 bit x86 with an allyesconfig build.
> > >...
> >
> > Not -fno-inline but -fno-inline-functions-called-once
> > (completely different option).
>
> Do you know when gcc started to support
> -fno-inline-functions-called-once?
>
> I do not have anything older than 3.4.5 build here.
>
> I should have a gcc 3.2 (Documentation/Changes)
> but no at the moment.

The inline-functions-called-once optimization is only available with
unit-at-a-time, and the -fno-inline-functions-called-once option is
therefore present since gcc 3.4.

> Sam

cu
Adrian

--

"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed

2008-01-22 00:57:55

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

On Mon, Jan 21, 2008 at 01:06:41PM +0100, Sam Ravnborg wrote:
> On Mon, Jan 21, 2008 at 07:52:57PM +0900, Paul Mundt wrote:
> > On Mon, Jan 21, 2008 at 11:47:45AM +0100, Sam Ravnborg wrote:
> > > On Mon, Jan 21, 2008 at 11:45:06AM +0100, Sam Ravnborg wrote:
> > > > On Mon, Jan 21, 2008 at 11:29:52AM +0100, Andreas Schwab wrote:
> > > > > Sam Ravnborg <[email protected]> writes:
> > > > >
> > > > > > On Mon, Jan 21, 2008 at 04:33:41PM +0900, Paul Mundt wrote:
> > > > > >> so the ## is being taken directly rather than acting as a concatenation.
> > > > > >
> > > > > > Strange...
> > > > > > I can reproduce with gcc 3.4.5 here - will fix.
> > > > >
> > > > > The ## operator does not work with -traditional.
> > > >
> > > > Crap - then it breaks at the following architectures:
> > > > sh64, s390, m68k, m32r
> > > >
> > > > Thanks Andreas.
> > >
> > > OK - I was too quick it seem.
> > > sh has:
> > > arch/sh/Makefile:CPPFLAGS_vmlinux.lds := -traditional
> > >
> > > So this needs to be ripped out as it is not needed.
> > >
> > Yes, that can be killed. If this is aimed at 2.6.25, I'll just kill it
> > off in my tree. Otherwise, feel free to roll this in to your patch set.
>
> It is aimed for 2.6.25 and it looks reasonable to reach that goal.
> So please take this patch in your tree.
>
Done.

2008-01-22 03:26:00

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

On Tue, Jan 22, 2008 at 09:56:57AM +0900, Paul Mundt wrote:
> On Mon, Jan 21, 2008 at 01:06:41PM +0100, Sam Ravnborg wrote:
> > On Mon, Jan 21, 2008 at 07:52:57PM +0900, Paul Mundt wrote:
> > > On Mon, Jan 21, 2008 at 11:47:45AM +0100, Sam Ravnborg wrote:
> > > > On Mon, Jan 21, 2008 at 11:45:06AM +0100, Sam Ravnborg wrote:
> > > > > On Mon, Jan 21, 2008 at 11:29:52AM +0100, Andreas Schwab wrote:
> > > > > > Sam Ravnborg <[email protected]> writes:
> > > > > >
> > > > > > > On Mon, Jan 21, 2008 at 04:33:41PM +0900, Paul Mundt wrote:
> > > > > > >> so the ## is being taken directly rather than acting as a concatenation.
> > > > > > >
> > > > > > > Strange...
> > > > > > > I can reproduce with gcc 3.4.5 here - will fix.
> > > > > >
> > > > > > The ## operator does not work with -traditional.
> > > > >
> > > > > Crap - then it breaks at the following architectures:
> > > > > sh64, s390, m68k, m32r
> > > > >
> > > > > Thanks Andreas.
> > > >
> > > > OK - I was too quick it seem.
> > > > sh has:
> > > > arch/sh/Makefile:CPPFLAGS_vmlinux.lds := -traditional
> > > >
> > > > So this needs to be ripped out as it is not needed.
> > > >
> > > Yes, that can be killed. If this is aimed at 2.6.25, I'll just kill it
> > > off in my tree. Otherwise, feel free to roll this in to your patch set.
> >
> > It is aimed for 2.6.25 and it looks reasonable to reach that goal.
> > So please take this patch in your tree.
> >
> Done.
Thanks Paul,
and thanks for the prompt testing!

Sam

2008-01-22 21:16:38

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

On Sun, Jan 20, 2008 at 09:09:03PM +0100, Sam Ravnborg wrote:
> Introducing separate sections for __dev* (HOTPLUG),
> __cpu* (HOTPLUG_CPU) and __mem* (MEMORY_HOTPLUG)
> allows us to do a much more reliable Section mismatch
> check in modpost. We are no longer dependent on the actual
> configuration of for example HOTPLUG.
>
> This has the effect that all users see much more
> Section mismatch warnings than before because they
> were almost all hidden when HOTPLUG was enabled.
> The advantage of this is that when building a piece
> of code then it is much more likely that the Section
> mismatch errors are spotted and the warnings will be
> felt less random of nature.
>
> Signed-off-by: Sam Ravnborg <[email protected]>
> Cc: Greg KH <[email protected]>
> Cc: Randy Dunlap <[email protected]>
> Cc: Adrian Bunk <[email protected]>

I like this a lot. It makes things much more understandable from a
driver developer's point of view, and would allow us to mark some things
as freeable when we do not run with a CPU hotplug system :)

Feel free to add a:
Acked-by: Greg Kroah-Hartman <[email protected]>
to the patch, if you want to take it in your tree.

thanks,

greg k-h

2008-01-22 21:25:38

by Russell King

[permalink] [raw]
Subject: Re: [PATCH] Use separate sections for __dev/__cpu/__mem code/data

On Tue, Jan 22, 2008 at 01:17:15PM -0800, Greg KH wrote:
> I like this a lot. It makes things much more understandable from a
> driver developer's point of view, and would allow us to mark some things
> as freeable when we do not run with a CPU hotplug system :)

You mean at run time - I'm not sure if there's any advantage to that.

In order to free the hotplug cpu data and text, you'd have to make
those sections page aligned - and then you have the question of
how much space you are wasting in doing so. That will be variable
over time as the code changes.

Also, if you were to merge the hotplug cpu text and data to reduce
the wastage, would that cause any architectures any issues? (Thinking
about execute-only being set on the kernel's text section only, etc.)

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: