| |
A special procedure is needed to debug init_module function
from a module. Module debugging information is available only when gdb
is notified of the module (for kgdb 1.9 onwards) or when loadmodule.sh
script finishes (for kgdb 1.8 and earlier). init_module
function from a module is already executed by that time. Hence
init_module cannot be debugged with this procedure.
To debug init_module, place a breakpoint in the kernel
just before the point where it calls init_module function.
For kgdb versions 1.9 and later
Load the module with modprobe or insmod and wait for the breakpoint to
occur. When the breakpoint occurs gdb has
already detected that the module was loaded. You can now place a
breakpoint anywhere in the module.
For kgdb versions 1.8 and earlier
Once the kernel breaks into the debugger, wait for loadmodule.sh
script to exit. At this point of time init_module isn't called
and all the debugging information is available. Now load the module
object file loading script generated by loadmodule.sh script
to load the module object file into gdb.
Once the module object file is loaded, a breakpoint can be placed
anywhere in the module such as a statement in init_module
function.
A snippet of the kernel/module.c file from 2.4.10 kernel is
shown below with the place where a breakpoint can be placed.
/* Free our temporary memory. */
put_mod_name(n_name);
put_mod_name(name);
/* Initialize the module. */
atomic_set(&mod->uc.useWorking of
loadmodule.sh script
This information applies only to kgdb versions 1.8 and earlier.
Object file sections
Consider a module object file trfs. The sections
contained in the file can be listed using objdump command.
$ objdump -h trfs
trfs: file format elf32-i386
Sections:
Idx Name
Size
VMA
LMA File off Algn
0 .text
0000162c 00000000 00000000 00000040 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .text.lock 0000010a 00000000
00000000 0000166c 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
2 .rodata 000002a4
00000000 00000000 00001780 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 __ksymtab 00000020
00000000 00000000 00001a24 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
4 .kstrtab 0000006f
00000000 00000000 00001a60 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .modinfo 00000111
00000000 00000000 00001acf 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .data
00000178 00000000 00000000 00001be0 2**5
CONTENTS, ALLOC, LOAD, RELOC, DATA
7 .bss
00000010 00000000 00000000 00001d58 2**2
ALLOC
8 .stab
0003b8b0 00000000 00000000 00001d58 2**2
CONTENTS, RELOC, READONLY, DEBUGGING
9 .stabstr 000e32bd
00000000 00000000 0003d608 2**0
CONTENTS, READONLY, DEBUGGING
10 .comment 000001ab
00000000 00000000 001208c5 2**0
CONTENTS, READONLY
11 .note
0000008c 00000010 00000010 00120a70 2**0
CONTENTS, READONLY
.text is the code section. Sections .data and .bss
contain initialized and uninitialized data respectively. Debugging
information is contained in sections .stab and .stabstr.
VMA is the virtual address of the section. Since the file is not
relocated yet, VMAs of all sections are zero.
Kernel object file, vmlinux, is relocated. Hence VMAs
of sections in vmlinux are the actual addresses where they
appear in virtual address space of a process.
[amit@askii-pc linux-2.4.6-kgdb]$ objdump -h vmlinux
vmlinux: file format elf32-i386
Sections:
Idx Name
Size
VMA
LMA File off Algn
0 .text
0014ed2b c0100000 c0100000 00001000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .text.lock 00009579 c024ed30
c024ed30 0014fd30 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .rodata 00048061
c02582c0 c02582c0 001592c0 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .kstrtab 0000a200
c02a0340 c02a0340 001a1340 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 __ex_table 00001848 c02aa540
c02aa540 001ab540 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 __ksymtab 000023f0
c02abd88 c02abd88 001acd88 2**2
CONTENTS, ALLOC, LOAD
, READONLY, DATA
6 .data
0001a200 c02ae180 c02ae180 001af180 2**5
CONTENTS, ALLOC, LOAD, DATA
7 .data.init_task 00002000 c02ca000
c02ca000 001ca000 2**5
CONTENTS, ALLOC, LOAD, DATA
8 .text.init 00018718 c02cc000
c02cc000 001cc000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
9 .data.init 0001ed18 c02e4720
c02e4720 001e4720 2**5
CONTENTS, ALLOC, LOAD, DATA
10 .setup.init 00000170 c0303440
c0303440 00203440 2**2
CONTENTS, ALLOC, LOAD, DATA
11 .initcall.init 000000bc c03035b0
c03035b0 002035b0 2**2
CONTENTS, ALLOC, LOAD, DATA
12 .data.page_aligned 00000800 c0304000
c0304000 00204000 2**5
CONTENTS, ALLOC, LOAD, DATA
13 .data.cacheline_aligned 00004520 c0304800
c0304800 00204800 2**5
CONTENTS, ALLOC, LOAD, DATA
14 .bss
00041f54 c0308d20 c0308d20 00208d20 2**5
ALLOC
15 .stab
00615708 00000000 00000000 00208d20 2**2
CONTENTS, READONLY, DEBUGGING
16 .stabstr 001b4ec1
00000000 00000000 0081e428 2**0
CONTENTS, READONLY, DEBUGGING
17 .comment 00005bfa
00000000 00000000 009d32e9 2**0
CONTENTS, READONLY
18 .note
00001e28 c034ac74 c034ac74 009d8ee3 2**0
CONTENTS, READONLY
As you can see from above output, the code section, .text,
begins at address 0xc0100000.
Loading of the module
When the module is loaded into kernel, it has to be first
relocated. Relocation of a module means changing all relative
references in it to absolute addresses. After a module is relocated,
the insmod command prints module map file if requested on
command line. A module map file contains addresses of sections and all
symbols in the module. Part of a module map file for module trfs is
given below.
[amit@askii-pc linux-2.4.6-kgdb]$ head -n 20 /tmp/trfs.map
Sections:
Size Address Align
.this
00000060 c1808000 2**2
.text
0000162c c1808060 2**4
.text.lock 0000010a
c180968c 2**0
.rodata
000002a4 c18097a0 2**5
__ksymtab 00000048
c1809a44 2**2
.kstrtab 00000109
c1809aa0 2**5
.data
00000178 c1809bc0 2**5
.bss
00000010 c1809d38 2**2
__archdata 00000000
c1809d50 2**4
Symbols:
00000000 a translators.c
00000000 a linkinfo.c
00000000 a view.c
00000000 a super.c
00000000 a dirinfo.c
00000000 a link.c
00000000 a dir.c
c1808000 d __this_module
The code section, .text, is loaded at address 0xc1808060.
Generation of gdb script
loadmodule.sh script generates a gdb script for loading the
object file into gdb. The script tells gdb to load the module object
file and gives it addresses where different sections are loaded. The
gdb script for above module map is show below.
[amit@askii-pc linux-2.4.6-kgdb]$ cat
/mnt/work/gdbscripts/loadtrfs
add-symbol-file /mnt/work/build/old-pc/trfs/modules/trfs/trfs
0xc1808060 -s .text.lock 0xc180968c -s .rodata 0xc18097a0 -s __ksymtab
0xc1809a44 -s .data 0xc1809bc0
[amit@askii-pc linux-2.4.6-kgdb]$
The loadmodule.sh script finds addresses of sections
from the module map file.
Loading object files into gdb
When gdb loads a module object file with given addresses, it can
calculate address of a symbol in it by adding their relative addresses
to the absolute address of the section that contains it. Consider a
function tr_initviewtree in a module trfs. The
section that contains it and relative address of the function
in that section can be found out by using objdump.
[amit@askii-pc trfs]$ objdump -t trfs | grep tr_initviewtree
000014f0 g F .text 00000016
tr_initviewtree
[amit@askii-pc trfs]$
.text is the section that contains the function.
character F indicates that it's a function. 0x14f0 is
the relative address of the function in section .text.
0x16 is the length of the code of the function. The address
where the function is loaded is 0xc1808060 + 0x14f0 = 0xc1809550.
The address is also given in the module map file.
[amit@askii-pc trfs]$ grep tr_initviewtree /tmp/trfs.map
c1809550 T tr_initviewtree
[amit@askii-pc trfs]$
gdb calculates addresses by adding relative addresses to
absolute addresses of sections as shown above.
[amit@askii-pc gdbscripts]$ gdbmod
GNU gdb 20000204
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License,
and you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty"
for details.
This GDB was configured as "i686-pc-linux-gnu".
(gdb) source loadtrfs
add symbol table from file
"/mnt/work/build/old-pc/trfs/modules/trfs/trfs" at
.text_addr = 0xc1808060
.text.lock_addr =
0xc180968c
.rodata_addr = 0xc18097a0
__ksymtab_addr =
0xc1809a44
.data_addr = 0xc1809bc0
(gdb) p tr_initviewtree
$1 = {void ()} 0xc1809550 <tr_initviewtree>
(gdb) [amit@askii-pc gdbscripts]$
|
|