* coffread.c (cs_to_section): Use gdb_bfd_section_index.
[deliverable/binutils-gdb.git] / gdb / solib-target.c
CommitLineData
cfa9d6d9
DJ
1/* Definitions for targets which report shared library events.
2
28e7fd62 3 Copyright (C) 2007-2013 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"
cfa9d6d9
DJ
28
29#include "gdb_string.h"
30
cfa9d6d9
DJ
31/* Private data for each loaded library. */
32struct lm_info
33{
34 /* The library's name. The name is normally kept in the struct
35 so_list; it is only here during XML parsing. */
36 char *name;
37
1fddbabb
PA
38 /* The target can either specify segment bases or section bases, not
39 both. */
40
cfa9d6d9
DJ
41 /* The base addresses for each independently relocatable segment of
42 this shared library. */
43 VEC(CORE_ADDR) *segment_bases;
44
1fddbabb
PA
45 /* The base addresses for each independently allocatable,
46 relocatable section of this shared library. */
47 VEC(CORE_ADDR) *section_bases;
48
cfa9d6d9 49 /* The cached offsets for each section of this shared library,
1fddbabb 50 determined from SEGMENT_BASES, or SECTION_BASES. */
cfa9d6d9
DJ
51 struct section_offsets *offsets;
52};
53
54typedef struct lm_info *lm_info_p;
55DEF_VEC_P(lm_info_p);
56
57#if !defined(HAVE_LIBEXPAT)
58
899cff7a 59static VEC(lm_info_p) *
cfa9d6d9
DJ
60solib_target_parse_libraries (const char *library)
61{
62 static int have_warned;
63
64 if (!have_warned)
65 {
66 have_warned = 1;
67 warning (_("Can not parse XML library list; XML support was disabled "
68 "at compile time"));
69 }
70
71 return NULL;
72}
73
74#else /* HAVE_LIBEXPAT */
75
76#include "xml-support.h"
77
78/* Handle the start of a <segment> element. */
79
80static void
81library_list_start_segment (struct gdb_xml_parser *parser,
82 const struct gdb_xml_element *element,
83 void *user_data, VEC(gdb_xml_value_s) *attributes)
84{
85 VEC(lm_info_p) **list = user_data;
86 struct lm_info *last = VEC_last (lm_info_p, *list);
3d2c1d41 87 ULONGEST *address_p = xml_find_attribute (attributes, "address")->value;
358eb95e 88 CORE_ADDR address = (CORE_ADDR) *address_p;
cfa9d6d9 89
1fddbabb
PA
90 if (last->section_bases != NULL)
91 gdb_xml_error (parser,
92 _("Library list with both segments and sections"));
93
267f6504 94 VEC_safe_push (CORE_ADDR, last->segment_bases, 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,
100 void *user_data, VEC(gdb_xml_value_s) *attributes)
101{
102 VEC(lm_info_p) **list = user_data;
103 struct lm_info *last = VEC_last (lm_info_p, *list);
3d2c1d41 104 ULONGEST *address_p = xml_find_attribute (attributes, "address")->value;
1fddbabb
PA
105 CORE_ADDR address = (CORE_ADDR) *address_p;
106
107 if (last->segment_bases != NULL)
108 gdb_xml_error (parser,
109 _("Library list with both segments and sections"));
110
267f6504 111 VEC_safe_push (CORE_ADDR, last->section_bases, address);
1fddbabb
PA
112}
113
cfa9d6d9
DJ
114/* Handle the start of a <library> element. */
115
116static void
117library_list_start_library (struct gdb_xml_parser *parser,
118 const struct gdb_xml_element *element,
119 void *user_data, VEC(gdb_xml_value_s) *attributes)
120{
121 VEC(lm_info_p) **list = user_data;
122 struct lm_info *item = XZALLOC (struct lm_info);
3d2c1d41 123 const char *name = xml_find_attribute (attributes, "name")->value;
cfa9d6d9
DJ
124
125 item->name = xstrdup (name);
126 VEC_safe_push (lm_info_p, *list, item);
127}
128
1fddbabb
PA
129static void
130library_list_end_library (struct gdb_xml_parser *parser,
131 const struct gdb_xml_element *element,
132 void *user_data, const char *body_text)
133{
134 VEC(lm_info_p) **list = user_data;
135 struct lm_info *lm_info = VEC_last (lm_info_p, *list);
433759f7 136
1fddbabb
PA
137 if (lm_info->segment_bases == NULL
138 && lm_info->section_bases == NULL)
139 gdb_xml_error (parser,
140 _("No segment or section bases defined"));
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,
149 void *user_data, VEC(gdb_xml_value_s) *attributes)
150{
3d2c1d41 151 char *version = xml_find_attribute (attributes, "version")->value;
cfa9d6d9
DJ
152
153 if (strcmp (version, "1.0") != 0)
154 gdb_xml_error (parser,
155 _("Library list has unsupported version \"%s\""),
156 version);
157}
158
159/* Discard the constructed library list. */
160
161static void
162solib_target_free_library_list (void *p)
163{
164 VEC(lm_info_p) **result = p;
165 struct lm_info *info;
166 int ix;
167
168 for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
169 {
170 xfree (info->name);
171 VEC_free (CORE_ADDR, info->segment_bases);
1fddbabb 172 VEC_free (CORE_ADDR, info->section_bases);
cfa9d6d9
DJ
173 xfree (info);
174 }
175 VEC_free (lm_info_p, *result);
176 *result = NULL;
177}
178
179/* The allowed elements and attributes for an XML library list.
180 The root element is a <library-list>. */
181
d6c10e95 182static const struct gdb_xml_attribute segment_attributes[] = {
cfa9d6d9
DJ
183 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
184 { NULL, GDB_XML_AF_NONE, NULL, NULL }
185};
186
d6c10e95 187static const struct gdb_xml_attribute section_attributes[] = {
1fddbabb
PA
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_element library_children[] = {
1fddbabb
PA
193 { "segment", segment_attributes, NULL,
194 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
cfa9d6d9 195 library_list_start_segment, NULL },
1fddbabb
PA
196 { "section", section_attributes, NULL,
197 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
198 library_list_start_section, NULL },
cfa9d6d9
DJ
199 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
200};
201
d6c10e95 202static const struct gdb_xml_attribute library_attributes[] = {
cfa9d6d9
DJ
203 { "name", GDB_XML_AF_NONE, NULL, NULL },
204 { NULL, GDB_XML_AF_NONE, NULL, NULL }
205};
206
d6c10e95 207static const struct gdb_xml_element library_list_children[] = {
cfa9d6d9
DJ
208 { "library", library_attributes, library_children,
209 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
1fddbabb 210 library_list_start_library, library_list_end_library },
cfa9d6d9
DJ
211 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
212};
213
d6c10e95 214static const struct gdb_xml_attribute library_list_attributes[] = {
cfa9d6d9
DJ
215 { "version", GDB_XML_AF_NONE, NULL, NULL },
216 { NULL, GDB_XML_AF_NONE, NULL, NULL }
217};
218
d6c10e95 219static const struct gdb_xml_element library_list_elements[] = {
cfa9d6d9
DJ
220 { "library-list", library_list_attributes, library_list_children,
221 GDB_XML_EF_NONE, library_list_start_list, NULL },
222 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
223};
224
225static VEC(lm_info_p) *
226solib_target_parse_libraries (const char *library)
227{
cfa9d6d9 228 VEC(lm_info_p) *result = NULL;
efc0eabd
PA
229 struct cleanup *back_to = make_cleanup (solib_target_free_library_list,
230 &result);
cfa9d6d9 231
efc0eabd
PA
232 if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd",
233 library_list_elements, library, &result) == 0)
234 {
235 /* Parsed successfully, keep the result. */
236 discard_cleanups (back_to);
237 return result;
238 }
cfa9d6d9
DJ
239
240 do_cleanups (back_to);
efc0eabd 241 return NULL;
cfa9d6d9
DJ
242}
243#endif
244
245static struct so_list *
246solib_target_current_sos (void)
247{
248 struct so_list *new_solib, *start = NULL, *last = NULL;
b25d79d4
PM
249 char *library_document;
250 struct cleanup *old_chain;
cfa9d6d9
DJ
251 VEC(lm_info_p) *library_list;
252 struct lm_info *info;
253 int ix;
254
255 /* Fetch the list of shared libraries. */
256 library_document = target_read_stralloc (&current_target,
257 TARGET_OBJECT_LIBRARIES,
258 NULL);
259 if (library_document == NULL)
260 return NULL;
261
b25d79d4
PM
262 /* solib_target_parse_libraries may throw, so we use a cleanup. */
263 old_chain = make_cleanup (xfree, library_document);
264
cfa9d6d9
DJ
265 /* Parse the list. */
266 library_list = solib_target_parse_libraries (library_document);
b25d79d4
PM
267
268 /* library_document string is not needed behind this point. */
269 do_cleanups (old_chain);
270
cfa9d6d9
DJ
271 if (library_list == NULL)
272 return NULL;
273
274 /* Build a struct so_list for each entry on the list. */
275 for (ix = 0; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
276 {
277 new_solib = XZALLOC (struct so_list);
278 strncpy (new_solib->so_name, info->name, SO_NAME_MAX_PATH_SIZE - 1);
279 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
280 strncpy (new_solib->so_original_name, info->name,
281 SO_NAME_MAX_PATH_SIZE - 1);
282 new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
283 new_solib->lm_info = info;
284
285 /* We no longer need this copy of the name. */
286 xfree (info->name);
287 info->name = NULL;
288
289 /* Add it to the list. */
290 if (!start)
291 last = start = new_solib;
292 else
293 {
294 last->next = new_solib;
295 last = new_solib;
296 }
297 }
298
299 /* Free the library list, but not its members. */
300 VEC_free (lm_info_p, library_list);
301
302 return start;
303}
304
305static void
306solib_target_special_symbol_handling (void)
307{
308 /* Nothing needed. */
309}
310
311static void
268a4a75 312solib_target_solib_create_inferior_hook (int from_tty)
cfa9d6d9
DJ
313{
314 /* Nothing needed. */
315}
316
317static void
318solib_target_clear_solib (void)
319{
320 /* Nothing needed. */
321}
322
323static void
324solib_target_free_so (struct so_list *so)
325{
326 gdb_assert (so->lm_info->name == NULL);
327 xfree (so->lm_info->offsets);
328 VEC_free (CORE_ADDR, so->lm_info->segment_bases);
329 xfree (so->lm_info);
330}
331
332static void
333solib_target_relocate_section_addresses (struct so_list *so,
0542c86d 334 struct target_section *sec)
cfa9d6d9 335{
cfa9d6d9
DJ
336 CORE_ADDR offset;
337
338 /* Build the offset table only once per object file. We can not do
339 it any earlier, since we need to open the file first. */
340 if (so->lm_info->offsets == NULL)
341 {
cfa9d6d9
DJ
342 int num_sections = bfd_count_sections (so->abfd);
343
344 so->lm_info->offsets = xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections));
345
1fddbabb 346 if (so->lm_info->section_bases)
cfa9d6d9 347 {
cfa9d6d9 348 int i;
1fddbabb
PA
349 asection *sect;
350 int num_section_bases
351 = VEC_length (CORE_ADDR, so->lm_info->section_bases);
352 int num_alloc_sections = 0;
353
354 for (i = 0, sect = so->abfd->sections;
355 sect != NULL;
356 i++, sect = sect->next)
357 if ((bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
358 num_alloc_sections++;
359
360 if (num_alloc_sections != num_section_bases)
361 warning (_("\
362Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
cfa9d6d9 363 so->so_name);
1fddbabb 364 else
cfa9d6d9 365 {
1fddbabb
PA
366 int bases_index = 0;
367 int found_range = 0;
368 CORE_ADDR *section_bases;
433759f7 369
1fddbabb
PA
370 section_bases = VEC_address (CORE_ADDR,
371 so->lm_info->section_bases);
372
373 so->addr_low = ~(CORE_ADDR) 0;
374 so->addr_high = 0;
375 for (i = 0, sect = so->abfd->sections;
376 sect != NULL;
377 i++, sect = sect->next)
378 {
379 if (!(bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
380 continue;
381 if (bfd_section_size (so->abfd, sect) > 0)
382 {
383 CORE_ADDR low, high;
433759f7 384
1fddbabb
PA
385 low = section_bases[i];
386 high = low + bfd_section_size (so->abfd, sect) - 1;
387
388 if (low < so->addr_low)
389 so->addr_low = low;
390 if (high > so->addr_high)
391 so->addr_high = high;
392 gdb_assert (so->addr_low <= so->addr_high);
393 found_range = 1;
394 }
3e43a32a
MS
395 so->lm_info->offsets->offsets[i]
396 = section_bases[bases_index];
1fddbabb
PA
397 bases_index++;
398 }
399 if (!found_range)
400 so->addr_low = so->addr_high = 0;
401 gdb_assert (so->addr_low <= so->addr_high);
402 }
403 }
404 else if (so->lm_info->segment_bases)
405 {
406 struct symfile_segment_data *data;
433759f7 407
1fddbabb
PA
408 data = get_symfile_segment_data (so->abfd);
409 if (data == NULL)
410 warning (_("\
411Could not relocate shared library \"%s\": no segments"), so->so_name);
412 else
413 {
414 ULONGEST orig_delta;
415 int i;
416 int num_bases;
417 CORE_ADDR *segment_bases;
418
419 num_bases = VEC_length (CORE_ADDR, so->lm_info->segment_bases);
420 segment_bases = VEC_address (CORE_ADDR,
421 so->lm_info->segment_bases);
422
423 if (!symfile_map_offsets_to_segments (so->abfd, data,
424 so->lm_info->offsets,
425 num_bases, segment_bases))
426 warning (_("\
427Could not relocate shared library \"%s\": bad offsets"), so->so_name);
428
429 /* Find the range of addresses to report for this library in
430 "info sharedlibrary". Report any consecutive segments
431 which were relocated as a single unit. */
432 gdb_assert (num_bases > 0);
433 orig_delta = segment_bases[0] - data->segment_bases[0];
434
435 for (i = 1; i < data->num_segments; i++)
436 {
437 /* If we have run out of offsets, assume all
438 remaining segments have the same offset. */
439 if (i >= num_bases)
440 continue;
441
442 /* If this segment does not have the same offset, do
443 not include it in the library's range. */
444 if (segment_bases[i] - data->segment_bases[i] != orig_delta)
445 break;
446 }
447
448 so->addr_low = segment_bases[0];
449 so->addr_high = (data->segment_bases[i - 1]
450 + data->segment_sizes[i - 1]
451 + orig_delta);
452 gdb_assert (so->addr_low <= so->addr_high);
453
454 free_symfile_segment_data (data);
cfa9d6d9 455 }
cfa9d6d9
DJ
456 }
457 }
458
65cf3563
TT
459 offset = so->lm_info->offsets->offsets[gdb_bfd_section_index (sec->bfd,
460 sec->the_bfd_section)];
cfa9d6d9
DJ
461 sec->addr += offset;
462 sec->endaddr += offset;
463}
464
465static int
466solib_target_open_symbol_file_object (void *from_ttyp)
467{
468 /* We can't locate the main symbol file based on the target's
469 knowledge; the user has to specify it. */
470 return 0;
471}
472
473static int
474solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
475{
476 /* We don't have a range of addresses for the dynamic linker; there
477 may not be one in the program's address space. So only report
478 PLT entries (which may be import stubs). */
479 return in_plt_section (pc, NULL);
480}
481
8d465389 482struct target_so_ops solib_target_so_ops;
cfa9d6d9 483
3e43a32a
MS
484/* -Wmissing-prototypes */
485extern initialize_file_ftype _initialize_solib_target;
cfa9d6d9
DJ
486
487void
488_initialize_solib_target (void)
489{
490 solib_target_so_ops.relocate_section_addresses
491 = solib_target_relocate_section_addresses;
492 solib_target_so_ops.free_so = solib_target_free_so;
493 solib_target_so_ops.clear_solib = solib_target_clear_solib;
494 solib_target_so_ops.solib_create_inferior_hook
495 = solib_target_solib_create_inferior_hook;
496 solib_target_so_ops.special_symbol_handling
497 = solib_target_special_symbol_handling;
498 solib_target_so_ops.current_sos = solib_target_current_sos;
499 solib_target_so_ops.open_symbol_file_object
500 = solib_target_open_symbol_file_object;
501 solib_target_so_ops.in_dynsym_resolve_code
502 = solib_target_in_dynsym_resolve_code;
831a0c44 503 solib_target_so_ops.bfd_open = solib_bfd_open;
98d64339
PA
504
505 /* Set current_target_so_ops to solib_target_so_ops if not already
506 set. */
507 if (current_target_so_ops == 0)
508 current_target_so_ops = &solib_target_so_ops;
cfa9d6d9 509}
This page took 0.756892 seconds and 4 git commands to generate.