diff options
-rw-r--r-- | gdb/ChangeLog | 12 | ||||
-rw-r--r-- | gdb/ada-tasks.c | 138 |
2 files changed, 103 insertions, 47 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3ce3c12..3c50019 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2012-02-23 Tristan Gingold <gingold@adacore.com> + + * ada-tasks.c (struct ada_tasks_inferior_data): Add + known_tasks_element and known_tasks_length fields. + (read_known_tasks_array): Change argument type. Use pointer type + and number of elements from DATA. Adjust. + (read_known_tasks_list): Likewise. + (get_known_tasks_addr): Remove. + (ada_set_current_inferior_known_tasks_addr): Renamed to ... + (ada_tasks_inferior_data_sniffer): ... this. Use symtab for element + type and array length. Merge former get_known_tasks_addr code. + 2012-02-23 Jan Kratochvil <jan.kratochvil@redhat.com> PR backtrace/13716 diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c index 274d83a..4c0b667 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,95 @@ 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; + const char *name; + 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; + struct type *idxtype; + + if (TYPE_CODE (type) == TYPE_CODE_ARRAY + && (eltype = check_typedef (TYPE_TARGET_TYPE (type))) + && TYPE_CODE (eltype) == TYPE_CODE_PTR + && (idxtype = check_typedef (TYPE_INDEX_TYPE (type))) + && !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 +953,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 +961,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 |