23.6. 使用 GDB 來除錯可載入模組

當除錯一個發生在模組內的 panic, 或是使用遠端 GDB 來除錯使用動態模組的機器, 你應該告知 GDB 如何獲得這些模組的符號資訊。

首先,你應該編譯好包含除錯資訊的模組:

    # cd /sys/modules/linux
    # make clean; make COPTS=-g

如果你使用遠端 GDB,你可以在特定機器上執行 kldstat 來找出這個模組在哪被載入:

    # kldstat
    Id Refs Address    Size     Name
     1    4 0xc0100000 1c1678   kernel
     2    1 0xc0a9e000 6000     linprocfs.ko
     3    1 0xc0ad7000 2000     warp_saver.ko
     4    1 0xc0adc000 11000    linux.ko

If you are debugging a crash dump, you'll need to walk the linker_files list, starting at linker_files->tqh_first and following the link.tqe_next pointers until you find the entry with the filename you are looking for. The address member of that entry is the load address of the module.

接著,你必須找出文字區段在模組中的位移量:

    # objdump --section-headers /sys/modules/linux/linux.ko | grep text
      3 .rel.text     000016e0  000038e0  000038e0  000038e0  2**2
     10 .text         00007f34  000062d0  000062d0  000062d0  2**2

區段 10 是在上面這個例子中,你想要的 .text 區段。第四個十六進位欄位是在這個檔案中,文字區段的位移量 (總共六個欄位)。在這個模組的載入記憶體增加這個位移量, 來獲得模組代碼的再定位記憶體。 在我們的例子中,我們得到 0xc0adc000 + 0x62d0 = 0xc0ae22d0。 在 GDB 中使用 add-symbol-file 指令來告知除錯器關於這個模組:

    (kgdb) add-symbol-file /sys/modules/linux/linux.ko 0xc0ae22d0
    add symbol table from file "/sys/modules/linux/linux.ko" at text_addr = 0xc0ae22d0?
    (y or n) y
    Reading symbols from /sys/modules/linux/linux.ko...done.
    (kgdb)

你現在應該存取所有在模組中的符號了。