solib_target_free_so memory leak
[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. */
44f81a76 49 gdb::unique_xmalloc_ptr<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. */
d0e449a1 308 if (li->offsets == NULL)
cfa9d6d9 309 {
d445b2f6 310 int num_sections = gdb_bfd_count_sections (so->abfd);
cfa9d6d9 311
44f81a76
HD
312 li->offsets.reset ((struct section_offsets *)
313 xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections)));
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 }
f2f46dfc 358 li->offsets->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
PA
367 {
368 struct symfile_segment_data *data;
433759f7 369
1fddbabb
PA
370 data = get_symfile_segment_data (so->abfd);
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
44f81a76
HD
379 if (!symfile_map_offsets_to_segments (so->abfd, data,
380 li->offsets.get (),
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
SM
389 gdb_assert (li->segment_bases.size () > 0);
390 orig_delta = li->segment_bases[0] - data->segment_bases[0];
1fddbabb
PA
391
392 for (i = 1; i < data->num_segments; i++)
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. */
d17f7b36
SM
401 if (li->segment_bases[i] - data->segment_bases[i]
402 != orig_delta)
1fddbabb
PA
403 break;
404 }
405
d17f7b36 406 so->addr_low = li->segment_bases[0];
1fddbabb
PA
407 so->addr_high = (data->segment_bases[i - 1]
408 + data->segment_sizes[i - 1]
409 + orig_delta);
410 gdb_assert (so->addr_low <= so->addr_high);
411
412 free_symfile_segment_data (data);
cfa9d6d9 413 }
cfa9d6d9
DJ
414 }
415 }
416
d0e449a1
SM
417 offset = li->offsets->offsets[gdb_bfd_section_index
418 (sec->the_bfd_section->owner,
419 sec->the_bfd_section)];
cfa9d6d9
DJ
420 sec->addr += offset;
421 sec->endaddr += offset;
422}
423
424static int
bf469271 425solib_target_open_symbol_file_object (int from_tty)
cfa9d6d9
DJ
426{
427 /* We can't locate the main symbol file based on the target's
428 knowledge; the user has to specify it. */
429 return 0;
430}
431
432static int
433solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
434{
435 /* We don't have a range of addresses for the dynamic linker; there
436 may not be one in the program's address space. So only report
437 PLT entries (which may be import stubs). */
3e5d3a5a 438 return in_plt_section (pc);
cfa9d6d9
DJ
439}
440
8d465389 441struct target_so_ops solib_target_so_ops;
cfa9d6d9 442
cfa9d6d9
DJ
443void
444_initialize_solib_target (void)
445{
446 solib_target_so_ops.relocate_section_addresses
447 = solib_target_relocate_section_addresses;
448 solib_target_so_ops.free_so = solib_target_free_so;
449 solib_target_so_ops.clear_solib = solib_target_clear_solib;
450 solib_target_so_ops.solib_create_inferior_hook
451 = solib_target_solib_create_inferior_hook;
cfa9d6d9
DJ
452 solib_target_so_ops.current_sos = solib_target_current_sos;
453 solib_target_so_ops.open_symbol_file_object
454 = solib_target_open_symbol_file_object;
455 solib_target_so_ops.in_dynsym_resolve_code
456 = solib_target_in_dynsym_resolve_code;
831a0c44 457 solib_target_so_ops.bfd_open = solib_bfd_open;
98d64339
PA
458
459 /* Set current_target_so_ops to solib_target_so_ops if not already
460 set. */
461 if (current_target_so_ops == 0)
462 current_target_so_ops = &solib_target_so_ops;
cfa9d6d9 463}
This page took 1.314814 seconds and 4 git commands to generate.