Fix reading of .debug_str_offsets{,.dwo} twice.
[deliverable/binutils-gdb.git] / gdb / solib-target.c
CommitLineData
cfa9d6d9
DJ
1/* Definitions for targets which report shared library events.
2
32d0add0 3 Copyright (C) 2007-2015 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 28
cfa9d6d9
DJ
29/* Private data for each loaded library. */
30struct lm_info
31{
32 /* The library's name. The name is normally kept in the struct
33 so_list; it is only here during XML parsing. */
34 char *name;
35
1fddbabb
PA
36 /* The target can either specify segment bases or section bases, not
37 both. */
38
cfa9d6d9
DJ
39 /* The base addresses for each independently relocatable segment of
40 this shared library. */
41 VEC(CORE_ADDR) *segment_bases;
42
1fddbabb
PA
43 /* The base addresses for each independently allocatable,
44 relocatable section of this shared library. */
45 VEC(CORE_ADDR) *section_bases;
46
cfa9d6d9 47 /* The cached offsets for each section of this shared library,
1fddbabb 48 determined from SEGMENT_BASES, or SECTION_BASES. */
cfa9d6d9
DJ
49 struct section_offsets *offsets;
50};
51
52typedef struct lm_info *lm_info_p;
53DEF_VEC_P(lm_info_p);
54
55#if !defined(HAVE_LIBEXPAT)
56
899cff7a 57static VEC(lm_info_p) *
cfa9d6d9
DJ
58solib_target_parse_libraries (const char *library)
59{
60 static int have_warned;
61
62 if (!have_warned)
63 {
64 have_warned = 1;
65 warning (_("Can not parse XML library list; XML support was disabled "
66 "at compile time"));
67 }
68
69 return NULL;
70}
71
72#else /* HAVE_LIBEXPAT */
73
74#include "xml-support.h"
75
76/* Handle the start of a <segment> element. */
77
78static void
79library_list_start_segment (struct gdb_xml_parser *parser,
80 const struct gdb_xml_element *element,
81 void *user_data, VEC(gdb_xml_value_s) *attributes)
82{
83 VEC(lm_info_p) **list = user_data;
84 struct lm_info *last = VEC_last (lm_info_p, *list);
3d2c1d41 85 ULONGEST *address_p = xml_find_attribute (attributes, "address")->value;
358eb95e 86 CORE_ADDR address = (CORE_ADDR) *address_p;
cfa9d6d9 87
1fddbabb
PA
88 if (last->section_bases != NULL)
89 gdb_xml_error (parser,
90 _("Library list with both segments and sections"));
91
267f6504 92 VEC_safe_push (CORE_ADDR, last->segment_bases, address);
cfa9d6d9
DJ
93}
94
1fddbabb
PA
95static void
96library_list_start_section (struct gdb_xml_parser *parser,
97 const struct gdb_xml_element *element,
98 void *user_data, VEC(gdb_xml_value_s) *attributes)
99{
100 VEC(lm_info_p) **list = user_data;
101 struct lm_info *last = VEC_last (lm_info_p, *list);
3d2c1d41 102 ULONGEST *address_p = xml_find_attribute (attributes, "address")->value;
1fddbabb
PA
103 CORE_ADDR address = (CORE_ADDR) *address_p;
104
105 if (last->segment_bases != NULL)
106 gdb_xml_error (parser,
107 _("Library list with both segments and sections"));
108
267f6504 109 VEC_safe_push (CORE_ADDR, last->section_bases, address);
1fddbabb
PA
110}
111
cfa9d6d9
DJ
112/* Handle the start of a <library> element. */
113
114static void
115library_list_start_library (struct gdb_xml_parser *parser,
116 const struct gdb_xml_element *element,
117 void *user_data, VEC(gdb_xml_value_s) *attributes)
118{
119 VEC(lm_info_p) **list = user_data;
41bf6aca 120 struct lm_info *item = XCNEW (struct lm_info);
3d2c1d41 121 const char *name = xml_find_attribute (attributes, "name")->value;
cfa9d6d9
DJ
122
123 item->name = xstrdup (name);
124 VEC_safe_push (lm_info_p, *list, item);
125}
126
1fddbabb
PA
127static void
128library_list_end_library (struct gdb_xml_parser *parser,
129 const struct gdb_xml_element *element,
130 void *user_data, const char *body_text)
131{
132 VEC(lm_info_p) **list = user_data;
133 struct lm_info *lm_info = VEC_last (lm_info_p, *list);
433759f7 134
1fddbabb
PA
135 if (lm_info->segment_bases == NULL
136 && lm_info->section_bases == NULL)
137 gdb_xml_error (parser,
138 _("No segment or section bases defined"));
139}
140
141
cfa9d6d9
DJ
142/* Handle the start of a <library-list> element. */
143
144static void
145library_list_start_list (struct gdb_xml_parser *parser,
146 const struct gdb_xml_element *element,
147 void *user_data, VEC(gdb_xml_value_s) *attributes)
148{
3d2c1d41 149 char *version = xml_find_attribute (attributes, "version")->value;
cfa9d6d9
DJ
150
151 if (strcmp (version, "1.0") != 0)
152 gdb_xml_error (parser,
153 _("Library list has unsupported version \"%s\""),
154 version);
155}
156
157/* Discard the constructed library list. */
158
159static void
160solib_target_free_library_list (void *p)
161{
162 VEC(lm_info_p) **result = p;
163 struct lm_info *info;
164 int ix;
165
166 for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
167 {
168 xfree (info->name);
169 VEC_free (CORE_ADDR, info->segment_bases);
1fddbabb 170 VEC_free (CORE_ADDR, info->section_bases);
cfa9d6d9
DJ
171 xfree (info);
172 }
173 VEC_free (lm_info_p, *result);
174 *result = NULL;
175}
176
177/* The allowed elements and attributes for an XML library list.
178 The root element is a <library-list>. */
179
d6c10e95 180static const struct gdb_xml_attribute segment_attributes[] = {
cfa9d6d9
DJ
181 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
182 { NULL, GDB_XML_AF_NONE, NULL, NULL }
183};
184
d6c10e95 185static const struct gdb_xml_attribute section_attributes[] = {
1fddbabb
PA
186 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
187 { NULL, GDB_XML_AF_NONE, NULL, NULL }
188};
189
d6c10e95 190static const struct gdb_xml_element library_children[] = {
1fddbabb
PA
191 { "segment", segment_attributes, NULL,
192 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
cfa9d6d9 193 library_list_start_segment, NULL },
1fddbabb
PA
194 { "section", section_attributes, NULL,
195 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
196 library_list_start_section, NULL },
cfa9d6d9
DJ
197 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
198};
199
d6c10e95 200static const struct gdb_xml_attribute library_attributes[] = {
cfa9d6d9
DJ
201 { "name", GDB_XML_AF_NONE, NULL, NULL },
202 { NULL, GDB_XML_AF_NONE, NULL, NULL }
203};
204
d6c10e95 205static const struct gdb_xml_element library_list_children[] = {
cfa9d6d9
DJ
206 { "library", library_attributes, library_children,
207 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
1fddbabb 208 library_list_start_library, library_list_end_library },
cfa9d6d9
DJ
209 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
210};
211
d6c10e95 212static const struct gdb_xml_attribute library_list_attributes[] = {
cfa9d6d9
DJ
213 { "version", GDB_XML_AF_NONE, NULL, NULL },
214 { NULL, GDB_XML_AF_NONE, NULL, NULL }
215};
216
d6c10e95 217static const struct gdb_xml_element library_list_elements[] = {
cfa9d6d9
DJ
218 { "library-list", library_list_attributes, library_list_children,
219 GDB_XML_EF_NONE, library_list_start_list, NULL },
220 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
221};
222
223static VEC(lm_info_p) *
224solib_target_parse_libraries (const char *library)
225{
cfa9d6d9 226 VEC(lm_info_p) *result = NULL;
efc0eabd
PA
227 struct cleanup *back_to = make_cleanup (solib_target_free_library_list,
228 &result);
cfa9d6d9 229
efc0eabd
PA
230 if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd",
231 library_list_elements, library, &result) == 0)
232 {
233 /* Parsed successfully, keep the result. */
234 discard_cleanups (back_to);
235 return result;
236 }
cfa9d6d9
DJ
237
238 do_cleanups (back_to);
efc0eabd 239 return NULL;
cfa9d6d9
DJ
240}
241#endif
242
243static struct so_list *
244solib_target_current_sos (void)
245{
246 struct so_list *new_solib, *start = NULL, *last = NULL;
b25d79d4
PM
247 char *library_document;
248 struct cleanup *old_chain;
cfa9d6d9
DJ
249 VEC(lm_info_p) *library_list;
250 struct lm_info *info;
251 int ix;
252
253 /* Fetch the list of shared libraries. */
254 library_document = target_read_stralloc (&current_target,
255 TARGET_OBJECT_LIBRARIES,
256 NULL);
257 if (library_document == NULL)
258 return NULL;
259
b25d79d4
PM
260 /* solib_target_parse_libraries may throw, so we use a cleanup. */
261 old_chain = make_cleanup (xfree, library_document);
262
cfa9d6d9
DJ
263 /* Parse the list. */
264 library_list = solib_target_parse_libraries (library_document);
b25d79d4
PM
265
266 /* library_document string is not needed behind this point. */
267 do_cleanups (old_chain);
268
cfa9d6d9
DJ
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 {
41bf6aca 275 new_solib = XCNEW (struct so_list);
cfa9d6d9
DJ
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 333{
cfa9d6d9
DJ
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 {
d445b2f6 340 int num_sections = gdb_bfd_count_sections (so->abfd);
cfa9d6d9
DJ
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;
433759f7 367
1fddbabb
PA
368 section_bases = VEC_address (CORE_ADDR,
369 so->lm_info->section_bases);
370
371 so->addr_low = ~(CORE_ADDR) 0;
372 so->addr_high = 0;
373 for (i = 0, sect = so->abfd->sections;
374 sect != NULL;
375 i++, sect = sect->next)
376 {
377 if (!(bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
378 continue;
379 if (bfd_section_size (so->abfd, sect) > 0)
380 {
381 CORE_ADDR low, high;
433759f7 382
1fddbabb
PA
383 low = section_bases[i];
384 high = low + bfd_section_size (so->abfd, sect) - 1;
385
386 if (low < so->addr_low)
387 so->addr_low = low;
388 if (high > so->addr_high)
389 so->addr_high = high;
390 gdb_assert (so->addr_low <= so->addr_high);
391 found_range = 1;
392 }
3e43a32a
MS
393 so->lm_info->offsets->offsets[i]
394 = section_bases[bases_index];
1fddbabb
PA
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
2b2848e2
DE
457 offset = so->lm_info->offsets->offsets[gdb_bfd_section_index
458 (sec->the_bfd_section->owner,
459 sec->the_bfd_section)];
cfa9d6d9
DJ
460 sec->addr += offset;
461 sec->endaddr += offset;
462}
463
464static int
465solib_target_open_symbol_file_object (void *from_ttyp)
466{
467 /* We can't locate the main symbol file based on the target's
468 knowledge; the user has to specify it. */
469 return 0;
470}
471
472static int
473solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
474{
475 /* We don't have a range of addresses for the dynamic linker; there
476 may not be one in the program's address space. So only report
477 PLT entries (which may be import stubs). */
3e5d3a5a 478 return in_plt_section (pc);
cfa9d6d9
DJ
479}
480
8d465389 481struct target_so_ops solib_target_so_ops;
cfa9d6d9 482
3e43a32a
MS
483/* -Wmissing-prototypes */
484extern initialize_file_ftype _initialize_solib_target;
cfa9d6d9
DJ
485
486void
487_initialize_solib_target (void)
488{
489 solib_target_so_ops.relocate_section_addresses
490 = solib_target_relocate_section_addresses;
491 solib_target_so_ops.free_so = solib_target_free_so;
492 solib_target_so_ops.clear_solib = solib_target_clear_solib;
493 solib_target_so_ops.solib_create_inferior_hook
494 = solib_target_solib_create_inferior_hook;
495 solib_target_so_ops.special_symbol_handling
496 = solib_target_special_symbol_handling;
497 solib_target_so_ops.current_sos = solib_target_current_sos;
498 solib_target_so_ops.open_symbol_file_object
499 = solib_target_open_symbol_file_object;
500 solib_target_so_ops.in_dynsym_resolve_code
501 = solib_target_in_dynsym_resolve_code;
831a0c44 502 solib_target_so_ops.bfd_open = solib_bfd_open;
98d64339
PA
503
504 /* Set current_target_so_ops to solib_target_so_ops if not already
505 set. */
506 if (current_target_so_ops == 0)
507 current_target_so_ops = &solib_target_so_ops;
cfa9d6d9 508}
This page took 1.720795 seconds and 4 git commands to generate.