亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

System.map文件的示例分析

發布時間:2022-02-19 14:08:44 來源:億速云 閱讀:133 作者:小新 欄目:開發技術

小編給大家分享一下System.map文件的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

有關System.map文件的信息好象很缺乏。其實它一點也不神秘,并且在整個事情當中它并不象看上去那么得重要。但是由于缺乏必要的文檔說明,使其顯得比較神秘。它就象耳垂,我們每個人都有,但卻不知道是干什么用的。本網頁就是用來說明這個問題的。

注意,我并不會是百分之一百正確的。例如,一個系統很可能沒有/proc文件系統支持,但是大多數系統肯定有。這里我假定你是“隨大流的”,并有一個典型配置的系統。

System.map文件的示例分析

某些有關內核出錯(oops)的闡述來自于Alessandro Rubini的“Linux設備驅動程序” 一書,我是從其中學到大部分內核編程知識的。

什么是符號(Symbols)?

在編程中,一個符號(symbol)是一個程序的創建塊:它是一個變量名或一個函數名。 正如你自己編制的程序一樣,內核具有各種符號也是不應該感到驚奇的。當然,區別在 于內核是一非常復雜的代碼塊,并且含有許多、許多的全局符號。

內核符號表(Kernel Symbol Table)是什么東西?

內核并不使用符號名。它是通過變量或函數的地址(指針)來使用變量或函數的,而 不是使用size_t BytesRead,內核更喜歡使用(例如)c0343f20來引用 這個變量。

而另一方面,人們并不喜歡象c0343f20這樣的名字。我們跟喜歡使用象 size_t BytesRead這樣的表示。通常,這并不會帶來什么問題。內核主要 是用C語言寫成的,所以在我們編程時編譯器/連接程序允許我們使用符號名,并且使 內核在運行時使用地址表示。這樣大家都滿意了。

然而,存在一種情況,此時我們需要知道一個符號的地址(或者一個地址對應的 符號)。這是通過符號表來做到的,與gdb能夠從一個地址給出函數名(或者給出一個 函數名的地址)的情況很相似。符號表是所有符號及其對應地址的一個列表。這里是 一個符號表例子:

c03441a0 B dmi_broken

c03441a4 B is_sony_vaio_laptop

c03441c0 b dmi_ident

c0344200 b pci_bios_present

c0344204 b pirq_table

c0344208 b pirq_router

c034420c b pirq_router_dev

c0344220 b ascii_buffer

c0344224 b ascii_buf_bytes

你可以看出名稱為dmi_broken的變量位于內核地址c03441a0處。

什么是System.map文件?

有兩個文件是用作符號表的:

  1. /proc/ksyms
  2. System.map

這里,你現在可以知道System.map文件是干什么用的了。

每當你編譯一個新內核時,各種符號名的地址定會變化。

/proc/ksyms 是一個 “proc文件” 并且是在內核啟動時創建的。實際上 它不是一個真實的文件;它只是內核數據的簡單表示形式,呈現出象一個磁盤文件似 的。如果你不相信我,那么就試試找出/proc/ksyms的文件大小來。因此, 對于當前運行的內核來說,它總是正確的..

然而,System.map卻是文件系統上的一個真實文件。當你編譯一個新內核時,你原 來的System.map中的符號信息就不正確了。隨著每次內核的編譯,就會產生一個新的 System.map文件,并且需要用該文件取代原來的文件。

什么是一個Oops?

在自己編制的程序中最常見的出錯情況是什么?是段出錯(segfault),信號11。

Linux內核中最常見的bug是什么?也是段出錯。除此,正如你想象的那樣,段出 錯的問題是非常復雜的,而且也是非常嚴重的。當內核引用了一個無效指針時,并不 稱其為段出錯 — 而被稱為”oops”。一個oops表明內核存在一個bug,應該總是提出 報告并修正該bug。

請注意,一個oops與一個段出錯并不是一回事。你的程序并不能從段出錯中恢復 過來,當出現一個oops時,并不意味著內核肯定處于不穩定的狀態。Linux內核是非常 健壯的;一個oops可能僅殺死了當前進程,并使余下的內核處于一個良好的、穩定的 狀態。

一個oops并非是內核死循環(panic)。在內核調用了panic()函數后,內核就不能 繼續運行了;此時系統就處于停頓狀態并且必須重啟。如果系統中關鍵部分遭到破壞 那么一個oops也可能會導致內核進入死循環(panic)。例如,設備驅動程序中 出現的oops就幾乎不會導致系統進行死循環。

當出現一個oops時,系統就會顯示出用于調試問題的相關信息,比如所有CPU寄存器 中的內容以及頁描述符表的位置等,尤其會象下面那樣打印出EIP(指令指針)的內容:

EIP: 0010:[]

Call Trace: []

一個Oops與System.map文件有什么關系呢?

我想你也會認為EIP和Call Trace所給出的信息并不多,但是重要 的是,對于內核開發人員來說這些信息也是不夠的。由于一個符號并沒有固定的地址, c010b860可以指向任何地方。

為了幫助我們使用oops含糊的輸出,Linux使用了一個稱為klogd(內核日志后臺程序)的 后臺程序,klogd會截取內核oops并且使用syslogd將其記錄下來,并將某些象c010b860 的信息轉換成我們可以識別和使用的信息。換句話說,klogd是一個內核消息記錄器(logger), 它可以進行名字-地址之間的解析。一旦klogd開始轉換內核消息,它就使用手頭的記錄器, 將整個系統的消息記錄下來,通常是使用syslogd記錄器。

為了進行名字-地址解析,klogd就要用到System.map文件。我想你現在 知道一個oops與System.map的關系了。

深入說明: 其實klogd會執行兩類地址解析活動。

  • 靜態轉換,將使用System.map文件。
  • 動態轉換,該方式用于可加載模塊,不使用System.map,因此與本討論沒有關系,但我仍然對其加以簡單說明。

Klogd動態轉換 假設你加載了一個產生oops的內核模塊。于是就會產生一個oops消息,klogd就會截獲它,并發現該oops發生在d00cf810處。由于該地址屬于動態加載模塊,因此在System.map文件中沒有對應條目。klogd將會在其中尋找并會毫無所獲,于是斷定是一個可加載模塊產生了oops。此時klogd就會向內核查詢該可加載模塊輸出的符號。即使該模塊的編制者沒有輸出其符號,klogd也起碼會知道是哪個模塊產生了oops,這總比對一個oops一無所知要好。 還有其它的軟件會使用System.map,我將在后面作一說明。

System.map應該位于什么地方?

System.map應該位于使用它的軟件能夠尋找到的地方,也就是說,klogd會在什么地方尋找它。在系統啟動時,如果沒有以一個參數的形式為klogd給出System.map的位置,則klogd將會在三個地方搜尋System.map。依次為:

  1. /boot/System.map
  2. /System.map
  3. /usr/src/linux/System.map

System.map 同樣也含有版本信息,并且klogd能夠智能化地搜索正確的map文件。例如,假設你正在運行內核2.4.18并且相應的map文件位于/boot/System.map。現在你在目錄/usr/src/linux中編譯一個新內核2.5.1。在編譯期間,文件 /usr/src/linux/System.map就會被創建。當你啟動該新內核時,klogd將首先查詢 /boot/System.map,確認它不是啟動內核正確的map文件,就會查詢 /usr/src/linux/System.map, 確定該文件是啟動內核正確的map文件并開始讀取其中的符號信息。

幾個注意點:

  • 在2.5.x系列內核的某個版本,Linux內核會開始untar成linux-version,而非只是linux (請舉手表決 — 有多少人一直等待著這樣做?)。我不知道klogd是否已經修改為在/usr/src/linux-version/System.map中搜索。TODO:查看klogd源代碼。
  • 在線手冊上對此也沒有完整描述,請看: strace -f /sbin/klogd | grep ‘System.map’ 31208 open(“/boot/System.map-2.4.18”, O_RDONLY|O_LARGEFILE) = 2顯然,不僅klogd在三個搜索目錄中尋找正確版本的map文件,klogd也同樣知道尋找名字為 “System.map” 后加”-內核版本”,象 System.map-2.4.18. 這是klogd未公開的特性。

有一些驅動程序將使用System.map來解析符號(因為它們與內核頭連接而非glibc庫等),如果沒有System.map文件,它們將不能正確地工作。這與一個模塊由于內核版本不匹配而沒有得到加載是兩碼事。模塊加載是與內核版本有關,而與即使是同一版本內核其符號表也會變化的編譯后內核無關。

還有誰使用了System.map?

不要認為System.map文件僅對內核oops有用。盡管內核本身實際上不使用System.map,其它程序,象klogd,lsof, satan# strace lsof 2>&1 1> /dev/null | grep System readlink(“/proc/22711/fd/4”, “/boot/System.map-2.4.18”, 4095) = 23

ps, satan# strace ps 2>&1 1> /dev/null | grep System open(“/boot/System.map-2.4.18”, O_RDONLY|O_NONBLOCK|O_NOCTTY) = 6

以及其它許多軟件,象dosemu,需要有一個正確的System.map文件。

如果我沒有一個好的System.map,會發生什么問題?

假設你在同一臺機器上有多個內核。則每個內核都需要一個獨立的 System.map文件!如果所啟動的內核沒有對應的System.map文件,那么你將定期地看到這樣一條信息: System.map does not match actual kernel (System.map與實際內核不匹配) 不是一個致命錯誤,但是每當你執行ps ax時都會惱人地出現。有些軟件,比如dosemu,可能不會正常工作。最后,當出現一個內核oops時,klogd或ksymoops的輸出可能會不可靠。

我如何對上述情況進行補救?

方法是將你所有的System.map文件放在目錄/boot下,并使用內核版本號重新對它們進行命名。假設你有以下多個內核:

  • /boot/vmlinuz-2.2.14
  • /boot/vmlinuz-2.2.13

那么,只需對應各內核版本對map文件進行改名,并放在/boot下,如:

/boot/System.map-2.2.14 /boot/System.map-2.2.13

如果你有同一個內核的兩個拷貝怎么辦?例如:

  • /boot/vmlinuz-2.2.14
  • /boot/vmlinuz-2.2.14.nosound

最佳解決方案將是所有軟件能夠查找下列文件:

/boot/System.map-2.2.14 /boot/System.map-2.2.14.nosound

但是說實在的,我并不知道這是否是最佳情況。我曾經見到搜尋”System.map-kernelversion”,但是對于搜索”System.map-kernelversion.othertext”的情況呢? 我不太清楚。此時我所能做的就是利用這樣一個事實:/usr/src/linux是標準map文件的搜索路徑,所以你的map文件將放在:

  • /boot/System.map-2.2.14
  • /usr/src/linux/System.map (對于nosound版本)

你也可以使用符號連接:

System.map-2.2.14
System.map-2.2.14.sound
System.map -> System.map-2.2.14.sound

看完了這篇文章,相信你對“System.map文件的示例分析”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

淮滨县| 华亭县| 科技| 宣城市| 方城县| 阿勒泰市| 咸宁市| 阳高县| 无棣县| 鄂伦春自治旗| 宣城市| 巫溪县| 吐鲁番市| 临颍县| 钟山县| 武汉市| 巴青县| 莎车县| 弥渡县| 甘谷县| 芮城县| 绥中县| 连山| 成都市| 永福县| 哈巴河县| 新和县| 资讯| 岱山县| 玛沁县| 益阳市| 阿勒泰市| 湖南省| 浑源县| 莱西市| 淳化县| 邹平县| 九龙县| 阿鲁科尔沁旗| 龙泉市| 陆河县|