编译命令
clang命令
- 生成目标文件: 目标文件包含了机器指令代码、数据,链接时需要的信息,符号表、调试信息、字符串表。
- 如果不指定
target,默认是Mach-0 64-bit object x86_64
clang -x c -g -c a.c -o a.o
* `-x`:指定编译文件语言类型
* `-g`:生成调试信息
* `-c`:生成目标文件,只运行preprocess, compile, assemble,不链接
* `-o`:输出文件
* `-isysroot`: 使用的SDK路径
* `-I<directory>`: 在指定目录寻找头文件,对应Xcode中的`header search path`
* `-L <dir>`: 指定库文件路径(.a\.dy1ib库文件),对应Xcode中的`library search paths`
* `-l<library_name>`: 指定链接的库文件名称(.a\.dylib库文件),对应Xcode中的`other link flags -lAFNetworking`
* `-F<directory>`: 在指定目录寻找framework头文件
* `-framework <framework_name>`在指定链接的framework名称,生成相应的LLVM文件格式,来进行链接时间优化,当我们配合着`-S`使用时,生成汇编语言文件。否则生成`bitcode`格式的目标文件
* `-flto=<value>`设置LTO的模式,它值有`full` or `thin`,默认是`full`
* `-f1to=full`,默认值,单片 (monolithic) LTO通过将所有输入合并到单个模块中来实现此目的
* `-flto=thin`,使用`ThinLTo`代替
* `-emit-llvm` 对汇编程序和目标文件使用 LLVM 表示
* `-install-name` 指定动态库初次安装时的默认路径,向`LC_ID_DYLIB`添加安装路径,该路径作为dyld定位该库。
* `-Xlinker <arg>` 将参数传递链接器
* `-print-target` 打印支持的架构2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
clang 是使用 LLVM 汇编器将源文件转化为目标代码。 clang -o 是将.c源文件编译成为一个可执行的二进制代码,-o 选项其实是指定输出文件文件名,如果不加-c选项,clang默认会编译链接生成可执行文件,文件的名称由 -o选项指定。
- 指定生成
Mach-064-bitx86-64目标文件格式:
clang -x c -target x86_64-apple-macos10.15 -a -c a.c -o a.o- 如果指定 target 不带 apple 系统版本(包括
macosipadosios,真机和模拟器)。例如x86_64,那么生成的目标文件是Liunx的ELF 64-bit
clang -x c -target x86_64 -g -c a.c -o a.o- 编译
.m文件
clang -x objective-c -target x86_64-apple-macos10.15 -fobjc-arc -fmodules -isysroot /Applications/Xcode.app/C
ontents/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/iPho
neOS.platform/Developer/SDKs/iPhoneOS13.6.sdk -c a.c -o a.o2
3
4
5
- 编译
.mm文件- 在mac 上编译
shellclang -x objective-c++ -target x86_64-apple-macos10.15 -std=c++11 -stdlib=libc++ -fobjc-arc -fmodules -isysr oot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -c te st.mm -o test.o1
2
3- 在模拟器上编译
shellclang -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.o1
在模拟器上链接其他三方库:
shellclang -x objective-c -target x86_64-apple-ios13.5-simulator -fobjc-arc -fmodules -isysroot /Applications/Xcod e.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.6.sdk -I/Users/w s/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/i PhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.6.sdk -F/Users/ws/Desktop/᧞ᑕ/Library/դᎱ-ପ -fobjcarc -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/դᎱ-ପ -fobjcarc -lAFNetworking -dead-strip test.o -o test1
2
3
4
5
6
7
8
9
10- 编译成
arm64真机
shellclang -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 test1
2
3- 编译成
- 生成
dsYM文件,-g1: 将调试信息写入DWARF格式文件
clang -x c -g1 a.c -o a.o杳看调试信息
dwartdump 取出并验证 DWARF 格式调试信息
dwarfdump a.o
dwarfdump a.dSYM
dwarfdump --lookup 0x100000f20 --arch=x86_64 a.dSYM
--lookup:查看地址的调试信息。将显示出所在的目录,文件,函数等信息2
3
4
查看文件内容 otool objdump
otool 用来查看Mach-0文件内部结构:
otool -l liba.dylib
otool -h libTest.a
otool -l test | grep 'DYLIB' -A 3 #查看 1oad command,搜索`DYLIB`关键字,往下打印3行
otool -l libTestExample.dylib | grep "ID" -A 5` #查看 1oad command,搜索ID关键字,往下打印5行
-l:显示解析后的`mach header`和`1oad command`
-h:显示未解析的`mach header`
-L:打印所有链接的动态库路径
-D:打印当前动态库的`instal1_name`2
3
4
5
6
7
8
9
objdump用来查看文件内部结构,包括 ELF 和 Mach-0:
objdump --macho -h a.0
objdump --macho -x a.o
objdump --macho -s -d a.o
objdump --macho --syms a.0
--macho:指定Mach-0类型
-h:打印各个段的基本信息
-x:打印各个段更详细的信息
-d:将所有包含指定的段反汇编
-s:将所有段的内容以16进制的方式打印出来
-lazy-bind:打印`lazy binding info`
--syms 打印符号表2
3
4
5
6
7
8
9
10
11
12
静态库的压缩和解压缩
ar压缩目标文件,并对其进行编号和索引,形成静态库。同时也可以解压缩静态库,查看有哪些目标文件
ar -rc a.a a.o
-r:添加or替换文件
-c:不输出任何信息
-t:列出包含的目标文件2
3
4
创建静态库 - libtool
创建库命令:1ibtool。可以创建静态库和动态库:
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
-static: 静态库
-arch_only: 指定架构2
3
4
5
6
创建动态库
- 使用 clang 创建动态库
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- 使用 ld 创建动态库, 先生成静态库,再通过 ld 链接成动态库。
ld -dylib -arch x86_64 \
-macosx_version_min 11.1 \
-syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.sdk \
-lsystem -framework Foundation \
-all_load \
libTestExample.a -o libTestExample2
3
4
5
6
修改动态库路径 install_name_tool
install_name_tool -id /Users/xx/Desktop/aa/dylib/libTestExample.dylib libTestExample.dylib
-id: 修改动态库路径
-add_rpath: 添加相对路径
-rpath old new: 替换路径
-delete_rpath: 删除路径2
3
4
5
6
查看符号表 nm
nm命令:
nm -pa a.o
-a: 显示符号表的所有内容
-g: 显示全局符号
-p: 不排序。显示符号表本来的顺序
-r: 逆转顺序
-u: 显示未定义符号2
3
4
5
6
生成dSYM文件
dsymutil 可以被理解为是调试信息链接器。它按照上面的步骤执行:
- 读取
debug map - 从
.o文件中加载DWARF - 重新定位所有地址
- 最后将全部的
DWARF打包成dSYM Bundle。有了dSYM后,我们就拥有了最标准的DWARF的文件,任何可以dwart读取工具(可以处理Mach-0二进制文件)都可以处理该标准DWARF
dsymutil 操作 DWARF 格式的debug symbol。可以将可执行文件debug symbol 的生成 DWARF 格式的文件:
dsymutil -f a -o a.dSYM
`-f`: .dwarf格式文件
`-o <filename>`:输出 .dSYM 格式文件2
3
移除符号
strip 用来移除和修改符号表:
strip -S a.o
-S 删除调试符号
-X 移除本地符号,“L’开头的
-× 移除全部的本地符号,只保留全局符号2
3
4
链接器 ld
* `-a11_load` 加载静态库的包含的所有文件。
* `-objc` 加载静态库的包含的所有义的Objective-C类和Category .
* `-force_load <path_to_archive>` 加载静态库中指定的文件
* `-dead_strip` 剥离无用的代码
* `-Xlinker -why_live -Xlinker <_方法名>` 这个方法因为什么没有被剥离,方法名前缀_2
3
4
5
- 链接动态库与静态库
ld -dylib -arch x86_64 -macosx_version_min 10.13 a.dylib -o a
ld -static -arch x86_64 -e _main a.a -o a2
3
查看可执行文件代码段 - objdump
objdump --macho -d 可执行文件
Xcode打印加载的库
Pre-main Time指 main 函数执行之前的加载时问,包括 dylib 动态库加载/ Mach-0文件加载, Rebase/BindingObiective-C Runtime 加载等。
Xcode 自身提供了一个在控制台打印这些时间的方法:在Xcode 中Edit Scheme -> Run -> Auguments 添加环境变量DYLD PRINT_ STATISTICS并把其值设为 1
DYLD PRINT_LIBRARIES:打印出所有被加载的库。DYLD_PRINT_LIBRARIES_POST_LAUNCH:打印的是通过dlopen调用返回的库,包括动态库的依赖库,主要发生在main 函数运行之后。
二进制重排
- 链接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.o2
3
4
5
- 生成Link Map 文件
ld -map output.map -lsystem -lc++ -framework Foundation test.o -o output
-map map_file_path 生成map文件。
主要包括三大部分:
Object Files: 生成二进制用到的 `1ink` 单元的路径和文件编号
Sections: 记录 `Mach-O` 每个`Segment/section` 的地址范围
Symbols: 按顺序记录每个符号的地址范围2
3
4
5
6
7
install name tool更改动态共享库的安装名称并操纵运行路径.
install_name_tool -add_rpath <directory> libs_File
install_name_tool -delete_rpath <directory> libs_File
install_name_tool -rpath <old> <new> libs_File2
3
生成目标文件的过程中发生了什么?
编译器 (clang-cl) -> 汇编器 (Ivm-as) 链接器(lvm-ld)并没有被执行 所以输出的目标文件不会包含Unix程序在被装载和执行时所必须的包含信息,但它以后可以被链接到一个程序。
Mach-o File Format
一个Mach-0文件有两部分组成:header 和data。
- header :代表了文件的映射,描述了文件的内容以及文件所有内容所在的位置。
- data:紧跟header之后,由多个二进制组成,
one by one。
header包含三种类型Mach header、segment、 sections。section描述了对应的二进制信息。
注意:Mach header属于header的一部分,它包含了整个文件的信息和segment信息
Segments(segment commands):指定操作系统应该将Segments加载到内存中的 什么位置,以及为该Segments分配的字节数。还指定文件中的哪些字节属于该 Segments, 以及文件包含多少sections。始终是4096字节或4 KB的倍数,其中 4096字节是最小大小。
Section:所有sections都在每个segment之后一个接一个地描述。sections里面定 义其名称,在内存中的地址,大小,文件中section数据的偏移量和seoment名 称。
Load Commands
进制文件加载进内存要执行的一些指令。
这里的指令主要在负责我们 APP 对应进程的创建和基本设置(分配虛拟内存,创建主线程,处理代码签名/加密的工作),然后对动态链接库 (.dylib 系统库和我们自己创建的动态库) 进行库加载和符号解析的工作。