關鍵詞:vmlinux、strip、dump、_text、__end_rodata等等。linux
在平常的調試中,可能會在某些狀況下踩到內核重要的數據,好比代碼段或者rodata之類。spa
這種狀況下,須要確認這些數據是否異常。調試
所謂的異常就是從DDR中讀出的數據可否和vmlinux對上。code
原始的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
鏈接上JTAG,而後經過dump memory將DDR中數據導出。class
dump memory kernel.bin 0x8000000 0x809c7200
其中0x80000000是內核執行的起始地址,0x809c7200能夠從System.map中獲取,也即_end值。map
從下圖能夠看出,在內核啓動以後不變的數據部分是代碼段(_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中進行二進制比較以下: