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