2002-11-29 16:06:42

by Zwane Mwaikambo

[permalink] [raw]
Subject: [BUG][2.5.50] kallsyms dies badly with module

Hi Rusty,
If kallsyms_lookup tries to get a symbol from tiglusb.c loaded as
a module it oopses.

sysrq T
...
tcsh R current 0 1447 1445 (NOTLB)
Call Trace:
[<c0129ef1>] del_timer_sync+0x1/0x90
[<c012a68f>] schedule_timeout+0x6f/0xc0
[<c012a610>] process_timeout+0x0/0x10
[<d0878ab4>] <1>Unable to handle kernel paging request at virtual address d086e4d8
printing eip:
c013653c
*pde = 0fef4067
*pte = 00000000
Oops: 0000
CPU: 0
EIP: 0060:[<c013653c>] Not tainted
EFLAGS: 00010286
EIP is at __print_symbol+0x3c/0x100
eax: 00000000 ebx: d0878ab4 ecx: ffffffff edx: d087600c
esi: d086e4d8 edi: d086e4d8 ebp: ccf21c1c esp: ccf21bec
ds: 0068 es: 0068 ss: 0068
Process tcsh (pid: 1447, threadinfo=ccf20000 task=cdebe120)
Stack: ffffc56e ccf21bec 00000e74 00000054 d087600c 0000000e ccf21c40 c0122d4c
d0878ab4 d0878ab4 cdebe120 00000006 ccf21c40 c010a7a4 c046a0ef d0878ab4
cdebe120 c011e5eb ccf21f04 c052b5d8 00000074 00000001 c026c28e 00000074
Call Trace:
[<c0122d4c>] printk+0x18c/0x220
[<d0878ab4>] <1>Unable to handle kernel paging request at virtual address d086e4d8
printing eip:

...

Until it finally deadlocks in the page fault handler. Basically it will
keep getting an invalid page fault on any of the driver's symbols. The
first oops was in strlen;

0xc013653c is in __print_symbol (include/asm/string.h:184).
179 #define __HAVE_ARCH_STRLEN
180 static inline size_t strlen(const char * s)
181 {
182 int d0;
183 register int __res;
184 __asm__ __volatile__(
185 "repne\n\t"
186 "scasb\n\t"
187 "notl %0\n\t"
188 "decl %0"

0xc0136537 <__print_symbol+55>: or $0xffffffff,%ecx
0xc013653a <__print_symbol+58>: mov %esi,%edi
0xc013653c <__print_symbol+60>: repnz scas %es:(%edi),%al
0xc013653e <__print_symbol+62>: not %ecx

eax: 00000000 ebx: d0878ab4 ecx: ffffffff edx: d087600c
esi: d086e4d8 edi: d086e4d8 ebp: ccf21c1c esp: ccf21bec
ds: 0068 es: 0068 ss: 0068

nm -n of tiglusb.o is below, and according to a printk, tiglusb_open
starts at 0xd0928000;

U copy_from_user
U copy_to_user
U __down_failed
U __down_failed_interruptible
U __might_sleep
U no_llseek
U printk
U register_chrdev
U schedule_timeout
U sleep_on
U sprintf
U __this_module
U unregister_chrdev
U __up_wakeup
U usb_bulk_msg
U usb_clear_halt
U usb_deregister
U usb_register
U usb_set_configuration
U __wake_up
00000000 T __exitfn
00000000 T __initfn
00000000 D __module_name
00000000 r __module_usb_device_size
00000000 b tiglusb
00000000 t tiglusb_cleanup
00000000 t tiglusb_init
00000000 t tiglusb_open
00000000 d timeout
00000020 d tiglusb_fops
00000080 d tiglusb_ids
000000a8 d __module_usb_device_table
000000c0 d tiglusb_driver
00000120 t tiglusb_release
000001c0 t tiglusb_read
00000320 t tiglusb_write
00000480 t tiglusb_ioctl
00000500 b devfs_handle
000005d0 t tiglusb_probe
00000720 t tiglusb_disconnect
000007d0 t __constant_c_and_count_memset
0000085c t .text.lock.tiglusb


Any information on how to further debug this would be appreciated as i'm
not familiar with the kallsyms innards.

Cheers,
Zwane
--
function.linuxpower.ca


2002-12-02 01:50:24

by Rusty Russell

[permalink] [raw]
Subject: Re: [BUG][2.5.50] kallsyms dies badly with module

In message <Pine.LNX.4.50.0211291105440.14410-100000@montezuma.mastecende.com>
you write:
> Hi Rusty,
> If kallsyms_lookup tries to get a symbol from tiglusb.c loaded as
> a module it oopses.

Yes, see kallsyms fix patch (attached for your convenience). I was
keeping the wrong module section 8(

Hope this helps,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

Name: Kallsyms inside module fix
Author: Rusty Russell
Status: Tested on 2.5.50

D: Two fixes. Firstly, set ALLOC on the right section so we actually
D: keep the symbol names and don't deref a freed section, and secondly
D: get the symbol size (more) correct.

diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.50/kernel/module.c working-2.5.50-ksymoops/kernel/module.c
--- linux-2.5.50/kernel/module.c Mon Nov 25 08:44:19 2002
+++ working-2.5.50-ksymoops/kernel/module.c Thu Nov 28 16:22:56 2002
@@ -892,7 +892,7 @@ static struct module *load_module(void *
}
#ifdef CONFIG_KALLSYMS
/* symbol and string tables for decoding later. */
- if (sechdrs[i].sh_type == SHT_SYMTAB || i == hdr->e_shstrndx)
+ if (sechdrs[i].sh_type == SHT_SYMTAB || i == strindex)
sechdrs[i].sh_flags |= SHF_ALLOC;
#endif
#ifndef CONFIG_MODULE_UNLOAD
@@ -1165,7 +1165,14 @@ static const char *get_ksymbol(struct mo
unsigned long *size,
unsigned long *offset)
{
- unsigned int i, next = 0, best = 0;
+ unsigned int i, best = 0;
+ unsigned long nextval;
+
+ /* At worse, next value is at end of module */
+ if (inside_core(mod, addr))
+ nextval = (unsigned long)mod->module_core+mod->core_size;
+ else
+ nextval = (unsigned long)mod->module_init+mod->init_size;

/* Scan for closest preceeding symbol, and next symbol. (ELF
starts real symbols at 1). */
@@ -1177,22 +1186,14 @@ static const char *get_ksymbol(struct mo
&& mod->symtab[i].st_value > mod->symtab[best].st_value)
best = i;
if (mod->symtab[i].st_value > addr
- && mod->symtab[i].st_value < mod->symtab[next].st_value)
- next = i;
+ && mod->symtab[i].st_value < nextval)
+ nextval = mod->symtab[i].st_value;
}

if (!best)
return NULL;

- if (!next) {
- /* Last symbol? It ends at the end of the module then. */
- if (inside_core(mod, addr))
- *size = mod->module_core+mod->core_size - (void*)addr;
- else
- *size = mod->module_init+mod->init_size - (void*)addr;
- } else
- *size = mod->symtab[next].st_value - addr;
-
+ *size = nextval - mod->symtab[best].st_value;
*offset = addr - mod->symtab[best].st_value;
return mod->strtab + mod->symtab[best].st_name;
}