在linux平臺實現atosl

更多技術乾貨請戳:聽雲博客html

序言linux

怎麼在linux 平臺下實現一個相似於mac 平臺下的 atos 工具( iOS 符號化解析)?git

分析問題github

在github上找到了幾年前的開源實現,[https://github.com/dechaoqiu/atosl](https://github.com/dechaoqiu/atosl)web

編譯出來的atosl工具日常很大概率是工做正常的,只有在特殊狀況下會出現解析錯誤,主要表現爲如下方式:小程序

一、使用Swift 編寫的app ,編譯出來的 atosl 必定會解析錯誤(亂碼形式) swift

二、使用C+ + 實現的一些函數,編譯出來的 atosl 解析出來的字符串也是亂碼xcode

三、在解析 iOS 系統framwork 框架的時候 有概率會出現解析錯誤(亂碼形式) app

四、用戶的某些崩潰信息不能定位到具體的 line no,編譯出來的 atosl服務只能解析出來offset。框架

iOS dSYM 文件結構剖析

在 iOS App 開發過程當中,咱們會利用Xcode打包,生成.xarchive的包文件,經過Xcode 的Organizer 工具能夠管理並導出發佈文件,iOS 開發者對這些過程都是輕車熟路,這裏再也不重複闡述,主要想講的是,打包以後生成的dSYM 文件。

dSYM 是一個目錄,打開以後,咱們會找到一個二進制文件以下圖

能夠看出iOS 使用的是DWARF文件結構 (Debug With Attributed RecordFormats) 是一種調試文件結構標準,結構至關複雜。

[https://www.prevanders.net/dwarf.html](https://www.prevanders.net/dwarf.html)

dSYM 文件的一個重要做用就在於,當咱們的程序發生崩潰,經過crash log 或其餘方式 ,會看到調用棧信息。 經過log信息,咱們並不知道具體是在哪個文件的哪個位置出了問題, 這個時候這個二進制文件提供的信息就很是有用了,經過它咱們能夠經過工具 去符號化, Mac OS X 平臺下 Xcode 自帶了 atos 這樣的工具,這樣能夠直接定位到某個文件的具體位置。 用法以下:

在 Mac OS 下有 dwarfdump 工具來解析DWARF文件,很顯然解析出來的信息並不能知足咱們的全部需求。

dwarfdump -a  SwfitTest

若是要了解其內部結構,請參考《iOS系統分析(二)Mach-O二進制文件解析》。

思路

github 下載 atosl 源代碼,C寫的 

添加Cxx 與 Swift的錯誤樣例

make test 結果以下,很明顯 Cxx 與 Swift 符號化有問題,這就是我要解決的問題。

返回到mac os x中利用xcode 提供的 xcrun atos 處理,可以正確解析,(因此我要作的事情就是在linux平臺下實現一個 相似於mac os x 平臺下的  atos -\>輸入輸出相同)

解決C+ + 亂碼的思考過程,在前面學習分析 Mach-O 文件的時候 使用過一個 MachOView 工具,而後我用工具打開QuartzCore 這個dSYM 文件,發如今 SymTables 裏面解析出來的 字符串也是亂碼,可是神奇的事情發生了,當我鼠標停留在某一行亂碼的時候 復出了正確的解析字符串,這說明 MachOView 是可以正確解析C + + 名字的。果斷 github 搜源代碼. 從這裏知道了 編譯器在編譯過程當中會對函數作一些手腳,下面分析編譯器的行爲。

mangled symbol names (重整符號名稱)

C/Cxx

在C這樣的語言中,任何給定的名字(符號)只能對應惟一的一個函數或數據,不須要名字重整(name mangling)。即使如此,若是你看一個典型的純C二進制的符號表,你會發現每一個函數名有一個 (下劃線)的前綴,以下:

這種簡單的「mangling」(重整)已有很長的歷史,實際上沒有多少用處,但仍爲兼容性和一致性起到一些效果。按照慣例,C中定義的名字會有下劃線,而純彙編定義的全局符號則沒有(儘管許多彙編語言的做者爲了一致性,也會預先考慮下劃線的定義)。      

Objective-C  

它的符號名字不會有異議或者說衝突;Objective-C的方法實現的形式是: -[class selector](#),而且objective - c不容許相同的類使用不一樣的參數來重載相同的selectors。

Cxx

一個沒有額外信息的簡單的名字可能會產生異議,因此必須作一些處理, 以下:

由於function對應兩個包含不一樣參數的函數,這在cxx中是合法的定義,因此咱們不能簡單地生成兩個\_ function符號,由於連接器會不知道如何連接,沒法區分不一樣的函數實現。所以,cxx編譯器使用一組嚴格的編碼規則「mangles」(重整)了符號。

Swift

1. 最開始的字符’-‘對Swift符號是必須的

2. ‘-T’是Swift全局符號的標記

解決方法 

按照這個規則本身去還原符號也是可行的,不過仍是比較費時,還可能有bug。

幸虧Xcode 自帶了個工具, 能夠查看這些 mangled name 的原本面目,就不須要本身從新去實現.

解決思路過程

既然apple 提供了工具,那麼我就不須要去本身寫了,直接調用便可,在xcode的目錄中找到了工具地址以下:

第一種解決方法 :管道通訊 atosl 直接調用 swift-demangle 。

第二種解決方法 : 將swift-demangle.dylib 連接到程序中。

正確解析。接下來要想辦法將這個小程序移植到Linux 平臺下。

我猜這是Swift提供的工具,Google 發現Swift是源代碼級別開源,果真支持Linux。

在linux上編譯 Swift

配置環境編譯之(Ubuntu 14.04),編譯過程當中有坑(內存必須配置5GB以上,硬盤30GB 以上)

warning:若是你遇到相似 clang: error: unable to execute command: Killed 的報錯,不要多想,就是內存爆了,多試幾回也許就成功了。

若是一切正常1小時就能編譯完畢(個人硬件環境 MacBookAir  1.4GHz CPU   8GB 內存  固態硬盤,用了將近1個小時)。

第一種解決方案:swift編譯完成後 在build/xxx/xxx/xxx/bin 下果真有ELF這個可執行文件

第二種解決方案: 使用編譯出來的庫文件

在lib目錄下 沒有找到 .so動態庫,納悶好久(swift的 編譯腳本使用的是Cmake) Darwin 這個術語是指 mac  系統內核核心 (包括 xnu kernel 與 Unix Shell 環境),註釋掉這裏就能夠將(Linux 共享庫) .so 編譯出來,若是要編譯靜態庫 則須要修改cmake腳本,以下圖:

共享庫編譯出來了,則直接動態連接到 atosl中,swift 只能在Ubutun上編譯,若是最終你的atosl 要在 Linux的其餘發行版上運行,最好將全部的依賴庫用靜態連接。

2

make test

測試發現 cxx 與Swift的測試樣例 的 offset(定位到的 line no 解析不出來),github上的代碼已經好久沒有人維護了,最後仍是果斷重寫之。

end

(有任何問題請聯繫 email:liutianshxkernel@gmail.com)

 原文連接:http://blog.tingyun.com/web/article/detail/1342

相關文章
相關標籤/搜索