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