Clang探究及應(yīng)用

1.前言

本篇文章旨在展示Clang的探究過程

  • 探究Clang的意義
  • Clang在iOS當(dāng)中的發(fā)展史
  • 編譯過程
  • 學(xué)習(xí)Clang的實際應(yīng)用

2.意義

  • 1.oc捎迫、swift都是編譯型語言,兩者都采用Clang作為前端編譯器,LLVM作為后端編譯器,學(xué)習(xí)Clang了解程序的編譯執(zhí)行過程
  • 2.探究代碼的底層實現(xiàn)
  • 3.了解mach-o,dylid,dSYM是什么
  • 4.app瘦身料祠、啟動優(yōu)化利花、lldb調(diào)試技巧、Clang插件定制
    在學(xué)習(xí)戴銘的課程中也多次提到了Clang對于開發(fā)的幫助,有興趣的可以去學(xué)習(xí)下iOS高手開發(fā)課

3.Xcode中的編譯器發(fā)展史

  • 1.xcode3以前:GCC
  • 2.xcode3:增加llvm,gcc前端+llvm后端
  • 3.xcode4.2:出現(xiàn)clang-llvm3.0成為默認(rèn)編譯器
  • 4.xcode4.6llvm升級到4.2版本
  • 5.code5:gcc被廢棄,新的編譯器是llvm5.0,從gcc過渡到clang-llvm時代
    參考指令:clang -v

4.編譯過程

一次完整的編譯流程:clang -ccc-print-phases main.m

0: input, "main.m", objective-c         
1: preprocessor, {0}, objective-c-cpp-output    
2: compiler, {1}, ir
3: backend, {2}, assembler
4: assembler, {3}, object
5: linker, {4}, image
6: bind-arch, "x86_64", {5}, image

4.1預(yù)處理

xcrun clang -x objective-c -E -DDEBUG=1 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.1.sdk main.m

在xocde中查看preprocess過程Product->Perform Action->Preprocess

4.2詞法分析

clang -fmodules -fsyntax-only -Xclang -dump-tokens -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.1.sdk main.m

4.3語法分析

clang -fmodules -fsyntax-only -Xclang -ast-dump -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.1.sdk main.m   

4.4生成中間代碼

clang -O3 -S -fobjc-arc -emit-llvm -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.1.sdk main.m -o main.ll

O3代碼優(yōu)化級別,optimization level

4.5生成目標(biāo)文件

clang -fmodules -c -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.1.sdk main.m -o main.o

4.6生成可執(zhí)行文件

clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.1.sdk main.o AppDelegate.o -o main   

4.7Demo演示

新建一個C項目Demo ,演示生成可執(zhí)行文件的過程


image.png
clang -fmodules -c main.c -o main.o
clang main.o -o main
./main

4.8Xcode查看編譯過程

我們可以查看到編譯的整個過程信息


image.png

5.查看oc的c++實現(xiàn)

clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.1.sdk AppDelegate.m

6.Mach-O

編譯后的可執(zhí)行文件,包括exec(剛才生成的main)王滤、dylib(/usr/lib)

Mach-O 文件包含三個區(qū)域
1.Mach-O Header:包含字節(jié)順序,magic弦追,cpu 類型裙椭,加載指令的數(shù)量等
2.Load Commands:包含很多內(nèi)容的表躏哩,包括區(qū)域的位置,符號表揉燃,動態(tài)符號表等。每個加載指令包含一個元信息筋栋,比如指令類型炊汤,名稱,在二進(jìn)制中的位置等
3.Section:最大的部分,包含了代碼抢腐,數(shù)據(jù)姑曙,比如符號表,動態(tài)符號表等迈倍。
輔助查看工具MachoView

image.png

7.LinkMap文件

Write Link Map File設(shè)置為YES,指定存儲目錄$(SRCROOT)/build/LinkMap.txt,編譯后該文件列出了編譯后的每一個.o文件(包括靜態(tài)庫里的),以及每一個每一個目標(biāo)文件的代碼段,數(shù)據(jù)存儲詳情.默認(rèn):Build/Intermediates.noindex/ClangDemo.build/Debug-iphonesimulator/ClangDemo.build
__text表示編譯后的程序執(zhí)行語句伤靠,__data表示已初始化的全局變量和局部靜態(tài)變量,__bss表示未初始化的全局變量和局部靜態(tài)變量啼染,__cstring表示代碼里的字符串常量宴合,等等。

Address           Size      File    Name
0x100001380   0x00000040  [  2]     +[ViewController createSark]
偏移地址          4*16byte  所屬文件

8.學(xué)習(xí)Clang作用

8.1App瘦身方案

1.滴滴 基于clang插件的一種iOS包大小瘦身方案
https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488360&idx=1&sn=94fba30a87d0f9bc0b9ff94d3fed3386&source=41#wechat_redirect
2.微信 iOS微信安裝包瘦身
https://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=207986417&idx=1&sn=77ea7d8e4f8ab7b59111e78c86ccfe66&3rd=MzA3MDU4NTYzMw==&scene=6#rd
3.阿里 減小ipa體積之刪除frameWork中無用mach-O文件
https://www.oschina.net/question/2625381_2168321

可以看到以上方案都是基于編譯過程/結(jié)果進(jìn)行優(yōu)化,可見Clang在app開發(fā)過程中起到的強(qiáng)大作用

8.2App啟動優(yōu)化

啟動流程:
    1.Load dylibs->rebase->bind->objc->initializers
讀取app的可執(zhí)行文件,Mach-o,在可執(zhí)行文件的Mach_header查找lc_load_dylib的加載指令,查找需要的動態(tài)庫dylib,
    2.加載到內(nèi)存的可執(zhí)行文件都是不可用的,需要ASLR(進(jìn)程每次啟動,地址空間都會被簡單的隨機(jī)化,有PIE標(biāo)識,otool -hv ClangDemo),需要rabase,binding
        rebase:因為初始地址和內(nèi)存地址不同,需要修正
        binding:因為動態(tài)庫不編譯進(jìn)程序最終的二進(jìn)制文件中,而是在運行的時候動態(tài)的查找調(diào)用函數(shù)的地址
    以上主要是__DATA中的指針數(shù)量
    3.objc setup        
    libsystem中l(wèi)ibsystem_initializer初始化libdispatch,調(diào)用了os_object_init,最終調(diào)用了objc_init,objc_init中綁定了3個方法,map_2_images,load_images,unmap_images:
    map_2_images:Binding操作結(jié)束之后,發(fā)出dyld_image_state_bound通知,調(diào)用map_2_images,主要做以下幾件事來完成objc setup:
    讀取二進(jìn)制文件的DATA段內(nèi)容,找到與objc相關(guān)的信息.
    注冊objc類
    確保selector的唯一性
    讀取protocol以及category的信息
    load_images:函數(shù)作用就是調(diào)用objc的load方法,它監(jiān)聽dyld_image_state_dependents-initialize通知
    unmap_image可以理解為map_2_images的逆向操作.
    以上3步都是修改__DATA segment中的內(nèi)容.

    4.靜態(tài)初始化工作,例如load函數(shù),c++的一些初始化構(gòu)造函數(shù)
    5.執(zhí)行完上述的fix-ups之后,接著就會調(diào)用mian()
    
方法:
    優(yōu)化__data__,即去除無用的類,方法,屬性,分類 

9.DSYM是什么

從Mach-o文件中抽取調(diào)試信息(二進(jìn)制地址對,源碼文件,行號以及函數(shù)名字的對應(yīng)關(guān)系)而得到的文件目錄,實際用于保存調(diào)試信息的是.dSYM文件中的DWARF,可以手動生成.
查看.dSYM文件內(nèi)容:dwarfdump -v ClangDemo.app.dSYM

10.Xcode中的clang

警告提示:Incomplete objective-c protocols等等

11.lldb調(diào)試

app運行斷點調(diào)試時,以下列出以下幾個比較有用的lldb調(diào)試方法

  • thread return直接跳出方法:
  • expression修改值 ,比如 expression name = @"張三"
  • bt 10堆棧打印10條,也可以直接bt
  • thread return 跳出方法
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迹鹅,一起剝皮案震驚了整個濱河市卦洽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌斜棚,老刑警劉巖阀蒂,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異弟蚀,居然都是意外死亡蚤霞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門义钉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來争便,“玉大人,你說我怎么就攤上這事断医≈鸵遥” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵鉴嗤,是天一觀的道長斩启。 經(jīng)常有香客問我,道長醉锅,這世上最難降的妖魔是什么兔簇? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮硬耍,結(jié)果婚禮上垄琐,老公的妹妹穿的比我還像新娘。我一直安慰自己经柴,他們只是感情好狸窘,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著坯认,像睡著了一般翻擒。 火紅的嫁衣襯著肌膚如雪氓涣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天陋气,我揣著相機(jī)與錄音劳吠,去河邊找鬼。 笑死巩趁,一個胖子當(dāng)著我的面吹牛痒玩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播议慰,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼蠢古,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了褒脯?” 一聲冷哼從身側(cè)響起便瑟,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎番川,沒想到半個月后到涂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡颁督,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年践啄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沉御。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡屿讽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吠裆,到底是詐尸還是另有隱情伐谈,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布试疙,位于F島的核電站诵棵,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏祝旷。R本人自食惡果不足惜履澳,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望怀跛。 院中可真熱鬧距贷,春花似錦、人聲如沸吻谋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滨溉。三九已至什湘,卻和暖如春长赞,著一層夾襖步出監(jiān)牢的瞬間晦攒,已是汗流浹背闽撤。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留脯颜,地道東北人哟旗。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像栋操,于是被迫代替她去往敵國和親闸餐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348