static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **rtos_reg_list, int *num_regs) { struct target_list *head; struct target *target; struct target *curr; struct reg **reg_list; int retval; if (rtos == NULL) return ERROR_FAIL; target = rtos->target; /* Find the thread with that thread_id */ if (target->smp) { curr = NULL; for (head = target->head; head != NULL; head = head->next) { curr = head->target; if (thread_id == threadid_from_target(curr)) break; } if (head == NULL) return ERROR_FAIL; } else { curr = target; if (thread_id != threadid_from_target(curr)) return ERROR_FAIL; } if (!target_was_examined(curr)) return ERROR_FAIL; retval = target_get_gdb_reg_list(curr, ®_list, num_regs, REG_CLASS_GENERAL); if (retval != ERROR_OK) return retval; *rtos_reg_list = calloc(*num_regs, sizeof(struct rtos_reg)); if (*rtos_reg_list == NULL) { free(reg_list); return ERROR_FAIL; } for (int i = 0; i < *num_regs; i++) { (*rtos_reg_list)[i].number = (*reg_list)[i].number; (*rtos_reg_list)[i].size = (*reg_list)[i].size; memcpy((*rtos_reg_list)[i].value, (*reg_list)[i].value, ((*reg_list)[i].size + 7) / 8); } free(reg_list); return ERROR_OK; }
int get_current(struct target *target, int create) { struct target_list *head; head = target->head; uint8_t *buf; uint32_t val; uint32_t ti_addr; uint8_t *buffer = calloc(1, 4); struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; struct current_thread *ctt = linux_os->current_threads; /* invalid current threads content */ while (ctt != NULL) { ctt->threadid = -1; ctt->TS = 0xdeadbeef; ctt = ctt->next; } while (head != (struct target_list *)NULL) { struct reg **reg_list; int reg_list_size; int retval; if (target_get_gdb_reg_list(head->target, ®_list, ®_list_size) != ERROR_OK) { free(buffer); return ERROR_TARGET_FAILURE; } if (!reg_list[13]->valid) reg_list[13]->type->get(reg_list[13]); buf = reg_list[13]->value; val = get_buffer(target, buf); ti_addr = (val & 0xffffe000); uint32_t TS_addr = ti_addr + 0xc; retval = fill_buffer(target, TS_addr, buffer); if (retval == ERROR_OK) { uint32_t TS = get_buffer(target, buffer); uint32_t cpu, on_cpu = TS + ONCPU; retval = fill_buffer(target, on_cpu, buffer); if (retval == ERROR_OK) { /*uint32_t cpu = get_buffer(target, buffer);*/ struct current_thread *ct = linux_os->current_threads; cpu = head->target->coreid; while ((ct != NULL) && (ct->core_id != (int32_t) cpu)) ct = ct->next; if ((ct != NULL) && (ct->TS == 0xdeadbeef)) ct->TS = TS; else LOG_ERROR ("error in linux current thread update"); if (create) { struct threads *t; t = calloc(1, sizeof(struct threads)); t->base_addr = ct->TS; fill_task(target, t); get_name(target, t); t->oncpu = cpu; insert_into_threadlist(target, t); t->status = 3; t->thread_info_addr = 0xdeadbeef; ct->threadid = t->threadid; linux_os->thread_count++; #ifdef PID_CHECK ct->pid = t->pid; #endif /*LOG_INFO("Creation of current thread %s",t->name);*/ } } } free(reg_list); head = head->next; } free(buffer); return ERROR_OK; }
static int linux_os_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list) { struct target *target = rtos->target; struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; int i = 0; struct current_thread *tmp = linux_os->current_threads; struct current_thread *next; char *hex_string; int found = 0; int retval; /* check if a current thread is requested */ next = tmp; do { if (next->threadid == thread_id) found = 1; else next = next->next; } while ((found == 0) && (next != tmp) && (next != NULL)); if (found == 1) { /* search target to perfom the access */ struct reg **reg_list; int reg_list_size, reg_packet_size = 0; struct target_list *head; head = target->head; found = 0; do { if (head->target->coreid == next->core_id) { target = head->target; found = 1; } else head = head->next; } while ((head != (struct target_list *)NULL) && (found == 0)); if (found == 0) { LOG_ERROR ( "current thread %" PRIx64 ": no target to perform access of core id %x", thread_id, next->core_id); return ERROR_FAIL; } /*LOG_INFO("thread %lx current on core %x",thread_id, * target->coreid);*/ retval = target_get_gdb_reg_list(target, ®_list, ®_list_size); if (retval != ERROR_OK) return retval; for (i = 0; i < reg_list_size; i++) reg_packet_size += reg_list[i]->size; *hex_reg_list = malloc(DIV_ROUND_UP(reg_packet_size, 8) * 2); hex_string = *hex_reg_list; for (i = 0; i < reg_list_size; i++) { if (!reg_list[i]->valid) reg_list[i]->type->get(reg_list[i]); hex_string = reg_converter(hex_string, reg_list[i]->value, (reg_list[i]->size) / 8); } free(reg_list); } else { struct threads *temp = linux_os->thread_list; *hex_reg_list = (char *)calloc(1, 500 * sizeof(char)); hex_string = *hex_reg_list; for (i = 0; i < 16; i++) hex_string += sprintf(hex_string, "%02x", 0); while ((temp != NULL) && (temp->threadid != target->rtos->current_threadid)) temp = temp->next; if (temp != NULL) { if (temp->context == NULL) temp->context = cpu_context_read(target, temp-> base_addr, &temp-> thread_info_addr); hex_string = reg_converter(hex_string, &temp->context->R4, 4); hex_string = reg_converter(hex_string, &temp->context->R5, 4); hex_string = reg_converter(hex_string, &temp->context->R6, 4); hex_string = reg_converter(hex_string, &temp->context->R7, 4); hex_string = reg_converter(hex_string, &temp->context->R8, 4); hex_string = reg_converter(hex_string, &temp->context->R9, 4); for (i = 0; i < 4; i++) /*R10 = 0x0 */ hex_string += sprintf(hex_string, "%02x", 0); hex_string = reg_converter(hex_string, &temp->context->FP, 4); hex_string = reg_converter(hex_string, &temp->context->IP, 4); hex_string = reg_converter(hex_string, &temp->context->SP, 4); for (i = 0; i < 4; i++) hex_string += sprintf(hex_string, "%02x", 0); hex_string = reg_converter(hex_string, &temp->context->PC, 4); for (i = 0; i < 100; i++) /*100 */ hex_string += sprintf(hex_string, "%02x", 0); uint32_t cpsr = 0x00000000; reg_converter(hex_string, &cpsr, 4); } } return ERROR_OK; }