1*ef5ccd6cSJohn Marino /* Copyright (C) 1992-2013 Free Software Foundation, Inc.
25796c8dcSSimon Schubert
35796c8dcSSimon Schubert This file is part of GDB.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
65796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
75796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
85796c8dcSSimon Schubert (at your option) any later version.
95796c8dcSSimon Schubert
105796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
115796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
125796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
135796c8dcSSimon Schubert GNU General Public License for more details.
145796c8dcSSimon Schubert
155796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
165796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
175796c8dcSSimon Schubert
185796c8dcSSimon Schubert #include "defs.h"
195796c8dcSSimon Schubert #include "observer.h"
205796c8dcSSimon Schubert #include "gdbcmd.h"
215796c8dcSSimon Schubert #include "target.h"
225796c8dcSSimon Schubert #include "ada-lang.h"
235796c8dcSSimon Schubert #include "gdbcore.h"
245796c8dcSSimon Schubert #include "inferior.h"
255796c8dcSSimon Schubert #include "gdbthread.h"
26a45ae5f8SJohn Marino #include "progspace.h"
27a45ae5f8SJohn Marino #include "objfiles.h"
285796c8dcSSimon Schubert
295796c8dcSSimon Schubert /* The name of the array in the GNAT runtime where the Ada Task Control
305796c8dcSSimon Schubert Block of each task is stored. */
315796c8dcSSimon Schubert #define KNOWN_TASKS_NAME "system__tasking__debug__known_tasks"
325796c8dcSSimon Schubert
33c50c785cSJohn Marino /* The maximum number of tasks known to the Ada runtime. */
345796c8dcSSimon Schubert static const int MAX_NUMBER_OF_KNOWN_TASKS = 1000;
355796c8dcSSimon Schubert
36a45ae5f8SJohn Marino /* The name of the variable in the GNAT runtime where the head of a task
37a45ae5f8SJohn Marino chain is saved. This is an alternate mechanism to find the list of known
38a45ae5f8SJohn Marino tasks. */
39a45ae5f8SJohn Marino #define KNOWN_TASKS_LIST "system__tasking__debug__first_task"
40a45ae5f8SJohn Marino
415796c8dcSSimon Schubert enum task_states
425796c8dcSSimon Schubert {
435796c8dcSSimon Schubert Unactivated,
445796c8dcSSimon Schubert Runnable,
455796c8dcSSimon Schubert Terminated,
465796c8dcSSimon Schubert Activator_Sleep,
475796c8dcSSimon Schubert Acceptor_Sleep,
485796c8dcSSimon Schubert Entry_Caller_Sleep,
495796c8dcSSimon Schubert Async_Select_Sleep,
505796c8dcSSimon Schubert Delay_Sleep,
515796c8dcSSimon Schubert Master_Completion_Sleep,
525796c8dcSSimon Schubert Master_Phase_2_Sleep,
535796c8dcSSimon Schubert Interrupt_Server_Idle_Sleep,
545796c8dcSSimon Schubert Interrupt_Server_Blocked_Interrupt_Sleep,
555796c8dcSSimon Schubert Timer_Server_Sleep,
565796c8dcSSimon Schubert AST_Server_Sleep,
575796c8dcSSimon Schubert Asynchronous_Hold,
585796c8dcSSimon Schubert Interrupt_Server_Blocked_On_Event_Flag,
595796c8dcSSimon Schubert Activating,
605796c8dcSSimon Schubert Acceptor_Delay_Sleep
615796c8dcSSimon Schubert };
625796c8dcSSimon Schubert
635796c8dcSSimon Schubert /* A short description corresponding to each possible task state. */
645796c8dcSSimon Schubert static const char *task_states[] = {
655796c8dcSSimon Schubert N_("Unactivated"),
665796c8dcSSimon Schubert N_("Runnable"),
675796c8dcSSimon Schubert N_("Terminated"),
685796c8dcSSimon Schubert N_("Child Activation Wait"),
695796c8dcSSimon Schubert N_("Accept or Select Term"),
705796c8dcSSimon Schubert N_("Waiting on entry call"),
715796c8dcSSimon Schubert N_("Async Select Wait"),
725796c8dcSSimon Schubert N_("Delay Sleep"),
735796c8dcSSimon Schubert N_("Child Termination Wait"),
745796c8dcSSimon Schubert N_("Wait Child in Term Alt"),
755796c8dcSSimon Schubert "",
765796c8dcSSimon Schubert "",
775796c8dcSSimon Schubert "",
785796c8dcSSimon Schubert "",
795796c8dcSSimon Schubert N_("Asynchronous Hold"),
805796c8dcSSimon Schubert "",
815796c8dcSSimon Schubert N_("Activating"),
825796c8dcSSimon Schubert N_("Selective Wait")
835796c8dcSSimon Schubert };
845796c8dcSSimon Schubert
855796c8dcSSimon Schubert /* A longer description corresponding to each possible task state. */
865796c8dcSSimon Schubert static const char *long_task_states[] = {
875796c8dcSSimon Schubert N_("Unactivated"),
885796c8dcSSimon Schubert N_("Runnable"),
895796c8dcSSimon Schubert N_("Terminated"),
905796c8dcSSimon Schubert N_("Waiting for child activation"),
915796c8dcSSimon Schubert N_("Blocked in accept or select with terminate"),
925796c8dcSSimon Schubert N_("Waiting on entry call"),
935796c8dcSSimon Schubert N_("Asynchronous Selective Wait"),
945796c8dcSSimon Schubert N_("Delay Sleep"),
955796c8dcSSimon Schubert N_("Waiting for children termination"),
965796c8dcSSimon Schubert N_("Waiting for children in terminate alternative"),
975796c8dcSSimon Schubert "",
985796c8dcSSimon Schubert "",
995796c8dcSSimon Schubert "",
1005796c8dcSSimon Schubert "",
1015796c8dcSSimon Schubert N_("Asynchronous Hold"),
1025796c8dcSSimon Schubert "",
1035796c8dcSSimon Schubert N_("Activating"),
1045796c8dcSSimon Schubert N_("Blocked in selective wait statement")
1055796c8dcSSimon Schubert };
1065796c8dcSSimon Schubert
1075796c8dcSSimon Schubert /* The index of certain important fields in the Ada Task Control Block
1085796c8dcSSimon Schubert record and sub-records. */
1095796c8dcSSimon Schubert
110a45ae5f8SJohn Marino struct atcb_fieldnos
1115796c8dcSSimon Schubert {
1125796c8dcSSimon Schubert /* Fields in record Ada_Task_Control_Block. */
1135796c8dcSSimon Schubert int common;
1145796c8dcSSimon Schubert int entry_calls;
1155796c8dcSSimon Schubert int atc_nesting_level;
1165796c8dcSSimon Schubert
1175796c8dcSSimon Schubert /* Fields in record Common_ATCB. */
1185796c8dcSSimon Schubert int state;
1195796c8dcSSimon Schubert int parent;
1205796c8dcSSimon Schubert int priority;
1215796c8dcSSimon Schubert int image;
1225796c8dcSSimon Schubert int image_len; /* This field may be missing. */
123a45ae5f8SJohn Marino int activation_link;
1245796c8dcSSimon Schubert int call;
1255796c8dcSSimon Schubert int ll;
1265796c8dcSSimon Schubert
1275796c8dcSSimon Schubert /* Fields in Task_Primitives.Private_Data. */
1285796c8dcSSimon Schubert int ll_thread;
1295796c8dcSSimon Schubert int ll_lwp; /* This field may be missing. */
1305796c8dcSSimon Schubert
1315796c8dcSSimon Schubert /* Fields in Common_ATCB.Call.all. */
1325796c8dcSSimon Schubert int call_self;
1335796c8dcSSimon Schubert };
1345796c8dcSSimon Schubert
135a45ae5f8SJohn Marino /* This module's per-program-space data. */
1365796c8dcSSimon Schubert
137a45ae5f8SJohn Marino struct ada_tasks_pspace_data
138a45ae5f8SJohn Marino {
139a45ae5f8SJohn Marino /* Nonzero if the data has been initialized. If set to zero,
140a45ae5f8SJohn Marino it means that the data has either not been initialized, or
141a45ae5f8SJohn Marino has potentially become stale. */
142a45ae5f8SJohn Marino int initialized_p;
1435796c8dcSSimon Schubert
144a45ae5f8SJohn Marino /* The ATCB record type. */
145a45ae5f8SJohn Marino struct type *atcb_type;
146a45ae5f8SJohn Marino
147a45ae5f8SJohn Marino /* The ATCB "Common" component type. */
148a45ae5f8SJohn Marino struct type *atcb_common_type;
149a45ae5f8SJohn Marino
150a45ae5f8SJohn Marino /* The type of the "ll" field, from the atcb_common_type. */
151a45ae5f8SJohn Marino struct type *atcb_ll_type;
152a45ae5f8SJohn Marino
153a45ae5f8SJohn Marino /* The type of the "call" field, from the atcb_common_type. */
154a45ae5f8SJohn Marino struct type *atcb_call_type;
155a45ae5f8SJohn Marino
156a45ae5f8SJohn Marino /* The index of various fields in the ATCB record and sub-records. */
157a45ae5f8SJohn Marino struct atcb_fieldnos atcb_fieldno;
158a45ae5f8SJohn Marino };
159a45ae5f8SJohn Marino
160a45ae5f8SJohn Marino /* Key to our per-program-space data. */
161a45ae5f8SJohn Marino static const struct program_space_data *ada_tasks_pspace_data_handle;
162a45ae5f8SJohn Marino
163a45ae5f8SJohn Marino typedef struct ada_task_info ada_task_info_s;
164a45ae5f8SJohn Marino DEF_VEC_O(ada_task_info_s);
165a45ae5f8SJohn Marino
166a45ae5f8SJohn Marino /* The kind of data structure used by the runtime to store the list
167a45ae5f8SJohn Marino of Ada tasks. */
168a45ae5f8SJohn Marino
169a45ae5f8SJohn Marino enum ada_known_tasks_kind
170a45ae5f8SJohn Marino {
171a45ae5f8SJohn Marino /* Use this value when we haven't determined which kind of structure
172a45ae5f8SJohn Marino is being used, or when we need to recompute it.
173a45ae5f8SJohn Marino
174a45ae5f8SJohn Marino We set the value of this enumerate to zero on purpose: This allows
175a45ae5f8SJohn Marino us to use this enumerate in a structure where setting all fields
176a45ae5f8SJohn Marino to zero will result in this kind being set to unknown. */
177a45ae5f8SJohn Marino ADA_TASKS_UNKNOWN = 0,
178a45ae5f8SJohn Marino
179a45ae5f8SJohn Marino /* This value means that we did not find any task list. Unless
180a45ae5f8SJohn Marino there is a bug somewhere, this means that the inferior does not
181a45ae5f8SJohn Marino use tasking. */
182a45ae5f8SJohn Marino ADA_TASKS_NOT_FOUND,
183a45ae5f8SJohn Marino
184a45ae5f8SJohn Marino /* This value means that the task list is stored as an array.
185a45ae5f8SJohn Marino This is the usual method, as it causes very little overhead.
186a45ae5f8SJohn Marino But this method is not always used, as it does use a certain
187a45ae5f8SJohn Marino amount of memory, which might be scarse in certain environments. */
188a45ae5f8SJohn Marino ADA_TASKS_ARRAY,
189a45ae5f8SJohn Marino
190a45ae5f8SJohn Marino /* This value means that the task list is stored as a linked list.
191a45ae5f8SJohn Marino This has more runtime overhead than the array approach, but
192a45ae5f8SJohn Marino also require less memory when the number of tasks is small. */
193a45ae5f8SJohn Marino ADA_TASKS_LIST,
194a45ae5f8SJohn Marino };
195a45ae5f8SJohn Marino
196a45ae5f8SJohn Marino /* This module's per-inferior data. */
197a45ae5f8SJohn Marino
198a45ae5f8SJohn Marino struct ada_tasks_inferior_data
199a45ae5f8SJohn Marino {
200a45ae5f8SJohn Marino /* The type of data structure used by the runtime to store
201a45ae5f8SJohn Marino the list of Ada tasks. The value of this field influences
202a45ae5f8SJohn Marino the interpretation of the known_tasks_addr field below:
203a45ae5f8SJohn Marino - ADA_TASKS_UNKNOWN: The value of known_tasks_addr hasn't
204a45ae5f8SJohn Marino been determined yet;
205a45ae5f8SJohn Marino - ADA_TASKS_NOT_FOUND: The program probably does not use tasking
206a45ae5f8SJohn Marino and the known_tasks_addr is irrelevant;
207a45ae5f8SJohn Marino - ADA_TASKS_ARRAY: The known_tasks is an array;
208a45ae5f8SJohn Marino - ADA_TASKS_LIST: The known_tasks is a list. */
209a45ae5f8SJohn Marino enum ada_known_tasks_kind known_tasks_kind;
210a45ae5f8SJohn Marino
211a45ae5f8SJohn Marino /* The address of the known_tasks structure. This is where
212a45ae5f8SJohn Marino the runtime stores the information for all Ada tasks.
213a45ae5f8SJohn Marino The interpretation of this field depends on KNOWN_TASKS_KIND
214a45ae5f8SJohn Marino above. */
215a45ae5f8SJohn Marino CORE_ADDR known_tasks_addr;
216a45ae5f8SJohn Marino
217*ef5ccd6cSJohn Marino /* Type of elements of the known task. Usually a pointer. */
218*ef5ccd6cSJohn Marino struct type *known_tasks_element;
219*ef5ccd6cSJohn Marino
220*ef5ccd6cSJohn Marino /* Number of elements in the known tasks array. */
221*ef5ccd6cSJohn Marino unsigned int known_tasks_length;
222*ef5ccd6cSJohn Marino
223a45ae5f8SJohn Marino /* When nonzero, this flag indicates that the task_list field
224a45ae5f8SJohn Marino below is up to date. When set to zero, the list has either
225a45ae5f8SJohn Marino not been initialized, or has potentially become stale. */
226a45ae5f8SJohn Marino int task_list_valid_p;
2275796c8dcSSimon Schubert
2285796c8dcSSimon Schubert /* The list of Ada tasks.
2295796c8dcSSimon Schubert
2305796c8dcSSimon Schubert Note: To each task we associate a number that the user can use to
2315796c8dcSSimon Schubert reference it - this number is printed beside each task in the tasks
2325796c8dcSSimon Schubert info listing displayed by "info tasks". This number is equal to
2335796c8dcSSimon Schubert its index in the vector + 1. Reciprocally, to compute the index
2345796c8dcSSimon Schubert of a task in the vector, we need to substract 1 from its number. */
235a45ae5f8SJohn Marino VEC(ada_task_info_s) *task_list;
236a45ae5f8SJohn Marino };
2375796c8dcSSimon Schubert
238a45ae5f8SJohn Marino /* Key to our per-inferior data. */
239a45ae5f8SJohn Marino static const struct inferior_data *ada_tasks_inferior_data_handle;
240a45ae5f8SJohn Marino
241a45ae5f8SJohn Marino /* Return the ada-tasks module's data for the given program space (PSPACE).
242a45ae5f8SJohn Marino If none is found, add a zero'ed one now.
243a45ae5f8SJohn Marino
244a45ae5f8SJohn Marino This function always returns a valid object. */
245a45ae5f8SJohn Marino
246a45ae5f8SJohn Marino static struct ada_tasks_pspace_data *
get_ada_tasks_pspace_data(struct program_space * pspace)247a45ae5f8SJohn Marino get_ada_tasks_pspace_data (struct program_space *pspace)
248a45ae5f8SJohn Marino {
249a45ae5f8SJohn Marino struct ada_tasks_pspace_data *data;
250a45ae5f8SJohn Marino
251a45ae5f8SJohn Marino data = program_space_data (pspace, ada_tasks_pspace_data_handle);
252a45ae5f8SJohn Marino if (data == NULL)
253a45ae5f8SJohn Marino {
254a45ae5f8SJohn Marino data = XZALLOC (struct ada_tasks_pspace_data);
255a45ae5f8SJohn Marino set_program_space_data (pspace, ada_tasks_pspace_data_handle, data);
256a45ae5f8SJohn Marino }
257a45ae5f8SJohn Marino
258a45ae5f8SJohn Marino return data;
259a45ae5f8SJohn Marino }
260a45ae5f8SJohn Marino
261a45ae5f8SJohn Marino /* Return the ada-tasks module's data for the given inferior (INF).
262a45ae5f8SJohn Marino If none is found, add a zero'ed one now.
263a45ae5f8SJohn Marino
264a45ae5f8SJohn Marino This function always returns a valid object.
265a45ae5f8SJohn Marino
266a45ae5f8SJohn Marino Note that we could use an observer of the inferior-created event
267a45ae5f8SJohn Marino to make sure that the ada-tasks per-inferior data always exists.
268a45ae5f8SJohn Marino But we prefered this approach, as it avoids this entirely as long
269a45ae5f8SJohn Marino as the user does not use any of the tasking features. This is
270a45ae5f8SJohn Marino quite possible, particularly in the case where the inferior does
271a45ae5f8SJohn Marino not use tasking. */
272a45ae5f8SJohn Marino
273a45ae5f8SJohn Marino static struct ada_tasks_inferior_data *
get_ada_tasks_inferior_data(struct inferior * inf)274a45ae5f8SJohn Marino get_ada_tasks_inferior_data (struct inferior *inf)
275a45ae5f8SJohn Marino {
276a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data;
277a45ae5f8SJohn Marino
278a45ae5f8SJohn Marino data = inferior_data (inf, ada_tasks_inferior_data_handle);
279a45ae5f8SJohn Marino if (data == NULL)
280a45ae5f8SJohn Marino {
281a45ae5f8SJohn Marino data = XZALLOC (struct ada_tasks_inferior_data);
282a45ae5f8SJohn Marino set_inferior_data (inf, ada_tasks_inferior_data_handle, data);
283a45ae5f8SJohn Marino }
284a45ae5f8SJohn Marino
285a45ae5f8SJohn Marino return data;
286a45ae5f8SJohn Marino }
2875796c8dcSSimon Schubert
2885796c8dcSSimon Schubert /* Return the task number of the task whose ptid is PTID, or zero
2895796c8dcSSimon Schubert if the task could not be found. */
2905796c8dcSSimon Schubert
2915796c8dcSSimon Schubert int
ada_get_task_number(ptid_t ptid)2925796c8dcSSimon Schubert ada_get_task_number (ptid_t ptid)
2935796c8dcSSimon Schubert {
2945796c8dcSSimon Schubert int i;
295a45ae5f8SJohn Marino struct inferior *inf = find_inferior_pid (ptid_get_pid (ptid));
296a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data;
2975796c8dcSSimon Schubert
298a45ae5f8SJohn Marino gdb_assert (inf != NULL);
299a45ae5f8SJohn Marino data = get_ada_tasks_inferior_data (inf);
300a45ae5f8SJohn Marino
301a45ae5f8SJohn Marino for (i = 0; i < VEC_length (ada_task_info_s, data->task_list); i++)
302a45ae5f8SJohn Marino if (ptid_equal (VEC_index (ada_task_info_s, data->task_list, i)->ptid,
303a45ae5f8SJohn Marino ptid))
3045796c8dcSSimon Schubert return i + 1;
3055796c8dcSSimon Schubert
3065796c8dcSSimon Schubert return 0; /* No matching task found. */
3075796c8dcSSimon Schubert }
3085796c8dcSSimon Schubert
309a45ae5f8SJohn Marino /* Return the task number of the task running in inferior INF which
310a45ae5f8SJohn Marino matches TASK_ID , or zero if the task could not be found. */
3115796c8dcSSimon Schubert
3125796c8dcSSimon Schubert static int
get_task_number_from_id(CORE_ADDR task_id,struct inferior * inf)313a45ae5f8SJohn Marino get_task_number_from_id (CORE_ADDR task_id, struct inferior *inf)
3145796c8dcSSimon Schubert {
315a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf);
3165796c8dcSSimon Schubert int i;
3175796c8dcSSimon Schubert
318a45ae5f8SJohn Marino for (i = 0; i < VEC_length (ada_task_info_s, data->task_list); i++)
3195796c8dcSSimon Schubert {
3205796c8dcSSimon Schubert struct ada_task_info *task_info =
321a45ae5f8SJohn Marino VEC_index (ada_task_info_s, data->task_list, i);
3225796c8dcSSimon Schubert
3235796c8dcSSimon Schubert if (task_info->task_id == task_id)
3245796c8dcSSimon Schubert return i + 1;
3255796c8dcSSimon Schubert }
3265796c8dcSSimon Schubert
3275796c8dcSSimon Schubert /* Task not found. Return 0. */
3285796c8dcSSimon Schubert return 0;
3295796c8dcSSimon Schubert }
3305796c8dcSSimon Schubert
3315796c8dcSSimon Schubert /* Return non-zero if TASK_NUM is a valid task number. */
3325796c8dcSSimon Schubert
3335796c8dcSSimon Schubert int
valid_task_id(int task_num)3345796c8dcSSimon Schubert valid_task_id (int task_num)
3355796c8dcSSimon Schubert {
336a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data;
337a45ae5f8SJohn Marino
338a45ae5f8SJohn Marino ada_build_task_list ();
339a45ae5f8SJohn Marino data = get_ada_tasks_inferior_data (current_inferior ());
3405796c8dcSSimon Schubert return (task_num > 0
341a45ae5f8SJohn Marino && task_num <= VEC_length (ada_task_info_s, data->task_list));
3425796c8dcSSimon Schubert }
3435796c8dcSSimon Schubert
3445796c8dcSSimon Schubert /* Return non-zero iff the task STATE corresponds to a non-terminated
3455796c8dcSSimon Schubert task state. */
3465796c8dcSSimon Schubert
3475796c8dcSSimon Schubert static int
ada_task_is_alive(struct ada_task_info * task_info)3485796c8dcSSimon Schubert ada_task_is_alive (struct ada_task_info *task_info)
3495796c8dcSSimon Schubert {
3505796c8dcSSimon Schubert return (task_info->state != Terminated);
3515796c8dcSSimon Schubert }
3525796c8dcSSimon Schubert
353c50c785cSJohn Marino /* Call the ITERATOR function once for each Ada task that hasn't been
354c50c785cSJohn Marino terminated yet. */
355c50c785cSJohn Marino
356c50c785cSJohn Marino void
iterate_over_live_ada_tasks(ada_task_list_iterator_ftype * iterator)357c50c785cSJohn Marino iterate_over_live_ada_tasks (ada_task_list_iterator_ftype *iterator)
358c50c785cSJohn Marino {
359c50c785cSJohn Marino int i, nb_tasks;
360c50c785cSJohn Marino struct ada_task_info *task;
361a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data;
362c50c785cSJohn Marino
363a45ae5f8SJohn Marino ada_build_task_list ();
364a45ae5f8SJohn Marino data = get_ada_tasks_inferior_data (current_inferior ());
365a45ae5f8SJohn Marino nb_tasks = VEC_length (ada_task_info_s, data->task_list);
366c50c785cSJohn Marino
367c50c785cSJohn Marino for (i = 0; i < nb_tasks; i++)
368c50c785cSJohn Marino {
369a45ae5f8SJohn Marino task = VEC_index (ada_task_info_s, data->task_list, i);
370c50c785cSJohn Marino if (!ada_task_is_alive (task))
371c50c785cSJohn Marino continue;
372c50c785cSJohn Marino iterator (task);
373c50c785cSJohn Marino }
374c50c785cSJohn Marino }
375c50c785cSJohn Marino
3765796c8dcSSimon Schubert /* Extract the contents of the value as a string whose length is LENGTH,
3775796c8dcSSimon Schubert and store the result in DEST. */
3785796c8dcSSimon Schubert
3795796c8dcSSimon Schubert static void
value_as_string(char * dest,struct value * val,int length)3805796c8dcSSimon Schubert value_as_string (char *dest, struct value *val, int length)
3815796c8dcSSimon Schubert {
3825796c8dcSSimon Schubert memcpy (dest, value_contents (val), length);
3835796c8dcSSimon Schubert dest[length] = '\0';
3845796c8dcSSimon Schubert }
3855796c8dcSSimon Schubert
3865796c8dcSSimon Schubert /* Extract the string image from the fat string corresponding to VAL,
3875796c8dcSSimon Schubert and store it in DEST. If the string length is greater than MAX_LEN,
3885796c8dcSSimon Schubert then truncate the result to the first MAX_LEN characters of the fat
3895796c8dcSSimon Schubert string. */
3905796c8dcSSimon Schubert
3915796c8dcSSimon Schubert static void
read_fat_string_value(char * dest,struct value * val,int max_len)3925796c8dcSSimon Schubert read_fat_string_value (char *dest, struct value *val, int max_len)
3935796c8dcSSimon Schubert {
3945796c8dcSSimon Schubert struct value *array_val;
3955796c8dcSSimon Schubert struct value *bounds_val;
3965796c8dcSSimon Schubert int len;
3975796c8dcSSimon Schubert
3985796c8dcSSimon Schubert /* The following variables are made static to avoid recomputing them
3995796c8dcSSimon Schubert each time this function is called. */
4005796c8dcSSimon Schubert static int initialize_fieldnos = 1;
4015796c8dcSSimon Schubert static int array_fieldno;
4025796c8dcSSimon Schubert static int bounds_fieldno;
4035796c8dcSSimon Schubert static int upper_bound_fieldno;
4045796c8dcSSimon Schubert
4055796c8dcSSimon Schubert /* Get the index of the fields that we will need to read in order
4065796c8dcSSimon Schubert to extract the string from the fat string. */
4075796c8dcSSimon Schubert if (initialize_fieldnos)
4085796c8dcSSimon Schubert {
4095796c8dcSSimon Schubert struct type *type = value_type (val);
4105796c8dcSSimon Schubert struct type *bounds_type;
4115796c8dcSSimon Schubert
4125796c8dcSSimon Schubert array_fieldno = ada_get_field_index (type, "P_ARRAY", 0);
4135796c8dcSSimon Schubert bounds_fieldno = ada_get_field_index (type, "P_BOUNDS", 0);
4145796c8dcSSimon Schubert
4155796c8dcSSimon Schubert bounds_type = TYPE_FIELD_TYPE (type, bounds_fieldno);
4165796c8dcSSimon Schubert if (TYPE_CODE (bounds_type) == TYPE_CODE_PTR)
4175796c8dcSSimon Schubert bounds_type = TYPE_TARGET_TYPE (bounds_type);
4185796c8dcSSimon Schubert if (TYPE_CODE (bounds_type) != TYPE_CODE_STRUCT)
4195796c8dcSSimon Schubert error (_("Unknown task name format. Aborting"));
4205796c8dcSSimon Schubert upper_bound_fieldno = ada_get_field_index (bounds_type, "UB0", 0);
4215796c8dcSSimon Schubert
4225796c8dcSSimon Schubert initialize_fieldnos = 0;
4235796c8dcSSimon Schubert }
4245796c8dcSSimon Schubert
4255796c8dcSSimon Schubert /* Get the size of the task image by checking the value of the bounds.
4265796c8dcSSimon Schubert The lower bound is always 1, so we only need to read the upper bound. */
4275796c8dcSSimon Schubert bounds_val = value_ind (value_field (val, bounds_fieldno));
4285796c8dcSSimon Schubert len = value_as_long (value_field (bounds_val, upper_bound_fieldno));
4295796c8dcSSimon Schubert
4305796c8dcSSimon Schubert /* Make sure that we do not read more than max_len characters... */
4315796c8dcSSimon Schubert if (len > max_len)
4325796c8dcSSimon Schubert len = max_len;
4335796c8dcSSimon Schubert
4345796c8dcSSimon Schubert /* Extract LEN characters from the fat string. */
4355796c8dcSSimon Schubert array_val = value_ind (value_field (val, array_fieldno));
4365796c8dcSSimon Schubert read_memory (value_address (array_val), dest, len);
4375796c8dcSSimon Schubert
4385796c8dcSSimon Schubert /* Add the NUL character to close the string. */
4395796c8dcSSimon Schubert dest[len] = '\0';
4405796c8dcSSimon Schubert }
4415796c8dcSSimon Schubert
4425796c8dcSSimon Schubert /* Get from the debugging information the type description of all types
4435796c8dcSSimon Schubert related to the Ada Task Control Block that will be needed in order to
4445796c8dcSSimon Schubert read the list of known tasks in the Ada runtime. Also return the
4455796c8dcSSimon Schubert associated ATCB_FIELDNOS.
4465796c8dcSSimon Schubert
4475796c8dcSSimon Schubert Error handling: Any data missing from the debugging info will cause
4485796c8dcSSimon Schubert an error to be raised, and none of the return values to be set.
4495796c8dcSSimon Schubert Users of this function can depend on the fact that all or none of the
4505796c8dcSSimon Schubert return values will be set. */
4515796c8dcSSimon Schubert
4525796c8dcSSimon Schubert static void
get_tcb_types_info(void)453a45ae5f8SJohn Marino get_tcb_types_info (void)
4545796c8dcSSimon Schubert {
4555796c8dcSSimon Schubert struct type *type;
4565796c8dcSSimon Schubert struct type *common_type;
4575796c8dcSSimon Schubert struct type *ll_type;
4585796c8dcSSimon Schubert struct type *call_type;
459a45ae5f8SJohn Marino struct atcb_fieldnos fieldnos;
460a45ae5f8SJohn Marino struct ada_tasks_pspace_data *pspace_data;
4615796c8dcSSimon Schubert
4625796c8dcSSimon Schubert const char *atcb_name = "system__tasking__ada_task_control_block___XVE";
4635796c8dcSSimon Schubert const char *atcb_name_fixed = "system__tasking__ada_task_control_block";
4645796c8dcSSimon Schubert const char *common_atcb_name = "system__tasking__common_atcb";
4655796c8dcSSimon Schubert const char *private_data_name = "system__task_primitives__private_data";
4665796c8dcSSimon Schubert const char *entry_call_record_name = "system__tasking__entry_call_record";
4675796c8dcSSimon Schubert
468c50c785cSJohn Marino /* ATCB symbols may be found in several compilation units. As we
469c50c785cSJohn Marino are only interested in one instance, use standard (literal,
470c50c785cSJohn Marino C-like) lookups to get the first match. */
471c50c785cSJohn Marino
4725796c8dcSSimon Schubert struct symbol *atcb_sym =
473c50c785cSJohn Marino lookup_symbol_in_language (atcb_name, NULL, VAR_DOMAIN,
474c50c785cSJohn Marino language_c, NULL);
4755796c8dcSSimon Schubert const struct symbol *common_atcb_sym =
476c50c785cSJohn Marino lookup_symbol_in_language (common_atcb_name, NULL, VAR_DOMAIN,
477c50c785cSJohn Marino language_c, NULL);
4785796c8dcSSimon Schubert const struct symbol *private_data_sym =
479c50c785cSJohn Marino lookup_symbol_in_language (private_data_name, NULL, VAR_DOMAIN,
480c50c785cSJohn Marino language_c, NULL);
4815796c8dcSSimon Schubert const struct symbol *entry_call_record_sym =
482c50c785cSJohn Marino lookup_symbol_in_language (entry_call_record_name, NULL, VAR_DOMAIN,
483c50c785cSJohn Marino language_c, NULL);
4845796c8dcSSimon Schubert
4855796c8dcSSimon Schubert if (atcb_sym == NULL || atcb_sym->type == NULL)
4865796c8dcSSimon Schubert {
4875796c8dcSSimon Schubert /* In Ravenscar run-time libs, the ATCB does not have a dynamic
4885796c8dcSSimon Schubert size, so the symbol name differs. */
489c50c785cSJohn Marino atcb_sym = lookup_symbol_in_language (atcb_name_fixed, NULL, VAR_DOMAIN,
490c50c785cSJohn Marino language_c, NULL);
4915796c8dcSSimon Schubert
4925796c8dcSSimon Schubert if (atcb_sym == NULL || atcb_sym->type == NULL)
4935796c8dcSSimon Schubert error (_("Cannot find Ada_Task_Control_Block type. Aborting"));
4945796c8dcSSimon Schubert
4955796c8dcSSimon Schubert type = atcb_sym->type;
4965796c8dcSSimon Schubert }
4975796c8dcSSimon Schubert else
4985796c8dcSSimon Schubert {
4995796c8dcSSimon Schubert /* Get a static representation of the type record
5005796c8dcSSimon Schubert Ada_Task_Control_Block. */
5015796c8dcSSimon Schubert type = atcb_sym->type;
5025796c8dcSSimon Schubert type = ada_template_to_fixed_record_type_1 (type, NULL, 0, NULL, 0);
5035796c8dcSSimon Schubert }
5045796c8dcSSimon Schubert
5055796c8dcSSimon Schubert if (common_atcb_sym == NULL || common_atcb_sym->type == NULL)
5065796c8dcSSimon Schubert error (_("Cannot find Common_ATCB type. Aborting"));
5075796c8dcSSimon Schubert if (private_data_sym == NULL || private_data_sym->type == NULL)
5085796c8dcSSimon Schubert error (_("Cannot find Private_Data type. Aborting"));
5095796c8dcSSimon Schubert if (entry_call_record_sym == NULL || entry_call_record_sym->type == NULL)
5105796c8dcSSimon Schubert error (_("Cannot find Entry_Call_Record type. Aborting"));
5115796c8dcSSimon Schubert
5125796c8dcSSimon Schubert /* Get the type for Ada_Task_Control_Block.Common. */
5135796c8dcSSimon Schubert common_type = common_atcb_sym->type;
5145796c8dcSSimon Schubert
5155796c8dcSSimon Schubert /* Get the type for Ada_Task_Control_Bloc.Common.Call.LL. */
5165796c8dcSSimon Schubert ll_type = private_data_sym->type;
5175796c8dcSSimon Schubert
5185796c8dcSSimon Schubert /* Get the type for Common_ATCB.Call.all. */
5195796c8dcSSimon Schubert call_type = entry_call_record_sym->type;
5205796c8dcSSimon Schubert
5215796c8dcSSimon Schubert /* Get the field indices. */
5225796c8dcSSimon Schubert fieldnos.common = ada_get_field_index (type, "common", 0);
5235796c8dcSSimon Schubert fieldnos.entry_calls = ada_get_field_index (type, "entry_calls", 1);
5245796c8dcSSimon Schubert fieldnos.atc_nesting_level =
5255796c8dcSSimon Schubert ada_get_field_index (type, "atc_nesting_level", 1);
5265796c8dcSSimon Schubert fieldnos.state = ada_get_field_index (common_type, "state", 0);
5275796c8dcSSimon Schubert fieldnos.parent = ada_get_field_index (common_type, "parent", 1);
5285796c8dcSSimon Schubert fieldnos.priority = ada_get_field_index (common_type, "base_priority", 0);
5295796c8dcSSimon Schubert fieldnos.image = ada_get_field_index (common_type, "task_image", 1);
5305796c8dcSSimon Schubert fieldnos.image_len = ada_get_field_index (common_type, "task_image_len", 1);
531a45ae5f8SJohn Marino fieldnos.activation_link = ada_get_field_index (common_type,
532a45ae5f8SJohn Marino "activation_link", 1);
5335796c8dcSSimon Schubert fieldnos.call = ada_get_field_index (common_type, "call", 1);
5345796c8dcSSimon Schubert fieldnos.ll = ada_get_field_index (common_type, "ll", 0);
5355796c8dcSSimon Schubert fieldnos.ll_thread = ada_get_field_index (ll_type, "thread", 0);
5365796c8dcSSimon Schubert fieldnos.ll_lwp = ada_get_field_index (ll_type, "lwp", 1);
5375796c8dcSSimon Schubert fieldnos.call_self = ada_get_field_index (call_type, "self", 0);
5385796c8dcSSimon Schubert
5395796c8dcSSimon Schubert /* On certain platforms such as x86-windows, the "lwp" field has been
5405796c8dcSSimon Schubert named "thread_id". This field will likely be renamed in the future,
5415796c8dcSSimon Schubert but we need to support both possibilities to avoid an unnecessary
5425796c8dcSSimon Schubert dependency on a recent compiler. We therefore try locating the
5435796c8dcSSimon Schubert "thread_id" field in place of the "lwp" field if we did not find
5445796c8dcSSimon Schubert the latter. */
5455796c8dcSSimon Schubert if (fieldnos.ll_lwp < 0)
5465796c8dcSSimon Schubert fieldnos.ll_lwp = ada_get_field_index (ll_type, "thread_id", 1);
5475796c8dcSSimon Schubert
5485796c8dcSSimon Schubert /* Set all the out parameters all at once, now that we are certain
5495796c8dcSSimon Schubert that there are no potential error() anymore. */
550a45ae5f8SJohn Marino pspace_data = get_ada_tasks_pspace_data (current_program_space);
551a45ae5f8SJohn Marino pspace_data->initialized_p = 1;
552a45ae5f8SJohn Marino pspace_data->atcb_type = type;
553a45ae5f8SJohn Marino pspace_data->atcb_common_type = common_type;
554a45ae5f8SJohn Marino pspace_data->atcb_ll_type = ll_type;
555a45ae5f8SJohn Marino pspace_data->atcb_call_type = call_type;
556a45ae5f8SJohn Marino pspace_data->atcb_fieldno = fieldnos;
5575796c8dcSSimon Schubert }
5585796c8dcSSimon Schubert
5595796c8dcSSimon Schubert /* Build the PTID of the task from its COMMON_VALUE, which is the "Common"
5605796c8dcSSimon Schubert component of its ATCB record. This PTID needs to match the PTID used
5615796c8dcSSimon Schubert by the thread layer. */
5625796c8dcSSimon Schubert
5635796c8dcSSimon Schubert static ptid_t
ptid_from_atcb_common(struct value * common_value)5645796c8dcSSimon Schubert ptid_from_atcb_common (struct value *common_value)
5655796c8dcSSimon Schubert {
5665796c8dcSSimon Schubert long thread = 0;
5675796c8dcSSimon Schubert CORE_ADDR lwp = 0;
5685796c8dcSSimon Schubert struct value *ll_value;
5695796c8dcSSimon Schubert ptid_t ptid;
570a45ae5f8SJohn Marino const struct ada_tasks_pspace_data *pspace_data
571a45ae5f8SJohn Marino = get_ada_tasks_pspace_data (current_program_space);
5725796c8dcSSimon Schubert
573a45ae5f8SJohn Marino ll_value = value_field (common_value, pspace_data->atcb_fieldno.ll);
5745796c8dcSSimon Schubert
575a45ae5f8SJohn Marino if (pspace_data->atcb_fieldno.ll_lwp >= 0)
576a45ae5f8SJohn Marino lwp = value_as_address (value_field (ll_value,
577a45ae5f8SJohn Marino pspace_data->atcb_fieldno.ll_lwp));
578a45ae5f8SJohn Marino thread = value_as_long (value_field (ll_value,
579a45ae5f8SJohn Marino pspace_data->atcb_fieldno.ll_thread));
5805796c8dcSSimon Schubert
5815796c8dcSSimon Schubert ptid = target_get_ada_task_ptid (lwp, thread);
5825796c8dcSSimon Schubert
5835796c8dcSSimon Schubert return ptid;
5845796c8dcSSimon Schubert }
5855796c8dcSSimon Schubert
5865796c8dcSSimon Schubert /* Read the ATCB data of a given task given its TASK_ID (which is in practice
5875796c8dcSSimon Schubert the address of its assocated ATCB record), and store the result inside
5885796c8dcSSimon Schubert TASK_INFO. */
5895796c8dcSSimon Schubert
5905796c8dcSSimon Schubert static void
read_atcb(CORE_ADDR task_id,struct ada_task_info * task_info)5915796c8dcSSimon Schubert read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
5925796c8dcSSimon Schubert {
5935796c8dcSSimon Schubert struct value *tcb_value;
5945796c8dcSSimon Schubert struct value *common_value;
5955796c8dcSSimon Schubert struct value *atc_nesting_level_value;
5965796c8dcSSimon Schubert struct value *entry_calls_value;
5975796c8dcSSimon Schubert struct value *entry_calls_value_element;
5985796c8dcSSimon Schubert int called_task_fieldno = -1;
599a45ae5f8SJohn Marino static const char ravenscar_task_name[] = "Ravenscar task";
600a45ae5f8SJohn Marino const struct ada_tasks_pspace_data *pspace_data
601a45ae5f8SJohn Marino = get_ada_tasks_pspace_data (current_program_space);
6025796c8dcSSimon Schubert
603a45ae5f8SJohn Marino if (!pspace_data->initialized_p)
604a45ae5f8SJohn Marino get_tcb_types_info ();
6055796c8dcSSimon Schubert
606a45ae5f8SJohn Marino tcb_value = value_from_contents_and_address (pspace_data->atcb_type,
607a45ae5f8SJohn Marino NULL, task_id);
608a45ae5f8SJohn Marino common_value = value_field (tcb_value, pspace_data->atcb_fieldno.common);
6095796c8dcSSimon Schubert
6105796c8dcSSimon Schubert /* Fill in the task_id. */
6115796c8dcSSimon Schubert
6125796c8dcSSimon Schubert task_info->task_id = task_id;
6135796c8dcSSimon Schubert
6145796c8dcSSimon Schubert /* Compute the name of the task.
6155796c8dcSSimon Schubert
6165796c8dcSSimon Schubert Depending on the GNAT version used, the task image is either a fat
6175796c8dcSSimon Schubert string, or a thin array of characters. Older versions of GNAT used
6185796c8dcSSimon Schubert to use fat strings, and therefore did not need an extra field in
6195796c8dcSSimon Schubert the ATCB to store the string length. For efficiency reasons, newer
6205796c8dcSSimon Schubert versions of GNAT replaced the fat string by a static buffer, but this
6215796c8dcSSimon Schubert also required the addition of a new field named "Image_Len" containing
6225796c8dcSSimon Schubert the length of the task name. The method used to extract the task name
6235796c8dcSSimon Schubert is selected depending on the existence of this field.
6245796c8dcSSimon Schubert
6255796c8dcSSimon Schubert In some run-time libs (e.g. Ravenscar), the name is not in the ATCB;
6265796c8dcSSimon Schubert we may want to get it from the first user frame of the stack. For now,
6275796c8dcSSimon Schubert we just give a dummy name. */
6285796c8dcSSimon Schubert
629a45ae5f8SJohn Marino if (pspace_data->atcb_fieldno.image_len == -1)
6305796c8dcSSimon Schubert {
631a45ae5f8SJohn Marino if (pspace_data->atcb_fieldno.image >= 0)
6325796c8dcSSimon Schubert read_fat_string_value (task_info->name,
633a45ae5f8SJohn Marino value_field (common_value,
634a45ae5f8SJohn Marino pspace_data->atcb_fieldno.image),
6355796c8dcSSimon Schubert sizeof (task_info->name) - 1);
6365796c8dcSSimon Schubert else
637a45ae5f8SJohn Marino {
638a45ae5f8SJohn Marino struct minimal_symbol *msym;
639a45ae5f8SJohn Marino
640a45ae5f8SJohn Marino msym = lookup_minimal_symbol_by_pc (task_id);
641a45ae5f8SJohn Marino if (msym)
642a45ae5f8SJohn Marino {
643a45ae5f8SJohn Marino const char *full_name = SYMBOL_LINKAGE_NAME (msym);
644a45ae5f8SJohn Marino const char *task_name = full_name;
645a45ae5f8SJohn Marino const char *p;
646a45ae5f8SJohn Marino
647a45ae5f8SJohn Marino /* Strip the prefix. */
648a45ae5f8SJohn Marino for (p = full_name; *p; p++)
649a45ae5f8SJohn Marino if (p[0] == '_' && p[1] == '_')
650a45ae5f8SJohn Marino task_name = p + 2;
651a45ae5f8SJohn Marino
652a45ae5f8SJohn Marino /* Copy the task name. */
653a45ae5f8SJohn Marino strncpy (task_info->name, task_name, sizeof (task_info->name));
654a45ae5f8SJohn Marino task_info->name[sizeof (task_info->name) - 1] = 0;
6555796c8dcSSimon Schubert }
6565796c8dcSSimon Schubert else
6575796c8dcSSimon Schubert {
658a45ae5f8SJohn Marino /* No symbol found. Use a default name. */
659a45ae5f8SJohn Marino strcpy (task_info->name, ravenscar_task_name);
660a45ae5f8SJohn Marino }
661a45ae5f8SJohn Marino }
662a45ae5f8SJohn Marino }
663a45ae5f8SJohn Marino else
664a45ae5f8SJohn Marino {
665a45ae5f8SJohn Marino int len = value_as_long
666a45ae5f8SJohn Marino (value_field (common_value,
667a45ae5f8SJohn Marino pspace_data->atcb_fieldno.image_len));
6685796c8dcSSimon Schubert
6695796c8dcSSimon Schubert value_as_string (task_info->name,
670a45ae5f8SJohn Marino value_field (common_value,
671a45ae5f8SJohn Marino pspace_data->atcb_fieldno.image),
672a45ae5f8SJohn Marino len);
6735796c8dcSSimon Schubert }
6745796c8dcSSimon Schubert
6755796c8dcSSimon Schubert /* Compute the task state and priority. */
6765796c8dcSSimon Schubert
677a45ae5f8SJohn Marino task_info->state =
678a45ae5f8SJohn Marino value_as_long (value_field (common_value,
679a45ae5f8SJohn Marino pspace_data->atcb_fieldno.state));
6805796c8dcSSimon Schubert task_info->priority =
681a45ae5f8SJohn Marino value_as_long (value_field (common_value,
682a45ae5f8SJohn Marino pspace_data->atcb_fieldno.priority));
6835796c8dcSSimon Schubert
6845796c8dcSSimon Schubert /* If the ATCB contains some information about the parent task,
6855796c8dcSSimon Schubert then compute it as well. Otherwise, zero. */
6865796c8dcSSimon Schubert
687a45ae5f8SJohn Marino if (pspace_data->atcb_fieldno.parent >= 0)
6885796c8dcSSimon Schubert task_info->parent =
689a45ae5f8SJohn Marino value_as_address (value_field (common_value,
690a45ae5f8SJohn Marino pspace_data->atcb_fieldno.parent));
6915796c8dcSSimon Schubert else
6925796c8dcSSimon Schubert task_info->parent = 0;
6935796c8dcSSimon Schubert
6945796c8dcSSimon Schubert
6955796c8dcSSimon Schubert /* If the ATCB contains some information about entry calls, then
6965796c8dcSSimon Schubert compute the "called_task" as well. Otherwise, zero. */
6975796c8dcSSimon Schubert
698a45ae5f8SJohn Marino if (pspace_data->atcb_fieldno.atc_nesting_level > 0
699a45ae5f8SJohn Marino && pspace_data->atcb_fieldno.entry_calls > 0)
7005796c8dcSSimon Schubert {
7015796c8dcSSimon Schubert /* Let My_ATCB be the Ada task control block of a task calling the
7025796c8dcSSimon Schubert entry of another task; then the Task_Id of the called task is
7035796c8dcSSimon Schubert in My_ATCB.Entry_Calls (My_ATCB.ATC_Nesting_Level).Called_Task. */
704a45ae5f8SJohn Marino atc_nesting_level_value =
705a45ae5f8SJohn Marino value_field (tcb_value, pspace_data->atcb_fieldno.atc_nesting_level);
7065796c8dcSSimon Schubert entry_calls_value =
707a45ae5f8SJohn Marino ada_coerce_to_simple_array_ptr
708a45ae5f8SJohn Marino (value_field (tcb_value, pspace_data->atcb_fieldno.entry_calls));
7095796c8dcSSimon Schubert entry_calls_value_element =
7105796c8dcSSimon Schubert value_subscript (entry_calls_value,
7115796c8dcSSimon Schubert value_as_long (atc_nesting_level_value));
7125796c8dcSSimon Schubert called_task_fieldno =
7135796c8dcSSimon Schubert ada_get_field_index (value_type (entry_calls_value_element),
7145796c8dcSSimon Schubert "called_task", 0);
7155796c8dcSSimon Schubert task_info->called_task =
7165796c8dcSSimon Schubert value_as_address (value_field (entry_calls_value_element,
7175796c8dcSSimon Schubert called_task_fieldno));
7185796c8dcSSimon Schubert }
7195796c8dcSSimon Schubert else
7205796c8dcSSimon Schubert {
7215796c8dcSSimon Schubert task_info->called_task = 0;
7225796c8dcSSimon Schubert }
7235796c8dcSSimon Schubert
7245796c8dcSSimon Schubert /* If the ATCB cotnains some information about RV callers,
7255796c8dcSSimon Schubert then compute the "caller_task". Otherwise, zero. */
7265796c8dcSSimon Schubert
7275796c8dcSSimon Schubert task_info->caller_task = 0;
728a45ae5f8SJohn Marino if (pspace_data->atcb_fieldno.call >= 0)
7295796c8dcSSimon Schubert {
7305796c8dcSSimon Schubert /* Get the ID of the caller task from Common_ATCB.Call.all.Self.
7315796c8dcSSimon Schubert If Common_ATCB.Call is null, then there is no caller. */
7325796c8dcSSimon Schubert const CORE_ADDR call =
733a45ae5f8SJohn Marino value_as_address (value_field (common_value,
734a45ae5f8SJohn Marino pspace_data->atcb_fieldno.call));
7355796c8dcSSimon Schubert struct value *call_val;
7365796c8dcSSimon Schubert
7375796c8dcSSimon Schubert if (call != 0)
7385796c8dcSSimon Schubert {
7395796c8dcSSimon Schubert call_val =
740a45ae5f8SJohn Marino value_from_contents_and_address (pspace_data->atcb_call_type,
741a45ae5f8SJohn Marino NULL, call);
7425796c8dcSSimon Schubert task_info->caller_task =
743a45ae5f8SJohn Marino value_as_address
744a45ae5f8SJohn Marino (value_field (call_val, pspace_data->atcb_fieldno.call_self));
7455796c8dcSSimon Schubert }
7465796c8dcSSimon Schubert }
7475796c8dcSSimon Schubert
748c50c785cSJohn Marino /* And finally, compute the task ptid. Note that there are situations
749c50c785cSJohn Marino where this cannot be determined:
750c50c785cSJohn Marino - The task is no longer alive - the ptid is irrelevant;
751c50c785cSJohn Marino - We are debugging a core file - the thread is not always
752c50c785cSJohn Marino completely preserved for us to link back a task to its
753c50c785cSJohn Marino underlying thread. Since we do not support task switching
754c50c785cSJohn Marino when debugging core files anyway, we don't need to compute
755c50c785cSJohn Marino that task ptid.
756c50c785cSJohn Marino In either case, we don't need that ptid, and it is just good enough
757c50c785cSJohn Marino to set it to null_ptid. */
7585796c8dcSSimon Schubert
759c50c785cSJohn Marino if (target_has_execution && ada_task_is_alive (task_info))
7605796c8dcSSimon Schubert task_info->ptid = ptid_from_atcb_common (common_value);
7615796c8dcSSimon Schubert else
7625796c8dcSSimon Schubert task_info->ptid = null_ptid;
7635796c8dcSSimon Schubert }
7645796c8dcSSimon Schubert
7655796c8dcSSimon Schubert /* Read the ATCB info of the given task (identified by TASK_ID), and
766a45ae5f8SJohn Marino add the result to the given inferior's TASK_LIST. */
7675796c8dcSSimon Schubert
7685796c8dcSSimon Schubert static void
add_ada_task(CORE_ADDR task_id,struct inferior * inf)769a45ae5f8SJohn Marino add_ada_task (CORE_ADDR task_id, struct inferior *inf)
7705796c8dcSSimon Schubert {
7715796c8dcSSimon Schubert struct ada_task_info task_info;
772a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf);
7735796c8dcSSimon Schubert
7745796c8dcSSimon Schubert read_atcb (task_id, &task_info);
775a45ae5f8SJohn Marino VEC_safe_push (ada_task_info_s, data->task_list, &task_info);
7765796c8dcSSimon Schubert }
7775796c8dcSSimon Schubert
7785796c8dcSSimon Schubert /* Read the Known_Tasks array from the inferior memory, and store
779a45ae5f8SJohn Marino it in the current inferior's TASK_LIST. Return non-zero upon success. */
7805796c8dcSSimon Schubert
7815796c8dcSSimon Schubert static int
read_known_tasks_array(struct ada_tasks_inferior_data * data)782*ef5ccd6cSJohn Marino read_known_tasks_array (struct ada_tasks_inferior_data *data)
7835796c8dcSSimon Schubert {
784*ef5ccd6cSJohn Marino const int target_ptr_byte = TYPE_LENGTH (data->known_tasks_element);
785*ef5ccd6cSJohn Marino const int known_tasks_size = target_ptr_byte * data->known_tasks_length;
7865796c8dcSSimon Schubert gdb_byte *known_tasks = alloca (known_tasks_size);
7875796c8dcSSimon Schubert int i;
7885796c8dcSSimon Schubert
789a45ae5f8SJohn Marino /* Build a new list by reading the ATCBs from the Known_Tasks array
790a45ae5f8SJohn Marino in the Ada runtime. */
791*ef5ccd6cSJohn Marino read_memory (data->known_tasks_addr, known_tasks, known_tasks_size);
792*ef5ccd6cSJohn Marino for (i = 0; i < data->known_tasks_length; i++)
7935796c8dcSSimon Schubert {
7945796c8dcSSimon Schubert CORE_ADDR task_id =
7955796c8dcSSimon Schubert extract_typed_address (known_tasks + i * target_ptr_byte,
796*ef5ccd6cSJohn Marino data->known_tasks_element);
7975796c8dcSSimon Schubert
7985796c8dcSSimon Schubert if (task_id != 0)
799a45ae5f8SJohn Marino add_ada_task (task_id, current_inferior ());
8005796c8dcSSimon Schubert }
8015796c8dcSSimon Schubert
8025796c8dcSSimon Schubert return 1;
8035796c8dcSSimon Schubert }
8045796c8dcSSimon Schubert
805a45ae5f8SJohn Marino /* Read the known tasks from the inferior memory, and store it in
806a45ae5f8SJohn Marino the current inferior's TASK_LIST. Return non-zero upon success. */
807a45ae5f8SJohn Marino
808a45ae5f8SJohn Marino static int
read_known_tasks_list(struct ada_tasks_inferior_data * data)809*ef5ccd6cSJohn Marino read_known_tasks_list (struct ada_tasks_inferior_data *data)
810a45ae5f8SJohn Marino {
811*ef5ccd6cSJohn Marino const int target_ptr_byte = TYPE_LENGTH (data->known_tasks_element);
812a45ae5f8SJohn Marino gdb_byte *known_tasks = alloca (target_ptr_byte);
813a45ae5f8SJohn Marino CORE_ADDR task_id;
814a45ae5f8SJohn Marino const struct ada_tasks_pspace_data *pspace_data
815a45ae5f8SJohn Marino = get_ada_tasks_pspace_data (current_program_space);
816a45ae5f8SJohn Marino
817a45ae5f8SJohn Marino /* Sanity check. */
818a45ae5f8SJohn Marino if (pspace_data->atcb_fieldno.activation_link < 0)
819a45ae5f8SJohn Marino return 0;
820a45ae5f8SJohn Marino
821a45ae5f8SJohn Marino /* Build a new list by reading the ATCBs. Read head of the list. */
822*ef5ccd6cSJohn Marino read_memory (data->known_tasks_addr, known_tasks, target_ptr_byte);
823*ef5ccd6cSJohn Marino task_id = extract_typed_address (known_tasks, data->known_tasks_element);
824a45ae5f8SJohn Marino while (task_id != 0)
825a45ae5f8SJohn Marino {
826a45ae5f8SJohn Marino struct value *tcb_value;
827a45ae5f8SJohn Marino struct value *common_value;
828a45ae5f8SJohn Marino
829a45ae5f8SJohn Marino add_ada_task (task_id, current_inferior ());
830a45ae5f8SJohn Marino
831a45ae5f8SJohn Marino /* Read the chain. */
832a45ae5f8SJohn Marino tcb_value = value_from_contents_and_address (pspace_data->atcb_type,
833a45ae5f8SJohn Marino NULL, task_id);
834a45ae5f8SJohn Marino common_value = value_field (tcb_value, pspace_data->atcb_fieldno.common);
835a45ae5f8SJohn Marino task_id = value_as_address
836a45ae5f8SJohn Marino (value_field (common_value,
837a45ae5f8SJohn Marino pspace_data->atcb_fieldno.activation_link));
838a45ae5f8SJohn Marino }
839a45ae5f8SJohn Marino
840a45ae5f8SJohn Marino return 1;
841a45ae5f8SJohn Marino }
842a45ae5f8SJohn Marino
843*ef5ccd6cSJohn Marino /* Set all fields of the current inferior ada-tasks data pointed by DATA.
844*ef5ccd6cSJohn Marino Do nothing if those fields are already set and still up to date. */
845a45ae5f8SJohn Marino
846a45ae5f8SJohn Marino static void
ada_tasks_inferior_data_sniffer(struct ada_tasks_inferior_data * data)847*ef5ccd6cSJohn Marino ada_tasks_inferior_data_sniffer (struct ada_tasks_inferior_data *data)
848a45ae5f8SJohn Marino {
849*ef5ccd6cSJohn Marino struct minimal_symbol *msym;
850*ef5ccd6cSJohn Marino struct symbol *sym;
851a45ae5f8SJohn Marino
852*ef5ccd6cSJohn Marino /* Return now if already set. */
853a45ae5f8SJohn Marino if (data->known_tasks_kind != ADA_TASKS_UNKNOWN)
854a45ae5f8SJohn Marino return;
855a45ae5f8SJohn Marino
856*ef5ccd6cSJohn Marino /* Try array. */
857*ef5ccd6cSJohn Marino
858*ef5ccd6cSJohn Marino msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
859*ef5ccd6cSJohn Marino if (msym != NULL)
860a45ae5f8SJohn Marino {
861a45ae5f8SJohn Marino data->known_tasks_kind = ADA_TASKS_ARRAY;
862*ef5ccd6cSJohn Marino data->known_tasks_addr = SYMBOL_VALUE_ADDRESS (msym);
863*ef5ccd6cSJohn Marino
864*ef5ccd6cSJohn Marino /* Try to get pointer type and array length from the symtab. */
865*ef5ccd6cSJohn Marino sym = lookup_symbol_in_language (KNOWN_TASKS_NAME, NULL, VAR_DOMAIN,
866*ef5ccd6cSJohn Marino language_c, NULL);
867*ef5ccd6cSJohn Marino if (sym != NULL)
868*ef5ccd6cSJohn Marino {
869*ef5ccd6cSJohn Marino /* Validate. */
870*ef5ccd6cSJohn Marino struct type *type = check_typedef (SYMBOL_TYPE (sym));
871*ef5ccd6cSJohn Marino struct type *eltype = NULL;
872*ef5ccd6cSJohn Marino struct type *idxtype = NULL;
873*ef5ccd6cSJohn Marino
874*ef5ccd6cSJohn Marino if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
875*ef5ccd6cSJohn Marino eltype = check_typedef (TYPE_TARGET_TYPE (type));
876*ef5ccd6cSJohn Marino if (eltype != NULL
877*ef5ccd6cSJohn Marino && TYPE_CODE (eltype) == TYPE_CODE_PTR)
878*ef5ccd6cSJohn Marino idxtype = check_typedef (TYPE_INDEX_TYPE (type));
879*ef5ccd6cSJohn Marino if (idxtype != NULL
880*ef5ccd6cSJohn Marino && !TYPE_LOW_BOUND_UNDEFINED (idxtype)
881*ef5ccd6cSJohn Marino && !TYPE_HIGH_BOUND_UNDEFINED (idxtype))
882*ef5ccd6cSJohn Marino {
883*ef5ccd6cSJohn Marino data->known_tasks_element = eltype;
884*ef5ccd6cSJohn Marino data->known_tasks_length =
885*ef5ccd6cSJohn Marino TYPE_HIGH_BOUND (idxtype) - TYPE_LOW_BOUND (idxtype) + 1;
886*ef5ccd6cSJohn Marino return;
887*ef5ccd6cSJohn Marino }
888*ef5ccd6cSJohn Marino }
889*ef5ccd6cSJohn Marino
890*ef5ccd6cSJohn Marino /* Fallback to default values. The runtime may have been stripped (as
891*ef5ccd6cSJohn Marino in some distributions), but it is likely that the executable still
892*ef5ccd6cSJohn Marino contains debug information on the task type (due to implicit with of
893*ef5ccd6cSJohn Marino Ada.Tasking). */
894*ef5ccd6cSJohn Marino data->known_tasks_element =
895*ef5ccd6cSJohn Marino builtin_type (target_gdbarch ())->builtin_data_ptr;
896*ef5ccd6cSJohn Marino data->known_tasks_length = MAX_NUMBER_OF_KNOWN_TASKS;
897a45ae5f8SJohn Marino return;
898a45ae5f8SJohn Marino }
899a45ae5f8SJohn Marino
900*ef5ccd6cSJohn Marino
901*ef5ccd6cSJohn Marino /* Try list. */
902*ef5ccd6cSJohn Marino
903*ef5ccd6cSJohn Marino msym = lookup_minimal_symbol (KNOWN_TASKS_LIST, NULL, NULL);
904*ef5ccd6cSJohn Marino if (msym != NULL)
905a45ae5f8SJohn Marino {
906a45ae5f8SJohn Marino data->known_tasks_kind = ADA_TASKS_LIST;
907*ef5ccd6cSJohn Marino data->known_tasks_addr = SYMBOL_VALUE_ADDRESS (msym);
908*ef5ccd6cSJohn Marino data->known_tasks_length = 1;
909*ef5ccd6cSJohn Marino
910*ef5ccd6cSJohn Marino sym = lookup_symbol_in_language (KNOWN_TASKS_LIST, NULL, VAR_DOMAIN,
911*ef5ccd6cSJohn Marino language_c, NULL);
912*ef5ccd6cSJohn Marino if (sym != NULL && SYMBOL_VALUE_ADDRESS (sym) != 0)
913*ef5ccd6cSJohn Marino {
914*ef5ccd6cSJohn Marino /* Validate. */
915*ef5ccd6cSJohn Marino struct type *type = check_typedef (SYMBOL_TYPE (sym));
916*ef5ccd6cSJohn Marino
917*ef5ccd6cSJohn Marino if (TYPE_CODE (type) == TYPE_CODE_PTR)
918*ef5ccd6cSJohn Marino {
919*ef5ccd6cSJohn Marino data->known_tasks_element = type;
920a45ae5f8SJohn Marino return;
921a45ae5f8SJohn Marino }
922*ef5ccd6cSJohn Marino }
923*ef5ccd6cSJohn Marino
924*ef5ccd6cSJohn Marino /* Fallback to default values. */
925*ef5ccd6cSJohn Marino data->known_tasks_element =
926*ef5ccd6cSJohn Marino builtin_type (target_gdbarch ())->builtin_data_ptr;
927*ef5ccd6cSJohn Marino data->known_tasks_length = 1;
928*ef5ccd6cSJohn Marino return;
929*ef5ccd6cSJohn Marino }
930*ef5ccd6cSJohn Marino
931*ef5ccd6cSJohn Marino /* Can't find tasks. */
932a45ae5f8SJohn Marino
933a45ae5f8SJohn Marino data->known_tasks_kind = ADA_TASKS_NOT_FOUND;
934a45ae5f8SJohn Marino data->known_tasks_addr = 0;
935a45ae5f8SJohn Marino }
936a45ae5f8SJohn Marino
937a45ae5f8SJohn Marino /* Read the known tasks from the current inferior's memory, and store it
938a45ae5f8SJohn Marino in the current inferior's data TASK_LIST.
939a45ae5f8SJohn Marino Return non-zero upon success. */
940a45ae5f8SJohn Marino
941a45ae5f8SJohn Marino static int
read_known_tasks(void)942a45ae5f8SJohn Marino read_known_tasks (void)
943a45ae5f8SJohn Marino {
944a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data =
945a45ae5f8SJohn Marino get_ada_tasks_inferior_data (current_inferior ());
946a45ae5f8SJohn Marino
947a45ae5f8SJohn Marino /* Step 1: Clear the current list, if necessary. */
948a45ae5f8SJohn Marino VEC_truncate (ada_task_info_s, data->task_list, 0);
949a45ae5f8SJohn Marino
950a45ae5f8SJohn Marino /* Step 2: do the real work.
951a45ae5f8SJohn Marino If the application does not use task, then no more needs to be done.
952a45ae5f8SJohn Marino It is important to have the task list cleared (see above) before we
953a45ae5f8SJohn Marino return, as we don't want a stale task list to be used... This can
954a45ae5f8SJohn Marino happen for instance when debugging a non-multitasking program after
955a45ae5f8SJohn Marino having debugged a multitasking one. */
956*ef5ccd6cSJohn Marino ada_tasks_inferior_data_sniffer (data);
957a45ae5f8SJohn Marino gdb_assert (data->known_tasks_kind != ADA_TASKS_UNKNOWN);
958a45ae5f8SJohn Marino
959a45ae5f8SJohn Marino switch (data->known_tasks_kind)
960a45ae5f8SJohn Marino {
961a45ae5f8SJohn Marino case ADA_TASKS_NOT_FOUND: /* Tasking not in use in inferior. */
962a45ae5f8SJohn Marino return 0;
963a45ae5f8SJohn Marino case ADA_TASKS_ARRAY:
964*ef5ccd6cSJohn Marino return read_known_tasks_array (data);
965a45ae5f8SJohn Marino case ADA_TASKS_LIST:
966*ef5ccd6cSJohn Marino return read_known_tasks_list (data);
967a45ae5f8SJohn Marino }
968a45ae5f8SJohn Marino
969a45ae5f8SJohn Marino /* Step 3: Set task_list_valid_p, to avoid re-reading the Known_Tasks
970a45ae5f8SJohn Marino array unless needed. Then report a success. */
971a45ae5f8SJohn Marino data->task_list_valid_p = 1;
972a45ae5f8SJohn Marino
973a45ae5f8SJohn Marino return 1;
974a45ae5f8SJohn Marino }
975a45ae5f8SJohn Marino
976a45ae5f8SJohn Marino /* Build the task_list by reading the Known_Tasks array from
977a45ae5f8SJohn Marino the inferior, and return the number of tasks in that list
978a45ae5f8SJohn Marino (zero means that the program is not using tasking at all). */
9795796c8dcSSimon Schubert
9805796c8dcSSimon Schubert int
ada_build_task_list(void)981a45ae5f8SJohn Marino ada_build_task_list (void)
9825796c8dcSSimon Schubert {
983a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data;
984a45ae5f8SJohn Marino
9855796c8dcSSimon Schubert if (!target_has_stack)
9865796c8dcSSimon Schubert error (_("Cannot inspect Ada tasks when program is not running"));
9875796c8dcSSimon Schubert
988a45ae5f8SJohn Marino data = get_ada_tasks_inferior_data (current_inferior ());
989a45ae5f8SJohn Marino if (!data->task_list_valid_p)
990a45ae5f8SJohn Marino read_known_tasks ();
9915796c8dcSSimon Schubert
992a45ae5f8SJohn Marino return VEC_length (ada_task_info_s, data->task_list);
993a45ae5f8SJohn Marino }
994a45ae5f8SJohn Marino
995a45ae5f8SJohn Marino /* Print a table providing a short description of all Ada tasks
996a45ae5f8SJohn Marino running inside inferior INF. If ARG_STR is set, it will be
997a45ae5f8SJohn Marino interpreted as a task number, and the table will be limited to
998a45ae5f8SJohn Marino that task only. */
999a45ae5f8SJohn Marino
1000a45ae5f8SJohn Marino void
print_ada_task_info(struct ui_out * uiout,char * arg_str,struct inferior * inf)1001a45ae5f8SJohn Marino print_ada_task_info (struct ui_out *uiout,
1002a45ae5f8SJohn Marino char *arg_str,
1003a45ae5f8SJohn Marino struct inferior *inf)
10045796c8dcSSimon Schubert {
1005a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data;
1006a45ae5f8SJohn Marino int taskno, nb_tasks;
1007a45ae5f8SJohn Marino int taskno_arg = 0;
1008a45ae5f8SJohn Marino struct cleanup *old_chain;
1009a45ae5f8SJohn Marino int nb_columns;
1010a45ae5f8SJohn Marino
1011a45ae5f8SJohn Marino if (ada_build_task_list () == 0)
1012a45ae5f8SJohn Marino {
1013a45ae5f8SJohn Marino ui_out_message (uiout, 0,
1014a45ae5f8SJohn Marino _("Your application does not use any Ada tasks.\n"));
1015a45ae5f8SJohn Marino return;
10165796c8dcSSimon Schubert }
10175796c8dcSSimon Schubert
1018a45ae5f8SJohn Marino if (arg_str != NULL && arg_str[0] != '\0')
1019a45ae5f8SJohn Marino taskno_arg = value_as_long (parse_and_eval (arg_str));
1020a45ae5f8SJohn Marino
1021a45ae5f8SJohn Marino if (ui_out_is_mi_like_p (uiout))
1022a45ae5f8SJohn Marino /* In GDB/MI mode, we want to provide the thread ID corresponding
1023a45ae5f8SJohn Marino to each task. This allows clients to quickly find the thread
1024a45ae5f8SJohn Marino associated to any task, which is helpful for commands that
1025a45ae5f8SJohn Marino take a --thread argument. However, in order to be able to
1026a45ae5f8SJohn Marino provide that thread ID, the thread list must be up to date
1027a45ae5f8SJohn Marino first. */
1028a45ae5f8SJohn Marino target_find_new_threads ();
1029a45ae5f8SJohn Marino
1030a45ae5f8SJohn Marino data = get_ada_tasks_inferior_data (inf);
1031a45ae5f8SJohn Marino
1032a45ae5f8SJohn Marino /* Compute the number of tasks that are going to be displayed
1033a45ae5f8SJohn Marino in the output. If an argument was given, there will be
1034a45ae5f8SJohn Marino at most 1 entry. Otherwise, there will be as many entries
1035a45ae5f8SJohn Marino as we have tasks. */
1036a45ae5f8SJohn Marino if (taskno_arg)
1037a45ae5f8SJohn Marino {
1038a45ae5f8SJohn Marino if (taskno_arg > 0
1039a45ae5f8SJohn Marino && taskno_arg <= VEC_length (ada_task_info_s, data->task_list))
1040a45ae5f8SJohn Marino nb_tasks = 1;
1041a45ae5f8SJohn Marino else
1042a45ae5f8SJohn Marino nb_tasks = 0;
10435796c8dcSSimon Schubert }
1044a45ae5f8SJohn Marino else
1045a45ae5f8SJohn Marino nb_tasks = VEC_length (ada_task_info_s, data->task_list);
10465796c8dcSSimon Schubert
1047a45ae5f8SJohn Marino nb_columns = ui_out_is_mi_like_p (uiout) ? 8 : 7;
1048a45ae5f8SJohn Marino old_chain = make_cleanup_ui_out_table_begin_end (uiout, nb_columns,
1049a45ae5f8SJohn Marino nb_tasks, "tasks");
1050a45ae5f8SJohn Marino ui_out_table_header (uiout, 1, ui_left, "current", "");
1051a45ae5f8SJohn Marino ui_out_table_header (uiout, 3, ui_right, "id", "ID");
1052a45ae5f8SJohn Marino ui_out_table_header (uiout, 9, ui_right, "task-id", "TID");
1053a45ae5f8SJohn Marino /* The following column is provided in GDB/MI mode only because
1054a45ae5f8SJohn Marino it is only really useful in that mode, and also because it
1055a45ae5f8SJohn Marino allows us to keep the CLI output shorter and more compact. */
1056a45ae5f8SJohn Marino if (ui_out_is_mi_like_p (uiout))
1057a45ae5f8SJohn Marino ui_out_table_header (uiout, 4, ui_right, "thread-id", "");
1058a45ae5f8SJohn Marino ui_out_table_header (uiout, 4, ui_right, "parent-id", "P-ID");
1059a45ae5f8SJohn Marino ui_out_table_header (uiout, 3, ui_right, "priority", "Pri");
1060a45ae5f8SJohn Marino ui_out_table_header (uiout, 22, ui_left, "state", "State");
1061a45ae5f8SJohn Marino /* Use ui_noalign for the last column, to prevent the CLI uiout
1062a45ae5f8SJohn Marino from printing an extra space at the end of each row. This
1063a45ae5f8SJohn Marino is a bit of a hack, but does get the job done. */
1064a45ae5f8SJohn Marino ui_out_table_header (uiout, 1, ui_noalign, "name", "Name");
1065a45ae5f8SJohn Marino ui_out_table_body (uiout);
10665796c8dcSSimon Schubert
1067a45ae5f8SJohn Marino for (taskno = 1;
1068a45ae5f8SJohn Marino taskno <= VEC_length (ada_task_info_s, data->task_list);
1069a45ae5f8SJohn Marino taskno++)
10705796c8dcSSimon Schubert {
10715796c8dcSSimon Schubert const struct ada_task_info *const task_info =
1072a45ae5f8SJohn Marino VEC_index (ada_task_info_s, data->task_list, taskno - 1);
1073a45ae5f8SJohn Marino int parent_id;
1074a45ae5f8SJohn Marino struct cleanup *chain2;
10755796c8dcSSimon Schubert
10765796c8dcSSimon Schubert gdb_assert (task_info != NULL);
10775796c8dcSSimon Schubert
1078a45ae5f8SJohn Marino /* If the user asked for the output to be restricted
1079a45ae5f8SJohn Marino to one task only, and this is not the task, skip
1080a45ae5f8SJohn Marino to the next one. */
1081a45ae5f8SJohn Marino if (taskno_arg && taskno != taskno_arg)
1082a45ae5f8SJohn Marino continue;
10835796c8dcSSimon Schubert
1084a45ae5f8SJohn Marino chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
1085a45ae5f8SJohn Marino
1086a45ae5f8SJohn Marino /* Print a star if this task is the current task (or the task
1087a45ae5f8SJohn Marino currently selected). */
1088a45ae5f8SJohn Marino if (ptid_equal (task_info->ptid, inferior_ptid))
1089a45ae5f8SJohn Marino ui_out_field_string (uiout, "current", "*");
10905796c8dcSSimon Schubert else
1091a45ae5f8SJohn Marino ui_out_field_skip (uiout, "current");
10925796c8dcSSimon Schubert
10935796c8dcSSimon Schubert /* Print the task number. */
1094a45ae5f8SJohn Marino ui_out_field_int (uiout, "id", taskno);
10955796c8dcSSimon Schubert
10965796c8dcSSimon Schubert /* Print the Task ID. */
1097a45ae5f8SJohn Marino ui_out_field_fmt (uiout, "task-id", "%9lx", (long) task_info->task_id);
10985796c8dcSSimon Schubert
1099a45ae5f8SJohn Marino /* Print the associated Thread ID. */
1100a45ae5f8SJohn Marino if (ui_out_is_mi_like_p (uiout))
1101a45ae5f8SJohn Marino {
1102a45ae5f8SJohn Marino const int thread_id = pid_to_thread_id (task_info->ptid);
1103a45ae5f8SJohn Marino
1104a45ae5f8SJohn Marino if (thread_id != 0)
1105a45ae5f8SJohn Marino ui_out_field_int (uiout, "thread-id", thread_id);
1106a45ae5f8SJohn Marino else
1107a45ae5f8SJohn Marino /* This should never happen unless there is a bug somewhere,
1108a45ae5f8SJohn Marino but be resilient when that happens. */
1109a45ae5f8SJohn Marino ui_out_field_skip (uiout, "thread-id");
1110a45ae5f8SJohn Marino }
1111a45ae5f8SJohn Marino
1112a45ae5f8SJohn Marino /* Print the ID of the parent task. */
1113a45ae5f8SJohn Marino parent_id = get_task_number_from_id (task_info->parent, inf);
1114a45ae5f8SJohn Marino if (parent_id)
1115a45ae5f8SJohn Marino ui_out_field_int (uiout, "parent-id", parent_id);
1116a45ae5f8SJohn Marino else
1117a45ae5f8SJohn Marino ui_out_field_skip (uiout, "parent-id");
11185796c8dcSSimon Schubert
11195796c8dcSSimon Schubert /* Print the base priority of the task. */
1120a45ae5f8SJohn Marino ui_out_field_int (uiout, "priority", task_info->priority);
11215796c8dcSSimon Schubert
11225796c8dcSSimon Schubert /* Print the task current state. */
11235796c8dcSSimon Schubert if (task_info->caller_task)
1124a45ae5f8SJohn Marino ui_out_field_fmt (uiout, "state",
1125a45ae5f8SJohn Marino _("Accepting RV with %-4d"),
1126a45ae5f8SJohn Marino get_task_number_from_id (task_info->caller_task,
1127a45ae5f8SJohn Marino inf));
1128a45ae5f8SJohn Marino else if (task_info->state == Entry_Caller_Sleep
1129a45ae5f8SJohn Marino && task_info->called_task)
1130a45ae5f8SJohn Marino ui_out_field_fmt (uiout, "state",
1131a45ae5f8SJohn Marino _("Waiting on RV with %-3d"),
1132a45ae5f8SJohn Marino get_task_number_from_id (task_info->called_task,
1133a45ae5f8SJohn Marino inf));
11345796c8dcSSimon Schubert else
1135a45ae5f8SJohn Marino ui_out_field_string (uiout, "state", task_states[task_info->state]);
11365796c8dcSSimon Schubert
11375796c8dcSSimon Schubert /* Finally, print the task name. */
1138a45ae5f8SJohn Marino ui_out_field_fmt (uiout, "name",
1139a45ae5f8SJohn Marino "%s",
1140a45ae5f8SJohn Marino task_info->name[0] != '\0' ? task_info->name
1141a45ae5f8SJohn Marino : _("<no name>"));
1142a45ae5f8SJohn Marino
1143a45ae5f8SJohn Marino ui_out_text (uiout, "\n");
1144a45ae5f8SJohn Marino do_cleanups (chain2);
11455796c8dcSSimon Schubert }
11465796c8dcSSimon Schubert
1147a45ae5f8SJohn Marino do_cleanups (old_chain);
11485796c8dcSSimon Schubert }
11495796c8dcSSimon Schubert
1150a45ae5f8SJohn Marino /* Print a detailed description of the Ada task whose ID is TASKNO_STR
1151a45ae5f8SJohn Marino for the given inferior (INF). */
11525796c8dcSSimon Schubert
11535796c8dcSSimon Schubert static void
info_task(struct ui_out * uiout,char * taskno_str,struct inferior * inf)1154a45ae5f8SJohn Marino info_task (struct ui_out *uiout, char *taskno_str, struct inferior *inf)
11555796c8dcSSimon Schubert {
11565796c8dcSSimon Schubert const int taskno = value_as_long (parse_and_eval (taskno_str));
11575796c8dcSSimon Schubert struct ada_task_info *task_info;
11585796c8dcSSimon Schubert int parent_taskno = 0;
1159a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf);
11605796c8dcSSimon Schubert
1161a45ae5f8SJohn Marino if (ada_build_task_list () == 0)
1162a45ae5f8SJohn Marino {
1163a45ae5f8SJohn Marino ui_out_message (uiout, 0,
1164a45ae5f8SJohn Marino _("Your application does not use any Ada tasks.\n"));
1165a45ae5f8SJohn Marino return;
1166a45ae5f8SJohn Marino }
1167a45ae5f8SJohn Marino
1168a45ae5f8SJohn Marino if (taskno <= 0 || taskno > VEC_length (ada_task_info_s, data->task_list))
11695796c8dcSSimon Schubert error (_("Task ID %d not known. Use the \"info tasks\" command to\n"
11705796c8dcSSimon Schubert "see the IDs of currently known tasks"), taskno);
1171a45ae5f8SJohn Marino task_info = VEC_index (ada_task_info_s, data->task_list, taskno - 1);
11725796c8dcSSimon Schubert
11735796c8dcSSimon Schubert /* Print the Ada task ID. */
11745796c8dcSSimon Schubert printf_filtered (_("Ada Task: %s\n"),
1175*ef5ccd6cSJohn Marino paddress (target_gdbarch (), task_info->task_id));
11765796c8dcSSimon Schubert
11775796c8dcSSimon Schubert /* Print the name of the task. */
11785796c8dcSSimon Schubert if (task_info->name[0] != '\0')
11795796c8dcSSimon Schubert printf_filtered (_("Name: %s\n"), task_info->name);
11805796c8dcSSimon Schubert else
11815796c8dcSSimon Schubert printf_filtered (_("<no name>\n"));
11825796c8dcSSimon Schubert
11835796c8dcSSimon Schubert /* Print the TID and LWP. */
11845796c8dcSSimon Schubert printf_filtered (_("Thread: %#lx\n"), ptid_get_tid (task_info->ptid));
11855796c8dcSSimon Schubert printf_filtered (_("LWP: %#lx\n"), ptid_get_lwp (task_info->ptid));
11865796c8dcSSimon Schubert
11875796c8dcSSimon Schubert /* Print who is the parent (if any). */
11885796c8dcSSimon Schubert if (task_info->parent != 0)
1189a45ae5f8SJohn Marino parent_taskno = get_task_number_from_id (task_info->parent, inf);
11905796c8dcSSimon Schubert if (parent_taskno)
11915796c8dcSSimon Schubert {
11925796c8dcSSimon Schubert struct ada_task_info *parent =
1193a45ae5f8SJohn Marino VEC_index (ada_task_info_s, data->task_list, parent_taskno - 1);
11945796c8dcSSimon Schubert
11955796c8dcSSimon Schubert printf_filtered (_("Parent: %d"), parent_taskno);
11965796c8dcSSimon Schubert if (parent->name[0] != '\0')
11975796c8dcSSimon Schubert printf_filtered (" (%s)", parent->name);
11985796c8dcSSimon Schubert printf_filtered ("\n");
11995796c8dcSSimon Schubert }
12005796c8dcSSimon Schubert else
12015796c8dcSSimon Schubert printf_filtered (_("No parent\n"));
12025796c8dcSSimon Schubert
12035796c8dcSSimon Schubert /* Print the base priority. */
12045796c8dcSSimon Schubert printf_filtered (_("Base Priority: %d\n"), task_info->priority);
12055796c8dcSSimon Schubert
12065796c8dcSSimon Schubert /* print the task current state. */
12075796c8dcSSimon Schubert {
12085796c8dcSSimon Schubert int target_taskno = 0;
12095796c8dcSSimon Schubert
12105796c8dcSSimon Schubert if (task_info->caller_task)
12115796c8dcSSimon Schubert {
1212a45ae5f8SJohn Marino target_taskno = get_task_number_from_id (task_info->caller_task, inf);
12135796c8dcSSimon Schubert printf_filtered (_("State: Accepting rendezvous with %d"),
12145796c8dcSSimon Schubert target_taskno);
12155796c8dcSSimon Schubert }
12165796c8dcSSimon Schubert else if (task_info->state == Entry_Caller_Sleep && task_info->called_task)
12175796c8dcSSimon Schubert {
1218a45ae5f8SJohn Marino target_taskno = get_task_number_from_id (task_info->called_task, inf);
12195796c8dcSSimon Schubert printf_filtered (_("State: Waiting on task %d's entry"),
12205796c8dcSSimon Schubert target_taskno);
12215796c8dcSSimon Schubert }
12225796c8dcSSimon Schubert else
12235796c8dcSSimon Schubert printf_filtered (_("State: %s"), _(long_task_states[task_info->state]));
12245796c8dcSSimon Schubert
12255796c8dcSSimon Schubert if (target_taskno)
12265796c8dcSSimon Schubert {
12275796c8dcSSimon Schubert struct ada_task_info *target_task_info =
1228a45ae5f8SJohn Marino VEC_index (ada_task_info_s, data->task_list, target_taskno - 1);
12295796c8dcSSimon Schubert
12305796c8dcSSimon Schubert if (target_task_info->name[0] != '\0')
12315796c8dcSSimon Schubert printf_filtered (" (%s)", target_task_info->name);
12325796c8dcSSimon Schubert }
12335796c8dcSSimon Schubert
12345796c8dcSSimon Schubert printf_filtered ("\n");
12355796c8dcSSimon Schubert }
12365796c8dcSSimon Schubert }
12375796c8dcSSimon Schubert
12385796c8dcSSimon Schubert /* If ARG is empty or null, then print a list of all Ada tasks.
12395796c8dcSSimon Schubert Otherwise, print detailed information about the task whose ID
12405796c8dcSSimon Schubert is ARG.
12415796c8dcSSimon Schubert
12425796c8dcSSimon Schubert Does nothing if the program doesn't use Ada tasking. */
12435796c8dcSSimon Schubert
12445796c8dcSSimon Schubert static void
info_tasks_command(char * arg,int from_tty)12455796c8dcSSimon Schubert info_tasks_command (char *arg, int from_tty)
12465796c8dcSSimon Schubert {
1247a45ae5f8SJohn Marino struct ui_out *uiout = current_uiout;
12485796c8dcSSimon Schubert
12495796c8dcSSimon Schubert if (arg == NULL || *arg == '\0')
1250a45ae5f8SJohn Marino print_ada_task_info (uiout, NULL, current_inferior ());
12515796c8dcSSimon Schubert else
1252a45ae5f8SJohn Marino info_task (uiout, arg, current_inferior ());
12535796c8dcSSimon Schubert }
12545796c8dcSSimon Schubert
12555796c8dcSSimon Schubert /* Print a message telling the user id of the current task.
12565796c8dcSSimon Schubert This function assumes that tasking is in use in the inferior. */
12575796c8dcSSimon Schubert
12585796c8dcSSimon Schubert static void
display_current_task_id(void)12595796c8dcSSimon Schubert display_current_task_id (void)
12605796c8dcSSimon Schubert {
12615796c8dcSSimon Schubert const int current_task = ada_get_task_number (inferior_ptid);
12625796c8dcSSimon Schubert
12635796c8dcSSimon Schubert if (current_task == 0)
12645796c8dcSSimon Schubert printf_filtered (_("[Current task is unknown]\n"));
12655796c8dcSSimon Schubert else
12665796c8dcSSimon Schubert printf_filtered (_("[Current task is %d]\n"), current_task);
12675796c8dcSSimon Schubert }
12685796c8dcSSimon Schubert
12695796c8dcSSimon Schubert /* Parse and evaluate TIDSTR into a task id, and try to switch to
12705796c8dcSSimon Schubert that task. Print an error message if the task switch failed. */
12715796c8dcSSimon Schubert
12725796c8dcSSimon Schubert static void
task_command_1(char * taskno_str,int from_tty,struct inferior * inf)1273a45ae5f8SJohn Marino task_command_1 (char *taskno_str, int from_tty, struct inferior *inf)
12745796c8dcSSimon Schubert {
12755796c8dcSSimon Schubert const int taskno = value_as_long (parse_and_eval (taskno_str));
12765796c8dcSSimon Schubert struct ada_task_info *task_info;
1277a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf);
12785796c8dcSSimon Schubert
1279a45ae5f8SJohn Marino if (taskno <= 0 || taskno > VEC_length (ada_task_info_s, data->task_list))
12805796c8dcSSimon Schubert error (_("Task ID %d not known. Use the \"info tasks\" command to\n"
12815796c8dcSSimon Schubert "see the IDs of currently known tasks"), taskno);
1282a45ae5f8SJohn Marino task_info = VEC_index (ada_task_info_s, data->task_list, taskno - 1);
12835796c8dcSSimon Schubert
12845796c8dcSSimon Schubert if (!ada_task_is_alive (task_info))
12855796c8dcSSimon Schubert error (_("Cannot switch to task %d: Task is no longer running"), taskno);
12865796c8dcSSimon Schubert
12875796c8dcSSimon Schubert /* On some platforms, the thread list is not updated until the user
12885796c8dcSSimon Schubert performs a thread-related operation (by using the "info threads"
12895796c8dcSSimon Schubert command, for instance). So this thread list may not be up to date
12905796c8dcSSimon Schubert when the user attempts this task switch. Since we cannot switch
12915796c8dcSSimon Schubert to the thread associated to our task if GDB does not know about
12925796c8dcSSimon Schubert that thread, we need to make sure that any new threads gets added
12935796c8dcSSimon Schubert to the thread list. */
12945796c8dcSSimon Schubert target_find_new_threads ();
12955796c8dcSSimon Schubert
1296cf7f2e2dSJohn Marino /* Verify that the ptid of the task we want to switch to is valid
1297cf7f2e2dSJohn Marino (in other words, a ptid that GDB knows about). Otherwise, we will
1298cf7f2e2dSJohn Marino cause an assertion failure later on, when we try to determine
1299cf7f2e2dSJohn Marino the ptid associated thread_info data. We should normally never
1300cf7f2e2dSJohn Marino encounter such an error, but the wrong ptid can actually easily be
1301cf7f2e2dSJohn Marino computed if target_get_ada_task_ptid has not been implemented for
1302cf7f2e2dSJohn Marino our target (yet). Rather than cause an assertion error in that case,
1303cf7f2e2dSJohn Marino it's nicer for the user to just refuse to perform the task switch. */
1304cf7f2e2dSJohn Marino if (!find_thread_ptid (task_info->ptid))
1305cf7f2e2dSJohn Marino error (_("Unable to compute thread ID for task %d.\n"
1306cf7f2e2dSJohn Marino "Cannot switch to this task."),
1307cf7f2e2dSJohn Marino taskno);
1308cf7f2e2dSJohn Marino
13095796c8dcSSimon Schubert switch_to_thread (task_info->ptid);
13105796c8dcSSimon Schubert ada_find_printable_frame (get_selected_frame (NULL));
13115796c8dcSSimon Schubert printf_filtered (_("[Switching to task %d]\n"), taskno);
13125796c8dcSSimon Schubert print_stack_frame (get_selected_frame (NULL),
13135796c8dcSSimon Schubert frame_relative_level (get_selected_frame (NULL)), 1);
13145796c8dcSSimon Schubert }
13155796c8dcSSimon Schubert
13165796c8dcSSimon Schubert
13175796c8dcSSimon Schubert /* Print the ID of the current task if TASKNO_STR is empty or NULL.
13185796c8dcSSimon Schubert Otherwise, switch to the task indicated by TASKNO_STR. */
13195796c8dcSSimon Schubert
13205796c8dcSSimon Schubert static void
task_command(char * taskno_str,int from_tty)13215796c8dcSSimon Schubert task_command (char *taskno_str, int from_tty)
13225796c8dcSSimon Schubert {
1323a45ae5f8SJohn Marino struct ui_out *uiout = current_uiout;
13245796c8dcSSimon Schubert
1325a45ae5f8SJohn Marino if (ada_build_task_list () == 0)
1326a45ae5f8SJohn Marino {
1327a45ae5f8SJohn Marino ui_out_message (uiout, 0,
1328a45ae5f8SJohn Marino _("Your application does not use any Ada tasks.\n"));
13295796c8dcSSimon Schubert return;
1330a45ae5f8SJohn Marino }
13315796c8dcSSimon Schubert
13325796c8dcSSimon Schubert if (taskno_str == NULL || taskno_str[0] == '\0')
13335796c8dcSSimon Schubert display_current_task_id ();
13345796c8dcSSimon Schubert else
13355796c8dcSSimon Schubert {
13365796c8dcSSimon Schubert /* Task switching in core files doesn't work, either because:
13375796c8dcSSimon Schubert 1. Thread support is not implemented with core files
13385796c8dcSSimon Schubert 2. Thread support is implemented, but the thread IDs created
13395796c8dcSSimon Schubert after having read the core file are not the same as the ones
13405796c8dcSSimon Schubert that were used during the program life, before the crash.
13415796c8dcSSimon Schubert As a consequence, there is no longer a way for the debugger
13425796c8dcSSimon Schubert to find the associated thead ID of any given Ada task.
13435796c8dcSSimon Schubert So, instead of attempting a task switch without giving the user
13445796c8dcSSimon Schubert any clue as to what might have happened, just error-out with
13455796c8dcSSimon Schubert a message explaining that this feature is not supported. */
13465796c8dcSSimon Schubert if (!target_has_execution)
13475796c8dcSSimon Schubert error (_("\
13485796c8dcSSimon Schubert Task switching not supported when debugging from core files\n\
13495796c8dcSSimon Schubert (use thread support instead)"));
1350a45ae5f8SJohn Marino task_command_1 (taskno_str, from_tty, current_inferior ());
13515796c8dcSSimon Schubert }
13525796c8dcSSimon Schubert }
13535796c8dcSSimon Schubert
1354a45ae5f8SJohn Marino /* Indicate that the given inferior's task list may have changed,
1355a45ae5f8SJohn Marino so invalidate the cache. */
13565796c8dcSSimon Schubert
13575796c8dcSSimon Schubert static void
ada_task_list_changed(struct inferior * inf)1358a45ae5f8SJohn Marino ada_task_list_changed (struct inferior *inf)
13595796c8dcSSimon Schubert {
1360a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf);
1361a45ae5f8SJohn Marino
1362a45ae5f8SJohn Marino data->task_list_valid_p = 0;
1363a45ae5f8SJohn Marino }
1364a45ae5f8SJohn Marino
1365a45ae5f8SJohn Marino /* Invalidate the per-program-space data. */
1366a45ae5f8SJohn Marino
1367a45ae5f8SJohn Marino static void
ada_tasks_invalidate_pspace_data(struct program_space * pspace)1368a45ae5f8SJohn Marino ada_tasks_invalidate_pspace_data (struct program_space *pspace)
1369a45ae5f8SJohn Marino {
1370a45ae5f8SJohn Marino get_ada_tasks_pspace_data (pspace)->initialized_p = 0;
1371a45ae5f8SJohn Marino }
1372a45ae5f8SJohn Marino
1373a45ae5f8SJohn Marino /* Invalidate the per-inferior data. */
1374a45ae5f8SJohn Marino
1375a45ae5f8SJohn Marino static void
ada_tasks_invalidate_inferior_data(struct inferior * inf)1376a45ae5f8SJohn Marino ada_tasks_invalidate_inferior_data (struct inferior *inf)
1377a45ae5f8SJohn Marino {
1378a45ae5f8SJohn Marino struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf);
1379a45ae5f8SJohn Marino
1380a45ae5f8SJohn Marino data->known_tasks_kind = ADA_TASKS_UNKNOWN;
1381a45ae5f8SJohn Marino data->task_list_valid_p = 0;
13825796c8dcSSimon Schubert }
13835796c8dcSSimon Schubert
13845796c8dcSSimon Schubert /* The 'normal_stop' observer notification callback. */
13855796c8dcSSimon Schubert
13865796c8dcSSimon Schubert static void
ada_normal_stop_observer(struct bpstats * unused_args,int unused_args2)13875796c8dcSSimon Schubert ada_normal_stop_observer (struct bpstats *unused_args, int unused_args2)
13885796c8dcSSimon Schubert {
13895796c8dcSSimon Schubert /* The inferior has been resumed, and just stopped. This means that
13905796c8dcSSimon Schubert our task_list needs to be recomputed before it can be used again. */
1391a45ae5f8SJohn Marino ada_task_list_changed (current_inferior ());
13925796c8dcSSimon Schubert }
13935796c8dcSSimon Schubert
13945796c8dcSSimon Schubert /* A routine to be called when the objfiles have changed. */
13955796c8dcSSimon Schubert
13965796c8dcSSimon Schubert static void
ada_new_objfile_observer(struct objfile * objfile)13975796c8dcSSimon Schubert ada_new_objfile_observer (struct objfile *objfile)
13985796c8dcSSimon Schubert {
1399a45ae5f8SJohn Marino struct inferior *inf;
14005796c8dcSSimon Schubert
1401a45ae5f8SJohn Marino /* Invalidate the relevant data in our program-space data. */
14025796c8dcSSimon Schubert
1403a45ae5f8SJohn Marino if (objfile == NULL)
1404a45ae5f8SJohn Marino {
1405a45ae5f8SJohn Marino /* All objfiles are being cleared, so we should clear all
1406a45ae5f8SJohn Marino our caches for all program spaces. */
1407a45ae5f8SJohn Marino struct program_space *pspace;
1408a45ae5f8SJohn Marino
1409a45ae5f8SJohn Marino for (pspace = program_spaces; pspace != NULL; pspace = pspace->next)
1410a45ae5f8SJohn Marino ada_tasks_invalidate_pspace_data (pspace);
1411a45ae5f8SJohn Marino }
1412a45ae5f8SJohn Marino else
1413a45ae5f8SJohn Marino {
1414a45ae5f8SJohn Marino /* The associated program-space data might have changed after
1415a45ae5f8SJohn Marino this objfile was added. Invalidate all cached data. */
1416a45ae5f8SJohn Marino ada_tasks_invalidate_pspace_data (objfile->pspace);
1417a45ae5f8SJohn Marino }
1418a45ae5f8SJohn Marino
1419a45ae5f8SJohn Marino /* Invalidate the per-inferior cache for all inferiors using
1420a45ae5f8SJohn Marino this objfile (or, in other words, for all inferiors who have
1421a45ae5f8SJohn Marino the same program-space as the objfile's program space).
1422a45ae5f8SJohn Marino If all objfiles are being cleared (OBJFILE is NULL), then
1423a45ae5f8SJohn Marino clear the caches for all inferiors. */
1424a45ae5f8SJohn Marino
1425a45ae5f8SJohn Marino for (inf = inferior_list; inf != NULL; inf = inf->next)
1426a45ae5f8SJohn Marino if (objfile == NULL || inf->pspace == objfile->pspace)
1427a45ae5f8SJohn Marino ada_tasks_invalidate_inferior_data (inf);
14285796c8dcSSimon Schubert }
14295796c8dcSSimon Schubert
14305796c8dcSSimon Schubert /* Provide a prototype to silence -Wmissing-prototypes. */
14315796c8dcSSimon Schubert extern initialize_file_ftype _initialize_tasks;
14325796c8dcSSimon Schubert
14335796c8dcSSimon Schubert void
_initialize_tasks(void)14345796c8dcSSimon Schubert _initialize_tasks (void)
14355796c8dcSSimon Schubert {
1436a45ae5f8SJohn Marino ada_tasks_pspace_data_handle = register_program_space_data ();
1437a45ae5f8SJohn Marino ada_tasks_inferior_data_handle = register_inferior_data ();
1438a45ae5f8SJohn Marino
14395796c8dcSSimon Schubert /* Attach various observers. */
14405796c8dcSSimon Schubert observer_attach_normal_stop (ada_normal_stop_observer);
14415796c8dcSSimon Schubert observer_attach_new_objfile (ada_new_objfile_observer);
14425796c8dcSSimon Schubert
14435796c8dcSSimon Schubert /* Some new commands provided by this module. */
14445796c8dcSSimon Schubert add_info ("tasks", info_tasks_command,
14455796c8dcSSimon Schubert _("Provide information about all known Ada tasks"));
14465796c8dcSSimon Schubert add_cmd ("task", class_run, task_command,
14475796c8dcSSimon Schubert _("Use this command to switch between Ada tasks.\n\
14485796c8dcSSimon Schubert Without argument, this command simply prints the current task ID"),
14495796c8dcSSimon Schubert &cmdlist);
14505796c8dcSSimon Schubert }
14515796c8dcSSimon Schubert
1452