2015-04-19 19:22:22

by Paul Gortmaker

[permalink] [raw]
Subject: [PATCH 1/2] modpost: expand pattern matching to support substring matches

Currently the match() function supports a leading * to match any
prefix and a trailing * to match any suffix. However there currently
is not a combination of both that can be used to target matches of
whole families of functions that share a common substring.

Here we expand the *foo and foo* match to also support *foo* with
the goal of targeting compiler generated symbol names that contain
strings like ".constprop." and ".isra."

Signed-off-by: Paul Gortmaker <[email protected]>
---
scripts/mod/modpost.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 22dbc604cdb9..b18cecb6bf5a 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -776,6 +776,7 @@ static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
* "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 that contains "foo"
*/
static int match(const char *sym, const char * const pat[])
{
@@ -784,8 +785,17 @@ static int match(const char *sym, const char * const pat[])
p = *pat++;
const char *endp = p + strlen(p) - 1;

+ /* "*foo*" */
+ if (*p == '*' && *endp == '*') {
+ char *here, *bare = strndup(p + 1, strlen(p) - 2);
+
+ here = strstr(sym, bare);
+ free(bare);
+ if (here != NULL)
+ return 1;
+ }
/* "*foo" */
- if (*p == '*') {
+ else if (*p == '*') {
if (strrcmp(sym, p + 1) == 0)
return 1;
}
--
2.2.1


2015-04-19 19:22:17

by Paul Gortmaker

[permalink] [raw]
Subject: [PATCH 2/2] modpost: don't emit section mismatch warnings for compiler optimizations

Currently an allyesconfig build [gcc-4.9.1] can generate the following:

WARNING: vmlinux.o(.text.unlikely+0x3864): Section mismatch in
reference from the function cpumask_empty.constprop.3() to the
variable .init.data:nmi_ipi_mask

which comes from the cpumask_empty usage in arch/x86/kernel/nmi_selftest.c.

Normally we would not see a symbol entry for cpumask_empty since it is:

static inline bool cpumask_empty(const struct cpumask *srcp)

however in this case, the variant of the symbol gets emitted when GCC does
constant propagation optimization.

Fix things up so that any locally optimized constprop variants don't warn
when accessing variables that live in the __init sections.

Signed-off-by: Paul Gortmaker <[email protected]>
---
scripts/mod/modpost.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index b18cecb6bf5a..572f1e4a2626 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -908,6 +908,9 @@ static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL };
static const char *const init_exit_sections[] =
{ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL };

+/* all text sections */
+static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL };
+
/* data section */
static const char *const data_sections[] = { DATA_SECTIONS, NULL };

@@ -926,6 +929,7 @@ static const char *const data_sections[] = { DATA_SECTIONS, NULL };
static const char *const head_sections[] = { ".head.text*", NULL };
static const char *const linker_symbols[] =
{ "__init_begin", "_sinittext", "_einittext", NULL };
+static const char *const optim_symbols[] = { "*.constprop.*", NULL };

enum mismatch {
TEXT_TO_ANY_INIT,
@@ -1127,6 +1131,17 @@ static const struct sectioncheck *section_mismatch(
* This pattern is identified by
* refsymname = __init_begin, _sinittext, _einittext
*
+ * Pattern 5:
+ * GCC may optimize static inlines when fed constant arg(s) resulting
+ * in functions like cpumask_empty() -- generating an associated symbol
+ * cpumask_empty.constprop.3 that appears in the audit. If the const that
+ * is passed in comes from __init, like say nmi_ipi_mask, we get a
+ * meaningless section warning. May need to add isra symbols too...
+ * This pattern is identified by
+ * tosec = init section
+ * fromsec = text section
+ * refsymname = *.constprop.*
+ *
**/
static int secref_whitelist(const struct sectioncheck *mismatch,
const char *fromsec, const char *fromsym,
@@ -1159,6 +1174,12 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
if (match(tosym, linker_symbols))
return 0;

+ /* Check for pattern 5 */
+ if (match(fromsec, text_sections) &&
+ match(tosec, init_sections) &&
+ match(fromsym, optim_symbols))
+ return 0;
+
return 1;
}

--
2.2.1

2015-04-20 02:17:20

by Rusty Russell

[permalink] [raw]
Subject: Re: [PATCH 2/2] modpost: don't emit section mismatch warnings for compiler optimizations

Paul Gortmaker <[email protected]> writes:
> Currently an allyesconfig build [gcc-4.9.1] can generate the following:
>
> WARNING: vmlinux.o(.text.unlikely+0x3864): Section mismatch in
> reference from the function cpumask_empty.constprop.3() to the
> variable .init.data:nmi_ipi_mask
>
> which comes from the cpumask_empty usage in arch/x86/kernel/nmi_selftest.c.

Thanks for the excellent explanation and patches.

Applied!
Rusty.

>
> Normally we would not see a symbol entry for cpumask_empty since it is:
>
> static inline bool cpumask_empty(const struct cpumask *srcp)
>
> however in this case, the variant of the symbol gets emitted when GCC does
> constant propagation optimization.
>
> Fix things up so that any locally optimized constprop variants don't warn
> when accessing variables that live in the __init sections.
>
> Signed-off-by: Paul Gortmaker <[email protected]>
> ---
> scripts/mod/modpost.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
> index b18cecb6bf5a..572f1e4a2626 100644
> --- a/scripts/mod/modpost.c
> +++ b/scripts/mod/modpost.c
> @@ -908,6 +908,9 @@ static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL };
> static const char *const init_exit_sections[] =
> {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL };
>
> +/* all text sections */
> +static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL };
> +
> /* data section */
> static const char *const data_sections[] = { DATA_SECTIONS, NULL };
>
> @@ -926,6 +929,7 @@ static const char *const data_sections[] = { DATA_SECTIONS, NULL };
> static const char *const head_sections[] = { ".head.text*", NULL };
> static const char *const linker_symbols[] =
> { "__init_begin", "_sinittext", "_einittext", NULL };
> +static const char *const optim_symbols[] = { "*.constprop.*", NULL };
>
> enum mismatch {
> TEXT_TO_ANY_INIT,
> @@ -1127,6 +1131,17 @@ static const struct sectioncheck *section_mismatch(
> * This pattern is identified by
> * refsymname = __init_begin, _sinittext, _einittext
> *
> + * Pattern 5:
> + * GCC may optimize static inlines when fed constant arg(s) resulting
> + * in functions like cpumask_empty() -- generating an associated symbol
> + * cpumask_empty.constprop.3 that appears in the audit. If the const that
> + * is passed in comes from __init, like say nmi_ipi_mask, we get a
> + * meaningless section warning. May need to add isra symbols too...
> + * This pattern is identified by
> + * tosec = init section
> + * fromsec = text section
> + * refsymname = *.constprop.*
> + *
> **/
> static int secref_whitelist(const struct sectioncheck *mismatch,
> const char *fromsec, const char *fromsym,
> @@ -1159,6 +1174,12 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
> if (match(tosym, linker_symbols))
> return 0;
>
> + /* Check for pattern 5 */
> + if (match(fromsec, text_sections) &&
> + match(tosec, init_sections) &&
> + match(fromsym, optim_symbols))
> + return 0;
> +
> return 1;
> }
>
> --
> 2.2.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/