前幾篇文章我們探討了靜態(tài)鏈接
、動(dòng)態(tài)鏈接
秤茅、靜態(tài)庫(kù)
稚补、動(dòng)態(tài)庫(kù)
等,這里我們?cè)賮?lái)回顧一下我們用到的一些編譯命令框喳。
生成目標(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 |
指定編譯文件語(yǔ)言類(lèi)型 |
-g |
生成調(diào)試信息 |
-c |
生成目標(biāo)文件诞挨,只運(yùn)行preprocess , compile , assemble 莉撇,不鏈接 |
-o |
輸出文件 |
-I<directory> |
在指定目錄中尋找頭文件 |
-L<directory> |
指定庫(kù)文件路徑(.a/.dylib 庫(kù)文件) |
-l<library_name> |
指定鏈接的庫(kù)文件名稱(.a/.dylib 庫(kù)文件) |
-F<directory> |
在指定目錄尋找framework 文件 |
-framework <framework_name> |
在指定鏈接的framework 名稱,生成相應(yīng)的LLVM 文件格式亭姥,來(lái)進(jìn)行鏈接時(shí)間優(yōu)化稼钩。當(dāng)我們配合-S 使用是,生成匯編語(yǔ)言文件达罗。否則生成bitcode 格式的目標(biāo)文件 |
-flto=<value> |
設(shè)置LTO的模式:full or thin |
-flto |
設(shè)置LTO的模式:full |
-flto=full |
默認(rèn)值坝撑,單片(monolithic)LTO通過(guò)將所有初入合并到單個(gè)模塊中來(lái)實(shí)現(xiàn)此目的 |
-flto=thin |
使用ThinLTO代替-emit-llvm
|
-install_name |
指定動(dòng)態(tài)庫(kù)初次安裝時(shí)的默認(rèn)路徑,向LC_ID_DYLIB 添加安裝路徑粮揉,該路徑作為dyld 定位該庫(kù)巡李。 |
clang -o
是將.c
源文件編譯生吃一個(gè)可執(zhí)行的二進(jìn)制代碼(-o
選項(xiàng)其實(shí)是指定輸出文件的文件名;如果不加-c
選項(xiàng)扶认,clang
默認(rèn)會(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-macos10.15 -g -c a.c -o a.o
- 3膨蛮、如果指定
target
不帶Apple
系統(tǒng)版本(包括macOS
,ipadOS
,iOS
, 真機(jī)和模擬器);例如x86_64
季研,那么生成的目標(biāo)問(wèn)價(jià)是Linux
的ELF 64-bit
:
clang -x c -target x86_64 -g -c a.c -o a.o
- 4敞葛、編譯
.m
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
clang -x c -g -target arm64-apple-ios13.5 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk -c a.c -o a.o
- 5、編譯
.mm
在Mac
上編譯:
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 te st.mm -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 -c test.m -o test.o
在模擬器上鏈接其他三方庫(kù):
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/Users/ws/Desktop/課程/Library/代碼庫(kù)/AFNetworking.framework/Headers -F/Users/ws/Desktop/課程/Library/代碼庫(kù) -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/Users/ws/Desktop/課程/Library/代碼庫(kù) -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/Users/ws/Desktop/課程/Library/代碼庫(kù) -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/Users/ws/Desktop/課程/Library/代碼庫(kù) -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/Users/ws/Desktop/課程/Library/代碼庫(kù) -fobjc-arc -framework AFNetworking test.o -o test
生成dSYM
文件:
clang -x c -g1 a.c -o a.o
-g1: 將調(diào)試信息寫(xiě)入`DWARF`格式文件
查看調(diào)試信息
swarfdump
取出并驗(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
用來(lái)查看Mach-O
文件內(nèi)部結(jié)構(gòu):
otool -l liba.dylib
otool -h libTest.a
-l : 顯示解析后的 mach header 和 load command
-h : 顯示未解析的 mach header
-L : 打印所有鏈接的動(dòng)態(tài)庫(kù)路徑
-D : 打印當(dāng)前動(dòng)態(tài)庫(kù)的`install_name`
objdump
用來(lái)查看文件內(nèi)部結(jié)構(gòu)氨肌,包括ELF
和 Mach-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 類(lèi)型
-h : 打印各個(gè)段的基本信息
-x : 打印各個(gè)段更詳細(xì)的信息
-d : 將所有包含指定的段反匯編
-s: 將所有段的內(nèi)容以16進(jìn)制的方式打印出來(lái)
--lazy-bind : 打印 lazy binding info
--syms 打印符號(hào)表
靜態(tài)庫(kù)的壓縮和解壓縮
ar
壓縮目標(biāo)文件,并對(duì)其進(jìn)行編號(hào)和索引酌畜,形成靜態(tài)庫(kù)怎囚。同時(shí)也可以解壓縮靜態(tài)庫(kù),查看有哪些目標(biāo)文件:
ar -rc a.a a.o
-r : 添加 或 替換文件
-c : 不輸出任何信息
-t : 列出包含的目標(biāo)文件
創(chuàng)建靜態(tài)庫(kù)
創(chuàng)建庫(kù)命令:libtool
檩奠∽耍可以創(chuàng)建靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù):
libtool -static -arch_only x86_64 a.o -o a.a
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)庫(kù)
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)表本來(lái)的順序
-r : 逆轉(zhuǎn)順序
-u : 顯示未定義符號(hào)
生成dSYM文件
dsymutil
可以被理解為是調(diào)試信息鏈接器埠戳。它按照上面的步驟執(zhí)行:
- 讀取
debug map
- 從
.o
文件中加載DWARF
- 重新定位所有地址
- 最后將全部的
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
用來(lái)移出和修改符號(hào)表:
strip -S a.o
-S : 刪除調(diào)試符號(hào)
-X : 移除本地符號(hào)屁使,‘L’開(kāi)頭的
-x : 移除全部的本地符號(hào),只保留全局符號(hào)
鏈接器
ld
-all_load : 加載靜態(tài)庫(kù)包含的所有文件
-Objc : 加載靜態(tài)庫(kù)包含的所有的 Objective-C 和 Category
-force_load <path_to_archive> : 加載靜態(tài)庫(kù)中指定的文件
鏈接動(dòng)態(tài)庫(kù)與靜態(tài)庫(kù)
ld -dylib -arch x86_64 -macosx_version_min 10.13 a.dylib -o a
ld -static -arch x86_64 -e _main a.a -o a
Xcode 打印加載的庫(kù)
Pre-main Time
指 main
函數(shù)執(zhí)行之前的加載時(shí)間奔则,包括 dylib
動(dòng)態(tài)庫(kù)加載蛮寂, Mach-O
文件加載,Rebase/Binding
易茬,Objective-C Runtime
加載等酬蹋。
Xcode
自身提供了一個(gè)在控制臺(tái)打印這些時(shí)間的方法:在 Xcode
中 Edit Scheme -> Run -> Auguments
添加環(huán)境變量 DYLD_PRINT_STATISTICS
并把其值設(shè)為 1
。
DYLD_PRINT_LIBRARIES
: 打印出所有被加載的庫(kù)抽莱。
DYLD_PRINT_LIBRARIES_POST_LAUNCH
: 打印的是通過(guò)dlopen
調(diào)用返回的庫(kù)范抓,包括動(dòng)態(tài)庫(kù)的依賴庫(kù),主要發(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)制調(diào)用的 link 單元的路徑 和 文件編號(hào)
Sections : 記錄 Mach-O 每個(gè) Segment/section 的地址范圍
Symbols : 按順序記錄每個(gè)符號(hào)的地址范圍
-
install_name_tool
更改動(dòng)態(tài)共享庫(kù)的安裝名稱,并操縱運(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