+ /* Build a new list by reading the ATCBs from the Known_Tasks array
+ in the Ada runtime. */
+ read_memory (data->known_tasks_addr, known_tasks, known_tasks_size);
+ for (i = 0; i < data->known_tasks_length; i++)
+ {
+ CORE_ADDR task_id =
+ extract_typed_address (known_tasks + i * target_ptr_byte,
+ data->known_tasks_element);
+
+ if (task_id != 0)
+ add_ada_task (task_id, current_inferior ());
+ }
+
+ return 1;
+}
+
+/* Read the known tasks from the inferior memory, and store it in
+ the current inferior's TASK_LIST. Return non-zero upon success. */
+
+static int
+read_known_tasks_list (struct ada_tasks_inferior_data *data)
+{
+ const int target_ptr_byte = TYPE_LENGTH (data->known_tasks_element);
+ gdb_byte *known_tasks = alloca (target_ptr_byte);
+ CORE_ADDR task_id;
+ const struct ada_tasks_pspace_data *pspace_data
+ = get_ada_tasks_pspace_data (current_program_space);
+
+ /* Sanity check. */
+ if (pspace_data->atcb_fieldno.activation_link < 0)
+ return 0;
+
+ /* Build a new list by reading the ATCBs. Read head of the list. */
+ 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;
+ struct value *common_value;
+
+ add_ada_task (task_id, current_inferior ());
+
+ /* Read the chain. */
+ tcb_value = value_from_contents_and_address (pspace_data->atcb_type,
+ NULL, task_id);
+ common_value = value_field (tcb_value, pspace_data->atcb_fieldno.common);
+ task_id = value_as_address
+ (value_field (common_value,
+ pspace_data->atcb_fieldno.activation_link));
+ }
+
+ return 1;
+}
+
+/* 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_tasks_inferior_data_sniffer (struct ada_tasks_inferior_data *data)
+{
+ struct minimal_symbol *msym;
+ struct symbol *sym;
+
+ /* Return now if already set. */
+ if (data->known_tasks_kind != ADA_TASKS_UNKNOWN)
+ return;
+
+ /* 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 = 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;
+ }
+
+
+ /* 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 = 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;
+}
+
+/* Read the known tasks from the current inferior's memory, and store it
+ in the current inferior's data TASK_LIST.
+ Return non-zero upon success. */
+
+static int
+read_known_tasks (void)
+{
+ struct ada_tasks_inferior_data *data =
+ get_ada_tasks_inferior_data (current_inferior ());
+