gdb: fix vfork with multiple threads
[deliverable/binutils-gdb.git] / gdb / solib-target.c
CommitLineData
cfa9d6d9
DJ
1/* Definitions for targets which report shared library events.
2
3666a048 3 Copyright (C) 2007-2021 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"
8d465389 26#include "solib-target.h"
f2f46dfc 27#include <vector>
328d42d8 28#include "inferior.h"
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. */
6a053cb1 50 section_offsets offsets;
cfa9d6d9
DJ
51};
52
776489e0 53typedef std::vector<std::unique_ptr<lm_info_target>> lm_info_vector;
cfa9d6d9
DJ
54
55#if !defined(HAVE_LIBEXPAT)
56
776489e0 57static lm_info_vector
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
776489e0 69 return lm_info_vector ();
cfa9d6d9
DJ
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,
4d0fdd9b
SM
81 void *user_data,
82 std::vector<gdb_xml_value> &attributes)
cfa9d6d9 83{
776489e0
TT
84 lm_info_vector *list = (lm_info_vector *) user_data;
85 lm_info_target *last = list->back ().get ();
19ba03f4 86 ULONGEST *address_p
4d0fdd9b 87 = (ULONGEST *) xml_find_attribute (attributes, "address")->value.get ();
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,
4d0fdd9b
SM
100 void *user_data,
101 std::vector<gdb_xml_value> &attributes)
1fddbabb 102{
776489e0
TT
103 lm_info_vector *list = (lm_info_vector *) user_data;
104 lm_info_target *last = list->back ().get ();
19ba03f4 105 ULONGEST *address_p
4d0fdd9b 106 = (ULONGEST *) xml_find_attribute (attributes, "address")->value.get ();
1fddbabb
PA
107 CORE_ADDR address = (CORE_ADDR) *address_p;
108
f2f46dfc 109 if (!last->segment_bases.empty ())
1fddbabb
PA
110 gdb_xml_error (parser,
111 _("Library list with both segments and sections"));
112
f2f46dfc 113 last->section_bases.push_back (address);
1fddbabb
PA
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,
4d0fdd9b
SM
121 void *user_data,
122 std::vector<gdb_xml_value> &attributes)
cfa9d6d9 123{
776489e0 124 lm_info_vector *list = (lm_info_vector *) user_data;
51046d9e 125 lm_info_target *item = new lm_info_target;
2f667667 126 item->name
4d0fdd9b 127 = (const char *) xml_find_attribute (attributes, "name")->value.get ();
cfa9d6d9 128
776489e0 129 list->emplace_back (item);
cfa9d6d9
DJ
130}
131
1fddbabb
PA
132static void
133library_list_end_library (struct gdb_xml_parser *parser,
134 const struct gdb_xml_element *element,
135 void *user_data, const char *body_text)
136{
776489e0
TT
137 lm_info_vector *list = (lm_info_vector *) user_data;
138 lm_info_target *lm_info = list->back ().get ();
433759f7 139
f2f46dfc
SM
140 if (lm_info->segment_bases.empty () && lm_info->section_bases.empty ())
141 gdb_xml_error (parser, _("No segment or section bases defined"));
1fddbabb
PA
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,
4d0fdd9b
SM
150 void *user_data,
151 std::vector<gdb_xml_value> &attributes)
cfa9d6d9 152{
24c05f46 153 struct gdb_xml_value *version = xml_find_attribute (attributes, "version");
cfa9d6d9 154
24c05f46 155 /* #FIXED attribute may be omitted, Expat returns NULL in such case. */
8847cac2 156 if (version != NULL)
24c05f46 157 {
4d0fdd9b 158 const char *string = (const char *) version->value.get ();
24c05f46
JK
159
160 if (strcmp (string, "1.0") != 0)
161 gdb_xml_error (parser,
162 _("Library list has unsupported version \"%s\""),
21047726 163 string);
24c05f46 164 }
cfa9d6d9
DJ
165}
166
cfa9d6d9
DJ
167/* The allowed elements and attributes for an XML library list.
168 The root element is a <library-list>. */
169
d6c10e95 170static const struct gdb_xml_attribute segment_attributes[] = {
cfa9d6d9
DJ
171 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
172 { NULL, GDB_XML_AF_NONE, NULL, NULL }
173};
174
d6c10e95 175static const struct gdb_xml_attribute section_attributes[] = {
1fddbabb
PA
176 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
177 { NULL, GDB_XML_AF_NONE, NULL, NULL }
178};
179
d6c10e95 180static const struct gdb_xml_element library_children[] = {
1fddbabb
PA
181 { "segment", segment_attributes, NULL,
182 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
cfa9d6d9 183 library_list_start_segment, NULL },
1fddbabb
PA
184 { "section", section_attributes, NULL,
185 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
186 library_list_start_section, NULL },
cfa9d6d9
DJ
187 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
188};
189
d6c10e95 190static const struct gdb_xml_attribute library_attributes[] = {
cfa9d6d9
DJ
191 { "name", GDB_XML_AF_NONE, NULL, NULL },
192 { NULL, GDB_XML_AF_NONE, NULL, NULL }
193};
194
d6c10e95 195static const struct gdb_xml_element library_list_children[] = {
cfa9d6d9
DJ
196 { "library", library_attributes, library_children,
197 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
1fddbabb 198 library_list_start_library, library_list_end_library },
cfa9d6d9
DJ
199 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
200};
201
d6c10e95 202static const struct gdb_xml_attribute library_list_attributes[] = {
24c05f46 203 { "version", GDB_XML_AF_OPTIONAL, NULL, NULL },
cfa9d6d9
DJ
204 { NULL, GDB_XML_AF_NONE, NULL, NULL }
205};
206
d6c10e95 207static const struct gdb_xml_element library_list_elements[] = {
cfa9d6d9
DJ
208 { "library-list", library_list_attributes, library_list_children,
209 GDB_XML_EF_NONE, library_list_start_list, NULL },
210 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
211};
212
776489e0 213static lm_info_vector
cfa9d6d9
DJ
214solib_target_parse_libraries (const char *library)
215{
776489e0 216 lm_info_vector result;
cfa9d6d9 217
efc0eabd
PA
218 if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd",
219 library_list_elements, library, &result) == 0)
220 {
776489e0 221 /* Parsed successfully. */
efc0eabd
PA
222 return result;
223 }
cfa9d6d9 224
776489e0
TT
225 result.clear ();
226 return result;
cfa9d6d9
DJ
227}
228#endif
229
230static struct so_list *
231solib_target_current_sos (void)
232{
233 struct so_list *new_solib, *start = NULL, *last = NULL;
cfa9d6d9
DJ
234
235 /* Fetch the list of shared libraries. */
9018be22 236 gdb::optional<gdb::char_vector> library_document
328d42d8
SM
237 = target_read_stralloc (current_inferior ()->top_target (),
238 TARGET_OBJECT_LIBRARIES, NULL);
9018be22 239 if (!library_document)
cfa9d6d9
DJ
240 return NULL;
241
242 /* Parse the list. */
776489e0
TT
243 lm_info_vector library_list
244 = solib_target_parse_libraries (library_document->data ());
b25d79d4 245
776489e0 246 if (library_list.empty ())
cfa9d6d9
DJ
247 return NULL;
248
249 /* Build a struct so_list for each entry on the list. */
776489e0 250 for (auto &&info : library_list)
cfa9d6d9 251 {
41bf6aca 252 new_solib = XCNEW (struct so_list);
51046d9e
SM
253 strncpy (new_solib->so_name, info->name.c_str (),
254 SO_NAME_MAX_PATH_SIZE - 1);
cfa9d6d9 255 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
51046d9e 256 strncpy (new_solib->so_original_name, info->name.c_str (),
cfa9d6d9
DJ
257 SO_NAME_MAX_PATH_SIZE - 1);
258 new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
cfa9d6d9
DJ
259
260 /* We no longer need this copy of the name. */
51046d9e 261 info->name.clear ();
cfa9d6d9 262
776489e0
TT
263 new_solib->lm_info = info.release ();
264
cfa9d6d9
DJ
265 /* Add it to the list. */
266 if (!start)
267 last = start = new_solib;
268 else
269 {
270 last->next = new_solib;
271 last = new_solib;
272 }
273 }
274
cfa9d6d9
DJ
275 return start;
276}
277
cfa9d6d9 278static void
268a4a75 279solib_target_solib_create_inferior_hook (int from_tty)
cfa9d6d9
DJ
280{
281 /* Nothing needed. */
282}
283
284static void
285solib_target_clear_solib (void)
286{
287 /* Nothing needed. */
288}
289
290static void
291solib_target_free_so (struct so_list *so)
292{
d0e449a1
SM
293 lm_info_target *li = (lm_info_target *) so->lm_info;
294
51046d9e
SM
295 gdb_assert (li->name.empty ());
296
297 delete li;
cfa9d6d9
DJ
298}
299
300static void
301solib_target_relocate_section_addresses (struct so_list *so,
0542c86d 302 struct target_section *sec)
cfa9d6d9 303{
cfa9d6d9 304 CORE_ADDR offset;
d0e449a1 305 lm_info_target *li = (lm_info_target *) so->lm_info;
cfa9d6d9
DJ
306
307 /* Build the offset table only once per object file. We can not do
308 it any earlier, since we need to open the file first. */
6a053cb1 309 if (li->offsets.empty ())
cfa9d6d9 310 {
d445b2f6 311 int num_sections = gdb_bfd_count_sections (so->abfd);
cfa9d6d9 312
6a053cb1 313 li->offsets.assign (num_sections, 0);
cfa9d6d9 314
f2f46dfc 315 if (!li->section_bases.empty ())
cfa9d6d9 316 {
cfa9d6d9 317 int i;
1fddbabb 318 asection *sect;
1fddbabb
PA
319 int num_alloc_sections = 0;
320
321 for (i = 0, sect = so->abfd->sections;
322 sect != NULL;
323 i++, sect = sect->next)
fd361982 324 if ((bfd_section_flags (sect) & SEC_ALLOC))
1fddbabb
PA
325 num_alloc_sections++;
326
d17f7b36 327 if (num_alloc_sections != li->section_bases.size ())
1fddbabb
PA
328 warning (_("\
329Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
cfa9d6d9 330 so->so_name);
1fddbabb 331 else
cfa9d6d9 332 {
1fddbabb
PA
333 int bases_index = 0;
334 int found_range = 0;
1fddbabb
PA
335
336 so->addr_low = ~(CORE_ADDR) 0;
337 so->addr_high = 0;
338 for (i = 0, sect = so->abfd->sections;
339 sect != NULL;
340 i++, sect = sect->next)
341 {
fd361982 342 if (!(bfd_section_flags (sect) & SEC_ALLOC))
1fddbabb 343 continue;
fd361982 344 if (bfd_section_size (sect) > 0)
1fddbabb
PA
345 {
346 CORE_ADDR low, high;
433759f7 347
f2f46dfc 348 low = li->section_bases[i];
fd361982 349 high = low + bfd_section_size (sect) - 1;
1fddbabb
PA
350
351 if (low < so->addr_low)
352 so->addr_low = low;
353 if (high > so->addr_high)
354 so->addr_high = high;
355 gdb_assert (so->addr_low <= so->addr_high);
356 found_range = 1;
357 }
6a053cb1 358 li->offsets[i] = li->section_bases[bases_index];
1fddbabb
PA
359 bases_index++;
360 }
361 if (!found_range)
362 so->addr_low = so->addr_high = 0;
363 gdb_assert (so->addr_low <= so->addr_high);
364 }
365 }
f2f46dfc 366 else if (!li->segment_bases.empty ())
1fddbabb 367 {
62982abd
SM
368 symfile_segment_data_up data
369 = get_symfile_segment_data (so->abfd);
433759f7 370
1fddbabb
PA
371 if (data == NULL)
372 warning (_("\
373Could not relocate shared library \"%s\": no segments"), so->so_name);
374 else
375 {
376 ULONGEST orig_delta;
377 int i;
1fddbabb 378
62982abd 379 if (!symfile_map_offsets_to_segments (so->abfd, data.get (),
6a053cb1 380 li->offsets,
d17f7b36
SM
381 li->segment_bases.size (),
382 li->segment_bases.data ()))
1fddbabb
PA
383 warning (_("\
384Could not relocate shared library \"%s\": bad offsets"), so->so_name);
385
386 /* Find the range of addresses to report for this library in
387 "info sharedlibrary". Report any consecutive segments
388 which were relocated as a single unit. */
d17f7b36 389 gdb_assert (li->segment_bases.size () > 0);
68b888ff 390 orig_delta = li->segment_bases[0] - data->segments[0].base;
1fddbabb 391
68b888ff 392 for (i = 1; i < data->segments.size (); i++)
1fddbabb
PA
393 {
394 /* If we have run out of offsets, assume all
395 remaining segments have the same offset. */
d17f7b36 396 if (i >= li->segment_bases.size ())
1fddbabb
PA
397 continue;
398
399 /* If this segment does not have the same offset, do
400 not include it in the library's range. */
68b888ff 401 if (li->segment_bases[i] - data->segments[i].base
d17f7b36 402 != orig_delta)
1fddbabb
PA
403 break;
404 }
405
d17f7b36 406 so->addr_low = li->segment_bases[0];
68b888ff
SM
407 so->addr_high = (data->segments[i - 1].base
408 + data->segments[i - 1].size
1fddbabb
PA
409 + orig_delta);
410 gdb_assert (so->addr_low <= so->addr_high);
cfa9d6d9 411 }
cfa9d6d9
DJ
412 }
413 }
414
6a053cb1
TT
415 offset = li->offsets[gdb_bfd_section_index (sec->the_bfd_section->owner,
416 sec->the_bfd_section)];
cfa9d6d9
DJ
417 sec->addr += offset;
418 sec->endaddr += offset;
419}
420
421static int
bf469271 422solib_target_open_symbol_file_object (int from_tty)
cfa9d6d9
DJ
423{
424 /* We can't locate the main symbol file based on the target's
425 knowledge; the user has to specify it. */
426 return 0;
427}
428
429static int
430solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
431{
432 /* We don't have a range of addresses for the dynamic linker; there
433 may not be one in the program's address space. So only report
434 PLT entries (which may be import stubs). */
3e5d3a5a 435 return in_plt_section (pc);
cfa9d6d9
DJ
436}
437
8d465389 438struct target_so_ops solib_target_so_ops;
cfa9d6d9 439
6c265988 440void _initialize_solib_target ();
cfa9d6d9 441void
6c265988 442_initialize_solib_target ()
cfa9d6d9
DJ
443{
444 solib_target_so_ops.relocate_section_addresses
445 = solib_target_relocate_section_addresses;
446 solib_target_so_ops.free_so = solib_target_free_so;
447 solib_target_so_ops.clear_solib = solib_target_clear_solib;
448 solib_target_so_ops.solib_create_inferior_hook
449 = solib_target_solib_create_inferior_hook;
cfa9d6d9
DJ
450 solib_target_so_ops.current_sos = solib_target_current_sos;
451 solib_target_so_ops.open_symbol_file_object
452 = solib_target_open_symbol_file_object;
453 solib_target_so_ops.in_dynsym_resolve_code
454 = solib_target_in_dynsym_resolve_code;
831a0c44 455 solib_target_so_ops.bfd_open = solib_bfd_open;
98d64339
PA
456
457 /* Set current_target_so_ops to solib_target_so_ops if not already
458 set. */
459 if (current_target_so_ops == 0)
460 current_target_so_ops = &solib_target_so_ops;
cfa9d6d9 461}
This page took 1.540374 seconds and 4 git commands to generate.