[BACK]Return to debug.html CVS log [TXT][DIR] Up to [local] / prex-old / doc / html / doc

Annotation of prex-old/doc/html/doc/debug.html, Revision 1.1.1.1

1.1       nbrk        1: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
                      2: <html>
                      3: <head>
                      4:   <title>Prex Kernel Debugging Tips and Tricks</title>
                      5:   <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
                      6:   <meta name="keywords" content="Prex, embedded, real-time, operating system, RTOS, open source, free">
                      7:   <meta name="author" content="Kohsuke Ohtani">
                      8:   <link rel="stylesheet" type="text/css" href="../default.css" media="screen">
                      9:   <link rel="stylesheet" type="text/css" href="../print.css" media="print">
                     10: </head>
                     11: <body>
                     12: <div id="top">
                     13: </div>
                     14: <div id="middle">
                     15: 
                     16: <table id="content" cellpadding="0" cellspacing="0">
                     17:   <tbody>
                     18: 
                     19:     <tr>
                     20:       <td id="header" colspan="2" valign="top">
                     21:         <table width="100%" border="0" cellspacing="0" cellpadding="0">
                     22:         <tr>
                     23:           <td id="logo">
                     24:             <a href="http://prex.sourceforge.net/">
                     25:             <img alt="Prex logo" src="../img/logo.gif" border="0"
                     26:             style="width: 281px; height: 56px;"></a>
                     27:           </td>
                     28:           <td id="brief" align="right" valign="bottom">
                     29:             An Open Source, Royalty-free,<br>
                     30:            Real-time Operating System
                     31:           </td>
                     32:         </tr>
                     33:         </table>
                     34:       </td>
                     35:     </tr>
                     36: 
                     37:     <tr>
                     38:       <td id="directory" style="vertical-align: top;">
                     39:       <a href="http://prex.sourceforge.net/">Prex Home</a> >
                     40:       <a href="index.html">Document Index</a> >
                     41:       Kernel Debugging Tips and Tricks
                     42:     </tr>
                     43:     <tr><td class="pad" colspan="2" style="vertical-align: top;"></td></tr>
                     44: 
                     45:     <tr>
                     46:       <td id="main" style="vertical-align: top;">
                     47:       <h1>Prex Kernel Debugging Tips and Tricks</h1>
                     48: 
                     49: <i>Version 1.0, 2005/09/05</i><br>
                     50: 
                     51: <h3>Table of Contents</h3>
                     52: 
                     53: <ul>
                     54:   <li><a href="#dbg">Building a Debugging Kernel</a></li>
                     55:   <li><a href="#print">Kernel Print</a></li>
                     56:   <li><a href="#panic">Kernel Panic</a></li>
                     57:   <li><a href="#assert">Assertion Check</a></li>
                     58:   <li><a href="#trace">Function Trace</a></li>
                     59:   <li><a href="#dump">Kernel Dump</a></li>
                     60:   <li><a href="#gdb">Remote debugging with GDB</a></li>
                     61: </ul>
                     62: <br>
                     63: <br>
                     64: 
                     65: <h2 id="dbg">Building a Debugging Kernel</h2>
                     66: <p>
                     67: The Prex kernel is compiled with debugging version by default.
                     68: The debugging version will have the following extra functions
                     69: compared with the release version.
                     70: <ul>
                     71:   <li>printk() to output the debug message.</li>
                     72:   <li>panic() log for the fatal error.</li>
                     73:   <li>ASSERT() for the assertion check.</li>
                     74:   <li>Kernel function trace.</li>
                     75:   <li>Dump of the kernel objects.</li>
                     76: </ul>
                     77: <p>
                     78: However, you should care about the following two points.
                     79: </p>
                     80: <ul>
                     81:   <li>The size of executable image will become larger than
                     82:       the release version.</li>
                     83:   <li>The execution speed becomes slower than the release version.
                     84: </ul>
                     85: <p>
                     86: In order to build a release version, you must set the shell variable
                     87: named NDEBUG to 1 before compiling the kernel.
                     88: </p>
                     89: <pre class="terminal">
                     90: $ export NDEBUG=1
                     91: </pre>
                     92: 
                     93: 
                     94: <h2 id="print">Kernel Print</h2>
                     95: <p>
                     96: The most powerful tool for kernel debugging is printk(). You can check the
                     97: code path, or get the data value by putting the printk() anywhere in 
                     98: the kernel code.
                     99: </p>
                    100: <p>
                    101: printk() is the subset of printf() in standard C library. You can use
                    102: only following identifiers for the output string.
                    103: </p>
                    104: <ul>
                    105:   <li>%d - Decimal signed integer</li>
                    106:   <li>%x - Hex integer</li>
                    107:   <li>%u - Unsigned integer</li>
                    108:   <li>%c - Character</li>
                    109:   <li>%s - String</li>
                    110: </ul>
                    111: 
                    112: <h2 id="panic">Kernel Panic</h2>
                    113: <h3>What is Kernel Panic?</h3>
                    114: <p>
                    115: Panic is used to detect unrecoverable error in the kernel.
                    116: The kernel code can call panic() routine anytime if it
                    117: encounters a fatal error. panic() function will stop the system and
                    118: display the message if output device is available. If the kernel is not
                    119: compiled with debug mode, panic() will just reset the system without
                    120: any message. When GDB is connect to the kernel, the control will be
                    121: dropped to the debugger in panic().
                    122: </p>
                    123: 
                    124: <h3>Panic Screen</h3>
                    125: The following is a sample screen of panic() on i386.
                    126: <pre class="terminal">
                    127: =====================================================
                    128: Kernel panic!
                    129: Failed to create interrupt thread
                    130: =====================================================
                    131: ============================
                    132: Trap 3: Breakpoint
                    133: ============================
                    134: Trap frame 80002f28 error 0
                    135:  eax 00000001 ebx 800110ac ecx ffffffff edx 800192b6 esi 00000000 edi 00000000
                    136:  eip 80014289 esp 80002f28 ebp 80002f78 eflags 00000002
                    137:  cs  00000010 ss  00000018 ds  00000018 es  00000018 esp0 00002fff
                    138:  >> interrupt is disabled
                    139: Stack trace:
                    140:  80011103
                    141:  8001130c
                    142:  80010115
                    143: </pre>
                    144: 
                    145: <h2 id="assert">Assertion Check</h2>
                    146: 
                    147: <h3>What is Assertion Check?</h3>
                    148: <p>
                    149: The assert macro puts error messages into the kernel.
                    150: If the specified expression in ASSERT() is false, it displays
                    151: the message to the output device and stops the system.
                    152: </p>
                    153: <p>
                    154: For example, the following ASSERT() macro is put to the entry of the
                    155: irq_attach() routine.
                    156: This means the caller of irq_attach() must provide a valid
                    157: function pointer for ISR (interrupt service routine).
                    158: </p>
                    159: <pre>
                    160: int irq_attach(int vector, int prio, int shared, int (*isr)(int), void (*ist)(int))
                    161: {
                    162:        ASSERT(isr != NULL);
                    163:        ...
                    164: </pre>
                    165: If the kernel detect the invalid argument for isr, it will cause
                    166: a panic() with the following message.
                    167: <pre class="terminal">
                    168: Assertion failed: irq.c line:120 in irq_attach() 'isr != NULL'
                    169: </pre>
                    170: <p>
                    171: The important point is ASSERT() macro is only enabled with the kernel
                    172: debug version. If the assertion is caused by an application bug
                    173: or h/w bug, it should not be covered by ASSERT(). Such fault should be handled
                    174: as an "error" properly.
                    175: </p>
                    176: 
                    177: <h3>IRQ Assertion</h3>
                    178: <p>
                    179: There are some kernel routines that can not be called during
                    180: an interrupt context. For example, the following functions can not
                    181: be called by ISR.
                    182: </p>
                    183: <ul>
                    184:   <li>IRQ control code. (irq_attach() or irq_detach).</li>
                    185:   <li>The system call code that requires an user mode context.</li>
                    186:   <li>The kernel code that assumes it can synchronize by scheduling lock.
                    187:       (kmem).</li>
                    188: </ul>
                    189: <p>
                    190: In order to detect the invalid call of these functions, the kernel defines
                    191: a ASSERT_IRQ() macro. The kernel developer can put this macro in the 
                    192: head of the kernel routine which can not be called by ISR.
                    193: When ISR call such routine, the kernel will report the problem with panic()
                    194: message.
                    195: </p>
                    196: 
                    197: <h2 id="trace">Function Trace</h2>
                    198: The kernel trace is used to log the entry/exit of all functions at 
                    199: runtime.
                    200: It is useful to debug the timing critical issue related to 
                    201: an interrupt handler.
                    202: 
                    203: <h3>Installing the kernel trace</h3>
                    204: <p>
                    205: You must set the shell variable named KTRACE to 1 before compiling the kernel.
                    206: </p>
                    207: <pre class="terminal">
                    208: $ export KTRACE=1
                    209: </pre>
                    210: <p>
                    211: The kernel function trace is disabled by default. If you get the error
                    212: from gcc, you should check the function with "extern inline" in the header
                    213: file. Such function must be replaced as "static inline" routine to
                    214: enable the function trace.
                    215: </p>
                    216: 
                    217: <h3>Using the kernel trace</h3>
                    218: <p>
                    219: The following functions are available for the kernel trace.
                    220: </p>
                    221: <ul>
                    222:   <li>trace_on: Enable a function trace.</li>
                    223:   <li>trace_off: Disable a function trace.</li>
                    224:   <li>trace_dump: Dump the latest function log.</li>
                    225: </ul>
                    226: <p>
                    227: The trace code is using a ring buffer to store the log data.
                    228: So, older information will be disposed when newer log is filled in the buffer.
                    229: </p>
                    230: 
                    231: <h2 id="dump">Kernel Dump</h2>
                    232: 
                    233: <h3>Installing Kernel Dump</h3>
                    234: <p>
                    235: The kernel dump is used to dump the current status of each kernel
                    236: objects.
                    237: To install the kernel dump function, you must uncomment the following line
                    238: in config.h.
                    239: </p>
                    240: <pre>#define CONFIG_KDUMP 1</pre>
                    241: <p>
                    242: If you assign magic keys for the kernel dump, you can get the 
                    243: kernel dump as far as the keyboard IRQ is enabled.
                    244: The key assignment of the kernel dump depends on each platform.
                    245: </p>
                    246: 
                    247: <h3>Dump Sample</h3>
                    248: <p>
                    249: The following dump screen was got with Prex-i386pc.
                    250: </p>
                    251: <pre class="terminal">
                    252: Kernel dump usage:
                    253: F1=help F2=thread F3=task F4=object F5=timer F6=irq F7=dev F8=mem
                    254: 
                    255: thread_dump:
                    256:  mod thread   task     stat pol  prio base lock qntm total    susp sleep event
                    257:  --- -------- -------- ---- ---- ---- ---- ---- ---- -------- ---- ------------
                    258:  Knl 8002a014 800191a0 SLP  FIFO  022  022    1   50        1    0 interrupt
                    259:  Knl 80029a54 800191a0 SLP  FIFO  020  020    1   50        0    0 interrupt
                    260:  Knl 80029464 800191a0 SLP  RR    015  015    1   50        0    0 timer
                    261:  Knl 800190c0 800191a0 RUN* FIFO  255  255    1    0    44719    0 -
                    262:  Usr 8002a6e4 8002a574 SLP  RR    200  200    1   50        3    0 kbd
                    263: 
                    264: task_dump:
                    265:  mod task      nr_obj nr_thr map      susp exc hdlr name
                    266:  --- --------- ------ ------ -------- ---- -------- ------------
                    267:  Knl 800191a0*      1      4 8001ac20    0 00000000 kernel
                    268:  Usr 8002a574       1      1 8002a5e4    0 00000000 kmon
                    269: 
                    270: IRQ dump:
                    271:  vector isr      ist      ist-thr  ist-prio count
                    272:  ------ -------- -------- -------- -------- --------
                    273:  00     800110c8 00000000 00000000        0    54124
                    274:  01     80020784 800209f8 80029a54       20       66
                    275:  06     800212d0 80021360 8002a014       22        1
                    276:  12     80021aec 00000000 00000000        0        0
                    277: 
                    278: device_dump:
                    279:  device   open     close    read     write    ioctl    event    name
                    280:  -------- -------- -------- -------- -------- -------- -------- ------------
                    281:  8002a544 00000000 00000000 00000000 80020ecc 00000000 00000000 console
                    282:  80029fb4 80021b80 80021bb0 80021be0 00000000 00000000 00000000 mouse
                    283:  80029f44 8002161c 8002163c 80021714 80021800 800218dc 00000000 fd0
                    284:  800299e4 80020a30 80020a50 80020a70 00000000 00000000 00000000 kbd
                    285:  800299b4 00000000 00000000 80020584 00000000 00000000 00000000 rtc
                    286:  80029984 80022808 80022828 00000000 00000000 80022848 00000000 pm
                    287:  80029954 00000000 00000000 00000000 00000000 8002212c 00000000 cpu
                    288: 
                    289: page_dump:
                    290:  free pages:
                    291:  start      end      size
                    292:  --------   -------- --------
                    293:  00025000 - 00027000     2000
                    294:  00034000 - 0009f000    6b000
                    295:  00100000 - 040ff000  3fff000
                    296:  used=200K free=65971K total=66171K
                    297: 
                    298: kmem_dump: page=2 (8Kbyte) alloc=7056byte unused=1136byte
                    299: Allocated block:
                    300:  Size   48 bytes => 11
                    301:  Size   64 bytes => 5
                    302:  Size  112 bytes => 1
                    303:  Size  224 bytes => 4
                    304:  Size 1040 bytes => 5
                    305: Free block:
                    306:  Size   32 bytes => 1
                    307:  Size 1072 bytes => 1
                    308: 
                    309: vm_dump:
                    310: task=8002a574 map=8002a5e4 name=kmon
                    311:  region   virtual  physical size     flags
                    312:  -------- -------- -------- -------- -----
                    313:  8002a624 08048000 0002c000     1000 R----
                    314:  8002a654 08049000 0002e000     1000 RW---
                    315:  8002a6b4 7ffff000 0002f000     1000 RW---
                    316:  *total=12K bytes
                    317: </pre>
                    318: 
                    319: <h2 id="gdb">Remote Debugging with GDB</h2>
                    320: 
                    321: <h3>Installing the GDB remote stub</h3>
                    322: <p>
                    323: To install GDB stub into the Prex kernel, you must uncomment the following line
                    324: in config.h.
                    325: </p>
                    326: <pre>#define CONFIG_GDB 1</pre>
                    327: <p>
                    328: The GDB support is disabled by default.
                    329: </p>
                    330: 
                    331: <h3>Connecting to the remote machine</h3>
                    332: You should specify the path to the symbol file.
                    333: 
                    334: <pre class="terminal">(gdb) symbol-file /usr/src/prex/sys/prex.sym
                    335: (gdb) set remotebaud 115200
                    336: (gdb) target remote /dev/ttyS0</pre>
                    337: 
                    338: <h3>Debugging Sample</h3>
                    339: <pre class="terminal">$ i386-elf-gdb
                    340: GNU gdb 6.3
                    341: Copyright 2004 Free Software Foundation, Inc.
                    342: GDB is free software, covered by the GNU General Public License, and you are
                    343: welcome to change it and/or distribute copies of it under certain conditions.
                    344: Type "show copying" to see the conditions.
                    345: There is absolutely no warranty for GDB.  Type "show warranty" for details.
                    346: This GDB was configured as "--host=i686-pc-cygwin --target=i386-elf".
                    347: (gdb) symbol-file /usr/src/prex-0.1.2/sys/prex.sym
                    348: Reading symbols from /usr/src/prex-0.1.2/sys/prex.sym...done.
                    349: (gdb) set remotebaud 115200
                    350: (gdb) target remote /dev/ttyS0
                    351: Remote debugging using /dev/ttyS0
                    352: gdb_init () at gdb_glue.c:98
                    353: 98      }
                    354: (gdb) b context_init
                    355: Breakpoint 1 at 0x80010d27: file context.c, line 72.
                    356: (gdb) info break
                    357: Num Type           Disp Enb Address    What
                    358: 1   breakpoint     keep y   0x80010d27 in context_init at context.c:72
                    359: (gdb) c
                    360: Continuing.
                    361: 
                    362: Breakpoint 1, context_init (ctx=0x8001a16c, kstack=0x8002c414) at context.c:72
                    363: 72      {
                    364: (gdb) bt 3
                    365: #0  context_init (ctx=0x8001a16c, kstack=0x8002c414) at context.c:72
                    366: #1  0x800137fe in thread_init () at thread.c:469
                    367: #2  0x800125e0 in kernel_main () at main.c:76
                    368: (More stack frames follow...)
                    369: (gdb) list context_init
                    370: 67       *
                    371: 68       * @ctx: context id (pointer)
                    372: 69       * @kstack: kernel stack for the context
                    373: 70       */
                    374: 71      void context_init(context_t ctx, void *kstack)
                    375: 72      {
                    376: 73              struct kern_regs *k;
                    377: 74              struct cpu_regs *u;
                    378: 75
                    379: 76              ctx->uregs = (struct cpu_regs *)(kstack - sizeof(struct cpu_regs
                    380: ));
                    381: (gdb) up
                    382: #1  0x800137fe in thread_init () at thread.c:469
                    383: 469             context_init(&amp;idle_thread.context, stk + KSTACK_SIZE);
                    384: (gdb) list
                    385: 464                     panic("Failed to allocate idle stack");
                    386: 465             memset(stk, 0, KSTACK_SIZE);
                    387: 466             idle_thread.kstack = stk;
                    388: 467             printk("kernel stack size=%d\n", KSTACK_SIZE);
                    389: 468
                    390: 469             context_init(&amp;idle_thread.context, stk + KSTACK_SIZE);
                    391: 470             list_insert(&amp;kern_task.threads, &amp;idle_thread.task_link);
                    392: 471     }
                    393: (gdb) b 465
                    394: Breakpoint 2 at 0x800137c6: file thread.c, line 465.
                    395: (gdb) c
                    396: Continuing.
                    397: </pre>
                    398: 
                    399: 
                    400: 
                    401:       </td>
                    402:     </tr>
                    403:     <tr>
                    404:       <td id="footer" colspan="2" style="vertical-align: top;">
                    405:         <a href="http://sourceforge.net">
                    406:         <img src="http://sourceforge.net/sflogo.php?group_id=132028&amp;type=1"
                    407:         alt="SourceForge.net Logo" border="0" height="31" width="88"></a><br>
                    408:         Copyright&copy; 2005-2007 Kohsuke Ohtani
                    409:       </td>
                    410:     </tr>
                    411: 
                    412:   </tbody>
                    413: </table>
                    414: 
                    415: </div>
                    416: <div id="bottom"></div>
                    417: 
                    418: </body>
                    419: </html>

CVSweb