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; }
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; }
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; }
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; }