Fix Sparc %fsr regset offset for BSD and Linux.
[deliverable/binutils-gdb.git] / gdb / ada-tasks.c
index 2673fed6ab743a4f635351e863f75b20206a5af9..02ac6d0d07ba715da38cba5897efd72926309341 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (C) 1992, 1993, 1994, 1997, 1998, 1999, 2000, 2003, 2004, 2005,
-   2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1992-1994, 1997-2000, 2003-2005, 2007-2012 Free
+   Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -215,6 +215,12 @@ struct ada_tasks_inferior_data
      above.  */
   CORE_ADDR known_tasks_addr;
 
+  /* Type of elements of the known task.  Usually a pointer.  */
+  struct type *known_tasks_element;
+
+  /* Number of elements in the known tasks array.  */
+  unsigned int known_tasks_length;
+
   /* When nonzero, this flag indicates that the task_list field
      below is up to date.  When set to zero, the list has either
      not been initialized, or has potentially become stale.  */
@@ -591,7 +597,7 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
   struct value *entry_calls_value;
   struct value *entry_calls_value_element;
   int called_task_fieldno = -1;
-  const char ravenscar_task_name[] = "Ravenscar task";
+  static const char ravenscar_task_name[] = "Ravenscar task";
   const struct ada_tasks_pspace_data *pspace_data
     = get_ada_tasks_pspace_data (current_program_space);
 
@@ -629,7 +635,31 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
                                            pspace_data->atcb_fieldno.image),
                                sizeof (task_info->name) - 1);
       else
-        strcpy (task_info->name, ravenscar_task_name);
+       {
+         struct minimal_symbol *msym;
+
+         msym = lookup_minimal_symbol_by_pc (task_id);
+         if (msym)
+           {
+             const char *full_name = SYMBOL_LINKAGE_NAME (msym);
+             const char *task_name = full_name;
+             const char *p;
+
+             /* Strip the prefix.  */
+             for (p = full_name; *p; p++)
+               if (p[0] == '_' && p[1] == '_')
+                 task_name = p + 2;
+
+             /* Copy the task name.  */
+             strncpy (task_info->name, task_name, sizeof (task_info->name));
+             task_info->name[sizeof (task_info->name) - 1] = 0;
+           }
+         else
+           {
+             /* No symbol found.  Use a default name.  */
+             strcpy (task_info->name, ravenscar_task_name);
+           }
+       }
     }
   else
     {
@@ -750,24 +780,21 @@ add_ada_task (CORE_ADDR task_id, struct inferior *inf)
    it in the current inferior's TASK_LIST.  Return non-zero upon success.  */
 
 static int
-read_known_tasks_array (CORE_ADDR known_tasks_addr)
+read_known_tasks_array (struct ada_tasks_inferior_data *data)
 {
-  const int target_ptr_byte =
-    gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT;
-  const int known_tasks_size = target_ptr_byte * MAX_NUMBER_OF_KNOWN_TASKS;
+  const int target_ptr_byte = TYPE_LENGTH (data->known_tasks_element);
+  const int known_tasks_size = target_ptr_byte * data->known_tasks_length;
   gdb_byte *known_tasks = alloca (known_tasks_size);
   int i;
 
   /* Build a new list by reading the ATCBs from the Known_Tasks array
      in the Ada runtime.  */
-  read_memory (known_tasks_addr, known_tasks, known_tasks_size);
-  for (i = 0; i < MAX_NUMBER_OF_KNOWN_TASKS; i++)
+  read_memory (data->known_tasks_addr, known_tasks, known_tasks_size);
+  for (i = 0; i < data->known_tasks_length; i++)
     {
-      struct type *data_ptr_type =
-        builtin_type (target_gdbarch)->builtin_data_ptr;
       CORE_ADDR task_id =
         extract_typed_address (known_tasks + i * target_ptr_byte,
-                              data_ptr_type);
+                              data->known_tasks_element);
 
       if (task_id != 0)
         add_ada_task (task_id, current_inferior ());
@@ -780,13 +807,10 @@ read_known_tasks_array (CORE_ADDR known_tasks_addr)
    the current inferior's TASK_LIST.  Return non-zero upon success.  */
 
 static int
-read_known_tasks_list (CORE_ADDR known_tasks_addr)
+read_known_tasks_list (struct ada_tasks_inferior_data *data)
 {
-  const int target_ptr_byte =
-    gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT;
+  const int target_ptr_byte = TYPE_LENGTH (data->known_tasks_element);
   gdb_byte *known_tasks = alloca (target_ptr_byte);
-  struct type *data_ptr_type =
-    builtin_type (target_gdbarch)->builtin_data_ptr;
   CORE_ADDR task_id;
   const struct ada_tasks_pspace_data *pspace_data
     = get_ada_tasks_pspace_data (current_program_space);
@@ -796,8 +820,8 @@ read_known_tasks_list (CORE_ADDR known_tasks_addr)
     return 0;
 
   /* Build a new list by reading the ATCBs.  Read head of the list.  */
-  read_memory (known_tasks_addr, known_tasks, target_ptr_byte);
-  task_id = extract_typed_address (known_tasks, data_ptr_type);
+  read_memory (data->known_tasks_addr, known_tasks, target_ptr_byte);
+  task_id = extract_typed_address (known_tasks, data->known_tasks_element);
   while (task_id != 0)
     {
       struct value *tcb_value;
@@ -817,51 +841,96 @@ read_known_tasks_list (CORE_ADDR known_tasks_addr)
   return 1;
 }
 
-/* Return the address of the variable NAME that contains all the known
-   tasks maintained in the Ada Runtime.  Return NULL if the variable
-   could not be found, meaning that the inferior program probably does
-   not use tasking.  */
-
-static CORE_ADDR
-get_known_tasks_addr (const char *name)
-{
-  struct minimal_symbol *msym;
-
-  msym = lookup_minimal_symbol (name, NULL, NULL);
-  if (msym == NULL)
-    return 0;
-
-  return SYMBOL_VALUE_ADDRESS (msym);
-}
-
-/* Assuming DATA is the ada-tasks' data for the current inferior,
-   set the known_tasks_kind and known_tasks_addr fields.  Do nothing
-   if those fields are already set and still up to date.  */
+/* Set all fields of the current inferior ada-tasks data pointed by DATA.
+   Do nothing if those fields are already set and still up to date.  */
 
 static void
-ada_set_current_inferior_known_tasks_addr (struct ada_tasks_inferior_data *data)
+ada_tasks_inferior_data_sniffer (struct ada_tasks_inferior_data *data)
 {
-  CORE_ADDR known_tasks_addr;
+  struct minimal_symbol *msym;
+  struct symbol *sym;
 
+  /* Return now if already set.  */
   if (data->known_tasks_kind != ADA_TASKS_UNKNOWN)
     return;
 
-  known_tasks_addr = get_known_tasks_addr (KNOWN_TASKS_NAME);
-  if (known_tasks_addr != 0)
+  /* Try array.  */
+
+  msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
+  if (msym != NULL)
     {
       data->known_tasks_kind = ADA_TASKS_ARRAY;
-      data->known_tasks_addr = known_tasks_addr;
+      data->known_tasks_addr = SYMBOL_VALUE_ADDRESS (msym);
+
+      /* Try to get pointer type and array length from the symtab.  */
+      sym = lookup_symbol_in_language (KNOWN_TASKS_NAME, NULL, VAR_DOMAIN,
+                                      language_c, NULL);
+      if (sym != NULL)
+       {
+         /* Validate.  */
+         struct type *type = check_typedef (SYMBOL_TYPE (sym));
+         struct type *eltype = NULL;
+         struct type *idxtype = NULL;
+
+         if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+           eltype = check_typedef (TYPE_TARGET_TYPE (type));
+         if (eltype != NULL
+             && TYPE_CODE (eltype) == TYPE_CODE_PTR)
+           idxtype = check_typedef (TYPE_INDEX_TYPE (type));
+         if (idxtype != NULL
+             && !TYPE_LOW_BOUND_UNDEFINED (idxtype)
+             && !TYPE_HIGH_BOUND_UNDEFINED (idxtype))
+           {
+             data->known_tasks_element = eltype;
+             data->known_tasks_length =
+               TYPE_HIGH_BOUND (idxtype) - TYPE_LOW_BOUND (idxtype) + 1;
+             return;
+           }
+       }
+
+      /* Fallback to default values.  The runtime may have been stripped (as
+        in some distributions), but it is likely that the executable still
+        contains debug information on the task type (due to implicit with of
+        Ada.Tasking).  */
+      data->known_tasks_element =
+       builtin_type (target_gdbarch ())->builtin_data_ptr;
+      data->known_tasks_length = MAX_NUMBER_OF_KNOWN_TASKS;
       return;
     }
 
-  known_tasks_addr = get_known_tasks_addr (KNOWN_TASKS_LIST);
-  if (known_tasks_addr != 0)
+
+  /* Try list.  */
+
+  msym = lookup_minimal_symbol (KNOWN_TASKS_LIST, NULL, NULL);
+  if (msym != NULL)
     {
       data->known_tasks_kind = ADA_TASKS_LIST;
-      data->known_tasks_addr = known_tasks_addr;
+      data->known_tasks_addr = SYMBOL_VALUE_ADDRESS (msym);
+      data->known_tasks_length = 1;
+
+      sym = lookup_symbol_in_language (KNOWN_TASKS_LIST, NULL, VAR_DOMAIN,
+                                      language_c, NULL);
+      if (sym != NULL && SYMBOL_VALUE_ADDRESS (sym) != 0)
+       {
+         /* Validate.  */
+         struct type *type = check_typedef (SYMBOL_TYPE (sym));
+
+         if (TYPE_CODE (type) == TYPE_CODE_PTR)
+           {
+             data->known_tasks_element = type;
+             return;
+           }
+       }
+
+      /* Fallback to default values.  */
+      data->known_tasks_element =
+       builtin_type (target_gdbarch ())->builtin_data_ptr;
+      data->known_tasks_length = 1;
       return;
     }
 
+  /* Can't find tasks.  */
+
   data->known_tasks_kind = ADA_TASKS_NOT_FOUND;
   data->known_tasks_addr = 0;
 }
@@ -885,7 +954,7 @@ read_known_tasks (void)
      return, as we don't want a stale task list to be used...  This can
      happen for instance when debugging a non-multitasking program after
      having debugged a multitasking one.  */
-  ada_set_current_inferior_known_tasks_addr (data);
+  ada_tasks_inferior_data_sniffer (data);
   gdb_assert (data->known_tasks_kind != ADA_TASKS_UNKNOWN);
 
   switch (data->known_tasks_kind)
@@ -893,9 +962,9 @@ read_known_tasks (void)
       case ADA_TASKS_NOT_FOUND: /* Tasking not in use in inferior.  */
         return 0;
       case ADA_TASKS_ARRAY:
-        return read_known_tasks_array (data->known_tasks_addr);
+        return read_known_tasks_array (data);
       case ADA_TASKS_LIST:
-        return read_known_tasks_list (data->known_tasks_addr);
+        return read_known_tasks_list (data);
     }
 
   /* Step 3: Set task_list_valid_p, to avoid re-reading the Known_Tasks
@@ -960,7 +1029,21 @@ print_ada_task_info (struct ui_out *uiout,
     target_find_new_threads ();
 
   data = get_ada_tasks_inferior_data (inf);
-  nb_tasks = VEC_length (ada_task_info_s, data->task_list);
+
+  /* Compute the number of tasks that are going to be displayed
+     in the output.  If an argument was given, there will be
+     at most 1 entry.  Otherwise, there will be as many entries
+     as we have tasks.  */
+  if (taskno_arg)
+    {
+      if (taskno_arg > 0
+         && taskno_arg <= VEC_length (ada_task_info_s, data->task_list))
+       nb_tasks = 1;
+      else
+       nb_tasks = 0;
+    }
+  else
+    nb_tasks = VEC_length (ada_task_info_s, data->task_list);
 
   nb_columns = ui_out_is_mi_like_p (uiout) ? 8 : 7;
   old_chain = make_cleanup_ui_out_table_begin_end (uiout, nb_columns,
@@ -982,7 +1065,9 @@ print_ada_task_info (struct ui_out *uiout,
   ui_out_table_header (uiout, 1, ui_noalign, "name", "Name");
   ui_out_table_body (uiout);
 
-  for (taskno = 1; taskno <= nb_tasks; taskno++)
+  for (taskno = 1;
+       taskno <= VEC_length (ada_task_info_s, data->task_list);
+       taskno++)
     {
       const struct ada_task_info *const task_info =
        VEC_index (ada_task_info_s, data->task_list, taskno - 1);
@@ -1088,7 +1173,7 @@ info_task (struct ui_out *uiout, char *taskno_str, struct inferior *inf)
 
   /* Print the Ada task ID.  */
   printf_filtered (_("Ada Task: %s\n"),
-                  paddress (target_gdbarch, task_info->task_id));
+                  paddress (target_gdbarch (), task_info->task_id));
 
   /* Print the name of the task.  */
   if (task_info->name[0] != '\0')
This page took 0.028397 seconds and 4 git commands to generate.