Make various lm_info implementations inherit from a base class
[deliverable/binutils-gdb.git] / gdb / solib-target.c
CommitLineData
cfa9d6d9
DJ
1/* Definitions for targets which report shared library events.
2
61baf725 3 Copyright (C) 2007-2017 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 29/* Private data for each loaded library. */
d0e449a1 30struct lm_info_target : public lm_info_base
cfa9d6d9
DJ
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
d0e449a1
SM
52typedef lm_info_target *lm_info_target_p;
53DEF_VEC_P(lm_info_target_p);
cfa9d6d9
DJ
54
55#if !defined(HAVE_LIBEXPAT)
56
d0e449a1 57static VEC(lm_info_target_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{
d0e449a1
SM
83 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
84 lm_info_target *last = VEC_last (lm_info_target_p, *list);
19ba03f4 85 ULONGEST *address_p
bc84451b 86 = (ULONGEST *) xml_find_attribute (attributes, "address")->value;
358eb95e 87 CORE_ADDR address = (CORE_ADDR) *address_p;
cfa9d6d9 88
1fddbabb
PA
89 if (last->section_bases != NULL)
90 gdb_xml_error (parser,
91 _("Library list with both segments and sections"));
92
267f6504 93 VEC_safe_push (CORE_ADDR, last->segment_bases, address);
cfa9d6d9
DJ
94}
95
1fddbabb
PA
96static void
97library_list_start_section (struct gdb_xml_parser *parser,
98 const struct gdb_xml_element *element,
99 void *user_data, VEC(gdb_xml_value_s) *attributes)
100{
d0e449a1
SM
101 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
102 lm_info_target *last = VEC_last (lm_info_target_p, *list);
19ba03f4 103 ULONGEST *address_p
bc84451b 104 = (ULONGEST *) 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{
d0e449a1
SM
121 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
122 lm_info_target *item = XCNEW (lm_info_target);
19ba03f4
SM
123 const char *name
124 = (const char *) xml_find_attribute (attributes, "name")->value;
cfa9d6d9
DJ
125
126 item->name = xstrdup (name);
d0e449a1 127 VEC_safe_push (lm_info_target_p, *list, item);
cfa9d6d9
DJ
128}
129
1fddbabb
PA
130static void
131library_list_end_library (struct gdb_xml_parser *parser,
132 const struct gdb_xml_element *element,
133 void *user_data, const char *body_text)
134{
d0e449a1
SM
135 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
136 lm_info_target *lm_info = VEC_last (lm_info_target_p, *list);
433759f7 137
1fddbabb
PA
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{
24c05f46 152 struct gdb_xml_value *version = xml_find_attribute (attributes, "version");
cfa9d6d9 153
24c05f46 154 /* #FIXED attribute may be omitted, Expat returns NULL in such case. */
8847cac2 155 if (version != NULL)
24c05f46 156 {
19ba03f4 157 const char *string = (const char *) version->value;
24c05f46
JK
158
159 if (strcmp (string, "1.0") != 0)
160 gdb_xml_error (parser,
161 _("Library list has unsupported version \"%s\""),
21047726 162 string);
24c05f46 163 }
cfa9d6d9
DJ
164}
165
166/* Discard the constructed library list. */
167
168static void
169solib_target_free_library_list (void *p)
170{
d0e449a1
SM
171 VEC(lm_info_target_p) **result = (VEC(lm_info_target_p) **) p;
172 lm_info_target *info;
cfa9d6d9
DJ
173 int ix;
174
d0e449a1 175 for (ix = 0; VEC_iterate (lm_info_target_p, *result, ix, info); ix++)
cfa9d6d9
DJ
176 {
177 xfree (info->name);
178 VEC_free (CORE_ADDR, info->segment_bases);
1fddbabb 179 VEC_free (CORE_ADDR, info->section_bases);
cfa9d6d9
DJ
180 xfree (info);
181 }
d0e449a1 182 VEC_free (lm_info_target_p, *result);
cfa9d6d9
DJ
183 *result = NULL;
184}
185
186/* The allowed elements and attributes for an XML library list.
187 The root element is a <library-list>. */
188
d6c10e95 189static const struct gdb_xml_attribute segment_attributes[] = {
cfa9d6d9
DJ
190 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
191 { NULL, GDB_XML_AF_NONE, NULL, NULL }
192};
193
d6c10e95 194static const struct gdb_xml_attribute section_attributes[] = {
1fddbabb
PA
195 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
196 { NULL, GDB_XML_AF_NONE, NULL, NULL }
197};
198
d6c10e95 199static const struct gdb_xml_element library_children[] = {
1fddbabb
PA
200 { "segment", segment_attributes, NULL,
201 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
cfa9d6d9 202 library_list_start_segment, NULL },
1fddbabb
PA
203 { "section", section_attributes, NULL,
204 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
205 library_list_start_section, NULL },
cfa9d6d9
DJ
206 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
207};
208
d6c10e95 209static const struct gdb_xml_attribute library_attributes[] = {
cfa9d6d9
DJ
210 { "name", GDB_XML_AF_NONE, NULL, NULL },
211 { NULL, GDB_XML_AF_NONE, NULL, NULL }
212};
213
d6c10e95 214static const struct gdb_xml_element library_list_children[] = {
cfa9d6d9
DJ
215 { "library", library_attributes, library_children,
216 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
1fddbabb 217 library_list_start_library, library_list_end_library },
cfa9d6d9
DJ
218 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
219};
220
d6c10e95 221static const struct gdb_xml_attribute library_list_attributes[] = {
24c05f46 222 { "version", GDB_XML_AF_OPTIONAL, NULL, NULL },
cfa9d6d9
DJ
223 { NULL, GDB_XML_AF_NONE, NULL, NULL }
224};
225
d6c10e95 226static const struct gdb_xml_element library_list_elements[] = {
cfa9d6d9
DJ
227 { "library-list", library_list_attributes, library_list_children,
228 GDB_XML_EF_NONE, library_list_start_list, NULL },
229 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
230};
231
d0e449a1 232static VEC(lm_info_target_p) *
cfa9d6d9
DJ
233solib_target_parse_libraries (const char *library)
234{
d0e449a1 235 VEC(lm_info_target_p) *result = NULL;
efc0eabd
PA
236 struct cleanup *back_to = make_cleanup (solib_target_free_library_list,
237 &result);
cfa9d6d9 238
efc0eabd
PA
239 if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd",
240 library_list_elements, library, &result) == 0)
241 {
242 /* Parsed successfully, keep the result. */
243 discard_cleanups (back_to);
244 return result;
245 }
cfa9d6d9
DJ
246
247 do_cleanups (back_to);
efc0eabd 248 return NULL;
cfa9d6d9
DJ
249}
250#endif
251
252static struct so_list *
253solib_target_current_sos (void)
254{
255 struct so_list *new_solib, *start = NULL, *last = NULL;
b25d79d4
PM
256 char *library_document;
257 struct cleanup *old_chain;
d0e449a1
SM
258 VEC(lm_info_target_p) *library_list;
259 lm_info_target *info;
cfa9d6d9
DJ
260 int ix;
261
262 /* Fetch the list of shared libraries. */
263 library_document = target_read_stralloc (&current_target,
264 TARGET_OBJECT_LIBRARIES,
265 NULL);
266 if (library_document == NULL)
267 return NULL;
268
b25d79d4
PM
269 /* solib_target_parse_libraries may throw, so we use a cleanup. */
270 old_chain = make_cleanup (xfree, library_document);
271
cfa9d6d9
DJ
272 /* Parse the list. */
273 library_list = solib_target_parse_libraries (library_document);
b25d79d4
PM
274
275 /* library_document string is not needed behind this point. */
276 do_cleanups (old_chain);
277
cfa9d6d9
DJ
278 if (library_list == NULL)
279 return NULL;
280
281 /* Build a struct so_list for each entry on the list. */
d0e449a1 282 for (ix = 0; VEC_iterate (lm_info_target_p, library_list, ix, info); ix++)
cfa9d6d9 283 {
41bf6aca 284 new_solib = XCNEW (struct so_list);
cfa9d6d9
DJ
285 strncpy (new_solib->so_name, info->name, SO_NAME_MAX_PATH_SIZE - 1);
286 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
287 strncpy (new_solib->so_original_name, info->name,
288 SO_NAME_MAX_PATH_SIZE - 1);
289 new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
290 new_solib->lm_info = info;
291
292 /* We no longer need this copy of the name. */
293 xfree (info->name);
294 info->name = NULL;
295
296 /* Add it to the list. */
297 if (!start)
298 last = start = new_solib;
299 else
300 {
301 last->next = new_solib;
302 last = new_solib;
303 }
304 }
305
306 /* Free the library list, but not its members. */
d0e449a1 307 VEC_free (lm_info_target_p, library_list);
cfa9d6d9
DJ
308
309 return start;
310}
311
cfa9d6d9 312static void
268a4a75 313solib_target_solib_create_inferior_hook (int from_tty)
cfa9d6d9
DJ
314{
315 /* Nothing needed. */
316}
317
318static void
319solib_target_clear_solib (void)
320{
321 /* Nothing needed. */
322}
323
324static void
325solib_target_free_so (struct so_list *so)
326{
d0e449a1
SM
327 lm_info_target *li = (lm_info_target *) so->lm_info;
328
329 gdb_assert (li->name == NULL);
330 xfree (li->offsets);
331 VEC_free (CORE_ADDR, li->segment_bases);
332 xfree (li);
cfa9d6d9
DJ
333}
334
335static void
336solib_target_relocate_section_addresses (struct so_list *so,
0542c86d 337 struct target_section *sec)
cfa9d6d9 338{
cfa9d6d9 339 CORE_ADDR offset;
d0e449a1 340 lm_info_target *li = (lm_info_target *) so->lm_info;
cfa9d6d9
DJ
341
342 /* Build the offset table only once per object file. We can not do
343 it any earlier, since we need to open the file first. */
d0e449a1 344 if (li->offsets == NULL)
cfa9d6d9 345 {
d445b2f6 346 int num_sections = gdb_bfd_count_sections (so->abfd);
cfa9d6d9 347
d0e449a1 348 li->offsets
224c3ddb
SM
349 = ((struct section_offsets *)
350 xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections)));
cfa9d6d9 351
d0e449a1 352 if (li->section_bases)
cfa9d6d9 353 {
cfa9d6d9 354 int i;
1fddbabb
PA
355 asection *sect;
356 int num_section_bases
d0e449a1 357 = VEC_length (CORE_ADDR, li->section_bases);
1fddbabb
PA
358 int num_alloc_sections = 0;
359
360 for (i = 0, sect = so->abfd->sections;
361 sect != NULL;
362 i++, sect = sect->next)
363 if ((bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
364 num_alloc_sections++;
365
366 if (num_alloc_sections != num_section_bases)
367 warning (_("\
368Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
cfa9d6d9 369 so->so_name);
1fddbabb 370 else
cfa9d6d9 371 {
1fddbabb
PA
372 int bases_index = 0;
373 int found_range = 0;
374 CORE_ADDR *section_bases;
433759f7 375
1fddbabb 376 section_bases = VEC_address (CORE_ADDR,
d0e449a1 377 li->section_bases);
1fddbabb
PA
378
379 so->addr_low = ~(CORE_ADDR) 0;
380 so->addr_high = 0;
381 for (i = 0, sect = so->abfd->sections;
382 sect != NULL;
383 i++, sect = sect->next)
384 {
385 if (!(bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
386 continue;
387 if (bfd_section_size (so->abfd, sect) > 0)
388 {
389 CORE_ADDR low, high;
433759f7 390
1fddbabb
PA
391 low = section_bases[i];
392 high = low + bfd_section_size (so->abfd, sect) - 1;
393
394 if (low < so->addr_low)
395 so->addr_low = low;
396 if (high > so->addr_high)
397 so->addr_high = high;
398 gdb_assert (so->addr_low <= so->addr_high);
399 found_range = 1;
400 }
d0e449a1 401 li->offsets->offsets[i]
3e43a32a 402 = section_bases[bases_index];
1fddbabb
PA
403 bases_index++;
404 }
405 if (!found_range)
406 so->addr_low = so->addr_high = 0;
407 gdb_assert (so->addr_low <= so->addr_high);
408 }
409 }
d0e449a1 410 else if (li->segment_bases)
1fddbabb
PA
411 {
412 struct symfile_segment_data *data;
433759f7 413
1fddbabb
PA
414 data = get_symfile_segment_data (so->abfd);
415 if (data == NULL)
416 warning (_("\
417Could not relocate shared library \"%s\": no segments"), so->so_name);
418 else
419 {
420 ULONGEST orig_delta;
421 int i;
422 int num_bases;
423 CORE_ADDR *segment_bases;
424
d0e449a1
SM
425 num_bases = VEC_length (CORE_ADDR, li->segment_bases);
426 segment_bases = VEC_address (CORE_ADDR, li->segment_bases);
1fddbabb 427
d0e449a1 428 if (!symfile_map_offsets_to_segments (so->abfd, data, li->offsets,
1fddbabb
PA
429 num_bases, segment_bases))
430 warning (_("\
431Could not relocate shared library \"%s\": bad offsets"), so->so_name);
432
433 /* Find the range of addresses to report for this library in
434 "info sharedlibrary". Report any consecutive segments
435 which were relocated as a single unit. */
436 gdb_assert (num_bases > 0);
437 orig_delta = segment_bases[0] - data->segment_bases[0];
438
439 for (i = 1; i < data->num_segments; i++)
440 {
441 /* If we have run out of offsets, assume all
442 remaining segments have the same offset. */
443 if (i >= num_bases)
444 continue;
445
446 /* If this segment does not have the same offset, do
447 not include it in the library's range. */
448 if (segment_bases[i] - data->segment_bases[i] != orig_delta)
449 break;
450 }
451
452 so->addr_low = segment_bases[0];
453 so->addr_high = (data->segment_bases[i - 1]
454 + data->segment_sizes[i - 1]
455 + orig_delta);
456 gdb_assert (so->addr_low <= so->addr_high);
457
458 free_symfile_segment_data (data);
cfa9d6d9 459 }
cfa9d6d9
DJ
460 }
461 }
462
d0e449a1
SM
463 offset = li->offsets->offsets[gdb_bfd_section_index
464 (sec->the_bfd_section->owner,
465 sec->the_bfd_section)];
cfa9d6d9
DJ
466 sec->addr += offset;
467 sec->endaddr += offset;
468}
469
470static int
471solib_target_open_symbol_file_object (void *from_ttyp)
472{
473 /* We can't locate the main symbol file based on the target's
474 knowledge; the user has to specify it. */
475 return 0;
476}
477
478static int
479solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
480{
481 /* We don't have a range of addresses for the dynamic linker; there
482 may not be one in the program's address space. So only report
483 PLT entries (which may be import stubs). */
3e5d3a5a 484 return in_plt_section (pc);
cfa9d6d9
DJ
485}
486
8d465389 487struct target_so_ops solib_target_so_ops;
cfa9d6d9 488
3e43a32a
MS
489/* -Wmissing-prototypes */
490extern initialize_file_ftype _initialize_solib_target;
cfa9d6d9
DJ
491
492void
493_initialize_solib_target (void)
494{
495 solib_target_so_ops.relocate_section_addresses
496 = solib_target_relocate_section_addresses;
497 solib_target_so_ops.free_so = solib_target_free_so;
498 solib_target_so_ops.clear_solib = solib_target_clear_solib;
499 solib_target_so_ops.solib_create_inferior_hook
500 = solib_target_solib_create_inferior_hook;
cfa9d6d9
DJ
501 solib_target_so_ops.current_sos = solib_target_current_sos;
502 solib_target_so_ops.open_symbol_file_object
503 = solib_target_open_symbol_file_object;
504 solib_target_so_ops.in_dynsym_resolve_code
505 = solib_target_in_dynsym_resolve_code;
831a0c44 506 solib_target_so_ops.bfd_open = solib_bfd_open;
98d64339
PA
507
508 /* Set current_target_so_ops to solib_target_so_ops if not already
509 set. */
510 if (current_target_so_ops == 0)
511 current_target_so_ops = &solib_target_so_ops;
cfa9d6d9 512}
This page took 1.088225 seconds and 4 git commands to generate.