* arm-wince-tdep.c: Include "solib.h" and "solib-target.h".
[deliverable/binutils-gdb.git] / gdb / solib-target.c
CommitLineData
cfa9d6d9
DJ
1/* Definitions for targets which report shared library events.
2
3 Copyright (C) 2007
4 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
cfa9d6d9
DJ
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
cfa9d6d9
DJ
20
21#include "defs.h"
22#include "objfiles.h"
23#include "solist.h"
24#include "symtab.h"
25#include "symfile.h"
26#include "target.h"
27#include "vec.h"
8d465389 28#include "solib-target.h"
cfa9d6d9
DJ
29
30#include "gdb_string.h"
31
32DEF_VEC_O(CORE_ADDR);
33
34/* Private data for each loaded library. */
35struct lm_info
36{
37 /* The library's name. The name is normally kept in the struct
38 so_list; it is only here during XML parsing. */
39 char *name;
40
41 /* The base addresses for each independently relocatable segment of
42 this shared library. */
43 VEC(CORE_ADDR) *segment_bases;
44
45 /* The cached offsets for each section of this shared library,
46 determined from SEGMENT_BASES. */
47 struct section_offsets *offsets;
48};
49
50typedef struct lm_info *lm_info_p;
51DEF_VEC_P(lm_info_p);
52
53#if !defined(HAVE_LIBEXPAT)
54
899cff7a 55static VEC(lm_info_p) *
cfa9d6d9
DJ
56solib_target_parse_libraries (const char *library)
57{
58 static int have_warned;
59
60 if (!have_warned)
61 {
62 have_warned = 1;
63 warning (_("Can not parse XML library list; XML support was disabled "
64 "at compile time"));
65 }
66
67 return NULL;
68}
69
70#else /* HAVE_LIBEXPAT */
71
72#include "xml-support.h"
73
74/* Handle the start of a <segment> element. */
75
76static void
77library_list_start_segment (struct gdb_xml_parser *parser,
78 const struct gdb_xml_element *element,
79 void *user_data, VEC(gdb_xml_value_s) *attributes)
80{
81 VEC(lm_info_p) **list = user_data;
82 struct lm_info *last = VEC_last (lm_info_p, *list);
83 ULONGEST *address_p = VEC_index (gdb_xml_value_s, attributes, 0)->value;
358eb95e 84 CORE_ADDR address = (CORE_ADDR) *address_p;
cfa9d6d9 85
358eb95e 86 VEC_safe_push (CORE_ADDR, last->segment_bases, &address);
cfa9d6d9
DJ
87}
88
89/* Handle the start of a <library> element. */
90
91static void
92library_list_start_library (struct gdb_xml_parser *parser,
93 const struct gdb_xml_element *element,
94 void *user_data, VEC(gdb_xml_value_s) *attributes)
95{
96 VEC(lm_info_p) **list = user_data;
97 struct lm_info *item = XZALLOC (struct lm_info);
98 const char *name = VEC_index (gdb_xml_value_s, attributes, 0)->value;
99
100 item->name = xstrdup (name);
101 VEC_safe_push (lm_info_p, *list, item);
102}
103
104/* Handle the start of a <library-list> element. */
105
106static void
107library_list_start_list (struct gdb_xml_parser *parser,
108 const struct gdb_xml_element *element,
109 void *user_data, VEC(gdb_xml_value_s) *attributes)
110{
111 char *version = VEC_index (gdb_xml_value_s, attributes, 0)->value;
112
113 if (strcmp (version, "1.0") != 0)
114 gdb_xml_error (parser,
115 _("Library list has unsupported version \"%s\""),
116 version);
117}
118
119/* Discard the constructed library list. */
120
121static void
122solib_target_free_library_list (void *p)
123{
124 VEC(lm_info_p) **result = p;
125 struct lm_info *info;
126 int ix;
127
128 for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
129 {
130 xfree (info->name);
131 VEC_free (CORE_ADDR, info->segment_bases);
132 xfree (info);
133 }
134 VEC_free (lm_info_p, *result);
135 *result = NULL;
136}
137
138/* The allowed elements and attributes for an XML library list.
139 The root element is a <library-list>. */
140
141const struct gdb_xml_attribute segment_attributes[] = {
142 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
143 { NULL, GDB_XML_AF_NONE, NULL, NULL }
144};
145
146const struct gdb_xml_element library_children[] = {
147 { "segment", segment_attributes, NULL, GDB_XML_EF_REPEATABLE,
148 library_list_start_segment, NULL },
149 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
150};
151
152const struct gdb_xml_attribute library_attributes[] = {
153 { "name", GDB_XML_AF_NONE, NULL, NULL },
154 { NULL, GDB_XML_AF_NONE, NULL, NULL }
155};
156
157const struct gdb_xml_element library_list_children[] = {
158 { "library", library_attributes, library_children,
159 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
160 library_list_start_library, NULL },
161 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
162};
163
164const struct gdb_xml_attribute library_list_attributes[] = {
165 { "version", GDB_XML_AF_NONE, NULL, NULL },
166 { NULL, GDB_XML_AF_NONE, NULL, NULL }
167};
168
169const struct gdb_xml_element library_list_elements[] = {
170 { "library-list", library_list_attributes, library_list_children,
171 GDB_XML_EF_NONE, library_list_start_list, NULL },
172 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
173};
174
175static VEC(lm_info_p) *
176solib_target_parse_libraries (const char *library)
177{
178 struct gdb_xml_parser *parser;
179 VEC(lm_info_p) *result = NULL;
180 struct cleanup *before_deleting_result, *back_to;
181
182 back_to = make_cleanup (null_cleanup, NULL);
183 parser = gdb_xml_create_parser_and_cleanup (_("target library list"),
184 library_list_elements, &result);
185 gdb_xml_use_dtd (parser, "library-list.dtd");
186
187 before_deleting_result = make_cleanup (solib_target_free_library_list,
188 &result);
189
190 if (gdb_xml_parse (parser, library) == 0)
191 /* Parsed successfully, don't need to delete the result. */
192 discard_cleanups (before_deleting_result);
193
194 do_cleanups (back_to);
195 return result;
196}
197#endif
198
199static struct so_list *
200solib_target_current_sos (void)
201{
202 struct so_list *new_solib, *start = NULL, *last = NULL;
203 const char *library_document;
204 VEC(lm_info_p) *library_list;
205 struct lm_info *info;
206 int ix;
207
208 /* Fetch the list of shared libraries. */
209 library_document = target_read_stralloc (&current_target,
210 TARGET_OBJECT_LIBRARIES,
211 NULL);
212 if (library_document == NULL)
213 return NULL;
214
215 /* Parse the list. */
216 library_list = solib_target_parse_libraries (library_document);
217 if (library_list == NULL)
218 return NULL;
219
220 /* Build a struct so_list for each entry on the list. */
221 for (ix = 0; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
222 {
223 new_solib = XZALLOC (struct so_list);
224 strncpy (new_solib->so_name, info->name, SO_NAME_MAX_PATH_SIZE - 1);
225 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
226 strncpy (new_solib->so_original_name, info->name,
227 SO_NAME_MAX_PATH_SIZE - 1);
228 new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
229 new_solib->lm_info = info;
230
231 /* We no longer need this copy of the name. */
232 xfree (info->name);
233 info->name = NULL;
234
235 /* Add it to the list. */
236 if (!start)
237 last = start = new_solib;
238 else
239 {
240 last->next = new_solib;
241 last = new_solib;
242 }
243 }
244
245 /* Free the library list, but not its members. */
246 VEC_free (lm_info_p, library_list);
247
248 return start;
249}
250
251static void
252solib_target_special_symbol_handling (void)
253{
254 /* Nothing needed. */
255}
256
257static void
258solib_target_solib_create_inferior_hook (void)
259{
260 /* Nothing needed. */
261}
262
263static void
264solib_target_clear_solib (void)
265{
266 /* Nothing needed. */
267}
268
269static void
270solib_target_free_so (struct so_list *so)
271{
272 gdb_assert (so->lm_info->name == NULL);
273 xfree (so->lm_info->offsets);
274 VEC_free (CORE_ADDR, so->lm_info->segment_bases);
275 xfree (so->lm_info);
276}
277
278static void
279solib_target_relocate_section_addresses (struct so_list *so,
280 struct section_table *sec)
281{
282 int flags = bfd_get_section_flags (sec->bfd, sec->the_bfd_section);
283 CORE_ADDR offset;
284
285 /* Build the offset table only once per object file. We can not do
286 it any earlier, since we need to open the file first. */
287 if (so->lm_info->offsets == NULL)
288 {
289 struct symfile_segment_data *data;
290 int num_sections = bfd_count_sections (so->abfd);
291
292 so->lm_info->offsets = xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections));
293
294 data = get_symfile_segment_data (so->abfd);
295 if (data == NULL)
296 warning (_("Could not relocate shared library \"%s\": no segments"),
297 so->so_name);
298 else
299 {
300 ULONGEST orig_delta;
301 int i;
302 int num_bases = VEC_length (CORE_ADDR, so->lm_info->segment_bases);
303 CORE_ADDR *segment_bases = VEC_address (CORE_ADDR,
304 so->lm_info->segment_bases);
305
306 if (!symfile_map_offsets_to_segments (so->abfd, data,
307 so->lm_info->offsets,
308 num_bases, segment_bases))
309 warning (_("Could not relocate shared library \"%s\": bad offsets"),
310 so->so_name);
311
312 /* Find the range of addresses to report for this library in
313 "info sharedlibrary". Report any consecutive segments
314 which were relocated as a single unit. */
315 gdb_assert (num_bases > 0);
316 orig_delta = segment_bases[0] - data->segment_bases[0];
317
318 for (i = 1; i < data->num_segments; i++)
319 {
320 /* If we have run out of offsets, assume all remaining segments
321 have the same offset. */
322 if (i >= num_bases)
323 continue;
324
325 /* If this segment does not have the same offset, do not include
326 it in the library's range. */
327 if (segment_bases[i] - data->segment_bases[i] != orig_delta)
328 break;
329 }
330
331 so->addr_low = segment_bases[0];
332 so->addr_high = (data->segment_bases[i - 1]
333 + data->segment_sizes[i - 1]
5d9643ba
PA
334 + orig_delta);
335 gdb_assert (so->addr_low <= so->addr_high);
cfa9d6d9
DJ
336
337 free_symfile_segment_data (data);
338 }
339 }
340
341 offset = so->lm_info->offsets->offsets[sec->the_bfd_section->index];
342 sec->addr += offset;
343 sec->endaddr += offset;
344}
345
346static int
347solib_target_open_symbol_file_object (void *from_ttyp)
348{
349 /* We can't locate the main symbol file based on the target's
350 knowledge; the user has to specify it. */
351 return 0;
352}
353
354static int
355solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
356{
357 /* We don't have a range of addresses for the dynamic linker; there
358 may not be one in the program's address space. So only report
359 PLT entries (which may be import stubs). */
360 return in_plt_section (pc, NULL);
361}
362
8d465389 363struct target_so_ops solib_target_so_ops;
cfa9d6d9
DJ
364
365extern initialize_file_ftype _initialize_solib_target; /* -Wmissing-prototypes */
366
367void
368_initialize_solib_target (void)
369{
370 solib_target_so_ops.relocate_section_addresses
371 = solib_target_relocate_section_addresses;
372 solib_target_so_ops.free_so = solib_target_free_so;
373 solib_target_so_ops.clear_solib = solib_target_clear_solib;
374 solib_target_so_ops.solib_create_inferior_hook
375 = solib_target_solib_create_inferior_hook;
376 solib_target_so_ops.special_symbol_handling
377 = solib_target_special_symbol_handling;
378 solib_target_so_ops.current_sos = solib_target_current_sos;
379 solib_target_so_ops.open_symbol_file_object
380 = solib_target_open_symbol_file_object;
381 solib_target_so_ops.in_dynsym_resolve_code
382 = solib_target_in_dynsym_resolve_code;
cfa9d6d9 383}
This page took 0.062844 seconds and 4 git commands to generate.