Beispiel #1
0
static int embKernel_update_threads(struct rtos *rtos)
{
    /* int i = 0; */
    int retval;
    const struct embKernel_params *param;

    if (rtos == NULL)
        return -1;

    if (rtos->rtos_specific_params == NULL)
        return -3;

    if (rtos->symbols == NULL) {
        LOG_ERROR("No symbols for embKernel");
        return -4;
    }

    if (rtos->symbols[SYMBOL_ID_sCurrentTask].address == 0) {
        LOG_ERROR("Don't have the thread list head");
        return -2;
    }

    /* wipe out previous thread details if any */
    rtos_free_threadlist(rtos);

    param = (const struct embKernel_params *) rtos->rtos_specific_params;

    retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sCurrentTask].address, param->pointer_width,
                                (uint8_t *) &rtos->current_thread);
    if (retval != ERROR_OK) {
        LOG_ERROR("Error reading current thread in embKernel thread list");
        return retval;
    }

    int64_t max_used_priority = 0;
    retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sMaxPriorities].address, param->pointer_width,
                                (uint8_t *) &max_used_priority);
    if (retval != ERROR_OK)
        return retval;

    int thread_list_size = 0;
    retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sCurrentTaskCount].address,
                                param->thread_count_width, (uint8_t *) &thread_list_size);

    if (retval != ERROR_OK) {
        LOG_ERROR("Could not read embKernel thread count from target");
        return retval;
    }

    /* create space for new thread details */
    rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);
    if (!rtos->thread_details) {
        LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
        return ERROR_FAIL;
    }

    int threadIdx = 0;
    /* Look for ready tasks */
    for (int pri = 0; pri < max_used_priority; pri++) {
        /* Get first item in queue */
        int64_t iterable = 0;
        retval = target_read_buffer(rtos->target,
                                    rtos->symbols[SYMBOL_ID_sListReady].address + (pri * param->rtos_list_size), param->pointer_width,
                                    (uint8_t *) &iterable);
        if (retval != ERROR_OK)
            return retval;
        for (; iterable && threadIdx < thread_list_size; threadIdx++) {
            /* Get info from this iterable item */
            retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Ready");
            if (retval != ERROR_OK)
                return retval;
            /* Get next iterable item */
            retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
                                        (uint8_t *) &iterable);
            if (retval != ERROR_OK)
                return retval;
        }
    }
    /* Look for sleeping tasks */
    int64_t iterable = 0;
    retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListSleep].address, param->pointer_width,
                                (uint8_t *) &iterable);
    if (retval != ERROR_OK)
        return retval;
    for (; iterable && threadIdx < thread_list_size; threadIdx++) {
        /*Get info from this iterable item */
        retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Sleeping");
        if (retval != ERROR_OK)
            return retval;
        /*Get next iterable item */
        retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
                                    (uint8_t *) &iterable);
        if (retval != ERROR_OK)
            return retval;
    }

    /* Look for suspended tasks  */
    iterable = 0;
    retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListSuspended].address, param->pointer_width,
                                (uint8_t *) &iterable);
    if (retval != ERROR_OK)
        return retval;
    for (; iterable && threadIdx < thread_list_size; threadIdx++) {
        /* Get info from this iterable item */
        retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Suspended");
        if (retval != ERROR_OK)
            return retval;
        /*Get next iterable item */
        retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
                                    (uint8_t *) &iterable);
        if (retval != ERROR_OK)
            return retval;
    }

    rtos->thread_count = 0;
    rtos->thread_count = threadIdx;
    LOG_OUTPUT("Found %u tasks\n", (unsigned int)threadIdx);
    return 0;
}
Beispiel #2
0
static int hwthread_update_threads(struct rtos *rtos)
{
	int threads_found = 0;
	int thread_list_size = 0;
	struct target_list *head;
	struct target *target;
	int64_t current_thread = 0;
	enum target_debug_reason current_reason = DBG_REASON_UNDEFINED;

	if (rtos == NULL)
		return -1;

	target = rtos->target;

	/* wipe out previous thread details if any */
	rtos_free_threadlist(rtos);

	/* determine the number of "threads" */
	if (target->smp) {
		for (head = target->head; head != NULL; head = head->next) {
			struct target *curr = head->target;

			if (!target_was_examined(curr))
				continue;

			++thread_list_size;
		}
	} else
		thread_list_size = 1;

	/* create space for new thread details */
	rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);

	if (target->smp) {
		/* loop over all threads */
		for (head = target->head; head != NULL; head = head->next) {
			struct target *curr = head->target;

			if (!target_was_examined(curr))
				continue;

			threadid_t tid = threadid_from_target(curr);

			hwthread_fill_thread(rtos, curr, threads_found);

			/* find an interesting thread to set as current */
			switch (current_reason) {
			case DBG_REASON_UNDEFINED:
				current_reason = curr->debug_reason;
				current_thread = tid;
				break;
			case DBG_REASON_SINGLESTEP:
				/* single-step can only be overridden by itself */
				if (curr->debug_reason == DBG_REASON_SINGLESTEP) {
					if (tid == rtos->current_threadid)
						current_thread = tid;
				}
				break;
			case DBG_REASON_BREAKPOINT:
				/* single-step overrides breakpoint */
				if (curr->debug_reason == DBG_REASON_SINGLESTEP) {
					current_reason = curr->debug_reason;
					current_thread = tid;
				} else
				/* multiple breakpoints, prefer gdbs' threadid */
				if (curr->debug_reason == DBG_REASON_BREAKPOINT) {
					if (tid == rtos->current_threadid)
						current_thread = tid;
				}
				break;
			case DBG_REASON_WATCHPOINT:
				/* breakpoint and single-step override watchpoint */
				if (curr->debug_reason == DBG_REASON_SINGLESTEP ||
						curr->debug_reason == DBG_REASON_BREAKPOINT) {
					current_reason = curr->debug_reason;
					current_thread = tid;
				}
				break;
			case DBG_REASON_DBGRQ:
				/* all other reasons override debug-request */
				if (curr->debug_reason == DBG_REASON_SINGLESTEP ||
						curr->debug_reason == DBG_REASON_WATCHPOINT ||
						curr->debug_reason == DBG_REASON_BREAKPOINT) {
					current_reason = curr->debug_reason;
					current_thread = tid;
				} else
				if (curr->debug_reason == DBG_REASON_DBGRQ) {
					if (tid == rtos->current_threadid)
						current_thread = tid;
				}

				break;

			default:
				break;
			}

			threads_found++;
		}
	} else {
		hwthread_fill_thread(rtos, target, threads_found);
		current_thread = threadid_from_target(target);
		threads_found++;
	}

	rtos->thread_count = threads_found;

	/* we found an interesting thread, set it as current */
	if (current_thread != 0)
		rtos->current_thread = current_thread;
	else if (rtos->current_threadid != 0)
		rtos->current_thread = rtos->current_threadid;
	else
		rtos->current_thread = threadid_from_target(target);

	LOG_DEBUG("%s current_thread=%i", __func__, (int)rtos->current_thread);
	return 0;
}
Beispiel #3
0
static int uCOS_III_update_threads(struct rtos *rtos)
{
	struct uCOS_III_params *params = rtos->rtos_specific_params;
	int retval;

	/* free previous thread details */
	rtos_free_threadlist(rtos);

	/* verify RTOS is running */
	uint8_t rtos_running;

	retval = target_read_u8(rtos->target,
			rtos->symbols[uCOS_III_VAL_OSRunning].address,
			&rtos_running);
	if (retval != ERROR_OK) {
		LOG_ERROR("uCOS-III: failed to read RTOS running");
		return retval;
	}

	if (rtos_running != 1 && rtos_running != 0) {
		LOG_ERROR("uCOS-III: invalid RTOS running value");
		return ERROR_FAIL;
	}

	if (!rtos_running) {
		rtos->thread_details = calloc(1, sizeof(struct thread_detail));
		if (rtos->thread_details == NULL) {
			LOG_ERROR("uCOS-III: out of memory");
			return ERROR_FAIL;
		}

		rtos->thread_count = 1;
		rtos->thread_details->threadid = 0;
		rtos->thread_details->exists = true;
		rtos->current_thread = 0;

		return ERROR_OK;
	}

	/* update thread offsets */
	retval = uCOS_III_update_thread_offsets(rtos);
	if (retval != ERROR_OK) {
		LOG_ERROR("uCOS-III: failed to update thread offsets");
		return retval;
	}

	/* read current thread address */
	symbol_address_t current_thread_address = 0;

	retval = target_read_memory(rtos->target,
			rtos->symbols[uCOS_III_VAL_OSTCBCurPtr].address,
			params->pointer_width,
			1,
			(void *)&current_thread_address);
	if (retval != ERROR_OK) {
		LOG_ERROR("uCOS-III: failed to read current thread address");
		return retval;
	}

	/* read number of tasks */
	retval = target_read_u16(rtos->target,
			rtos->symbols[uCOS_III_VAL_OSTaskQty].address,
			(void *)&rtos->thread_count);
	if (retval != ERROR_OK) {
		LOG_ERROR("uCOS-III: failed to read thread count");
		return retval;
	}

	rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail));
	if (rtos->thread_details == NULL) {
		LOG_ERROR("uCOS-III: out of memory");
		return ERROR_FAIL;
	}

	/*
	 * uC/OS-III adds tasks in LIFO order; advance to the end of the
	 * list and work backwards to preserve the intended order.
	 */
	symbol_address_t thread_address = 0;

	retval = uCOS_III_find_last_thread_address(rtos, &thread_address);
	if (retval != ERROR_OK) {
		LOG_ERROR("uCOS-III: failed to find last thread address");
		return retval;
	}

	for (int i = 0; i < rtos->thread_count; i++) {
		struct thread_detail *thread_detail = &rtos->thread_details[i];
		char thread_str_buffer[UCOS_III_MAX_STRLEN + 1];

		/* find or create new threadid */
		retval = uCOS_III_find_or_create_thread(rtos, thread_address, &thread_detail->threadid);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to find or create thread");
			return retval;
		}

		if (thread_address == current_thread_address)
			rtos->current_thread = thread_detail->threadid;

		thread_detail->exists = true;

		/* read thread name */
		symbol_address_t thread_name_address = 0;

		retval = target_read_memory(rtos->target,
				thread_address + params->thread_name_offset,
				params->pointer_width,
				1,
				(void *)&thread_name_address);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to name address");
			return retval;
		}

		retval = target_read_buffer(rtos->target,
				thread_name_address,
				sizeof(thread_str_buffer),
				(void *)thread_str_buffer);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to read thread name");
			return retval;
		}

		thread_str_buffer[sizeof(thread_str_buffer) - 1] = '\0';
		thread_detail->thread_name_str = strdup(thread_str_buffer);

		/* read thread extra info */
		uint8_t thread_state;
		uint8_t thread_priority;

		retval = target_read_u8(rtos->target,
				thread_address + params->thread_state_offset,
				&thread_state);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to read thread state");
			return retval;
		}

		retval = target_read_u8(rtos->target,
				thread_address + params->thread_priority_offset,
				&thread_priority);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to read thread priority");
			return retval;
		}

		const char *thread_state_str;

		if (thread_state < ARRAY_SIZE(uCOS_III_thread_state_list))
			thread_state_str = uCOS_III_thread_state_list[thread_state];
		else
			thread_state_str = "Unknown";

		snprintf(thread_str_buffer, sizeof(thread_str_buffer), "State: %s, Priority: %d",
				thread_state_str, thread_priority);
		thread_detail->extra_info_str = strdup(thread_str_buffer);

		/* read previous thread address */
		retval = target_read_memory(rtos->target,
				thread_address + params->thread_prev_offset,
				params->pointer_width,
				1,
				(void *)&thread_address);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to read previous thread address");
			return retval;
		}
	}

	return ERROR_OK;
}
Beispiel #4
0
/*
 * API function, update list of threads
 */
static int mqx_update_threads(
	struct rtos *rtos
)
{
	uint32_t task_queue_addr = 0;
	uint32_t kernel_data_addr = 0;
	uint16_t task_queue_size = 0;
	uint32_t active_td_addr = 0;

	if (!rtos->rtos_specific_params)
		return -3;

	if (!rtos->symbols)
		return -4;

	/* clear old data */
	rtos_free_threadlist(rtos);
	/* check scheduler */
	if (ERROR_OK != mqx_is_scheduler_running(rtos))
		return ERROR_FAIL;
	/* get kernel_data symbol */
	if (ERROR_OK != mqx_get_symbol(
		rtos, mqx_VAL_mqx_kernel_data, &kernel_data_addr
	)) {
		return ERROR_FAIL;
	}
	/* read kernel_data */
	if (ERROR_OK != mqx_get_member(
		rtos, kernel_data_addr, 0, 4, "_mqx_kernel_data", &kernel_data_addr
	)) {
		return ERROR_FAIL;
	}
	/* get task queue address */
	task_queue_addr = kernel_data_addr + MQX_KERNEL_OFFSET_TDLIST;
	/* get task queue size */
	if (ERROR_OK != mqx_get_member(
		rtos, task_queue_addr, MQX_QUEUE_OFFSET_SIZE, 2,
		"kernel_data->TD_LIST.SIZE", &task_queue_size
	)) {
		return ERROR_FAIL;
	}
	/* get active ptr */
	if (ERROR_OK != mqx_get_member(
		rtos, kernel_data_addr, MQX_KERNEL_OFFSET_ACTIVE_TASK, 4,
		"kernel_data->ACTIVE_PTR", (void *)&active_td_addr
	)) {
		return ERROR_FAIL;
	}

	/* setup threads info */
	rtos->thread_count = task_queue_size;
	rtos->current_thread = 0;
	rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail));
	if (NULL == rtos->thread_details)
		return ERROR_FAIL;

	/*	loop over each task and setup thread details,
		the current_taskpool_addr is set to queue head
		NOTE: debugging functions task create/destroy
		might cause to show invalid data.
	*/
	for (
		uint32_t i = 0, taskpool_addr = task_queue_addr;
		i < (uint32_t)rtos->thread_count;
		i++
	) {
		uint8_t task_name[MQX_THREAD_NAME_LENGTH + 1];
		uint32_t task_addr = 0, task_template = 0, task_state = 0;
		uint32_t task_name_addr = 0, task_id = 0, task_errno = 0;
		uint32_t state_index = 0, state_max = 0;
		uint32_t extra_info_length = 0;
		char *state_name = "unknown state";

		/* set current taskpool address */
		if (ERROR_OK != mqx_get_member(
			rtos, taskpool_addr, MQX_TASK_OFFSET_NEXT, 4,
			"td_struct_ptr->NEXT", &taskpool_addr
		)) {
			return ERROR_FAIL;
		}
		/* get task address from taskpool */
		task_addr = taskpool_addr - MQX_TASK_OFFSET_TDLIST;
		/* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */
		if (ERROR_OK != mqx_get_member(
			rtos, task_addr, MQX_TASK_OFFSET_TEMPLATE, 4,
			"td_struct_ptr->TEMPLATE_LIST_PTR", &task_template
		)) {
			return ERROR_FAIL;
		}
		/* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */
		if (ERROR_OK != mqx_get_member(
			rtos, task_template, MQX_TASK_TEMPLATE_OFFSET_NAME, 4,
			"td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr
		)) {
			return ERROR_FAIL;
		}
		/* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */
		if (ERROR_OK != mqx_get_member(
			rtos, task_name_addr, 0, MQX_THREAD_NAME_LENGTH,
			"*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name
		)) {
			return ERROR_FAIL;
		}
		/* always terminate last character by force,
		   otherwise openocd might fail if task_name
		   has corrupted data */
		task_name[MQX_THREAD_NAME_LENGTH] = '\0';
		/* get value of 'td_struct_ptr->TASK_ID' */
		if (ERROR_OK != mqx_get_member(
			rtos, task_addr, MQX_TASK_OFFSET_ID, 4,
			"td_struct_ptr->TASK_ID", &task_id
		)) {
			return ERROR_FAIL;
		}
		/* get task errno */
		if (ERROR_OK != mqx_get_member(
			rtos, task_addr, MQX_TASK_OFFSET_ERROR_CODE, 4,
			"td_struct_ptr->TASK_ERROR_CODE", &task_errno
		)) {
			return ERROR_FAIL;
		}
		/* get value of 'td_struct_ptr->STATE' */
		if (ERROR_OK != mqx_get_member(
			rtos, task_addr, MQX_TASK_OFFSET_STATE, 4,
			"td_struct_ptr->STATE", &task_state
		)) {
			return ERROR_FAIL;
		}
		task_state &= MQX_TASK_STATE_MASK;
		/* and search for defined state */
		state_max = (sizeof(mqx_states)/sizeof(struct mqx_state));
		for (state_index = 0; (state_index < state_max); state_index++) {
			if (mqx_states[state_index].state == task_state) {
				state_name = mqx_states[state_index].name;
				break;
			}
		}

		/* setup thread details struct */
		rtos->thread_details[i].threadid = task_id;
		rtos->thread_details[i].exists = true;
		rtos->thread_details[i].display_str = NULL;
		/* set thread name */
		rtos->thread_details[i].thread_name_str = malloc(strlen((void *)task_name) + 1);
		if (NULL == rtos->thread_details[i].thread_name_str)
			return ERROR_FAIL;
		strcpy(rtos->thread_details[i].thread_name_str, (void *)task_name);
		/* set thread extra info
		 * - task state
		 * - task address
		 * - task errno
		 * calculate length as:
		 * state length + address length + errno length + formatter length
		 */
		extra_info_length += strlen((void *)state_name) + 8 + 8 + 8;
		rtos->thread_details[i].extra_info_str = malloc(extra_info_length + 1);
		if (NULL == rtos->thread_details[i].extra_info_str)
			return ERROR_FAIL;
		snprintf(
			rtos->thread_details[i].extra_info_str, extra_info_length, "%s : 0x%"PRIx32 " : %" PRIu32,
			state_name, task_addr, task_errno
		);
		/* set active thread */
		if (active_td_addr == task_addr)
			rtos->current_thread = task_id;
	}
	return ERROR_OK;
}