Re: WARNING: modpost: vmlinux.o(.text.unlikely+0x2c44): Section mismatch in reference from the function trace_define_generic_fields() to the variable .init.data:initcall_level_names

From: Steven Rostedt
Date: Mon Jan 10 2022 - 18:51:05 EST


On Tue, 21 Dec 2021 01:12:12 +0800
kernel test robot <lkp@xxxxxxxxx> wrote:

> All warnings (new ones prefixed by >>, old ones prefixed by <<):
>
> >> WARNING: modpost: vmlinux.o(.text.unlikely+0x2c44): Section mismatch in reference from the function trace_define_generic_fields() to the variable .init.data:initcall_level_names
> The function trace_define_generic_fields() references
> the variable __initdata initcall_level_names.
> This is often because trace_define_generic_fields lacks a __initdata
> annotation or the annotation of initcall_level_names is wrong.

I keep getting this, and it looks like a bug in the compiler not the kernel
code.

We have:

int filter_assign_type(const char *type)
{
if (strstr(type, "__data_loc") && strstr(type, "char"))
return FILTER_DYN_STRING;

if (strstr(type, "__rel_loc") && strstr(type, "char"))
return FILTER_RDYN_STRING;

if (strchr(type, '[') && strstr(type, "char"))
return FILTER_STATIC_STRING;

if (strcmp(type, "char *") == 0 || strcmp(type, "const char *") == 0)
return FILTER_PTR_STRING;

return FILTER_OTHER;
}

static int __trace_define_field(struct list_head *head, const char *type,
const char *name, int offset, int size,
int is_signed, int filter_type)
{
struct ftrace_event_field *field;

field = kmem_cache_alloc(field_cachep, GFP_TRACE);
if (!field)
return -ENOMEM;

field->name = name;
field->type = type;

if (filter_type == FILTER_OTHER)
field->filter_type = filter_assign_type(type);
else
field->filter_type = filter_type;

field->offset = offset;
field->size = size;
field->is_signed = is_signed;

list_add(&field->link, head);

return 0;
}

#define is_signed_type(type) (((type)(-1)) < (type)1)

static LIST_HEAD(ftrace_generic_fields);

#define __generic_field(type, item, filter_type) \
ret = __trace_define_field(&ftrace_generic_fields, #type, \
#item, 0, 0, is_signed_type(type), \
filter_type); \
if (ret) \
return ret;


static int trace_define_generic_fields(void)
{
int ret;

__generic_field(int, CPU, FILTER_CPU);
__generic_field(int, cpu, FILTER_CPU);
__generic_field(char *, COMM, FILTER_COMM);
__generic_field(char *, comm, FILTER_COMM);

return ret;
}


Please tell me where initcall_level_names is being referenced?

Either fix the compiler or tell me exactly what the bug is. Otherwise, stop
sending me this.

-- Steve