xref: /dragonfly/contrib/gdb-7/gdb/solib-target.c (revision ef5ccd6c)
1cf7f2e2dSJohn Marino /* Definitions for targets which report shared library events.
2cf7f2e2dSJohn Marino 
3*ef5ccd6cSJohn Marino    Copyright (C) 2007-2013 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 "objfiles.h"
22cf7f2e2dSJohn Marino #include "solist.h"
23cf7f2e2dSJohn Marino #include "symtab.h"
24cf7f2e2dSJohn Marino #include "symfile.h"
25cf7f2e2dSJohn Marino #include "target.h"
26cf7f2e2dSJohn Marino #include "vec.h"
27cf7f2e2dSJohn Marino #include "solib-target.h"
28cf7f2e2dSJohn Marino 
29cf7f2e2dSJohn Marino #include "gdb_string.h"
30cf7f2e2dSJohn Marino 
31cf7f2e2dSJohn Marino /* Private data for each loaded library.  */
32cf7f2e2dSJohn Marino struct lm_info
33cf7f2e2dSJohn Marino {
34cf7f2e2dSJohn Marino   /* The library's name.  The name is normally kept in the struct
35cf7f2e2dSJohn Marino      so_list; it is only here during XML parsing.  */
36cf7f2e2dSJohn Marino   char *name;
37cf7f2e2dSJohn Marino 
38cf7f2e2dSJohn Marino   /* The target can either specify segment bases or section bases, not
39cf7f2e2dSJohn Marino      both.  */
40cf7f2e2dSJohn Marino 
41cf7f2e2dSJohn Marino   /* The base addresses for each independently relocatable segment of
42cf7f2e2dSJohn Marino      this shared library.  */
43cf7f2e2dSJohn Marino   VEC(CORE_ADDR) *segment_bases;
44cf7f2e2dSJohn Marino 
45cf7f2e2dSJohn Marino   /* The base addresses for each independently allocatable,
46cf7f2e2dSJohn Marino      relocatable section of this shared library.  */
47cf7f2e2dSJohn Marino   VEC(CORE_ADDR) *section_bases;
48cf7f2e2dSJohn Marino 
49cf7f2e2dSJohn Marino   /* The cached offsets for each section of this shared library,
50cf7f2e2dSJohn Marino      determined from SEGMENT_BASES, or SECTION_BASES.  */
51cf7f2e2dSJohn Marino   struct section_offsets *offsets;
52cf7f2e2dSJohn Marino };
53cf7f2e2dSJohn Marino 
54cf7f2e2dSJohn Marino typedef struct lm_info *lm_info_p;
55cf7f2e2dSJohn Marino DEF_VEC_P(lm_info_p);
56cf7f2e2dSJohn Marino 
57cf7f2e2dSJohn Marino #if !defined(HAVE_LIBEXPAT)
58cf7f2e2dSJohn Marino 
VEC(lm_info_p)59cf7f2e2dSJohn Marino static VEC(lm_info_p) *
60cf7f2e2dSJohn Marino solib_target_parse_libraries (const char *library)
61cf7f2e2dSJohn Marino {
62cf7f2e2dSJohn Marino   static int have_warned;
63cf7f2e2dSJohn Marino 
64cf7f2e2dSJohn Marino   if (!have_warned)
65cf7f2e2dSJohn Marino     {
66cf7f2e2dSJohn Marino       have_warned = 1;
67cf7f2e2dSJohn Marino       warning (_("Can not parse XML library list; XML support was disabled "
68cf7f2e2dSJohn Marino 		 "at compile time"));
69cf7f2e2dSJohn Marino     }
70cf7f2e2dSJohn Marino 
71cf7f2e2dSJohn Marino   return NULL;
72cf7f2e2dSJohn Marino }
73cf7f2e2dSJohn Marino 
74cf7f2e2dSJohn Marino #else /* HAVE_LIBEXPAT */
75cf7f2e2dSJohn Marino 
76cf7f2e2dSJohn Marino #include "xml-support.h"
77cf7f2e2dSJohn Marino 
78cf7f2e2dSJohn Marino /* Handle the start of a <segment> element.  */
79cf7f2e2dSJohn Marino 
80cf7f2e2dSJohn Marino static void
library_list_start_segment(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)81cf7f2e2dSJohn Marino library_list_start_segment (struct gdb_xml_parser *parser,
82cf7f2e2dSJohn Marino 			    const struct gdb_xml_element *element,
83cf7f2e2dSJohn Marino 			    void *user_data, VEC(gdb_xml_value_s) *attributes)
84cf7f2e2dSJohn Marino {
85cf7f2e2dSJohn Marino   VEC(lm_info_p) **list = user_data;
86cf7f2e2dSJohn Marino   struct lm_info *last = VEC_last (lm_info_p, *list);
87a45ae5f8SJohn Marino   ULONGEST *address_p = xml_find_attribute (attributes, "address")->value;
88cf7f2e2dSJohn Marino   CORE_ADDR address = (CORE_ADDR) *address_p;
89cf7f2e2dSJohn Marino 
90cf7f2e2dSJohn Marino   if (last->section_bases != NULL)
91cf7f2e2dSJohn Marino     gdb_xml_error (parser,
92cf7f2e2dSJohn Marino 		   _("Library list with both segments and sections"));
93cf7f2e2dSJohn Marino 
94a45ae5f8SJohn Marino   VEC_safe_push (CORE_ADDR, last->segment_bases, address);
95cf7f2e2dSJohn Marino }
96cf7f2e2dSJohn Marino 
97cf7f2e2dSJohn Marino static void
library_list_start_section(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)98cf7f2e2dSJohn Marino library_list_start_section (struct gdb_xml_parser *parser,
99cf7f2e2dSJohn Marino 			    const struct gdb_xml_element *element,
100cf7f2e2dSJohn Marino 			    void *user_data, VEC(gdb_xml_value_s) *attributes)
101cf7f2e2dSJohn Marino {
102cf7f2e2dSJohn Marino   VEC(lm_info_p) **list = user_data;
103cf7f2e2dSJohn Marino   struct lm_info *last = VEC_last (lm_info_p, *list);
104a45ae5f8SJohn Marino   ULONGEST *address_p = xml_find_attribute (attributes, "address")->value;
105cf7f2e2dSJohn Marino   CORE_ADDR address = (CORE_ADDR) *address_p;
106cf7f2e2dSJohn Marino 
107cf7f2e2dSJohn Marino   if (last->segment_bases != NULL)
108cf7f2e2dSJohn Marino     gdb_xml_error (parser,
109cf7f2e2dSJohn Marino 		   _("Library list with both segments and sections"));
110cf7f2e2dSJohn Marino 
111a45ae5f8SJohn Marino   VEC_safe_push (CORE_ADDR, last->section_bases, address);
112cf7f2e2dSJohn Marino }
113cf7f2e2dSJohn Marino 
114cf7f2e2dSJohn Marino /* Handle the start of a <library> element.  */
115cf7f2e2dSJohn Marino 
116cf7f2e2dSJohn Marino static void
library_list_start_library(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)117cf7f2e2dSJohn Marino library_list_start_library (struct gdb_xml_parser *parser,
118cf7f2e2dSJohn Marino 			    const struct gdb_xml_element *element,
119cf7f2e2dSJohn Marino 			    void *user_data, VEC(gdb_xml_value_s) *attributes)
120cf7f2e2dSJohn Marino {
121cf7f2e2dSJohn Marino   VEC(lm_info_p) **list = user_data;
122cf7f2e2dSJohn Marino   struct lm_info *item = XZALLOC (struct lm_info);
123a45ae5f8SJohn Marino   const char *name = xml_find_attribute (attributes, "name")->value;
124cf7f2e2dSJohn Marino 
125cf7f2e2dSJohn Marino   item->name = xstrdup (name);
126cf7f2e2dSJohn Marino   VEC_safe_push (lm_info_p, *list, item);
127cf7f2e2dSJohn Marino }
128cf7f2e2dSJohn Marino 
129cf7f2e2dSJohn Marino static void
library_list_end_library(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,const char * body_text)130cf7f2e2dSJohn Marino library_list_end_library (struct gdb_xml_parser *parser,
131cf7f2e2dSJohn Marino 			  const struct gdb_xml_element *element,
132cf7f2e2dSJohn Marino 			  void *user_data, const char *body_text)
133cf7f2e2dSJohn Marino {
134cf7f2e2dSJohn Marino   VEC(lm_info_p) **list = user_data;
135cf7f2e2dSJohn Marino   struct lm_info *lm_info = VEC_last (lm_info_p, *list);
136cf7f2e2dSJohn Marino 
137cf7f2e2dSJohn Marino   if (lm_info->segment_bases == NULL
138cf7f2e2dSJohn Marino       && lm_info->section_bases == NULL)
139cf7f2e2dSJohn Marino     gdb_xml_error (parser,
140cf7f2e2dSJohn Marino 		   _("No segment or section bases defined"));
141cf7f2e2dSJohn Marino }
142cf7f2e2dSJohn Marino 
143cf7f2e2dSJohn Marino 
144cf7f2e2dSJohn Marino /* Handle the start of a <library-list> element.  */
145cf7f2e2dSJohn Marino 
146cf7f2e2dSJohn Marino static void
library_list_start_list(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)147cf7f2e2dSJohn Marino library_list_start_list (struct gdb_xml_parser *parser,
148cf7f2e2dSJohn Marino 			 const struct gdb_xml_element *element,
149cf7f2e2dSJohn Marino 			 void *user_data, VEC(gdb_xml_value_s) *attributes)
150cf7f2e2dSJohn Marino {
151a45ae5f8SJohn Marino   char *version = xml_find_attribute (attributes, "version")->value;
152cf7f2e2dSJohn Marino 
153cf7f2e2dSJohn Marino   if (strcmp (version, "1.0") != 0)
154cf7f2e2dSJohn Marino     gdb_xml_error (parser,
155cf7f2e2dSJohn Marino 		   _("Library list has unsupported version \"%s\""),
156cf7f2e2dSJohn Marino 		   version);
157cf7f2e2dSJohn Marino }
158cf7f2e2dSJohn Marino 
159cf7f2e2dSJohn Marino /* Discard the constructed library list.  */
160cf7f2e2dSJohn Marino 
161cf7f2e2dSJohn Marino static void
solib_target_free_library_list(void * p)162cf7f2e2dSJohn Marino solib_target_free_library_list (void *p)
163cf7f2e2dSJohn Marino {
164cf7f2e2dSJohn Marino   VEC(lm_info_p) **result = p;
165cf7f2e2dSJohn Marino   struct lm_info *info;
166cf7f2e2dSJohn Marino   int ix;
167cf7f2e2dSJohn Marino 
168cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
169cf7f2e2dSJohn Marino     {
170cf7f2e2dSJohn Marino       xfree (info->name);
171cf7f2e2dSJohn Marino       VEC_free (CORE_ADDR, info->segment_bases);
172cf7f2e2dSJohn Marino       VEC_free (CORE_ADDR, info->section_bases);
173cf7f2e2dSJohn Marino       xfree (info);
174cf7f2e2dSJohn Marino     }
175cf7f2e2dSJohn Marino   VEC_free (lm_info_p, *result);
176cf7f2e2dSJohn Marino   *result = NULL;
177cf7f2e2dSJohn Marino }
178cf7f2e2dSJohn Marino 
179cf7f2e2dSJohn Marino /* The allowed elements and attributes for an XML library list.
180cf7f2e2dSJohn Marino    The root element is a <library-list>.  */
181cf7f2e2dSJohn Marino 
182a45ae5f8SJohn Marino static const struct gdb_xml_attribute segment_attributes[] = {
183cf7f2e2dSJohn Marino   { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
184cf7f2e2dSJohn Marino   { NULL, GDB_XML_AF_NONE, NULL, NULL }
185cf7f2e2dSJohn Marino };
186cf7f2e2dSJohn Marino 
187a45ae5f8SJohn Marino static const struct gdb_xml_attribute section_attributes[] = {
188cf7f2e2dSJohn Marino   { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
189cf7f2e2dSJohn Marino   { NULL, GDB_XML_AF_NONE, NULL, NULL }
190cf7f2e2dSJohn Marino };
191cf7f2e2dSJohn Marino 
192a45ae5f8SJohn Marino static const struct gdb_xml_element library_children[] = {
193cf7f2e2dSJohn Marino   { "segment", segment_attributes, NULL,
194cf7f2e2dSJohn Marino     GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
195cf7f2e2dSJohn Marino     library_list_start_segment, NULL },
196cf7f2e2dSJohn Marino   { "section", section_attributes, NULL,
197cf7f2e2dSJohn Marino     GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
198cf7f2e2dSJohn Marino     library_list_start_section, NULL },
199cf7f2e2dSJohn Marino   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
200cf7f2e2dSJohn Marino };
201cf7f2e2dSJohn Marino 
202a45ae5f8SJohn Marino static const struct gdb_xml_attribute library_attributes[] = {
203cf7f2e2dSJohn Marino   { "name", GDB_XML_AF_NONE, NULL, NULL },
204cf7f2e2dSJohn Marino   { NULL, GDB_XML_AF_NONE, NULL, NULL }
205cf7f2e2dSJohn Marino };
206cf7f2e2dSJohn Marino 
207a45ae5f8SJohn Marino static const struct gdb_xml_element library_list_children[] = {
208cf7f2e2dSJohn Marino   { "library", library_attributes, library_children,
209cf7f2e2dSJohn Marino     GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
210cf7f2e2dSJohn Marino     library_list_start_library, library_list_end_library },
211cf7f2e2dSJohn Marino   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
212cf7f2e2dSJohn Marino };
213cf7f2e2dSJohn Marino 
214a45ae5f8SJohn Marino static const struct gdb_xml_attribute library_list_attributes[] = {
215cf7f2e2dSJohn Marino   { "version", GDB_XML_AF_NONE, NULL, NULL },
216cf7f2e2dSJohn Marino   { NULL, GDB_XML_AF_NONE, NULL, NULL }
217cf7f2e2dSJohn Marino };
218cf7f2e2dSJohn Marino 
219a45ae5f8SJohn Marino static const struct gdb_xml_element library_list_elements[] = {
220cf7f2e2dSJohn Marino   { "library-list", library_list_attributes, library_list_children,
221cf7f2e2dSJohn Marino     GDB_XML_EF_NONE, library_list_start_list, NULL },
222cf7f2e2dSJohn Marino   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
223cf7f2e2dSJohn Marino };
224cf7f2e2dSJohn Marino 
VEC(lm_info_p)225cf7f2e2dSJohn Marino static VEC(lm_info_p) *
226cf7f2e2dSJohn Marino solib_target_parse_libraries (const char *library)
227cf7f2e2dSJohn Marino {
228cf7f2e2dSJohn Marino   VEC(lm_info_p) *result = NULL;
229a45ae5f8SJohn Marino   struct cleanup *back_to = make_cleanup (solib_target_free_library_list,
230cf7f2e2dSJohn Marino 					  &result);
231cf7f2e2dSJohn Marino 
232a45ae5f8SJohn Marino   if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd",
233a45ae5f8SJohn Marino 			   library_list_elements, library, &result) == 0)
234a45ae5f8SJohn Marino     {
235a45ae5f8SJohn Marino       /* Parsed successfully, keep the result.  */
236a45ae5f8SJohn Marino       discard_cleanups (back_to);
237a45ae5f8SJohn Marino       return result;
238a45ae5f8SJohn Marino     }
239cf7f2e2dSJohn Marino 
240cf7f2e2dSJohn Marino   do_cleanups (back_to);
241a45ae5f8SJohn Marino   return NULL;
242cf7f2e2dSJohn Marino }
243cf7f2e2dSJohn Marino #endif
244cf7f2e2dSJohn Marino 
245cf7f2e2dSJohn Marino static struct so_list *
solib_target_current_sos(void)246cf7f2e2dSJohn Marino solib_target_current_sos (void)
247cf7f2e2dSJohn Marino {
248cf7f2e2dSJohn Marino   struct so_list *new_solib, *start = NULL, *last = NULL;
249*ef5ccd6cSJohn Marino   char *library_document;
250*ef5ccd6cSJohn Marino   struct cleanup *old_chain;
251cf7f2e2dSJohn Marino   VEC(lm_info_p) *library_list;
252cf7f2e2dSJohn Marino   struct lm_info *info;
253cf7f2e2dSJohn Marino   int ix;
254cf7f2e2dSJohn Marino 
255cf7f2e2dSJohn Marino   /* Fetch the list of shared libraries.  */
256cf7f2e2dSJohn Marino   library_document = target_read_stralloc (&current_target,
257cf7f2e2dSJohn Marino 					   TARGET_OBJECT_LIBRARIES,
258cf7f2e2dSJohn Marino 					   NULL);
259cf7f2e2dSJohn Marino   if (library_document == NULL)
260cf7f2e2dSJohn Marino     return NULL;
261cf7f2e2dSJohn Marino 
262*ef5ccd6cSJohn Marino   /* solib_target_parse_libraries may throw, so we use a cleanup.  */
263*ef5ccd6cSJohn Marino   old_chain = make_cleanup (xfree, library_document);
264*ef5ccd6cSJohn Marino 
265cf7f2e2dSJohn Marino   /* Parse the list.  */
266cf7f2e2dSJohn Marino   library_list = solib_target_parse_libraries (library_document);
267*ef5ccd6cSJohn Marino 
268*ef5ccd6cSJohn Marino   /* library_document string is not needed behind this point.  */
269*ef5ccd6cSJohn Marino   do_cleanups (old_chain);
270*ef5ccd6cSJohn Marino 
271cf7f2e2dSJohn Marino   if (library_list == NULL)
272cf7f2e2dSJohn Marino     return NULL;
273cf7f2e2dSJohn Marino 
274cf7f2e2dSJohn Marino   /* Build a struct so_list for each entry on the list.  */
275cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
276cf7f2e2dSJohn Marino     {
277cf7f2e2dSJohn Marino       new_solib = XZALLOC (struct so_list);
278cf7f2e2dSJohn Marino       strncpy (new_solib->so_name, info->name, SO_NAME_MAX_PATH_SIZE - 1);
279cf7f2e2dSJohn Marino       new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
280cf7f2e2dSJohn Marino       strncpy (new_solib->so_original_name, info->name,
281cf7f2e2dSJohn Marino 	       SO_NAME_MAX_PATH_SIZE - 1);
282cf7f2e2dSJohn Marino       new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
283cf7f2e2dSJohn Marino       new_solib->lm_info = info;
284cf7f2e2dSJohn Marino 
285cf7f2e2dSJohn Marino       /* We no longer need this copy of the name.  */
286cf7f2e2dSJohn Marino       xfree (info->name);
287cf7f2e2dSJohn Marino       info->name = NULL;
288cf7f2e2dSJohn Marino 
289cf7f2e2dSJohn Marino       /* Add it to the list.  */
290cf7f2e2dSJohn Marino       if (!start)
291cf7f2e2dSJohn Marino 	last = start = new_solib;
292cf7f2e2dSJohn Marino       else
293cf7f2e2dSJohn Marino 	{
294cf7f2e2dSJohn Marino 	  last->next = new_solib;
295cf7f2e2dSJohn Marino 	  last = new_solib;
296cf7f2e2dSJohn Marino 	}
297cf7f2e2dSJohn Marino     }
298cf7f2e2dSJohn Marino 
299cf7f2e2dSJohn Marino   /* Free the library list, but not its members.  */
300cf7f2e2dSJohn Marino   VEC_free (lm_info_p, library_list);
301cf7f2e2dSJohn Marino 
302cf7f2e2dSJohn Marino   return start;
303cf7f2e2dSJohn Marino }
304cf7f2e2dSJohn Marino 
305cf7f2e2dSJohn Marino static void
solib_target_special_symbol_handling(void)306cf7f2e2dSJohn Marino solib_target_special_symbol_handling (void)
307cf7f2e2dSJohn Marino {
308cf7f2e2dSJohn Marino   /* Nothing needed.  */
309cf7f2e2dSJohn Marino }
310cf7f2e2dSJohn Marino 
311cf7f2e2dSJohn Marino static void
solib_target_solib_create_inferior_hook(int from_tty)312cf7f2e2dSJohn Marino solib_target_solib_create_inferior_hook (int from_tty)
313cf7f2e2dSJohn Marino {
314cf7f2e2dSJohn Marino   /* Nothing needed.  */
315cf7f2e2dSJohn Marino }
316cf7f2e2dSJohn Marino 
317cf7f2e2dSJohn Marino static void
solib_target_clear_solib(void)318cf7f2e2dSJohn Marino solib_target_clear_solib (void)
319cf7f2e2dSJohn Marino {
320cf7f2e2dSJohn Marino   /* Nothing needed.  */
321cf7f2e2dSJohn Marino }
322cf7f2e2dSJohn Marino 
323cf7f2e2dSJohn Marino static void
solib_target_free_so(struct so_list * so)324cf7f2e2dSJohn Marino solib_target_free_so (struct so_list *so)
325cf7f2e2dSJohn Marino {
326cf7f2e2dSJohn Marino   gdb_assert (so->lm_info->name == NULL);
327cf7f2e2dSJohn Marino   xfree (so->lm_info->offsets);
328cf7f2e2dSJohn Marino   VEC_free (CORE_ADDR, so->lm_info->segment_bases);
329cf7f2e2dSJohn Marino   xfree (so->lm_info);
330cf7f2e2dSJohn Marino }
331cf7f2e2dSJohn Marino 
332cf7f2e2dSJohn Marino static void
solib_target_relocate_section_addresses(struct so_list * so,struct target_section * sec)333cf7f2e2dSJohn Marino solib_target_relocate_section_addresses (struct so_list *so,
334cf7f2e2dSJohn Marino 					 struct target_section *sec)
335cf7f2e2dSJohn Marino {
336cf7f2e2dSJohn Marino   CORE_ADDR offset;
337cf7f2e2dSJohn Marino 
338cf7f2e2dSJohn Marino   /* Build the offset table only once per object file.  We can not do
339cf7f2e2dSJohn Marino      it any earlier, since we need to open the file first.  */
340cf7f2e2dSJohn Marino   if (so->lm_info->offsets == NULL)
341cf7f2e2dSJohn Marino     {
342cf7f2e2dSJohn Marino       int num_sections = bfd_count_sections (so->abfd);
343cf7f2e2dSJohn Marino 
344cf7f2e2dSJohn Marino       so->lm_info->offsets = xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections));
345cf7f2e2dSJohn Marino 
346cf7f2e2dSJohn Marino       if (so->lm_info->section_bases)
347cf7f2e2dSJohn Marino 	{
348cf7f2e2dSJohn Marino 	  int i;
349cf7f2e2dSJohn Marino 	  asection *sect;
350cf7f2e2dSJohn Marino 	  int num_section_bases
351cf7f2e2dSJohn Marino 	    = VEC_length (CORE_ADDR, so->lm_info->section_bases);
352cf7f2e2dSJohn Marino 	  int num_alloc_sections = 0;
353cf7f2e2dSJohn Marino 
354cf7f2e2dSJohn Marino 	  for (i = 0, sect = so->abfd->sections;
355cf7f2e2dSJohn Marino 	       sect != NULL;
356cf7f2e2dSJohn Marino 	       i++, sect = sect->next)
357cf7f2e2dSJohn Marino 	    if ((bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
358cf7f2e2dSJohn Marino 	      num_alloc_sections++;
359cf7f2e2dSJohn Marino 
360cf7f2e2dSJohn Marino 	  if (num_alloc_sections != num_section_bases)
361cf7f2e2dSJohn Marino 	    warning (_("\
362cf7f2e2dSJohn Marino Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
363cf7f2e2dSJohn Marino 		     so->so_name);
364cf7f2e2dSJohn Marino 	  else
365cf7f2e2dSJohn Marino 	    {
366cf7f2e2dSJohn Marino 	      int bases_index = 0;
367cf7f2e2dSJohn Marino 	      int found_range = 0;
368cf7f2e2dSJohn Marino 	      CORE_ADDR *section_bases;
369cf7f2e2dSJohn Marino 
370cf7f2e2dSJohn Marino 	      section_bases = VEC_address (CORE_ADDR,
371cf7f2e2dSJohn Marino 					   so->lm_info->section_bases);
372cf7f2e2dSJohn Marino 
373cf7f2e2dSJohn Marino 	      so->addr_low = ~(CORE_ADDR) 0;
374cf7f2e2dSJohn Marino 	      so->addr_high = 0;
375cf7f2e2dSJohn Marino 	      for (i = 0, sect = so->abfd->sections;
376cf7f2e2dSJohn Marino 		   sect != NULL;
377cf7f2e2dSJohn Marino 		   i++, sect = sect->next)
378cf7f2e2dSJohn Marino 		{
379cf7f2e2dSJohn Marino 		  if (!(bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
380cf7f2e2dSJohn Marino 		    continue;
381cf7f2e2dSJohn Marino 		  if (bfd_section_size (so->abfd, sect) > 0)
382cf7f2e2dSJohn Marino 		    {
383cf7f2e2dSJohn Marino 		      CORE_ADDR low, high;
384cf7f2e2dSJohn Marino 
385cf7f2e2dSJohn Marino 		      low = section_bases[i];
386cf7f2e2dSJohn Marino 		      high = low + bfd_section_size (so->abfd, sect) - 1;
387cf7f2e2dSJohn Marino 
388cf7f2e2dSJohn Marino 		      if (low < so->addr_low)
389cf7f2e2dSJohn Marino 			so->addr_low = low;
390cf7f2e2dSJohn Marino 		      if (high > so->addr_high)
391cf7f2e2dSJohn Marino 			so->addr_high = high;
392cf7f2e2dSJohn Marino 		      gdb_assert (so->addr_low <= so->addr_high);
393cf7f2e2dSJohn Marino 		      found_range = 1;
394cf7f2e2dSJohn Marino 		    }
395a45ae5f8SJohn Marino 		  so->lm_info->offsets->offsets[i]
396a45ae5f8SJohn Marino 		    = section_bases[bases_index];
397cf7f2e2dSJohn Marino 		  bases_index++;
398cf7f2e2dSJohn Marino 		}
399cf7f2e2dSJohn Marino 	      if (!found_range)
400cf7f2e2dSJohn Marino 		so->addr_low = so->addr_high = 0;
401cf7f2e2dSJohn Marino 	      gdb_assert (so->addr_low <= so->addr_high);
402cf7f2e2dSJohn Marino 	    }
403cf7f2e2dSJohn Marino 	}
404cf7f2e2dSJohn Marino       else if (so->lm_info->segment_bases)
405cf7f2e2dSJohn Marino 	{
406cf7f2e2dSJohn Marino 	  struct symfile_segment_data *data;
407cf7f2e2dSJohn Marino 
408cf7f2e2dSJohn Marino 	  data = get_symfile_segment_data (so->abfd);
409cf7f2e2dSJohn Marino 	  if (data == NULL)
410cf7f2e2dSJohn Marino 	    warning (_("\
411cf7f2e2dSJohn Marino Could not relocate shared library \"%s\": no segments"), so->so_name);
412cf7f2e2dSJohn Marino 	  else
413cf7f2e2dSJohn Marino 	    {
414cf7f2e2dSJohn Marino 	      ULONGEST orig_delta;
415cf7f2e2dSJohn Marino 	      int i;
416cf7f2e2dSJohn Marino 	      int num_bases;
417cf7f2e2dSJohn Marino 	      CORE_ADDR *segment_bases;
418cf7f2e2dSJohn Marino 
419cf7f2e2dSJohn Marino 	      num_bases = VEC_length (CORE_ADDR, so->lm_info->segment_bases);
420cf7f2e2dSJohn Marino 	      segment_bases = VEC_address (CORE_ADDR,
421cf7f2e2dSJohn Marino 					   so->lm_info->segment_bases);
422cf7f2e2dSJohn Marino 
423cf7f2e2dSJohn Marino 	      if (!symfile_map_offsets_to_segments (so->abfd, data,
424cf7f2e2dSJohn Marino 						    so->lm_info->offsets,
425cf7f2e2dSJohn Marino 						    num_bases, segment_bases))
426cf7f2e2dSJohn Marino 		warning (_("\
427cf7f2e2dSJohn Marino Could not relocate shared library \"%s\": bad offsets"), so->so_name);
428cf7f2e2dSJohn Marino 
429cf7f2e2dSJohn Marino 	      /* Find the range of addresses to report for this library in
430cf7f2e2dSJohn Marino 		 "info sharedlibrary".  Report any consecutive segments
431cf7f2e2dSJohn Marino 		 which were relocated as a single unit.  */
432cf7f2e2dSJohn Marino 	      gdb_assert (num_bases > 0);
433cf7f2e2dSJohn Marino 	      orig_delta = segment_bases[0] - data->segment_bases[0];
434cf7f2e2dSJohn Marino 
435cf7f2e2dSJohn Marino 	      for (i = 1; i < data->num_segments; i++)
436cf7f2e2dSJohn Marino 		{
437cf7f2e2dSJohn Marino 		  /* If we have run out of offsets, assume all
438cf7f2e2dSJohn Marino 		     remaining segments have the same offset.  */
439cf7f2e2dSJohn Marino 		  if (i >= num_bases)
440cf7f2e2dSJohn Marino 		    continue;
441cf7f2e2dSJohn Marino 
442cf7f2e2dSJohn Marino 		  /* If this segment does not have the same offset, do
443cf7f2e2dSJohn Marino 		     not include it in the library's range.  */
444cf7f2e2dSJohn Marino 		  if (segment_bases[i] - data->segment_bases[i] != orig_delta)
445cf7f2e2dSJohn Marino 		    break;
446cf7f2e2dSJohn Marino 		}
447cf7f2e2dSJohn Marino 
448cf7f2e2dSJohn Marino 	      so->addr_low = segment_bases[0];
449cf7f2e2dSJohn Marino 	      so->addr_high = (data->segment_bases[i - 1]
450cf7f2e2dSJohn Marino 			       + data->segment_sizes[i - 1]
451cf7f2e2dSJohn Marino 			       + orig_delta);
452cf7f2e2dSJohn Marino 	      gdb_assert (so->addr_low <= so->addr_high);
453cf7f2e2dSJohn Marino 
454cf7f2e2dSJohn Marino 	      free_symfile_segment_data (data);
455cf7f2e2dSJohn Marino 	    }
456cf7f2e2dSJohn Marino 	}
457cf7f2e2dSJohn Marino     }
458cf7f2e2dSJohn Marino 
459cf7f2e2dSJohn Marino   offset = so->lm_info->offsets->offsets[sec->the_bfd_section->index];
460cf7f2e2dSJohn Marino   sec->addr += offset;
461cf7f2e2dSJohn Marino   sec->endaddr += offset;
462cf7f2e2dSJohn Marino }
463cf7f2e2dSJohn Marino 
464cf7f2e2dSJohn Marino static int
solib_target_open_symbol_file_object(void * from_ttyp)465cf7f2e2dSJohn Marino solib_target_open_symbol_file_object (void *from_ttyp)
466cf7f2e2dSJohn Marino {
467cf7f2e2dSJohn Marino   /* We can't locate the main symbol file based on the target's
468cf7f2e2dSJohn Marino      knowledge; the user has to specify it.  */
469cf7f2e2dSJohn Marino   return 0;
470cf7f2e2dSJohn Marino }
471cf7f2e2dSJohn Marino 
472cf7f2e2dSJohn Marino static int
solib_target_in_dynsym_resolve_code(CORE_ADDR pc)473cf7f2e2dSJohn Marino solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
474cf7f2e2dSJohn Marino {
475cf7f2e2dSJohn Marino   /* We don't have a range of addresses for the dynamic linker; there
476cf7f2e2dSJohn Marino      may not be one in the program's address space.  So only report
477cf7f2e2dSJohn Marino      PLT entries (which may be import stubs).  */
478cf7f2e2dSJohn Marino   return in_plt_section (pc, NULL);
479cf7f2e2dSJohn Marino }
480cf7f2e2dSJohn Marino 
481cf7f2e2dSJohn Marino struct target_so_ops solib_target_so_ops;
482cf7f2e2dSJohn Marino 
483a45ae5f8SJohn Marino /* -Wmissing-prototypes */
484a45ae5f8SJohn Marino extern initialize_file_ftype _initialize_solib_target;
485cf7f2e2dSJohn Marino 
486cf7f2e2dSJohn Marino void
_initialize_solib_target(void)487cf7f2e2dSJohn Marino _initialize_solib_target (void)
488cf7f2e2dSJohn Marino {
489cf7f2e2dSJohn Marino   solib_target_so_ops.relocate_section_addresses
490cf7f2e2dSJohn Marino     = solib_target_relocate_section_addresses;
491cf7f2e2dSJohn Marino   solib_target_so_ops.free_so = solib_target_free_so;
492cf7f2e2dSJohn Marino   solib_target_so_ops.clear_solib = solib_target_clear_solib;
493cf7f2e2dSJohn Marino   solib_target_so_ops.solib_create_inferior_hook
494cf7f2e2dSJohn Marino     = solib_target_solib_create_inferior_hook;
495cf7f2e2dSJohn Marino   solib_target_so_ops.special_symbol_handling
496cf7f2e2dSJohn Marino     = solib_target_special_symbol_handling;
497cf7f2e2dSJohn Marino   solib_target_so_ops.current_sos = solib_target_current_sos;
498cf7f2e2dSJohn Marino   solib_target_so_ops.open_symbol_file_object
499cf7f2e2dSJohn Marino     = solib_target_open_symbol_file_object;
500cf7f2e2dSJohn Marino   solib_target_so_ops.in_dynsym_resolve_code
501cf7f2e2dSJohn Marino     = solib_target_in_dynsym_resolve_code;
502cf7f2e2dSJohn Marino   solib_target_so_ops.bfd_open = solib_bfd_open;
503cf7f2e2dSJohn Marino 
504cf7f2e2dSJohn Marino   /* Set current_target_so_ops to solib_target_so_ops if not already
505cf7f2e2dSJohn Marino      set.  */
506cf7f2e2dSJohn Marino   if (current_target_so_ops == 0)
507cf7f2e2dSJohn Marino     current_target_so_ops = &solib_target_so_ops;
508cf7f2e2dSJohn Marino }
509