Replace "the the" with "the"
[deliverable/binutils-gdb.git] / gdb / solib-target.c
CommitLineData
cfa9d6d9
DJ
1/* Definitions for targets which report shared library events.
2
42a4f53d 3 Copyright (C) 2007-2019 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,
4d0fdd9b
SM
82 void *user_data,
83 std::vector<gdb_xml_value> &attributes)
cfa9d6d9 84{
d0e449a1
SM
85 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
86 lm_info_target *last = VEC_last (lm_info_target_p, *list);
19ba03f4 87 ULONGEST *address_p
4d0fdd9b 88 = (ULONGEST *) xml_find_attribute (attributes, "address")->value.get ();
358eb95e 89 CORE_ADDR address = (CORE_ADDR) *address_p;
cfa9d6d9 90
f2f46dfc 91 if (!last->section_bases.empty ())
1fddbabb
PA
92 gdb_xml_error (parser,
93 _("Library list with both segments and sections"));
94
f2f46dfc 95 last->segment_bases.push_back (address);
cfa9d6d9
DJ
96}
97
1fddbabb
PA
98static void
99library_list_start_section (struct gdb_xml_parser *parser,
100 const struct gdb_xml_element *element,
4d0fdd9b
SM
101 void *user_data,
102 std::vector<gdb_xml_value> &attributes)
1fddbabb 103{
d0e449a1
SM
104 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
105 lm_info_target *last = VEC_last (lm_info_target_p, *list);
19ba03f4 106 ULONGEST *address_p
4d0fdd9b 107 = (ULONGEST *) xml_find_attribute (attributes, "address")->value.get ();
1fddbabb
PA
108 CORE_ADDR address = (CORE_ADDR) *address_p;
109
f2f46dfc 110 if (!last->segment_bases.empty ())
1fddbabb
PA
111 gdb_xml_error (parser,
112 _("Library list with both segments and sections"));
113
f2f46dfc 114 last->section_bases.push_back (address);
1fddbabb
PA
115}
116
cfa9d6d9
DJ
117/* Handle the start of a <library> element. */
118
119static void
120library_list_start_library (struct gdb_xml_parser *parser,
121 const struct gdb_xml_element *element,
4d0fdd9b
SM
122 void *user_data,
123 std::vector<gdb_xml_value> &attributes)
cfa9d6d9 124{
d0e449a1 125 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
51046d9e 126 lm_info_target *item = new lm_info_target;
2f667667 127 item->name
4d0fdd9b 128 = (const char *) xml_find_attribute (attributes, "name")->value.get ();
cfa9d6d9 129
d0e449a1 130 VEC_safe_push (lm_info_target_p, *list, item);
cfa9d6d9
DJ
131}
132
1fddbabb
PA
133static void
134library_list_end_library (struct gdb_xml_parser *parser,
135 const struct gdb_xml_element *element,
136 void *user_data, const char *body_text)
137{
d0e449a1
SM
138 VEC(lm_info_target_p) **list = (VEC(lm_info_target_p) **) user_data;
139 lm_info_target *lm_info = VEC_last (lm_info_target_p, *list);
433759f7 140
f2f46dfc
SM
141 if (lm_info->segment_bases.empty () && lm_info->section_bases.empty ())
142 gdb_xml_error (parser, _("No segment or section bases defined"));
1fddbabb
PA
143}
144
145
cfa9d6d9
DJ
146/* Handle the start of a <library-list> element. */
147
148static void
149library_list_start_list (struct gdb_xml_parser *parser,
150 const struct gdb_xml_element *element,
4d0fdd9b
SM
151 void *user_data,
152 std::vector<gdb_xml_value> &attributes)
cfa9d6d9 153{
24c05f46 154 struct gdb_xml_value *version = xml_find_attribute (attributes, "version");
cfa9d6d9 155
24c05f46 156 /* #FIXED attribute may be omitted, Expat returns NULL in such case. */
8847cac2 157 if (version != NULL)
24c05f46 158 {
4d0fdd9b 159 const char *string = (const char *) version->value.get ();
24c05f46
JK
160
161 if (strcmp (string, "1.0") != 0)
162 gdb_xml_error (parser,
163 _("Library list has unsupported version \"%s\""),
21047726 164 string);
24c05f46 165 }
cfa9d6d9
DJ
166}
167
168/* Discard the constructed library list. */
169
170static void
171solib_target_free_library_list (void *p)
172{
d0e449a1
SM
173 VEC(lm_info_target_p) **result = (VEC(lm_info_target_p) **) p;
174 lm_info_target *info;
cfa9d6d9
DJ
175 int ix;
176
d0e449a1 177 for (ix = 0; VEC_iterate (lm_info_target_p, *result, ix, info); ix++)
51046d9e
SM
178 delete info;
179
d0e449a1 180 VEC_free (lm_info_target_p, *result);
cfa9d6d9
DJ
181 *result = NULL;
182}
183
184/* The allowed elements and attributes for an XML library list.
185 The root element is a <library-list>. */
186
d6c10e95 187static const struct gdb_xml_attribute segment_attributes[] = {
cfa9d6d9
DJ
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_attribute section_attributes[] = {
1fddbabb
PA
193 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
194 { NULL, GDB_XML_AF_NONE, NULL, NULL }
195};
196
d6c10e95 197static const struct gdb_xml_element library_children[] = {
1fddbabb
PA
198 { "segment", segment_attributes, NULL,
199 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
cfa9d6d9 200 library_list_start_segment, NULL },
1fddbabb
PA
201 { "section", section_attributes, NULL,
202 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
203 library_list_start_section, NULL },
cfa9d6d9
DJ
204 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
205};
206
d6c10e95 207static const struct gdb_xml_attribute library_attributes[] = {
cfa9d6d9
DJ
208 { "name", GDB_XML_AF_NONE, NULL, NULL },
209 { NULL, GDB_XML_AF_NONE, NULL, NULL }
210};
211
d6c10e95 212static const struct gdb_xml_element library_list_children[] = {
cfa9d6d9
DJ
213 { "library", library_attributes, library_children,
214 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
1fddbabb 215 library_list_start_library, library_list_end_library },
cfa9d6d9
DJ
216 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
217};
218
d6c10e95 219static const struct gdb_xml_attribute library_list_attributes[] = {
24c05f46 220 { "version", GDB_XML_AF_OPTIONAL, NULL, NULL },
cfa9d6d9
DJ
221 { NULL, GDB_XML_AF_NONE, NULL, NULL }
222};
223
d6c10e95 224static const struct gdb_xml_element library_list_elements[] = {
cfa9d6d9
DJ
225 { "library-list", library_list_attributes, library_list_children,
226 GDB_XML_EF_NONE, library_list_start_list, NULL },
227 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
228};
229
d0e449a1 230static VEC(lm_info_target_p) *
cfa9d6d9
DJ
231solib_target_parse_libraries (const char *library)
232{
d0e449a1 233 VEC(lm_info_target_p) *result = NULL;
efc0eabd
PA
234 struct cleanup *back_to = make_cleanup (solib_target_free_library_list,
235 &result);
cfa9d6d9 236
efc0eabd
PA
237 if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd",
238 library_list_elements, library, &result) == 0)
239 {
240 /* Parsed successfully, keep the result. */
241 discard_cleanups (back_to);
242 return result;
243 }
cfa9d6d9
DJ
244
245 do_cleanups (back_to);
efc0eabd 246 return NULL;
cfa9d6d9
DJ
247}
248#endif
249
250static struct so_list *
251solib_target_current_sos (void)
252{
253 struct so_list *new_solib, *start = NULL, *last = NULL;
d0e449a1
SM
254 VEC(lm_info_target_p) *library_list;
255 lm_info_target *info;
cfa9d6d9
DJ
256 int ix;
257
258 /* Fetch the list of shared libraries. */
9018be22 259 gdb::optional<gdb::char_vector> library_document
8b88a78e
PA
260 = target_read_stralloc (current_top_target (), TARGET_OBJECT_LIBRARIES,
261 NULL);
9018be22 262 if (!library_document)
cfa9d6d9
DJ
263 return NULL;
264
265 /* Parse the list. */
9018be22 266 library_list = solib_target_parse_libraries (library_document->data ());
b25d79d4 267
cfa9d6d9
DJ
268 if (library_list == NULL)
269 return NULL;
270
271 /* Build a struct so_list for each entry on the list. */
d0e449a1 272 for (ix = 0; VEC_iterate (lm_info_target_p, library_list, ix, info); ix++)
cfa9d6d9 273 {
41bf6aca 274 new_solib = XCNEW (struct so_list);
51046d9e
SM
275 strncpy (new_solib->so_name, info->name.c_str (),
276 SO_NAME_MAX_PATH_SIZE - 1);
cfa9d6d9 277 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
51046d9e 278 strncpy (new_solib->so_original_name, info->name.c_str (),
cfa9d6d9
DJ
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. */
51046d9e 284 info->name.clear ();
cfa9d6d9
DJ
285
286 /* Add it to the list. */
287 if (!start)
288 last = start = new_solib;
289 else
290 {
291 last->next = new_solib;
292 last = new_solib;
293 }
294 }
295
296 /* Free the library list, but not its members. */
d0e449a1 297 VEC_free (lm_info_target_p, library_list);
cfa9d6d9
DJ
298
299 return start;
300}
301
cfa9d6d9 302static void
268a4a75 303solib_target_solib_create_inferior_hook (int from_tty)
cfa9d6d9
DJ
304{
305 /* Nothing needed. */
306}
307
308static void
309solib_target_clear_solib (void)
310{
311 /* Nothing needed. */
312}
313
314static void
315solib_target_free_so (struct so_list *so)
316{
d0e449a1
SM
317 lm_info_target *li = (lm_info_target *) so->lm_info;
318
51046d9e
SM
319 gdb_assert (li->name.empty ());
320
321 delete li;
cfa9d6d9
DJ
322}
323
324static void
325solib_target_relocate_section_addresses (struct so_list *so,
0542c86d 326 struct target_section *sec)
cfa9d6d9 327{
cfa9d6d9 328 CORE_ADDR offset;
d0e449a1 329 lm_info_target *li = (lm_info_target *) so->lm_info;
cfa9d6d9
DJ
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. */
d0e449a1 333 if (li->offsets == NULL)
cfa9d6d9 334 {
d445b2f6 335 int num_sections = gdb_bfd_count_sections (so->abfd);
cfa9d6d9 336
d0e449a1 337 li->offsets
224c3ddb
SM
338 = ((struct section_offsets *)
339 xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections)));
cfa9d6d9 340
f2f46dfc 341 if (!li->section_bases.empty ())
cfa9d6d9 342 {
cfa9d6d9 343 int i;
1fddbabb 344 asection *sect;
1fddbabb
PA
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
d17f7b36 353 if (num_alloc_sections != li->section_bases.size ())
1fddbabb
PA
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;
1fddbabb
PA
361
362 so->addr_low = ~(CORE_ADDR) 0;
363 so->addr_high = 0;
364 for (i = 0, sect = so->abfd->sections;
365 sect != NULL;
366 i++, sect = sect->next)
367 {
368 if (!(bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
369 continue;
370 if (bfd_section_size (so->abfd, sect) > 0)
371 {
372 CORE_ADDR low, high;
433759f7 373
f2f46dfc 374 low = li->section_bases[i];
1fddbabb
PA
375 high = low + bfd_section_size (so->abfd, sect) - 1;
376
377 if (low < so->addr_low)
378 so->addr_low = low;
379 if (high > so->addr_high)
380 so->addr_high = high;
381 gdb_assert (so->addr_low <= so->addr_high);
382 found_range = 1;
383 }
f2f46dfc 384 li->offsets->offsets[i] = li->section_bases[bases_index];
1fddbabb
PA
385 bases_index++;
386 }
387 if (!found_range)
388 so->addr_low = so->addr_high = 0;
389 gdb_assert (so->addr_low <= so->addr_high);
390 }
391 }
f2f46dfc 392 else if (!li->segment_bases.empty ())
1fddbabb
PA
393 {
394 struct symfile_segment_data *data;
433759f7 395
1fddbabb
PA
396 data = get_symfile_segment_data (so->abfd);
397 if (data == NULL)
398 warning (_("\
399Could not relocate shared library \"%s\": no segments"), so->so_name);
400 else
401 {
402 ULONGEST orig_delta;
403 int i;
1fddbabb 404
d0e449a1 405 if (!symfile_map_offsets_to_segments (so->abfd, data, li->offsets,
d17f7b36
SM
406 li->segment_bases.size (),
407 li->segment_bases.data ()))
1fddbabb
PA
408 warning (_("\
409Could not relocate shared library \"%s\": bad offsets"), so->so_name);
410
411 /* Find the range of addresses to report for this library in
412 "info sharedlibrary". Report any consecutive segments
413 which were relocated as a single unit. */
d17f7b36
SM
414 gdb_assert (li->segment_bases.size () > 0);
415 orig_delta = li->segment_bases[0] - data->segment_bases[0];
1fddbabb
PA
416
417 for (i = 1; i < data->num_segments; i++)
418 {
419 /* If we have run out of offsets, assume all
420 remaining segments have the same offset. */
d17f7b36 421 if (i >= li->segment_bases.size ())
1fddbabb
PA
422 continue;
423
424 /* If this segment does not have the same offset, do
425 not include it in the library's range. */
d17f7b36
SM
426 if (li->segment_bases[i] - data->segment_bases[i]
427 != orig_delta)
1fddbabb
PA
428 break;
429 }
430
d17f7b36 431 so->addr_low = li->segment_bases[0];
1fddbabb
PA
432 so->addr_high = (data->segment_bases[i - 1]
433 + data->segment_sizes[i - 1]
434 + orig_delta);
435 gdb_assert (so->addr_low <= so->addr_high);
436
437 free_symfile_segment_data (data);
cfa9d6d9 438 }
cfa9d6d9
DJ
439 }
440 }
441
d0e449a1
SM
442 offset = li->offsets->offsets[gdb_bfd_section_index
443 (sec->the_bfd_section->owner,
444 sec->the_bfd_section)];
cfa9d6d9
DJ
445 sec->addr += offset;
446 sec->endaddr += offset;
447}
448
449static int
bf469271 450solib_target_open_symbol_file_object (int from_tty)
cfa9d6d9
DJ
451{
452 /* We can't locate the main symbol file based on the target's
453 knowledge; the user has to specify it. */
454 return 0;
455}
456
457static int
458solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
459{
460 /* We don't have a range of addresses for the dynamic linker; there
461 may not be one in the program's address space. So only report
462 PLT entries (which may be import stubs). */
3e5d3a5a 463 return in_plt_section (pc);
cfa9d6d9
DJ
464}
465
8d465389 466struct target_so_ops solib_target_so_ops;
cfa9d6d9 467
cfa9d6d9
DJ
468void
469_initialize_solib_target (void)
470{
471 solib_target_so_ops.relocate_section_addresses
472 = solib_target_relocate_section_addresses;
473 solib_target_so_ops.free_so = solib_target_free_so;
474 solib_target_so_ops.clear_solib = solib_target_clear_solib;
475 solib_target_so_ops.solib_create_inferior_hook
476 = solib_target_solib_create_inferior_hook;
cfa9d6d9
DJ
477 solib_target_so_ops.current_sos = solib_target_current_sos;
478 solib_target_so_ops.open_symbol_file_object
479 = solib_target_open_symbol_file_object;
480 solib_target_so_ops.in_dynsym_resolve_code
481 = solib_target_in_dynsym_resolve_code;
831a0c44 482 solib_target_so_ops.bfd_open = solib_bfd_open;
98d64339
PA
483
484 /* Set current_target_so_ops to solib_target_so_ops if not already
485 set. */
486 if (current_target_so_ops == 0)
487 current_target_so_ops = &solib_target_so_ops;
cfa9d6d9 488}
This page took 1.458922 seconds and 4 git commands to generate.