deadcode strip - ShenYj/ShenYj.github.io GitHub Wiki
-
死代码剥离,
clang
在链接过程中deadcode strip
默认就是生效的 -
dead_strip
-dead_strip Remove functions and data that are unreachable by the entry point or exported symbols.
动态库中使用
-mark_dead_strippable_dylib
参数-mark_dead_strippable_dylib Specifies that the dylib being built can be dead strip by any client. That is, the dylib has no initialization side effects. So if a client links against the dylib, but never uses any symbol from it, the linker can optimize away the use of the dylib.
如果并没有使用到该动态库的符号信息,那么链接器将会自动优化该动态库。不会因为路径问题崩溃。 同时,也可以在 App 中使用
-dead_strip_dylibs
获得相同的功能 -
区分于
Other Linker Flags (OTHER_LDFLAGS)
,Other Linker Flags (OTHER_LDFLAGS)
是仅限于静态库的
简单来讲,就是移除入口函数或者没有被导出符号使用到的函数或者代码。
dead_strip
与其他链接参数对比
-
准备
test.m
文件-
定义了全局函数:
global_function()
从符号角度讲是导出符号 -
定义了静态函数:
static_function()
从符号角度讲是本地符号 -
没有使用
global_function()
全局函数#import <Foundation/Foundation.h> // 全局符号 导出符号 void global_function() { } // 本地符号 static void static_function() { } int main() { // global_function(); NSLog(@"testApp ------"); return 0; }
-
-
脚本生成可执行文件, 并查看
__TEXT
, 对比-dead_strip
作用-
加上
-dead_strip
SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk # 链接OCTest到test.m中生成.o文件 clang -x objective-c \ -target x86_64-apple-macos11.1 \ -fobjc-arc \ -isysroot $SYSROOT \ -I./OCStaticLib \ -c test.m \ -o test.o # 将.o生成执行文件 clang -target x86_64-apple-macos11.1 \ -fobjc-arc \ -isysroot $SYSROOT \ -Xlinker -dead_strip \ -L./OCStaticLib \ -lOCTest \ test.o -o test
test: (__TEXT,__text) section _main: 100003f50: 55 pushq %rbp 100003f51: 48 89 e5 movq %rsp, %rbp 100003f54: 48 83 ec 10 subq $16, %rsp 100003f58: 48 8d 05 a9 00 00 00 leaq 169(%rip), %rax ## Objc cfstring ref: @"testApp ------" 100003f5f: c7 45 fc 00 00 00 00 movl $0, -4(%rbp) 100003f66: 48 89 c7 movq %rax, %rdi 100003f69: b0 00 movb $0, %al 100003f6b: e8 08 00 00 00 callq 0x100003f78 ## symbol stub for: _NSLog 100003f70: 31 c0 xorl %eax, %eax 100003f72: 48 83 c4 10 addq $16, %rsp 100003f76: 5d popq %rbp 100003f77: c3 retq
-
不加
-dead_strip
SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk # 链接OCTest到test.m中生成.o文件 clang -x objective-c \ -target x86_64-apple-macos11.1 \ -fobjc-arc \ -isysroot $SYSROOT \ -I./OCStaticLib \ -c test.m \ -o test.o # 将.o生成执行文件 clang -target x86_64-apple-macos11.1 \ -fobjc-arc \ -isysroot $SYSROOT \ -L./OCStaticLib \ -lOCTest \ test.o -o test
test: (__TEXT,__text) section _global_function: 100003f40: 55 pushq %rbp 100003f41: 48 89 e5 movq %rsp, %rbp 100003f44: 5d popq %rbp 100003f45: c3 retq 100003f46: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:(%rax,%rax) _main: 100003f50: 55 pushq %rbp 100003f51: 48 89 e5 movq %rsp, %rbp 100003f54: 48 83 ec 10 subq $16, %rsp 100003f58: 48 8d 05 a9 00 00 00 leaq 169(%rip), %rax ## Objc cfstring ref: @"testApp ------" 100003f5f: c7 45 fc 00 00 00 00 movl $0, -4(%rbp) 100003f66: 48 89 c7 movq %rax, %rdi 100003f69: b0 00 movb $0, %al 100003f6b: e8 08 00 00 00 callq 0x100003f78 ## symbol stub for: _NSLog 100003f70: 31 c0 xorl %eax, %eax 100003f72: 48 83 c4 10 addq $16, %rsp 100003f76: 5d popq %rbp 100003f77: c3 retq
-
查看 Mach-O参考: 三、查看Mach-O文件的机器指令(__TEXT)
在没有使用global_function()
全局函数情况下, 增加了-dead_strip
参数后, 被优化掉了
-
满足两个条件
- 没有被入口点使用
- 没有被导出符号使用
-
准备代码
#import <Foundation/Foundation.h> #import "OCTest.h" int main() { OCTest *oc = [OCTest new]; [oc test:nil]; NSLog(@"testApp ------"); return 0; }
-
脚本
SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk # 链接OCTest到test.m中生成.o文件 clang -x objective-c \ -target x86_64-apple-macos11.1 \ -fobjc-arc \ -isysroot $SYSROOT \ -I./OCStaticLib \ -c test.m \ -o test.o # 将.o生成执行文件 clang -target x86_64-apple-macos11.1 \ -fobjc-arc \ -isysroot $SYSROOT \ -Xlinker -dead_strip \ -Xlinker -all_load \ -L./OCStaticLib \ -lOCTest \ test.o -o test
在链接过程中默认参数
noall_load
, 避免Other Linker Flags
将代码剥离掉, 所以设置为all_load
, 来观察dead_strip
的作用效果 -
查看
__TEXT
test: (__TEXT,__text) section -[OCTest test:]: 100003470: 55 pushq %rbp 100003471: 48 89 e5 movq %rsp, %rbp 100003474: 48 83 ec 20 subq $32, %rsp 100003478: 48 89 7d f8 movq %rdi, -8(%rbp) 10000347c: 48 89 75 f0 movq %rsi, -16(%rbp) 100003480: 48 c7 45 e8 00 00 00 00 movq $0, -24(%rbp) 100003488: 48 8d 7d e8 leaq -24(%rbp), %rdi 10000348c: 48 89 d6 movq %rdx, %rsi 10000348f: e8 28 09 00 00 callq 0x100003dbc ## symbol stub for: _objc_storeStrong 100003494: 48 8d 05 75 0b 00 00 leaq 2933(%rip), %rax ## Objc cfstring ref: @"__TestExample" 10000349b: 48 89 c7 movq %rax, %rdi 10000349e: b0 00 movb $0, %al 1000034a0: e8 0b 09 00 00 callq 0x100003db0 ## symbol stub for: _NSLog 1000034a5: 31 c9 xorl %ecx, %ecx 1000034a7: 89 ce movl %ecx, %esi 1000034a9: 48 8d 7d e8 leaq -24(%rbp), %rdi 1000034ad: e8 0a 09 00 00 callq 0x100003dbc ## symbol stub for: _objc_storeStrong 1000034b2: 48 83 c4 20 addq $32, %rsp 1000034b6: 5d popq %rbp ... 省略
在
OC
中即便没有使用, 静态库中的符号也不会被剥离掉, 因为OC
是动态语言
虽然
dead strip
不会干掉oc
中的未使用符号,但是Other Linker Flags
默认可是noall_load
, 有可能被noall_load
给优化掉,这也是我们使用framework
静态库时为何需要配置-ObjC
查看符号为何没有被 dead strip
在链接的时候添加 why_live
参数
格式: -Xlinker -why_live -Xliner 符号
e.g.
# 将.o生成执行文件
clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot $SYSROOT \
-Xlinker -dead_strip \
-Xlinker -all_load \
-Xlinker -why_live -Xliner _global_function \
-L./OCStaticLib \
-lOCTest \
test.o -o test
终端在执行完链接后就会显示该符号被哪个函数,哪个 .o
所使用
_global_function from test.o
_main from test.o
_main from test.o