diff options
Diffstat (limited to 'gdb/ada-tasks.c')
-rw-r--r-- | gdb/ada-tasks.c | 820 |
1 files changed, 0 insertions, 820 deletions
diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c deleted file mode 100644 index eccd5a1..0000000 --- a/gdb/ada-tasks.c +++ /dev/null @@ -1,820 +0,0 @@ -/* file ada-tasks.c: Ada tasking control for GDB - Copyright 1997 Free Software Foundation, Inc. - Contributed by Ada Core Technologies, Inc -. - This file is part of GDB. - - [$Id$] - Authors: Roch-Alexandre Nomine Beguin, Arnaud Charlet <charlet@gnat.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - -*/ - -#include <ctype.h> -#include "defs.h" -#include "command.h" -#include "value.h" -#include "language.h" -#include "inferior.h" -#include "symtab.h" -#include "target.h" -#include "gdbcore.h" - -#if (defined(__alpha__) && defined(__osf__) && !defined(__alpha_vxworks)) -#include <sys/procfs.h> -#endif - -#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)) -#include "gregset.h" -#endif - -#include "ada-lang.h" - -/* FIXME: move all this conditional compilation in description - files or in configure.in */ - -#if defined (VXWORKS_TARGET) -#define THREAD_TO_PID(tid,lwpid) (tid) - -#elif defined (linux) -#define THREAD_TO_PID(tid,lwpid) (0) - -#elif (defined (sun) && defined (__SVR4)) -#define THREAD_TO_PID thread_to_pid - -#elif defined (sgi) || defined (__WIN32__) || defined (hpux) -#define THREAD_TO_PID(tid,lwpid) ((int)lwpid) - -#else -#define THREAD_TO_PID(tid,lwpid) (0) -#endif - -#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET) -#define THREAD_FETCH_REGISTERS dec_thread_fetch_registers -#define GET_CURRENT_THREAD dec_thread_get_current_thread -extern int dec_thread_get_registers (gdb_gregset_t *, gdb_fpregset_t *); -#endif - -#if defined (_AIX) -#define THREAD_FETCH_REGISTERS aix_thread_fetch_registers -#define GET_CURRENT_THREAD aix_thread_get_current_thread -#endif - -#if defined(VXWORKS_TARGET) -#define GET_CURRENT_THREAD() ((void*)inferior_pid) -#define THREAD_FETCH_REGISTERS() (-1) - -#elif defined (sun) && defined (__SVR4) -#define GET_CURRENT_THREAD solaris_thread_get_current_thread -#define THREAD_FETCH_REGISTERS() (-1) -extern void *GET_CURRENT_THREAD (); - -#elif defined (_AIX) || (defined(__alpha__) && defined(__osf__)) -extern void *GET_CURRENT_THREAD (); - -#elif defined (__WIN32__) || defined (hpux) -#define GET_CURRENT_THREAD() (inferior_pid) -#define THREAD_FETCH_REGISTERS() (-1) - -#else -#define GET_CURRENT_THREAD() (NULL) -#define THREAD_FETCH_REGISTERS() (-1) -#endif - -#define KNOWN_TASKS_NAME "system__tasking__debug__known_tasks" - -#define READ_MEMORY(addr, var) read_memory (addr, (char*) &var, sizeof (var)) -/* external declarations */ - -extern struct value *find_function_in_inferior (char *); - -/* Global visible variables */ - -struct task_entry *task_list = NULL; -int ada__tasks_check_symbol_table = 1; -void *pthread_kern_addr = NULL; - -#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)) -gdb_gregset_t gregset_saved; -gdb_fpregset_t fpregset_saved; -#endif - -/* The maximum number of tasks known to the Ada runtime */ -const int MAX_NUMBER_OF_KNOWN_TASKS = 1000; - -/* the current task */ -int current_task = -1, current_task_id = -1, current_task_index; -void *current_thread, *current_lwp; - -char *ada_task_states[] = { - "Unactivated", - "Runnable", - "Terminated", - "Child Activation Wait", - "Accept Statement", - "Waiting on entry call", - "Async Select Wait", - "Delay Sleep", - "Child Termination Wait", - "Wait Child in Term Alt", - "", - "", - "", - "", - "Asynchronous Hold" -}; - -/* Global internal types */ - -static char *ada_long_task_states[] = { - "Unactivated", - "Runnable", - "Terminated", - "Waiting for child activation", - "Blocked in accept statement", - "Waiting on entry call", - "Asynchronous Selective Wait", - "Delay Sleep", - "Waiting for children termination", - "Waiting for children in terminate alternative", - "", - "", - "", - "", - "Asynchronous Hold" -}; - -/* Global internal variables */ - -static int highest_task_num = 0; -int thread_support = 0; /* 1 if the thread library in use is supported */ -static int gdbtk_task_initialization = 0; - -static int -add_task_entry (void *p_task_id, int index) -{ - struct task_entry *new_task_entry = NULL; - struct task_entry *pt; - - highest_task_num++; - new_task_entry = xmalloc (sizeof (struct task_entry)); - new_task_entry->task_num = highest_task_num; - new_task_entry->task_id = p_task_id; - new_task_entry->known_tasks_index = index; - new_task_entry->next_task = NULL; - pt = task_list; - if (pt) - { - while (pt->next_task) - pt = pt->next_task; - pt->next_task = new_task_entry; - pt->stack_per = 0; - } - else - task_list = new_task_entry; - return new_task_entry->task_num; -} - -int -get_entry_number (void *p_task_id) -{ - struct task_entry *pt; - - pt = task_list; - while (pt != NULL) - { - if (pt->task_id == p_task_id) - return pt->task_num; - pt = pt->next_task; - } - return 0; -} - -static struct task_entry * -get_thread_entry_vptr (void *thread) -{ - struct task_entry *pt; - - pt = task_list; - while (pt != NULL) - { - if (pt->thread == thread) - return pt; - pt = pt->next_task; - } - return 0; -} - -static struct task_entry * -get_entry_vptr (int p_task_num) -{ - struct task_entry *pt; - - pt = task_list; - while (pt) - { - if (pt->task_num == p_task_num) - return pt; - pt = pt->next_task; - } - return NULL; -} - -void -init_task_list (void) -{ - struct task_entry *pt, *old_pt; - - pt = task_list; - while (pt) - { - old_pt = pt; - pt = pt->next_task; - xfree (old_pt); - }; - task_list = NULL; - highest_task_num = 0; -} - -int -valid_task_id (int task) -{ - return get_entry_vptr (task) != NULL; -} - -void * -get_self_id (void) -{ - struct value *val; - void *self_id; - int result; - struct task_entry *ent; - extern int do_not_insert_breakpoints; - -#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__)) - if (thread_support) -#endif - { - ent = get_thread_entry_vptr (GET_CURRENT_THREAD ()); - return ent ? ent->task_id : 0; - } - - /* FIXME: calling a function in the inferior with a multithreaded application - is not reliable, so return NULL if there is no safe way to get the current - task */ - return NULL; -} - -int -get_current_task () -{ - int result; - - /* FIXME: language_ada should be defined in defs.h */ - /* if (current_language->la_language != language_ada) return -1; */ - - result = get_entry_number (get_self_id ()); - - /* return -1 if not found */ - return result == 0 ? -1 : result; -} - -/* Print detailed information about specified task */ - -static void -info_task (char *arg, int from_tty) -{ - void *temp_task; - struct task_entry *pt, *pt2; - void *self_id, *caller; - struct task_fields atcb, atcb2; - struct entry_call call; - int bounds[2]; - char image[256]; - int num; - - /* FIXME: language_ada should be defined in defs.h */ - /* if (current_language->la_language != language_ada) - { - printf_filtered ("The current language does not support tasks.\n"); - return; - } - */ - pt = get_entry_vptr (atoi (arg)); - if (pt == NULL) - { - printf_filtered ("Task %s not found.\n", arg); - return; - } - - temp_task = pt->task_id; - - /* read the atcb in the inferior */ - READ_MEMORY ((CORE_ADDR) temp_task, atcb); - - /* print the Ada task id */ - printf_filtered ("Ada Task: %p\n", temp_task); - - /* print the name of the task */ - if (atcb.image.P_ARRAY != NULL) - { - READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS), bounds); - bounds[1] = EXTRACT_INT (bounds[1]); - read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_ARRAY), - (char *) &image, bounds[1]); - printf_filtered ("Name: %.*s\n", bounds[1], image); - } - else - printf_filtered ("<no name>\n"); - - /* print the thread id */ - - if ((long) pt->thread < 65536) - printf_filtered ("Thread: %ld\n", (long int) pt->thread); - else - printf_filtered ("Thread: %p\n", pt->thread); - - if ((long) pt->lwp != 0) - { - if ((long) pt->lwp < 65536) - printf_filtered ("LWP: %ld\n", (long int) pt->lwp); - else - printf_filtered ("LWP: %p\n", pt->lwp); - } - - /* print the parent gdb task id */ - num = get_entry_number (EXTRACT_ADDRESS (atcb.parent)); - if (num != 0) - { - printf_filtered ("Parent: %d", num); - pt2 = get_entry_vptr (num); - READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2); - - /* print the name of the task */ - if (atcb2.image.P_ARRAY != NULL) - { - READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS), - bounds); - bounds[1] = EXTRACT_INT (bounds[1]); - read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_ARRAY), - (char *) &image, bounds[1]); - printf_filtered (" (%.*s)\n", bounds[1], image); - } - else - printf_filtered ("\n"); - } - else - printf_filtered ("No parent\n"); - - /* print the base priority of the task */ - printf_filtered ("Base Priority: %d\n", EXTRACT_INT (atcb.priority)); - - /* print the current state of the task */ - - /* check if this task is accepting a rendezvous */ - if (atcb.call == NULL) - caller = NULL; - else - { - READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call); - caller = EXTRACT_ADDRESS (call.self); - } - - if (caller != NULL) - { - num = get_entry_number (caller); - printf_filtered ("Accepting rendezvous with %d", num); - - if (num != 0) - { - pt2 = get_entry_vptr (num); - READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2); - - /* print the name of the task */ - if (atcb2.image.P_ARRAY != NULL) - { - READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS), - bounds); - bounds[1] = EXTRACT_INT (bounds[1]); - read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_ARRAY), - (char *) &image, bounds[1]); - printf_filtered (" (%.*s)\n", bounds[1], image); - } - else - printf_filtered ("\n"); - } - else - printf_filtered ("\n"); - } - else - printf_filtered ("State: %s\n", ada_long_task_states[atcb.state]); -} - -#if 0 - -/* A useful function that shows the alignment of all the fields in the - tasks_fields structure - */ - -print_align (void) -{ - struct task_fields tf; - void *tf_base = &(tf); - void *tf_state = &(tf.state); - void *tf_entry_num = &(tf.entry_num); - void *tf_parent = &(tf.parent); - void *tf_priority = &(tf.priority); - void *tf_current_priority = &(tf.current_priority); - void *tf_image = &(tf.image); - void *tf_call = &(tf.call); - void *tf_thread = &(tf.thread); - void *tf_lwp = &(tf.lwp); - printf_filtered ("\n"); - printf_filtered ("(tf_base = 0x%x)\n", tf_base); - printf_filtered ("task_fields.entry_num at %3d (0x%x)\n", - tf_entry_num - tf_base, tf_entry_num); - printf_filtered ("task_fields.state at %3d (0x%x)\n", - tf_state - tf_base, tf_state); - printf_filtered ("task_fields.parent at %3d (0x%x)\n", - tf_parent - tf_base, tf_parent); - printf_filtered ("task_fields.priority at %3d (0x%x)\n", - tf_priority - tf_base, tf_priority); - printf_filtered ("task_fields.current_priority at %3d (0x%x)\n", - tf_current_priority - tf_base, tf_current_priority); - printf_filtered ("task_fields.image at %3d (0x%x)\n", - tf_image - tf_base, tf_image); - printf_filtered ("task_fields.call at %3d (0x%x)\n", - tf_call - tf_base, tf_call); - printf_filtered ("task_fields.thread at %3d (0x%x)\n", - tf_thread - tf_base, tf_thread); - printf_filtered ("task_fields.lwp at %3d (0x%x)\n", - tf_lwp - tf_base, tf_lwp); - printf_filtered ("\n"); -} -#endif - -/* Print information about currently known tasks */ - -static void -info_tasks (char *arg, int from_tty) -{ - struct value *val; - int i, task_number, state; - void *temp_task, *temp_tasks[MAX_NUMBER_OF_KNOWN_TASKS]; - struct task_entry *pt; - void *self_id, *caller, *thread_id = NULL; - struct task_fields atcb; - struct entry_call call; - int bounds[2]; - char image[256]; - int size; - char car; - -#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET) - pthreadTeb_t thr; - gdb_gregset_t regs; -#endif - - static struct symbol *sym; - static struct minimal_symbol *msym; - static void *known_tasks_addr = NULL; - - int init_only = gdbtk_task_initialization; - gdbtk_task_initialization = 0; - - task_number = 0; - - if (PIDGET (inferior_ptid) == 0) - { - printf_filtered ("The program is not being run under gdb. "); - printf_filtered ("Use 'run' or 'attach' first.\n"); - return; - } - - if (ada__tasks_check_symbol_table) - { - thread_support = 0; -#if (defined(__alpha__) && defined(__osf__) & !defined(VXWORKS_TARGET)) || \ - defined (_AIX) - thread_support = 1; -#endif - - msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL); - if (msym != NULL) - known_tasks_addr = (void *) SYMBOL_VALUE_ADDRESS (msym); - else -#ifndef VXWORKS_TARGET - return; -#else - { - if (target_lookup_symbol (KNOWN_TASKS_NAME, &known_tasks_addr) != 0) - return; - } -#endif - - ada__tasks_check_symbol_table = 0; - } - - if (known_tasks_addr == NULL) - return; - -#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__) || defined (hpux)) - if (thread_support) -#endif - thread_id = GET_CURRENT_THREAD (); - - /* then we get a list of tasks created */ - - init_task_list (); - - READ_MEMORY ((CORE_ADDR) known_tasks_addr, temp_tasks); - - for (i = 0; i < MAX_NUMBER_OF_KNOWN_TASKS; i++) - { - temp_task = EXTRACT_ADDRESS (temp_tasks[i]); - - if (temp_task != NULL) - { - task_number = get_entry_number (temp_task); - if (task_number == 0) - task_number = add_task_entry (temp_task, i); - } - } - - /* Return without printing anything if this function was called in - order to init GDBTK tasking. */ - - if (init_only) - return; - - /* print the header */ - -#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET) - printf_filtered - (" ID TID P-ID Pri Stack %% State Name\n"); -#else - printf_filtered (" ID TID P-ID Pri State Name\n"); -#endif - - /* Now that we have a list of task id's, we can print them */ - pt = task_list; - while (pt) - { - temp_task = pt->task_id; - - /* read the atcb in the inferior */ - READ_MEMORY ((CORE_ADDR) temp_task, atcb); - - /* store the thread id for future use */ - pt->thread = EXTRACT_ADDRESS (atcb.thread); - -#if defined (linux) - pt->lwp = (void *) THREAD_TO_PID (atcb.thread, 0); -#else - pt->lwp = EXTRACT_ADDRESS (atcb.lwp); -#endif - - /* print a star if this task is the current one */ - if (thread_id) -#if defined (__WIN32__) || defined (SGI) || defined (hpux) - printf_filtered (pt->lwp == thread_id ? "*" : " "); -#else - printf_filtered (pt->thread == thread_id ? "*" : " "); -#endif - - /* print the gdb task id */ - printf_filtered ("%3d", pt->task_num); - - /* print the Ada task id */ -#ifndef VXWORKS_TARGET - printf_filtered (" %9lx", (long) temp_task); -#else -#ifdef TARGET_64 - printf_filtered (" %#9lx", (unsigned long) pt->thread & 0x3ffffffffff); -#else - printf_filtered (" %#9lx", (long) pt->thread); -#endif -#endif - - /* print the parent gdb task id */ - printf_filtered - (" %4d", get_entry_number (EXTRACT_ADDRESS (atcb.parent))); - - /* print the base priority of the task */ - printf_filtered (" %3d", EXTRACT_INT (atcb.priority)); - -#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET) - if (pt->task_num == 1 || atcb.state == Terminated) - { - printf_filtered (" Unknown"); - goto next; - } - - read_memory ((CORE_ADDR) atcb.thread, &thr, sizeof (thr)); - current_thread = atcb.thread; - regs.regs[SP_REGNUM] = 0; - if (dec_thread_get_registers (®s, NULL) == 0) - { - pt->stack_per = (100 * ((long) thr.__stack_base - - regs.regs[SP_REGNUM])) / thr.__stack_size; - /* if the thread is terminated but still there, the - stack_base/size values are erroneous. Try to patch it */ - if (pt->stack_per < 0 || pt->stack_per > 100) - pt->stack_per = 0; - } - - /* print information about stack space used in the thread */ - if (thr.__stack_size < 1024 * 1024) - { - size = thr.__stack_size / 1024; - car = 'K'; - } - else if (thr.__stack_size < 1024 * 1024 * 1024) - { - size = thr.__stack_size / 1024 / 1024; - car = 'M'; - } - else /* Who knows... */ - { - size = thr.__stack_size / 1024 / 1024 / 1024; - car = 'G'; - } - printf_filtered (" %4d%c %2d", size, car, pt->stack_per); - next: -#endif - - /* print the current state of the task */ - - /* check if this task is accepting a rendezvous */ - if (atcb.call == NULL) - caller = NULL; - else - { - READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call); - caller = EXTRACT_ADDRESS (call.self); - } - - if (caller != NULL) - printf_filtered (" Accepting RV with %-4d", - get_entry_number (caller)); - else - { - state = atcb.state; -#if defined (__WIN32__) || defined (SGI) || defined (hpux) - if (state == Runnable && (thread_id && pt->lwp == thread_id)) -#else - if (state == Runnable && (thread_id && pt->thread == thread_id)) -#endif - /* Replace "Runnable" by "Running" if this is the current task */ - printf_filtered (" %-22s", "Running"); - else - printf_filtered (" %-22s", ada_task_states[state]); - } - - /* finally, print the name of the task */ - if (atcb.image.P_ARRAY != NULL) - { - READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS), - bounds); - bounds[1] = EXTRACT_INT (bounds[1]); - read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_ARRAY), - (char *) &image, bounds[1]); - printf_filtered (" %.*s\n", bounds[1], image); - } - else - printf_filtered (" <no name>\n"); - - pt = pt->next_task; - } -} - -/* Task list initialization for GDB-Tk. We basically use info_tasks() - to initialize our variables, but abort that function before we - actually print anything. */ - -int -gdbtk_tcl_tasks_initialize (void) -{ - gdbtk_task_initialization = 1; - info_tasks ("", gdb_stdout); - - return (task_list != NULL); -} - -static void -info_tasks_command (char *arg, int from_tty) -{ - if (arg == NULL || *arg == '\000') - info_tasks (arg, from_tty); - else - info_task (arg, from_tty); -} - -/* Switch from one thread to another. */ - -static void -switch_to_thread (ptid_t ptid) -{ - if (ptid_equal (ptid, inferior_ptid)) - return; - - inferior_ptid = ptid; - flush_cached_frames (); - registers_changed (); - stop_pc = read_pc (); - select_frame (get_current_frame ()); -} - -/* Switch to a specified task. */ - -static int -task_switch (void *tid, void *lwpid) -{ - int res = 0, pid; - - if (thread_support) - { - flush_cached_frames (); - - if (current_task != current_task_id) - { - res = THREAD_FETCH_REGISTERS (); - } - else - { -#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)) - supply_gregset (&gregset_saved); - supply_fpregset (&fpregset_saved); -#endif - } - - if (res == 0) - stop_pc = read_pc (); - select_frame (get_current_frame ()); - return res; - } - - return -1; -} - -static void -task_command (char *tidstr, int from_tty) -{ - int num; - struct task_entry *e; - - if (!tidstr) - error ("Please specify a task ID. Use the \"info tasks\" command to\n" - "see the IDs of currently known tasks."); - - num = atoi (tidstr); - e = get_entry_vptr (num); - - if (e == NULL) - error ("Task ID %d not known. Use the \"info tasks\" command to\n" - "see the IDs of currently known tasks.", num); - - if (current_task_id == -1) - { -#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)) - fill_gregset (&gregset_saved, -1); - fill_fpregset (&fpregset_saved, -1); -#endif - current_task_id = get_current_task (); - } - - current_task = num; - current_task_index = e->known_tasks_index; - current_thread = e->thread; - current_lwp = e->lwp; - if (task_switch (e->thread, e->lwp) == 0) - { - /* FIXME: find_printable_frame should be defined in frame.h, and - implemented in ada-lang.c */ - /* find_printable_frame (selected_frame, frame_relative_level (selected_frame)); */ - printf_filtered ("[Switching to task %d]\n", num); - print_stack_frame (selected_frame, - frame_relative_level (selected_frame), 1); - } - else - printf_filtered ("Unable to switch to task %d\n", num); -} - -void -_initialize_tasks (void) -{ - static struct cmd_list_element *task_cmd_list = NULL; - extern struct cmd_list_element *cmdlist; - - add_info ("tasks", info_tasks_command, - "Without argument: list all known Ada tasks, with status information.\n" - "info tasks n: print detailed information of task n.\n"); - - add_prefix_cmd ("task", class_run, task_command, - "Use this command to switch between tasks.\n\ - The new task ID must be currently known.", &task_cmd_list, "task ", 1, &cmdlist); -} |