內核配置
在2.6內核中,爲了更好地調試內核,引入了kallsyms。kallsyms抽取了內核用到的所有函數地址(全局的、靜態的)和非棧數據變量地址,生成一個數據塊,作爲只讀數據鏈接進kernel image,相當於內核中存了一個System.map。
CONFIG_KALLSYMS=y 符號表中包含所有的函數
CONFIG_KALLSYMS_ALL=y 符號表中包括所有的變量(包括沒有用EXPORT_SYMBOL導出的變量)
CONFIG_KALLSYMS_EXTRA_PASS=y
make menuconfig
General setup --->
[*] Configure standard kernel features (for small systems) --->
(選中此項,纔有/proc/kallsyms接口文件, oops問題,選中此選項即可,子選項可以忽略)
[*] Load all symbols for debugging/ksymoops
[*] Include all symbols in kallsyms
[*] Do an extra kallsyms pass
這樣當系統出現oops的時候打印的信息就不是數字了,而是對應的符號信息。
Call Trace:
[] sys_delete_module+0x191/0x1ce
[] do_page_fault+0x189/0x51d
[] syscall_call+0x7/0xb
System.map與kallsyms
./scripts/kallsyms.c生成System.map
./scripts/kallsyms.c解析vmlinux(.tmp_vmlinux)生成kallsyms.S(.tmp_kallsyms.S),然後內核編譯過程中將kallsyms.S(內核符號表)編入內核鏡像uImage
內核啓動後,kernel/kallsyms.c解析uImage形成/proc/kallsyms
/proc/kallsyms
cat /proc/kallsyms
000000000000a018 D per_cpu__xen_vcpu
000000000000a020 D per_cpu__xen_vcpu_info
000000000000a060 d per_cpu__mc_buffer
000000000000b570 D per_cpu__xen_mc_irq_flags
000000000000b578 D per_cpu__xen_cr3
000000000000b580 D per_cpu__xen_current_cr3
000000000000b5a0 d per_cpu__xen_runstate
000000000000b5e0 d per_cpu__xen_runstate_snapshot
000000000000b610 d per_cpu__xen_residual_stolen
第一列爲符號地址,第二列爲類型,第三列爲符號名。如果發現符號地址均爲0,那是因爲系統保護。使用root權限查看即可。
第二列的類型:有的符號是大寫的,有的是小寫。大寫的符號是全局的。
b 符號在未初始化數據區(BSS)
c 普通符號,是未初始化區域
d 符號在初始化數據區
g 符號針對小object,在初始化數據區
i 非直接引用其他符號的符號
n 調試符號
r 符號在只讀數據區
s 符號針對小object,在未初始化數據區
t 符號在代碼段
u 符號未定義
部分轉自:旅途@KryptosX » linux內核符號表kallsyms簡介
kallsyms_lookup_name
驅動代碼中可以通過kallsyms_lookup_name尋找對應的symbol,如,
#ifdef CONFIG_KALLSYMS_ALL
__boot_cpu_mode_sym = (void *)kallsyms_lookup_name("__boot_cpu_mode");
#else
__boot_cpu_mode_sym = resolve_symbol("__boot_cpu_mode");
#endif