為何需要hook日志:
1.控制臺(tái)輸出的日志太多太雜了,導(dǎo)致看不見(jiàn)關(guān)鍵信息.
2.或者有些輸出的日志search不到源碼,但是需要知道從哪兒調(diào)用的?(比如想知道哪個(gè)第三方庫(kù)調(diào)用的)
哪些方式:
1.控制臺(tái)右下角文本過(guò)濾,這個(gè)就不說(shuō)了....
2.設(shè)置xcode環(huán)境變量 OS_ACTIVITY_MODE 為 Disable,將會(huì)所有l(wèi)og不可見(jiàn),不論系統(tǒng)log還是自行輸出log
3.自定義宏代替NSLog宏
#ifdef _DEBUG
#define DLog(fmt, ...) NSLog((@"[Line %d] " fmt), __LINE__, ##__VA_ARGS__);
#else
#define DLog(...)
#endif
4.還有一些Log可能是在第三方的庫(kù)里面打印的,所以我們無(wú)法采用第三種方式.我們可以采用method_swizzle來(lái)進(jìn)行方法替換,但是NSLog和printf是函數(shù),這時(shí)候就需要用到fishhook來(lái)進(jìn)行函數(shù)實(shí)現(xiàn)替換
原理:
簡(jiǎn)單說(shuō)就是修改系統(tǒng)函數(shù)地址(自定義函數(shù)不可hook),達(dá)到函數(shù)實(shí)現(xiàn)交換的目的.詳見(jiàn)https://github.com/facebook/fishhook
用法
A.替換nslog
static void (*orig_nslog)(NSString *format, ...);
void my_nslog(NSString *format, ...) {
va_list vl;
va_start(vl, format);
NSString *str = [[NSString alloc] initWithFormat:format arguments:vl];
va_end(vl);
//此處類(lèi)似method_swizzle
orig_nslog([NSString stringWithFormat:@"test - %@",str]);
}
//啟動(dòng)后執(zhí)行下面這句話(huà)即可實(shí)現(xiàn)NSLog() hook
struct rebinding nslog_rebinding = {"NSLog",my_nslog,(void*)&orig_nslog};
//1代表后面有一個(gè)函數(shù)實(shí)現(xiàn)需要重新綁定
rebind_symbols((struct rebinding[1]){nslog_rebinding}, 1);
以下為hook之后的log
B.替換NSLogv,有些極少的情況,可能還需要hook NSLogv()
static void (*orig_nslogv)(NSString *format,va_list args);
void my_nslogv(NSString *format,va_list args) {
orig_nslogv(format,args);
}
struct rebinding nslogv_rebinding = {"NSLogv",my_nslogv,(void*)&orig_nslogv};
rebind_symbols((struct rebinding[1]){nslogv_rebinding}, 1);
C.替換printf
static void (*orig_printf)(const char *path, ...);
void my_printf(const char *path,...) {
orig_printf(path);
}
struct rebinding printf_rebinding = {"printf",my_printf,(void*)&orig_printf};
rebind_symbols((struct rebinding[1]){printf_rebinding}, 1);
hook效果如下
通過(guò)以上方式可以在hook住的時(shí)候看見(jiàn)左邊的調(diào)用堆棧信息,也許有一些幫助