static bool advanceCursor(KSStackCursor *cursor)
{
    MachineContextCursor* context = (MachineContextCursor*)cursor->context;
    uintptr_t nextAddress = 0;
    
    if(cursor->state.currentDepth >= context->maxStackDepth)
    {
        cursor->state.hasGivenUp = true;
        return false;
    }
    
    if(context->instructionAddress == 0)
    {
        context->instructionAddress = kscpu_instructionAddress(context->machineContext);
        if(context->instructionAddress == 0)
        {
            return false;
        }
        nextAddress = context->instructionAddress;
        goto successfulExit;
    }

    if(context->linkRegister == 0 && !context->isPastFramePointer)
    {
        // Link register, if available, is the second address in the trace.
        context->linkRegister = kscpu_linkRegister(context->machineContext);
        if(context->linkRegister != 0)
        {
            nextAddress = context->linkRegister;
            goto successfulExit;
        }
    }

    if(context->currentFrame.previous == NULL)
    {
        if(context->isPastFramePointer)
        {
            return false;
        }
        context->currentFrame.previous = (struct FrameEntry*)kscpu_framePointer(context->machineContext);
        context->isPastFramePointer = true;
    }

    if(!ksmem_copySafely(context->currentFrame.previous, &context->currentFrame, sizeof(context->currentFrame)))
    {
        return false;
    }
    if(context->currentFrame.previous == 0 || context->currentFrame.return_address == 0)
    {
        return false;
    }

    nextAddress = context->currentFrame.return_address;
    
successfulExit:
    cursor->stackEntry.address = kscpu_normaliseInstructionPointer(nextAddress);
    cursor->state.currentDepth++;
    return true;
}
Exemplo n.º 2
0
static bool advanceCursor(KSStackCursor *cursor)
{
    MachineContextCursor* cursorContext = (MachineContextCursor*)cursor->context;
    
    if(cursor->state.currentDepth >= cursor->state.maxDepth)
    {
        return false;
    }
    
    if(cursorContext->instructionAddress == 0)
    {
        return false;
    }

    if(cursorContext->linkRegister == 0 && !cursorContext->isPastFramePointer)
    {
        // Link register, if available, is the second address in the trace.
        cursorContext->linkRegister = kscpu_linkRegister(cursorContext->machineContext);
        if(cursorContext->linkRegister != 0)
        {
            cursor->stackEntry.address = cursorContext->linkRegister;
            cursor->state.currentDepth++;
            return true;
        }
    }

    if(cursorContext->currentFrame.previous == NULL)
    {
        if(cursorContext->isPastFramePointer)
        {
            return false;
        }
        cursorContext->currentFrame.previous = (struct FrameEntry*)kscpu_framePointer(cursorContext->machineContext);
        cursorContext->isPastFramePointer = true;
    }

    if(!ksmem_copySafely(cursorContext->currentFrame.previous, &cursorContext->currentFrame, sizeof(cursorContext->currentFrame)))
    {
        return false;
    }
    if(cursorContext->currentFrame.previous == 0 || cursorContext->currentFrame.return_address == 0)
    {
        return false;
    }

    cursor->stackEntry.address = cursorContext->currentFrame.return_address;
    cursor->state.currentDepth++;
    return true;
}