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; }
void kssc_initWithMachineContext(KSStackCursor *cursor, int maxStackDepth, const struct KSMachineContext* machineContext) { kssc_initCursor(cursor, maxStackDepth, kscpu_instructionAddress(machineContext)); cursor->advanceCursor = advanceCursor; MachineContextCursor* cursorContext = (MachineContextCursor*)cursor->context; cursorContext->machineContext = machineContext; cursorContext->instructionAddress = cursor->stackEntry.address; }