This session should describe how to use lcrash in analyzing kernel modules. First of all we make use of lcrash commands namelist and symtab.
We have a kernel module my_dummy.o containing a locale variable DUMMY of type dummy_t. The corresponding code fragment is as follows:
typedef struct dummy_s{
int member1;
char *member2;
struct dummy_s *member3;
} dummy_t;
static dummy_t DUMMY={0, "just a demonstration", &DUMMY};
Our intention will be to examine this local data with lcrash. To make it little more tricky we analyze a live dump and the module will be loaded while lcrash is running.
Our module was compiled using gcc option -gstabs to create type information. The symbol table of the module was generated using a command line like nm my_dummy.o > /tmp/my_dummy.map.
The file my_dummy.o was also copied to /tmp.
Start lcrash.
bash# lcrash /boot/System.map-2.2.18 /dev/mem /boot/Kerntypes
map = /boot/System.map-2.2.18, vmdump = /dev/mem, outfile = stdout, kerntypes =
/boot/Kerntypes
Please wait...
Loading system map ........................... Done.
Loading type info (Kerntypes) ... Done.
Loading ksyms from dump ........ Done.
>>
Look what modules are loaded.
>> module
ADDR SIZE USED NAME REFS
===========================================================================
d0103000 17928 1 ibmtr_cs []
d00fe000 6608 2 ds [ibmtr_cs]
d00f3000 23408 2 i82365 []
d00e6000 46848 0 pcmcia_core [ibmtr_cs
ds
i82365]
c02ad0e0 0 1 kernel_module []
===========================================================================
From another shell, load module my_dummy.
bash# insmod my_dummy.o bash#
Verify the former action with lcrash.
>> module
ADDR SIZE USED NAME REFS
===========================================================================
d0000000 1120 0 my_dummy []
d0103000 17928 1 ibmtr_cs []
d00fe000 6608 2 ds [ibmtr_cs]
d00f3000 23408 2 i82365 []
d00e6000 46848 0 pcmcia_core [ibmtr_cs
ds
i82365]
c02ad0e0 0 1 kernel_module []
===========================================================================
Look which symbols of the new module are exported.
>> module -f my_dummy
EXPORTED MODULE SYMBOLS:
===========================================================================
Module: my_dummy
Number of exported symbols: 6
ADDR NAME [MODULE]
d0000000 __insmod_my_dummy_O/home/aherrman/CPP/crash_ex/my_dummy.o_
M3B1CDF3B_V131602 [my_dummy]
d0000060 dummy_init [my_dummy]
d0000060 __insmod_my_dummy_S.text_L447 [my_dummy]
d000021f __insmod_my_dummy_S.rodata_L29 [my_dummy]
d000041c __insmod_my_dummy_S.bss_L16 [my_dummy]
d0000240 __insmod_my_dummy_S.data_L260 [my_dummy]
===========================================================================
Load type information of the module.
>> namelist -a /tmp/my_dummy.o
.The current namelist is /tmp/my_dummy.o (1)
>> namelist
INDEX NAMELIST
=================================================
0 /boot/Kerntypes
1 /tmp/my_dummy.o
=================================================
The current namelist is /tmp/my_dummy.o (1)
Load symbol table of the module.
>> symtab -a /tmp/my_dummy.map my_dummy
Adding symbol table.
filename: /tmp/my_dummy.map
text_offset: 0
data_offset: 0
rodata_offset: 0
bss_offset: 0
module size: 1120
..Done.
Something went wrong, offsets of text and data sections of the module should not be zero. This is caused by the fact, that we added our module after lcrash was started. We have to remove the loaded symbol table and we have to recreate the table __ksymtab__.
Remove our new symbol table and __ksymtab__.
>> symtab -l Loaded symbol tables: =========================================================================== #SYMS: 7803 /boot/System.map-2.2.18 TEXT: 0 DATA: 0 RODATA: 0 BSS: 0 #SYMS: 1163 __ksymtab__ TEXT: 0 DATA: 0 RODATA: 0 BSS: 0 #SYMS: 14 /tmp/my_dummy.map [my_dummy] TEXT: 0 DATA: 0 RODATA: 0 BSS: 0 =========================================================================== >> symtab -r /tmp/my_dummy.map Removing symbol table. Done. >> symtab -r __ksymtab__ Removing symbol table. Done.
Recreate symbol table __ksymtab__.
>> symtab -a __ksymtab__
Adding symbol table.
Loading ksyms from dump ........
Done.
Load our new symbol table again.
>> symtab -a /tmp/my_dummy.map my_dummy
Adding symbol table.
filename: /tmp/my_dummy.map
text_offset: d0000060
data_offset: d0000240
rodata_offset: d000021f
bss_offset: d000041c
module size: 1120
..Done.
>> symtab -l
Loaded symbol tables:
===========================================================================
#SYMS: 7803 /boot/System.map-2.2.18
TEXT: 0 DATA: 0 RODATA: 0 BSS: 0
#SYMS: 1169 __ksymtab__
TEXT: 0 DATA: 0 RODATA: 0 BSS: 0
#SYMS: 14 /tmp/my_dummy.map [my_dummy]
TEXT: d0000060 DATA: d0000240 RODATA: d000021f BSS: d000041c
===========================================================================
Look which symbols are available in module my_dummy.
>> symtab -l -f /tmp/my_dummy.map
===========================================================================
#SYMS: 14 /tmp/my_dummy.map [my_dummy]
TEXT: d0000060 DATA: d0000240 RODATA: d000021f BSS: d000041c
ADDR OFFSET TYPE NAME
------------------------------------------------------------
d0000060 0 GLOBAL_TEXT dummy_init
d00000f0 0 LOCAL_TEXT dummy_xmit
d0000130 0 LOCAL_TEXT dummy_get_stats
d0000140 0 LOCAL_TEXT dummy_open
d0000160 0 LOCAL_TEXT dummy_close
d0000180 0 LOCAL_TEXT set_multicast_list
d0000190 0 LOCAL_TEXT dummy_probe
d00001b0 0 GLOBAL_TEXT init_module
d00001f0 0 GLOBAL_TEXT cleanup_module
d000021f 0 LOCAL_TEXT Letext
d0000240 0 LOCAL_DATA DUMMY
d0000260 0 LOCAL_DATA dev_dummy
d000041c 0 LOCAL_DATA dummy_name
d00004c0 0 ABS /tmp/my_dummy.map_END
------------------------------------------------------------
===========================================================================
Try to examine the local variable DUMMY of our module.
>> whatis DUMMY
ADDR OFFSET TYPE NAME
============================================================
d0000240 0 LOCAL_DATA DUMMY
>> whatis dummy_t
struct dummy_s
struct dummy_s {
int member1;
char *member2;
struct dummy_s *member3;
};
>> print *(dummy_t*) d0000240
struct dummy_s {
member1 = 0
member2 = 0xd000021f
member3 = 0xd0000240
}
>> whatis dummy_s.member2
char *
>> print (char*) 0xd000021f
0xd000021f "just a demonstration"
Furthermore an additional symbol table of a kernel module provides you function names when setting up stack back-traces with trace or strace and when using disassembling routine dis.