コード例 #1
0
ファイル: KSBacktrace.c プロジェクト: Danielhhs/KSCrash
bool ksbt_isBacktraceTooLong(const STRUCT_MCONTEXT_L* const machineContext,
                             int maxLength)
{
    const uintptr_t instructionAddress = ksmach_instructionAddress(machineContext);

    if(instructionAddress == 0)
    {
        return 0;
    }

    KSFrameEntry frame = {0};
    const uintptr_t framePtr = ksmach_framePointer(machineContext);
    if(framePtr == 0 ||
       ksmach_copyMem((void*)framePtr, &frame, sizeof(frame)) != KERN_SUCCESS)
    {
        return 1;
    }
    for(int i = 1; i < maxLength; i++)
    {
        if(frame.previous == 0 ||
           ksmach_copyMem(frame.previous, &frame, sizeof(frame)) != KERN_SUCCESS)
        {
            return false;
        }
    }

    return true;
}
コード例 #2
0
ファイル: KSObjC.c プロジェクト: ALEXGUOQ/KSCrash
const char* ksobjc_className(void* address)
{
    ObjCObjectType objectType = ksobjc_objectType(address);
    class_t* pIsa = address;
    class_t cls;
    class_rw_t rw;
    class_ro_t ro;
    char name[128];

    if(objectType == kObjCObjectTypeNone)
    {
        return NULL;
    }

    if(objectType == kObjCObjectTypeObject)
    {
        // Copy the object's isa pointer
        if(ksmach_copyMem(pIsa, &pIsa, sizeof(pIsa)) != KERN_SUCCESS)
        {
            return NULL;
        }
    }

    // We're now guaranteed that pClass points to a class.

    if(ksmach_copyMem(pIsa, &cls, sizeof(cls)) != KERN_SUCCESS)
    {
        return NULL;
    }
    if(ksmach_copyMem(cls.data, &rw, sizeof(rw)) != KERN_SUCCESS)
    {
        return NULL;
    }
    if(ksmach_copyMem(rw.ro, &ro, sizeof(ro)) != KERN_SUCCESS)
    {
        return NULL;
    }
    size_t nameLength = ksmach_copyMaxPossibleMem(ro.name, name, sizeof(name));
    if(ro.name + nameLength < ro.name)
    {
        // Wrapped around address space.
        return NULL;
    }
    if(nameLength == 0 || !isValidClassNameStartChar(*name))
    {
        return NULL;
    }
    for(size_t i = 0; i < nameLength; i++)
    {
        if(!isValidClassNameChar(name[i]))
        {
            if(name[i] == 0)
            {
                return ro.name;
            }
            return NULL;
        }
    }
    return NULL;
}
コード例 #3
0
ファイル: KSBacktrace.c プロジェクト: Danielhhs/KSCrash
int ksbt_backtraceLength(const STRUCT_MCONTEXT_L* const machineContext)
{
    const uintptr_t instructionAddress = ksmach_instructionAddress(machineContext);

    if(instructionAddress == 0)
    {
        return 0;
    }

    KSFrameEntry frame = {0};
    const uintptr_t framePtr = ksmach_framePointer(machineContext);
    if(framePtr == 0 ||
       ksmach_copyMem((void*)framePtr, &frame, sizeof(frame)) != KERN_SUCCESS)
    {
        return 1;
    }
    for(int i = 1; i < kBacktraceGiveUpPoint; i++)
    {
        if(frame.previous == 0 ||
           ksmach_copyMem(frame.previous, &frame, sizeof(frame)) != KERN_SUCCESS)
        {
            return i;
        }
    }

    return kBacktraceGiveUpPoint;
}
コード例 #4
0
ファイル: KSBacktrace.c プロジェクト: Danielhhs/KSCrash
int ksbt_backtraceThreadState(const STRUCT_MCONTEXT_L* const machineContext,
                              uintptr_t*const backtraceBuffer,
                              const int skipEntries,
                              const int maxEntries)
{
    const uintptr_t instructionAddress = ksmach_instructionAddress(machineContext);

    if(maxEntries == 0)
    {
        return 0;
    }

    int startPoint = 0;
    if(skipEntries == 0)
    {
        backtraceBuffer[0] = instructionAddress;

        if(maxEntries == 1)
        {
            return 1;
        }

        startPoint = 1;
    }

    KSFrameEntry frame = {0};

    const uintptr_t framePtr = ksmach_framePointer(machineContext);
    if(framePtr == 0 ||
       ksmach_copyMem((void*)framePtr, &frame, sizeof(frame)) != KERN_SUCCESS)
    {
        return 0;
    }
    for(int i = 1; i < skipEntries; i++)
    {
        if(frame.previous == 0 ||
           ksmach_copyMem(frame.previous, &frame, sizeof(frame)) != KERN_SUCCESS)
        {
            return 0;
        }
    }

    int i;
    for(i = startPoint; i < maxEntries; i++)
    {
        backtraceBuffer[i] = DETAG_FRAME_CALLER_ADDRESS(frame.caller);
        if(backtraceBuffer[i] == 0 ||
           frame.previous == 0 ||
           ksmach_copyMem(frame.previous, &frame, sizeof(frame)) != KERN_SUCCESS)
        {
            break;
        }
    }
    return i;
}
コード例 #5
0
ファイル: KSMach.c プロジェクト: jimmychungbelkin/KSCrash
bool ksmach_getThreadQueueName(const thread_t thread,
                               char* const buffer,
                               size_t bufLength)
{
    struct internal_dispatch_queue_s* pQueue;
    struct internal_dispatch_queue_s queue;

    if(bufLength > sizeof(queue.dq_label))
    {
        bufLength = sizeof(queue.dq_label);
    }

    // Recast the opaque thread to our hacky internal thread structure pointer.
    const pthread_t pthread = pthread_from_mach_thread_np(thread);
    const internal_pthread_t const threadStruct = (internal_pthread_t)pthread;

    if(ksmach_copyMem(&threadStruct->tsd[dispatch_queue_key], &pQueue, sizeof(pQueue)) != KERN_SUCCESS)
    {
        KSLOG_TRACE("Could not copy queue pointer from %p", &threadStruct->tsd[dispatch_queue_key]);
        return false;
    }

    if(pQueue == NULL)
    {
        KSLOG_TRACE("Queue pointer is NULL");
        return false;
    }

    if(ksmach_copyMem(pQueue, &queue, sizeof(queue)) != KERN_SUCCESS)
    {
        KSLOG_TRACE("Could not copy queue data from %p", pQueue);
        return false;
    }

    // Queue label must be a null terminated string.
    int iLabel;
    for(iLabel = 0; iLabel < (int)sizeof(queue.dq_label); iLabel++)
    {
        if(queue.dq_label[iLabel] < ' ' || queue.dq_label[iLabel] > '~')
        {
            break;
        }
    }
    if(queue.dq_label[iLabel] != 0)
    {
        // Found a non-null, invalid char.
        KSLOG_TRACE("Queue label contains invalid chars");
        return false;
    }
    
    strncpy(buffer, queue.dq_label, bufLength);
    KSLOG_TRACE("Queue label = %s", buffer);
    return true;
}
コード例 #6
0
ファイル: KSMach.c プロジェクト: AisakaTiger/KSCrash
size_t ksmach_copyMaxPossibleMem(const void* const src,
                                 void* const dst,
                                 const size_t numBytes)
{
    const uint8_t* pSrc = src;
    const uint8_t* pSrcMax = (uint8_t*)src + numBytes;
    const uint8_t* pSrcEnd = (uint8_t*)src + numBytes;
    uint8_t* pDst = dst;

    size_t bytesCopied = 0;

    // Short-circuit if no memory is readable
    if(ksmach_copyMem(src, dst, 1) != KERN_SUCCESS)
    {
        return 0;
    }
    else if(numBytes <= 1)
    {
        return numBytes;
    }

    for(;;)
    {
        ssize_t copyLength = pSrcEnd - pSrc;
        if(copyLength <= 0)
        {
            break;
        }

        if(ksmach_copyMem(pSrc, pDst, (size_t)copyLength) == KERN_SUCCESS)
        {
            bytesCopied += (size_t)copyLength;
            pSrc += copyLength;
            pDst += copyLength;
            pSrcEnd = pSrc + (pSrcMax - pSrc) / 2;
        }
        else
        {
            if(copyLength <= 1)
            {
                break;
            }
            pSrcMax = pSrcEnd;
            pSrcEnd = pSrc + copyLength / 2;
        }
    }
    return bytesCopied;
}
コード例 #7
0
ファイル: KSMach.c プロジェクト: AisakaTiger/KSCrash
thread_t ksmach_machThreadFromPThread(const pthread_t pthread)
{
    const internal_pthread_t threadStruct = (internal_pthread_t)pthread;
    thread_t machThread = 0;
    if(ksmach_copyMem(&threadStruct->kernel_thread, &machThread, sizeof(machThread)) != KERN_SUCCESS)
    {
        KSLOG_TRACE("Could not copy mach thread from %p", threadStruct->kernel_thread);
        return 0;
    }
    return machThread;
}
コード例 #8
0
ファイル: KSMach.c プロジェクト: AisakaTiger/KSCrash
pthread_t ksmach_pthreadFromMachThread(const thread_t thread)
{
    internal_pthread_t threadStruct = (internal_pthread_t)g_topThread;
    thread_t machThread = 0;

    for(int i = 0; i < 50; i++)
    {
        if(ksmach_copyMem(&threadStruct->kernel_thread, &machThread, sizeof(machThread)) != KERN_SUCCESS)
        {
            break;
        }
        if(machThread == thread)
        {
            return (pthread_t)threadStruct;
        }

        if(ksmach_copyMem(&threadStruct->plist.tqe_next, &threadStruct, sizeof(threadStruct)) != KERN_SUCCESS)
        {
            break;
        }
    }
    return 0;
}
コード例 #9
0
ファイル: KSMach.c プロジェクト: edison9888/KSCrash
bool ksmach_getThreadName(const thread_t thread,
                          char* const buffer,
                          size_t bufLength)
{
    const pthread_t pthread = ksmach_pthreadFromMachThread(thread);
    const internal_pthread_t threadStruct = (internal_pthread_t)pthread;
    size_t copyLength = bufLength > MAXTHREADNAMESIZE ? MAXTHREADNAMESIZE : bufLength;

    if(ksmach_copyMem(threadStruct->pthread_name, buffer, copyLength) != KERN_SUCCESS)
    {
        KSLOG_TRACE("Could not copy thread name from %p", threadStruct->pthread_name);
        return false;
    }
    buffer[copyLength-1] = 0;
    return true;
}
コード例 #10
0
ファイル: KSObjC.c プロジェクト: ALEXGUOQ/KSCrash
ObjCObjectType ksobjc_objectType(void* self)
{
    /*
     How to determine if it's a class or object.

     Root object/class:
     - class: self->isa->superclass == self
     - object: self->isa->superclass == nil

     Non-root object/class:
     - class: self->isa->isa->isa == self->isa->isa
     - object: self->isa->isa->isa->isa == self->isa->isa->isa
     */

    class_t* pIsa;
    class_t cls;

    if(self == NULL)
    {
        return kObjCObjectTypeNone;
    }

    // Get the object/class isa pointer
    if(ksmach_copyMem(self, &pIsa, sizeof(pIsa)) != KERN_SUCCESS)
    {
        return kObjCObjectTypeNone;
    }

    // Copy the class contents
    if(ksmach_copyMem(pIsa, &cls, sizeof(cls)) != KERN_SUCCESS)
    {
        return kObjCObjectTypeNone;
    }

    // Simple case: Root object or class.
    if(cls.superclass == NULL)
    {
        return kObjCObjectTypeObject;
    }
    if(cls.superclass == self)
    {
        return kObjCObjectTypeClass;
    }

    // One more isa before loop = class
    pIsa = cls.isa;
    if(ksmach_copyMem(pIsa, &cls, sizeof(cls)) != KERN_SUCCESS)
    {
        return kObjCObjectTypeNone;
    }
    if(cls.isa == pIsa)
    {
        return kObjCObjectTypeClass;
    }

    // Two more isa before loop = object
    pIsa = cls.isa;
    if(ksmach_copyMem(pIsa, &cls, sizeof(cls)) != KERN_SUCCESS)
    {
        return kObjCObjectTypeNone;
    }
    if(cls.isa == pIsa)
    {
        return kObjCObjectTypeObject;
    }

    // Don't know what this is
    return kObjCObjectTypeNone;
}
コード例 #11
0
ファイル: KSBacktrace.c プロジェクト: AisakaTiger/KSCrash
int ksbt_backtraceThreadState(const STRUCT_MCONTEXT_L* const machineContext,
                              uintptr_t*const backtraceBuffer,
                              const int skipEntries,
                              const int maxEntries)
{
    if(maxEntries == 0)
    {
        return 0;
    }

    int i = 0;

    if(skipEntries == 0)
    {
        const uintptr_t instructionAddress = ksmach_instructionAddress(machineContext);
        backtraceBuffer[i] = instructionAddress;
        i++;

        if(i == maxEntries)
        {
            return i;
        }
    }

    if(skipEntries <= 1)
    {
        uintptr_t linkRegister = ksmach_linkRegister(machineContext);

        if(linkRegister)
        {
            backtraceBuffer[i] = linkRegister;
            i++;

            if (i == maxEntries)
            {
                return i;
            }
        }
    }

    KSFrameEntry frame = {0};

    const uintptr_t framePtr = ksmach_framePointer(machineContext);
    if(framePtr == 0 ||
       ksmach_copyMem((void*)framePtr, &frame, sizeof(frame)) != KERN_SUCCESS)
    {
        return 0;
    }
    for(int j = 1; j < skipEntries; j++)
    {
        if(frame.previous == 0 ||
           ksmach_copyMem(frame.previous, &frame, sizeof(frame)) != KERN_SUCCESS)
        {
            return 0;
        }
    }

    for(; i < maxEntries; i++)
    {
        backtraceBuffer[i] = frame.return_address;
        if(backtraceBuffer[i] == 0 ||
           frame.previous == 0 ||
           ksmach_copyMem(frame.previous, &frame, sizeof(frame)) != KERN_SUCCESS)
        {
            break;
        }
    }
    return i;
}