Mailinglist Archive: opensuse-bugs (4691 mails)

< Previous Next >
[Bug 582222] kernel panic on boot with gcc-4.5-compiled kernel (Attempted to kill init!)
  • From: bugzilla_noreply@xxxxxxxxxx
  • Date: Tue, 23 Feb 2010 22:27:51 +0000
  • Message-id: <20100223222751.4EDC424551B@xxxxxxxxxxxxxxxxxxxxxx>
http://bugzilla.novell.com/show_bug.cgi?id=582222

http://bugzilla.novell.com/show_bug.cgi?id=582222#c5


--- Comment #5 from Jeff Mahoney <jeffm@xxxxxxxxxx> 2010-02-23 22:27:50 UTC ---
Ok, I've tracked it down. It's failing because instead of calling the
->raw_init callback for the second event, it's calling the ->unregfunc.

It's failing in event_trace_init(), where it goes through each of the ftrace
events and runs the ->raw_init() callback.

ftrace events are defined in the _ftrace_events section as an array of struct
ftrace_event_call, aligned to 4 byte boundaries.

An event is defined like this:
struct ftrace_event_call {
struct list_head list;
char *name;
char *system;
struct dentry *dir;
struct trace_event *event;
int enabled;
int (*regfunc)(struct ftrace_event_call *);
void (*unregfunc)(struct ftrace_event_call *);
int id;
int (*raw_init)(struct ftrace_event_call *);
int (*show_format)(struct ftrace_event_call *,
struct trace_seq *);
int (*define_fields)(struct ftrace_event_call *);
struct list_head fields;
int filter_active;
struct event_filter *filter;
void *mod;
void *data;

int profile_count;
int (*profile_enable)(struct ftrace_event_call *);
void (*profile_disable)(struct ftrace_event_call *);
};

[...]

#define DEFINE_EVENT(template, call, proto, args) \
\
static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) event_##call = { \
.name = #call, \
.system = __stringify(TRACE_SYSTEM), \
.event = &ftrace_event_type_##call, \
.raw_init = trace_event_raw_init, \
.regfunc = ftrace_raw_reg_event_##call, \
.unregfunc = ftrace_raw_unreg_event_##call, \
.show_format = ftrace_format_##template, \
.define_fields = ftrace_define_fields_##template, \
_TRACE_PROFILE_INIT(call) \
}

This is the objdump of arch/x86/kernel/ptrace.o, where the sys_enter ftrace
vent is defined.

With gcc 4.5:
Disassembly of section _ftrace_events:

0000000000000000 <event_sys_exit>:
...
10: R_X86_64_64 .rodata.str1.1+0x3f
18: R_X86_64_64 .rodata.str1.1+0x81
28: R_X86_64_64 .data
38: R_X86_64_64 .text+0x380
40: R_X86_64_64 .text+0x300
50: R_X86_64_64 trace_event_raw_init
58: R_X86_64_64 .text+0x1e0
60: R_X86_64_64 .text+0x410
a0: R_X86_64_64 .text+0x360
a8: R_X86_64_64 .text+0x2e0

00000000000000c0 <event_sys_enter>:
...
d0: R_X86_64_64 .rodata.str1.1+0x35
d8: R_X86_64_64 .rodata.str1.1+0x81
e8: R_X86_64_64 .data+0x60
f8: R_X86_64_64 .text+0x340
100: R_X86_64_64 .text+0x2c0
110: R_X86_64_64 trace_event_raw_init
118: R_X86_64_64 .text+0x150
120: R_X86_64_64 .text+0x3a0
160: R_X86_64_64 .text+0x320
168: R_X86_64_64 .text+0x2a0

With gcc 4.4:

Disassembly of section _ftrace_events:

0000000000000000 <event_sys_exit>:
...
10: R_X86_64_64 .rodata.str1.1+0x3f
18: R_X86_64_64 .rodata.str1.1+0x7d
28: R_X86_64_64 .data
38: R_X86_64_64 .text+0x3c0
40: R_X86_64_64 .text+0x340
50: R_X86_64_64 trace_event_raw_init
58: R_X86_64_64 .text+0x250
60: R_X86_64_64 .text+0x450
a0: R_X86_64_64 .text+0x3a0
a8: R_X86_64_64 .text+0x320

00000000000000b0 <event_sys_enter>:
...
c0: R_X86_64_64 .rodata.str1.1+0x35
c8: R_X86_64_64 .rodata.str1.1+0x7d
d8: R_X86_64_64 .data+0x60
e8: R_X86_64_64 .text+0x380
f0: R_X86_64_64 .text+0x300
100: R_X86_64_64 trace_event_raw_init
108: R_X86_64_64 .text+0x1e0
110: R_X86_64_64 .text+0x3e0
150: R_X86_64_64 .text+0x360
158: R_X86_64_64 .text+0x2e0


For both versions, I see:
(gdb) print sizeof(struct ftrace_event_call)
$1 = 176

So the second event is at 0xc0 in the gcc 4.5-built version and at 0xb0 in the
gcc 4.4-build version.

Here's the disass of the relevant portion of the loop that iterates these event
structures in event_trace_init -- on the gcc 4.5 version.
e8: 48 c7 c3 00 00 00 00 mov $0x0,%rbx
eb: R_X86_64_32S __start_ftrace_events
..
138: 48 83 7b 10 00 cmpq $0x0,0x10(%rbx)
13d: 74 73 je 1b2 <event_trace_init+0x182>
13f: 48 8b 43 50 mov 0x50(%rbx),%rax
143: 48 85 c0 test %rax,%rax
146: 74 22 je 16a <event_trace_init+0x13a>
148: 48 89 df mov %rbx,%rdi
14b: ff d0 callq *%rax
..
1b2: 48 81 c3 b0 00 00 00 add $0xb0,%rbx
1b9: 48 81 fb 00 00 00 00 cmp $0x0,%rbx
1bc: R_X86_64_32S __stop_ftrace_events
1c0: 0f 82 72 ff ff ff jb 138 <event_trace_init+0x108>

So at first, we're at the beginning of __start_ftrace_events, which starts with
the sys_exit ftrace event, followed by the sys_enter ftrace event. Using local
addresses, that means:

event 0: 0x000
event 1: 0x0b0
event 2: 0x160

. but instead of finding event 1 at b0, we're in between array members. When
we go back up and look up the raw_init callback, which should be at 0x100 and
set to trace_event_raw_init, we get .text+0x2c0
(ftrace_raw_unreg_event_sys_enter) instead. Naturally, nothing is set up yet
since we haven't registered anything yet, so we blow up.

--
Configure bugmail: http://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.

< Previous Next >
References