xref: /dflybsd-src/contrib/gdb-7/gdb/progspace.c (revision a45ae5f869d9cfcb3e41dbab486e10bfa9e336bf)
1cf7f2e2dSJohn Marino /* Program and address space management, for GDB, the GNU debugger.
2cf7f2e2dSJohn Marino 
3*a45ae5f8SJohn Marino    Copyright (C) 2009-2012 Free Software Foundation, Inc.
4cf7f2e2dSJohn Marino 
5cf7f2e2dSJohn Marino    This file is part of GDB.
6cf7f2e2dSJohn Marino 
7cf7f2e2dSJohn Marino    This program is free software; you can redistribute it and/or modify
8cf7f2e2dSJohn Marino    it under the terms of the GNU General Public License as published by
9cf7f2e2dSJohn Marino    the Free Software Foundation; either version 3 of the License, or
10cf7f2e2dSJohn Marino    (at your option) any later version.
11cf7f2e2dSJohn Marino 
12cf7f2e2dSJohn Marino    This program is distributed in the hope that it will be useful,
13cf7f2e2dSJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
14cf7f2e2dSJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15cf7f2e2dSJohn Marino    GNU General Public License for more details.
16cf7f2e2dSJohn Marino 
17cf7f2e2dSJohn Marino    You should have received a copy of the GNU General Public License
18cf7f2e2dSJohn Marino    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19cf7f2e2dSJohn Marino 
20cf7f2e2dSJohn Marino #include "defs.h"
21cf7f2e2dSJohn Marino #include "gdbcmd.h"
22cf7f2e2dSJohn Marino #include "objfiles.h"
23cf7f2e2dSJohn Marino #include "arch-utils.h"
24cf7f2e2dSJohn Marino #include "gdbcore.h"
25cf7f2e2dSJohn Marino #include "solib.h"
26cf7f2e2dSJohn Marino #include "gdbthread.h"
27cf7f2e2dSJohn Marino 
28cf7f2e2dSJohn Marino /* The last program space number assigned.  */
29cf7f2e2dSJohn Marino int last_program_space_num = 0;
30cf7f2e2dSJohn Marino 
31cf7f2e2dSJohn Marino /* The head of the program spaces list.  */
32cf7f2e2dSJohn Marino struct program_space *program_spaces;
33cf7f2e2dSJohn Marino 
34cf7f2e2dSJohn Marino /* Pointer to the current program space.  */
35cf7f2e2dSJohn Marino struct program_space *current_program_space;
36cf7f2e2dSJohn Marino 
37cf7f2e2dSJohn Marino /* The last address space number assigned.  */
38cf7f2e2dSJohn Marino static int highest_address_space_num;
39cf7f2e2dSJohn Marino 
40cf7f2e2dSJohn Marino /* Prototypes for local functions */
41cf7f2e2dSJohn Marino 
42cf7f2e2dSJohn Marino static void program_space_alloc_data (struct program_space *);
43cf7f2e2dSJohn Marino static void program_space_free_data (struct program_space *);
44cf7f2e2dSJohn Marino 
45cf7f2e2dSJohn Marino 
46cf7f2e2dSJohn Marino /* An address space.  Currently this is not used for much other than
47cf7f2e2dSJohn Marino    for comparing if pspaces/inferior/threads see the same address
48cf7f2e2dSJohn Marino    space.  */
49cf7f2e2dSJohn Marino 
50cf7f2e2dSJohn Marino struct address_space
51cf7f2e2dSJohn Marino {
52cf7f2e2dSJohn Marino   int num;
53cf7f2e2dSJohn Marino };
54cf7f2e2dSJohn Marino 
55cf7f2e2dSJohn Marino /* Create a new address space object, and add it to the list.  */
56cf7f2e2dSJohn Marino 
57cf7f2e2dSJohn Marino struct address_space *
58cf7f2e2dSJohn Marino new_address_space (void)
59cf7f2e2dSJohn Marino {
60cf7f2e2dSJohn Marino   struct address_space *aspace;
61cf7f2e2dSJohn Marino 
62cf7f2e2dSJohn Marino   aspace = XZALLOC (struct address_space);
63cf7f2e2dSJohn Marino   aspace->num = ++highest_address_space_num;
64cf7f2e2dSJohn Marino 
65cf7f2e2dSJohn Marino   return aspace;
66cf7f2e2dSJohn Marino }
67cf7f2e2dSJohn Marino 
68cf7f2e2dSJohn Marino /* Maybe create a new address space object, and add it to the list, or
69cf7f2e2dSJohn Marino    return a pointer to an existing address space, in case inferiors
70cf7f2e2dSJohn Marino    share an address space on this target system.  */
71cf7f2e2dSJohn Marino 
72cf7f2e2dSJohn Marino struct address_space *
73cf7f2e2dSJohn Marino maybe_new_address_space (void)
74cf7f2e2dSJohn Marino {
75cf7f2e2dSJohn Marino   int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch);
76cf7f2e2dSJohn Marino 
77cf7f2e2dSJohn Marino   if (shared_aspace)
78cf7f2e2dSJohn Marino     {
79cf7f2e2dSJohn Marino       /* Just return the first in the list.  */
80cf7f2e2dSJohn Marino       return program_spaces->aspace;
81cf7f2e2dSJohn Marino     }
82cf7f2e2dSJohn Marino 
83cf7f2e2dSJohn Marino   return new_address_space ();
84cf7f2e2dSJohn Marino }
85cf7f2e2dSJohn Marino 
86cf7f2e2dSJohn Marino static void
87cf7f2e2dSJohn Marino free_address_space (struct address_space *aspace)
88cf7f2e2dSJohn Marino {
89cf7f2e2dSJohn Marino   xfree (aspace);
90cf7f2e2dSJohn Marino }
91cf7f2e2dSJohn Marino 
92cf7f2e2dSJohn Marino int
93cf7f2e2dSJohn Marino address_space_num (struct address_space *aspace)
94cf7f2e2dSJohn Marino {
95cf7f2e2dSJohn Marino   return aspace->num;
96cf7f2e2dSJohn Marino }
97cf7f2e2dSJohn Marino 
98cf7f2e2dSJohn Marino /* Start counting over from scratch.  */
99cf7f2e2dSJohn Marino 
100cf7f2e2dSJohn Marino static void
101cf7f2e2dSJohn Marino init_address_spaces (void)
102cf7f2e2dSJohn Marino {
103cf7f2e2dSJohn Marino   highest_address_space_num = 0;
104cf7f2e2dSJohn Marino }
105cf7f2e2dSJohn Marino 
106cf7f2e2dSJohn Marino 
107cf7f2e2dSJohn Marino 
108cf7f2e2dSJohn Marino /* Adds a new empty program space to the program space list, and binds
109cf7f2e2dSJohn Marino    it to ASPACE.  Returns the pointer to the new object.  */
110cf7f2e2dSJohn Marino 
111cf7f2e2dSJohn Marino struct program_space *
112cf7f2e2dSJohn Marino add_program_space (struct address_space *aspace)
113cf7f2e2dSJohn Marino {
114cf7f2e2dSJohn Marino   struct program_space *pspace;
115cf7f2e2dSJohn Marino 
116cf7f2e2dSJohn Marino   pspace = XZALLOC (struct program_space);
117cf7f2e2dSJohn Marino 
118cf7f2e2dSJohn Marino   pspace->num = ++last_program_space_num;
119cf7f2e2dSJohn Marino   pspace->aspace = aspace;
120cf7f2e2dSJohn Marino 
121cf7f2e2dSJohn Marino   program_space_alloc_data (pspace);
122cf7f2e2dSJohn Marino 
123cf7f2e2dSJohn Marino   pspace->next = program_spaces;
124cf7f2e2dSJohn Marino   program_spaces = pspace;
125cf7f2e2dSJohn Marino 
126cf7f2e2dSJohn Marino   return pspace;
127cf7f2e2dSJohn Marino }
128cf7f2e2dSJohn Marino 
129cf7f2e2dSJohn Marino /* Releases program space PSPACE, and all its contents (shared
130cf7f2e2dSJohn Marino    libraries, objfiles, and any other references to the PSPACE in
131cf7f2e2dSJohn Marino    other modules).  It is an internal error to call this when PSPACE
132cf7f2e2dSJohn Marino    is the current program space, since there should always be a
133cf7f2e2dSJohn Marino    program space.  */
134cf7f2e2dSJohn Marino 
135cf7f2e2dSJohn Marino static void
136cf7f2e2dSJohn Marino release_program_space (struct program_space *pspace)
137cf7f2e2dSJohn Marino {
138cf7f2e2dSJohn Marino   struct cleanup *old_chain = save_current_program_space ();
139cf7f2e2dSJohn Marino 
140cf7f2e2dSJohn Marino   gdb_assert (pspace != current_program_space);
141cf7f2e2dSJohn Marino 
142cf7f2e2dSJohn Marino   set_current_program_space (pspace);
143cf7f2e2dSJohn Marino 
144cf7f2e2dSJohn Marino   breakpoint_program_space_exit (pspace);
145cf7f2e2dSJohn Marino   no_shared_libraries (NULL, 0);
146cf7f2e2dSJohn Marino   exec_close ();
147cf7f2e2dSJohn Marino   free_all_objfiles ();
148cf7f2e2dSJohn Marino   if (!gdbarch_has_shared_address_space (target_gdbarch))
149cf7f2e2dSJohn Marino     free_address_space (pspace->aspace);
150cf7f2e2dSJohn Marino   resize_section_table (&pspace->target_sections,
151cf7f2e2dSJohn Marino 			-resize_section_table (&pspace->target_sections, 0));
152cf7f2e2dSJohn Marino     /* Discard any data modules have associated with the PSPACE.  */
153cf7f2e2dSJohn Marino   program_space_free_data (pspace);
154cf7f2e2dSJohn Marino   xfree (pspace);
155cf7f2e2dSJohn Marino 
156cf7f2e2dSJohn Marino   do_cleanups (old_chain);
157cf7f2e2dSJohn Marino }
158cf7f2e2dSJohn Marino 
159cf7f2e2dSJohn Marino /* Unlinks PSPACE from the pspace list, and releases it.  */
160cf7f2e2dSJohn Marino 
161cf7f2e2dSJohn Marino void
162cf7f2e2dSJohn Marino remove_program_space (struct program_space *pspace)
163cf7f2e2dSJohn Marino {
164cf7f2e2dSJohn Marino   struct program_space *ss, **ss_link;
165cf7f2e2dSJohn Marino 
166cf7f2e2dSJohn Marino   ss = program_spaces;
167cf7f2e2dSJohn Marino   ss_link = &program_spaces;
168cf7f2e2dSJohn Marino   while (ss)
169cf7f2e2dSJohn Marino     {
170cf7f2e2dSJohn Marino       if (ss != pspace)
171cf7f2e2dSJohn Marino 	{
172cf7f2e2dSJohn Marino 	  ss_link = &ss->next;
173cf7f2e2dSJohn Marino 	  ss = *ss_link;
174cf7f2e2dSJohn Marino 	  continue;
175cf7f2e2dSJohn Marino 	}
176cf7f2e2dSJohn Marino 
177cf7f2e2dSJohn Marino       *ss_link = ss->next;
178cf7f2e2dSJohn Marino       release_program_space (ss);
179cf7f2e2dSJohn Marino       ss = *ss_link;
180cf7f2e2dSJohn Marino     }
181cf7f2e2dSJohn Marino }
182cf7f2e2dSJohn Marino 
183cf7f2e2dSJohn Marino /* Copies program space SRC to DEST.  Copies the main executable file,
184cf7f2e2dSJohn Marino    and the main symbol file.  Returns DEST.  */
185cf7f2e2dSJohn Marino 
186cf7f2e2dSJohn Marino struct program_space *
187cf7f2e2dSJohn Marino clone_program_space (struct program_space *dest, struct program_space *src)
188cf7f2e2dSJohn Marino {
189cf7f2e2dSJohn Marino   struct cleanup *old_chain;
190cf7f2e2dSJohn Marino 
191cf7f2e2dSJohn Marino   old_chain = save_current_program_space ();
192cf7f2e2dSJohn Marino 
193cf7f2e2dSJohn Marino   set_current_program_space (dest);
194cf7f2e2dSJohn Marino 
195cf7f2e2dSJohn Marino   if (src->ebfd != NULL)
196cf7f2e2dSJohn Marino     exec_file_attach (bfd_get_filename (src->ebfd), 0);
197cf7f2e2dSJohn Marino 
198cf7f2e2dSJohn Marino   if (src->symfile_object_file != NULL)
199cf7f2e2dSJohn Marino     symbol_file_add_main (src->symfile_object_file->name, 0);
200cf7f2e2dSJohn Marino 
201cf7f2e2dSJohn Marino   do_cleanups (old_chain);
202cf7f2e2dSJohn Marino   return dest;
203cf7f2e2dSJohn Marino }
204cf7f2e2dSJohn Marino 
205cf7f2e2dSJohn Marino /* Sets PSPACE as the current program space.  It is the caller's
206cf7f2e2dSJohn Marino    responsibility to make sure that the currently selected
207cf7f2e2dSJohn Marino    inferior/thread matches the selected program space.  */
208cf7f2e2dSJohn Marino 
209cf7f2e2dSJohn Marino void
210cf7f2e2dSJohn Marino set_current_program_space (struct program_space *pspace)
211cf7f2e2dSJohn Marino {
212cf7f2e2dSJohn Marino   if (current_program_space == pspace)
213cf7f2e2dSJohn Marino     return;
214cf7f2e2dSJohn Marino 
215cf7f2e2dSJohn Marino   gdb_assert (pspace != NULL);
216cf7f2e2dSJohn Marino 
217cf7f2e2dSJohn Marino   current_program_space = pspace;
218cf7f2e2dSJohn Marino 
219cf7f2e2dSJohn Marino   /* Different symbols change our view of the frame chain.  */
220cf7f2e2dSJohn Marino   reinit_frame_cache ();
221cf7f2e2dSJohn Marino }
222cf7f2e2dSJohn Marino 
223cf7f2e2dSJohn Marino /* A cleanups callback, helper for save_current_program_space
224cf7f2e2dSJohn Marino    below.  */
225cf7f2e2dSJohn Marino 
226cf7f2e2dSJohn Marino static void
227cf7f2e2dSJohn Marino restore_program_space (void *arg)
228cf7f2e2dSJohn Marino {
229cf7f2e2dSJohn Marino   struct program_space *saved_pspace = arg;
230cf7f2e2dSJohn Marino 
231cf7f2e2dSJohn Marino   set_current_program_space (saved_pspace);
232cf7f2e2dSJohn Marino }
233cf7f2e2dSJohn Marino 
234cf7f2e2dSJohn Marino /* Save the current program space so that it may be restored by a later
235cf7f2e2dSJohn Marino    call to do_cleanups.  Returns the struct cleanup pointer needed for
236cf7f2e2dSJohn Marino    later doing the cleanup.  */
237cf7f2e2dSJohn Marino 
238cf7f2e2dSJohn Marino struct cleanup *
239cf7f2e2dSJohn Marino save_current_program_space (void)
240cf7f2e2dSJohn Marino {
241cf7f2e2dSJohn Marino   struct cleanup *old_chain = make_cleanup (restore_program_space,
242cf7f2e2dSJohn Marino 					    current_program_space);
243cf7f2e2dSJohn Marino 
244cf7f2e2dSJohn Marino   return old_chain;
245cf7f2e2dSJohn Marino }
246cf7f2e2dSJohn Marino 
247cf7f2e2dSJohn Marino /* Returns true iff there's no inferior bound to PSPACE.  */
248cf7f2e2dSJohn Marino 
249cf7f2e2dSJohn Marino static int
250cf7f2e2dSJohn Marino pspace_empty_p (struct program_space *pspace)
251cf7f2e2dSJohn Marino {
252cf7f2e2dSJohn Marino   if (find_inferior_for_program_space (pspace) != NULL)
253cf7f2e2dSJohn Marino       return 0;
254cf7f2e2dSJohn Marino 
255cf7f2e2dSJohn Marino   return 1;
256cf7f2e2dSJohn Marino }
257cf7f2e2dSJohn Marino 
258cf7f2e2dSJohn Marino /* Prune away automatically added program spaces that aren't required
259cf7f2e2dSJohn Marino    anymore.  */
260cf7f2e2dSJohn Marino 
261cf7f2e2dSJohn Marino void
262cf7f2e2dSJohn Marino prune_program_spaces (void)
263cf7f2e2dSJohn Marino {
264cf7f2e2dSJohn Marino   struct program_space *ss, **ss_link;
265cf7f2e2dSJohn Marino   struct program_space *current = current_program_space;
266cf7f2e2dSJohn Marino 
267cf7f2e2dSJohn Marino   ss = program_spaces;
268cf7f2e2dSJohn Marino   ss_link = &program_spaces;
269cf7f2e2dSJohn Marino   while (ss)
270cf7f2e2dSJohn Marino     {
271cf7f2e2dSJohn Marino       if (ss == current || !pspace_empty_p (ss))
272cf7f2e2dSJohn Marino 	{
273cf7f2e2dSJohn Marino 	  ss_link = &ss->next;
274cf7f2e2dSJohn Marino 	  ss = *ss_link;
275cf7f2e2dSJohn Marino 	  continue;
276cf7f2e2dSJohn Marino 	}
277cf7f2e2dSJohn Marino 
278cf7f2e2dSJohn Marino       *ss_link = ss->next;
279cf7f2e2dSJohn Marino       release_program_space (ss);
280cf7f2e2dSJohn Marino       ss = *ss_link;
281cf7f2e2dSJohn Marino     }
282cf7f2e2dSJohn Marino }
283cf7f2e2dSJohn Marino 
284cf7f2e2dSJohn Marino /* Prints the list of program spaces and their details on UIOUT.  If
285cf7f2e2dSJohn Marino    REQUESTED is not -1, it's the ID of the pspace that should be
286cf7f2e2dSJohn Marino    printed.  Otherwise, all spaces are printed.  */
287cf7f2e2dSJohn Marino 
288cf7f2e2dSJohn Marino static void
289cf7f2e2dSJohn Marino print_program_space (struct ui_out *uiout, int requested)
290cf7f2e2dSJohn Marino {
291cf7f2e2dSJohn Marino   struct program_space *pspace;
292cf7f2e2dSJohn Marino   int count = 0;
293cf7f2e2dSJohn Marino   struct cleanup *old_chain;
294cf7f2e2dSJohn Marino 
295cf7f2e2dSJohn Marino   /* Might as well prune away unneeded ones, so the user doesn't even
296cf7f2e2dSJohn Marino      seem them.  */
297cf7f2e2dSJohn Marino   prune_program_spaces ();
298cf7f2e2dSJohn Marino 
299cf7f2e2dSJohn Marino   /* Compute number of pspaces we will print.  */
300cf7f2e2dSJohn Marino   ALL_PSPACES (pspace)
301cf7f2e2dSJohn Marino     {
302cf7f2e2dSJohn Marino       if (requested != -1 && pspace->num != requested)
303cf7f2e2dSJohn Marino 	continue;
304cf7f2e2dSJohn Marino 
305cf7f2e2dSJohn Marino       ++count;
306cf7f2e2dSJohn Marino     }
307cf7f2e2dSJohn Marino 
308cf7f2e2dSJohn Marino   /* There should always be at least one.  */
309cf7f2e2dSJohn Marino   gdb_assert (count > 0);
310cf7f2e2dSJohn Marino 
311cf7f2e2dSJohn Marino   old_chain = make_cleanup_ui_out_table_begin_end (uiout, 3, count, "pspaces");
312cf7f2e2dSJohn Marino   ui_out_table_header (uiout, 1, ui_left, "current", "");
313cf7f2e2dSJohn Marino   ui_out_table_header (uiout, 4, ui_left, "id", "Id");
314cf7f2e2dSJohn Marino   ui_out_table_header (uiout, 17, ui_left, "exec", "Executable");
315cf7f2e2dSJohn Marino   ui_out_table_body (uiout);
316cf7f2e2dSJohn Marino 
317cf7f2e2dSJohn Marino   ALL_PSPACES (pspace)
318cf7f2e2dSJohn Marino     {
319cf7f2e2dSJohn Marino       struct cleanup *chain2;
320cf7f2e2dSJohn Marino       struct inferior *inf;
321cf7f2e2dSJohn Marino       int printed_header;
322cf7f2e2dSJohn Marino 
323cf7f2e2dSJohn Marino       if (requested != -1 && requested != pspace->num)
324cf7f2e2dSJohn Marino 	continue;
325cf7f2e2dSJohn Marino 
326cf7f2e2dSJohn Marino       chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
327cf7f2e2dSJohn Marino 
328cf7f2e2dSJohn Marino       if (pspace == current_program_space)
329cf7f2e2dSJohn Marino 	ui_out_field_string (uiout, "current", "*");
330cf7f2e2dSJohn Marino       else
331cf7f2e2dSJohn Marino 	ui_out_field_skip (uiout, "current");
332cf7f2e2dSJohn Marino 
333cf7f2e2dSJohn Marino       ui_out_field_int (uiout, "id", pspace->num);
334cf7f2e2dSJohn Marino 
335cf7f2e2dSJohn Marino       if (pspace->ebfd)
336cf7f2e2dSJohn Marino 	ui_out_field_string (uiout, "exec",
337cf7f2e2dSJohn Marino 			     bfd_get_filename (pspace->ebfd));
338cf7f2e2dSJohn Marino       else
339cf7f2e2dSJohn Marino 	ui_out_field_skip (uiout, "exec");
340cf7f2e2dSJohn Marino 
341cf7f2e2dSJohn Marino       /* Print extra info that doesn't really fit in tabular form.
342cf7f2e2dSJohn Marino 	 Currently, we print the list of inferiors bound to a pspace.
343cf7f2e2dSJohn Marino 	 There can be more than one inferior bound to the same pspace,
344cf7f2e2dSJohn Marino 	 e.g., both parent/child inferiors in a vfork, or, on targets
345cf7f2e2dSJohn Marino 	 that share pspaces between inferiors.  */
346cf7f2e2dSJohn Marino       printed_header = 0;
347cf7f2e2dSJohn Marino       for (inf = inferior_list; inf; inf = inf->next)
348cf7f2e2dSJohn Marino 	if (inf->pspace == pspace)
349cf7f2e2dSJohn Marino 	  {
350cf7f2e2dSJohn Marino 	    if (!printed_header)
351cf7f2e2dSJohn Marino 	      {
352cf7f2e2dSJohn Marino 		printed_header = 1;
353cf7f2e2dSJohn Marino 		printf_filtered ("\n\tBound inferiors: ID %d (%s)",
354cf7f2e2dSJohn Marino 				 inf->num,
355cf7f2e2dSJohn Marino 				 target_pid_to_str (pid_to_ptid (inf->pid)));
356cf7f2e2dSJohn Marino 	      }
357cf7f2e2dSJohn Marino 	    else
358cf7f2e2dSJohn Marino 	      printf_filtered (", ID %d (%s)",
359cf7f2e2dSJohn Marino 			       inf->num,
360cf7f2e2dSJohn Marino 			       target_pid_to_str (pid_to_ptid (inf->pid)));
361cf7f2e2dSJohn Marino 	  }
362cf7f2e2dSJohn Marino 
363cf7f2e2dSJohn Marino       ui_out_text (uiout, "\n");
364cf7f2e2dSJohn Marino       do_cleanups (chain2);
365cf7f2e2dSJohn Marino     }
366cf7f2e2dSJohn Marino 
367cf7f2e2dSJohn Marino   do_cleanups (old_chain);
368cf7f2e2dSJohn Marino }
369cf7f2e2dSJohn Marino 
370cf7f2e2dSJohn Marino /* Boolean test for an already-known program space id.  */
371cf7f2e2dSJohn Marino 
372cf7f2e2dSJohn Marino static int
373cf7f2e2dSJohn Marino valid_program_space_id (int num)
374cf7f2e2dSJohn Marino {
375cf7f2e2dSJohn Marino   struct program_space *pspace;
376cf7f2e2dSJohn Marino 
377cf7f2e2dSJohn Marino   ALL_PSPACES (pspace)
378cf7f2e2dSJohn Marino     if (pspace->num == num)
379cf7f2e2dSJohn Marino       return 1;
380cf7f2e2dSJohn Marino 
381cf7f2e2dSJohn Marino   return 0;
382cf7f2e2dSJohn Marino }
383cf7f2e2dSJohn Marino 
384cf7f2e2dSJohn Marino /* If ARGS is NULL or empty, print information about all program
385cf7f2e2dSJohn Marino    spaces.  Otherwise, ARGS is a text representation of a LONG
386cf7f2e2dSJohn Marino    indicating which the program space to print information about.  */
387cf7f2e2dSJohn Marino 
388cf7f2e2dSJohn Marino static void
389cf7f2e2dSJohn Marino maintenance_info_program_spaces_command (char *args, int from_tty)
390cf7f2e2dSJohn Marino {
391cf7f2e2dSJohn Marino   int requested = -1;
392cf7f2e2dSJohn Marino 
393cf7f2e2dSJohn Marino   if (args && *args)
394cf7f2e2dSJohn Marino     {
395cf7f2e2dSJohn Marino       requested = parse_and_eval_long (args);
396cf7f2e2dSJohn Marino       if (!valid_program_space_id (requested))
397cf7f2e2dSJohn Marino 	error (_("program space ID %d not known."), requested);
398cf7f2e2dSJohn Marino     }
399cf7f2e2dSJohn Marino 
400*a45ae5f8SJohn Marino   print_program_space (current_uiout, requested);
401cf7f2e2dSJohn Marino }
402cf7f2e2dSJohn Marino 
403cf7f2e2dSJohn Marino /* Simply returns the count of program spaces.  */
404cf7f2e2dSJohn Marino 
405cf7f2e2dSJohn Marino int
406cf7f2e2dSJohn Marino number_of_program_spaces (void)
407cf7f2e2dSJohn Marino {
408cf7f2e2dSJohn Marino   struct program_space *pspace;
409cf7f2e2dSJohn Marino   int count = 0;
410cf7f2e2dSJohn Marino 
411cf7f2e2dSJohn Marino   ALL_PSPACES (pspace)
412cf7f2e2dSJohn Marino     count++;
413cf7f2e2dSJohn Marino 
414cf7f2e2dSJohn Marino   return count;
415cf7f2e2dSJohn Marino }
416cf7f2e2dSJohn Marino 
417cf7f2e2dSJohn Marino /* Update all program spaces matching to address spaces.  The user may
418cf7f2e2dSJohn Marino    have created several program spaces, and loaded executables into
419cf7f2e2dSJohn Marino    them before connecting to the target interface that will create the
420cf7f2e2dSJohn Marino    inferiors.  All that happens before GDB has a chance to know if the
421cf7f2e2dSJohn Marino    inferiors will share an address space or not.  Call this after
422cf7f2e2dSJohn Marino    having connected to the target interface and having fetched the
423cf7f2e2dSJohn Marino    target description, to fixup the program/address spaces mappings.
424cf7f2e2dSJohn Marino 
425cf7f2e2dSJohn Marino    It is assumed that there are no bound inferiors yet, otherwise,
426cf7f2e2dSJohn Marino    they'd be left with stale referenced to released aspaces.  */
427cf7f2e2dSJohn Marino 
428cf7f2e2dSJohn Marino void
429cf7f2e2dSJohn Marino update_address_spaces (void)
430cf7f2e2dSJohn Marino {
431cf7f2e2dSJohn Marino   int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch);
432cf7f2e2dSJohn Marino   struct program_space *pspace;
433cf7f2e2dSJohn Marino   struct inferior *inf;
434cf7f2e2dSJohn Marino 
435cf7f2e2dSJohn Marino   init_address_spaces ();
436cf7f2e2dSJohn Marino 
437cf7f2e2dSJohn Marino   if (shared_aspace)
438cf7f2e2dSJohn Marino     {
439cf7f2e2dSJohn Marino       struct address_space *aspace = new_address_space ();
440cf7f2e2dSJohn Marino 
441cf7f2e2dSJohn Marino       free_address_space (current_program_space->aspace);
442cf7f2e2dSJohn Marino       ALL_PSPACES (pspace)
443cf7f2e2dSJohn Marino 	pspace->aspace = aspace;
444cf7f2e2dSJohn Marino     }
445cf7f2e2dSJohn Marino   else
446cf7f2e2dSJohn Marino     ALL_PSPACES (pspace)
447cf7f2e2dSJohn Marino       {
448cf7f2e2dSJohn Marino 	free_address_space (pspace->aspace);
449cf7f2e2dSJohn Marino 	pspace->aspace = new_address_space ();
450cf7f2e2dSJohn Marino       }
451cf7f2e2dSJohn Marino 
452cf7f2e2dSJohn Marino   for (inf = inferior_list; inf; inf = inf->next)
453cf7f2e2dSJohn Marino     if (gdbarch_has_global_solist (target_gdbarch))
454cf7f2e2dSJohn Marino       inf->aspace = maybe_new_address_space ();
455cf7f2e2dSJohn Marino     else
456cf7f2e2dSJohn Marino       inf->aspace = inf->pspace->aspace;
457cf7f2e2dSJohn Marino }
458cf7f2e2dSJohn Marino 
459cf7f2e2dSJohn Marino /* Save the current program space so that it may be restored by a later
460cf7f2e2dSJohn Marino    call to do_cleanups.  Returns the struct cleanup pointer needed for
461cf7f2e2dSJohn Marino    later doing the cleanup.  */
462cf7f2e2dSJohn Marino 
463cf7f2e2dSJohn Marino struct cleanup *
464cf7f2e2dSJohn Marino save_current_space_and_thread (void)
465cf7f2e2dSJohn Marino {
466cf7f2e2dSJohn Marino   struct cleanup *old_chain;
467cf7f2e2dSJohn Marino 
468cf7f2e2dSJohn Marino   /* If restoring to null thread, we need to restore the pspace as
469cf7f2e2dSJohn Marino      well, hence, we need to save the current program space first.  */
470cf7f2e2dSJohn Marino   old_chain = save_current_program_space ();
471cf7f2e2dSJohn Marino   save_current_inferior ();
472cf7f2e2dSJohn Marino   make_cleanup_restore_current_thread ();
473cf7f2e2dSJohn Marino 
474cf7f2e2dSJohn Marino   return old_chain;
475cf7f2e2dSJohn Marino }
476cf7f2e2dSJohn Marino 
477cf7f2e2dSJohn Marino /* Switches full context to program space PSPACE.  Switches to the
478cf7f2e2dSJohn Marino    first thread found bound to PSPACE.  */
479cf7f2e2dSJohn Marino 
480cf7f2e2dSJohn Marino void
481cf7f2e2dSJohn Marino switch_to_program_space_and_thread (struct program_space *pspace)
482cf7f2e2dSJohn Marino {
483cf7f2e2dSJohn Marino   struct inferior *inf;
484cf7f2e2dSJohn Marino 
485cf7f2e2dSJohn Marino   inf = find_inferior_for_program_space (pspace);
486cf7f2e2dSJohn Marino   if (inf != NULL)
487cf7f2e2dSJohn Marino     {
488cf7f2e2dSJohn Marino       struct thread_info *tp;
489cf7f2e2dSJohn Marino 
490cf7f2e2dSJohn Marino       tp = any_live_thread_of_process (inf->pid);
491cf7f2e2dSJohn Marino       if (tp != NULL)
492cf7f2e2dSJohn Marino 	{
493cf7f2e2dSJohn Marino 	  switch_to_thread (tp->ptid);
494cf7f2e2dSJohn Marino 	  /* Switching thread switches pspace implicitly.  We're
495cf7f2e2dSJohn Marino 	     done.  */
496cf7f2e2dSJohn Marino 	  return;
497cf7f2e2dSJohn Marino 	}
498cf7f2e2dSJohn Marino     }
499cf7f2e2dSJohn Marino 
500cf7f2e2dSJohn Marino   switch_to_thread (null_ptid);
501cf7f2e2dSJohn Marino   set_current_program_space (pspace);
502cf7f2e2dSJohn Marino }
503cf7f2e2dSJohn Marino 
504cf7f2e2dSJohn Marino 
505cf7f2e2dSJohn Marino 
506cf7f2e2dSJohn Marino /* Keep a registry of per-program_space data-pointers required by other GDB
507cf7f2e2dSJohn Marino    modules.  */
508cf7f2e2dSJohn Marino 
509cf7f2e2dSJohn Marino struct program_space_data
510cf7f2e2dSJohn Marino {
511cf7f2e2dSJohn Marino   unsigned index;
512cf7f2e2dSJohn Marino   void (*cleanup) (struct program_space *, void *);
513cf7f2e2dSJohn Marino };
514cf7f2e2dSJohn Marino 
515cf7f2e2dSJohn Marino struct program_space_data_registration
516cf7f2e2dSJohn Marino {
517cf7f2e2dSJohn Marino   struct program_space_data *data;
518cf7f2e2dSJohn Marino   struct program_space_data_registration *next;
519cf7f2e2dSJohn Marino };
520cf7f2e2dSJohn Marino 
521cf7f2e2dSJohn Marino struct program_space_data_registry
522cf7f2e2dSJohn Marino {
523cf7f2e2dSJohn Marino   struct program_space_data_registration *registrations;
524cf7f2e2dSJohn Marino   unsigned num_registrations;
525cf7f2e2dSJohn Marino };
526cf7f2e2dSJohn Marino 
527cf7f2e2dSJohn Marino static struct program_space_data_registry program_space_data_registry
528cf7f2e2dSJohn Marino   = { NULL, 0 };
529cf7f2e2dSJohn Marino 
530cf7f2e2dSJohn Marino const struct program_space_data *
531cf7f2e2dSJohn Marino register_program_space_data_with_cleanup
532cf7f2e2dSJohn Marino   (void (*cleanup) (struct program_space *, void *))
533cf7f2e2dSJohn Marino {
534cf7f2e2dSJohn Marino   struct program_space_data_registration **curr;
535cf7f2e2dSJohn Marino 
536cf7f2e2dSJohn Marino   /* Append new registration.  */
537cf7f2e2dSJohn Marino   for (curr = &program_space_data_registry.registrations;
538cf7f2e2dSJohn Marino        *curr != NULL; curr = &(*curr)->next);
539cf7f2e2dSJohn Marino 
540cf7f2e2dSJohn Marino   *curr = XMALLOC (struct program_space_data_registration);
541cf7f2e2dSJohn Marino   (*curr)->next = NULL;
542cf7f2e2dSJohn Marino   (*curr)->data = XMALLOC (struct program_space_data);
543cf7f2e2dSJohn Marino   (*curr)->data->index = program_space_data_registry.num_registrations++;
544cf7f2e2dSJohn Marino   (*curr)->data->cleanup = cleanup;
545cf7f2e2dSJohn Marino 
546cf7f2e2dSJohn Marino   return (*curr)->data;
547cf7f2e2dSJohn Marino }
548cf7f2e2dSJohn Marino 
549cf7f2e2dSJohn Marino const struct program_space_data *
550cf7f2e2dSJohn Marino register_program_space_data (void)
551cf7f2e2dSJohn Marino {
552cf7f2e2dSJohn Marino   return register_program_space_data_with_cleanup (NULL);
553cf7f2e2dSJohn Marino }
554cf7f2e2dSJohn Marino 
555cf7f2e2dSJohn Marino static void
556cf7f2e2dSJohn Marino program_space_alloc_data (struct program_space *pspace)
557cf7f2e2dSJohn Marino {
558cf7f2e2dSJohn Marino   gdb_assert (pspace->data == NULL);
559cf7f2e2dSJohn Marino   pspace->num_data = program_space_data_registry.num_registrations;
560cf7f2e2dSJohn Marino   pspace->data = XCALLOC (pspace->num_data, void *);
561cf7f2e2dSJohn Marino }
562cf7f2e2dSJohn Marino 
563cf7f2e2dSJohn Marino static void
564cf7f2e2dSJohn Marino program_space_free_data (struct program_space *pspace)
565cf7f2e2dSJohn Marino {
566cf7f2e2dSJohn Marino   gdb_assert (pspace->data != NULL);
567cf7f2e2dSJohn Marino   clear_program_space_data (pspace);
568cf7f2e2dSJohn Marino   xfree (pspace->data);
569cf7f2e2dSJohn Marino   pspace->data = NULL;
570cf7f2e2dSJohn Marino }
571cf7f2e2dSJohn Marino 
572cf7f2e2dSJohn Marino void
573cf7f2e2dSJohn Marino clear_program_space_data (struct program_space *pspace)
574cf7f2e2dSJohn Marino {
575cf7f2e2dSJohn Marino   struct program_space_data_registration *registration;
576cf7f2e2dSJohn Marino   int i;
577cf7f2e2dSJohn Marino 
578cf7f2e2dSJohn Marino   gdb_assert (pspace->data != NULL);
579cf7f2e2dSJohn Marino 
580cf7f2e2dSJohn Marino   for (registration = program_space_data_registry.registrations, i = 0;
581cf7f2e2dSJohn Marino        i < pspace->num_data;
582cf7f2e2dSJohn Marino        registration = registration->next, i++)
583cf7f2e2dSJohn Marino     if (pspace->data[i] != NULL && registration->data->cleanup)
584cf7f2e2dSJohn Marino       registration->data->cleanup (pspace, pspace->data[i]);
585cf7f2e2dSJohn Marino 
586cf7f2e2dSJohn Marino   memset (pspace->data, 0, pspace->num_data * sizeof (void *));
587cf7f2e2dSJohn Marino }
588cf7f2e2dSJohn Marino 
589cf7f2e2dSJohn Marino void
590cf7f2e2dSJohn Marino set_program_space_data (struct program_space *pspace,
591cf7f2e2dSJohn Marino 		       const struct program_space_data *data,
592cf7f2e2dSJohn Marino 		       void *value)
593cf7f2e2dSJohn Marino {
594cf7f2e2dSJohn Marino   gdb_assert (data->index < pspace->num_data);
595cf7f2e2dSJohn Marino   pspace->data[data->index] = value;
596cf7f2e2dSJohn Marino }
597cf7f2e2dSJohn Marino 
598cf7f2e2dSJohn Marino void *
599c50c785cSJohn Marino program_space_data (struct program_space *pspace,
600c50c785cSJohn Marino 		    const struct program_space_data *data)
601cf7f2e2dSJohn Marino {
602cf7f2e2dSJohn Marino   gdb_assert (data->index < pspace->num_data);
603cf7f2e2dSJohn Marino   return pspace->data[data->index];
604cf7f2e2dSJohn Marino }
605cf7f2e2dSJohn Marino 
606cf7f2e2dSJohn Marino 
607cf7f2e2dSJohn Marino 
608cf7f2e2dSJohn Marino void
609cf7f2e2dSJohn Marino initialize_progspace (void)
610cf7f2e2dSJohn Marino {
611cf7f2e2dSJohn Marino   add_cmd ("program-spaces", class_maintenance,
612c50c785cSJohn Marino 	   maintenance_info_program_spaces_command,
613c50c785cSJohn Marino 	   _("Info about currently known program spaces."),
614cf7f2e2dSJohn Marino 	   &maintenanceinfolist);
615cf7f2e2dSJohn Marino 
616cf7f2e2dSJohn Marino   /* There's always one program space.  Note that this function isn't
617cf7f2e2dSJohn Marino      an automatic _initialize_foo function, since other
618cf7f2e2dSJohn Marino      _initialize_foo routines may need to install their per-pspace
619cf7f2e2dSJohn Marino      data keys.  We can only allocate a progspace when all those
620cf7f2e2dSJohn Marino      modules have done that.  Do this before
621cf7f2e2dSJohn Marino      initialize_current_architecture, because that accesses exec_bfd,
622cf7f2e2dSJohn Marino      which in turn dereferences current_program_space.  */
623cf7f2e2dSJohn Marino   current_program_space = add_program_space (new_address_space ());
624cf7f2e2dSJohn Marino }
625