X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Frtos%2Flinux.c;h=74172b70a43c189b27d69cfe9e5e33f9c8cf72e0;hb=d46b28983dc27369e90f4dc8a0e54b5057583b38;hp=e249ff49e96217f53816de3ea73a0ff32ae188ce;hpb=7b032df3aa63905c16c63f1ba4414a04687f3777;p=openocd.git diff --git a/src/rtos/linux.c b/src/rtos/linux.c index e249ff49e9..74172b70a4 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -14,9 +14,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -28,8 +26,8 @@ #include "target/target.h" #include "target/target_type.h" #include "helper/log.h" +#include "helper/types.h" #include "rtos.h" -#include "helper/log.h" #include "rtos_standard_stackings.h" #include #include "server/gdb_server.h" @@ -40,7 +38,7 @@ #define MAX_THREADS 200 /* specific task */ struct linux_os { - char *name; + const char *name; uint32_t init_task_addr; int thread_count; int threadid_count; @@ -107,11 +105,11 @@ static int linux_os_dummy_update(struct rtos *rtos) return 0; } -static int linux_compute_virt2phys(struct target *target, uint32_t address) +static int linux_compute_virt2phys(struct target *target, target_addr_t address) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; - uint32_t pa = 0; + target_addr_t pa = 0; int retval = target->type->virt2phys(target, address, &pa); if (retval != ERROR_OK) { LOG_ERROR("Cannot compute linux virt2phys translation"); @@ -140,27 +138,17 @@ static int linux_read_memory(struct target *target, return ERROR_FAIL; } #ifdef PHYS - target->type->read_phys_memory(target, pa, size, count, buffer); + target_read_phys_memory(target, pa, size, count, buffer); #endif - target->type->read_memory(target, address, size, count, buffer); + target_read_memory(target, address, size, count, buffer); return ERROR_OK; } -static char *reg_converter(char *buffer, void *reg, int size) -{ - int i; - - for (i = 0; i < size; i++) - buffer += sprintf(buffer, "%02x", ((uint8_t *) reg)[i]); - - return buffer; -} - int fill_buffer(struct target *target, uint32_t addr, uint8_t *buffer) { if ((addr & 0xfffffffc) != addr) - LOG_INFO("unaligned address %x!!", addr); + LOG_INFO("unaligned address %" PRIx32 "!!", addr); int retval = linux_read_memory(target, addr, 4, 1, buffer); return retval; @@ -176,15 +164,13 @@ uint32_t get_buffer(struct target *target, const uint8_t *buffer) } static int linux_os_thread_reg_list(struct rtos *rtos, - int64_t thread_id, char **hex_reg_list) + int64_t thread_id, struct rtos_reg **reg_list, int *num_regs) { 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 */ @@ -197,127 +183,65 @@ static int linux_os_thread_reg_list(struct rtos *rtos, 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; + if (found == 0) { + LOG_ERROR("could not find thread: %" PRIx64, thread_id); + return ERROR_FAIL; + } - *hex_reg_list = malloc(DIV_ROUND_UP(reg_packet_size, 8) * 2); + /* search target to perfom the access */ + struct reg **gdb_reg_list; + struct target_list *head; + head = target->head; + found = 0; + do { + if (head->target->coreid == next->core_id) { - hex_string = *hex_reg_list; + target = head->target; + found = 1; + } else + head = head->next; - for (i = 0; i < reg_list_size; i++) { - if (!reg_list[i]->valid) - reg_list[i]->type->get(reg_list[i]); + } while ((head != (struct target_list *)NULL) && (found == 0)); - hex_string = reg_converter(hex_string, - reg_list[i]->value, - (reg_list[i]->size) / 8); - } + if (found == 0) { + LOG_ERROR + ( + "current thread %" PRIx64 ": no target to perform access of core id %" PRIx32, + thread_id, + next->core_id); + return ERROR_FAIL; + } - free(reg_list); + /*LOG_INFO("thread %lx current on core %x",thread_id, target->coreid);*/ + retval = target_get_gdb_reg_list(target, &gdb_reg_list, num_regs, REG_CLASS_GENERAL); + if (retval != ERROR_OK) + return retval; - } else { - struct threads *temp = linux_os->thread_list; - *hex_reg_list = (char *)calloc(1, 500 * sizeof(char)); - hex_string = *hex_reg_list; + *reg_list = calloc(*num_regs, sizeof(struct rtos_reg)); - for (i = 0; i < 16; i++) - hex_string += sprintf(hex_string, "%02x", 0); + for (int i = 0; i < *num_regs; ++i) { + if (!gdb_reg_list[i]->valid) + gdb_reg_list[i]->type->get(gdb_reg_list[i]); - while ((temp != NULL) && - (temp->threadid != target->rtos->current_threadid)) - temp = temp->next; + (*reg_list)[i].number = gdb_reg_list[i]->number; + (*reg_list)[i].size = gdb_reg_list[i]->size; - 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; - hex_string = reg_converter(hex_string, &cpsr, 4); - } + buf_cpy(gdb_reg_list[i]->value, (*reg_list)[i].value, (*reg_list)[i].size); } + return ERROR_OK; } -static int linux_os_detect(struct target *target) +static bool linux_os_detect(struct target *target) { LOG_INFO("should no be called"); - return 0; + return false; } static int linux_os_smp_init(struct target *target); static int linux_os_clean(struct target *target); #define INIT_TASK 0 -static char *linux_symbol_list[] = { +static const char * const linux_symbol_list[] = { "init_task", NULL }; @@ -326,9 +250,9 @@ static int linux_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) { unsigned int i; *symbol_list = (symbol_table_elem_t *) - malloc(sizeof(symbol_table_elem_t) / sizeof(char *)); + calloc(ARRAY_SIZE(linux_symbol_list), sizeof(symbol_table_elem_t)); - for (i = 0; i < sizeof(linux_symbol_list) / sizeof(char *); i++) + for (i = 0; i < ARRAY_SIZE(linux_symbol_list); i++) (*symbol_list)[i].symbol_name = linux_symbol_list[i]; return 0; @@ -348,7 +272,7 @@ const struct rtos_type Linux_os = { .ps_command = linux_ps_command, }; -static int linux_thread_packet(struct connection *connection, char *packet, +static int linux_thread_packet(struct connection *connection, char const *packet, int packet_size); static void linux_identify_current_threads(struct target *target); @@ -420,6 +344,8 @@ int fill_task(struct target *target, struct threads *t) } else LOG_ERROR("fill task: unable to read memory"); + free(buffer); + return retval; } @@ -494,8 +420,10 @@ int get_current(struct target *target, int create) int retval; if (target_get_gdb_reg_list(head->target, ®_list, - ®_list_size) != ERROR_OK) + ®_list_size, REG_CLASS_GENERAL) != ERROR_OK) { + free(buffer); return ERROR_TARGET_FAILURE; + } if (!reg_list[13]->valid) reg_list[13]->type->get(reg_list[13]); @@ -526,7 +454,7 @@ int get_current(struct target *target, int create) LOG_ERROR ("error in linux current thread update"); - if (create) { + if (create && ct) { struct threads *t; t = calloc(1, sizeof(struct threads)); t->base_addr = ct->TS; @@ -550,6 +478,8 @@ int get_current(struct target *target, int create) head = head->next; } + free(buffer); + return ERROR_OK; } @@ -615,6 +545,7 @@ retry: (uint8_t *) registers); if (retval != ERROR_OK) { + free(buffer); LOG_ERROR("cpu_context: unable to read memory\n"); return context; } @@ -643,6 +574,8 @@ retry: if (*thread_info_addr_old == 0xdeadbeef) *thread_info_addr_old = thread_info_addr_update; + free(buffer); + return context; } @@ -655,11 +588,13 @@ uint32_t next_task(struct target *target, struct threads *t) if (retval == ERROR_OK) { uint32_t val = get_buffer(target, buffer); val = val - NEXT; - return val; free(buffer); + return val; } else LOG_ERROR("next task: unable to read memory"); + free(buffer); + return 0; } @@ -769,15 +704,16 @@ int linux_get_tasks(struct target *target, int context) struct threads *last = NULL; t->base_addr = linux_os->init_task_addr; /* retrieve the thread id , currently running in the different smp core */ - retval = get_current(target, 1); + get_current(target, 1); while (((t->base_addr != linux_os->init_task_addr) && (t->base_addr != 0)) || (loop == 0)) { loop++; - retval = fill_task(target, t); + fill_task(target, t); retval = get_name(target, t); if (loop > MAX_THREADS) { + free(t); LOG_INFO("more than %d threads !!", MAX_THREADS); return ERROR_FAIL; } @@ -829,6 +765,7 @@ int linux_get_tasks(struct target *target, int context) (timeval_ms() - start) / linux_os->threadid_count); LOG_INFO("threadid count %d", linux_os->threadid_count); + free(t); return ERROR_OK; } @@ -973,7 +910,7 @@ error_handling: #ifndef PID_CHECK error_handling: free(t); - LOG_ERROR("unable toread pid"); + LOG_ERROR("unable to read pid"); return; #endif @@ -1101,7 +1038,7 @@ static int linux_task_update(struct target *target, int context) } int linux_gdb_thread_packet(struct target *target, - struct connection *connection, char *packet, + struct connection *connection, char const *packet, int packet_size) { int retval; @@ -1120,25 +1057,25 @@ int linux_gdb_thread_packet(struct target *target, if (retval != ERROR_OK) return ERROR_TARGET_FAILURE; - char *out_str = (char *)calloc(1, 350 * sizeof(int64_t)); + char *out_str = calloc(MAX_THREADS * 17 + 10, 1); char *tmp_str = out_str; tmp_str += sprintf(tmp_str, "m"); struct threads *temp = linux_os->thread_list; - tmp_str += sprintf(tmp_str, "%016" PRIx64, temp->threadid); - temp = temp->next; while (temp != NULL) { - tmp_str += sprintf(tmp_str, ","); tmp_str += sprintf(tmp_str, "%016" PRIx64, temp->threadid); temp = temp->next; + if (temp) + tmp_str += sprintf(tmp_str, ","); } gdb_put_packet(connection, out_str, strlen(out_str)); + free(out_str); return ERROR_OK; } int linux_gdb_thread_update(struct target *target, - struct connection *connection, char *packet, + struct connection *connection, char const *packet, int packet_size) { int found = 0; @@ -1157,7 +1094,7 @@ int linux_gdb_thread_update(struct target *target, if (found == 1) { /*LOG_INFO("INTO GDB THREAD UPDATE FOUNDING START TASK");*/ - char *out_strr = (char *)calloc(1, 350 * sizeof(int64_t)); + char *out_strr = calloc(MAX_THREADS * 17 + 10, 1); char *tmp_strr = out_strr; tmp_strr += sprintf(tmp_strr, "m"); /*LOG_INFO("CHAR MALLOC & M DONE");*/ @@ -1185,7 +1122,7 @@ int linux_gdb_thread_update(struct target *target, } int linux_thread_extra_info(struct target *target, - struct connection *connection, char *packet, + struct connection *connection, char const *packet, int packet_size) { int64_t threadid = 0; @@ -1199,27 +1136,25 @@ int linux_thread_extra_info(struct target *target, if (temp->threadid == threadid) { char *pid = " PID: "; char *pid_current = "*PID: "; - char *name = "NAME: "; + char *name = "Name: "; int str_size = strlen(pid) + strlen(name); - char *tmp_str = (char *)calloc(1, str_size + 50); + char *tmp_str = calloc(1, str_size + 50); char *tmp_str_ptr = tmp_str; - /* discriminate cuurent task */ + /* discriminate current task */ if (temp->status == 3) tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid_current); else tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid); - tmp_str_ptr += - sprintf(tmp_str_ptr, "%d", (int)temp->pid); - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", " | "); - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", name); - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", temp->name); - char *hex_str = - (char *)calloc(1, strlen(tmp_str) * 2 + 1); - str_to_hex(hex_str, tmp_str); - gdb_put_packet(connection, hex_str, strlen(hex_str)); + tmp_str_ptr += sprintf(tmp_str_ptr, "%d, ", (int)temp->pid); + sprintf(tmp_str_ptr, "%s", name); + sprintf(tmp_str_ptr, "%s", temp->name); + char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1); + size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str, + strlen(tmp_str), strlen(tmp_str) * 2 + 1); + gdb_put_packet(connection, hex_str, pkt_len); free(hex_str); free(tmp_str); return ERROR_OK; @@ -1233,7 +1168,7 @@ int linux_thread_extra_info(struct target *target, } int linux_gdb_T_packet(struct connection *connection, - struct target *target, char *packet, int packet_size) + struct target *target, char const *packet, int packet_size) { int64_t threadid; struct linux_os *linux_os = (struct linux_os *) @@ -1294,7 +1229,7 @@ int linux_gdb_T_packet(struct connection *connection, } int linux_gdb_h_packet(struct connection *connection, - struct target *target, char *packet, int packet_size) + struct target *target, char const *packet, int packet_size) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; @@ -1362,7 +1297,7 @@ int linux_gdb_h_packet(struct connection *connection, return ERROR_OK; } -static int linux_thread_packet(struct connection *connection, char *packet, +static int linux_thread_packet(struct connection *connection, char const *packet, int packet_size) { int retval = ERROR_OK; @@ -1383,10 +1318,8 @@ static int linux_thread_packet(struct connection *connection, char *packet, break; case 'q': - if ((strstr(packet, "qSymbol"))) { + if (strncmp(packet, "qSymbol", 7) == 0) { if (rtos_qsymbol(connection, packet, packet_size) == 1) { - gdb_put_packet(connection, "OK", 2); - linux_compute_virt2phys(target, target->rtos-> symbols[INIT_TASK]. @@ -1394,7 +1327,7 @@ static int linux_thread_packet(struct connection *connection, char *packet, } break; - } else if (strstr(packet, "qfThreadInfo")) { + } else if (strncmp(packet, "qfThreadInfo", 12) == 0) { if (linux_os->thread_list == NULL) { retval = linux_gdb_thread_packet(target, connection, @@ -1408,10 +1341,10 @@ static int linux_thread_packet(struct connection *connection, char *packet, packet_size); break; } - } else if (strstr(packet, "qsThreadInfo")) { + } else if (strncmp(packet, "qsThreadInfo", 12) == 0) { gdb_put_packet(connection, "l", 1); break; - } else if (strstr(packet, "qThreadExtraInfo,")) { + } else if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) { linux_thread_extra_info(target, connection, packet, packet_size); break; @@ -1454,7 +1387,7 @@ static int linux_thread_packet(struct connection *connection, char *packet, } } - /* if a packet handler returned an error, exit input loop */ + /* if a packet handler returned an error, exit input loop */ if (retval != ERROR_OK) return retval; } @@ -1512,7 +1445,7 @@ static int linux_os_create(struct target *target) os_linux->threads_needs_update = 0; os_linux->threadid_count = 1; os_linux->current_threads = NULL; - target->rtos->rtos_specific_params = (void *)os_linux; + target->rtos->rtos_specific_params = os_linux; ct->core_id = target->coreid; ct->threadid = -1; ct->TS = 0xdeadbeef; @@ -1559,14 +1492,14 @@ static char *linux_ps_command(struct target *target) if (temp->context) tmp += sprintf(tmp, - "%d\t\t%d\t\t%x\t\t%s\n", - (int)temp->pid, temp->oncpu, + "%" PRId32 "\t\t%" PRId32 "\t\t%" PRIx32 "\t\t%s\n", + temp->pid, temp->oncpu, temp->asid, temp->name); else tmp += sprintf(tmp, - "%d\t\t%d\t\t%x\t\t%s\n", - (int)temp->pid, temp->oncpu, + "%" PRId32 "\t\t%" PRId32 "\t\t%" PRIx32 "\t\t%s\n", + temp->pid, temp->oncpu, temp->asid, temp->name); }