如何快速定位 Linux Panic 出錯的程式碼

來源:互聯網
上載者:User

標籤:linux   panic   調試   

問題描述

核心調試中最常見的一個問題是:核心Panic後,如何快速定位到出錯的程式碼?

就是這樣一個常見的問題,面試過的大部分同學都未能很好地回答,這裡希望能夠做很徹底地解答。

問題分析

核心Panic時,一般會列印回調,並列印出當前出錯的地址:

kernel/panic.c:panic():

    #ifdef CONFIG_DEBUG_BUGVERBOSE        /*         * Avoid nested stack-dumping if a panic occurs during oops processing         */        if (!test_taint(TAINT_DIE) && oops_in_progress <= 1)            dump_stack();    #endif

dump_stack()調用關係如下:

dump_stack() --> __dump_stack() --> show_stack() --> dump_backtrace()

dump_backtrace()會列印整個回調,例如:

[<001360ac>] (unwind_backtrace+0x0/0xf8) from [<00147b7c>] (warn_slowpath_common+0x50/0x60)[<00147b7c>] (warn_slowpath_common+0x50/0x60) from [<00147c40>] (warn_slowpath_null+0x1c/0x24)[<00147c40>] (warn_slowpath_null+0x1c/0x24) from [<0014de44>] (local_bh_enable_ip+0xa0/0xac)[<0014de44>] (local_bh_enable_ip+0xa0/0xac) from [<0019594c>] (bdi_register+0xec/0x150)

通常,上面的回調會列印出出錯的地址。

解決方案

通過分析,要快速定位出錯的程式碼,其實就是快速尋找到出錯的地址對應的代碼?

  • 情況一

    在代碼編譯串連時,每個函數都有起始地址和長度,這個地址是程式運行時的地址,而函數內部,每條指令相對於函數開始地址會有位移。那麼有了地址以後,就可以定位到該地址落在哪個函數的區間內,然後找到該函數,進而通過計算位移,定位到程式碼。
  • 情況二

    但是,如果拿到的記錄檔所在的系統版本跟當前的代碼版本不一致,那麼編譯後的地址就會有差異。那麼簡單地直接通過地址就可能找不到原來的位置,這個就可能需要回調裡頭的函數名資訊。先通過函數名定位到所在函數,然後通過位移定位到程式碼。
    相應的工具有addr2line, gdb, objdump等,這幾個工具在[How to read a Linux kernel panic?](http://stackoverflow.com/questions/13468286/how-to-read-a-linux-kernel-panic)都有介紹,我們將針對上面的執行個體做更具體的分析。需要提到的是,代碼的實際運行是不需要符號的,只需要地址就行。所以如果要調試代碼,必須確保偵錯符號已經編譯到核心中,不然,回調裡頭列印的是一堆地址,根本看不到符號,那麼對於上面提到的情況二而言,將無法準確定位問題。如果要擷取到足夠多的調試資訊,請根據需要開啟如下選項:
    CONFIG_KALLSYMS=yCONFIG_KALLSYMS_ALL=yCONFIG_DEBUG_BUGVERBOSE=yCONFIG_STACKTRACE=y

    下面分別介紹各種用法。

    • addr2line

      如果出錯的核心跟當前需要調試的核心一致,而且編譯器等都一致,那麼可以通過addr2line直接擷取到出錯的程式碼,假設出錯地址為0019594c:

      $ addr2line -e vmlinux_with_debug_info 0x0019594cmm/backing-dev.c:335

      然後用vim就可以直接找到代碼出錯的位置:

      $ vim mm/backing-dev.c +335

      如果是情況二,可以先通過nm擷取到當前的vmlinux中bdi_register函數的真實位置。

      $ nm vmlinux | grep bdi_register0x00195860 T bdi_register

      然後,加上0xec的位移,即可算出真真實位址:

      $ echo "obase=16;ibase=10;$((0x00195860+0xec))" | bc -l19594C
    • gdb

      這個也適用情況二,因為可以直接用 符號+位移 的方式,因此,即使其他地方有改動,這個相對的位置是不變的。

      $ gdb vmlinux_with_debug_info$ list *(bdi_register+0xec)0x0019594c is in bdi_register (/path/to/mm/backing-dev.c:335).330     bdi->dev = dev;331332     bdi_debug_register(bdi, dev_name(dev));333     set_bit(BDI_registered, &bdi->state);334335     spin_lock_bh(&bdi_lock);336     list_add_tail_rcu(&bdi->bdi_list, &bdi_list);337     spin_unlock_bh(&bdi_lock);338339     trace_writeback_bdi_register(bdi);

      如果是情況一,則可以直接用地址:list *0x0019594c

    • objdump

      如果是情況一,直接用地址dump出來。咱們回頭看一下Backtrace資訊:bdi_register+0xec/0x150,這裡的0xec是位移,而0x150是該函數的大小。用objdump預設可以擷取整個vmlinux的代碼,但是咱們其實只擷取一部分,這個可以通過--start-address--stop-address來指定。另外-d可以彙編代碼,-S則可以併入原始碼。

      $ objdump -dS vmlinux_with_debug_info --start-address=0x0019594c --end-address=$((0x0019594c+0x150))

      如果是情況二,也可以跟addr2line一樣先算出真真實位址,然後再通過上面的方法匯出。

    總地來看,gdb還是來得簡單方便,無論是情況下和情況二都適用,而且很快捷地就顯示出了出錯的代碼位置,並且能夠顯示代碼的內容。

    對於使用者態來說,分析的方式類似。如果要在應用中擷取Backtrace,可以參考Generating backtraces。其例子如下:

    #include <execinfo.h>#define BACKTRACE_SIZ 64void show_backtrace (void){        void    *array[BACKTRACE_SIZ];        size_t   size, i;        char   **strings;        size = backtrace(array, BACKTRACE_SIZ);        strings = backtrace_symbols(array, size);        for (i = 0; i < size; i++) {            printf("%p : %s\n", array[i], strings[i]);        }        free(strings);  // malloced by backtrace_symbols}

    編譯代碼時需要加上:-funwind-tables-g-rdynamic

如何快速定位 Linux Panic 出錯的程式碼

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.