]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/solib-target.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / solib-target.c
CommitLineData
cfa9d6d9
DJ
1/* Definitions for targets which report shared library events.
2
1d506c26 3 Copyright (C) 2007-2024 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. */
e3b63a79 31struct lm_info_target final : public lm_info
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
1c0dfccb 53using lm_info_target_up = std::unique_ptr<lm_info_target>;
cfa9d6d9
DJ
54
55#if !defined(HAVE_LIBEXPAT)
56
f005ccb4 57static std::vector<lm_info_target_up>
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
f005ccb4 69 return {};
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{
1c0dfccb 84 auto *list = (std::vector<lm_info_target_up> *) user_data;
776489e0 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{
1c0dfccb 103 auto *list = (std::vector<lm_info_target_up> *) user_data;
776489e0 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{
1c0dfccb 124 auto *list = (std::vector<lm_info_target_up> *) 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{
1c0dfccb 137 auto *list = (std::vector<lm_info_target_up> *) user_data;
776489e0 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
1c0dfccb 213static std::vector<lm_info_target_up>
cfa9d6d9
DJ
214solib_target_parse_libraries (const char *library)
215{
1c0dfccb 216 std::vector<lm_info_target_up> 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
3fe0dfd1 230static intrusive_list<shobj>
cfa9d6d9
DJ
231solib_target_current_sos (void)
232{
3fe0dfd1 233 intrusive_list<shobj> sos;
cfa9d6d9
DJ
234
235 /* Fetch the list of shared libraries. */
6b09f134 236 std::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)
8971d278 240 return {};
cfa9d6d9
DJ
241
242 /* Parse the list. */
1c0dfccb 243 std::vector<lm_info_target_up> library_list
776489e0 244 = solib_target_parse_libraries (library_document->data ());
b25d79d4 245
3fe0dfd1 246 /* Build a struct shobj for each entry on the list. */
1c0dfccb 247 for (lm_info_target_up &info : library_list)
cfa9d6d9 248 {
3fe0dfd1 249 shobj *new_solib = new shobj;
cfa9d6d9 250
98107b0b
SM
251 /* We don't need a copy of the name in INFO anymore. */
252 new_solib->so_name = std::move (info->name);
253 new_solib->so_original_name = new_solib->so_name;
7ad0a42e 254 new_solib->lm_info = std::move (info);
776489e0 255
cfa9d6d9 256 /* Add it to the list. */
8971d278 257 sos.push_back (*new_solib);
cfa9d6d9
DJ
258 }
259
8971d278 260 return sos;
cfa9d6d9
DJ
261}
262
cfa9d6d9 263static void
268a4a75 264solib_target_solib_create_inferior_hook (int from_tty)
cfa9d6d9
DJ
265{
266 /* Nothing needed. */
267}
268
cfa9d6d9 269static void
3fe0dfd1 270solib_target_relocate_section_addresses (shobj &so, target_section *sec)
cfa9d6d9 271{
cfa9d6d9 272 CORE_ADDR offset;
7ad0a42e 273 auto *li = gdb::checked_static_cast<lm_info_target *> (so.lm_info.get ());
cfa9d6d9
DJ
274
275 /* Build the offset table only once per object file. We can not do
276 it any earlier, since we need to open the file first. */
6a053cb1 277 if (li->offsets.empty ())
cfa9d6d9 278 {
200b8563 279 int num_sections = gdb_bfd_count_sections (so.abfd.get ());
cfa9d6d9 280
6a053cb1 281 li->offsets.assign (num_sections, 0);
cfa9d6d9 282
f2f46dfc 283 if (!li->section_bases.empty ())
cfa9d6d9 284 {
cfa9d6d9 285 int i;
1fddbabb 286 asection *sect;
1fddbabb
PA
287 int num_alloc_sections = 0;
288
bb86ab83 289 for (i = 0, sect = so.abfd->sections;
1fddbabb
PA
290 sect != NULL;
291 i++, sect = sect->next)
fd361982 292 if ((bfd_section_flags (sect) & SEC_ALLOC))
1fddbabb
PA
293 num_alloc_sections++;
294
d17f7b36 295 if (num_alloc_sections != li->section_bases.size ())
1fddbabb
PA
296 warning (_("\
297Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
98107b0b 298 so.so_name.c_str ());
1fddbabb 299 else
cfa9d6d9 300 {
1fddbabb
PA
301 int bases_index = 0;
302 int found_range = 0;
1fddbabb 303
bb86ab83
SM
304 so.addr_low = ~(CORE_ADDR) 0;
305 so.addr_high = 0;
306 for (i = 0, sect = so.abfd->sections;
1fddbabb
PA
307 sect != NULL;
308 i++, sect = sect->next)
309 {
fd361982 310 if (!(bfd_section_flags (sect) & SEC_ALLOC))
1fddbabb 311 continue;
fd361982 312 if (bfd_section_size (sect) > 0)
1fddbabb
PA
313 {
314 CORE_ADDR low, high;
433759f7 315
f2f46dfc 316 low = li->section_bases[i];
fd361982 317 high = low + bfd_section_size (sect) - 1;
1fddbabb 318
bb86ab83
SM
319 if (low < so.addr_low)
320 so.addr_low = low;
321 if (high > so.addr_high)
322 so.addr_high = high;
323 gdb_assert (so.addr_low <= so.addr_high);
1fddbabb
PA
324 found_range = 1;
325 }
6a053cb1 326 li->offsets[i] = li->section_bases[bases_index];
1fddbabb
PA
327 bases_index++;
328 }
329 if (!found_range)
bb86ab83
SM
330 so.addr_low = so.addr_high = 0;
331 gdb_assert (so.addr_low <= so.addr_high);
1fddbabb
PA
332 }
333 }
f2f46dfc 334 else if (!li->segment_bases.empty ())
1fddbabb 335 {
62982abd 336 symfile_segment_data_up data
200b8563 337 = get_symfile_segment_data (so.abfd.get ());
433759f7 338
1fddbabb
PA
339 if (data == NULL)
340 warning (_("\
98107b0b 341Could not relocate shared library \"%s\": no segments"), so.so_name.c_str ());
1fddbabb
PA
342 else
343 {
344 ULONGEST orig_delta;
345 int i;
1fddbabb 346
200b8563 347 if (!symfile_map_offsets_to_segments (so.abfd.get (), data.get (),
6a053cb1 348 li->offsets,
d17f7b36
SM
349 li->segment_bases.size (),
350 li->segment_bases.data ()))
1fddbabb 351 warning (_("\
98107b0b 352Could not relocate shared library \"%s\": bad offsets"), so.so_name.c_str ());
1fddbabb
PA
353
354 /* Find the range of addresses to report for this library in
355 "info sharedlibrary". Report any consecutive segments
356 which were relocated as a single unit. */
d17f7b36 357 gdb_assert (li->segment_bases.size () > 0);
68b888ff 358 orig_delta = li->segment_bases[0] - data->segments[0].base;
1fddbabb 359
68b888ff 360 for (i = 1; i < data->segments.size (); i++)
1fddbabb
PA
361 {
362 /* If we have run out of offsets, assume all
363 remaining segments have the same offset. */
d17f7b36 364 if (i >= li->segment_bases.size ())
1fddbabb
PA
365 continue;
366
367 /* If this segment does not have the same offset, do
368 not include it in the library's range. */
68b888ff 369 if (li->segment_bases[i] - data->segments[i].base
d17f7b36 370 != orig_delta)
1fddbabb
PA
371 break;
372 }
373
bb86ab83
SM
374 so.addr_low = li->segment_bases[0];
375 so.addr_high = (data->segments[i - 1].base
68b888ff 376 + data->segments[i - 1].size
1fddbabb 377 + orig_delta);
bb86ab83 378 gdb_assert (so.addr_low <= so.addr_high);
cfa9d6d9 379 }
cfa9d6d9
DJ
380 }
381 }
382
6a053cb1
TT
383 offset = li->offsets[gdb_bfd_section_index (sec->the_bfd_section->owner,
384 sec->the_bfd_section)];
cfa9d6d9
DJ
385 sec->addr += offset;
386 sec->endaddr += offset;
387}
388
389static int
bf469271 390solib_target_open_symbol_file_object (int from_tty)
cfa9d6d9
DJ
391{
392 /* We can't locate the main symbol file based on the target's
393 knowledge; the user has to specify it. */
394 return 0;
395}
396
397static int
398solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
399{
400 /* We don't have a range of addresses for the dynamic linker; there
401 may not be one in the program's address space. So only report
402 PLT entries (which may be import stubs). */
3e5d3a5a 403 return in_plt_section (pc);
cfa9d6d9
DJ
404}
405
549dfc51 406const struct target_so_ops solib_target_so_ops =
cfa9d6d9 407{
549dfc51 408 solib_target_relocate_section_addresses,
549dfc51 409 nullptr,
6fe4d5bf 410 nullptr,
549dfc51
TT
411 solib_target_solib_create_inferior_hook,
412 solib_target_current_sos,
413 solib_target_open_symbol_file_object,
414 solib_target_in_dynsym_resolve_code,
415 solib_bfd_open,
416};