| Index: gdb/ada-tasks.c
|
| diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
|
| index 274d83a894f6a5f9c998a3a4e6b57a318dd2580b..0e441fbff6343cd569b337a6ed48b72469cca444 100644
|
| --- a/gdb/ada-tasks.c
|
| +++ b/gdb/ada-tasks.c
|
| @@ -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. */
|
| @@ -774,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 ());
|
| @@ -804,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);
|
| @@ -820,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;
|
| @@ -841,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;
|
| }
|
| @@ -909,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)
|
| @@ -917,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
|
|
|