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