嵌入式linux除錯技巧

2021-08-10 01:47:13 字數 4276 閱讀 2792

1、列印往往是最常用的除錯技巧。

除錯核心和驅動都可以採用printk。在kernel.h (include\linux)中定義了log的等級。

未指定日誌級別的 printk() 採用的預設級別是 default_message_loglevel,這個巨集在kernel/printk.c 中被定義為整數 4,即對應kern_warning。在 /proc/sys/kernel/printk 會顯示4個數值(可由 echo 修改),分別表示當前控制台日誌級別、未明確指定日誌級別的預設訊息日誌級別、最小(最高)允許設定的控制台日誌級別、引導時預設的日誌級別。當 printk() 中的訊息日誌級別小於當前控制台日誌級別時,printk 的資訊(要有\n符)就會在控制台上顯示。但無論當前控制台日誌級別是何值,通過/proc/kmsg (或使用dmesg)總能檢視。另外如果配置好並執行了 syslogd 或 klogd,沒有在控制台上顯示的 printk 的資訊也會追加到 /var/log/messages.log 中。

#define	kern_emerg	"<0>"	/* system is unusable			*/

#define kern_alert "<1>" /* action must be taken immediately */

#define kern_crit "<2>" /* critical conditions */

#define kern_err "<3>" /* error conditions */

#define kern_warning "<4>" /* warning conditions */

#define kern_notice "<5>" /* normal but significant condition */

#define kern_info "<6>" /* informational */

#define kern_debug "<7>" /* debug-level messages

2、列印的東西在哪輸出?

uboot中設定了命令列引數:

set bootargs console=ttysac0,115200   root=/dev/mtdblock3

正是console環境決定了printk的輸出地方。

3、如何利用printk除錯?

在程式中合適的地方加入printk()函式,當無法正常輸出的時候,認定此處可能存在bug。

printk(kern_debug"%s %s %d\n", __file__, __function__, __line__);

1、定位位置(模組還是核心)

通過oops檢視pc值pc = 0x00000000 它屬於什麼的位址?

是核心的位址,還是通過insmod載入的驅動程式的位址?先判斷是否屬於核心的位址 : 

看核心編譯makefile目錄下的 system.map(編譯完核心都會發現在核心根目錄下面多出來乙個system.map檔案)確定核心的函式的位址範圍 : c0004000~c03faa94。

所以可以確定 : 導致錯誤的指令不在核心的位址範圍,則它屬於insmod載入的驅動程式的位址範圍。

modules linked in: 會指明是哪個驅動程式,但是很多時候載入的驅動程式很多,是不會指明具體是哪個。所以還是需要根據pc值來確定究竟是哪個驅動程式。先看看載入的驅動程式的位址範圍。在開發板目錄下 : cat /proc/kallsyms >> kallsyms.txt (核心函式的位址、載入的函式的位址)kallsyms.txt檔案中的內容介紹 //t : 表示全域性函式 t : 表示靜態函式。

模組:

cat /proc/kallsyms >> kallsyms.txt找乙個相近的

arm-linux-objdump -d lcd.ko > lcd.dis 反彙編

根據pc定位那一句出現了問題

核心:arm-linux-objdump -d vmlinux > vmlinux.dis反彙編核心

搜尋pc值

(1)oops資訊的序號,#1,表示是第1次。

internal error: oops: 5 [#1]

(2)核心中載入的模組的名稱

modules linked in: first_drv
(3)發生錯誤時,

cpu的序號,對於單處理器系統,序號為0。

cpu: 0    not tainted  (2.6.22.6 #1)
(4)

pc就是發生錯誤時,指令的位址。

大多時候,pc值只會給出乙個位址,不會指示說是在哪個函式裡面。

pc is at first_drv_open+0x18(該指令的偏移)/0x3c(該函式的總大小) [first_drv]

(5)lr暫存器的值。

lr is at chrdev_open+0x14c/0x164
lr暫存器的值

(6)發生錯誤時,cpu各個

暫存器的值。

pc = 0xbf000018

pc : lr : psr: a0000013

sp : c3c7be88 ip : c3c7be98 fp : c3c7be94

r10: 00000000 r9 : c3c7a000 r8 : c049abc0

r7 : 00000000 r6 : 00000000 r5 : c3e740c0 r4 : c06d41e0

r3 : bf000000 r2 : 56000050 r1 : bf000964 r0 : 00000000

執行這條導致錯誤的指令時各個暫存器的值

flags: nzcv  irqs on  fiqs on  mode svc_32 segment user

control: c000717f  table: 33eb0000  dac: 00000015

(7)發生錯誤時,當前程序是它,並不是說發生錯誤的是這個程序

process firstdrvtest (pid: 777, stack limit = 0xc3c7a258)

發生錯誤時當前程序的名稱是firstdrvtest

(8)棧資訊

stack: (0xc3c7be88 to 0xc3c7c000)

be80: c3c7bebc c3c7be98 c008d888 bf000010 00000000 c049abc0

bea0: c3e740c0 c008d73c c0474e20 c3e766a8 c3c7bee4 c3c7bec0c0089e48 c008d74c

bec0: c049abc0 c3c7bf04 00000003 ffffff9c c002c044 c3d10000c3c7befc c3c7bee8

(9)棧回溯資訊,可以從中看出函式呼叫關係:從最後乙個函式 sys_init_module 開始,向上可以找到函式呼叫的關係。

可以通過核心配置資訊 make menuconfig 來指定是否輸出棧回溯資訊。

backtrace: (回溯)

(first_drv_open+0x0/0x3c [first_drv]) from (chrdev_open+0x14c/0x164)

(chrdev_open+0x0/0x164) from (__dentry_open+0x100/0x1e8)

r8:c3e766a8 r7:c0474e20 r6:c008d73c r5:c3e740c0r4:c049abc0

(__dentry_open+0x0/0x1e8) from (nameidata_to_filp+0x34/0x48)

(nameidata_to_filp+0x0/0x48) from (do_filp_open+0x40/0x48)

r4:00000002

(do_filp_open+0x0/0x48) from (do_sys_open+0x54/0xe4)

r5:bec1fee0 r4:00000002

(do_sys_open+0x0/0xe4) from (sys_open+0x24/0x28)

(sys_open+0x0/0x28) from (ret_fast_syscall+0x0/0x2c)

code: e24cb004 e59f1024 e3a00000 e5912000 (e5923000)

segmentation fault

嵌入式Linux除錯技術

嵌入式除錯方法 1.模擬器。比如qtopia core可以用奇趣提供的frame buffer模擬工具qvfb,arm硬體模擬可以用skyeye開源專案。2.遠端除錯。偵錯程式還在pc上,偵錯程式與被除錯的程式通過網路通訊。3.通過log和core dump等檔案事後分析。大多數開發人員認為kgdb...

嵌入式linux除錯技術

android模擬器只能通過埠對映的方式使用kgdbserver除錯程式。但開發板除了可以通過ip連線到kgdbserver外還可以通過串列埠進行連線。開發板同樣也帶了kgdbserver程式,可直接執行。大多數開發人員認為kgdb是最好的核心除錯工具。kgdb除了提供類似的printk函式的日誌輸...

linux 下嵌入式開發除錯

除錯使用者程式 主機 linux os eclipse cdt gdb gcc交叉編譯鏈 目標機 armlinux os gdbserver 通訊方式 tcp 檔案傳輸方式 ftp,minicom,通過nfs.配置參考 除錯linux kernel.bootloder u boot 除錯核心 gdb...