スタートの最適化 - バイナリリメイク
IOSのシステムは、仮想および物理メモリページングなり、物理メモリへのマッピング仮想メモリページの最小単位です。
スタート:
我々はAPPの開始について話しているときに表示される最初のページから開始するには、アイコンをクリックしてください。
コールドスタート:
プログラム完全に(場合によっては、プロセスを強制終了した後、他の多くのAPPを開け、今回のプログラムが物理メモリに対応する物理メモリ、仮想メモリから再ロードされる別のプログラムのニーズによって使用されている)、または最初のインストールの開始(最初のインストールまたはアンインストール後、重機など)。
ホットスタート:
別の開始に続いて、プログラムを、殺した後、まだ我々のデータを保持している対応する物理メモリへのこの時間は、仮想メモリから完全な再読み込みを必要としません。
プログラムが仮想メモリから物理メモリへの負荷がロードされたページングされ、開始します。データは、仮想メモリのページ(iOSの16キロバイト)してページを保存しています。物理メモリが、我々は負荷に必要なものではないときに、プログラムを起動する場合は、仮想メモリのページフォールトをリロードします。より多くの場合より少なく、その認識が、出てこない場合、それは、起動速度に影響を与えます。
楽器
Xcodeのデバッグツールが付属しています。開くにはXcodeのコマンド+ Iを開き
、多くのシステムトレースを使用してここにありますデバッグツールを
単にここで、各スレッド内のデータを参照するために、ダブルクリックして開きます、ここでスレッドは見る必要が仮想メモリであり、
デモは、最初の空のプロジェクトを作成し、その後、携帯電話に実行し、その後、IPAのインストールを変更するには、IPAの署名を再インストールし、目的は、携帯電話のIPAをインストールするには、記述ファイルを追加することです。プロファイルがすでに携帯電話にインストールされて存在し、それが直接コマンド+ Rに可能です
デバッグを通じ、最初に開いた(コールドスタート)たくさんのファイルをロードしていますが、ロードされてはるかに少ないでしょう再起動(ウォームスタート)を指示し、プログラムを強制終了する場合。この後、我々は仮想メモリをロードする必要がないときに再び開始するために、物理メモリ、物理メモリにロードされていることを知って、それがすぐに開始します。プログラムを殺すために時間が、その後、他の開いているプログラムの多くがある場合は、我々は再びプログラムを開いて、それがコールドスタートであることがわかります。あなたが別のアプリケーションの実行により、使用中の物理メモリを分析することができます前にロード。
物理メモリの仮想メモリ、仮想メモリは、連続しているコネクタを介して対応する物理メモリに対応し、対応する物理メモリが固定されていない状況下では、開かれたスペアメモリ、または対応する番号を上書きするには、noアイドル時間を見つけることですメモリ。
ファイル担保ページにロードされたデータは、ファイルが1を占めていない、1は16キロバイトで、エネルギーの多くを置きます。
バイナリ並べ替え
なぜバイナリ再配置、プログラムが順番に実行されるため。
たとえば:
246が負荷に開始された今、仮想メモリ6、123 456、135はロードを開始する必要はありません。しかし、実行順序が6つの完全にロードされた内側にあります。並び替えバイナリオブジェクトは、他の内容のロードを開始してから数ページの実行順序を上に移動するページに246枚のニーズです。
バイナリ再配置は、これらのシンボルが再配置され、スタートシンボル系列を知ることは困難です。
Xcodeは設定可能です。彼はコネクタが長く、シンボルのパックXcodeの時間シーケンスがファイル内にパッケージ化されますへの書き込み、-order_file内部で使用されているldのXcodeの。
どのようにブートシーケンスを確認するには
、1シーケンスファイルの
ビルドフェーズを- >実行順序内のコンパイルソース・ファイルは、オーダー(調整可能)で
修飾法のないファイルの再配列は、道のため、機能を決定していない場合。B前ページにページを、方法Aは、B法の前に実行されます。
図2に示すように、シンボル・テーブル・オーダー。
ビルド設定- >リンクマップファイルを書く - > YES 自動的にシンボルテーブル生成
翻訳が完了した後にコンパイルされ、このリンクマップに書き込まれます。
そして、開いているビューの
Xcodeの製品の展示- > filedome.app - >右ショーでファインダー- >二つのディレクトリ(および同様の製品は)Intermediates.noindexを発見したまで- > filedome.build - >デバッグ- iphoneos - > filedome.build - > filedome -LinkMap-通常arm64.txt(の.textファイルの末尾にこれを見つけます。)
図4に示すように、シンボルは
方法のいくつかの.o、機能、等シンボルファイル名に属する(16進数)多くのスペースを取る位置(アドレスコード)を開始します
# Address Size File Name
0x1000051C8 0x00000098 [ 1] +[LJLWeakProxy proxyWithTarget:]
0x100005260 0x0000006C [ 1] -[LJLWeakProxy methodSignatureForSelector:]
0x1000052CC 0x0000009C [ 1] -[LJLWeakProxy forwardInvocation:]
0x100005368 0x00000034 [ 1] -[LJLWeakProxy target]
0x10000539C 0x00000048 [ 1] -[LJLWeakProxy setTarget:]
0x1000053E4 0x0000003C [ 1] -[LJLWeakProxy .cxx_destruct]
0x100005420 0x000000E0 [ 2] -[LJLGCDTwoViewController viewDidLoad]
0x100005500 0x00000014 [ 2] -[LJLGCDTwoViewController createGroup]
0x100005514 0x000000C4 [ 2] -[LJLGCDTwoViewController groupRest1]
0x1000055D8 0x0000003C [ 2] ___37-[LJLGCDTwoViewController groupRest1]_block_invoke
0x100005614 0x0000003C [ 2] ___37-[LJLGCDTwoViewController groupRest1]_block_invoke_2
0x100005650 0x0000002C [ 2] ___37-[LJLGCDTwoViewController groupRest1]_block_invoke_3
0x10000567C 0x000001A0 [ 2] -[LJLGCDTwoViewController groupRest2]
0x10000581C 0x00000054 [ 2] ___37-[LJLGCDTwoViewController groupRest2]_block_invoke
バイナリ並べ替え開始
1. .ORDER作成し
、プロジェクトのルートディレクトリを開き、入力するターミナル:タッチliujilou.orderを入力します。liujilou.orderを生成するためのルートディレクトリにあるファイル(自分の状況プロジェクトに従って命名)。
2、Xcodeの設定
ビルド- >設定- >注文ファイル (./liujilou.order 相対パスでのルートディレクトリにあります)
@implementation ViewController
//随便写一些代码
//函数
void test()
{
block1();
}
void(^block1)(void) = ^(void){
};
......
//例如 :编辑 liujilou.order
_main
-[LJLWeakProxy setTarget:]
-[LJLWeakProxy .cxx_destruct]
-[liujilou hello]
その後、コンパイラのコマンド+ Bキャッシュに関するコマンド+ Kをクリア、
# Symbols:
# Address Size File Name
0x1000051C8 0x000000A4 [ 11] _main
0x10000526C 0x00000048 [ 1] -[LJLWeakProxy setTarget:]
0x1000052B4 0x0000003C [ 1] -[LJLWeakProxy .cxx_destruct]
0x1000052F0 0x00000098 [ 1] +[LJLWeakProxy proxyWithTarget:]
0x100005388 0x0000006C [ 1] -[LJLWeakProxy methodSignatureForSelector:]
0x1000053F4 0x0000009C [ 1] -[LJLWeakProxy forwardInvocation:]
0x100005490 0x00000034 [ 1] -[LJLWeakProxy target]
0x1000054C4 0x000000E0 [ 2] -[LJLGCDTwoViewController viewDidLoad]
0x1000055A4 0x00000014 [ 2] -[LJLGCDTwoViewController createGroup]
0x1000055B8 0x000000C4 [ 2] -[LJLGCDTwoViewController groupRest1]
0x10000567C 0x0000003C [ 2] ___37-[LJLGCDTwoViewController
以上の結果を対比し、我々は今我々が.ORDER編集したもののブートシーケンスの順序を確認することができます
_main
-[LJLWeakProxy setTarget:]
-[LJLWeakProxy .cxx_destruct]
私たちのプロジェクトの一つとエラーが無視されることはありません、私たちは順番に書かれている場合でも、このメソッドを持っていません。だから、間違った状況を心配し、問題が発生しません。
-[liujilou hello]
拡張:
シンボル他の方法は、(アドレスの並び順に応じて完全に、緩んでいない)NM参照
ターミナル。
//打开自己APP 目录,并不是让输入 ../
cd ... /filedome.app
nm filedome
nm -p filedome 书序排列,但是也不是完全按照启动顺序排列的
nm -u filedome 只看系统的方法等
nm -U filedome 只看自定义的方法等
それはまだ、リンク・マップの対象となるので、それは、許可されていません。
真のバイナリの再配置を実現するために、我々はすべてのメソッド、関数やその他の記号を始めるために、と順番保存し、ファイルがバイナリ再配置を達成するために書かれている必要があります。記事ビブラートが、それはそれを見るために、すべての特定の記事をフックしません。
ビブラートの研究開発実践:ベースのソリューションは、APP速度バイナリを起動するには、15%以上向上させるために再配置され
、そのアイデアの:
)このシステムの機能をすべてOCプロセスは、(objc_msgsend行くだろうし、あなたは釣り針フックobjc_msgSend()あなたが得ることができると行くことができます[すべてのOCメソッド呼び出し、およびobjc_msgsendから、この内部をフックは、()は、第2のパラメータ(SEL)は、すべてのシンボルを得ました。
しかし、この1は関係していobjc_msgSend()は変数のパラメータであるため、ピットである、唯一のスタックレジスタを介してバランスを維持するためにアセンブラを書くことができます。あなたがこの中で深い探求することができない、と釣り針について学ぶためにコンパイルされたiOSラムがわからない場合。
そして、このような初期化できませんフック
よりも部分ブロックフック
C ++間接的な関数呼び出しの静的スキャンレジスタを介して出てきません。
あなたは90%に80%を転位することができます。これは推奨されていない場合は100%を必要としています。
私は完全に私たちが使用しているすべてのシンボルにフックしたいです
打ち鳴らす計装
これは、コード・カバレッジ・ツールは、翻訳
の中で、すべてのカスタムプロジェクトのためのコードを検出することが可能です。
1.設定の
ビルド設定- >その他Cフラグを追加します。
-fsanitize-coverage=trace-pc-guard
その後、コンパイルエラー(未定義のシンボルが、私たちはそのいくつかのポイント必見のシステムコールでこれらええ、それだけのショーでプロジェクトを配るません)します。
Undefined symbol: ___sanitizer_cov_trace_pc_guard_init
Undefined symbol: ___sanitizer_cov_trace_pc_guard
あなたはすべてのメソッドにデフォルト___sanitizer_cov_trace_pc_guardで追加さ-fsanitizeカバレッジ=トレース-PC-ガードを追加したためです。文書のルック打ち鳴らします。プロジェクトにこれらの二つの機能を検索します。
extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
uint32_t *stop) {
static uint64_t N; // Counter for the guards.
if (start == stop || *start) return; // Initialize only once.
printf("INIT: %p %p\n", start, stop);
for (uint32_t *x = start; x < stop; x++)
*x = ++N; // Guards should start from 1.
}
extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
if (!*guard) return; // Duplicate the guard check.
// If you set *guard to 0 this code will not be called again for this edge.
// Now you can get the PC and do whatever you want:
// store it somewhere or symbolize it and print right away.
// The values of `*guard` are as you set them in
// __sanitizer_cov_trace_pc_guard_init and so you can make them consecutive
// and use them to dereference an array or a bit vector.
void *PC = __builtin_return_address(0);
char PcDescr[1024];
// This function is a part of the sanitizer run-time.
// To use it, link with AddressSanitizer or other sanitizer.
__sanitizer_symbolize_pc(PC, "%p %F %L", PcDescr, sizeof(PcDescr));
printf("guard: %p %x PC %s\n", guard, *guard, PcDescr);
}
もちろん__sanitizer_symbolize_pc()がエラーした後、重要な最初のコメントを継続していきます。
さて、このプロジェクトを開始し、起動が完了した後に一時停止します。そして、それを印刷
INIT: 0x1029135e8 0x102913e70
......
(lldb) x 0x1029135e8
0x1029135e8: 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................
0x1029135f8: 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 ................
(lldb) x 0x102913e70
0x102913e70: 98 cb 90 02 01 00 00 00 00 00 00 00 00 00 00 00 ................
0x102913e80: ca 98 90 02 01 00 00 00 00 00 00 00 00 00 00 00 ................
(lldb) x 0x102913e70-0x4
0x102913e6c: 22 02 00 00 98 cb 90 02 01 00 00 00 00 00 00 00 "...............
0x102913e7c: 00 00 00 00 ca 98 90 02 01 00 00 00 00 00 00 00 ................
最後の印刷が終了位置であり、ディスプレイは、4で4であるので、前進4を移動させる、最後のものでなければならないプリントアウト。
リトルエンディアンモード2202万は、16進数222ブートローダー546進表記です。
ViewControllerをプラスloadメソッドでは(必ずしも主にこれは私がシンボルの数をプリントアウト推測起動しないかどうかを確認するために、負荷、負荷への負荷が始まりである必要はありません)
INIT: 0x10286b610 0x10286be9c
......
(lldb) x 0x10286b610
0x10286b610: 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................
0x10286b620: 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 ................
(lldb) x 0x10286be9c
0x10286be9c: 00 00 00 00 98 4b 86 02 01 00 00 00 00 00 00 00 .....K..........
0x10286beac: 00 00 00 00 c7 18 86 02 01 00 00 00 00 00 00 00 ................
(lldb) x 0x10286be9c-0x4
0x10286be98: 23 02 00 00 00 00 00 00 98 4b 86 02 01 00 00 00 #........K......
0x10286bea8: 00 00 00 00 00 00 00 00 c7 18 86 02 01 00 00 00 ................
ディスカバリーは変更され、現在のものより2302万以上でました。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
test();
}
+ (void)initialize
{
}
void(^block)(void) = ^(void) {
};
void test(){
block();
}
3回を印刷するには、画面上のポイント。
guard: 0x10de29ae0 f5 PC (\3041
guard: 0x10de29ae4 f6 PC \211\352:
guard: 0x10de29ae8 f7 PC 0/\337\341\376
使用して、ブロックを初期化し、関数が増加しますので、この方法は、すべてのシンボルをフックすることができるかもしれません。
その後、ビューをコンパイル
filedome`-[ViewController touchesBegan:withEvent:]:
.....
0x10214cca4 <+40>: bl 0x10214ce44 ; __sanitizer_cov_trace_pc_guard at ViewController.m:117
0x10214cca8 <+44>: ldr x8, [sp, #0x28]
BLコンパイル手段は、アドレス0x10214ce44にジャンプする命令をジャンプ
;セミコロンは説明コメント注釈コンテンツはコンパイルViewController.mで117 __sanitizer_cov_trace_pc_guardの最初の行のアドレスであるものとします
filedome`test:
-> 0x100df0d2c <+0>: stp x29, x30, [sp, #-0x10]!
0x100df0d30 <+4>: mov x29, sp
0x100df0d34 <+8>: adrp x8, 23
0x100df0d38 <+12>: add x0, x8, #0x9d8 ; =0x9d8
0x100df0d3c <+16>: bl 0x100df0e44 ; __sanitizer_cov_trace_pc_guard at ViewController.m:117
filedome`block1_block_invoke:
0x102becd60 <+0>: sub sp, sp, #0x30 ; =0x30
0x102becd64 <+4>: stp x29, x30, [sp, #0x20]
0x102becd68 <+8>: add x29, sp, #0x20 ; =0x20
0x102becd6c <+12>: adrp x8, 23
0x102becd70 <+16>: add x8, x8, #0x9dc ; =0x9dc
0x102becd74 <+20>: str x0, [sp, #0x8]
0x102becd78 <+24>: mov x0, x8
0x102becd7c <+28>: bl 0x102bece44 ; __sanitizer_cov_trace_pc_guard at ViewController.m:117
テストブロックでは、ブレークポイントでマークされ、その後、一つ一つを失い、__sanitizer_cov_trace_pc_guardまでのすべてのジャンプを発見しました。
私たちが配置された打ち鳴らすようなコードは、オーバーレイに挿入されています。メソッド、関数、コードの先頭行に含まれる内部ブロックで、静的で計装。挿入のエッジでコード、新たな行動フックの行を挿入することです。
大要のアドレスを決定するには、次の関数のアドレスを関数が実行されたときに実行されるように保存されますときX30レジスタへの完全復帰。
#import "ViewController.h"
#import <dlfcn.h>
#import <libkern/OSAtomic.h>
#import "filedome-Swift.h"
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
uint32_t *stop) {
static uint64_t N; // Counter for the guards.
if (start == stop || *start) return; // Initialize only once.
printf("INIT: %p %p\n", start, stop);
for (uint32_t *x = start; x < stop; x++)
*x = ++N; // Guards should start from 1.
}
シンボルのすべてを取得するために保存する必要が後が、子スレッドであり、実行することができるので、配列を使用することはできませんので、配列に問題があるでしょう
//原子队列 1、先进后出 2、线程安全 3、只能保存结构体
static OSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT;
//定义符号结构体
typedef struct {
void *pc;
void *next;//下一个数据的结构体指针地址
}SYNode;
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
// if (!*guard) return; // Duplicate the guard check.
// 汇编一个函数执行完返回会将下一个要执行的函数地址给保存到 x30 寄存器中,将返回值给下一个函数。
// 所以这个函数的命名就是 返回 内存地址。 这里PC 就是拿到的内存地址
void *PC = __builtin_return_address(0);
SYNode * node = malloc(sizeof(SYNode));
*node = (SYNode){PC,NULL};
// 进入 入栈
// 最后一个参数是下一个数据的位置,也就是往上边的*node 的第二位插入
// offsetof(SYNode, next) next 成员在 结构体 SYNode 中的偏移值
OSAtomicEnqueue(&symbolList, node, offsetof(SYNode, next));
// dlopen 通过动态库拿到句柄 通过句柄拿到函数的内存地址
// dladdr 通过函数内存地址拿到函数
// typedef struct dl_info {
// const char *dli_fname; /* Pathname of shared object 函数的路径 */
// void *dli_fbase; /* Base address of shared object 函数的地址 */
// const char *dli_sname; /* Name of nearest symbol 函数符号 */
// void *dli_saddr; /* Address of nearest symbol 函数起始地址 */
// } Dl_info;
// Dl_info info;
// dladdr(PC, &info);
// printf("fnam:%s \n fbase:%p \n sname:%s \n saddr:%p \n",
// info.dli_fname,
// info.dli_fbase,
// info.dli_sname,
// info.dli_saddr);
//fnam:/Users/liujilou/Library/Developer/CoreSimulator/Devices/F8857F80-4697-496A-8FE8-255DA2056C17/data/Containers/Bundle/Application/B57CF494-5D7D-4044-87B4-949E971BD39D/filedome.app/filedome
//fbase:0x108a1d000
//sname:-[LGPerson setNum:]
//saddr:0x108a27ff0
// 拿到了全部的符号之后需要保存,但是不能用数组,因为有可能会有在子线程执行的,所以用数组会有问题
// 用原子队列 #import <libkern/OSAtomic.h>
}
貯蔵の完了後に除去横断し、次に注文シンボルテーブルファイルを編集するために必要。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSMutableArray <NSString *>* symbolNames = [NSMutableArray array];
while (YES) {
SYNode * node = OSAtomicDequeue(&symbolList, offsetof(SYNode, next));
if (node == NULL) {
break;
}
Dl_info info;
dladdr(node->pc, &info);
NSString * name = @(info.dli_sname);
BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["];
NSString * symbolName = isObjc? name : [@"_" stringByAppendingString:name];//c函数前面带下划线
[symbolNames addObject:symbolName];
printf("%s \n",info.dli_sname);
}
// symbolNames = [[symbolNames reverseObjectEnumerator] allObjects];//取反
NSEnumerator * emt = [symbolNames reverseObjectEnumerator];
NSMutableArray<NSString*>* funcs = [NSMutableArray arrayWithCapacity:symbolNames.count];
NSString * name;
while (name = [emt nextObject]) {
if (![funcs containsObject:name]) {
[funcs addObject:name];
}
}
// 删掉当前方法(因为这个点击方法不是必须的)
[funcs removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];
NSString * funcStr = [funcs componentsJoinedByString:@"\n"];
NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"liujilou.order"];
NSData * fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
// 在路径上创建文件
[[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];
NSLog(@"%@",filePath);
// 1、压栈先进后出
// 2、获取的符号会有重复
// 3、load 的首位是0,所以要把if (!*guard) return; 注释掉。由此可以知道如果我们想过来某些函数,可以类似这样操作
}
この場所には穴があります
ダイレクト一方(YES){}無限ループになり、それが印刷されています
-[ViewController touchesBegan:withEvent:]
-[ViewController touchesBegan:withEvent:]
......
アセンブラビューを見ることでポイントを破る、あなたは見つけるでしょう
- [ViewControllerをtouchesBegan:withEventは:] : コール三回
__sanitizer_cov_trace_pc_guard
CBNZ×8、
これは私たちのwhileループ、トリガ__sanitizer_cov_trace_pc_guardです。
あなたが休憩bを持っている場合は、コードが先頭に継続していない場合は、飛び出します。
サイクルが来る
(offsetofは&symbolList、ノード、OSAtomicEnqueue )次に、(SYNode)を、
添加
SYNode *ノード= OSAtomicDequeue(&symbolList )、次に、offsetofは(SYNode);
少なくとも一つ、及びその後に入るプラス1なり取り出しを、内少なくとも一つを除去しました。それはサイクルとなっています。
ソリューションのビルド- >設定- >その他Cフラグは
、-カバレッジを-fsanitize =トレース-PC-ガードプラスFUNC
-fsanitize-coverage=func,trace-pc-guard
printf();呼び出しはこれにジャンプするつもりはない()メソッドは、社内のprintfではないので、それがあります。社内プラスメソッド内のみ
これは、プログラムを実行することによって、コンパイラを可能にし、画面をクリックしてサンドボックス内のliujilou.orderファイルを生成します。今すぐファイルをエクスポートし、プロジェクトliujilou.orderプロジェクトの前にファイルを交換しました。
実機Xcodeのアプリのサンドボックスのコンテンツを参照してください
メニュー開くためにウィンドウ- >デバイスやシミュレータを(ショートカットはShift +コマンド+ 2)
選択したデバイスに接続されている実機で
代替的に、再コンパイルコマンド+ Bの終了後シーケンスを見てみること
# Symbols:
# Address Size File Name
0x100005710 0x000000C8 [ 11] _main
0x1000057D8 0x00000058 [ 23] -[AppDelegate window]
0x100005830 0x00000070 [ 23] -[AppDelegate setWindow:]
0x1000058A0 0x000001A0 [ 23] -[AppDelegate application:didFinishLaunchingWithOptions:]
0x100005A40 0x00000090 [ 10] -[ViewController .cxx_destruct]
0x100005AD0 0x0000066C [ 10] -[ViewController viewDidLoad]
0x10000613C 0x00000070 [ 10] -[ViewController setDataArr:]
0x1000061AC 0x00000068 [ 12] -[LGPerson setNum:]
0x100006214 0x00000068 [ 12] -[LGPerson setHeight:]
0x10000627C 0x00000068 [ 12] -[LGPerson setAge:]
0x1000062E4 0x00000074 [ 23] -[AppDelegate applicationDidBecomeActive:]
転位が完了している、我々は、シーケンス開始
迅速わずかに異なる設定を
増やすドームSWIFTコード以下、テストのために。
// SwiftTest.swift
// filedome
//import Foundation
import UIKit
//简单点用UIKit
class SwiftTest: NSObject {
@objc class public func swiftTestLoad(){
print("swiftTest");
}
}
ViewControllerをインポートヘッダーファイルとそれを呼び出します
#import "filedome-Swift.h"
- (void)viewDidLoad {
[SwiftTest swiftTestLoad];
}
ビルド設定 - >その他スウィフトフラグ(必要なプロジェクトは、人が検索よりも小さいかどうか、SWIFTコードを持っています)
-sanitize-coverage=func
-sanitize=undefined
プリントルックプリントラン
-[ViewController touchesBegan:withEvent:]
-[AppDelegate applicationDidBecomeActive:]
-[AppDelegate window]
// 下面的这4个就是swift 的
$ss5print_9separator10terminatoryypd_S2StFfA1_
$ss5print_9separator10terminatoryypd_S2StFfA0_
$s8filedome9SwiftTestC05swiftC4LoadyyFZ
$s8filedome9SwiftTestC05swiftC4LoadyyFZTo
-[LGPerson setAge:]
-[LGPerson setHeight:]
バイナリ重みの最後の行の後、注文ファイル、リンクマップの構成を生成します。弊社のバイナリ並べ替え並べ替えが完了した場合でも、この時間、この時間の必要性その他のCフラグ/その他スウィフトフラグの設定を削除し、この設定は自動的に我々のコードにジャンプ実行__sanitizer_cov_trace_pc_guardが挿入されているので。ヘビーエンド行が必要とされていない、除去する必要があります。
同時に__sanitizer_cov_trace_pc_guardにおける当社のViewControllerでもを取り除きたいです。
最適化された結果:
非常に明白ではありませんが、主な目的は、プロジェクトが、バイナリ並べ替えを見てする必要がある場合には、非常に大きなありながら、これ以上のスペースを最適化することはできないがある場合、プロジェクトが最適化された最適化することです。