arm64 register and debug-state access

osfmk/arm64/status.c · 2726 lines · browse source

Machine-dependent thread state reads and writes, including ARM_THREAD_STATE64 and ARM_DEBUG_STATE64. Debug-state handling validates counts and controls, carries the MDSCR single-step bit, and allocates or releases per-thread debug state as needed.

machine_thread_get_state source
Routine: machine_thread_get_state
kern_return_t
machine_thread_get_state(thread_t                 thread,
    thread_flavor_t          flavor,
    thread_state_t           tstate,
    mach_msg_type_number_t * count)
{
	switch (flavor) {
	case THREAD_STATE_FLAVOR_LIST:
		if (*count < 4) {
			return KERN_INVALID_ARGUMENT;
		}

		tstate[0] = ARM_THREAD_STATE;
		tstate[1] = ARM_VFP_STATE;
		tstate[2] = ARM_EXCEPTION_STATE;
		tstate[3] = ARM_DEBUG_STATE;
		*count = 4;
		break;

	case THREAD_STATE_FLAVOR_LIST_NEW:
		if (*count < 4) {
			return KERN_INVALID_ARGUMENT;
		}

		tstate[0] = ARM_THREAD_STATE;
		tstate[1] = ARM_VFP_STATE;
		tstate[2] = thread_is_64bit_data(thread) ? ARM_EXCEPTION_STATE64 : ARM_EXCEPTION_STATE;
		tstate[3] = thread_is_64bit_data(thread) ? ARM_DEBUG_STATE64 : ARM_DEBUG_STATE32;
		*count = 4;
		break;
… more in source
machine_thread_set_state source
Routine: machine_thread_set_state
kern_return_t
machine_thread_set_state(thread_t               thread,
    thread_flavor_t        flavor,
    thread_state_t         tstate,
    mach_msg_type_number_t count)
{
	kern_return_t rn;

	switch (flavor) {
	case ARM_THREAD_STATE:
		rn = handle_set_arm_thread_state(tstate, count, thread->machine.upcb);
		if (rn) {
			return rn;
		}
		break;

	case ARM_THREAD_STATE32:
		if (thread_is_64bit_data(thread)) {
			return KERN_INVALID_ARGUMENT;
		}

		rn = handle_set_arm32_thread_state(tstate, count, thread->machine.upcb);
		if (rn) {
			return rn;
		}
		break;

#if __arm64__
	case ARM_THREAD_STATE64:
		if (!thread_is_64bit_data(thread)) {
… more in source
find_debug_state64 source · find_debug_state64 reference
arm_debug_state64_t *
find_debug_state64(thread_t thread)
{
	if (thread && thread->machine.DebugData) {
		return &(thread->machine.DebugData->uds.ds64);
	} else {
		return NULL;
	}
}
find_or_allocate_debug_state64 source · find_or_allocate_debug_state64 reference
Finds the debug state for the given 64 bit thread, allocating one if it does not exist. @param thread 64 bit thread to find or allocate debug state for @returns A pointer to the given thread's 64 bit debug state or a null pointer if the given thread is null or the allocation of a new debug state fails.
arm_debug_state64_t *
find_or_allocate_debug_state64(thread_t thread)
{
	arm_debug_state64_t *thread_state = find_debug_state64(thread);
	if (thread != NULL && thread_state == NULL) {
		thread->machine.DebugData = zalloc_flags(ads_zone,
		    Z_WAITOK | Z_NOFAIL);
		bzero(thread->machine.DebugData, sizeof *(thread->machine.DebugData));
		thread->machine.DebugData->dsh.flavor = ARM_DEBUG_STATE64;
		thread->machine.DebugData->dsh.count = ARM_DEBUG_STATE64_COUNT;
		os_ref_init(&thread->machine.DebugData->ref, &dbg_refgrp);
		thread_state = find_debug_state64(thread);
	}
	return thread_state;
}
free_debug_state source · free_debug_state reference
Frees a thread's debug state if allocated. Otherwise does nothing. @param thread thread to free the debug state of
static inline void
free_debug_state(thread_t thread)
{
	if (thread != NULL && thread->machine.DebugData != NULL) {
		arm_debug_state_t *pTmp = thread->machine.DebugData;
		thread->machine.DebugData = NULL;

		if (os_ref_release(&pTmp->ref) == 0) {
			zfree(ads_zone, pTmp);
		}
	}
}