Change section_offsets to a std::vector
[deliverable/binutils-gdb.git] / gdb / solib-target.c
CommitLineData
cfa9d6d9
DJ
1/* Definitions for targets which report shared library events.
2
b811d2c2 3 Copyright (C) 2007-2020 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>
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. */
51046d9e 34 std::string name;
cfa9d6d9 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. */
f2f46dfc 41 std::vector<CORE_ADDR> segment_bases;
cfa9d6d9 42
1fddbabb
PA
43 /* The base addresses for each independently allocatable,
44 relocatable section of this shared library. */
f2f46dfc 45 std::vector<CORE_ADDR> section_bases;
1fddbabb 46
cfa9d6d9 47 /* The cached offsets for each section of this shared library,
1fddbabb 48 determined from SEGMENT_BASES, or SECTION_BASES. */
6a053cb1 49 section_offsets offsets;
cfa9d6d9
DJ
50};
51
776489e0 52typedef std::vector<std::unique_ptr<lm_info_target>> lm_info_vector;
cfa9d6d9
DJ
53
54#if !defined(HAVE_LIBEXPAT)
55
776489e0 56static lm_info_vector
cfa9d6d9
DJ
57solib_target_parse_libraries (const char *library)
58{
59 static int have_warned;
60
61 if (!have_warned)
62 {
63 have_warned = 1;
64 warning (_("Can not parse XML library list; XML support was disabled "
65 "at compile time"));
66 }
67
776489e0 68 return lm_info_vector ();
cfa9d6d9
DJ
69}
70
71#else /* HAVE_LIBEXPAT */
72
73#include "xml-support.h"
74
75/* Handle the start of a <segment> element. */
76
77static void
78library_list_start_segment (struct gdb_xml_parser *parser,
79 const struct gdb_xml_element *element,
4d0fdd9b
SM
80 void *user_data,
81 std::vector<gdb_xml_value> &attributes)
cfa9d6d9 82{
776489e0
TT
83 lm_info_vector *list = (lm_info_vector *) user_data;
84 lm_info_target *last = list->back ().get ();
19ba03f4 85 ULONGEST *address_p
4d0fdd9b 86 = (ULONGEST *) xml_find_attribute (attributes, "address")->value.get ();
358eb95e 87 CORE_ADDR address = (CORE_ADDR) *address_p;
cfa9d6d9 88
f2f46dfc 89 if (!last->section_bases.empty ())
1fddbabb
PA
90 gdb_xml_error (parser,
91 _("Library list with both segments and sections"));
92
f2f46dfc 93 last->segment_bases.push_back (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,
4d0fdd9b
SM
99 void *user_data,
100 std::vector<gdb_xml_value> &attributes)
1fddbabb 101{
776489e0
TT
102 lm_info_vector *list = (lm_info_vector *) user_data;
103 lm_info_target *last = list->back ().get ();
19ba03f4 104 ULONGEST *address_p
4d0fdd9b 105 = (ULONGEST *) xml_find_attribute (attributes, "address")->value.get ();
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,
4d0fdd9b
SM
120 void *user_data,
121 std::vector<gdb_xml_value> &attributes)
cfa9d6d9 122{
776489e0 123 lm_info_vector *list = (lm_info_vector *) user_data;
51046d9e 124 lm_info_target *item = new lm_info_target;
2f667667 125 item->name
4d0fdd9b 126 = (const char *) xml_find_attribute (attributes, "name")->value.get ();
cfa9d6d9 127
776489e0 128 list->emplace_back (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{
776489e0
TT
136 lm_info_vector *list = (lm_info_vector *) user_data;
137 lm_info_target *lm_info = list->back ().get ();
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,
4d0fdd9b
SM
149 void *user_data,
150 std::vector<gdb_xml_value> &attributes)
cfa9d6d9 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 {
4d0fdd9b 157 const char *string = (const char *) version->value.get ();
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
cfa9d6d9
DJ
166/* The allowed elements and attributes for an XML library list.
167 The root element is a <library-list>. */
168
d6c10e95 169static const struct gdb_xml_attribute segment_attributes[] = {
cfa9d6d9
DJ
170 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
171 { NULL, GDB_XML_AF_NONE, NULL, NULL }
172};
173
d6c10e95 174static const struct gdb_xml_attribute section_attributes[] = {
1fddbabb
PA
175 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
176 { NULL, GDB_XML_AF_NONE, NULL, NULL }
177};
178
d6c10e95 179static const struct gdb_xml_element library_children[] = {
1fddbabb
PA
180 { "segment", segment_attributes, NULL,
181 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
cfa9d6d9 182 library_list_start_segment, NULL },
1fddbabb
PA
183 { "section", section_attributes, NULL,
184 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
185 library_list_start_section, NULL },
cfa9d6d9
DJ
186 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
187};
188
d6c10e95 189static const struct gdb_xml_attribute library_attributes[] = {
cfa9d6d9
DJ
190 { "name", GDB_XML_AF_NONE, NULL, NULL },
191 { NULL, GDB_XML_AF_NONE, NULL, NULL }
192};
193
d6c10e95 194static const struct gdb_xml_element library_list_children[] = {
cfa9d6d9
DJ
195 { "library", library_attributes, library_children,
196 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
1fddbabb 197 library_list_start_library, library_list_end_library },
cfa9d6d9
DJ
198 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
199};
200
d6c10e95 201static const struct gdb_xml_attribute library_list_attributes[] = {
24c05f46 202 { "version", GDB_XML_AF_OPTIONAL, NULL, NULL },
cfa9d6d9
DJ
203 { NULL, GDB_XML_AF_NONE, NULL, NULL }
204};
205
d6c10e95 206static const struct gdb_xml_element library_list_elements[] = {
cfa9d6d9
DJ
207 { "library-list", library_list_attributes, library_list_children,
208 GDB_XML_EF_NONE, library_list_start_list, NULL },
209 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
210};
211
776489e0 212static lm_info_vector
cfa9d6d9
DJ
213solib_target_parse_libraries (const char *library)
214{
776489e0 215 lm_info_vector result;
cfa9d6d9 216
efc0eabd
PA
217 if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd",
218 library_list_elements, library, &result) == 0)
219 {
776489e0 220 /* Parsed successfully. */
efc0eabd
PA
221 return result;
222 }
cfa9d6d9 223
776489e0
TT
224 result.clear ();
225 return result;
cfa9d6d9
DJ
226}
227#endif
228
229static struct so_list *
230solib_target_current_sos (void)
231{
232 struct so_list *new_solib, *start = NULL, *last = NULL;
cfa9d6d9
DJ
233
234 /* Fetch the list of shared libraries. */
9018be22 235 gdb::optional<gdb::char_vector> library_document
8b88a78e
PA
236 = target_read_stralloc (current_top_target (), TARGET_OBJECT_LIBRARIES,
237 NULL);
9018be22 238 if (!library_document)
cfa9d6d9
DJ
239 return NULL;
240
241 /* Parse the list. */
776489e0
TT
242 lm_info_vector library_list
243 = solib_target_parse_libraries (library_document->data ());
b25d79d4 244
776489e0 245 if (library_list.empty ())
cfa9d6d9
DJ
246 return NULL;
247
248 /* Build a struct so_list for each entry on the list. */
776489e0 249 for (auto &&info : library_list)
cfa9d6d9 250 {
41bf6aca 251 new_solib = XCNEW (struct so_list);
51046d9e
SM
252 strncpy (new_solib->so_name, info->name.c_str (),
253 SO_NAME_MAX_PATH_SIZE - 1);
cfa9d6d9 254 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
51046d9e 255 strncpy (new_solib->so_original_name, info->name.c_str (),
cfa9d6d9
DJ
256 SO_NAME_MAX_PATH_SIZE - 1);
257 new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
cfa9d6d9
DJ
258
259 /* We no longer need this copy of the name. */
51046d9e 260 info->name.clear ();
cfa9d6d9 261
776489e0
TT
262 new_solib->lm_info = info.release ();
263
cfa9d6d9
DJ
264 /* Add it to the list. */
265 if (!start)
266 last = start = new_solib;
267 else
268 {
269 last->next = new_solib;
270 last = new_solib;
271 }
272 }
273
cfa9d6d9
DJ
274 return start;
275}
276
cfa9d6d9 277static void
268a4a75 278solib_target_solib_create_inferior_hook (int from_tty)
cfa9d6d9
DJ
279{
280 /* Nothing needed. */
281}
282
283static void
284solib_target_clear_solib (void)
285{
286 /* Nothing needed. */
287}
288
289static void
290solib_target_free_so (struct so_list *so)
291{
d0e449a1
SM
292 lm_info_target *li = (lm_info_target *) so->lm_info;
293
51046d9e
SM
294 gdb_assert (li->name.empty ());
295
296 delete li;
cfa9d6d9
DJ
297}
298
299static void
300solib_target_relocate_section_addresses (struct so_list *so,
0542c86d 301 struct target_section *sec)
cfa9d6d9 302{
cfa9d6d9 303 CORE_ADDR offset;
d0e449a1 304 lm_info_target *li = (lm_info_target *) so->lm_info;
cfa9d6d9
DJ
305
306 /* Build the offset table only once per object file. We can not do
307 it any earlier, since we need to open the file first. */
6a053cb1 308 if (li->offsets.empty ())
cfa9d6d9 309 {
d445b2f6 310 int num_sections = gdb_bfd_count_sections (so->abfd);
cfa9d6d9 311
6a053cb1 312 li->offsets.assign (num_sections, 0);
cfa9d6d9 313
f2f46dfc 314 if (!li->section_bases.empty ())
cfa9d6d9 315 {
cfa9d6d9 316 int i;
1fddbabb 317 asection *sect;
1fddbabb
PA
318 int num_alloc_sections = 0;
319
320 for (i = 0, sect = so->abfd->sections;
321 sect != NULL;
322 i++, sect = sect->next)
fd361982 323 if ((bfd_section_flags (sect) & SEC_ALLOC))
1fddbabb
PA
324 num_alloc_sections++;
325
d17f7b36 326 if (num_alloc_sections != li->section_bases.size ())
1fddbabb
PA
327 warning (_("\
328Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
cfa9d6d9 329 so->so_name);
1fddbabb 330 else
cfa9d6d9 331 {
1fddbabb
PA
332 int bases_index = 0;
333 int found_range = 0;
1fddbabb
PA
334
335 so->addr_low = ~(CORE_ADDR) 0;
336 so->addr_high = 0;
337 for (i = 0, sect = so->abfd->sections;
338 sect != NULL;
339 i++, sect = sect->next)
340 {
fd361982 341 if (!(bfd_section_flags (sect) & SEC_ALLOC))
1fddbabb 342 continue;
fd361982 343 if (bfd_section_size (sect) > 0)
1fddbabb
PA
344 {
345 CORE_ADDR low, high;
433759f7 346
f2f46dfc 347 low = li->section_bases[i];
fd361982 348 high = low + bfd_section_size (sect) - 1;
1fddbabb
PA
349
350 if (low < so->addr_low)
351 so->addr_low = low;
352 if (high > so->addr_high)
353 so->addr_high = high;
354 gdb_assert (so->addr_low <= so->addr_high);
355 found_range = 1;
356 }
6a053cb1 357 li->offsets[i] = li->section_bases[bases_index];
1fddbabb
PA
358 bases_index++;
359 }
360 if (!found_range)
361 so->addr_low = so->addr_high = 0;
362 gdb_assert (so->addr_low <= so->addr_high);
363 }
364 }
f2f46dfc 365 else if (!li->segment_bases.empty ())
1fddbabb
PA
366 {
367 struct symfile_segment_data *data;
433759f7 368
1fddbabb
PA
369 data = get_symfile_segment_data (so->abfd);
370 if (data == NULL)
371 warning (_("\
372Could not relocate shared library \"%s\": no segments"), so->so_name);
373 else
374 {
375 ULONGEST orig_delta;
376 int i;
1fddbabb 377
44f81a76 378 if (!symfile_map_offsets_to_segments (so->abfd, data,
6a053cb1 379 li->offsets,
d17f7b36
SM
380 li->segment_bases.size (),
381 li->segment_bases.data ()))
1fddbabb
PA
382 warning (_("\
383Could not relocate shared library \"%s\": bad offsets"), so->so_name);
384
385 /* Find the range of addresses to report for this library in
386 "info sharedlibrary". Report any consecutive segments
387 which were relocated as a single unit. */
d17f7b36
SM
388 gdb_assert (li->segment_bases.size () > 0);
389 orig_delta = li->segment_bases[0] - data->segment_bases[0];
1fddbabb
PA
390
391 for (i = 1; i < data->num_segments; i++)
392 {
393 /* If we have run out of offsets, assume all
394 remaining segments have the same offset. */
d17f7b36 395 if (i >= li->segment_bases.size ())
1fddbabb
PA
396 continue;
397
398 /* If this segment does not have the same offset, do
399 not include it in the library's range. */
d17f7b36
SM
400 if (li->segment_bases[i] - data->segment_bases[i]
401 != orig_delta)
1fddbabb
PA
402 break;
403 }
404
d17f7b36 405 so->addr_low = li->segment_bases[0];
1fddbabb
PA
406 so->addr_high = (data->segment_bases[i - 1]
407 + data->segment_sizes[i - 1]
408 + orig_delta);
409 gdb_assert (so->addr_low <= so->addr_high);
410
411 free_symfile_segment_data (data);
cfa9d6d9 412 }
cfa9d6d9
DJ
413 }
414 }
415
6a053cb1
TT
416 offset = li->offsets[gdb_bfd_section_index (sec->the_bfd_section->owner,
417 sec->the_bfd_section)];
cfa9d6d9
DJ
418 sec->addr += offset;
419 sec->endaddr += offset;
420}
421
422static int
bf469271 423solib_target_open_symbol_file_object (int from_tty)
cfa9d6d9
DJ
424{
425 /* We can't locate the main symbol file based on the target's
426 knowledge; the user has to specify it. */
427 return 0;
428}
429
430static int
431solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
432{
433 /* We don't have a range of addresses for the dynamic linker; there
434 may not be one in the program's address space. So only report
435 PLT entries (which may be import stubs). */
3e5d3a5a 436 return in_plt_section (pc);
cfa9d6d9
DJ
437}
438
8d465389 439struct target_so_ops solib_target_so_ops;
cfa9d6d9 440
cfa9d6d9
DJ
441void
442_initialize_solib_target (void)
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.355193 seconds and 4 git commands to generate.