]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/solib-target.c
Eliminate catch_errors
[thirdparty/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"
f2f46dfc 28#include <vector>
cfa9d6d9 29
cfa9d6d9 30/* Private data for each loaded library. */
d0e449a1 31struct lm_info_target : public lm_info_base
cfa9d6d9
DJ
32{
33 /* The library's name. The name is normally kept in the struct
34 so_list; it is only here during XML parsing. */
51046d9e 35 std::string name;
cfa9d6d9 36
1fddbabb
PA
37 /* The target can either specify segment bases or section bases, not
38 both. */
39
cfa9d6d9
DJ
40 /* The base addresses for each independently relocatable segment of
41 this shared library. */
f2f46dfc 42 std::vector<CORE_ADDR> segment_bases;
cfa9d6d9 43
1fddbabb
PA
44 /* The base addresses for each independently allocatable,
45 relocatable section of this shared library. */
f2f46dfc 46 std::vector<CORE_ADDR> section_bases;
1fddbabb 47
cfa9d6d9 48 /* The cached offsets for each section of this shared library,
1fddbabb 49 determined from SEGMENT_BASES, or SECTION_BASES. */
51046d9e 50 section_offsets *offsets = NULL;
cfa9d6d9
DJ
51};
52
d0e449a1
SM
53typedef lm_info_target *lm_info_target_p;
54DEF_VEC_P(lm_info_target_p);
cfa9d6d9
DJ
55
56#if !defined(HAVE_LIBEXPAT)
57
d0e449a1 58static VEC(lm_info_target_p) *
cfa9d6d9
DJ
59solib_target_parse_libraries (const char *library)
60{
61 static int have_warned;
62
63 if (!have_warned)
64 {
65 have_warned = 1;
66 warning (_("Can not parse XML library list; XML support was disabled "
67 "at compile time"));
68 }
69
70 return NULL;
71}
72
73#else /* HAVE_LIBEXPAT */
74
75#include "xml-support.h"
76
77/* Handle the start of a <segment> element. */
78
79static void
80library_list_start_segment (struct gdb_xml_parser *parser,
81 const struct gdb_xml_element *element,
82 void *user_data, VEC(gdb_xml_value_s) *attributes)
83{
d0e449a1
SM
84 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
85 lm_info_target *last = VEC_last (lm_info_target_p, *list);
19ba03f4 86 ULONGEST *address_p
bc84451b 87 = (ULONGEST *) xml_find_attribute (attributes, "address")->value;
358eb95e 88 CORE_ADDR address = (CORE_ADDR) *address_p;
cfa9d6d9 89
f2f46dfc 90 if (!last->section_bases.empty ())
1fddbabb
PA
91 gdb_xml_error (parser,
92 _("Library list with both segments and sections"));
93
f2f46dfc 94 last->segment_bases.push_back (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{
d0e449a1
SM
102 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
103 lm_info_target *last = VEC_last (lm_info_target_p, *list);
19ba03f4 104 ULONGEST *address_p
bc84451b 105 = (ULONGEST *) xml_find_attribute (attributes, "address")->value;
1fddbabb
PA
106 CORE_ADDR address = (CORE_ADDR) *address_p;
107
f2f46dfc 108 if (!last->segment_bases.empty ())
1fddbabb
PA
109 gdb_xml_error (parser,
110 _("Library list with both segments and sections"));
111
f2f46dfc 112 last->section_bases.push_back (address);
1fddbabb
PA
113}
114
cfa9d6d9
DJ
115/* Handle the start of a <library> element. */
116
117static void
118library_list_start_library (struct gdb_xml_parser *parser,
119 const struct gdb_xml_element *element,
120 void *user_data, VEC(gdb_xml_value_s) *attributes)
121{
d0e449a1 122 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
51046d9e 123 lm_info_target *item = new lm_info_target;
19ba03f4
SM
124 const char *name
125 = (const char *) xml_find_attribute (attributes, "name")->value;
cfa9d6d9
DJ
126
127 item->name = xstrdup (name);
d0e449a1 128 VEC_safe_push (lm_info_target_p, *list, item);
cfa9d6d9
DJ
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{
d0e449a1
SM
136 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
137 lm_info_target *lm_info = VEC_last (lm_info_target_p, *list);
433759f7 138
f2f46dfc
SM
139 if (lm_info->segment_bases.empty () && lm_info->section_bases.empty ())
140 gdb_xml_error (parser, _("No segment or section bases defined"));
1fddbabb
PA
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{
24c05f46 151 struct gdb_xml_value *version = xml_find_attribute (attributes, "version");
cfa9d6d9 152
24c05f46 153 /* #FIXED attribute may be omitted, Expat returns NULL in such case. */
8847cac2 154 if (version != NULL)
24c05f46 155 {
19ba03f4 156 const char *string = (const char *) version->value;
24c05f46
JK
157
158 if (strcmp (string, "1.0") != 0)
159 gdb_xml_error (parser,
160 _("Library list has unsupported version \"%s\""),
21047726 161 string);
24c05f46 162 }
cfa9d6d9
DJ
163}
164
165/* Discard the constructed library list. */
166
167static void
168solib_target_free_library_list (void *p)
169{
d0e449a1
SM
170 VEC(lm_info_target_p) **result = (VEC(lm_info_target_p) **) p;
171 lm_info_target *info;
cfa9d6d9
DJ
172 int ix;
173
d0e449a1 174 for (ix = 0; VEC_iterate (lm_info_target_p, *result, ix, info); ix++)
51046d9e
SM
175 delete info;
176
d0e449a1 177 VEC_free (lm_info_target_p, *result);
cfa9d6d9
DJ
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
d6c10e95 184static const struct gdb_xml_attribute segment_attributes[] = {
cfa9d6d9
DJ
185 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
186 { NULL, GDB_XML_AF_NONE, NULL, NULL }
187};
188
d6c10e95 189static const struct gdb_xml_attribute section_attributes[] = {
1fddbabb
PA
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_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
d6c10e95 204static const struct gdb_xml_attribute library_attributes[] = {
cfa9d6d9
DJ
205 { "name", GDB_XML_AF_NONE, NULL, NULL },
206 { NULL, GDB_XML_AF_NONE, NULL, NULL }
207};
208
d6c10e95 209static const struct gdb_xml_element library_list_children[] = {
cfa9d6d9
DJ
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
d6c10e95 216static const struct gdb_xml_attribute library_list_attributes[] = {
24c05f46 217 { "version", GDB_XML_AF_OPTIONAL, NULL, NULL },
cfa9d6d9
DJ
218 { NULL, GDB_XML_AF_NONE, NULL, NULL }
219};
220
d6c10e95 221static const struct gdb_xml_element library_list_elements[] = {
cfa9d6d9
DJ
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
d0e449a1 227static VEC(lm_info_target_p) *
cfa9d6d9
DJ
228solib_target_parse_libraries (const char *library)
229{
d0e449a1 230 VEC(lm_info_target_p) *result = NULL;
efc0eabd
PA
231 struct cleanup *back_to = make_cleanup (solib_target_free_library_list,
232 &result);
cfa9d6d9 233
efc0eabd
PA
234 if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd",
235 library_list_elements, library, &result) == 0)
236 {
237 /* Parsed successfully, keep the result. */
238 discard_cleanups (back_to);
239 return result;
240 }
cfa9d6d9
DJ
241
242 do_cleanups (back_to);
efc0eabd 243 return NULL;
cfa9d6d9
DJ
244}
245#endif
246
247static struct so_list *
248solib_target_current_sos (void)
249{
250 struct so_list *new_solib, *start = NULL, *last = NULL;
b25d79d4
PM
251 char *library_document;
252 struct cleanup *old_chain;
d0e449a1
SM
253 VEC(lm_info_target_p) *library_list;
254 lm_info_target *info;
cfa9d6d9
DJ
255 int ix;
256
257 /* Fetch the list of shared libraries. */
258 library_document = target_read_stralloc (&current_target,
259 TARGET_OBJECT_LIBRARIES,
260 NULL);
261 if (library_document == NULL)
262 return NULL;
263
b25d79d4
PM
264 /* solib_target_parse_libraries may throw, so we use a cleanup. */
265 old_chain = make_cleanup (xfree, library_document);
266
cfa9d6d9
DJ
267 /* Parse the list. */
268 library_list = solib_target_parse_libraries (library_document);
b25d79d4
PM
269
270 /* library_document string is not needed behind this point. */
271 do_cleanups (old_chain);
272
cfa9d6d9
DJ
273 if (library_list == NULL)
274 return NULL;
275
276 /* Build a struct so_list for each entry on the list. */
d0e449a1 277 for (ix = 0; VEC_iterate (lm_info_target_p, library_list, ix, info); ix++)
cfa9d6d9 278 {
41bf6aca 279 new_solib = XCNEW (struct so_list);
51046d9e
SM
280 strncpy (new_solib->so_name, info->name.c_str (),
281 SO_NAME_MAX_PATH_SIZE - 1);
cfa9d6d9 282 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
51046d9e 283 strncpy (new_solib->so_original_name, info->name.c_str (),
cfa9d6d9
DJ
284 SO_NAME_MAX_PATH_SIZE - 1);
285 new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
286 new_solib->lm_info = info;
287
288 /* We no longer need this copy of the name. */
51046d9e 289 info->name.clear ();
cfa9d6d9
DJ
290
291 /* Add it to the list. */
292 if (!start)
293 last = start = new_solib;
294 else
295 {
296 last->next = new_solib;
297 last = new_solib;
298 }
299 }
300
301 /* Free the library list, but not its members. */
d0e449a1 302 VEC_free (lm_info_target_p, library_list);
cfa9d6d9
DJ
303
304 return start;
305}
306
cfa9d6d9 307static void
268a4a75 308solib_target_solib_create_inferior_hook (int from_tty)
cfa9d6d9
DJ
309{
310 /* Nothing needed. */
311}
312
313static void
314solib_target_clear_solib (void)
315{
316 /* Nothing needed. */
317}
318
319static void
320solib_target_free_so (struct so_list *so)
321{
d0e449a1
SM
322 lm_info_target *li = (lm_info_target *) so->lm_info;
323
51046d9e
SM
324 gdb_assert (li->name.empty ());
325
326 delete li;
cfa9d6d9
DJ
327}
328
329static void
330solib_target_relocate_section_addresses (struct so_list *so,
0542c86d 331 struct target_section *sec)
cfa9d6d9 332{
cfa9d6d9 333 CORE_ADDR offset;
d0e449a1 334 lm_info_target *li = (lm_info_target *) so->lm_info;
cfa9d6d9
DJ
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. */
d0e449a1 338 if (li->offsets == NULL)
cfa9d6d9 339 {
d445b2f6 340 int num_sections = gdb_bfd_count_sections (so->abfd);
cfa9d6d9 341
d0e449a1 342 li->offsets
224c3ddb
SM
343 = ((struct section_offsets *)
344 xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections)));
cfa9d6d9 345
f2f46dfc 346 if (!li->section_bases.empty ())
cfa9d6d9 347 {
cfa9d6d9 348 int i;
1fddbabb 349 asection *sect;
1fddbabb
PA
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
d17f7b36 358 if (num_alloc_sections != li->section_bases.size ())
1fddbabb
PA
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;
1fddbabb
PA
366
367 so->addr_low = ~(CORE_ADDR) 0;
368 so->addr_high = 0;
369 for (i = 0, sect = so->abfd->sections;
370 sect != NULL;
371 i++, sect = sect->next)
372 {
373 if (!(bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
374 continue;
375 if (bfd_section_size (so->abfd, sect) > 0)
376 {
377 CORE_ADDR low, high;
433759f7 378
f2f46dfc 379 low = li->section_bases[i];
1fddbabb
PA
380 high = low + bfd_section_size (so->abfd, sect) - 1;
381
382 if (low < so->addr_low)
383 so->addr_low = low;
384 if (high > so->addr_high)
385 so->addr_high = high;
386 gdb_assert (so->addr_low <= so->addr_high);
387 found_range = 1;
388 }
f2f46dfc 389 li->offsets->offsets[i] = li->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 }
f2f46dfc 397 else if (!li->segment_bases.empty ())
1fddbabb
PA
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;
1fddbabb 409
d0e449a1 410 if (!symfile_map_offsets_to_segments (so->abfd, data, li->offsets,
d17f7b36
SM
411 li->segment_bases.size (),
412 li->segment_bases.data ()))
1fddbabb
PA
413 warning (_("\
414Could not relocate shared library \"%s\": bad offsets"), so->so_name);
415
416 /* Find the range of addresses to report for this library in
417 "info sharedlibrary". Report any consecutive segments
418 which were relocated as a single unit. */
d17f7b36
SM
419 gdb_assert (li->segment_bases.size () > 0);
420 orig_delta = li->segment_bases[0] - data->segment_bases[0];
1fddbabb
PA
421
422 for (i = 1; i < data->num_segments; i++)
423 {
424 /* If we have run out of offsets, assume all
425 remaining segments have the same offset. */
d17f7b36 426 if (i >= li->segment_bases.size ())
1fddbabb
PA
427 continue;
428
429 /* If this segment does not have the same offset, do
430 not include it in the library's range. */
d17f7b36
SM
431 if (li->segment_bases[i] - data->segment_bases[i]
432 != orig_delta)
1fddbabb
PA
433 break;
434 }
435
d17f7b36 436 so->addr_low = li->segment_bases[0];
1fddbabb
PA
437 so->addr_high = (data->segment_bases[i - 1]
438 + data->segment_sizes[i - 1]
439 + orig_delta);
440 gdb_assert (so->addr_low <= so->addr_high);
441
442 free_symfile_segment_data (data);
cfa9d6d9 443 }
cfa9d6d9
DJ
444 }
445 }
446
d0e449a1
SM
447 offset = li->offsets->offsets[gdb_bfd_section_index
448 (sec->the_bfd_section->owner,
449 sec->the_bfd_section)];
cfa9d6d9
DJ
450 sec->addr += offset;
451 sec->endaddr += offset;
452}
453
454static int
bf469271 455solib_target_open_symbol_file_object (int from_tty)
cfa9d6d9
DJ
456{
457 /* We can't locate the main symbol file based on the target's
458 knowledge; the user has to specify it. */
459 return 0;
460}
461
462static int
463solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
464{
465 /* We don't have a range of addresses for the dynamic linker; there
466 may not be one in the program's address space. So only report
467 PLT entries (which may be import stubs). */
3e5d3a5a 468 return in_plt_section (pc);
cfa9d6d9
DJ
469}
470
8d465389 471struct target_so_ops solib_target_so_ops;
cfa9d6d9 472
cfa9d6d9
DJ
473void
474_initialize_solib_target (void)
475{
476 solib_target_so_ops.relocate_section_addresses
477 = solib_target_relocate_section_addresses;
478 solib_target_so_ops.free_so = solib_target_free_so;
479 solib_target_so_ops.clear_solib = solib_target_clear_solib;
480 solib_target_so_ops.solib_create_inferior_hook
481 = solib_target_solib_create_inferior_hook;
cfa9d6d9
DJ
482 solib_target_so_ops.current_sos = solib_target_current_sos;
483 solib_target_so_ops.open_symbol_file_object
484 = solib_target_open_symbol_file_object;
485 solib_target_so_ops.in_dynsym_resolve_code
486 = solib_target_in_dynsym_resolve_code;
831a0c44 487 solib_target_so_ops.bfd_open = solib_bfd_open;
98d64339
PA
488
489 /* Set current_target_so_ops to solib_target_so_ops if not already
490 set. */
491 if (current_target_so_ops == 0)
492 current_target_so_ops = &solib_target_so_ops;
cfa9d6d9 493}