2009-10-23 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / gdb / solib-target.c
CommitLineData
cfa9d6d9
DJ
1/* Definitions for targets which report shared library events.
2
0fb0cc75 3 Copyright (C) 2007, 2008, 2009 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);
138 if (lm_info->segment_bases == NULL
139 && lm_info->section_bases == NULL)
140 gdb_xml_error (parser,
141 _("No segment or section bases defined"));
142}
143
144
cfa9d6d9
DJ
145/* Handle the start of a <library-list> element. */
146
147static void
148library_list_start_list (struct gdb_xml_parser *parser,
149 const struct gdb_xml_element *element,
150 void *user_data, VEC(gdb_xml_value_s) *attributes)
151{
152 char *version = VEC_index (gdb_xml_value_s, attributes, 0)->value;
153
154 if (strcmp (version, "1.0") != 0)
155 gdb_xml_error (parser,
156 _("Library list has unsupported version \"%s\""),
157 version);
158}
159
160/* Discard the constructed library list. */
161
162static void
163solib_target_free_library_list (void *p)
164{
165 VEC(lm_info_p) **result = p;
166 struct lm_info *info;
167 int ix;
168
169 for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
170 {
171 xfree (info->name);
172 VEC_free (CORE_ADDR, info->segment_bases);
1fddbabb 173 VEC_free (CORE_ADDR, info->section_bases);
cfa9d6d9
DJ
174 xfree (info);
175 }
176 VEC_free (lm_info_p, *result);
177 *result = NULL;
178}
179
180/* The allowed elements and attributes for an XML library list.
181 The root element is a <library-list>. */
182
183const struct gdb_xml_attribute segment_attributes[] = {
184 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
185 { NULL, GDB_XML_AF_NONE, NULL, NULL }
186};
187
1fddbabb
PA
188const struct gdb_xml_attribute section_attributes[] = {
189 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
190 { NULL, GDB_XML_AF_NONE, NULL, NULL }
191};
192
cfa9d6d9 193const struct gdb_xml_element library_children[] = {
1fddbabb
PA
194 { "segment", segment_attributes, NULL,
195 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
cfa9d6d9 196 library_list_start_segment, NULL },
1fddbabb
PA
197 { "section", section_attributes, NULL,
198 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
199 library_list_start_section, NULL },
cfa9d6d9
DJ
200 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
201};
202
203const struct gdb_xml_attribute library_attributes[] = {
204 { "name", GDB_XML_AF_NONE, NULL, NULL },
205 { NULL, GDB_XML_AF_NONE, NULL, NULL }
206};
207
208const struct gdb_xml_element library_list_children[] = {
209 { "library", library_attributes, library_children,
210 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
1fddbabb 211 library_list_start_library, library_list_end_library },
cfa9d6d9
DJ
212 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
213};
214
215const struct gdb_xml_attribute library_list_attributes[] = {
216 { "version", GDB_XML_AF_NONE, NULL, NULL },
217 { NULL, GDB_XML_AF_NONE, NULL, NULL }
218};
219
220const struct gdb_xml_element library_list_elements[] = {
221 { "library-list", library_list_attributes, library_list_children,
222 GDB_XML_EF_NONE, library_list_start_list, NULL },
223 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
224};
225
226static VEC(lm_info_p) *
227solib_target_parse_libraries (const char *library)
228{
229 struct gdb_xml_parser *parser;
230 VEC(lm_info_p) *result = NULL;
231 struct cleanup *before_deleting_result, *back_to;
232
233 back_to = make_cleanup (null_cleanup, NULL);
234 parser = gdb_xml_create_parser_and_cleanup (_("target library list"),
235 library_list_elements, &result);
236 gdb_xml_use_dtd (parser, "library-list.dtd");
237
238 before_deleting_result = make_cleanup (solib_target_free_library_list,
239 &result);
240
241 if (gdb_xml_parse (parser, library) == 0)
242 /* Parsed successfully, don't need to delete the result. */
243 discard_cleanups (before_deleting_result);
244
245 do_cleanups (back_to);
246 return result;
247}
248#endif
249
250static struct so_list *
251solib_target_current_sos (void)
252{
253 struct so_list *new_solib, *start = NULL, *last = NULL;
254 const char *library_document;
255 VEC(lm_info_p) *library_list;
256 struct lm_info *info;
257 int ix;
258
259 /* Fetch the list of shared libraries. */
260 library_document = target_read_stralloc (&current_target,
261 TARGET_OBJECT_LIBRARIES,
262 NULL);
263 if (library_document == NULL)
264 return NULL;
265
266 /* Parse the list. */
267 library_list = solib_target_parse_libraries (library_document);
268 if (library_list == NULL)
269 return NULL;
270
271 /* Build a struct so_list for each entry on the list. */
272 for (ix = 0; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
273 {
274 new_solib = XZALLOC (struct so_list);
275 strncpy (new_solib->so_name, info->name, SO_NAME_MAX_PATH_SIZE - 1);
276 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
277 strncpy (new_solib->so_original_name, info->name,
278 SO_NAME_MAX_PATH_SIZE - 1);
279 new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
280 new_solib->lm_info = info;
281
282 /* We no longer need this copy of the name. */
283 xfree (info->name);
284 info->name = NULL;
285
286 /* Add it to the list. */
287 if (!start)
288 last = start = new_solib;
289 else
290 {
291 last->next = new_solib;
292 last = new_solib;
293 }
294 }
295
296 /* Free the library list, but not its members. */
297 VEC_free (lm_info_p, library_list);
298
299 return start;
300}
301
302static void
303solib_target_special_symbol_handling (void)
304{
305 /* Nothing needed. */
306}
307
308static void
309solib_target_solib_create_inferior_hook (void)
310{
311 /* Nothing needed. */
312}
313
314static void
315solib_target_clear_solib (void)
316{
317 /* Nothing needed. */
318}
319
320static void
321solib_target_free_so (struct so_list *so)
322{
323 gdb_assert (so->lm_info->name == NULL);
324 xfree (so->lm_info->offsets);
325 VEC_free (CORE_ADDR, so->lm_info->segment_bases);
326 xfree (so->lm_info);
327}
328
329static void
330solib_target_relocate_section_addresses (struct so_list *so,
0542c86d 331 struct target_section *sec)
cfa9d6d9
DJ
332{
333 int flags = bfd_get_section_flags (sec->bfd, sec->the_bfd_section);
334 CORE_ADDR offset;
335
336 /* Build the offset table only once per object file. We can not do
337 it any earlier, since we need to open the file first. */
338 if (so->lm_info->offsets == NULL)
339 {
cfa9d6d9
DJ
340 int num_sections = bfd_count_sections (so->abfd);
341
342 so->lm_info->offsets = xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections));
343
1fddbabb 344 if (so->lm_info->section_bases)
cfa9d6d9 345 {
cfa9d6d9 346 int i;
1fddbabb
PA
347 asection *sect;
348 int num_section_bases
349 = VEC_length (CORE_ADDR, so->lm_info->section_bases);
350 int num_alloc_sections = 0;
351
352 for (i = 0, sect = so->abfd->sections;
353 sect != NULL;
354 i++, sect = sect->next)
355 if ((bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
356 num_alloc_sections++;
357
358 if (num_alloc_sections != num_section_bases)
359 warning (_("\
360Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
cfa9d6d9 361 so->so_name);
1fddbabb 362 else
cfa9d6d9 363 {
1fddbabb
PA
364 int bases_index = 0;
365 int found_range = 0;
366 CORE_ADDR *section_bases;
367 section_bases = VEC_address (CORE_ADDR,
368 so->lm_info->section_bases);
369
370 so->addr_low = ~(CORE_ADDR) 0;
371 so->addr_high = 0;
372 for (i = 0, sect = so->abfd->sections;
373 sect != NULL;
374 i++, sect = sect->next)
375 {
376 if (!(bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
377 continue;
378 if (bfd_section_size (so->abfd, sect) > 0)
379 {
380 CORE_ADDR low, high;
381 low = section_bases[i];
382 high = low + bfd_section_size (so->abfd, sect) - 1;
383
384 if (low < so->addr_low)
385 so->addr_low = low;
386 if (high > so->addr_high)
387 so->addr_high = high;
388 gdb_assert (so->addr_low <= so->addr_high);
389 found_range = 1;
390 }
391 so->lm_info->offsets->offsets[i] = section_bases[bases_index];
392 bases_index++;
393 }
394 if (!found_range)
395 so->addr_low = so->addr_high = 0;
396 gdb_assert (so->addr_low <= so->addr_high);
397 }
398 }
399 else if (so->lm_info->segment_bases)
400 {
401 struct symfile_segment_data *data;
402 data = get_symfile_segment_data (so->abfd);
403 if (data == NULL)
404 warning (_("\
405Could not relocate shared library \"%s\": no segments"), so->so_name);
406 else
407 {
408 ULONGEST orig_delta;
409 int i;
410 int num_bases;
411 CORE_ADDR *segment_bases;
412
413 num_bases = VEC_length (CORE_ADDR, so->lm_info->segment_bases);
414 segment_bases = VEC_address (CORE_ADDR,
415 so->lm_info->segment_bases);
416
417 if (!symfile_map_offsets_to_segments (so->abfd, data,
418 so->lm_info->offsets,
419 num_bases, segment_bases))
420 warning (_("\
421Could not relocate shared library \"%s\": bad offsets"), so->so_name);
422
423 /* Find the range of addresses to report for this library in
424 "info sharedlibrary". Report any consecutive segments
425 which were relocated as a single unit. */
426 gdb_assert (num_bases > 0);
427 orig_delta = segment_bases[0] - data->segment_bases[0];
428
429 for (i = 1; i < data->num_segments; i++)
430 {
431 /* If we have run out of offsets, assume all
432 remaining segments have the same offset. */
433 if (i >= num_bases)
434 continue;
435
436 /* If this segment does not have the same offset, do
437 not include it in the library's range. */
438 if (segment_bases[i] - data->segment_bases[i] != orig_delta)
439 break;
440 }
441
442 so->addr_low = segment_bases[0];
443 so->addr_high = (data->segment_bases[i - 1]
444 + data->segment_sizes[i - 1]
445 + orig_delta);
446 gdb_assert (so->addr_low <= so->addr_high);
447
448 free_symfile_segment_data (data);
cfa9d6d9 449 }
cfa9d6d9
DJ
450 }
451 }
452
453 offset = so->lm_info->offsets->offsets[sec->the_bfd_section->index];
454 sec->addr += offset;
455 sec->endaddr += offset;
456}
457
458static int
459solib_target_open_symbol_file_object (void *from_ttyp)
460{
461 /* We can't locate the main symbol file based on the target's
462 knowledge; the user has to specify it. */
463 return 0;
464}
465
466static int
467solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
468{
469 /* We don't have a range of addresses for the dynamic linker; there
470 may not be one in the program's address space. So only report
471 PLT entries (which may be import stubs). */
472 return in_plt_section (pc, NULL);
473}
474
8d465389 475struct target_so_ops solib_target_so_ops;
cfa9d6d9
DJ
476
477extern initialize_file_ftype _initialize_solib_target; /* -Wmissing-prototypes */
478
479void
480_initialize_solib_target (void)
481{
482 solib_target_so_ops.relocate_section_addresses
483 = solib_target_relocate_section_addresses;
484 solib_target_so_ops.free_so = solib_target_free_so;
485 solib_target_so_ops.clear_solib = solib_target_clear_solib;
486 solib_target_so_ops.solib_create_inferior_hook
487 = solib_target_solib_create_inferior_hook;
488 solib_target_so_ops.special_symbol_handling
489 = solib_target_special_symbol_handling;
490 solib_target_so_ops.current_sos = solib_target_current_sos;
491 solib_target_so_ops.open_symbol_file_object
492 = solib_target_open_symbol_file_object;
493 solib_target_so_ops.in_dynsym_resolve_code
494 = solib_target_in_dynsym_resolve_code;
831a0c44 495 solib_target_so_ops.bfd_open = solib_bfd_open;
cfa9d6d9 496}
This page took 0.258445 seconds and 4 git commands to generate.