[ Next Article | Previous Article | Book Contents | Library Home | Legal | Search ]
Kernel Extensions and Device Support Programming Concepts

Using the KDB Kernel Debug Program

This section contains the following sections:

The example files provide a demonstration kernel extension and a program to load, execute, and unload the extension. These programs may be compiled, linked, and executed as indicated in the following material. Note, to use these programs to follow the examples you need a machine with a C compiler, a console, and running with a KDB kernel enabled for debugging. To use the KDB Kernel Debugger you will need exclusive use of the machine.

Examples using the KDB Kernel Debugger with the demonstration programs are included in each of the following sections. The examples are shown in tables which contain two columns. The first column of the table contains an indication of the system prompt and the user input to perform each step. The second column of each table explains the function of the command and includes example output, where applicable. In the examples, since only the console is used, the demo program is switched between the background and the foreground as needed.


Example Files

The files listed below are used in examples throughout this section.

To build the demonstration programs:

This script produces:

The following sections describe compilation and link options used in the comp_link script in more detail and also cover using the map and list files.


Generating Maps and Listings

Assembler listing and map files are useful tools for debugging using the KDB Kernel Debugger. In order to create the assembler list file during compilation, use the -qlist option. Also use the -qsource option to get the C source listing in the same file:

cc -c -DEBUG -D_KERNEL -DIBMR2 demokext.c -qsource -qlist

In order to obtain a map file, use the -bmap:FileName option for the link editor. The following example creates a map file of demokext.map:

ld -o demokext demokext.o -edemokext -bimport:/lib/syscalls.exp \
-bimport:/lib/kernex.exp -lcsys -bexport:demokext.exp -bmap:demokext.map

Compiler Listing

The assembler and source listing is used to correlate any C source line with the corresponding assembler lines. The following is a portion of the list file, created by the cc command used earlier, for the demonstration kernel extension. This information is included in the compilation listing because of the -qsource option for the cc command. The left column is the line number in the source code:

    .
    .
   63 |                 case 1:  /* Increment */
   64 |                         sprintf(buf, "Before increment: j=%d demokext_j=%d\n",
   65 |                                 j, demokext_j);
   66 |                         write_log(fpp, buf, &bytes_written);
   67 |                         demokext_j++;
   68 |                         j++;
   69 |                         sprintf(buf, "After increment: j=%d demokext_j=%d\n",
   70 |                                 j, demokext_j);
   71 |                         write_log(fpp, buf, &bytes_written);
   72 |                         break;
    .
    .

The following is the assembler listing for the corresponding C code shown above. This information was included in the compilation listing because of the -qlist option used on the cc command earlier.

    .
    .
   64| 0000B0 l        80BF0030   2     L4A      gr5=j(gr31,48)
   64| 0000B4 l        83C20008   1     L4A      gr30=.demokext_j(gr2,0)
   64| 0000B8 l        80DE0000   2     L4A      gr6=demokext_j(gr30,0)
   64| 0000BC ai       30610048   1     AI       gr3=gr1,72
   64| 0000C0 ai       309F005C   1     AI       gr4=gr31,92
   64| 0000C4 bl       4BFFFF3D   0     CALL     gr3=sprintf,4,buf",gr3,""5",gr4-gr6,sprintf",gr1,cr[01567]",gr0",gr4"-gr12",fp0"-fp13"
   64| 0000C8 cror     4DEF7B82   1
   66| 0000CC l        80610040   1     L4A      gr3=fpp(gr1,64)
   66| 0000D0 ai       30810048   1     AI       gr4=gr1,72
   66| 0000D4 ai       30A100AC   1     AI       gr5=gr1,172
   66| 0000D8 bl       4800018D   0     CALL     gr3=write_log,3,gr3,buf",gr4,bytes_written",gr5,write_log",gr1,cr[01567]",gr0",gr4"-gr12",fp0"-fp13"
   66| 0000DC cal      387E0000   2     LR       gr3=gr30
   67| 0000E0 l        80830000   1     L4A      gr4=demokext_j(gr3,0)
   67| 0000E4 ai       30840001   2     AI       gr4=gr4,1
   67| 0000E8 st       90830000   1     ST4A     demokext_j(gr3,0)=gr4
   68| 0000EC l        809F0030   1     L4A      gr4=j(gr31,48)
   68| 0000F0 ai       30A40001   2     AI       gr5=gr4,1
   68| 0000F4 st       90BF0030   1     ST4A     j(gr31,48)=gr5
   69| 0000F8 l        80C30000   1     L4A      gr6=demokext_j(gr3,0)
   69| 0000FC ai       30610048   1     AI       gr3=gr1,72
   69| 000100 ai       309F0084   1     AI       gr4=gr31,132
   69| 000104 bl       4BFFFEFD   0     CALL     gr3=sprintf,4,buf",gr3,""6",gr4-gr6,sprintf",gr1,cr[01567]",gr0",gr4"-gr12",fp0"-fp13"
   69| 000108 cror     4DEF7B82   1
   71| 00010C l        80610040   1     L4A      gr3=fpp(gr1,64)
   71| 000110 ai       30810048   1     AI       gr4=gr1,72
   71| 000114 ai       30A100AC   1     AI       gr5=gr1,172
   71| 000118 bl       4800014D   0     CALL     gr3=write_log,3,gr3,buf",gr4,bytes_written",gr5,write_log",gr1,cr[01567]",gr0",gr4"-gr12",fp0"-fp13"
   72| 00011C b        48000098   1     B        CL.8,-1
    .
    .

With both the assembler listing and the C source listing, the assembly instructions associated with each C statement may be found. As an example, consider the C source line at line 67 of the demonstration kernel extension:

   67 |                         demokext_j++;

The corresponding assembler instructions are:

   67| 0000E0 l        80830000   1     L4A      gr4=demokext_j(gr3,0)
   67| 0000E4 ai       30840001   2     AI       gr4=gr4,1
   67| 0000E8 st       90830000   1     ST4A     demokext_j(gr3,0)=gr4

The offsets of these instructions within the demonstration kernel extension (demokext) are 0000E0, 0000E4, and 0000E8.

Map File

The binder map file is a symbol map in address order format. Each symbol listed in the map file has a storage class (CL) and a type (TY) associated with it.

Storage classes correspond to the XMC_XX variables defined in the syms.h file. Each storage class belongs to one of the following section types:

.text Contains read-only data (instructions). Addresses listed in this section use the beginning of the .text section as origin. The .text section can contain one of the following storage class (CL) values:
DB Debug Table. Identifies a class of sections that has the same characteristics as read only data.
GL Glue Code. Identifies a section that has the same characteristics as a program code. This type of section has code to interface with a routine in another module. Part of the interface code requirement is to maintain TOC addressability across the call.
PR Program Code. Identifies the sections that provide executable instructions for the module.
R0 Read Only Data. Identifies the sections that contain constants that are not modified during execution.
TB Reserved.
TI Reserved.
XO Extended Op. Identifies a section of code that is to be treated as a pseudo-machine instruction.
.data Contains read-write initialized data. Addresses listed in this section use the beginning of the .data section as origin. The .data section can contain one of the following storage class (CL) values:
DS Descriptor. Identifies a function descriptor. This information is used to describe function pointers in languages such as C and Fortran.
RW Read Write Data. Identifies a section that contains data that is known to require change during execution.
SV SVC. Identifies a section of code that is to be treated as a supervisory call.
T0 TOC Anchor. Used only by the predefined TOC symbol. Identifies the special symbol TOC. Used only by the TOC header.
TC TOC Entry. Identifies address data that will reside in the TOC.
TD TOC Data Entry. Identifies data that will reside in the TOC.
UA Unclassified. Identifies data that contains data of an unknown storage class.
.bss Contains read-write uninitialized data. Addresses listed in this section use the beginning of the .data section as origin. The .bss section contain one of the following storage class (CL) values:
BS BSS class. Identifies a section that contains uninitialized data.
UC Unnamed Fortran Common. Identifies a section that contains read write data.

Types correspond to the XTY_XX variables defined in the syms.h file. The type (TY) can be one of the following values:

ER External Reference
LD Label Definition
SD Section Definition
CM BSS Common Definition

The following is the map file for the demonstration kernel extension. This file was created because of the -bmap:demokext.map option of the ld command shown earlier.

    1   ADDRESS MAP FOR demokext
    2   *IE ADDRESS  LENGTH AL CL TY Sym#  NAME                      SOURCE-FIL E(OBJECT) or IMPORT-FILE{SHARED-OBJECT}
    3   --- -------- ------ -- -- -- ----- ------------------------- -------------------------------------------------
    4    I                        ER S1    _system_configuration     /lib/syscalls.exp{/unix}
    5    I                        ER S2    fp_open                   /lib/kernex.exp{/unix}
    6    I                        ER S3    fp_close                  /lib/kernex.exp{/unix}
    7    I                        ER S4    fp_write                  /lib/kernex.exp{/unix}
    8    I                        ER S5    sprintf                   /lib/kernex.exp{/unix}
    9       00000000 000360  2 PR SD S6    <>                        demokext.c(demokext.o)
   10       00000000           PR LD S7    .demokext
   11       00000210           PR LD S8    .close_log
   12       00000264           PR LD S9    .write_log
   13       000002F4           PR LD S10   .open_log
   14       00000360 000108  5 PR SD S11   .strcpy                   strcpy.s(/usr/lib/libcsys.a[strcpy.o])
   15       00000468 000028  2 GL SD S12   <.sprintf>                glink.s(/usr/lib/glink.o)
   16       00000468           GL LD S13   .sprintf
   17       00000490 000028  2 GL SD S14   <.fp_close>               glink.s(/usr/lib/glink.o)
   18       00000490           GL LD S15   .fp_close
   19       000004C0 0000F8  5 PR SD S16   .strlen                   strlen.s(/usr/lib/libcsys.a[strlen.o])
   20       000005B8 000028  2 GL SD S17   <.fp_write>               glink.s(/usr/lib/glink.o)
   21       000005B8           GL LD S18   .fp_write
   22       000005E0 000028  2 GL SD S19   <.fp_open>                glink.s(/usr/lib/glink.o)
   23       000005E0           GL LD S20   .fp_open
   24       00000000 0000F9  3 RW SD S21   <_$STATIC>                demokext.c(demokext.o)
   25     E 000000FC 000004  2 RW SD S22   demokext_j                demokext.c(demokext.o)
   26   *   00000100 00000C  2 DS SD S23   demokext                  demokext.c(demokext.o)
   27       0000010C 000000  2 T0 SD S24   <TOC>
   28       0000010C 000004  2 TC SD S25   <_$STATIC>
   29       00000110 000004  2 TC SD S26   <_system_configuration>
   30       00000114 000004  2 TC SD S27   <demokext_j>
   31       00000118 000004  2 TC SD S28   <sprintf>
   32       0000011C 000004  2 TC SD S29   <fp_close>
   33       00000120 000004  2 TC SD S30   <fp_write>
   34       00000124 000004  2 TC SD S31   <fp_open>

In the above map file, the .data section starts at the statement for line 24:

   24       00000000 0000F9  3 RW SD S21   <_$STATIC>                demokext.c(demokext.o)

The TOC (Table Of Contents) starts at the statement for line 27:

   27       0000010C 000000  2 T0 SD S24   <TOC>

Setting Breakpoints

Setting a breakpoint is essential for debugging kernel extensions. To set a breakpoint, use the following sequence of steps:

  1. Locate the assembler instruction corresponding to the C statement.
  2. Get the offset of the assembler instruction from the listing.
  3. Locate the address where the kernel extension is loaded.
  4. Add the address of the assembler instruction to the address where kernel extension is loaded.
  5. Set the breakpoint with the KDB b (break) subcommand.

The process of locating the assembler instruction and getting its offset is explained in the previous section. To continue with the demokext example, we will set a break at the C source line 67, which increments the variable demokext_j. The list file indicates that this line starts at an offset of 0xE0. So the next step is to determine the address where the kernel extension is loaded.

Determine the Location of your Kernel Extension

To determine the address at which a kernel extension has been loaded, use the following procedure. First, find the load point (the entry point) of the executable kernel extension. This is a label supplied with the -e option for the ld command. In the example this is the demokext routine.

Use one of the following methods to locate the address of this load point and set a breakpoint at the appropriate offset from this point.

The following provides examples of each of the above methods using the demo and demokext routines compiled earlier. Note, the following must be run as the root user. For this example, assume that a break is to be set at line 67, which has an offset from the beginning of demokext of 0xE0.

Prompt and Console Input Function and Example Output
Load the demokext kernel extension
$ ./demo Run the demo program, this loads the demokext extension. Note, the value printed for kmid, this is used later in this example.
$ <CTRL-Z> Stop the demo program.
$ bg Put the demo program in the background.
$ <CTRL-\> Activate KDB, use the appropriate key sequence for your configuration. You should have a KDB prompt on completion of this step.
Set a breakpoint using Method 1
KDB(0)> b demokext+E0 Set a breakpoint using the symbol demokext. This is the easiest and most common way of setting a breakpoint within KDB. KDB responds with an indication of the address where the break is set.
KDB(0)> b List all breakpoints. KDB displays a list of all breakpoints currently active.
KDB(0)> ca This clears all breakpoints
KDB(0)> b List all breakpoints. KDB indicates there are no active breakpoints.
Set a breakpoint using Method 2
KDB(0)> lke List loaded extensions. The output from this subcommand will be similar to:
     ADDRESS     FILE FILESIZE    FLAGS MODULE NAME

  1 04E17F80 01303F00 000007F0 00000272  ./demokext
  2 04E17E80 0503A000 00000E88 00000248  /unix
  3 04E17C00 04FA3000 00071B34 00000272  /usr/lib/drivers/nfs.ext
  4 04E17A80 05021000 00000E88 00000248  /unix
  5 04E17800 01303B98 00000348 00000272  /usr/lib/drivers/nfs_kdes.ext
  6 04E17B80 04F96000 00000E34 00000248  /unix
  7 04E17500 01301A10 0000217C 00000272  /etc/drivers/blockset64
                     .
                     .

Enter <CTRL-C> to exit the KDB Kernel Debugger paging function, if more than one page of data is present. You may exit the paging function at any time by using <CTRL-C>. Pressing <ENTER> displays the next page of data; <SPACE> displays the next line of data. Additionally, the number of lines per page may be changed using the set screen_size xx subcommand; where xx is the number of lines to be be considered a page.

KDB(0)> lke 1 List detailed information about the extension of interest. The parameter to the lke subcommand is the slot number for the ./demokext entry from the previous step. The output from this command will be similar to:
     ADDRESS     FILE FILESIZE    FLAGS MODULE NAME

  1 04E17F80 01303F00 000007F0 00000272  ./demokext
le_flags....... TEXT KERNELEX DATAINTEXT DATA DATAEXISTS 
le_next........ 04E17E80 le_fp.......... 00000000 
le_filename.... 04E17FD8 le_file........ 01303F00 
le_filesize.... 000007F0 le_data........ 013045C8 
le_tid......... 00000000 le_datasize.... 00000128 
le_usecount.... 00000003 le_loadcount... 00000001 
le_ndepend..... 00000001 le_maxdepend... 00000001 
le_ule......... 0502E000 le_deferred.... 00000000 
le_exports..... 0502E000 le_de.......... 6C696263 
le_searchlist.. B0000420 le_dlusecount.. 00000000 
le_dlindex..... 00002F6C le_lex......... 00000000 
le_fh.......... 00000000 le_depend.... @ 04E17FD4 
TOC@........... 013046D4
                             <PROCESS TRACE BACKS>
                   .demokext 01304040                   .close_log 013041FC 
                  .write_log 01304240                    .open_log 013042B4 
                     .strcpy 01304320               .sprintf.glink 01304428 
             .fp_close.glink 01304450                      .strlen 01304480 
             .fp_write.glink 01304578               .fp_open.glink 013045A0 

From the PROCESS TRACE BACKS we see that the first instruction of demokext is at 01304040. So the break for line 67 would be at this address plus E0.

KDB(0)> b 01304040+e0 Set the break at the desired location. KDB responds with an indication of the address that the breakpoint is at.
KDB(0)> ca Clear all breakpoints.
Set a breakpoint using Method 3
KDB(0)> nm demokext This translates a symbol to an effective address. The output from this subcommand will be similar to:
Symbol Address : 01304040
   TOC Address : 013046D4

The value of the symbol demokext is the address of the first instruction of the demokext routine. So this value can be used to set a breakpoint, just as in the previous example.

KDB(0)> b 01304040+e0 Set the break at the desired location. KDB responds with an indication of the address that the breakpoint is at.
KDB(0)> dw 01304040+e0 Display the word at the breakpoint. KDB will respond with something similar to:
01304120: 80830000 30840001 90830000 809F0030  ....0..........0

This can then be checked against the assembly code in the listing to verify that the break is set at the correct location.

KDB(0)> ca Clear all breakpoints.
Set a breakpoint using Method 4
KDB(0)> dw 1304748 Display the memory at the address returned as the kmid from the sysconfig routine at the beginning of this example. KDB responds with something similar to:
demokext+000000: 01304040 01304754 00000000 01304648  .0@@.0GT.....0FH
The first word of data displayed is the address of the first instruction of the demokext routine. Note, the data displayed is at the location demokext+000000. This corresponds to line 26 of the map presented earlier. However, the most important thing to note is that demokext+000000 and .demokext+000000 are not the same address. The location .demokext+000000 corresponds to line 10 of the map and is the address of the first instruction for the demokext routine.
KDB(0)> b 01304040+e0 Set the break at the location indicated from the previous command plus the offset to get to line 67. KDB responds with an indication of the address that the breakpoint is at.
ca Clear all breakpoints.
Set a breakpoint using Method 5
KDB(0)> devsw 1 Display the device switch table for the first entry. Note, the demonstration program that is being used is not a device driver; so this example just uses the addresses of the first device driver in the device switch table and is not related in any way to the demonstration program. The KDB devsw command displays data similar to:
Slot address 50006040
MAJ#001  OPEN            CLOSE           READ            WRITE
         .syopen         .nulldev        .syread         .sywrite        
         IOCTL           STRATEGY        TTY             SELECT
         .syioctl        .nodev          00000000        .syselect       
         CONFIG          PRINT           DUMP            MPX
         .nodev          .nodev          .nodev          .nodev          
         REVOKE          DSDPTR          SELPTR          OPTS
         .nodev          00000000        00000000        00000012        
KDB(0)> b .syopen+20 Set a breakpoint at an offset of 0x20 from the beginning of the open routine for the first device driver in the device switch table. Note, KDB responds with an indication of where the break was set.
KDB(0)> ca Clear all breakpoints.
KDB(0)> ns Turn off symbolic name translation.
KDB(0)> devsw 1 Display the device switch table for the first device driver again. This time, with symbolic name translation turned off addresses instead of names will be displayed. The output from this subcommand is similar to:
Slot address 50006040
MAJ#001  OPEN            CLOSE           READ            WRITE
         00208858        00059750        002086D4        0020854C        
         IOCTL           STRATEGY        TTY             SELECT
         00208290        00059774        00000000        00208224        
         CONFIG          PRINT           DUMP            MPX
KDB(0)> b 00208858+20 Set a break at an offset of 0x20 from the beginning of the open routine for the first device driver in the device switch table. This will set the same break that was set at the beginning of Set a breakpoint using Method 5. KDB responds with an indication of where the break was set.
KDB(0)> ns Toggle symbolic name translation on.
KDB(0)> ca Clear all breaks.
KDB(0)> g Exit the KDB Kernel Debugger and let the system resume normal execution.
Unload the demokext kernel extension
$ fg Bring the demo program to the foreground. Note, it will be waiting for user input of 0 to unload and exit, 1 to increment counters, or 2 decrement counters (the prompt will not be redisplayed, since it was shown prior to stopping the program and placing it in the background).
./demo 0 Enter a value of 0 to indicate that the kernel extension is to be unloaded and that the demo program is to terminate.


Viewing and Modifying Global Data

Global data may be accessed by several methods. In this section three methods are presented to access global data. The demo and demokext programs continue to be used in the illustrations in this section. In particular, the variable demokext_j (which is exported) is used in the examples.

The first method presented demonstrates the simpliest method of access for global data. The second method presented demonstrates accessing global data using the TOC and the map file. This method requires that the system is stopped in the KDB Kernel Debugger within a procedure of the kernel extension to be debugged. Finally, the third method demonstrates a way to access global data using the map file, but without using the TOC.

Note that in Method 2, using the TOC, the address of the address of the data for demokext_j was calculated; while in Method 3 simply the address of the data for demokext_j was found. Also note that Method 1 is the primary method of access of global data when using the KDB Kernel Debugger. The other methods are mainly described to show alternatives and to allow the use of additional KDB subcommands in the following examples.

Prompt and Console Input Function and Example Output
Load the demokext kernel extension
$ ./demo Run the demo program, this loads the demokext extension.
$ <CTRL-Z> Stop the demo program.
$ bg Put the demo program in the background.
$ <CTRL-\> Activate KDB, use the appropriate key sequence for your configuration. You should have a KDB prompt on completion of this step.
Viewing/Modifying Global Data using Method 1
KDB(0)> dw demokext_j Display a word at the address of the demokext_j variable. Since the kernel extension was just loaded this variable should have a value of 99 and the KDB Kernel Debugger should display that value. The data displayed should be similar to the following:
demokext_j+000000: 00000063 01304040 01304754 00000000  ...c.0@@.0GT....
KDB(0)> ns Turn off symbolic name translation.
KDB(0)> dw demokext_j This will again display the word at the address of the demokext_j variable, except with symbolic name translation turned off. So the data displayed should be similar to:
01304744: 00000063 01304040 01304754 00000000  ...c.0@@.0GT....
KDB(0)> ns Turn symbolic name translation on.
KDB(0)> mw demokext_j Modify the word at the address of the demokext_j variable. The KDB Kernel Debugger displays the current value of the word and waits for user input to change the value. The data displayed should be:
01304744:  00000063  =

A new value may then be entered. After a new value is entered, the next word of memory is displayed for possible modification. To end memory modification a period (.) is entered. So to complete this step, enter a value of 64 (100 decimal) for the first address and then enter a period to end modification.

Viewing/Modifying Global Data using Method 2
KDB(0)> b demokext+e0 Set a break at line 67 of the demokext routine (see the examples in the previous section). Breaking at this location will insure that the KDB Kernel Debugger is invoked while within the demokext routines. Then we can get the value of General Purpose Register 2, to determine the address of the TOC.
KDB(0)> g Exit the KDB Kernel Debugger. This exits the debugger and we can then bring the demo program to the foreground and choose a selection to cause the demokext routine to be called for configuration. Since a break has been set this will cause the KDB Kernel Debugger to be invoked.
$ fg Bring the demo program to the foreground.
./demo 1 Enter a value of 1 to select the option to increment the counters within the demokext kernel extension. This causes a break at line 67 of demokext.
KDB(0)> dr Display the general purpose registers. The data displayed should be similar to the following:
r0  : 0130411C  r1  : 2FF3B210  r2  : 01304754  r3  : 01304744  r4  : 0047B180
r5  : 0047B230  r6  : 000005FB  r7  : 000DD300  r8  : 000005FB  r9  : 000DD300
r10 : 00000000  r11 : 00000000  r12 : 013042F4  r13 : DEADBEEF  r14 : 00000001
r15 : 2FF22D80  r16 : 2FF22D88  r17 : 00000000  r18 : DEADBEEF  r19 : DEADBEEF
r20 : DEADBEEF  r21 : DEADBEEF  r22 : DEADBEEF  r23 : DEADBEEF  r24 : 2FF3B6E0
r25 : 2FF3B400  r26 : 10000574  r27 : 22222484  r28 : E3001E30  r29 : E6001800
r30 : 01304744  r31 : 01304648  
Using the map, the offset to the TOC entry for demokext_j from the start of the TOC was 0x00000008 (see the above text concerning Method 2). Adding this offset to the value displayed for r2 indicates that the TOC entry of interest is at: 0x0130475C. Note, the KDB Kernel Debugger may be used to perform the addition. In this case the subcommand to use would be hcal @r2+8.
KDB(0)> dw 0130475C Display the TOC entry for demokext_j. This entry will contain the address of the data for demokext_j. The data displayed should be similar to:
TOC+000008: 01304744 000BCB34 00242E94 001E0518  .0GD...4.$......

The value for the first word displayed is the address of the data for the demokext_j variable.

KDB(0)> dw 01304744 Display the data for demokext_j. The data displayed should indicate that the value for demokext_j is still 0x0000064, which we set it to earlier. This is because the breakpoint set was in the demokext routine prior to demokext_j being incremented. The data displayed should be similar to:
demokext_j+000000: 00000064 01304040 01304754 00000000  ...d.0@@.0GT....
KDB(0)> ca Clear all breakpoints.
KDB(0)> g Exit the kernel debugger. Be careful here, when we exit, the demo program will still be in the foreground and there will be a prompt for the next option. Also note that the kernel extension is going to run and increment demokext_j; so next time it should have a value of 0x00000065.
Enter choice: <CTRL-Z> Enter <CTRL-Z> to stop the demo program.
$ bg Place the demo program in the background.
Viewing/Modifying Global Data using Method 3
$ <CTRL-\> Activate KDB, use the appropriate key sequence for your configuration. You should have a KDB prompt on completion of this step.
KDB(0)> dw demokext+704 Display the data for the demokext_j variable. The 704 value is calculated from the map (refer to the above text for Method 3). This offset is then added to the load point of the demokext routine. Though there are numerous ways to find this address, in this case the simpliest is to just use the symbolic name; to review other options refer back to the Setting Breakpoints section. As mentioned, earlier the value for demokext_j should now be 0x00000065. The data displayed should be similar to:
demokext_j+000000: 00000065 01304040 01304754 00000000  ...e.0@@.0GT....
KDB(0)> g Exit the KDB Kernel Debugger.
$ fg Bring the demo program to the foreground.
./demo 0 Enter an option of 0 to unload the demokext kernel extension and exit.


Stack Trace

The stack trace gives the stack history. This provides the sequence of procedure calls leading to the current IAR. The Saved LR is the address of the instruction calling this procedure. You can use the map file to locate the name of the procedure. Note that the first stack frame shown is almost always useless, since data either has not been saved yet, or is from a previous call. The last function preceding the Saved LR is the function that called the procedure.

The following is a concise view of the stack:

    Low                     |                    |Stack grows at
    Addresses               |                    |this end.
                            |--------------------|
    Callee's stack ->  0    |     Back chain     |
    pointer            4    |      Saved CR      |
                       8    |      Saved LR      |
                    12-16   |      Reserved      |<---LINK AREA (callee)
                      20    |      SAVED TOC     |
                            |--------------------|
    Space for P1-P8         |         P1         |  OUTPUT ARGUMENT AREA
    is always reserved      |        ...         |<---(Used by callee to
                            |         Pn         |    construct argument
                            |      Callee's      |
                            |       stack        | <--- LOCAL STACK AREA
                            |        area        |
                            |--------------------|
                            |                    | (Possible word wasted
                            |--------------------|    for alignment.)
    -8*nfprs-4*ngprs -->    |   Caller's GPR     | Rfirst = R13 for full
    save                    |     save area      |          save
                            |    max 19 words    | R31
                            |--------------------|
    -8*nfprs -->            |   Caller's FPR     | Ffirst = F14 for a
                            |     save area      |          full save
                            |   max 18 dblwds    | F31
                            |--------------------|
    Caller's stack ->  0    |     Back chain     |
    pointer            4    |      Saved CR      |
                       8    |      Saved LR      |
                    12-16   |      Reserved      |<---LINK AREA (caller)
                       20   |      Saved TOC     |
                            |--------------------|
    Space for P1-P8    24   |         P1         |  INPUT PARAMETER AREA
    is always reserved      |        ...         | <---(Callee's input
                            |         Pn         |     parameters found
                            |--------------------|      here. Is also
                            |      Caller's      |   caller's arg area.)
                            |       stack        |
    High                    |        area        |
    Addresses               |

To illustrate some of the capabilities of the KDB Kernel Debugger for viewing the stack use the demo program and demokext kernel extension again. This time a break will be set in the write_log routine.

Prompt and Console Input Function and Example Output
Load the demokext kernel extension
$ ./demo Run the demo program, this loads the demokext extension.
$ <CTRL-Z> Stop the demo program.
$ bg Put the demo program in the background.
$ <CTRL-\> Activate KDB, use the appropriate key sequence for your configuration. You should have a KDB prompt on completion of this step.
Set and execute to a breakpoint in write_log
KDB(0)> b demokext+280 Set a break at line 117 of demokext.c; this is the first line of write_log. The offset of 0x00000280 was determined from the list file as described in earlier sections.
KDB(0)> g Exit the KDB Kernel Debugger.
$ fg Bring the demo program to the foreground.
./demo 1 Select option 1 to increment the counters in the kernel extension demokext. This causes the KDB Kernel Debugger to be invoked; stopped at the breakpoint set in write_log.
View the stack
KDB(0)> stack This displays the stack for the current process, which was the the demo program calling the demokext kernel extension (since there was a break set). The stack trace back displays the routines called and even traces back through system calls. The displayed data should be similar to:
thread+001800 STACK:
[013042C0]write_log+00001C (10002040, 2FF3B258, 2FF3B2BC)
[013040B0]demokext+000070 (00000001, 2FF3B338)
[001E3BF4]config_kmod+0000F0 (??, ??, ??)
[001E3FA8]sysconfig+000140 (??, ??, ??)
[000039D8].sys_call+000000 ()
[10000570]main+000280 (??, ??)
[10000188]__start+000088 ()
KDB(0)> s 4 This subcommand steps 4 instructions. This should get into a strlen call. If it doesn't, continue stepping until strlen is entered.
KDB(0)> stack Reexamine the stack. It should now include the strlen call and should be similar to:
thread+001800 STACK:
[01304500]strlen+000000 ()
[013042CC]write_log+000028 (10002040, 2FF3B258, 2FF3B2BC)
[013040B0]demokext+000070 (00000001, 2FF3B338)
[001E3BF4]config_kmod+0000F0 (??, ??, ??)
[001E3FA8]sysconfig+000140 (??, ??, ??)
[000039D8].sys_call+000000 ()
[10000570]main+000280 (??, ??)
[10000188]__start+000088 ()
KDB(0)> set display_stack_frames This subcommand toggles a KDB Kernel Debugger option to display the top (lower addresses) 64 bytes for each stack frame.
KDB(0)> stack Redisplay the stack with the display_stack_frames option turned on. The output should be similar to:
thread+001800 STACK:
[01304510]strlen+000000 ()
=======================================================================
2FF3B1C0: 2FF3 B210  2FF3 B380  0130 4364  0000 0000   /.../....0Cd....
2FF3B1D0: 2FF3 B230  0130 4754  0023 AD5C  2222 2082   /..0.0GT.#.\"" .
2FF3B1E0: 0012 0000  2FF3 B400  0000 0480  0000 510C   ..../.........Q.
2FF3B1F0: 2FF3 B260  4A22 2860  001D CEC8  0000 153C   /..`J"(`.......<
=======================================================================
[013042CC]write_log+000028 (10002040, 2FF3B258, 2FF3B2BC)
=======================================================================
2FF3B210: 2FF3 B2E0  0000 0003  0130 40B4  0000 0000   /........0@.....
2FF3B220: 0000 0000  2FF3 B380  1000 2040  2FF3 B258   ..../..... @/..X
2FF3B230: 2FF3 B2BC  0000 0000  001E 5968  0000 0000   /.........Yh....
2FF3B240: 0000 0000  0027 83E8  0048 5358  007F FFFF   .....'...HSX....
=======================================================================
[013040B0]demokext+000070 (00000001, 2FF3B338)
=======================================================================
2FF3B2E0: 2FF3 B370  2233 4484  001E 3BF8  0000 0000   /..p"3D...;.....
2FF3B2F0: 0000 0000  0027 83E8  0000 0001  2FF3 B338   .....'....../..8
2FF3B300: E300 1E30  0000 0020  2FF1 F9F8  2FF1 F9FC   ...0... /.../...
2FF3B310: 8000 0000  0000 0001  2FF1 F780  0000 3D20   ......../.....= 
[001E3BF4]config_kmod+0000F0 (??, ??, ??)
=======================================================================
2FF3B370: 2FF3 B3C0  0027 83E8  001E 3FAC  2FF2 2FF8   /....'....?././.
2FF3B380: 0000 0002  2FF3 B400  F014 8912  0000 0FFE   ..../...........
2FF3B390: 2FF3 B388  0000 153C  0000 0001  2000 7758   /......<.... .wX
2FF3B3A0: 0000 0000  0000 09B4  0000 0FFE  0000 0000   ................
=======================================================================
[001E3FA8]sysconfig+000140 (??, ??, ??)
=======================================================================
2FF3B3C0: 2FF2 1AA0  0002 D0B0  0000 39DC  2222 2022   /.........9."" "
2FF3B3D0: 0000 3E7C  0000 0000  2000 9CF8  2000 9D08   ..>|.... ... ...
2FF3B3E0: 2000 A1D8  0000 0000  0000 0000  0000 0000    ...............
2FF3B3F0: 0000 0000  0024 FA90  0000 0000  0000 0000   .....$..........
=======================================================================
[000039D8].sys_call+000000 ()
=======================================================================
2FF21AA0: 2FF2 2D30  0000 0000  1000 0574  0000 0000   /.-0.......t....
2FF21AB0: 0000 0000  2000 0B14  2000 08AC  2FF2 1AE0   .... ... .../...
2FF21AC0: 0000 000E  F014 992D  6F69 6365  3A20 0000   .......-oice: ..
2FF21AD0: FFFF FFFF  D012 D1C0  0000 0000  0000 0000   ................
=======================================================================
[10000570]main+000280 (??, ??)
=======================================================================
2FF22D30: 0000 0000  0000 0000  1000 018C  0000 0000   ................
2FF22D40: 0000 0000  0000 0000  0000 0000  0000 0000   ................
2FF22D50: 0000 0000  0000 0000  0000 0000  0000 0000   ................
2FF22D60: 0000 0000  0000 0000  0000 0000  0000 0000   ................
=======================================================================
[10000188]__start+000088 ()

The displayed data can be interpreted using the diagram presented at the first of this section.

KDB(0)> set display_stack_frames Toggle the display_stack_frames option off.
KDB(0)> set display_stacked_regs This subcommand toggles a KDB Kernel Debugger option to display the registers saved in each stack frame.
KDB(0)> stack Redisplay the stack with the display_stacked_regs option activated. The display should be similar to:
thread+001800 STACK:
[01304510]strlen+000010 ()
[013042CC]write_log+000028 (10002040, 2FF3B258, 2FF3B2BC)
   r30 : 00000000 r31 : 01304648 
[013040B0]demokext+000070 (00000001, 2FF3B338)
   r30 : 00000000 r31 : 00000000 
[001E3BF4]config_kmod+0000F0 (??, ??, ??)
   r30 : 00000005 r31 : 2FF21AF8 
[001E3FA8]sysconfig+000140 (??, ??, ??)
   r30 : 04DAE000 r31 : 00000000 
[000039D8].sys_call+000000 ()
[10000570]main+000280 (??, ??)
   r25 : DEADBEEF r26 : DEADBEEF r27 : DEADBEEF r28 : DEADBEEF r29 : DEADBEEF 
   r30 : DEADBEEF r31 : DEADBEEF 
[10000188]__start+000088 ()
KDB(0)> set display_stacked_regs Toggle the display_stacked_regs option off.
KDB(0)> dw @r1 90 Display the stack in raw format. Note, the address for the stack is in general purpose register 1, so that may be used. The address could also have been obtained from the output when the display_stack_frames option was set. This subcommand displays 0x90 words of the stack in hex and ascii. The output should be similar to the following:
2FF3B1C0: 2FF3B210 2FF3B380 01304364 00000000  /.../....0Cd....
2FF3B1D0: 2FF3B230 01304754 0023AD5C 22222082  /..0.0GT.#.\"" .
2FF3B1E0: 00120000 2FF3B400 00000480 0000510C  ..../.........Q.
2FF3B1F0: 2FF3B260 4A222860 001DCEC8 0000153C  /..`J"(`.......<
2FF3B200: 00000000 00000000 00000000 01304648  .............0FH
2FF3B210: 2FF3B2E0 00000003 013040B4 00000000  /........0@.....
2FF3B220: 00000000 2FF3B380 10002040 2FF3B258  ..../..... @/..X
2FF3B230: 2FF3B2BC 00000000 001E5968 00000000  /.........Yh....
2FF3B240: 00000000 002783E8 00485358 007FFFFF  .....'...HSX....
2FF3B250: 10002040 00000000 64656D6F 6B657874  .. @....demokext
2FF3B260: 20776173 2063616C 6C656420 666F7220   was called for 
2FF3B270: 636F6E66 69677572 6174696F 6E0A0000  configuration...
2FF3B280: 00000000 00000000 00001000 2FF3B390  ............/...
2FF3B290: 2FF3B2E0 00040003 001CE9EC 314C0000  /...........1L..
2FF3B2A0: 2FF3B2E0 002783E8 2FF3B338 00000000  /....'../..8....
2FF3B2B0: 00000000 2E746578 74000000 10000100  .....text.......
2FF3B2C0: 10000100 00000710 00000100 00000000  ................
2FF3B2D0: 00000000 2FF3B380 00000000 00000000  ..../...........
2FF3B2E0: 2FF3B370 22334484 001E3BF8 00000000  /..p"3D...;.....
2FF3B2F0: 00000000 002783E8 00000001 2FF3B338  .....'....../..8
2FF3B300: E3001E30 00000020 2FF1F9F8 2FF1F9FC  ...0... /.../...
2FF3B310: 80000000 00000001 2FF1F780 00003D20  ......../.....= 
2FF3B320: 2FF21AE8 00000010 01304748 00000001  /........0GH....
2FF3B330: 2FF21AE8 00000010 2FF3B320 FFFFFFFF  /......./.. ....
2FF3B340: 00000001 00000000 00000000 00000000  ................
2FF3B350: 00000010 00001C08 00000000 00000000  ................
2FF3B360: 00000031 82222824 00000005 2FF21AF8  ...1."($..../...
2FF3B370: 2FF3B3C0 002783E8 001E3FAC 2FF22FF8  /....'....?././.
2FF3B380: 00000002 2FF3B400 F0148912 00000FFE  ..../...........
2FF3B390: 2FF3B388 0000153C 00000001 20007758  /......<.... .wX
2FF3B3A0: 00000000 000009B4 00000FFE 00000000  ................
2FF3B3B0: 00000010 E6001800 04DAE000 00000000  ................
2FF3B3C0: 2FF21AA0 0002D0B0 000039DC 22222022  /.........9."" "
2FF3B3D0: 00003E7C 00000000 20009CF8 20009D08  ..>|.... ... ...
2FF3B3E0: 2000A1D8 00000000 00000000 00000000   ...............
2FF3B3F0: 00000000 0024FA90 00000000 00000000  .....$..........

This portion of the stack may be interpreted using the diagram at the beginning of this section.

KDB(0)> ca Clear all breakpoints.
KDB(0)> g Exit the kernel debugger. Upon exitting the debugger the prompt from the demo program should be displayed.
Enter choice: 0 Enter an choice of 0 to unload the kernel extension and quit.

[ Next Article | Previous Article | Book Contents | Library Home | Legal | Search ]