編譯命令

目錄


一、生成目標文件: .o

目標文件包含了機器指令代碼、數(shù)據(jù),鏈接時需要的信息,符號表、調試信息,字符串表。

  1. 不指定target, 默認是Mach-O 64-bit object x86_64 :
clang -x c -g -c a.c -o a.o
-x:指定編譯文件語言類型
-g:生成調試信息
-c:生成目標文件,只運行preprocess, compile, assemble, 不鏈接
-o:輸出文件
-I<directory>在指定目錄尋找頭文件
-L<dir>指定庫文件路徑(. a\.dylib庫文件)
-l<library_name>指定鏈接的庫文件名稱(. a\.dylib庫文件)
-F<directory>在指定目錄尋找framework頭文件
-framework <framework_name>在指定鏈接的framework名稱生成相應的LLVM文件格式,來進行鏈接時間優(yōu)化
當我們配合著-S使用時,生成匯編語言文件。否則生成bitcode格式的目標文件
-flto=<value>設置LTO的模式: full or thin
-flto 設置LTO的模式: full
-flto=full, 默認值,單片(monolithic) LTO通過將所有輸入合并到單個模塊中來實現(xiàn)此目的
-flto=thin,使用ThinLTO代替
-emit-llvm
-install_name指定動態(tài)庫初次安裝時的默認路徑,向'LC_ID_DYLIB '添加安裝路徑,該路徑作為dyld定位該庫。

clang -o是將.c源文件編譯成為一個可執(zhí)行的二進制代碼( -o 選項其實是指定輸出文件文件名,如果不加-c選項,clang默認會編譯鏈接生成可執(zhí)行文件,文件的名稱由-o選項指定)。

clang-c是使用LLVM匯編器將源文件轉化為目標代碼。

  1. 指定生成Mach-O 64-bit x86-64目標文件格式:
clang -x c -target x86_64-apple-macos10.15 -g -c a.c -o a.o
  1. 如果指定target不帶apple系統(tǒng)版本(包括macOSipadOS,iOS真機模擬器)。例如x86_64, 那么生成的目標文件是LinuxELF 64-bit :
clang -x c -target x86_64 -g -c a.c -o a.o
  1. 編譯.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
  1. 編譯.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 test.mm -o test.o

在模擬器上編譯:

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

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

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/AFNetworking.framework/Headers -F/Users/ws/Desktop/Library \
-c test.m -o test.o

clang -target x86_64-apple-ios13.5-simulator \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.6.sdk \
-F/Users/ws/Desktop/Library \
-fobjc-arc \
-framework AFNetworking \
-v test.o -o test

clang -target x86_64-apple-ios13.5-simulator \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.6.sdk \
-L/Users/ws/Desktop/Library \
-fobjc-arc \
-lAFNetworking \
-dead-strip \
test.o -o test

編譯成arm64真機:

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 \
-fobjc-arc \
-lAFNetworking \
test.o -o test

clang -target arm64-apple-ios13.5 \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk \
-F/Users/ws/Desktop//Library \
-fobjc-arc \
-framework AFNetworking \
test.o -o test
  1. 生成dSYM文件:
clang -x c -g1 a.c -o a.o
-g1: 將調試信息寫入DWARF格式文件

二、查看調試信息

dwarfdump取出并驗證DWARF格式調試信息:

dwarfdump a.o
dwarfdump a.dSYM
dwarfdump --lookup 0x100000f20 --arch=x86_64 a.dSYM
--lookup查看地址的調試信息。將顯示出所在的目錄,文件,函數(shù)等信息

三、查看文件內容

otool用來查看Mach-O文件內部結構:

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

-l:顯示解析后的mach header和load command
-h:顯示未解析的mach header
-L:打印所有鏈接的動態(tài)庫路徑
-D:打印當前動態(tài)庫的install_ name

objdump用來查看文件內部結構,包括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: 打印各個段的基本信息
-x: 打印各個段更詳細的信息
-d: 將所有包含指定的段反匯編
-s:將所有段的內容以16進制的方式打印出來
--lazy-bind:打印lazy binding info
--syms打印符號表

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

ar壓縮目標文件,并對其進行編號和索引,形成靜態(tài)庫。同時也可以解壓縮靜態(tài)庫,查看有哪些目標文件:

ar -rc a.a a.o
-r:添加or替換文件
-c: 不輸出任何信息
-t:列出包含的.o目標文件

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

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

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)建動態(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

七、查看符號表

nm命令:

nm -pa a.o
-a:顯示符號表的所有內容
-g:顯示全局符號
-p:不排序。顯示符號表本來的順序
-r:逆轉順序
-u: 顯示未定義符號

八、生成dSYM文件

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

  • 讀取debug map
  • .o文件中加載DWARF
  • 重新定位所有地址
  • 最后將全部的DWARF打包成dSYM Bundle
    有了dsYM后,我們就擁有了最標準的DWARF的文件,任何可以dwarf讀取工具(可以處理Mach-O二進制文件)都可以處理該標準DWARF)。

dsymutil操作DWARF格式的debug symbol。 可以將可執(zhí)行文件debug symbol的生成DWARF格式的文件:

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

九、移除符號

strip用來移除和修改符號表:

strip -S a.o
-S刪除調試符號
-X移除本地符號,‘L '開頭的
-x移除全部的本地符號,只保留全局符號

十、鏈接器

ld

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

十一、鏈接動態(tài)庫與靜態(tài)庫

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打印加載的庫

Pre-main Timemain函數(shù)執(zhí)行之前的加載時間,包括dylib動態(tài)庫加載, Mach-O 文件加載, Rebase/Binding,Objective-C Runtime加載等。
Xcode自身提供了一個在控制臺打印這些時間的方法:在XcodeEdit Scheme -> Run -> Auguments添加環(huán)境變量DYLD_PRINT_STATISTICS并把其值設為1。
DYLD_PRINT_LIBRARIES:打印出所有被加載的庫。
DYLD_PRINT_LIBRARIES_POST_LAUNCH:打印的是通過dlopen調用返回的庫,包括動態(tài)庫的依賴庫,主要發(fā)生在main函數(shù)運行之后。


十三、二進制重排

鏈接order.fle

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: 生成二進制用到的`link`單元的路徑和文件編號
Sections:記錄 Mach-O 每個Segment/section 的地址范圍
Symbols:按順序記錄每 個符號的地址范圍

install_name_tool
更改動態(tài)共享庫的安裝名稱并操縱運行路徑

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

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

編譯器(clang-cl) --> 匯編器(lvm-as)
鏈接器(lvm-ld)并沒有被執(zhí)行
所以輸出的目標文件不會包含Unix程序在被裝載和執(zhí)行時所必須的包含信息,但它以后可以被鏈接到一個程序。

十四、Mach-O File Format

一個Mach-O文件由兩部分組成headerdata。
header:代表了文件的映射,描述了文件的內容以及文件所有內容所在的位置。
data:緊跟header之后,由多個二進制組成,one by one。

  • header:
    header:包含三種類型。Mach header, segment, sections
    header內的section描述了對應的二進制信息。
    注意:Mach header屬于header的一部分,它包含了整個文件的信息和segment信息

  • segment:
    Segments(segment commands);指定操作系統(tǒng)應該將Segments加載到內存中的什么位置,以及為該Segments分配的字節(jié)數(shù)。還指定文件中的哪些字節(jié)屬于該Segments,以及文件包含多少sections。始終是4096字節(jié)或4KB的倍數(shù),其中4096字節(jié)是最小大小。

  • sections:
    Section:所有sections都在每個segment之后一個接個地描述。 sections里面定義其名稱,在內存中的地址,大小,文件中section數(shù)據(jù)的偏移量和segment名稱。

Load Commands

進制文件加載進內存要執(zhí)行的一些指令。
這里的指令主要在負責我們APP對應進程的創(chuàng)建和基本設置(分配虛擬內存,創(chuàng)建主線程,處理代碼簽名/加密的工作),然后對動態(tài)鏈接庫(.dylib系統(tǒng)庫和我們自己創(chuàng)建的動態(tài)庫)進行庫加載和符號解析的工作。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 生成目標文件 目標文件包含了機器指令代碼、數(shù)據(jù)、鏈接時需要的信息、符號表、調試信息、字符串表。 1.不指定targ...
    HotPotCat閱讀 458評論 0 1
  • 生成目標文件 目標文件包含了機器指令代碼,數(shù)據(jù),連接時需要的信息,符號表,調試信息,字符串表。1.不指定 targ...
    凱歌948閱讀 686評論 0 0
  • 概述 ??本文檔描述了Mach-O文件格式的結構,它被用來存儲程序和庫到硬盤中,作為Mac OS X程序的二進制接...
    VenpleD閱讀 1,660評論 0 5
  • 當我們設置了 Enable Bitcode=YES ,進行Archive時,bitcode會被嵌入到鏈接后的Mac...
    純情_小火雞閱讀 1,555評論 0 3
  • 介紹 Mach-O 的全稱是 Mach Object File Format??梢允强蓤?zhí)行文件,目標代碼或共享庫,...
    星光社的戴銘閱讀 2,646評論 1 21

友情鏈接更多精彩內容