編譯命令

生成目標(biāo)文件

目標(biāo)文件包含了機(jī)器指令代碼逐沙、數(shù)據(jù)、鏈接時(shí)需要的信息搏讶、符號(hào)表佳鳖、調(diào)試信息、字符串表媒惕。

1.不指定target腋颠,默認(rèn)是Mach-O 64-bit object x86_64

clang-x c -g -c a.c -o a.o
-x: 指定編譯文件語言類型
-g: 生成調(diào)試信息
-c: 生成目標(biāo)文件,只運(yùn)行`preprocess`吓笙、`compile`淑玫、 `assemble`不鏈接
-o: 輸出文件
-I<directory>:在指定目錄尋找頭文件
-L <dir> :指定庫文件路徑(.a'.dylib庫文件)
-l<library_name> :指定鏈接的庫文件名稱(.a'.dylib庫文件)
-F<directory> :在指定鏈接的framework名稱
-framework <framework_name> framework
生成相應(yīng)的LLVM文件格式,來進(jìn)行鏈接時(shí)間優(yōu)化
當(dāng)我們配合著-S使用時(shí)面睛,生成匯編語言文件絮蒿。否則生成bitcode格式的目標(biāo)文件
-flto=<value> :設(shè)置LTO的模式:full or thin
-flto :設(shè)置LTO的模式:full
-flto=full:默認(rèn)值,單片(monolithic) LTO通過將所有輸入合并到單個(gè)模塊中來實(shí)現(xiàn)此目的
-flto=thin:使用ThinLTO代替
-emit-llvm
-install_name :指定動(dòng)態(tài)庫初次安裝時(shí)的默認(rèn)路徑叁鉴,向'LC_ID_DYLIB'添加安裝路徑土涝,該路徑作為dyld定位該庫。

clang -o是將.c源文件編譯成為一個(gè)可執(zhí)行的二進(jìn)制代碼(-o選項(xiàng)其實(shí)是指定輸出文件文件名幌墓,如果不加-c選項(xiàng), 會(huì)編譯鏈接生成可執(zhí)行文件但壮,文件的名稱由-o選項(xiàng)指定)冀泻。
clang -c是使用LLVM匯編器將源文件轉(zhuǎn)化為目標(biāo)代碼。

2.指定生成Mach-O 64-bit x86-64目標(biāo)文件格式

clang -x c -target x86_64-apple-macos11.1 -g -c a.c -o a.o

3.如果指定target不帶apple系統(tǒng)版本(包括macOS 蜡饵、ipadOS 弹渔、iOS真機(jī)和模擬器)。例如x86_64溯祸,那么生成的目標(biāo)文件是LinuxELF 64-bit

clang -x c -target x86_64 -g -c a.c -o a.o

4. 編譯.m

macOS

clang -x objective-c \
-target x86_64-apple-macos10.15  \
 -fobjc-arc \ 
 -fmodules \ 
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk \ 
-c test.m -o test.o

iOS

clang -x c -g \
-target arm64-apple-ios13.5 \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPho neOS.platform/Developer/SDKs/iPhoneOS13.6.sdk \
-c a.c -o a.o

5. 編譯.mm

macOS

clang -x objective-c++  \
-target x86_64-apple-macos10.15  \
-std=c++11  \
-stdlib=libc++  \ 
-fobjc-arc  \
-fmodules  \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk \ 
-c test.mm -o test.o

iOS模擬器

clang -x objective-c  \
-target x86_64-apple-ios13.5-simulator  \
-fobjc-arc  \
-fmodules  \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.6.sdk \
-c test.m -o test.o

在模擬器上鏈接其他三方庫

clang -x objective-c \
-target x86_64-apple-ios13.5-simulator \
-fobjc-arc  \
-fmodules  \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.6.sdk \
-I/framework Headers 目錄/Headers \
-F/代碼庫目錄\ 
-c test.m -o test.o \
clang -target x86_64-apple-ios13.5-simulator  \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/i PhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.6.sdk  \
-F/代碼庫目錄 \
-fobjc-arc \
-framework AFNetworking \
-v test.o -o test \
clang -target x86_64-apple-ios13.5-simulator \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/i PhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.6.sdk \
-L/代碼庫目錄 \ 
-fobjc-arc  \
-lAFNetworking  \
-dead-strip test.o -o test

編譯成arm64真機(jī)

clang -target arm64-apple-ios13.5  \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk \
-L/代碼倉庫 \
-fobjc-arc \
-lAFNetworking \
test .o -o test \
clang -target arm64-apple-ios13.5 \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.pla tform/Developer/SDKs/iPhoneOS13.6.sdk \
-F/代碼倉庫 \
-fobjc-arc \
-framework AFNetworking  \
test.o -o test

6. 生成dSYM文件

clang -x c -g1 a.c -o a.o

-g1:將調(diào)試信息寫入DWARF格式文件

查看調(diào)試信息

dwarfdump取出并驗(yàn)證DWARF格式調(diào)試信息:

dwarfdump a.o
dwarfdump a.dSYM
dwarfdump --lookup 0x100000f20 --arch=x86_64 a.dSYM

--lookup查看地址的調(diào)試信息肢专。將顯示出所在的目錄,文件焦辅,函數(shù)等信息博杖。

查看文件內(nèi)容

otool用來查看Mach-o文件內(nèi)部結(jié)構(gòu)

otool -l liba.dylib
otool -h libTest.a

-I:顯示解析后的 mach headerload command
-h:顯示未解析的mach header
-L:打印所有鏈接的動(dòng)態(tài)庫路徑
-D:打印當(dāng)前動(dòng)態(tài)庫的install_name

objdump用來查看文件內(nèi)部結(jié)構(gòu),包括ELFMach-o

objdump --macho -h a.o 
objdump --macho -x a.o 
objdump --macho -s -d a.o 
objdump --macho --syms a.o

--macho:指定 Mach-o 類型
-h:打印各個(gè)段的基本信息
-x:打印各個(gè)段更詳細(xì)的信息
-d:將所有包含指定的段反匯編
-s:將所有段的內(nèi)容以16進(jìn)制的方式打印出來
--lazy-bind:打印 lazy binding info
--syms:打印符號(hào)表

靜態(tài)庫的壓縮和解壓縮

ar壓縮目標(biāo)文件筷登,并對(duì)其進(jìn)行編號(hào)和索引剃根,形成靜態(tài)庫。同時(shí)也可以解壓縮靜態(tài)庫前方,查看有哪些目標(biāo)文件 狈醉。

ar -rc a.a  a.o

-r:添加or替換文件
-c:不輸出任何信息
-t:列出包含的目標(biāo)文件

創(chuàng)建靜態(tài)庫

創(chuàng)建庫命令:libtool,可以創(chuàng)建靜態(tài)庫和動(dòng)態(tài)庫镣丑。

//macOS
libtool -static -arch_only x86_64 a.o -o a.a
//iOS
libtool -static -arch_only arm64 -D \
-syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk \
test.o -o libTest.a

創(chuàng)建動(dòng)態(tài)庫

clang -dynamiclib \
-target arm64-apple-ios13.5 \
-isysroot  /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk \
a.o -o a.dylib

查看符號(hào)表

nm命令:

nm -pa a.o

-a:顯示符號(hào)表的所有內(nèi)容
-g:顯加全局符號(hào)
-p:不排序舔糖。顯示符號(hào)表本來的順序
-r:逆轉(zhuǎn)順序
-u:顯示未定義符號(hào)

生成dSYM文件

dsymutil可以被理解為是調(diào)試信息鏈接器。
它按照以下的步驟執(zhí)行:

  1. 讀取 debug map
  2. .o文件中加載DWARF
  3. 重新定位所有地址
  4. 最后將全部的DWARF打包成dSYM Bundle

有了 dSYM后莺匠,我們就擁有了最標(biāo)準(zhǔn)的DWARF的文件金吗,任何dwarf讀取工具(可以處理Mach-O二進(jìn)制文件)都可以處理該標(biāo)準(zhǔn)DWARF
dsymutil操作DWARF格式的debug symbol趣竣∫∶恚可以將可執(zhí)行文件debug symbol生成DWARF格式的文件:

dsymutil -f a -o a.dSYM

-f: .dwarf格式文件
-o <filename>:輸出.dSYM格式文件

移除符號(hào)

strip用來移除和修改符號(hào)表

strip -S a.o

-S:刪除調(diào)試符號(hào)
-X:移除本地符號(hào),L開頭的
-x:移除全部的本地符號(hào)遥缕,只保留全局符號(hào)

鏈接器

ld
-all_load:加載靜態(tài)庫的包含的所有文件卫袒。
-ObjC:加載靜態(tài)庫的包含的所有義的Objective-C類和Category
-force_load <path_to_archive>:加載靜態(tài)庫中指定的文件单匣。

鏈接動(dòng)態(tài)庫與靜態(tài)庫

ld -dylib -arch x86_64 -macosx_version_min 10.13 a.dylib -o a
Id -static -arch x86_64 -e _main a.a -o a

Xcode打印加載的庫

Pre-main Timemain函數(shù)執(zhí)行之前的加載時(shí)間夕凝,包括dylib動(dòng)態(tài)庫加載, Objective-C Runtime 加載等。
Xcode自身提供了一個(gè)在控制臺(tái)打印這些時(shí)間的方法户秤,在XcodeEdit Scheme -> Run -> Auguments添加環(huán)境變量 DYLD_PRINT_STATISTICS 并把其值設(shè)為 1码秉。
DYLD_PRINT_LIBRARIES:打印出所有被加載的庫。
DYLD_PRINT_LIBRARIES_POST_LAUNCH :打印的是通過dlopen調(diào)用返回的庫鸡号,包括動(dòng)態(tài)庫的依賴庫转砖,主要發(fā)生在main函數(shù)運(yùn)行之后鲸伴。

二進(jìn)制重排

鏈接 order.file

ld -o test test.o -lsystem -order_file test.order
ld -o test test.o -lsystem -lc++ -framework Foundation -order_file test.order
ld -map output.map -lsystem -o output a.o

生成Link Map文件

ld -map output.map -lsystem -lc++ -framework Foundation test.o -o output

-map map_file_path 生成 map 文件晋控。
主要包括三大部分:
Object Files:生成二進(jìn)制用到的link單元的路徑和文件編號(hào)
Sections: 記錄Mach-O 每個(gè) Segment/section 的地址范圍
Symbols:按順序記錄每個(gè)符號(hào)的地址范圍

install_name_tool

更改動(dòng)態(tài)共享庫的安裝名稱并操縱運(yùn)行路徑。

install_name_tool -add_rpath <directory> libs_File
install_name_tool -delete_rpath <directory> libs_File
install_name_tool -rpath <old> <new> libs_File 

概念說明

生成目標(biāo)文件的過程中發(fā)生了什么?

  • 編譯器(clang-cl)->匯編器(llvm-as)
  • 鏈接器(llvm-ld)并沒有被執(zhí)行

所以輸出的目標(biāo)文件不會(huì)包含Unix程序在被裝載和執(zhí)行時(shí)所必須的包含信息姓赤,但它以后可以被鏈接到一個(gè)程序赡译。

Mach-o File Format

—個(gè)Mach-o文件有兩部分組成:headerdata

  • header:代表了文件的映射模捂,描述了文件的內(nèi)容以及文件所有內(nèi)容所在的位置捶朵。header包含三種類型:Mach header, segment, sections 蜘矢。header內(nèi)的section描述了對(duì)應(yīng)的二進(jìn)制信息狂男。
  • data:緊跟header之后,由多個(gè)二進(jìn)制組成品腹,one by one岖食。
  1. Mach header:屬于header的一部分,它包含了整個(gè)文件的信息和segment信息舞吭。
  2. Segments(segment commands):指定操作系統(tǒng)應(yīng)該將Segments加載到內(nèi)存中的什么位置泡垃,以及為該Segments分配的字節(jié)數(shù)。還指定文件中的哪些字節(jié)屬于該 Segments,以及文件包含多少sections羡鸥。始終是4096字節(jié)或4KB的倍數(shù)蔑穴,其中4096字節(jié)是最小大小。
  3. Section:所有sections都在每個(gè)segment``之后一個(gè)接一個(gè)地描述惧浴。sections里面定義其名稱存和,在內(nèi)存中的地址,大小衷旅,文件中section數(shù)據(jù)的偏移量和segment名稱捐腿。

Load Commands

二進(jìn)制文件加載進(jìn)內(nèi)存要執(zhí)行的一些指令。
這里的指令主要在負(fù)責(zé)我們APP對(duì)應(yīng)進(jìn)程的創(chuàng)建和基本設(shè)置(分配虛擬內(nèi)存柿顶,創(chuàng)建主線程茄袖,處理代碼簽名/加密的工作),然后對(duì)動(dòng)態(tài)鏈接庫(.dylib 系統(tǒng)庫和我們自己創(chuàng)建的動(dòng)態(tài)庫)進(jìn)行庫加載和符號(hào)解析的工作嘁锯。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末宪祥,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子家乘,更是在濱河造成了極大的恐慌蝗羊,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烤低,死亡現(xiàn)場離奇詭異肘交,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)扑馁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門涯呻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凉驻,“玉大人涝登,你說我怎么就攤上這事效诅÷彝叮” “怎么了戚炫?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵双肤,是天一觀的道長。 經(jīng)常有香客問我七芭,道長蔑赘,這世上最難降的妖魔是什么米死? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任究西,我火速辦了婚禮物喷,結(jié)果婚禮上峦失,老公的妹妹穿的比我還像新娘尉辑。我一直安慰自己,他們只是感情好卓练,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布嘱么。 她就那樣靜靜地躺著顽悼,像睡著了一般蔚龙。 火紅的嫁衣襯著肌膚如雪府蛇。 梳的紋絲不亂的頭發(fā)上屿愚,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天妆距,我揣著相機(jī)與錄音娱据,去河邊找鬼中剩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛掠剑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播型酥,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盯拱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了迹辐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤明吩,失蹤者是張志新(化名)和其女友劉穎殷费,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體详羡,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年水泉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了草则。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蟹漓。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖葡粒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卿嘲,我是刑警寧澤夫壁,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站掌唾,受9級(jí)特大地震影響糯彬,放射性物質(zhì)發(fā)生泄漏似扔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一豪墅、第九天 我趴在偏房一處隱蔽的房頂上張望偶器。 院中可真熱鬧屏轰,春花似錦憋飞、人聲如沸唁盏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春恕曲,著一層夾襖步出監(jiān)牢的瞬間佩谣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工实蓬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茸俭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓安皱,卻偏偏與公主長得像调鬓,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子酌伊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 生成目標(biāo)文件 目標(biāo)文件包含了機(jī)器指令代碼腾窝,數(shù)據(jù),連接時(shí)需要的信息,符號(hào)表虹脯,調(diào)試信息驴娃,字符串表。1.不指定 targ...
    凱歌948閱讀 542評(píng)論 0 0
  • 當(dāng)我們?cè)O(shè)置了 Enable Bitcode=YES 循集,進(jìn)行Archive時(shí),bitcode會(huì)被嵌入到鏈接后的Mac...
    純情_小火雞閱讀 1,421評(píng)論 0 3
  • 本文主要是《程序員的自我修養(yǎng)》學(xué)習(xí)筆記奸例,并著重闡述了程序啟動(dòng)的流程及Mac相關(guān)的知識(shí)點(diǎn)谐区; 一炼杖、簡介 程序內(nèi)存通過分...
    FengyunSky閱讀 958評(píng)論 0 0
  • 目的 探索iOS Crash分類及捕獲流程 了解Crash文件結(jié)構(gòu)及段含義 了解Mach-o文件結(jié)構(gòu) 分析Cras...
    lltree閱讀 1,313評(píng)論 0 8
  • 概述 ??本文檔描述了Mach-O文件格式的結(jié)構(gòu)邮弹,它被用來存儲(chǔ)程序和庫到硬盤中盟劫,作為Mac OS X程序的二進(jìn)制接...
    VenpleD閱讀 1,469評(píng)論 0 5