經過JTAG對比內核啓動後text/rodata段內容

關鍵詞:vmlinux、strip、dump、_text、__end_rodata等等。linux

 

在平常的調試中,可能會在某些狀況下踩到內核重要的數據,好比代碼段或者rodata之類。spa

這種狀況下,須要確認這些數據是否異常。調試

所謂的異常就是從DDR中讀出的數據可否和vmlinux對上。code

1. 準備vmlinux數據

原始的vmlinux文件,須要strip:blog

strip vmlinux -o vmlinux_stripped

而後去掉vmlinux的0x1000頭部。ip

dd if=vmlinux_stripped of=vmlinux_stripped_noheader bs=4096 skip=1

最終獲得的文件vmlinux_stripped_noheader就是加載到內核中運行的可執行文件。it

2. 從DDR中導出數據

鏈接上JTAG,而後經過dump memory將DDR中數據導出。class

dump memory kernel.bin 0x8000000 0x809c7200

 其中0x80000000是內核執行的起始地址,0x809c7200能夠從System.map中獲取,也即_end值。map

3. 對比數據

從下圖能夠看出,在內核啓動以後不變的數據部分是代碼段(_text <--> _etext)和只讀數據段(__start_rodata <--> __end_data)。二進制

在System.map中找到以下幾個關鍵地址:

...
80049000 T _text
...
806af4e8 T _etext
...
806b0000 R __start_rodata
...
80909000 R __end_rodata
...

在從_text到__end_rodata中間的數據,在整個運行期間是不會改變的。

獲取上述符號對應地址的快捷方式:

grep -E " _text|_etext|__start_rodata|__end_rodata|__start_data_ro_after_init|__end_data_ro_after_init" System.map

 

可是存在一個特殊的RO_AFTER_INIT_DATA段,這部分數據在init初始化以後就不會改變。可是仍然和vmlinux是不同的。

#ifndef RO_AFTER_INIT_DATA
#define RO_AFTER_INIT_DATA                        \
    __start_data_ro_after_init = .;                    \
    *(.data..ro_after_init)                        \
    __end_data_ro_after_init = .;
#endif

從DDR中導出_text到__end_rodata之間的數據:

dump memory kernel.bin 0x80049000 0x80909000

從stripped以後的vmlinux中截取_text到__end_rodata之間的數據:

dd if=vmlinux_stripped of=vmlinux_stripped_noheader bs=4096 skip=74 count=2240

0x8004900對應73個頁面,可是還須要去掉1個頁面的頭,因此一共是74個頁面。

0x80909000-0x8004900=0x8c000,即一共2240個頁面。

在BeyondCompare中進行二進制比較以下:

相關文章
相關標籤/搜索