在使用perf排查問題時,我們經常會發現[kernel.kallsyms]這個子產品。這到底是個什麼東西呢?
在2.6版的核心中,為了更友善的調試核心代碼,開發者考慮将核心代碼中所有函數以及所有非棧變量的位址抽取出來,形成是一個簡單的資料塊(data blob:符号和位址對應),并将此連結進 vmlinux 中去。
在需要的時候,核心就可以将符号位址資訊以及符号名稱都顯示出來,友善開發者對核心代碼的調試。完成這一位址抽取+資料快組織封裝功能的相關子系統就稱之為 kallsyms。
反之,如果沒有 kallsyms 的幫助,核心隻能将十六進制的符号位址呈現給外界,因為它能了解的隻有符号位址,并不能顯示各種函數名等符号。
kallsyms抽取了核心用到的所有函數位址(全局的、靜态的)和非棧資料變量位址,生成一個資料塊,作為隻讀資料連結進kernel image,相當于核心中存了一個system.map。
要在一個核心中啟用 kallsyms 功能。須設定 config_kallsyms 選項為y;如果要在 kallsyms 中包含全部符号資訊,須設定 config_kallsyms_all 為y
得益于/proc檔案系統,我們可以直接讀取這個表。
<code>1</code>
<code>$ </code><code>less</code> <code>/proc/kallsyms</code>
<code>01</code>
<code>000000000000a018 d per_cpu__xen_vcpu</code>
<code>02</code>
<code>000000000000a020 d per_cpu__xen_vcpu_info</code>
<code>03</code>
<code>000000000000a060 d per_cpu__mc_buffer</code>
<code>04</code>
<code>000000000000b570 d per_cpu__xen_mc_irq_flags</code>
<code>05</code>
<code>000000000000b578 d per_cpu__xen_cr3</code>
<code>06</code>
<code>000000000000b580 d per_cpu__xen_current_cr3</code>
<code>07</code>
<code>000000000000b5a0 d per_cpu__xen_runstate</code>
<code>08</code>
<code>000000000000b5e0 d per_cpu__xen_runstate_snapshot</code>
<code>09</code>
<code>000000000000b610 d per_cpu__xen_residual_stolen</code>
<code>10</code>
<code>000000000000b618 d per_cpu__xen_residual_blocked</code>
<code>11</code>
<code>000000000000b620 d per_cpu__xen_clock_events</code>
<code>12</code>
<code>000000000000b6a0 d per_cpu__xen_debug_irq</code>
<code>13</code>
<code>000000000000b6a4 d per_cpu__xen_resched_irq</code>
<code>14</code>
<code>000000000000b6a8 d per_cpu__xen_callfunc_irq</code>
<code>15</code>
<code>000000000000b6ac d per_cpu__xen_callfuncsingle_irq</code>
這個應該可以很容易看出,第一列為符号位址,第二列為類型,第三列為符号名。
注意:如果發現符号位址均為0,那是因為系統保護。使用root權限檢視即可。
第二列的類型:
有的符号是大寫的,有的是小寫。大寫的符号是全局的。
b 符号在未初始化資料區(bss)
c 普通符号,是未初始化區域
d 符号在初始化資料區
g 符号針對小object,在初始化資料區
i 非直接引用其他符号的符号
n 調試符号
r 符号在隻讀資料區
s 符号針對小object,在未初始化資料區
t 符号在代碼段
u 符号未定義