KSCrash源码阅读(Monitors)

前言


版本:1.15.18

这一篇主要介绍如何捕获异常的,由于KSCrash做了反调试,阅读起来有点麻烦,只能一步一步的阅读源码来探寻原理


Monitors

这个目录下面对crash的类型进行了分类处理,挑几个重点的来看


  1. KSCrashMonitor_NSException
    #import "KSCrash.h"
    #import "KSCrashMonitor_NSException.h"
    #import "KSStackCursor_Backtrace.h"
    #include "KSCrashMonitorContext.h"
    #include "KSID.h"
    #include "KSThread.h"
    #import <Foundation/Foundation.h>
    
    //#define KSLogger_LocalLevel TRACE
    #import "KSLogger.h"
    
    
    // ============================================================================
    #pragma mark - Globals -
    // ============================================================================
    
    static volatile bool g_isEnabled = 0;
    
    static KSCrash_MonitorContext g_monitorContext;
    
    /** The exception handler that was in place before we installed ours. */
    static NSUncaughtExceptionHandler* g_previousUncaughtExceptionHandler;
    
    
    // ============================================================================
    #pragma mark - Callbacks -
    // ============================================================================
    
    /** Our custom excepetion handler.
     * Fetch the stack trace from the exception and write a report.
     *
     * @param exception The exception that was raised.
     */
    /*  捕获到crash之后
     1.暂停所有线程 保护现场
     2.获取堆栈
     3.保存信息(符号化之后)
     4.唤醒线程
     5.将crash抛给原先的处理函数
     */
    static void handleException(NSException* exception, BOOL currentSnapshotUserReported) {
        KSLOG_DEBUG(@"Trapped exception11111 %@", exception);
        
        if(g_isEnabled)
        {
            
            ksmc_suspendEnvironment();
            kscm_notifyFatalExceptionCaptured(false);
    
            KSLOG_DEBUG(@"Filling out context.");
            NSArray* addresses = [exception callStackReturnAddresses];
            NSUInteger numFrames = addresses.count;
            uintptr_t* callstack = malloc(numFrames * sizeof(*callstack));
            for(NSUInteger i = 0; i < numFrames; i++)
            {
                callstack[i] = (uintptr_t)[addresses[i] unsignedLongLongValue];
            }
    
            char eventID[37];
            ksid_generate(eventID);
            KSMC_NEW_CONTEXT(machineContext);
            ksmc_getContextForThread(ksthread_self(), machineContext, true);
            KSStackCursor cursor;
            kssc_initWithBacktrace(&cursor, callstack, (int)numFrames, 0);
    
            KSCrash_MonitorContext* crashContext = &g_monitorContext;
            memset(crashContext, 0, sizeof(*crashContext));
            crashContext->crashType = KSCrashMonitorTypeNSException;
            crashContext->eventID = eventID;
            crashContext->offendingMachineContext = machineContext;
            crashContext->registersAreValid = false;
            crashContext->NSException.name = [[exception name] UTF8String];
            crashContext->NSException.userInfo = [[NSString stringWithFormat:@"%@", exception.userInfo] UTF8String];
            crashContext->exceptionName = crashContext->NSException.name;
            crashContext->crashReason = [[exception reason] UTF8String];
            crashContext->stackCursor = &cursor;
            crashContext->currentSnapshotUserReported = currentSnapshotUserReported;
    
            KSLOG_DEBUG(@"Calling main crash handler.");
            kscm_handleException(crashContext);
    
            free(callstack);
            if (currentSnapshotUserReported) {
                ksmc_resumeEnvironment();
            }
            if (g_previousUncaughtExceptionHandler != NULL)
            {
                KSLOG_DEBUG(@"Calling original exception handler.");
                g_previousUncaughtExceptionHandler(exception);
            }
        }
    }
    
    static void handleCurrentSnapshotUserReportedException(NSException* exception) {
        handleException(exception, true);
    }
    
    static void handleUncaughtException(NSException* exception) {
        handleException(exception, false);
    }
    
    // ============================================================================
    #pragma mark - API -
    // ============================================================================
    //授权开关
    static void setEnabled(bool isEnabled)
    {
        
        NSLog(@"************KSCrashMonitor_NSException isEnabled :%d",isEnabled);
        if(isEnabled != g_isEnabled)
        {
            g_isEnabled = isEnabled;
            if(isEnabled)
            {
                KSLOG_DEBUG(@"Backing up original handler.");
                g_previousUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();
                
                KSLOG_DEBUG(@"Setting new handler.");
                NSSetUncaughtExceptionHandler(&handleUncaughtException);
                KSCrash.sharedInstance.uncaughtExceptionHandler = &handleUncaughtException;
                KSCrash.sharedInstance.currentSnapshotUserReportedExceptionHandler = &handleCurrentSnapshotUserReportedException;
            }
            else
            {
                KSLOG_DEBUG(@"Restoring original handler.");
                NSSetUncaughtExceptionHandler(g_previousUncaughtExceptionHandler);
            }
        }
    }
    
    static bool isEnabled()
    {
        return g_isEnabled;
    }
    //是否已对KSCrashMonitor_NSException进行授权
    KSCrashMonitorAPI* kscm_nsexception_getAPI()
    {
        static KSCrashMonitorAPI api =
        {
            .setEnabled = setEnabled,
            .isEnabled = isEnabled
        };
        return &api;
    }
    

     

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值