14 Breakpoint 3, sys_init_module (umod=0x30029000, len=0x2473e,

15     uargs=0x10016338 '') at kernel/module.c:1907

16 1907                    ret = mod->init();

17 (gdb) lsmod

18 Address Module

19 0xD102F9A0 loop

20 (gdb) set $m=(struct module *)0xD102F9A0.

21 (gdb) p $m->module_core

22 $1 = (void *) 0xd102c000

23 (gdb) add-symbol-file ./drivers/block/loop.ko 0xd102c000

24 add symbol table from file './drivers/block/loop.ko' at

25         .text_addr = 0xd102c000

26 (y or n) y

27 Reading symbols from /home/chris/sandbox/linux-2.6.13-amcc/drivers/block /loop.ko...done.

Starting with line 2, we use the gdb user-defined macro connect created earlier in Listing 14-10 to connect to the target board and set our initial breakpoints. We then add the breakpoint in module.c, as shown in line 7, and we issue the continue command (c). Now the kernel completes the boot process and we establish a telnet session into the target and load the loop.ko module (not shown). When the loopback module is loaded, we immediately hit breakpoint #3. gdb then displays the information shown in lines 14 through 16.

At this point, we need to discover the address where the Linux kernel linked our module's .text section. Linux stores this address in the module information structure struct module in the module_core element. Using the lsmod macro we defined in Listing 14-16, we obtain the address of the struct module associated with our loop.ko module. This is shown in lines 17 through 19. Now we use this structure address to obtain the module's .text address from the module_core structure member. We pass this address to the gdb add-symbol-file command, and gdb uses this address to adjust its internal symbol table to match the actual addresses where the module was linked into the kernel. From there, we can proceed in the usual manner to set breakpoints in the module, step through code, examine data, and so on.

We conclude this section with a demonstration of placing a breakpoint in the loopback module's initialization function so that we can step through the module's initialization code. The complication here is that the kernel loads the module's initialization code into a separately allocated portion of memory so that it can be freed after use. Recall from Chapter 5, 'Kernel Initialization,' our discussion of the __init macro. This macro expands into a compiler attribute that directs the linker to place the marked portion of code into a specially named ELF section. In essence, any function defined with this attribute is placed in a separate ELF section named .init.text. Its use is similar to the following:

static int __init loop_init(void){...}

This invocation would place the compiled loop_init() function into the .init.text section of the loop.ko object module. When the module is loaded, the kernel allocates a chunk of memory for the main body of the module, which is pointed to by the struct module member named module_core. It then allocates a separate chunk of memory to hold the .init.text section. After the initialization function is called, the kernel frees the memory that contained the initialization function. Because the object module is split like this, we need to inform gdb of this addressing scheme to be able to use symbolic data for debugging the initialization function.[97] Listing 14-19 demonstrates these steps.

Listing 14-19. Debugging Module init Code

$ ppc_4xx-gdb -slient vmlinux

(gdb) target remote /dev/ttyS0

Remote debugging using /dev/ttyS0

breakinst () at arch/ppc/kernel/ppc-stub.c:825

825     }

<< Place a breakpoint before calling module init >>

(gdb) b module.c:1907

Breakpoint 1 at 0xc0036418: file kernel/module.c, line 1907.

(gdb) c

Continuing.

Breakpoint 1, sys_init_module (umod=0xd102ef40, len=0x23cb3, uargs=0x10016338 '')

at kernel/module.c:1907

1907                    ret = mod->init();

<< Discover init addressing from struct module >>

(gdb) lsmod

Address         Module

0xD102EF40      loop

(gdb) set $m=(struct module *)0xD102EF40

(gdb) p $m->module_core

$1 = (void *) 0xd102b000

(gdb) p $m->module_init

$2 = (void *) 0xd1031000

<< Now load a symbol file using the core and init addrs >>

(gdb) add-symbol-file ./drivers/block/loop.ko 0xd102b000 -s .init.text 0xd1031000

add symbol table from file './drivers/block/loop.ko' at

        .text_addr = 0xd102b000

        .init.text_addr = 0xd1031000

(y or n) y

Reading symbols from /home/chris/sandbox/linux-2.6.13- amcc/drivers/block/loop.ko...done.

(gdb) b loop_init

Breakpoint 3 at 0xd1031000: file drivers/block/loop.c, line 1244.

(gdb) c

Continuing.

<< Breakpoint hit, proceed to debug module init function >>

Breakpoint 3, 0xd1031000 in loop_init () file drivers/block/loop.c, line 1244

1244        if (max_loop < 1 || max_loop > 256)

(gdb) 

14.3.6. printk Debugging

Debugging kernel and device driver code using printk is a popular technique, mostly because printk has evolved into a very robust method. You can call printk from almost any context, including from interrupt handlers. printk is the kernel's version of the familiar printf() C library function. printk is defined in .../kernel/printk.c.

It is important to understand the limitations of using printk for debugging. First, printk requires a console device. Moreover, although the console device is configured as early as possible during kernel initialization, there are many calls to printk before the console device has been initialized. We present a method to cope with this

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату